@axium/notes 0.1.12 → 0.2.1
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 +61 -0
- package/dist/common.d.ts +0 -13
- package/dist/common.js +0 -2
- package/dist/hooks.d.ts +0 -3
- package/dist/hooks.js +1 -32
- package/dist/server.d.ts +1 -5
- package/dist/server.js +4 -15
- package/lib/Note.svelte +17 -11
- package/package.json +8 -6
- package/routes/notes/+page.svelte +15 -12
- package/routes/notes/[id]/+page.svelte +1 -1
package/db.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../server/schemas/db.json",
|
|
3
|
+
"format": 0,
|
|
4
|
+
"versions": [
|
|
5
|
+
{
|
|
6
|
+
"delta": false,
|
|
7
|
+
"tables": {
|
|
8
|
+
"notes": {
|
|
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
|
+
"modified": { "type": "timestamptz", "required": true, "default": "now()" },
|
|
14
|
+
"publicPermission": { "type": "integer", "required": true, "default": 0 },
|
|
15
|
+
"title": { "type": "text", "required": true },
|
|
16
|
+
"content": { "type": "text" },
|
|
17
|
+
"labels": { "type": "text[]", "required": true, "default": "'{}'::text[]" }
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"acl.notes": {
|
|
21
|
+
"columns": {
|
|
22
|
+
"userId": { "type": "uuid", "required": true, "references": "users.id", "onDelete": "cascade" },
|
|
23
|
+
"itemId": { "type": "uuid", "required": true, "references": "notes.id", "onDelete": "cascade" },
|
|
24
|
+
"createdAt": { "type": "timestamptz", "required": true, "default": "now()" },
|
|
25
|
+
"permission": { "type": "integer", "required": true, "check": "permission >= 0 AND permission <= 5" }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"indexes": ["notes:userId", "acl.notes:userId", "acl.notes:itemId"]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"delta": true,
|
|
33
|
+
"alter_tables": {
|
|
34
|
+
"notes": {
|
|
35
|
+
"drop_columns": ["publicPermission"]
|
|
36
|
+
},
|
|
37
|
+
"acl.notes": {
|
|
38
|
+
"drop_constraints": ["PK_acl_notes"],
|
|
39
|
+
"drop_columns": ["permission"],
|
|
40
|
+
"add_columns": {
|
|
41
|
+
"role": { "type": "text" },
|
|
42
|
+
"tag": { "type": "text" },
|
|
43
|
+
"read": { "type": "boolean", "required": true, "default": false },
|
|
44
|
+
"edit": { "type": "boolean", "required": true, "default": false },
|
|
45
|
+
"manage": { "type": "boolean", "required": true, "default": false }
|
|
46
|
+
},
|
|
47
|
+
"alter_columns": {
|
|
48
|
+
"userId": { "ops": ["drop_required"] }
|
|
49
|
+
},
|
|
50
|
+
"add_constraints": {
|
|
51
|
+
"unique_notes": { "type": "unique", "on": ["itemId", "userId", "role", "tag"], "nulls_not_distinct": true }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"wipe": ["notes", "acl.notes"],
|
|
58
|
+
"acl_tables": {
|
|
59
|
+
"notes": "acl.notes"
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/common.d.ts
CHANGED
|
@@ -3,19 +3,6 @@ export declare const NoteInit: z.ZodObject<{
|
|
|
3
3
|
title: z.ZodString;
|
|
4
4
|
content: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
5
5
|
labels: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
6
|
-
publicPermission: z.ZodDefault<z.ZodEnum<{
|
|
7
|
-
readonly None: 0;
|
|
8
|
-
readonly Read: 1;
|
|
9
|
-
readonly Comment: 2;
|
|
10
|
-
readonly Edit: 3;
|
|
11
|
-
readonly Manage: 5;
|
|
12
|
-
}> & {
|
|
13
|
-
readonly None: 0;
|
|
14
|
-
readonly Read: 1;
|
|
15
|
-
readonly Comment: 2;
|
|
16
|
-
readonly Edit: 3;
|
|
17
|
-
readonly Manage: 5;
|
|
18
|
-
}>;
|
|
19
6
|
}, z.core.$strip>;
|
|
20
7
|
export interface NoteInit extends z.infer<typeof NoteInit> {
|
|
21
8
|
}
|
package/dist/common.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { Permission } from '@axium/core/access';
|
|
2
1
|
import * as z from 'zod';
|
|
3
2
|
export const NoteInit = z.object({
|
|
4
3
|
title: z.string().max(100),
|
|
5
4
|
content: z.string().max(10_000).nullish(),
|
|
6
5
|
labels: z.array(z.string().max(30)).default([]),
|
|
7
|
-
publicPermission: Permission.default(0),
|
|
8
6
|
});
|
package/dist/hooks.d.ts
CHANGED
package/dist/hooks.js
CHANGED
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
import {
|
|
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 { notes } = await count('notes');
|
|
9
6
|
return `${notes} notes`;
|
|
10
7
|
}
|
|
11
|
-
export async function db_init() {
|
|
12
|
-
start('Creating table notes');
|
|
13
|
-
await database.schema
|
|
14
|
-
.createTable('notes')
|
|
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('modified', 'timestamptz', col => col.notNull().defaultTo(sql `now()`))
|
|
19
|
-
.addColumn('publicPermission', 'integer', col => col.notNull().defaultTo(0))
|
|
20
|
-
.addColumn('title', 'text', col => col.notNull())
|
|
21
|
-
.addColumn('content', 'text')
|
|
22
|
-
.addColumn('labels', sql `text[]`, col => col.notNull().defaultTo(sql `'{}'::text[]`))
|
|
23
|
-
.execute()
|
|
24
|
-
.then(done)
|
|
25
|
-
.catch(warnExists);
|
|
26
|
-
await createIndex('notes', 'userId');
|
|
27
|
-
await acl.createTable('notes');
|
|
28
|
-
}
|
|
29
|
-
export async function db_wipe() {
|
|
30
|
-
start('Wiping data from notes');
|
|
31
|
-
await database.deleteFrom('notes').execute().then(done);
|
|
32
|
-
await acl.wipeTable('notes');
|
|
33
|
-
}
|
|
34
|
-
export async function remove() {
|
|
35
|
-
await acl.dropTable('notes');
|
|
36
|
-
start('Dropping table notes');
|
|
37
|
-
await database.schema.dropTable('notes').execute().then(done);
|
|
38
|
-
}
|
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 {
|
|
@@ -9,11 +8,8 @@ declare module '@axium/server/database' {
|
|
|
9
8
|
modified: Generated<Date>;
|
|
10
9
|
title: string;
|
|
11
10
|
content: string | null;
|
|
12
|
-
publicPermission: Generated<Permission>;
|
|
13
11
|
labels: Generated<string[]>;
|
|
14
12
|
};
|
|
15
|
-
|
|
16
|
-
interface ExpectedSchema {
|
|
17
|
-
notes: ColumnTypes<Schema['notes']>;
|
|
13
|
+
'acl.notes': DBAccessControl & DBBool<'read' | 'edit' | 'manage'>;
|
|
18
14
|
}
|
|
19
15
|
}
|
package/dist/server.js
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
import { Permission } from '@axium/core';
|
|
2
1
|
import { checkAuthForItem, checkAuthForUser } from '@axium/server/auth';
|
|
3
|
-
import { 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';
|
|
6
5
|
import * as z from 'zod';
|
|
7
6
|
import { NoteInit } from './common.js';
|
|
8
|
-
expectedTypes.notes = {
|
|
9
|
-
id: { type: 'uuid', required: true, hasDefault: true },
|
|
10
|
-
userId: { type: 'uuid', required: true },
|
|
11
|
-
created: { type: 'timestamptz', required: true, hasDefault: true },
|
|
12
|
-
modified: { type: 'timestamptz', required: true, hasDefault: true },
|
|
13
|
-
title: { type: 'text', required: true },
|
|
14
|
-
content: { type: 'text' },
|
|
15
|
-
publicPermission: { type: 'int4', required: true, hasDefault: true },
|
|
16
|
-
labels: { type: '_text', required: true, hasDefault: true },
|
|
17
|
-
};
|
|
18
7
|
addRoute({
|
|
19
8
|
path: '/api/users/:id/notes',
|
|
20
9
|
params: { id: z.uuid() },
|
|
@@ -42,12 +31,12 @@ addRoute({
|
|
|
42
31
|
path: '/api/notes/:id',
|
|
43
32
|
params: { id: z.uuid() },
|
|
44
33
|
async GET(request, { id }) {
|
|
45
|
-
const { item } = await checkAuthForItem(request, 'notes', id,
|
|
34
|
+
const { item } = await checkAuthForItem(request, 'notes', id, { read: true });
|
|
46
35
|
return item;
|
|
47
36
|
},
|
|
48
37
|
async PATCH(request, { id }) {
|
|
49
38
|
const init = await parseBody(request, NoteInit);
|
|
50
|
-
await checkAuthForItem(request, 'notes', id,
|
|
39
|
+
await checkAuthForItem(request, 'notes', id, { edit: true });
|
|
51
40
|
return await database
|
|
52
41
|
.updateTable('notes')
|
|
53
42
|
.set(init)
|
|
@@ -58,7 +47,7 @@ addRoute({
|
|
|
58
47
|
.catch(withError('Could not update note'));
|
|
59
48
|
},
|
|
60
49
|
async DELETE(request, { id }) {
|
|
61
|
-
await checkAuthForItem(request, 'notes', id,
|
|
50
|
+
await checkAuthForItem(request, 'notes', id, { manage: true });
|
|
62
51
|
return await database
|
|
63
52
|
.deleteFrom('notes')
|
|
64
53
|
.where('id', '=', id)
|
package/lib/Note.svelte
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
import { copy } from '@axium/client/clipboard';
|
|
8
8
|
import { download } from 'utilium/dom.js';
|
|
9
9
|
|
|
10
|
-
let { note = $bindable(), notes = $bindable() }: { note: Note; notes?: Note[] } = $props();
|
|
10
|
+
let { note = $bindable(), notes = $bindable(), pageMode = false }: { note: Note; notes?: Note[]; pageMode?: boolean } = $props();
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
|
-
<div class=
|
|
13
|
+
<div class={['note', pageMode && 'full-page']}>
|
|
14
14
|
<div class="note-header">
|
|
15
15
|
<input
|
|
16
16
|
type="text"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
fetchAPI('PATCH', 'notes/:id', note, note.id);
|
|
23
23
|
}}
|
|
24
24
|
/>
|
|
25
|
-
<Popover>
|
|
25
|
+
<Popover showToggle="hover">
|
|
26
26
|
<div
|
|
27
27
|
class="menu-item"
|
|
28
28
|
onclick={() =>
|
|
@@ -77,6 +77,20 @@
|
|
|
77
77
|
padding: 1em;
|
|
78
78
|
border: 1px solid var(--bg-accent);
|
|
79
79
|
background-color: var(--bg-alt);
|
|
80
|
+
height: fit-content;
|
|
81
|
+
max-height: 40em;
|
|
82
|
+
anchor-name: --note;
|
|
83
|
+
|
|
84
|
+
textarea {
|
|
85
|
+
resize: none;
|
|
86
|
+
field-sizing: content;
|
|
87
|
+
height: max-content;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.note.full-page {
|
|
92
|
+
max-height: unset;
|
|
93
|
+
height: 100%;
|
|
80
94
|
}
|
|
81
95
|
|
|
82
96
|
.note-header {
|
|
@@ -90,12 +104,4 @@
|
|
|
90
104
|
padding: 0;
|
|
91
105
|
}
|
|
92
106
|
}
|
|
93
|
-
|
|
94
|
-
.note :global(.popover-toggle) {
|
|
95
|
-
visibility: hidden;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.note:hover :global(.popover-toggle) {
|
|
99
|
-
visibility: visible;
|
|
100
|
-
}
|
|
101
107
|
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axium/notes",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"author": "James Prevett <axium@jamespre.dev>",
|
|
5
5
|
"description": "Notes 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
|
|
38
|
-
"@axium/core": ">=0.
|
|
39
|
-
"@axium/server": ">=0.
|
|
38
|
+
"@axium/client": ">=0.9.6",
|
|
39
|
+
"@axium/core": ">=0.12.0",
|
|
40
|
+
"@axium/server": ">=0.28.0",
|
|
40
41
|
"@sveltejs/kit": "^2.27.3",
|
|
41
42
|
"utilium": "^2.4.0"
|
|
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
|
{
|
|
@@ -15,18 +15,17 @@
|
|
|
15
15
|
|
|
16
16
|
<div class="notes-main">
|
|
17
17
|
<h1>Notes</h1>
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
</span>
|
|
18
|
+
<button
|
|
19
|
+
id="create-note"
|
|
20
|
+
class="icon-text mobile-float-right"
|
|
21
|
+
onclick={async () => {
|
|
22
|
+
const result = await fetchAPI('PUT', 'users/:id/notes', { title: '' }, data.session.userId);
|
|
23
|
+
parseNote(result);
|
|
24
|
+
notes.push(result);
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
<Icon i="plus" /> New Note
|
|
28
|
+
</button>
|
|
30
29
|
<div class="lists-container">
|
|
31
30
|
{#each notes as note}
|
|
32
31
|
<Note {note} bind:notes />
|
|
@@ -48,4 +47,8 @@
|
|
|
48
47
|
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
|
49
48
|
gap: 1em;
|
|
50
49
|
}
|
|
50
|
+
|
|
51
|
+
#create-note {
|
|
52
|
+
width: fit-content;
|
|
53
|
+
}
|
|
51
54
|
</style>
|