diff --git a/README.md b/README.md
index 07a096f..c82ea0f 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ mysql> FLUSH PRIVILEGES;
Populate the database using knex, which should add tables automatically.
```
-knex --knexfile src/knexfile.ts migrate:latest
+make knex-migrate
```
This should populate your database with the required tables.
diff --git a/src/db-types.ts b/src/db-types.ts
index a5925a3..384d1c6 100644
--- a/src/db-types.ts
+++ b/src/db-types.ts
@@ -31,6 +31,7 @@ export type EntriesRecord = {
billable: number;
created_at: Date;
modified_at: Date;
+ version: number;
}
export type PeopleRecord = {
diff --git a/src/entry/controller/item.ts b/src/entry/controller/item.ts
index 64f3ab6..253fdb6 100644
--- a/src/entry/controller/item.ts
+++ b/src/entry/controller/item.ts
@@ -18,13 +18,13 @@ class Entry extends Controller {
const person = await personService.findById(
+ctx.params.personId,
);
-
- ctx.response.body = hal.item(
- await entryService.findById(
- person,
- +ctx.params.entryId,
- )
+ const entry = await entryService.findById(
+ person,
+ +ctx.params.entryId,
);
+
+ ctx.response.body = hal.item(entry);
+ ctx.response.headers.set('ETag', '"' + entry.version + '"');
}
async put(ctx: Context) {
diff --git a/src/entry/formats/hal.ts b/src/entry/formats/hal.ts
index ed9bfec..64ec874 100644
--- a/src/entry/formats/hal.ts
+++ b/src/entry/formats/hal.ts
@@ -50,6 +50,9 @@ export function item(entry: Entry) {
href: entry.person.href
}
},
+ _headers: {
+ ETag: '"' + entry.version + '"',
+ },
description: entry.description,
date: entry.date,
minutes: entry.minutes,
diff --git a/src/entry/service.ts b/src/entry/service.ts
index 84f642b..d59d42d 100644
--- a/src/entry/service.ts
+++ b/src/entry/service.ts
@@ -135,13 +135,15 @@ export async function create(entry: NewEntry): Promise {
description: entry.description,
billable: entry.billable,
created_at: new Date(),
- modified_at: new Date()
+ modified_at: new Date(),
+ version: 1,
});
return {
...entry,
id: result[0],
href: `/person/${entry.person.id}/entry/${result[0]}`,
+ version: 1,
createdAt: new Date(),
modifiedAt: new Date()
};
@@ -150,14 +152,17 @@ export async function create(entry: NewEntry): Promise {
export async function update(entry: Entry): Promise {
- await knex('entries').update({
- project_id: entry.project.id,
- date: entry.date,
- minutes: entry.minutes,
- description: entry.description,
- billable: entry.billable,
- modified_at: new Date()
- }).where({id: entry.id});
+ await knex('entries')
+ .update({
+ project_id: entry.project.id,
+ date: entry.date,
+ minutes: entry.minutes,
+ description: entry.description,
+ billable: entry.billable,
+ modified_at: new Date(),
+ })
+ .increment('version', 1)
+ .where({id: entry.id});
}
@@ -180,7 +185,8 @@ function mapRecord(input: EntriesRecord, project: Project, person: Person): Entr
description: input.description,
billable: !!input.billable,
createdAt: input.created_at,
- modifiedAt: input.modified_at
+ modifiedAt: input.modified_at,
+ version: input.version,
};
}
diff --git a/src/migrations/20221027052445_entry_version.ts b/src/migrations/20221027052445_entry_version.ts
new file mode 100644
index 0000000..859068f
--- /dev/null
+++ b/src/migrations/20221027052445_entry_version.ts
@@ -0,0 +1,24 @@
+import { Knex } from 'knex';
+
+
+export async function up(knex: Knex): Promise {
+
+ await knex.schema.alterTable('entries', table => {
+
+ table.integer('version').unsigned().notNullable().defaultTo(1);
+
+ });
+
+}
+
+
+export async function down(knex: Knex): Promise {
+
+ await knex.schema.alterTable('entries', table => {
+
+ table.dropColumn('version');
+
+ });
+
+}
+
diff --git a/src/types.ts b/src/types.ts
index cfc0fd7..ea4650a 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -50,8 +50,9 @@ export type Entry = {
modifiedAt: Date;
createdAt: Date;
+ version: number;
}
export type NewEntry =
- Omit;
+ Omit;