@dinoxx/dinox-cli 1.0.18 → 1.0.20
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/README.md +807 -418
- package/dist/auth/userInfo.d.ts +2 -0
- package/dist/auth/userInfo.js +28 -11
- package/dist/cli.js +15 -1
- package/dist/commands/auth/index.d.ts +2 -0
- package/dist/commands/auth/index.js +217 -163
- package/dist/commands/boxes/index.d.ts +2 -0
- package/dist/commands/boxes/index.js +119 -75
- package/dist/commands/boxes/repo.d.ts +8 -0
- package/dist/commands/boxes/repo.js +41 -0
- package/dist/commands/config/index.d.ts +2 -0
- package/dist/commands/config/index.js +85 -36
- package/dist/commands/descriptor/register.d.ts +8 -0
- package/dist/commands/descriptor/register.js +113 -0
- package/dist/commands/descriptor/types.d.ts +37 -0
- package/dist/commands/descriptor/types.js +17 -0
- package/dist/commands/graph/index.d.ts +2 -0
- package/dist/commands/graph/index.js +143 -73
- package/dist/commands/info/index.d.ts +2 -0
- package/dist/commands/info/index.js +41 -14
- package/dist/commands/mcp/index.js +11 -10
- package/dist/commands/mcp/server.js +8 -4
- package/dist/commands/mcp/tools.js +30 -104
- package/dist/commands/mcp/types.d.ts +8 -1
- package/dist/commands/meta/index.d.ts +2 -0
- package/dist/commands/meta/index.js +64 -33
- package/dist/commands/meta/repo.d.ts +6 -0
- package/dist/commands/meta/repo.js +6 -0
- package/dist/commands/notes/actions.d.ts +10 -0
- package/dist/commands/notes/actions.js +403 -0
- package/dist/commands/notes/descriptors.d.ts +4 -0
- package/dist/commands/notes/descriptors.js +250 -0
- package/dist/commands/notes/dryRun.d.ts +31 -0
- package/dist/commands/notes/dryRun.js +130 -0
- package/dist/commands/notes/index.d.ts +2 -51
- package/dist/commands/notes/index.js +2 -581
- package/dist/commands/notes/repo.d.ts +9 -0
- package/dist/commands/notes/repo.js +56 -10
- package/dist/commands/notes/runtime.d.ts +28 -0
- package/dist/commands/notes/runtime.js +185 -0
- package/dist/commands/notes/searchOutput.d.ts +10 -2
- package/dist/commands/notes/searchOutput.js +14 -2
- package/dist/commands/notes/searchResponse.d.ts +51 -0
- package/dist/commands/notes/searchResponse.js +56 -0
- package/dist/commands/notes/searchSql.js +2 -0
- package/dist/commands/prompt/index.d.ts +2 -0
- package/dist/commands/prompt/index.js +122 -72
- package/dist/commands/prompt/repo.d.ts +7 -0
- package/dist/commands/prompt/repo.js +46 -0
- package/dist/commands/schema/commandMetadata.d.ts +2 -0
- package/dist/commands/schema/commandMetadata.js +18 -0
- package/dist/commands/schema/globalOptions.d.ts +3 -0
- package/dist/commands/schema/globalOptions.js +3 -0
- package/dist/commands/schema/index.d.ts +4 -0
- package/dist/commands/schema/index.js +109 -0
- package/dist/commands/schema/renderSkills.d.ts +6 -0
- package/dist/commands/schema/renderSkills.js +216 -0
- package/dist/commands/schema/spec.d.ts +6 -0
- package/dist/commands/schema/spec.js +40 -0
- package/dist/commands/schema/types.d.ts +47 -0
- package/dist/commands/schema/types.js +1 -0
- package/dist/commands/storage/index.d.ts +4 -0
- package/dist/commands/storage/index.js +292 -0
- package/dist/commands/storage/repo.d.ts +162 -0
- package/dist/commands/storage/repo.js +770 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +41 -27
- package/dist/commands/tags/index.d.ts +2 -0
- package/dist/commands/tags/index.js +121 -79
- package/dist/commands/tags/repo.d.ts +7 -0
- package/dist/commands/tags/repo.js +52 -0
- package/dist/commands/todo/dryRun.d.ts +23 -0
- package/dist/commands/todo/dryRun.js +133 -0
- package/dist/commands/todo/index.d.ts +2 -0
- package/dist/commands/todo/index.js +285 -135
- package/dist/commands/todo/repo.d.ts +11 -0
- package/dist/commands/todo/repo.js +37 -9
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.js +35 -13
- package/dist/commands/writeDryRun.d.ts +62 -0
- package/dist/commands/writeDryRun.js +131 -0
- package/dist/config/paths.d.ts +2 -1
- package/dist/config/paths.js +11 -1
- package/dist/config/resolve.js +7 -5
- package/dist/constants/links.d.ts +1 -1
- package/dist/constants/links.js +1 -1
- package/dist/daemon/ensure.js +3 -2
- package/dist/daemon/index.js +17 -15
- package/dist/dinox.js +9 -13
- package/dist/powersync/runtime.d.ts +1 -1
- package/dist/powersync/runtime.js +5 -3
- package/dist/powersync/schema/index.d.ts +27 -0
- package/dist/powersync/schema/index.js +2 -0
- package/dist/powersync/schema/note.d.ts +1 -0
- package/dist/powersync/schema/note.js +1 -0
- package/dist/powersync/schema/projects.d.ts +3 -0
- package/dist/powersync/schema/projects.js +3 -0
- package/dist/powersync/schema/storage.d.ts +24 -0
- package/dist/powersync/schema/storage.js +24 -0
- package/dist/skills/check.d.ts +6 -0
- package/dist/skills/check.js +254 -0
- package/dist/utils/bidlinkCanonicalization.d.ts +2 -0
- package/dist/utils/bidlinkCanonicalization.js +161 -0
- package/dist/utils/dryRun.d.ts +13 -0
- package/dist/utils/dryRun.js +69 -0
- package/dist/utils/output.d.ts +19 -0
- package/dist/utils/output.js +155 -1
- package/dist/utils/terminalSanitization.d.ts +2 -0
- package/dist/utils/terminalSanitization.js +33 -0
- package/dist/utils/tiptapMarkdown.d.ts +4 -1
- package/dist/utils/tiptapMarkdown.js +285 -113
- package/dist/utils/tiptapMarkdownSchema.d.ts +37 -0
- package/dist/utils/tiptapMarkdownSchema.js +577 -0
- package/dist/utils/tiptapMarkdownSchemaUtils.d.ts +74 -0
- package/dist/utils/tiptapMarkdownSchemaUtils.js +394 -0
- package/dist/utils/updateNotice.d.ts +7 -0
- package/dist/utils/updateNotice.js +64 -0
- package/package.json +25 -3
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { registerCommandGroup } from '../descriptor/register.js';
|
|
2
|
+
import { FORMAT_OPTIONS, OFFLINE_OPTIONS, SYNC_TIMEOUT_OPTIONS } from '../schema/globalOptions.js';
|
|
3
|
+
import { runNoteCreate, runNoteDelete, runNoteDetail, runNoteGet, runNotePreview, runNoteSearch, runNoteStar, runNoteUnstar, runNoteUpdate, } from './actions.js';
|
|
4
|
+
const NOTE_GLOBAL_OPTIONS = [...FORMAT_OPTIONS, ...OFFLINE_OPTIONS, ...SYNC_TIMEOUT_OPTIONS];
|
|
5
|
+
export const noteCommandGroup = {
|
|
6
|
+
name: 'note',
|
|
7
|
+
description: 'Manage notes',
|
|
8
|
+
commands: [
|
|
9
|
+
{
|
|
10
|
+
name: 'search',
|
|
11
|
+
description: 'Search notes by keyword, tags, date range, boxes, or SQL-like filter',
|
|
12
|
+
arguments: [{ syntax: '[query]', description: 'Search keyword; may be omitted for filter-only search' }],
|
|
13
|
+
options: [
|
|
14
|
+
{ flags: '--tags <expr>', description: 'Tag expression with AND/OR/NOT, or [] for empty tags', type: 'string' },
|
|
15
|
+
{ flags: '--from <date>', description: 'created_at start (YYYY-MM-DD or ISO datetime)', type: 'string' },
|
|
16
|
+
{ flags: '--to <date>', description: 'created_at end (YYYY-MM-DD or ISO datetime)', type: 'string' },
|
|
17
|
+
{ flags: '--days <n>', description: 'Recent N days by created_at; mutually exclusive with --from/--to', type: 'number' },
|
|
18
|
+
{ flags: '--starred <true|false>', description: 'Filter by starred status', type: 'string', enum: ['true', 'false'] },
|
|
19
|
+
{ flags: '--boxes <string|@file>', description: 'Box names (JSON array/comma list), or [] for empty boxes', type: 'string' },
|
|
20
|
+
{ flags: '--sql <expr>', description: 'SQL-like expression over id/content_md/summary/tags/zettel_boxes/created_at/type/is_starred', type: 'string' },
|
|
21
|
+
{ flags: '--limit <n>', description: 'Maximum returned notes', type: 'number' },
|
|
22
|
+
{ flags: '--offset <n>', description: 'Result offset for pagination', type: 'number', defaultValue: 0 },
|
|
23
|
+
{ flags: '--fields <list>', description: 'Comma-separated fields: id,title,summary,tags,created_at,boxes,is_starred', type: 'string[]' },
|
|
24
|
+
{ flags: '--include-deleted', description: 'Include soft-deleted notes', type: 'boolean' },
|
|
25
|
+
],
|
|
26
|
+
schema: {
|
|
27
|
+
path: 'note.search',
|
|
28
|
+
risk: 'read',
|
|
29
|
+
auth: 'required',
|
|
30
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
31
|
+
output: {
|
|
32
|
+
type: 'structured',
|
|
33
|
+
summary: 'AI-friendly note search payload',
|
|
34
|
+
entity: 'note_search_result',
|
|
35
|
+
fields: ['id', 'title', 'summary', 'tags', 'created_at', 'boxes', 'is_starred'],
|
|
36
|
+
metaFields: ['query', 'returned_count', 'total_count', 'stale', 'pagination', 'fields', 'applied_filters'],
|
|
37
|
+
},
|
|
38
|
+
mcp: {
|
|
39
|
+
toolName: 'dinox_search_notes',
|
|
40
|
+
description: 'Search notes by keyword, tags, date range, or SQL expression',
|
|
41
|
+
properties: [
|
|
42
|
+
{ name: 'query', type: 'string', description: 'Search keyword' },
|
|
43
|
+
{ name: 'tags', type: 'string', description: 'Tag expression (AND/OR/NOT)' },
|
|
44
|
+
{ name: 'from', type: 'string', description: 'Start date (YYYY-MM-DD)' },
|
|
45
|
+
{ name: 'to', type: 'string', description: 'End date (YYYY-MM-DD)' },
|
|
46
|
+
{ name: 'days', type: 'number', description: 'Recent N days' },
|
|
47
|
+
{ name: 'boxes', type: 'string[]', description: 'Box names' },
|
|
48
|
+
{ name: 'limit', type: 'number', description: 'Max results (default: 50)' },
|
|
49
|
+
{ name: 'offset', type: 'number', description: 'Result offset (default: 0)' },
|
|
50
|
+
{ name: 'fields', type: 'string[]', description: 'Returned fields: id,title,summary,tags,created_at,boxes,is_starred' },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
examples: [
|
|
54
|
+
'dino note search "AI" --days 7 --format json',
|
|
55
|
+
'dino note search --tags "(work OR life) AND NOT archived" --format json',
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
action: runNoteSearch,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'get',
|
|
62
|
+
description: 'Get one note by id, optionally in lightweight context mode',
|
|
63
|
+
arguments: [{ syntax: '<id>', description: 'Note id' }],
|
|
64
|
+
options: [{ flags: '--context-only', description: 'Return lightweight note context (title/tags/summary/links)', type: 'boolean' }],
|
|
65
|
+
schema: {
|
|
66
|
+
path: 'note.get',
|
|
67
|
+
risk: 'read',
|
|
68
|
+
auth: 'required',
|
|
69
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
70
|
+
output: {
|
|
71
|
+
type: 'structured',
|
|
72
|
+
summary: 'Single note or note context payload',
|
|
73
|
+
entity: 'note_context',
|
|
74
|
+
fields: ['id', 'title', 'summary', 'tags', 'created_at', 'updated_at', 'is_del', 'boxes', 'links'],
|
|
75
|
+
},
|
|
76
|
+
examples: ['dino note get <id> --context-only --format json', 'dino note get <id> --format json'],
|
|
77
|
+
},
|
|
78
|
+
action: runNoteGet,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'preview',
|
|
82
|
+
description: 'Preview the first N lines of note markdown',
|
|
83
|
+
arguments: [{ syntax: '<id>', description: 'Note id' }],
|
|
84
|
+
options: [{ flags: '--lines <n>', description: 'Number of lines to return', type: 'number', defaultValue: 10 }],
|
|
85
|
+
schema: {
|
|
86
|
+
path: 'note.preview',
|
|
87
|
+
risk: 'read',
|
|
88
|
+
auth: 'required',
|
|
89
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
90
|
+
output: {
|
|
91
|
+
type: 'structured',
|
|
92
|
+
summary: 'Markdown preview payload',
|
|
93
|
+
fields: ['note.id', 'note.title', 'note.preview', 'note.lines', 'note.truncated', 'stale'],
|
|
94
|
+
},
|
|
95
|
+
examples: ['dino note preview <id> --lines 30 --format json'],
|
|
96
|
+
},
|
|
97
|
+
action: runNotePreview,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'detail',
|
|
101
|
+
description: 'Get full note details for one or more ids',
|
|
102
|
+
arguments: [{ syntax: '[id]', description: 'Optional note id when reading a single note' }],
|
|
103
|
+
options: [{ flags: '--ids <string|@file>', description: 'Batch note ids (JSON array or comma/newline-separated)', type: 'string' }],
|
|
104
|
+
schema: {
|
|
105
|
+
path: 'note.detail',
|
|
106
|
+
risk: 'read',
|
|
107
|
+
auth: 'required',
|
|
108
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
109
|
+
output: {
|
|
110
|
+
type: 'structured',
|
|
111
|
+
summary: 'One full note object or an ordered array of note objects',
|
|
112
|
+
fields: ['id', 'title', 'content_md', 'content_text', 'content_json', 'tags', 'boxes', 'created_at', 'updated_at', 'is_del'],
|
|
113
|
+
},
|
|
114
|
+
mcp: {
|
|
115
|
+
toolName: 'dinox_get_note',
|
|
116
|
+
description: 'Get note details by ID',
|
|
117
|
+
properties: [{ name: 'id', type: 'string', description: 'Note ID', required: true }],
|
|
118
|
+
},
|
|
119
|
+
examples: ['dino note detail <id> --format json', 'dino note detail --ids @/tmp/note-ids.txt --format json'],
|
|
120
|
+
},
|
|
121
|
+
action: runNoteDetail,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'create',
|
|
125
|
+
description: 'Create a new note from markdown content',
|
|
126
|
+
options: [
|
|
127
|
+
{ flags: '--title <string>', description: 'Note title', required: true, type: 'string' },
|
|
128
|
+
{ flags: '--content <string|@file>', description: 'Markdown content', required: true, type: 'string' },
|
|
129
|
+
{ flags: '--type <note|crawl>', description: 'Note type: note or crawl', type: 'string', defaultValue: 'crawl', enum: ['note', 'crawl'] },
|
|
130
|
+
{ flags: '--tags <string|@file>', description: 'Tag list (JSON array or comma/newline-separated)', type: 'string' },
|
|
131
|
+
{ flags: '--boxes <string|@file>', description: 'Box names (JSON array or comma/newline-separated)', type: 'string' },
|
|
132
|
+
{ flags: '--dry-run', description: 'Preview the write without executing it', type: 'boolean' },
|
|
133
|
+
],
|
|
134
|
+
schema: {
|
|
135
|
+
path: 'note.create',
|
|
136
|
+
risk: 'write',
|
|
137
|
+
auth: 'required',
|
|
138
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
139
|
+
output: {
|
|
140
|
+
type: 'structured',
|
|
141
|
+
summary: 'Creation acknowledgement with the new note id',
|
|
142
|
+
fields: ['id', 'stale'],
|
|
143
|
+
},
|
|
144
|
+
mcp: {
|
|
145
|
+
toolName: 'dinox_create_note',
|
|
146
|
+
description: 'Create a new note',
|
|
147
|
+
properties: [
|
|
148
|
+
{ name: 'title', type: 'string', description: 'Note title', required: true },
|
|
149
|
+
{ name: 'content', type: 'string', description: 'Markdown content', required: true },
|
|
150
|
+
{ name: 'tags', type: 'string[]', description: 'Tags' },
|
|
151
|
+
{ name: 'boxes', type: 'string[]', description: 'Zettel boxes' },
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
examples: ['dino note create --title "Weekly note" --content @/tmp/note.md --type note --format json'],
|
|
155
|
+
},
|
|
156
|
+
action: runNoteCreate,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'update',
|
|
160
|
+
description: 'Full-replace note tags, boxes, and/or starred state',
|
|
161
|
+
arguments: [{ syntax: '[id]', description: 'Optional note id for single-note update' }],
|
|
162
|
+
options: [
|
|
163
|
+
{ flags: '--ids <string|@file>', description: 'Batch note ids (JSON array or comma/newline-separated)', type: 'string' },
|
|
164
|
+
{ flags: '--tags <string|@file>', description: 'Full-replace tag list; use [] to clear', type: 'string' },
|
|
165
|
+
{ flags: '--boxes <string|@file>', description: 'Full-replace box names; use [] to clear', type: 'string' },
|
|
166
|
+
{ flags: '--starred <true|false>', description: 'Set starred status', type: 'string', enum: ['true', 'false'] },
|
|
167
|
+
{ flags: '--dry-run', description: 'Preview the write without executing it', type: 'boolean' },
|
|
168
|
+
],
|
|
169
|
+
schema: {
|
|
170
|
+
path: 'note.update',
|
|
171
|
+
risk: 'write',
|
|
172
|
+
auth: 'required',
|
|
173
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
174
|
+
output: {
|
|
175
|
+
type: 'structured',
|
|
176
|
+
summary: 'Mutation result with per-note update status',
|
|
177
|
+
fields: ['total', 'updatedCount', 'results', 'stale'],
|
|
178
|
+
},
|
|
179
|
+
examples: ['dino note update <id> --tags "work,ai" --format json', 'dino note update --ids @/tmp/note-ids.txt --boxes "Inbox" --format json'],
|
|
180
|
+
},
|
|
181
|
+
action: runNoteUpdate,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: 'delete',
|
|
185
|
+
description: 'Soft-delete a note by setting is_del=1',
|
|
186
|
+
arguments: [{ syntax: '<id>', description: 'Note id' }],
|
|
187
|
+
options: [{ flags: '--dry-run', description: 'Preview the write without executing it', type: 'boolean' }],
|
|
188
|
+
schema: {
|
|
189
|
+
path: 'note.delete',
|
|
190
|
+
risk: 'high-risk-write',
|
|
191
|
+
auth: 'required',
|
|
192
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
193
|
+
output: {
|
|
194
|
+
type: 'structured',
|
|
195
|
+
summary: 'Deletion acknowledgement',
|
|
196
|
+
fields: ['id', 'stale'],
|
|
197
|
+
},
|
|
198
|
+
examples: ['dino note delete <id> --format json'],
|
|
199
|
+
},
|
|
200
|
+
action: runNoteDelete,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'star',
|
|
204
|
+
description: 'Mark one or more notes as starred',
|
|
205
|
+
arguments: [{ syntax: '[id]', description: 'Optional note id for single-note update' }],
|
|
206
|
+
options: [
|
|
207
|
+
{ flags: '--ids <string|@file>', description: 'Batch note ids (JSON array or comma/newline-separated)', type: 'string' },
|
|
208
|
+
{ flags: '--dry-run', description: 'Preview the write without executing it', type: 'boolean' },
|
|
209
|
+
],
|
|
210
|
+
schema: {
|
|
211
|
+
path: 'note.star',
|
|
212
|
+
risk: 'write',
|
|
213
|
+
auth: 'required',
|
|
214
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
215
|
+
output: {
|
|
216
|
+
type: 'structured',
|
|
217
|
+
summary: 'Mutation result with per-note starred status',
|
|
218
|
+
fields: ['total', 'updatedCount', 'results', 'stale'],
|
|
219
|
+
},
|
|
220
|
+
examples: ['dino note star <id> --format json --dry-run'],
|
|
221
|
+
},
|
|
222
|
+
action: runNoteStar,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: 'unstar',
|
|
226
|
+
description: 'Mark one or more notes as not starred',
|
|
227
|
+
arguments: [{ syntax: '[id]', description: 'Optional note id for single-note update' }],
|
|
228
|
+
options: [
|
|
229
|
+
{ flags: '--ids <string|@file>', description: 'Batch note ids (JSON array or comma/newline-separated)', type: 'string' },
|
|
230
|
+
{ flags: '--dry-run', description: 'Preview the write without executing it', type: 'boolean' },
|
|
231
|
+
],
|
|
232
|
+
schema: {
|
|
233
|
+
path: 'note.unstar',
|
|
234
|
+
risk: 'write',
|
|
235
|
+
auth: 'required',
|
|
236
|
+
globalOptions: NOTE_GLOBAL_OPTIONS,
|
|
237
|
+
output: {
|
|
238
|
+
type: 'structured',
|
|
239
|
+
summary: 'Mutation result with per-note starred status',
|
|
240
|
+
fields: ['total', 'updatedCount', 'results', 'stale'],
|
|
241
|
+
},
|
|
242
|
+
examples: ['dino note unstar <id> --format json --dry-run'],
|
|
243
|
+
},
|
|
244
|
+
action: runNoteUnstar,
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
};
|
|
248
|
+
export function registerNoteCommands(program) {
|
|
249
|
+
registerCommandGroup(program, noteCommandGroup);
|
|
250
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AbstractPowerSyncDatabase } from '@powersync/common';
|
|
2
|
+
import type { ResolvedDinoxConfig } from '../../config/types.js';
|
|
3
|
+
import type { DryRunPreview } from '../../utils/dryRun.js';
|
|
4
|
+
export declare function buildNoteCreateDryRunPreview(args: {
|
|
5
|
+
db: AbstractPowerSyncDatabase;
|
|
6
|
+
config: ResolvedDinoxConfig;
|
|
7
|
+
offline: boolean;
|
|
8
|
+
userId: string;
|
|
9
|
+
title: string;
|
|
10
|
+
noteType: 'note' | 'crawl';
|
|
11
|
+
contentMd: string;
|
|
12
|
+
tagsInput: string[];
|
|
13
|
+
zettelBoxNames: string[];
|
|
14
|
+
}): Promise<DryRunPreview>;
|
|
15
|
+
export declare function buildNoteUpdateDryRunPreview(args: {
|
|
16
|
+
db: AbstractPowerSyncDatabase;
|
|
17
|
+
config: ResolvedDinoxConfig;
|
|
18
|
+
offline: boolean;
|
|
19
|
+
ids: string[];
|
|
20
|
+
tagsInput?: string[];
|
|
21
|
+
zettelBoxNames?: string[];
|
|
22
|
+
starred?: boolean;
|
|
23
|
+
commandName: 'dino note update' | 'dino note star' | 'dino note unstar';
|
|
24
|
+
action: 'update_note' | 'star_note' | 'unstar_note';
|
|
25
|
+
}): Promise<DryRunPreview>;
|
|
26
|
+
export declare function buildNoteDeleteDryRunPreview(args: {
|
|
27
|
+
db: AbstractPowerSyncDatabase;
|
|
28
|
+
config: ResolvedDinoxConfig;
|
|
29
|
+
offline: boolean;
|
|
30
|
+
id: string;
|
|
31
|
+
}): Promise<DryRunPreview>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { convertMarkdownToNoteContent } from '../../utils/tiptapMarkdown.js';
|
|
2
|
+
import { canonicalizeBidlinksInMarkdown } from '../../utils/bidlinkCanonicalization.js';
|
|
3
|
+
import { DinoxError } from '../../utils/errors.js';
|
|
4
|
+
import { assertNotesUpdatable, getNoteDetails, parseStoredTags, resolveZettelBoxIdsForCreate, resolveZettelBoxIdsForUpdate, validateTagsForCreate, validateTagsForUpdate, } from './repo.js';
|
|
5
|
+
function normalizeDistinctStrings(values) {
|
|
6
|
+
return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
|
|
7
|
+
}
|
|
8
|
+
function normalizeLowerSet(values) {
|
|
9
|
+
return normalizeDistinctStrings(values).map((value) => value.toLowerCase()).sort();
|
|
10
|
+
}
|
|
11
|
+
function sameNormalizedSet(left, right) {
|
|
12
|
+
const leftNormalized = normalizeLowerSet(left);
|
|
13
|
+
const rightNormalized = normalizeLowerSet(right);
|
|
14
|
+
if (leftNormalized.length !== rightNormalized.length) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return leftNormalized.every((value, index) => value === rightNormalized[index]);
|
|
18
|
+
}
|
|
19
|
+
function buildExecutionWarnings(config, offline) {
|
|
20
|
+
const warnings = [];
|
|
21
|
+
if (offline) {
|
|
22
|
+
warnings.push('Execution would run in offline mode and only use the local cache.');
|
|
23
|
+
}
|
|
24
|
+
if (!offline && !config.powersync.uploadBaseUrl) {
|
|
25
|
+
warnings.push('Execution would be local-only because powersync.uploadBaseUrl is unset.');
|
|
26
|
+
}
|
|
27
|
+
return warnings;
|
|
28
|
+
}
|
|
29
|
+
export async function buildNoteCreateDryRunPreview(args) {
|
|
30
|
+
const canonicalContentMd = await canonicalizeBidlinksInMarkdown(args.db, args.contentMd, args.userId);
|
|
31
|
+
const { contentText } = convertMarkdownToNoteContent(canonicalContentMd);
|
|
32
|
+
const tags = await validateTagsForCreate(args.db, args.tagsInput);
|
|
33
|
+
await resolveZettelBoxIdsForCreate(args.db, args.zettelBoxNames);
|
|
34
|
+
return {
|
|
35
|
+
dry_run: true,
|
|
36
|
+
command: 'dino note create',
|
|
37
|
+
action: 'create_note',
|
|
38
|
+
risk: 'write',
|
|
39
|
+
summary: `Create a ${args.noteType} note titled "${args.title}".`,
|
|
40
|
+
warnings: buildExecutionWarnings(args.config, args.offline),
|
|
41
|
+
inputs: {
|
|
42
|
+
title: args.title,
|
|
43
|
+
type: args.noteType,
|
|
44
|
+
tags,
|
|
45
|
+
boxes: normalizeDistinctStrings(args.zettelBoxNames),
|
|
46
|
+
content_chars: args.contentMd.length,
|
|
47
|
+
canonicalized_content_chars: canonicalContentMd.length,
|
|
48
|
+
markdown_changed: canonicalContentMd !== args.contentMd,
|
|
49
|
+
},
|
|
50
|
+
changes: {
|
|
51
|
+
title: args.title,
|
|
52
|
+
type: args.noteType,
|
|
53
|
+
tags,
|
|
54
|
+
boxes: normalizeDistinctStrings(args.zettelBoxNames),
|
|
55
|
+
content_preview: contentText.slice(0, 200),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export async function buildNoteUpdateDryRunPreview(args) {
|
|
60
|
+
await assertNotesUpdatable(args.db, args.ids);
|
|
61
|
+
const nextTags = Array.isArray(args.tagsInput)
|
|
62
|
+
? await validateTagsForUpdate(args.db, args.tagsInput)
|
|
63
|
+
: undefined;
|
|
64
|
+
if (Array.isArray(args.zettelBoxNames)) {
|
|
65
|
+
await resolveZettelBoxIdsForUpdate(args.db, args.zettelBoxNames);
|
|
66
|
+
}
|
|
67
|
+
const details = await getNoteDetails(args.db, args.ids);
|
|
68
|
+
const changes = details.map((note) => {
|
|
69
|
+
const currentTags = parseStoredTags(note.tags);
|
|
70
|
+
const nextBoxes = Array.isArray(args.zettelBoxNames) ? normalizeDistinctStrings(args.zettelBoxNames) : note.zettel_boxes;
|
|
71
|
+
const tagsTo = nextTags ?? currentTags;
|
|
72
|
+
const starredTo = typeof args.starred === 'boolean' ? args.starred : note.is_starred;
|
|
73
|
+
return {
|
|
74
|
+
id: note.id,
|
|
75
|
+
title: note.title ?? '',
|
|
76
|
+
tags_from: currentTags,
|
|
77
|
+
tags_to: tagsTo,
|
|
78
|
+
tags_changed: Array.isArray(args.tagsInput) ? !sameNormalizedSet(currentTags, tagsTo) : false,
|
|
79
|
+
boxes_from: note.zettel_boxes,
|
|
80
|
+
boxes_to: nextBoxes,
|
|
81
|
+
boxes_changed: Array.isArray(args.zettelBoxNames) ? !sameNormalizedSet(note.zettel_boxes, nextBoxes) : false,
|
|
82
|
+
starred_from: note.is_starred,
|
|
83
|
+
starred_to: starredTo,
|
|
84
|
+
starred_changed: typeof args.starred === 'boolean' ? note.is_starred !== starredTo : false,
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
const changedCount = changes.filter((item) => item.tags_changed || item.boxes_changed || item.starred_changed).length;
|
|
88
|
+
return {
|
|
89
|
+
dry_run: true,
|
|
90
|
+
command: args.commandName,
|
|
91
|
+
action: args.action,
|
|
92
|
+
risk: 'write',
|
|
93
|
+
summary: `Preview ${args.action.replace(/_/g, ' ')} for ${args.ids.length} note(s); ${changedCount} note(s) would change.`,
|
|
94
|
+
warnings: buildExecutionWarnings(args.config, args.offline),
|
|
95
|
+
inputs: {
|
|
96
|
+
ids: args.ids,
|
|
97
|
+
...(Array.isArray(args.tagsInput) ? { tags: nextTags } : {}),
|
|
98
|
+
...(Array.isArray(args.zettelBoxNames) ? { boxes: normalizeDistinctStrings(args.zettelBoxNames) } : {}),
|
|
99
|
+
...(typeof args.starred === 'boolean' ? { starred: args.starred } : {}),
|
|
100
|
+
},
|
|
101
|
+
targets: changes.map((item) => ({ id: item.id, title: item.title })),
|
|
102
|
+
changes,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export async function buildNoteDeleteDryRunPreview(args) {
|
|
106
|
+
const details = await getNoteDetails(args.db, [args.id]);
|
|
107
|
+
const note = details[0];
|
|
108
|
+
if (!note) {
|
|
109
|
+
throw new DinoxError(`Note not found: ${args.id}`);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
dry_run: true,
|
|
113
|
+
command: 'dino note delete',
|
|
114
|
+
action: 'delete_note',
|
|
115
|
+
risk: 'high-risk-write',
|
|
116
|
+
summary: `Soft-delete note "${note.title ?? ''}" (${note.id}).`,
|
|
117
|
+
warnings: buildExecutionWarnings(args.config, args.offline),
|
|
118
|
+
targets: [
|
|
119
|
+
{
|
|
120
|
+
id: note.id,
|
|
121
|
+
title: note.title ?? '',
|
|
122
|
+
is_del: note.is_del,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
changes: {
|
|
126
|
+
is_del_from: note.is_del ?? 0,
|
|
127
|
+
is_del_to: 1,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
@@ -1,51 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
type NoteSearchResponse = {
|
|
4
|
-
meta: {
|
|
5
|
-
query: string;
|
|
6
|
-
returned_count: number;
|
|
7
|
-
total_count: number;
|
|
8
|
-
stale: boolean;
|
|
9
|
-
pagination: {
|
|
10
|
-
limit: number | null;
|
|
11
|
-
offset: number;
|
|
12
|
-
has_more: boolean;
|
|
13
|
-
};
|
|
14
|
-
fields: NoteSearchField[] | null;
|
|
15
|
-
applied_filters: {
|
|
16
|
-
include_deleted: boolean;
|
|
17
|
-
tags_expression: string | null;
|
|
18
|
-
created_at_range: {
|
|
19
|
-
from: string | null;
|
|
20
|
-
to: string | null;
|
|
21
|
-
} | null;
|
|
22
|
-
days: number | null;
|
|
23
|
-
box_names: string[];
|
|
24
|
-
box_ids: string[];
|
|
25
|
-
match_empty_boxes: boolean;
|
|
26
|
-
sql_expression: string | null;
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
notes: NoteSearchResultItem[];
|
|
30
|
-
};
|
|
31
|
-
type BuildNoteSearchResponseInput = {
|
|
32
|
-
query: string;
|
|
33
|
-
notes: NoteSearchResultItem[];
|
|
34
|
-
totalCount: number;
|
|
35
|
-
stale: boolean;
|
|
36
|
-
includeDeleted: boolean;
|
|
37
|
-
limit?: number;
|
|
38
|
-
offset?: number;
|
|
39
|
-
fields?: NoteSearchField[];
|
|
40
|
-
tagsExpression?: string;
|
|
41
|
-
createdAtFrom?: string;
|
|
42
|
-
createdAtTo?: string;
|
|
43
|
-
days?: number;
|
|
44
|
-
boxNames: string[];
|
|
45
|
-
boxIds: string[];
|
|
46
|
-
matchEmptyBoxes: boolean;
|
|
47
|
-
sqlExpression?: string;
|
|
48
|
-
};
|
|
49
|
-
export declare function buildNoteSearchResponse(input: BuildNoteSearchResponseInput): NoteSearchResponse;
|
|
50
|
-
export declare function registerNoteCommands(program: Command): void;
|
|
51
|
-
export {};
|
|
1
|
+
export { buildNoteSearchResponse, type BuildNoteSearchResponseInput, type NoteSearchResponse, } from './searchResponse.js';
|
|
2
|
+
export { noteCommandGroup, registerNoteCommands } from './descriptors.js';
|