@axium/tasks 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/db.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "../server/schemas/db.json",
3
+ "format": 0,
4
+ "versions": [
5
+ {
6
+ "delta": false,
7
+ "tables": {
8
+ "task_lists": {
9
+ "columns": {
10
+ "id": { "type": "uuid", "required": true, "primary": true, "default": "gen_random_uuid()" },
11
+ "userId": { "type": "uuid", "required": true, "references": "users.id", "onDelete": "cascade" },
12
+ "created": { "type": "timestamptz", "required": true, "default": "now()" },
13
+ "publicPermission": { "type": "integer", "required": true, "default": 0 },
14
+ "name": { "type": "text", "required": true },
15
+ "description": { "type": "text" }
16
+ }
17
+ },
18
+ "tasks": {
19
+ "columns": {
20
+ "id": { "type": "uuid", "required": true, "primary": true, "default": "gen_random_uuid()" },
21
+ "created": { "type": "timestamptz", "required": true, "default": "now()" },
22
+ "listId": { "type": "uuid", "required": true, "references": "task_lists.id", "onDelete": "cascade" },
23
+ "summary": { "type": "text", "required": true },
24
+ "description": { "type": "text" },
25
+ "parentId": { "type": "uuid", "references": "tasks.id", "onDelete": "cascade" },
26
+ "completed": { "type": "boolean", "required": true, "default": false },
27
+ "due": { "type": "timestamptz" }
28
+ }
29
+ },
30
+ "acl.task_lists": {
31
+ "columns": {
32
+ "userId": { "type": "uuid", "required": true, "references": "users.id", "onDelete": "cascade" },
33
+ "itemId": { "type": "uuid", "required": true, "references": "task_lists.id", "onDelete": "cascade" },
34
+ "createdAt": { "type": "timestamptz", "required": true, "default": "now()" },
35
+ "permission": { "type": "integer", "required": true, "check": "permission >= 0 AND permission <= 5" }
36
+ }
37
+ }
38
+ },
39
+ "indexes": ["task_lists:userId", "acl.task_lists:userId", "acl.task_lists:itemId", "tasks:listId", "tasks:parentId"]
40
+ },
41
+ {
42
+ "delta": true,
43
+ "alter_tables": {
44
+ "task_lists": {
45
+ "drop_columns": ["publicPermission"]
46
+ },
47
+ "acl.task_lists": {
48
+ "drop_constraints": ["PK_acl_task_lists"],
49
+ "drop_columns": ["permission"],
50
+ "add_columns": {
51
+ "role": { "type": "text" },
52
+ "tag": { "type": "text" },
53
+ "read": { "type": "boolean", "required": true, "default": false },
54
+ "edit": { "type": "boolean", "required": true, "default": false },
55
+ "manage": { "type": "boolean", "required": true, "default": false }
56
+ },
57
+ "alter_columns": {
58
+ "userId": { "ops": ["drop_required"] }
59
+ },
60
+ "add_constraints": {
61
+ "unique_task_lists": { "type": "unique", "on": ["itemId", "userId", "role", "tag"], "nulls_not_distinct": true }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ ],
67
+ "wipe": ["task_lists", "tasks", "acl.task_lists"],
68
+ "acl_tables": {
69
+ "task_lists": "acl.task_lists"
70
+ }
71
+ }
package/dist/common.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { Permission } from '@axium/core';
2
1
  import type { WithRequired } from 'utilium';
3
2
  import * as z from 'zod';
4
3
  export declare const TaskInit: z.ZodObject<{
@@ -27,7 +26,6 @@ export interface TaskList extends TaskListInit {
27
26
  id: string;
28
27
  userId: string;
29
28
  created: Date;
30
- publicPermission: Permission;
31
29
  tasks?: Task[];
32
30
  }
33
31
  declare module '@axium/core/api' {
package/dist/hooks.d.ts CHANGED
@@ -1,6 +1,3 @@
1
1
  import './common.js';
2
2
  import './server.js';
3
3
  export declare function statusText(): Promise<string>;
4
- export declare function db_init(): Promise<void>;
5
- export declare function db_wipe(): Promise<void>;
6
- export declare function remove(): Promise<void>;
package/dist/hooks.js CHANGED
@@ -1,56 +1,7 @@
1
- import { done, start } from '@axium/core/node/io';
2
- import * as acl from '@axium/server/acl';
3
- import { count, createIndex, database, warnExists } from '@axium/server/database';
4
- import { sql } from 'kysely';
1
+ import { count } from '@axium/server/database';
5
2
  import './common.js';
6
3
  import './server.js';
7
4
  export async function statusText() {
8
5
  const { tasks, task_lists } = await count('tasks', 'task_lists');
9
6
  return `${tasks} tasks, ${task_lists} lists`;
10
7
  }
11
- export async function db_init() {
12
- start('Creating table task_lists');
13
- await database.schema
14
- .createTable('task_lists')
15
- .addColumn('id', 'uuid', col => col.primaryKey().defaultTo(sql `gen_random_uuid()`))
16
- .addColumn('userId', 'uuid', col => col.notNull().references('users.id').onDelete('cascade'))
17
- .addColumn('created', 'timestamptz', col => col.notNull().defaultTo(sql `now()`))
18
- .addColumn('publicPermission', 'integer', col => col.notNull().defaultTo(0))
19
- .addColumn('name', 'text', col => col.notNull())
20
- .addColumn('description', 'text')
21
- .execute()
22
- .then(done)
23
- .catch(warnExists);
24
- await createIndex('task_lists', 'userId');
25
- await acl.createTable('task_lists');
26
- start('Creating table tasks');
27
- await database.schema
28
- .createTable('tasks')
29
- .addColumn('id', 'uuid', col => col.primaryKey().defaultTo(sql `gen_random_uuid()`))
30
- .addColumn('created', 'timestamptz', col => col.notNull().defaultTo(sql `now()`))
31
- .addColumn('listId', 'uuid', col => col.notNull().references('task_lists.id').onDelete('cascade'))
32
- .addColumn('summary', 'text', col => col.notNull())
33
- .addColumn('description', 'text')
34
- .addColumn('parentId', 'uuid', col => col.references('tasks.id').onDelete('cascade'))
35
- .addColumn('completed', 'boolean', col => col.notNull().defaultTo(false))
36
- .addColumn('due', 'timestamptz')
37
- .execute()
38
- .then(done)
39
- .catch(warnExists);
40
- await createIndex('tasks', 'listId');
41
- await createIndex('tasks', 'parentId');
42
- }
43
- export async function db_wipe() {
44
- start('Wiping data from tasks');
45
- await database.deleteFrom('tasks').execute().then(done);
46
- start('Wiping data from task_lists');
47
- await database.deleteFrom('task_lists').execute().then(done);
48
- await acl.wipeTable('task_lists');
49
- }
50
- export async function remove() {
51
- start('Dropping table tasks');
52
- await database.schema.dropTable('tasks').execute().then(done);
53
- start('Dropping table task_lists');
54
- await database.schema.dropTable('task_lists').execute().then(done);
55
- await acl.dropTable('task_lists');
56
- }
package/dist/server.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { Permission } from '@axium/core';
2
1
  import type { Generated, GeneratedAlways } from 'kysely';
3
2
  declare module '@axium/server/database' {
4
3
  interface Schema {
@@ -16,13 +15,9 @@ declare module '@axium/server/database' {
16
15
  id: GeneratedAlways<string>;
17
16
  userId: string;
18
17
  created: GeneratedAlways<Date>;
19
- publicPermission: Generated<Permission>;
20
18
  name: string;
21
19
  description?: string | null;
22
20
  };
23
- }
24
- interface ExpectedSchema {
25
- tasks: ColumnTypes<Schema['tasks']>;
26
- task_lists: ColumnTypes<Schema['task_lists']>;
21
+ 'acl.task_lists': DBAccessControl & DBBool<'read' | 'edit' | 'manage'>;
27
22
  }
28
23
  }
package/dist/server.js CHANGED
@@ -1,34 +1,14 @@
1
- import { Permission } from '@axium/core';
2
1
  import { checkAuthForItem, checkAuthForUser } from '@axium/server/auth';
3
- import { database, expectedTypes } from '@axium/server/database';
2
+ import { database } from '@axium/server/database';
4
3
  import { parseBody, withError } from '@axium/server/requests';
5
4
  import { addRoute } from '@axium/server/routes';
5
+ import { jsonArrayFrom } from 'kysely/helpers/postgres';
6
6
  import * as z from 'zod';
7
7
  import { TaskInit, TaskListInit, TaskListUpdate } from './common.js';
8
- import { jsonArrayFrom } from 'kysely/helpers/postgres';
9
- expectedTypes.tasks = {
10
- id: { type: 'uuid', required: true, hasDefault: true },
11
- created: { type: 'timestamptz', required: true, hasDefault: true },
12
- summary: { type: 'text', required: true },
13
- description: { type: 'text' },
14
- listId: { type: 'uuid', required: true },
15
- parentId: { type: 'uuid' },
16
- completed: { type: 'bool', required: true, hasDefault: true },
17
- due: { type: 'timestamptz' },
18
- };
19
- expectedTypes.task_lists = {
20
- id: { type: 'uuid', required: true, hasDefault: true },
21
- userId: { type: 'uuid', required: true },
22
- created: { type: 'timestamptz', required: true, hasDefault: true },
23
- publicPermission: { type: 'int4', required: true, hasDefault: true },
24
- name: { type: 'text', required: true },
25
- description: { type: 'text' },
26
- };
27
8
  addRoute({
28
9
  path: '/api/users/:id/task_lists',
29
10
  params: { id: z.uuid() },
30
- async GET(request, params) {
31
- const userId = params.id;
11
+ async GET(request, { id: userId }) {
32
12
  await checkAuthForUser(request, userId);
33
13
  const lists = await database
34
14
  .selectFrom('task_lists')
@@ -42,9 +22,8 @@ addRoute({
42
22
  tasks: list.tasks.map(t => ({ ...t, created: new Date(t.created), due: t.due ? new Date(t.due) : null })),
43
23
  }));
44
24
  },
45
- async PUT(request, params) {
25
+ async PUT(request, { id: userId }) {
46
26
  const init = await parseBody(request, TaskListInit);
47
- const userId = params.id;
48
27
  await checkAuthForUser(request, userId);
49
28
  return await database
50
29
  .insertInto('task_lists')
@@ -57,9 +36,8 @@ addRoute({
57
36
  addRoute({
58
37
  path: '/api/task_lists/:id',
59
38
  params: { id: z.uuid() },
60
- async GET(request, params) {
61
- const id = params.id;
62
- const { item } = await checkAuthForItem(request, 'task_lists', id, Permission.Read);
39
+ async GET(request, { id }) {
40
+ const { item } = await checkAuthForItem(request, 'task_lists', id, { read: true });
63
41
  const tasks = await database
64
42
  .selectFrom('tasks')
65
43
  .selectAll()
@@ -68,10 +46,9 @@ addRoute({
68
46
  .catch(withError('Could not get tasks'));
69
47
  return Object.assign(item, { tasks });
70
48
  },
71
- async PUT(request, params) {
72
- const listId = params.id;
49
+ async PUT(request, { id: listId }) {
73
50
  const init = await parseBody(request, TaskInit.omit({ listId: true }));
74
- await checkAuthForItem(request, 'task_lists', listId, Permission.Edit);
51
+ await checkAuthForItem(request, 'task_lists', listId, { edit: true });
75
52
  return await database
76
53
  .insertInto('tasks')
77
54
  .values({ summary: '', ...init, listId })
@@ -79,9 +56,8 @@ addRoute({
79
56
  .executeTakeFirstOrThrow()
80
57
  .catch(withError('Could not update task list'));
81
58
  },
82
- async PATCH(request, params) {
83
- const id = params.id;
84
- await checkAuthForItem(request, 'task_lists', id, Permission.Edit);
59
+ async PATCH(request, { id }) {
60
+ await checkAuthForItem(request, 'task_lists', id, { edit: true });
85
61
  const init = await parseBody(request, TaskListInit);
86
62
  return await database
87
63
  .updateTable('task_lists')
@@ -91,10 +67,9 @@ addRoute({
91
67
  .executeTakeFirstOrThrow()
92
68
  .catch(withError('Could not update task list'));
93
69
  },
94
- async POST(request, params) {
70
+ async POST(request, { id }) {
95
71
  const body = await parseBody(request, TaskListUpdate);
96
- const id = params.id;
97
- await checkAuthForItem(request, 'task_lists', id, Permission.Edit);
72
+ await checkAuthForItem(request, 'task_lists', id, { edit: true });
98
73
  if (typeof body.all_completed == 'boolean') {
99
74
  await database
100
75
  .updateTable('tasks')
@@ -107,9 +82,8 @@ addRoute({
107
82
  }
108
83
  return {};
109
84
  },
110
- async DELETE(request, params) {
111
- const id = params.id;
112
- await checkAuthForItem(request, 'task_lists', id, Permission.Manage);
85
+ async DELETE(request, { id }) {
86
+ await checkAuthForItem(request, 'task_lists', id, { manage: true });
113
87
  return await database
114
88
  .deleteFrom('task_lists')
115
89
  .where('id', '=', id)
@@ -121,16 +95,15 @@ addRoute({
121
95
  addRoute({
122
96
  path: '/api/tasks/:id',
123
97
  params: { id: z.uuid() },
124
- async PATCH(request, params) {
98
+ async PATCH(request, { id }) {
125
99
  const init = await parseBody(request, TaskInit.omit({ listId: true }));
126
- const id = params.id;
127
100
  const task = await database
128
101
  .selectFrom('tasks')
129
102
  .select('listId')
130
103
  .where('id', '=', id)
131
104
  .executeTakeFirstOrThrow()
132
105
  .catch(withError('Could not get task'));
133
- await checkAuthForItem(request, 'task_lists', task.listId, Permission.Edit);
106
+ await checkAuthForItem(request, 'task_lists', task.listId, { edit: true });
134
107
  return await database
135
108
  .updateTable('tasks')
136
109
  .set(init)
@@ -139,15 +112,14 @@ addRoute({
139
112
  .executeTakeFirstOrThrow()
140
113
  .catch(withError('Could not update task'));
141
114
  },
142
- async DELETE(request, params) {
143
- const id = params.id;
115
+ async DELETE(request, { id }) {
144
116
  const task = await database
145
117
  .selectFrom('tasks')
146
118
  .select('listId')
147
119
  .where('id', '=', id)
148
120
  .executeTakeFirstOrThrow()
149
121
  .catch(withError('Could not fetch task'));
150
- await checkAuthForItem(request, 'task_lists', task.listId, Permission.Manage);
122
+ await checkAuthForItem(request, 'task_lists', task.listId, { manage: true });
151
123
  return await database
152
124
  .deleteFrom('tasks')
153
125
  .where('id', '=', id)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/tasks",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "description": "Tasks for Axium",
6
6
  "funding": {
@@ -28,15 +28,16 @@
28
28
  "files": [
29
29
  "dist",
30
30
  "lib",
31
- "routes"
31
+ "routes",
32
+ "db.json"
32
33
  ],
33
34
  "scripts": {
34
35
  "build": "tsc"
35
36
  },
36
37
  "peerDependencies": {
37
- "@axium/client": ">=0.6.0",
38
- "@axium/core": ">=0.9.0",
39
- "@axium/server": ">=0.26.0",
38
+ "@axium/client": ">=0.9.0",
39
+ "@axium/core": ">=0.12.0",
40
+ "@axium/server": ">=0.28.0",
40
41
  "@sveltejs/kit": "^2.27.3",
41
42
  "utilium": "^2.3.8"
42
43
  },
@@ -46,7 +47,8 @@
46
47
  "axium": {
47
48
  "server": {
48
49
  "routes": "routes",
49
- "hooks": "./dist/hooks.js"
50
+ "hooks": "./dist/hooks.js",
51
+ "db": "./db.json"
50
52
  },
51
53
  "apps": [
52
54
  {