@dinoxx/dinox-cli 1.0.20 → 1.0.21
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 +72 -139
- package/dist/auth/userInfo.d.ts +8 -1
- package/dist/auth/userInfo.js +38 -6
- package/dist/cli.js +0 -2
- package/dist/commands/auth/index.js +11 -4
- package/dist/commands/boxes/index.js +272 -52
- package/dist/commands/boxes/model.d.ts +34 -0
- package/dist/commands/boxes/model.js +78 -0
- package/dist/commands/boxes/operations.d.ts +86 -0
- package/dist/commands/boxes/operations.js +415 -0
- package/dist/commands/boxes/repo.d.ts +13 -6
- package/dist/commands/boxes/repo.js +272 -149
- package/dist/commands/boxes/store.d.ts +22 -0
- package/dist/commands/boxes/store.js +143 -0
- package/dist/commands/graph/index.js +2 -36
- package/dist/commands/mcp/noteContentTools.d.ts +222 -0
- package/dist/commands/mcp/noteContentTools.js +390 -0
- package/dist/commands/mcp/server.d.ts +3 -0
- package/dist/commands/mcp/server.js +43 -15
- package/dist/commands/mcp/tools.js +3 -1
- package/dist/commands/mcp/types.d.ts +6 -2
- package/dist/commands/meta/index.js +6 -22
- package/dist/commands/meta/repo.d.ts +0 -3
- package/dist/commands/meta/repo.js +1 -4
- package/dist/commands/notes/actions.d.ts +2 -0
- package/dist/commands/notes/actions.js +149 -55
- package/dist/commands/notes/bulk.d.ts +34 -0
- package/dist/commands/notes/bulk.js +204 -0
- package/dist/commands/notes/contentEngine.d.ts +95 -0
- package/dist/commands/notes/contentEngine.js +652 -0
- package/dist/commands/notes/contentPatch.d.ts +84 -0
- package/dist/commands/notes/contentPatch.js +337 -0
- package/dist/commands/notes/contentPatchCommand.d.ts +3 -0
- package/dist/commands/notes/contentPatchCommand.js +126 -0
- package/dist/commands/notes/descriptors.js +192 -40
- package/dist/commands/notes/export.d.ts +21 -0
- package/dist/commands/notes/export.js +224 -0
- package/dist/commands/notes/metadataMutation.d.ts +28 -0
- package/dist/commands/notes/metadataMutation.js +127 -0
- package/dist/commands/notes/repo.d.ts +20 -0
- package/dist/commands/notes/repo.js +135 -18
- package/dist/commands/notes/runtime.d.ts +3 -12
- package/dist/commands/notes/runtime.js +4 -30
- package/dist/commands/notes/searchSql.js +1 -1
- package/dist/commands/prompt/index.js +15 -45
- package/dist/commands/prompt/repo.js +2 -2
- package/dist/commands/runtime.d.ts +26 -0
- package/dist/commands/runtime.js +76 -0
- package/dist/commands/schema/renderSkills.js +20 -7
- package/dist/commands/schema/spec.d.ts +1 -2
- package/dist/commands/schema/spec.js +2 -3
- package/dist/commands/schema/types.d.ts +0 -13
- package/dist/commands/storage/index.js +30 -60
- package/dist/commands/sync.js +4 -2
- package/dist/commands/tags/content.d.ts +32 -0
- package/dist/commands/tags/content.js +243 -0
- package/dist/commands/tags/index.js +285 -49
- package/dist/commands/tags/model.d.ts +38 -0
- package/dist/commands/tags/model.js +100 -0
- package/dist/commands/tags/operations.d.ts +105 -0
- package/dist/commands/tags/operations.js +438 -0
- package/dist/commands/tags/repo.d.ts +5 -1
- package/dist/commands/tags/repo.js +142 -218
- package/dist/commands/tags/store.d.ts +28 -0
- package/dist/commands/tags/store.js +166 -0
- package/dist/commands/todo/index.js +30 -61
- package/dist/commands/writeDryRun.d.ts +25 -0
- package/dist/commands/writeDryRun.js +31 -1
- package/dist/config/resolve.js +2 -2
- package/dist/daemon/index.d.ts +2 -0
- package/dist/daemon/index.js +176 -58
- package/dist/powersync/runtime.d.ts +1 -0
- package/dist/powersync/runtime.js +10 -0
- package/dist/powersync/schema/content.d.ts +2 -0
- package/dist/powersync/schema/content.js +2 -0
- package/dist/powersync/schema/index.d.ts +2 -0
- package/dist/skills/check.d.ts +1 -1
- package/dist/skills/check.js +27 -2
- package/dist/utils/authToken.d.ts +2 -0
- package/dist/utils/authToken.js +7 -2
- package/dist/utils/noteContentEngine.d.ts +333 -0
- package/dist/utils/noteContentEngine.js +740 -0
- package/dist/utils/tiptapMarkdownSchema.js +31 -0
- package/package.json +4 -8
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { hydrateResolvedAuthIdentity } from '../auth/userInfo.js';
|
|
2
|
+
import { loadConfig } from '../config/store.js';
|
|
3
|
+
import { resolveConfig } from '../config/resolve.js';
|
|
4
|
+
import { connectPowerSync, waitForIdleDataFlow } from '../powersync/runtime.js';
|
|
5
|
+
import { syncNoteTokenIndex } from '../powersync/tokenIndex.js';
|
|
6
|
+
import { printHumanReadableLine } from '../utils/output.js';
|
|
7
|
+
import { parseSyncTimeoutMs } from '../utils/syncTimeout.js';
|
|
8
|
+
const PRE_SYNC_TIMEOUT_MS = 10_000;
|
|
9
|
+
const POST_WRITE_IDLE_TIMEOUT_MS = 5_000;
|
|
10
|
+
function isCommandExecutionContext(source) {
|
|
11
|
+
return typeof source === 'object' && source !== null && 'globals' in source;
|
|
12
|
+
}
|
|
13
|
+
function isCommanderCommand(source) {
|
|
14
|
+
return typeof source.optsWithGlobals === 'function';
|
|
15
|
+
}
|
|
16
|
+
function resolveGlobals(source) {
|
|
17
|
+
if (isCommandExecutionContext(source)) {
|
|
18
|
+
return source.globals;
|
|
19
|
+
}
|
|
20
|
+
if (isCommanderCommand(source)) {
|
|
21
|
+
return (source.optsWithGlobals?.() ?? {});
|
|
22
|
+
}
|
|
23
|
+
return source;
|
|
24
|
+
}
|
|
25
|
+
export function commandStale(runtime) {
|
|
26
|
+
return runtime.offline ? true : runtime.stale;
|
|
27
|
+
}
|
|
28
|
+
export async function withCommandRuntime(source, run) {
|
|
29
|
+
const globals = resolveGlobals(source);
|
|
30
|
+
const rawConfig = await loadConfig();
|
|
31
|
+
const baseConfig = resolveConfig(rawConfig);
|
|
32
|
+
const timeoutMs = parseSyncTimeoutMs(globals.syncTimeout) ?? baseConfig.sync.timeoutMs;
|
|
33
|
+
const offline = Boolean(globals.offline);
|
|
34
|
+
const { config } = offline
|
|
35
|
+
? { config: baseConfig }
|
|
36
|
+
: await hydrateResolvedAuthIdentity(baseConfig, { timeoutMs });
|
|
37
|
+
const { db, stale } = await connectPowerSync({ config, offline, timeoutMs });
|
|
38
|
+
try {
|
|
39
|
+
return await run({
|
|
40
|
+
db,
|
|
41
|
+
config,
|
|
42
|
+
rawConfig,
|
|
43
|
+
offline,
|
|
44
|
+
timeoutMs,
|
|
45
|
+
stale,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await db.close().catch(() => undefined);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export async function syncBeforeCommand(runtime, options = {}) {
|
|
53
|
+
if (runtime.offline) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
await waitForIdleDataFlow(runtime.db, Math.min(runtime.timeoutMs, options.timeoutMs ?? PRE_SYNC_TIMEOUT_MS));
|
|
57
|
+
if (options.syncTokenIndex) {
|
|
58
|
+
await syncNoteTokenIndex(runtime.db);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export async function waitForMutationUpload(runtime, options = {}) {
|
|
62
|
+
if (runtime.offline) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await waitForIdleDataFlow(runtime.db, Math.min(runtime.timeoutMs, options.timeoutMs ?? POST_WRITE_IDLE_TIMEOUT_MS));
|
|
66
|
+
}
|
|
67
|
+
export function printUploadDisabledWarning(runtime, message = 'warning: upload disabled (powersync.uploadBaseUrl is unset); changes are local-only for now') {
|
|
68
|
+
if (!runtime.offline && !runtime.config.powersync.uploadBaseUrl) {
|
|
69
|
+
printHumanReadableLine(message);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function printStaleCacheWarning(runtime, message = 'warning: sync timed out; local cache may be stale') {
|
|
73
|
+
if (runtime.stale && !runtime.offline) {
|
|
74
|
+
printHumanReadableLine(message);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -3,13 +3,14 @@ import path from 'node:path';
|
|
|
3
3
|
import { listCommandSchemas } from './spec.js';
|
|
4
4
|
const SECTION_ORDER = [
|
|
5
5
|
{ title: 'Auth', paths: ['auth.login', 'auth.logout', 'auth.status'] },
|
|
6
|
+
{ title: 'Daemon', paths: ['daemon.start', 'daemon.status', 'daemon.restart', 'daemon.stop'] },
|
|
6
7
|
{ title: 'Sync', paths: ['sync'] },
|
|
7
8
|
{ title: 'Schema', paths: ['schema'] },
|
|
8
9
|
{ title: 'Update CLI', paths: ['update'] },
|
|
9
|
-
{ title: 'Notes', paths: ['note.search', 'note.get', 'note.preview', 'note.detail', 'note.create', 'note.update', 'note.star', 'note.unstar', 'note.delete'] },
|
|
10
|
+
{ title: 'Notes', paths: ['note.search', 'note.get', 'note.preview', 'note.detail', 'note.export', 'note.content-read', 'note.create', 'note.update', 'note.tag', 'note.move', 'note.patch', 'note.bulk', 'note.star', 'note.unstar', 'note.delete'] },
|
|
10
11
|
{ title: 'Todo', paths: ['todo.search', 'todo.append', 'todo.create', 'todo.update'] },
|
|
11
|
-
{ title: 'Tags', paths: ['tag.list', 'tag.add'] },
|
|
12
|
-
{ title: 'Card Boxes (Zettel Boxes)', paths: ['box.list', 'box.add'] },
|
|
12
|
+
{ title: 'Tags', paths: ['tag.list', 'tag.tree', 'tag.stats', 'tag.add', 'tag.rename', 'tag.move', 'tag.merge', 'tag.suggest', 'tag.cleanup'] },
|
|
13
|
+
{ title: 'Card Boxes (Zettel Boxes)', paths: ['box.list', 'box.add', 'box.tree', 'box.stats', 'box.rename', 'box.move', 'box.merge', 'box.cleanup'] },
|
|
13
14
|
{ title: 'Prompts', paths: ['prompt.list', 'prompt.add'] },
|
|
14
15
|
{ title: 'Storage', paths: ['storage.list', 'storage.test', 'storage.upload', 'storage.stats'] },
|
|
15
16
|
{ title: 'Config', paths: ['config.get', 'config.set'] },
|
|
@@ -52,18 +53,23 @@ const GENERATED_COMMAND_SECTIONS = {
|
|
|
52
53
|
},
|
|
53
54
|
'skill:dino-manage-tags': {
|
|
54
55
|
title: 'Command Reference',
|
|
55
|
-
paths: ['tag.list', 'tag.add'],
|
|
56
|
+
paths: ['tag.list', 'tag.tree', 'tag.stats', 'tag.add', 'tag.rename', 'tag.move', 'tag.merge', 'tag.suggest', 'tag.cleanup'],
|
|
56
57
|
intro: 'Use these commands as the canonical Dinox CLI interface for tag management.',
|
|
57
58
|
notes: [
|
|
58
59
|
'For writes, run the same command with `--dry-run` first.',
|
|
60
|
+
'`tag rename` and `tag move` cascade descendant paths and note tag references inside one transaction.',
|
|
61
|
+
'`tag merge` remaps note references into the target tag and soft-deletes the source subtree.',
|
|
62
|
+
'Inline `hashtag` nodes keep `attrs.id` as `c_tag_node.id`; `attrs.label` stores the canonical path.',
|
|
59
63
|
],
|
|
60
64
|
},
|
|
61
65
|
'skill:dino-manage-boxes': {
|
|
62
66
|
title: 'Command Reference',
|
|
63
|
-
paths: ['box.list', 'box.add'],
|
|
67
|
+
paths: ['box.list', 'box.add', 'box.tree', 'box.stats', 'box.rename', 'box.move', 'box.merge', 'box.cleanup'],
|
|
64
68
|
intro: 'Use these commands as the canonical Dinox CLI interface for box management.',
|
|
65
69
|
notes: [
|
|
66
70
|
'For writes, run the same command with `--dry-run` first.',
|
|
71
|
+
'`box rename` and `box move` cascade descendant paths inside one transaction.',
|
|
72
|
+
'`box merge` remaps note references into the target box and soft-deletes the source subtree.',
|
|
67
73
|
],
|
|
68
74
|
},
|
|
69
75
|
'skill:dino-storage': {
|
|
@@ -77,11 +83,13 @@ const GENERATED_COMMAND_SECTIONS = {
|
|
|
77
83
|
},
|
|
78
84
|
'ref:dino-note:search-and-read': {
|
|
79
85
|
title: 'Command Surface',
|
|
80
|
-
paths: ['note.search', 'note.get', 'note.preview', 'note.detail'],
|
|
86
|
+
paths: ['note.search', 'note.get', 'note.preview', 'note.detail', 'note.export', 'note.content-read'],
|
|
81
87
|
intro: 'Use these generated commands as the canonical interfaces for note search and read workflows.',
|
|
82
88
|
notes: [
|
|
83
89
|
'Use `--boxes` for public box filters.',
|
|
84
90
|
'Prefer `--fields id,title,summary,tags,created_at,boxes,is_starred` when the user only needs search metadata.',
|
|
91
|
+
'Use `note export` for backup or migration; Markdown exports include frontmatter, JSON exports preserve note metadata and content JSON.',
|
|
92
|
+
'Use `note content-read` immediately before `note patch`; the returned readToken, content hash, block index, outline, and resolved hashtag paths are the required edit context.',
|
|
85
93
|
'`--sql` remains storage-oriented and still uses the field name `zettel_boxes`.',
|
|
86
94
|
],
|
|
87
95
|
},
|
|
@@ -97,10 +105,15 @@ const GENERATED_COMMAND_SECTIONS = {
|
|
|
97
105
|
},
|
|
98
106
|
'ref:dino-note:update-and-delete': {
|
|
99
107
|
title: 'Command Surface',
|
|
100
|
-
paths: ['note.update', 'note.star', 'note.unstar', 'note.delete'],
|
|
108
|
+
paths: ['note.update', 'note.tag', 'note.move', 'note.patch', 'note.bulk', 'note.star', 'note.unstar', 'note.delete'],
|
|
101
109
|
intro: 'Use these generated commands as the canonical interfaces for note mutation workflows.',
|
|
102
110
|
notes: [
|
|
103
111
|
'`--tags` and `--boxes` are full-replacement inputs.',
|
|
112
|
+
'`note update` is for explicit note ids and full metadata replacement. It is not an append command.',
|
|
113
|
+
'`note tag` and `note move` are explicit-id incremental organizers: add/remove preserves existing values, replace overwrites the whole list.',
|
|
114
|
+
'`note move` changes zettel box membership only; it does not move files or note content.',
|
|
115
|
+
'`note patch` is only for structured content edits. Run `note content-read` immediately before it, pass `--read-token` for real writes, and use `--allow-protected-replace` only after reviewing protected blocks.',
|
|
116
|
+
'`note bulk` is for filter-based batch metadata organization; it never accepts `--sql`, and real writes require `--confirm --expected-count <n>`.',
|
|
104
117
|
'Prefer `note star` / `note unstar` for pure starring changes, and `note update` when multiple fields change together.',
|
|
105
118
|
'Run the same command with `--dry-run --format json` first.',
|
|
106
119
|
],
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { CommandSchema } from './types.js';
|
|
2
|
-
export type { CommandSchema, CommandSchemaAuth,
|
|
2
|
+
export type { CommandSchema, CommandSchemaAuth, CommandSchemaOutput, CommandSchemaRisk, } from './types.js';
|
|
3
3
|
export declare const COMMAND_SCHEMAS: CommandSchema[];
|
|
4
4
|
export declare function listCommandSchemas(): CommandSchema[];
|
|
5
5
|
export declare function findCommandSchema(path: string): CommandSchema | null;
|
|
6
|
-
export declare function listMcpCommandSchemas(): CommandSchema[];
|
|
@@ -3,6 +3,7 @@ import { boxCommandGroup } from '../boxes/index.js';
|
|
|
3
3
|
import { commandSchemasFromGroupDescriptor } from '../descriptor/register.js';
|
|
4
4
|
import { standaloneCommandSchemaFromDescriptor } from '../descriptor/register.js';
|
|
5
5
|
import { configCommandGroup } from '../config/index.js';
|
|
6
|
+
import { daemonCommandGroup } from '../../daemon/index.js';
|
|
6
7
|
import { graphCommandGroup } from '../graph/index.js';
|
|
7
8
|
import { infoCommandDescriptor } from '../info/index.js';
|
|
8
9
|
import { noteCommandGroup } from '../notes/index.js';
|
|
@@ -16,6 +17,7 @@ import { updateCommandDescriptor } from '../update.js';
|
|
|
16
17
|
export const COMMAND_SCHEMAS = [
|
|
17
18
|
...commandSchemasFromGroupDescriptor(authCommandGroup),
|
|
18
19
|
...commandSchemasFromGroupDescriptor(configCommandGroup),
|
|
20
|
+
...commandSchemasFromGroupDescriptor(daemonCommandGroup),
|
|
19
21
|
standaloneCommandSchemaFromDescriptor(syncCommandDescriptor),
|
|
20
22
|
standaloneCommandSchemaFromDescriptor({ ...schemaCommandMetadata, action: async () => undefined }),
|
|
21
23
|
standaloneCommandSchemaFromDescriptor(infoCommandDescriptor),
|
|
@@ -35,6 +37,3 @@ export function listCommandSchemas() {
|
|
|
35
37
|
export function findCommandSchema(path) {
|
|
36
38
|
return COMMAND_SCHEMA_MAP.get(path) ?? null;
|
|
37
39
|
}
|
|
38
|
-
export function listMcpCommandSchemas() {
|
|
39
|
-
return COMMAND_SCHEMAS.filter((schema) => schema.mcp);
|
|
40
|
-
}
|
|
@@ -20,18 +20,6 @@ export type CommandSchemaOutput = {
|
|
|
20
20
|
fields?: string[];
|
|
21
21
|
metaFields?: string[];
|
|
22
22
|
};
|
|
23
|
-
export type CommandSchemaMcpProperty = {
|
|
24
|
-
name: string;
|
|
25
|
-
type: 'string' | 'number' | 'boolean' | 'string[]';
|
|
26
|
-
description: string;
|
|
27
|
-
required?: boolean;
|
|
28
|
-
enum?: string[];
|
|
29
|
-
};
|
|
30
|
-
export type CommandSchemaMcp = {
|
|
31
|
-
toolName: string;
|
|
32
|
-
description: string;
|
|
33
|
-
properties: CommandSchemaMcpProperty[];
|
|
34
|
-
};
|
|
35
23
|
export type CommandSchema = {
|
|
36
24
|
path: string;
|
|
37
25
|
command: string;
|
|
@@ -42,6 +30,5 @@ export type CommandSchema = {
|
|
|
42
30
|
arguments?: CommandSchemaArgument[];
|
|
43
31
|
options?: CommandSchemaOption[];
|
|
44
32
|
output: CommandSchemaOutput;
|
|
45
|
-
mcp?: CommandSchemaMcp;
|
|
46
33
|
examples: string[];
|
|
47
34
|
};
|
|
@@ -1,42 +1,20 @@
|
|
|
1
1
|
import { resolveAuthIdentity } from '../../auth/userInfo.js';
|
|
2
|
-
import { loadConfig } from '../../config/store.js';
|
|
3
|
-
import { resolveConfig } from '../../config/resolve.js';
|
|
4
|
-
import { connectPowerSync, waitForIdleDataFlow } from '../../powersync/runtime.js';
|
|
5
2
|
import { registerCommandGroup } from '../descriptor/register.js';
|
|
6
3
|
import { FORMAT_OPTIONS, OFFLINE_OPTIONS, SYNC_TIMEOUT_OPTIONS } from '../schema/globalOptions.js';
|
|
7
4
|
import { buildStorageTestDryRunPreview, buildStorageUploadDryRunPreview } from '../writeDryRun.js';
|
|
8
5
|
import { printDryRunPreview } from '../../utils/dryRun.js';
|
|
9
6
|
import { DinoxError } from '../../utils/errors.js';
|
|
10
7
|
import { getRequestedStructuredOutputFormat, printHumanReadableLine, printSuccess, } from '../../utils/output.js';
|
|
11
|
-
import {
|
|
8
|
+
import { commandStale, printStaleCacheWarning, printUploadDisabledWarning, syncBeforeCommand, waitForMutationUpload, withCommandRuntime, } from '../runtime.js';
|
|
12
9
|
import { getStorageStats, inspectStorageTest, inspectStorageUpload, listStorageConfigs, parseStorageUploadCategory, testStorageUpload, uploadFileToStorage, } from './repo.js';
|
|
13
10
|
const STORAGE_GLOBAL_OPTIONS = [...FORMAT_OPTIONS, ...OFFLINE_OPTIONS, ...SYNC_TIMEOUT_OPTIONS];
|
|
14
|
-
async function syncBeforeStorageCommand(db, offline, timeoutMs) {
|
|
15
|
-
if (offline) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
await waitForIdleDataFlow(db, Math.min(timeoutMs, 10_000));
|
|
19
|
-
}
|
|
20
|
-
async function withStorageDb(context, run) {
|
|
21
|
-
const rawConfig = await loadConfig();
|
|
22
|
-
const config = resolveConfig(rawConfig);
|
|
23
|
-
const timeoutMs = parseSyncTimeoutMs(context.globals.syncTimeout) ?? config.sync.timeoutMs;
|
|
24
|
-
const offline = Boolean(context.globals.offline);
|
|
25
|
-
const { db, stale } = await connectPowerSync({ config, offline, timeoutMs });
|
|
26
|
-
try {
|
|
27
|
-
await run({ db, config, rawConfig, offline, timeoutMs, stale });
|
|
28
|
-
}
|
|
29
|
-
finally {
|
|
30
|
-
await db.close().catch(() => undefined);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
11
|
async function runStorageList(context) {
|
|
34
|
-
await
|
|
35
|
-
const identity = await resolveAuthIdentity(
|
|
36
|
-
await
|
|
12
|
+
await withCommandRuntime(context, async (runtime) => {
|
|
13
|
+
const identity = await resolveAuthIdentity(runtime.config);
|
|
14
|
+
await syncBeforeCommand(runtime);
|
|
37
15
|
printSuccess({
|
|
38
|
-
stale:
|
|
39
|
-
...(await listStorageConfigs(db, identity.userId)),
|
|
16
|
+
stale: commandStale(runtime),
|
|
17
|
+
...(await listStorageConfigs(runtime.db, identity.userId)),
|
|
40
18
|
});
|
|
41
19
|
});
|
|
42
20
|
}
|
|
@@ -48,9 +26,10 @@ async function runStorageUpload(context) {
|
|
|
48
26
|
const options = context.options;
|
|
49
27
|
const category = parseStorageUploadCategory(options.category ?? 'files');
|
|
50
28
|
const structuredOutput = getRequestedStructuredOutputFormat() !== null;
|
|
51
|
-
await
|
|
52
|
-
const
|
|
53
|
-
await
|
|
29
|
+
await withCommandRuntime(context, async (runtime) => {
|
|
30
|
+
const { db } = runtime;
|
|
31
|
+
const identity = await resolveAuthIdentity(runtime.config);
|
|
32
|
+
await syncBeforeCommand(runtime);
|
|
54
33
|
const plan = await inspectStorageUpload(db, {
|
|
55
34
|
userId: identity.userId,
|
|
56
35
|
filePath,
|
|
@@ -60,8 +39,8 @@ async function runStorageUpload(context) {
|
|
|
60
39
|
});
|
|
61
40
|
if (options.dryRun) {
|
|
62
41
|
printDryRunPreview(buildStorageUploadDryRunPreview({
|
|
63
|
-
config,
|
|
64
|
-
offline,
|
|
42
|
+
config: runtime.config,
|
|
43
|
+
offline: runtime.offline,
|
|
65
44
|
filePath: plan.filePath,
|
|
66
45
|
fileName: plan.fileName,
|
|
67
46
|
sizeBytes: plan.sizeBytes,
|
|
@@ -80,15 +59,11 @@ async function runStorageUpload(context) {
|
|
|
80
59
|
storageId: options.storageId,
|
|
81
60
|
key: options.key,
|
|
82
61
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
if (!offline) {
|
|
87
|
-
await waitForIdleDataFlow(db, Math.min(timeoutMs, 5_000));
|
|
88
|
-
}
|
|
62
|
+
printUploadDisabledWarning(runtime, 'warning: upload disabled (powersync.uploadBaseUrl is unset); resource metadata is local-only for now');
|
|
63
|
+
await waitForMutationUpload(runtime);
|
|
89
64
|
const payload = {
|
|
90
65
|
ok: true,
|
|
91
|
-
stale:
|
|
66
|
+
stale: commandStale(runtime),
|
|
92
67
|
...result,
|
|
93
68
|
};
|
|
94
69
|
if (structuredOutput) {
|
|
@@ -104,9 +79,7 @@ async function runStorageUpload(context) {
|
|
|
104
79
|
if (result.thumbnailUrl) {
|
|
105
80
|
printHumanReadableLine(`- thumbnail: ${result.thumbnailUrl}`);
|
|
106
81
|
}
|
|
107
|
-
|
|
108
|
-
printHumanReadableLine('warning: sync timed out; local cache may be stale');
|
|
109
|
-
}
|
|
82
|
+
printStaleCacheWarning(runtime);
|
|
110
83
|
});
|
|
111
84
|
}
|
|
112
85
|
function formatBytes(bytes) {
|
|
@@ -123,17 +96,18 @@ function formatBytes(bytes) {
|
|
|
123
96
|
async function runStorageTest(context) {
|
|
124
97
|
const options = context.options;
|
|
125
98
|
const structuredOutput = getRequestedStructuredOutputFormat() !== null;
|
|
126
|
-
await
|
|
127
|
-
const
|
|
128
|
-
await
|
|
99
|
+
await withCommandRuntime(context, async (runtime) => {
|
|
100
|
+
const { db } = runtime;
|
|
101
|
+
const identity = await resolveAuthIdentity(runtime.config);
|
|
102
|
+
await syncBeforeCommand(runtime);
|
|
129
103
|
const plan = await inspectStorageTest(db, {
|
|
130
104
|
userId: identity.userId,
|
|
131
105
|
storageId: options.storageId,
|
|
132
106
|
});
|
|
133
107
|
if (options.dryRun) {
|
|
134
108
|
printDryRunPreview(buildStorageTestDryRunPreview({
|
|
135
|
-
config,
|
|
136
|
-
offline,
|
|
109
|
+
config: runtime.config,
|
|
110
|
+
offline: runtime.offline,
|
|
137
111
|
storage: plan.storage,
|
|
138
112
|
storageKey: plan.storageKey,
|
|
139
113
|
storageUrl: plan.storageUrl,
|
|
@@ -148,7 +122,7 @@ async function runStorageTest(context) {
|
|
|
148
122
|
});
|
|
149
123
|
const payload = {
|
|
150
124
|
ok: true,
|
|
151
|
-
stale:
|
|
125
|
+
stale: commandStale(runtime),
|
|
152
126
|
...result,
|
|
153
127
|
};
|
|
154
128
|
if (structuredOutput) {
|
|
@@ -162,20 +136,18 @@ async function runStorageTest(context) {
|
|
|
162
136
|
if (result.isPrivate) {
|
|
163
137
|
printHumanReadableLine('- note: the target bucket is private; direct reads may still require signed access.');
|
|
164
138
|
}
|
|
165
|
-
|
|
166
|
-
printHumanReadableLine('warning: sync timed out; local cache may be stale');
|
|
167
|
-
}
|
|
139
|
+
printStaleCacheWarning(runtime);
|
|
168
140
|
});
|
|
169
141
|
}
|
|
170
142
|
async function runStorageStats(context) {
|
|
171
143
|
const structuredOutput = getRequestedStructuredOutputFormat() !== null;
|
|
172
|
-
await
|
|
173
|
-
const identity = await resolveAuthIdentity(
|
|
174
|
-
await
|
|
175
|
-
const stats = await getStorageStats(db, identity.userId);
|
|
144
|
+
await withCommandRuntime(context, async (runtime) => {
|
|
145
|
+
const identity = await resolveAuthIdentity(runtime.config);
|
|
146
|
+
await syncBeforeCommand(runtime);
|
|
147
|
+
const stats = await getStorageStats(runtime.db, identity.userId);
|
|
176
148
|
const payload = {
|
|
177
149
|
ok: true,
|
|
178
|
-
stale:
|
|
150
|
+
stale: commandStale(runtime),
|
|
179
151
|
...stats,
|
|
180
152
|
};
|
|
181
153
|
if (structuredOutput) {
|
|
@@ -191,9 +163,7 @@ async function runStorageStats(context) {
|
|
|
191
163
|
printHumanReadableLine(`- ${entry.label}: ${entry.fileCount} files, ${formatBytes(entry.totalBytes)}`);
|
|
192
164
|
}
|
|
193
165
|
}
|
|
194
|
-
|
|
195
|
-
printHumanReadableLine('warning: sync timed out; local cache may be stale');
|
|
196
|
-
}
|
|
166
|
+
printStaleCacheWarning(runtime);
|
|
197
167
|
});
|
|
198
168
|
}
|
|
199
169
|
export const storageCommandGroup = {
|
package/dist/commands/sync.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { loadConfig } from '../config/store.js';
|
|
2
2
|
import { resolveConfig } from '../config/resolve.js';
|
|
3
|
+
import { hydrateResolvedAuthIdentity } from '../auth/userInfo.js';
|
|
3
4
|
import { registerStandaloneCommand } from './descriptor/register.js';
|
|
4
5
|
import { FORMAT_OPTIONS, SYNC_TIMEOUT_OPTIONS } from './schema/globalOptions.js';
|
|
5
6
|
import { getRequestedStructuredOutputFormat, printHumanReadableLine, printSuccess, } from '../utils/output.js';
|
|
@@ -22,9 +23,10 @@ export const syncCommandDescriptor = {
|
|
|
22
23
|
examples: ['dino sync --format json', 'dino sync --sync-timeout 600000 --format json'],
|
|
23
24
|
},
|
|
24
25
|
action: async (context) => {
|
|
25
|
-
const
|
|
26
|
+
const baseConfig = resolveConfig(await loadConfig());
|
|
26
27
|
const structuredOutput = getRequestedStructuredOutputFormat() !== null;
|
|
27
|
-
const timeoutMs = parseSyncTimeoutMs(context.globals.syncTimeout) ??
|
|
28
|
+
const timeoutMs = parseSyncTimeoutMs(context.globals.syncTimeout) ?? baseConfig.sync.timeoutMs;
|
|
29
|
+
const { config } = await hydrateResolvedAuthIdentity(baseConfig, { timeoutMs });
|
|
28
30
|
const { db, dbPath, stale } = await connectPowerSync({
|
|
29
31
|
config,
|
|
30
32
|
offline: false,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type NoteTagContentUpdate = {
|
|
2
|
+
tagsChanged: boolean;
|
|
3
|
+
contentJsonChanged: boolean;
|
|
4
|
+
contentMdChanged: boolean;
|
|
5
|
+
contentTextChanged: boolean;
|
|
6
|
+
tags: string[];
|
|
7
|
+
contentJson: string | null;
|
|
8
|
+
contentMd: string | null;
|
|
9
|
+
contentText: string | null;
|
|
10
|
+
};
|
|
11
|
+
export type TagReferenceLookup = {
|
|
12
|
+
idByPath: ReadonlyMap<string, string>;
|
|
13
|
+
pathById: ReadonlyMap<string, string>;
|
|
14
|
+
};
|
|
15
|
+
export declare function renameTagReferencesInNote(args: {
|
|
16
|
+
tags: string[];
|
|
17
|
+
contentJson: string | null;
|
|
18
|
+
contentMd: string | null;
|
|
19
|
+
contentText: string | null;
|
|
20
|
+
oldPrefix: string;
|
|
21
|
+
newPrefix: string;
|
|
22
|
+
lookup?: TagReferenceLookup;
|
|
23
|
+
}): NoteTagContentUpdate;
|
|
24
|
+
export declare function mergeTagReferencesInNote(args: {
|
|
25
|
+
tags: string[];
|
|
26
|
+
contentJson: string | null;
|
|
27
|
+
contentMd: string | null;
|
|
28
|
+
contentText: string | null;
|
|
29
|
+
oldPrefix: string;
|
|
30
|
+
newPrefix: string;
|
|
31
|
+
lookup?: TagReferenceLookup;
|
|
32
|
+
}): NoteTagContentUpdate;
|