@dinoxx/dinox-cli 1.0.22 → 1.1.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.
Files changed (144) hide show
  1. package/README.md +29 -9
  2. package/dist/auth/userInfo.d.ts +2 -0
  3. package/dist/auth/userInfo.js +55 -14
  4. package/dist/cli.js +36 -2
  5. package/dist/commands/auth/index.d.ts +35 -0
  6. package/dist/commands/auth/index.js +382 -83
  7. package/dist/commands/boxes/index.js +2 -6
  8. package/dist/commands/boxes/model.d.ts +3 -0
  9. package/dist/commands/boxes/model.js +16 -1
  10. package/dist/commands/boxes/operations.js +18 -8
  11. package/dist/commands/boxes/repo.js +13 -11
  12. package/dist/commands/boxes/store.js +1 -1
  13. package/dist/commands/config/index.js +7 -5
  14. package/dist/commands/descriptor/register.js +9 -0
  15. package/dist/commands/doctor.d.ts +123 -0
  16. package/dist/commands/doctor.js +539 -0
  17. package/dist/commands/graph/index.d.ts +1 -1
  18. package/dist/commands/graph/index.js +35 -21
  19. package/dist/commands/graph/repo.js +92 -17
  20. package/dist/commands/meta/index.js +4 -4
  21. package/dist/commands/meta/repo.js +4 -3
  22. package/dist/commands/notes/actions.d.ts +1 -1
  23. package/dist/commands/notes/actions.js +121 -78
  24. package/dist/commands/notes/bulk.d.ts +1 -0
  25. package/dist/commands/notes/bulk.js +23 -17
  26. package/dist/commands/notes/contentEngine.js +69 -11
  27. package/dist/commands/notes/contentPatch.d.ts +4 -1
  28. package/dist/commands/notes/contentPatch.js +105 -41
  29. package/dist/commands/notes/contentPatchCommand.js +28 -11
  30. package/dist/commands/notes/descriptors.js +50 -20
  31. package/dist/commands/notes/dryRun.d.ts +1 -0
  32. package/dist/commands/notes/dryRun.js +4 -7
  33. package/dist/commands/notes/export.d.ts +6 -0
  34. package/dist/commands/notes/export.js +26 -6
  35. package/dist/commands/notes/metadataMutation.d.ts +1 -0
  36. package/dist/commands/notes/metadataMutation.js +14 -3
  37. package/dist/commands/notes/repo.d.ts +46 -4
  38. package/dist/commands/notes/repo.js +113 -28
  39. package/dist/commands/notes/runtime.d.ts +2 -1
  40. package/dist/commands/notes/runtime.js +17 -1
  41. package/dist/commands/notes/searchSql.js +13 -6
  42. package/dist/commands/notes/writeReceipt.d.ts +20 -0
  43. package/dist/commands/notes/writeReceipt.js +82 -0
  44. package/dist/commands/prompt/index.js +3 -3
  45. package/dist/commands/prompt/repo.d.ts +4 -1
  46. package/dist/commands/prompt/repo.js +17 -7
  47. package/dist/commands/runtime.d.ts +14 -2
  48. package/dist/commands/runtime.js +74 -15
  49. package/dist/commands/schema/renderSkills.js +5 -2
  50. package/dist/commands/schema/spec.js +4 -0
  51. package/dist/commands/storage/index.js +8 -2
  52. package/dist/commands/storage/repo.d.ts +4 -0
  53. package/dist/commands/storage/repo.js +356 -92
  54. package/dist/commands/sync.js +16 -12
  55. package/dist/commands/tags/content.js +9 -0
  56. package/dist/commands/tags/index.js +2 -6
  57. package/dist/commands/tags/operations.js +15 -10
  58. package/dist/commands/tags/repo.d.ts +2 -0
  59. package/dist/commands/tags/repo.js +18 -5
  60. package/dist/commands/tags/store.js +1 -1
  61. package/dist/commands/todo/contentModel.d.ts +4 -3
  62. package/dist/commands/todo/contentModel.js +78 -28
  63. package/dist/commands/todo/dryRun.d.ts +1 -0
  64. package/dist/commands/todo/dryRun.js +17 -13
  65. package/dist/commands/todo/index.d.ts +6 -0
  66. package/dist/commands/todo/index.js +89 -123
  67. package/dist/commands/todo/repo.d.ts +36 -1
  68. package/dist/commands/todo/repo.js +146 -37
  69. package/dist/commands/todo/taskIdentity.d.ts +2 -0
  70. package/dist/commands/todo/taskIdentity.js +64 -0
  71. package/dist/commands/todo/taskModel.js +27 -17
  72. package/dist/commands/update.d.ts +13 -1
  73. package/dist/commands/update.js +135 -23
  74. package/dist/commands/writeDryRun.d.ts +3 -2
  75. package/dist/commands/writeDryRun.js +4 -3
  76. package/dist/commands/writeDurability.d.ts +5 -0
  77. package/dist/commands/writeDurability.js +22 -0
  78. package/dist/config/paths.js +6 -1
  79. package/dist/config/resolve.d.ts +2 -0
  80. package/dist/config/resolve.js +23 -9
  81. package/dist/config/store.d.ts +3 -0
  82. package/dist/config/store.js +61 -14
  83. package/dist/config/types.d.ts +4 -0
  84. package/dist/daemon/client.d.ts +26 -1
  85. package/dist/daemon/client.js +236 -12
  86. package/dist/daemon/ensure.js +74 -12
  87. package/dist/daemon/index.d.ts +42 -0
  88. package/dist/daemon/index.js +202 -52
  89. package/dist/daemon/lifecycle.d.ts +42 -0
  90. package/dist/daemon/lifecycle.js +115 -0
  91. package/dist/daemon/pid.d.ts +19 -6
  92. package/dist/daemon/pid.js +147 -13
  93. package/dist/daemon/route.d.ts +14 -0
  94. package/dist/daemon/route.js +40 -0
  95. package/dist/daemon/server.d.ts +11 -0
  96. package/dist/daemon/server.js +201 -50
  97. package/dist/daemon/types.d.ts +29 -1
  98. package/dist/daemon/types.js +1 -0
  99. package/dist/dinox.js +25 -1
  100. package/dist/powersync/connector.js +31 -16
  101. package/dist/powersync/exclusiveRuntime.d.ts +19 -0
  102. package/dist/powersync/exclusiveRuntime.js +42 -0
  103. package/dist/powersync/runtime.d.ts +24 -4
  104. package/dist/powersync/runtime.js +234 -36
  105. package/dist/powersync/syncGate.d.ts +3 -1
  106. package/dist/powersync/syncGate.js +7 -1
  107. package/dist/powersync/tokenIndex.d.ts +11 -0
  108. package/dist/powersync/tokenIndex.js +159 -22
  109. package/dist/powersync/uploader.js +107 -52
  110. package/dist/utils/abort.js +0 -4
  111. package/dist/utils/asyncRelease.d.ts +2 -0
  112. package/dist/utils/asyncRelease.js +25 -0
  113. package/dist/utils/bidlinkCanonicalization.js +3 -0
  114. package/dist/utils/dryRun.d.ts +1 -1
  115. package/dist/utils/errors.d.ts +15 -1
  116. package/dist/utils/errors.js +223 -5
  117. package/dist/utils/output.d.ts +1 -0
  118. package/dist/utils/output.js +51 -15
  119. package/dist/utils/redact.js +1 -1
  120. package/dist/utils/sqliteLease.d.ts +8 -0
  121. package/dist/utils/sqliteLease.js +59 -0
  122. package/dist/utils/syncTimeout.d.ts +7 -1
  123. package/dist/utils/syncTimeout.js +8 -7
  124. package/dist/utils/terminalSanitization.js +6 -2
  125. package/dist/utils/tiptapMarkdown.js +49 -3
  126. package/dist/utils/tiptapMarkdownSyntax.d.ts +9 -0
  127. package/dist/utils/tiptapMarkdownSyntax.js +249 -0
  128. package/dist/utils/tokenize.js +24 -2
  129. package/dist/utils/updateNotice.js +60 -12
  130. package/package.json +12 -10
  131. package/dist/commands/mcp/auth.d.ts +0 -4
  132. package/dist/commands/mcp/auth.js +0 -75
  133. package/dist/commands/mcp/index.d.ts +0 -2
  134. package/dist/commands/mcp/index.js +0 -86
  135. package/dist/commands/mcp/noteContentTools.d.ts +0 -222
  136. package/dist/commands/mcp/noteContentTools.js +0 -390
  137. package/dist/commands/mcp/server.d.ts +0 -34
  138. package/dist/commands/mcp/server.js +0 -424
  139. package/dist/commands/mcp/tools.d.ts +0 -2
  140. package/dist/commands/mcp/tools.js +0 -32
  141. package/dist/commands/mcp/types.d.ts +0 -39
  142. package/dist/commands/mcp/types.js +0 -1
  143. package/dist/utils/noteContentEngine.d.ts +0 -333
  144. package/dist/utils/noteContentEngine.js +0 -740
@@ -1,18 +1,18 @@
1
1
  import { withPowerSyncWriteTransaction } from '../../powersync/runtime.js';
2
2
  import { DinoxError } from '../../utils/errors.js';
3
3
  import { nowIsoUtc } from '../../utils/time.js';
4
- import { MAX_BOX_NAME_LENGTH, MAX_BOX_PATH_LENGTH, REQUIRED_NOTE_BOX_COLUMNS, assertMaxLength, canonicalizeBoxPath, getLeafName, normalizeBoxLookupKey, parseStoredBoxIds, trimString, } from './model.js';
4
+ import { MAX_BOX_NAME_LENGTH, REQUIRED_NOTE_BOX_COLUMNS, assertBoxPathLimits, assertTextLimits, canonicalizeBoxPath, getLeafName, normalizeBoxLookupKey, parseStoredBoxIds, trimString, } from './model.js';
5
5
  import { activeBoxNodes, activeNodeByPath, assertCanWriteBox, assertRequiredColumns, assertWritableBoxNodes, descendantsOf, ensureNoPathConflict, getTableColumns, isActiveBoxNode, isDescendantBoxPath, loadAllBoxNodes, requireActivePath, toBoxListItem, } from './store.js';
6
6
  function buildSubtreeChanges(args) {
7
7
  const newRootPath = canonicalizeBoxPath(args.newRootPath);
8
8
  if (!newRootPath) {
9
9
  throw new DinoxError('Target box path is required');
10
10
  }
11
- assertMaxLength('Box path', newRootPath, MAX_BOX_PATH_LENGTH);
12
11
  const rootPrefix = `${args.root.path}/`;
13
12
  return descendantsOf(args.nodes, args.root).map((node) => {
14
13
  const suffix = node.id === args.root.id ? '' : node.path.slice(rootPrefix.length);
15
14
  const toPath = suffix ? `${newRootPath}/${suffix}` : newRootPath;
15
+ assertBoxPathLimits(toPath, 'Target box path');
16
16
  return {
17
17
  id: node.id,
18
18
  fromPath: node.path,
@@ -53,7 +53,8 @@ async function applySubtreePathChanges(args) {
53
53
  UPDATE c_zettel_box
54
54
  SET name = ?, path = ?, parent_id = ?, updated_at = ?
55
55
  WHERE id = ?
56
- `, [getLeafName(change.toPath), change.toPath, parentId, args.timestamp, change.id]);
56
+ AND TRIM(COALESCE(user_no, '')) = ?
57
+ `, [getLeafName(change.toPath), change.toPath, parentId, args.timestamp, change.id, args.userId]);
57
58
  }
58
59
  }
59
60
  function parseRenameInput(input) {
@@ -66,7 +67,8 @@ function parseRenameInput(input) {
66
67
  if (!newName || newName.includes('/')) {
67
68
  throw new DinoxError('New box name must be a single path segment');
68
69
  }
69
- assertMaxLength('Box name', newName, MAX_BOX_NAME_LENGTH);
70
+ assertBoxPathLimits(path);
71
+ assertTextLimits('Box name', newName, MAX_BOX_NAME_LENGTH);
70
72
  return { path, newName, userId };
71
73
  }
72
74
  function parseMoveInput(input) {
@@ -79,6 +81,8 @@ function parseMoveInput(input) {
79
81
  if (!to) {
80
82
  throw new DinoxError('Target parent path is required');
81
83
  }
84
+ assertBoxPathLimits(path);
85
+ assertBoxPathLimits(to, 'Target parent path');
82
86
  return { path, to, userId };
83
87
  }
84
88
  function parseMergeInput(input) {
@@ -91,6 +95,8 @@ function parseMergeInput(input) {
91
95
  if (!to) {
92
96
  throw new DinoxError('Target box path is required');
93
97
  }
98
+ assertBoxPathLimits(from, 'Source box path');
99
+ assertBoxPathLimits(to, 'Target box path');
94
100
  return { from, to, userId };
95
101
  }
96
102
  export async function getBoxTree(db, input = {}) {
@@ -127,13 +133,13 @@ async function loadNoteBoxRows(db, userId) {
127
133
  FROM c_note
128
134
  WHERE TRIM(COALESCE(id, '')) <> ''
129
135
  AND (is_del IS NULL OR is_del = 0)
130
- AND (TRIM(COALESCE(user_no, '')) = ? OR TRIM(COALESCE(user_no, '')) = '')
136
+ AND TRIM(COALESCE(user_no, '')) = ?
131
137
  `, [userId]);
132
138
  }
133
139
  async function loadNoteBoxStats(db, userId) {
134
140
  const normalizedUserId = trimString(userId);
135
141
  const userFilter = normalizedUserId
136
- ? `AND (TRIM(COALESCE(n.user_no, '')) = ? OR TRIM(COALESCE(n.user_no, '')) = '')`
142
+ ? `AND TRIM(COALESCE(n.user_no, '')) = ?`
137
143
  : '';
138
144
  const rows = await db.getAll(`
139
145
  SELECT
@@ -299,6 +305,7 @@ export async function renameBox(db, input, options = {}) {
299
305
  nodes,
300
306
  changes,
301
307
  newRootParentId: root.parentId,
308
+ userId: parsed.userId,
302
309
  timestamp: nowIsoUtc(),
303
310
  });
304
311
  });
@@ -331,6 +338,7 @@ export async function moveBox(db, input, options = {}) {
331
338
  nodes,
332
339
  changes,
333
340
  newRootParentId: targetParent.id,
341
+ userId: parsed.userId,
334
342
  timestamp: nowIsoUtc(),
335
343
  });
336
344
  });
@@ -393,14 +401,16 @@ export async function mergeBox(db, input, options = {}) {
393
401
  UPDATE c_note
394
402
  SET zettel_boxes = ?, updated_at = ?, version = COALESCE(version, 0) + 1
395
403
  WHERE id = ?
396
- `, [JSON.stringify(note.after), timestamp, note.id]);
404
+ AND TRIM(COALESCE(user_no, '')) = ?
405
+ `, [JSON.stringify(note.after), timestamp, note.id, parsed.userId]);
397
406
  }
398
407
  for (const boxId of softDeletedBoxIds) {
399
408
  await tx.execute(`
400
409
  UPDATE c_zettel_box
401
410
  SET is_del = 1, updated_at = ?
402
411
  WHERE id = ?
403
- `, [timestamp, boxId]);
412
+ AND TRIM(COALESCE(user_no, '')) = ?
413
+ `, [timestamp, boxId, parsed.userId]);
404
414
  }
405
415
  });
406
416
  }
@@ -1,7 +1,7 @@
1
1
  import { generateId } from '../../utils/id.js';
2
2
  import { DinoxError } from '../../utils/errors.js';
3
3
  import { withPowerSyncWriteTransaction } from '../../powersync/runtime.js';
4
- import { MAX_BOX_COLOR_LENGTH, MAX_BOX_DESCRIPTION_LENGTH, MAX_BOX_NAME_LENGTH, MAX_BOX_PATH_LENGTH, assertMaxLength, canonicalizeBoxPath, getLeafName, normalizeBoxLookupKey, toNullableId, trimString, } from './model.js';
4
+ import { MAX_BOX_COLOR_LENGTH, MAX_BOX_DESCRIPTION_LENGTH, MAX_BOX_NAME_LENGTH, assertBoxPathLimits, assertTextLimits, canonicalizeBoxPath, getLeafName, normalizeBoxLookupKey, toNullableId, trimString, } from './model.js';
5
5
  import { assertCanWriteBox, getTableColumns } from './store.js';
6
6
  export { canonicalizeBoxPath } from './model.js';
7
7
  function normalizeLookupKey(value) {
@@ -16,10 +16,10 @@ function parseAddBoxInput(input) {
16
16
  const name = getLeafName(path);
17
17
  const description = trimString(input.description);
18
18
  const color = trimString(input.color);
19
- assertMaxLength('Box name', name, MAX_BOX_NAME_LENGTH);
20
- assertMaxLength('Box path', path, MAX_BOX_PATH_LENGTH);
21
- assertMaxLength('Box description', description, MAX_BOX_DESCRIPTION_LENGTH);
22
- assertMaxLength('Box color', color, MAX_BOX_COLOR_LENGTH);
19
+ assertBoxPathLimits(path);
20
+ assertTextLimits('Box name', name, MAX_BOX_NAME_LENGTH);
21
+ assertTextLimits('Box description', description, MAX_BOX_DESCRIPTION_LENGTH);
22
+ assertTextLimits('Box color', color, MAX_BOX_COLOR_LENGTH);
23
23
  return {
24
24
  userId,
25
25
  path,
@@ -28,7 +28,7 @@ function parseAddBoxInput(input) {
28
28
  color,
29
29
  };
30
30
  }
31
- async function loadBoxNodesByPath(db) {
31
+ async function loadBoxNodesByPath(db, userId) {
32
32
  const rows = await db.getAll(`
33
33
  SELECT
34
34
  TRIM(COALESCE(id, '')) AS id,
@@ -41,12 +41,13 @@ async function loadBoxNodesByPath(db) {
41
41
  TRIM(COALESCE(user_no, '')) AS user_no
42
42
  FROM c_zettel_box
43
43
  WHERE TRIM(COALESCE(id, '')) <> ''
44
+ AND TRIM(COALESCE(user_no, '')) = ?
44
45
  ORDER BY
45
46
  CASE WHEN is_del IS NULL OR is_del = 0 THEN 0 ELSE 1 END ASC,
46
47
  updated_at DESC,
47
48
  created_at DESC,
48
49
  id DESC
49
- `, []);
50
+ `, [userId]);
50
51
  const nodesByPath = new Map();
51
52
  for (const row of rows) {
52
53
  const id = trimString(row.id);
@@ -77,7 +78,7 @@ async function loadBoxNodesByPath(db) {
77
78
  export async function listBoxes(db, input = {}) {
78
79
  const userId = trimString(input.userId);
79
80
  const userFilter = userId
80
- ? `AND (TRIM(COALESCE(user_no, '')) = ? OR TRIM(COALESCE(user_no, '')) = '')`
81
+ ? `AND TRIM(COALESCE(user_no, '')) = ?`
81
82
  : '';
82
83
  const rows = await db.getAll(`
83
84
  SELECT DISTINCT
@@ -158,7 +159,8 @@ async function restoreOrUpdateExistingBox(args) {
158
159
  UPDATE c_zettel_box
159
160
  SET ${assignments.join(', ')}
160
161
  WHERE id = ?
161
- `, params);
162
+ AND TRIM(COALESCE(user_no, '')) = ?
163
+ `, [...params, userId]);
162
164
  return wasDeleted;
163
165
  }
164
166
  async function insertBoxNode(args) {
@@ -186,7 +188,7 @@ export async function addBox(db, input) {
186
188
  const parsed = parseAddBoxInput(input);
187
189
  const columnNames = await getTableColumns(db, 'c_zettel_box');
188
190
  assertCanWriteBox(columnNames, parsed.userId, 'insert');
189
- const nodesByPath = await loadBoxNodesByPath(db);
191
+ const nodesByPath = await loadBoxNodesByPath(db, parsed.userId);
190
192
  const existingLeaf = nodesByPath.get(normalizeLookupKey(parsed.path));
191
193
  if (existingLeaf && existingLeaf.isDel !== 1) {
192
194
  throw buildBoxExistsError(parsed.path, [existingLeaf.id]);
@@ -286,7 +288,7 @@ export async function inspectAddBox(db, input) {
286
288
  const parsed = parseAddBoxInput(input);
287
289
  const columnNames = await getTableColumns(db, 'c_zettel_box');
288
290
  assertCanWriteBox(columnNames, parsed.userId, 'insert');
289
- const nodesByPath = await loadBoxNodesByPath(db);
291
+ const nodesByPath = await loadBoxNodesByPath(db, parsed.userId);
290
292
  const existingLeaf = nodesByPath.get(normalizeLookupKey(parsed.path));
291
293
  if (existingLeaf && existingLeaf.isDel !== 1) {
292
294
  throw buildBoxExistsError(parsed.path, [existingLeaf.id]);
@@ -20,7 +20,7 @@ export function assertCanWriteBox(columnNames, userId, action) {
20
20
  export async function loadAllBoxNodes(db, options = {}) {
21
21
  const userId = trimString(options.userId);
22
22
  const userFilter = userId
23
- ? `AND (TRIM(COALESCE(user_no, '')) = ? OR TRIM(COALESCE(user_no, '')) = '')`
23
+ ? `AND TRIM(COALESCE(user_no, '')) = ?`
24
24
  : '';
25
25
  const rows = await db.getAll(`
26
26
  SELECT
@@ -5,6 +5,7 @@ import { FORMAT_OPTIONS } from '../schema/globalOptions.js';
5
5
  import { DinoxError } from '../../utils/errors.js';
6
6
  import { getRequestedStructuredOutputFormat, printSuccess } from '../../utils/output.js';
7
7
  import { redactAuthorization } from '../../utils/redact.js';
8
+ import { MAX_SYNC_TIMEOUT_MS, parseSyncTimeoutMs } from '../../utils/syncTimeout.js';
8
9
  export function sanitizeConfigForDisplay(config) {
9
10
  if (!config || typeof config !== 'object' || Array.isArray(config)) {
10
11
  return config;
@@ -13,6 +14,7 @@ export function sanitizeConfigForDisplay(config) {
13
14
  const auth = clone?.auth;
14
15
  if (auth && typeof auth === 'object') {
15
16
  auth.authorization = redactAuthorization(auth.authorization);
17
+ delete auth.stateRevision;
16
18
  }
17
19
  delete clone.powersync;
18
20
  return clone;
@@ -38,13 +40,13 @@ async function runConfigSet(context) {
38
40
  throw new DinoxError(`Unknown config key: ${key}`);
39
41
  }
40
42
  if (key === 'sync.timeoutMs') {
41
- const parsed = Number(value);
42
- if (!Number.isFinite(parsed) || parsed <= 0) {
43
- throw new DinoxError('sync.timeoutMs must be a positive integer');
43
+ const parsed = parseSyncTimeoutMs(value, { label: 'sync.timeoutMs' });
44
+ if (parsed === undefined) {
45
+ throw new DinoxError(`sync.timeoutMs must be a positive integer no greater than ${MAX_SYNC_TIMEOUT_MS}`);
44
46
  }
45
- await setConfigValue(key, Math.trunc(parsed));
47
+ await setConfigValue(key, parsed);
46
48
  if (getRequestedStructuredOutputFormat()) {
47
- printSuccess({ ok: true, key, value: Math.trunc(parsed) });
49
+ printSuccess({ ok: true, key, value: parsed });
48
50
  }
49
51
  return;
50
52
  }
@@ -1,3 +1,5 @@
1
+ import { DinoxError } from '../../utils/errors.js';
2
+ import { getRequestedStructuredOutputFormat } from '../../utils/output.js';
1
3
  import { toSchemaArgument, toSchemaOption } from './types.js';
2
4
  function deriveArgumentKey(syntax) {
3
5
  const normalized = syntax.trim().replace(/^[<[.]+|[>\].]+$/g, '');
@@ -64,6 +66,13 @@ export function registerCommandGroup(program, group) {
64
66
  });
65
67
  }
66
68
  parent.action((_options, command) => {
69
+ if (getRequestedStructuredOutputFormat()) {
70
+ throw new DinoxError(`Missing subcommand for \`dino ${group.name}\``, {
71
+ code: 'USAGE_ERROR',
72
+ suggestion: `Run \`dino ${group.name} --help\` to list available subcommands.`,
73
+ recoverable: true,
74
+ });
75
+ }
67
76
  command.outputHelp();
68
77
  });
69
78
  return parent;
@@ -0,0 +1,123 @@
1
+ import { Command } from 'commander';
2
+ import { hydrateResolvedAuthIdentity } from '../auth/userInfo.js';
3
+ import { loadConfig } from '../config/store.js';
4
+ import { resolveConfig } from '../config/resolve.js';
5
+ import type { ResolvedDinoxConfig } from '../config/types.js';
6
+ import { shutdownDaemonForExclusiveAccess } from '../daemon/client.js';
7
+ import { restartDaemonLocked } from '../daemon/index.js';
8
+ import { acquireDaemonStartLock } from '../daemon/pid.js';
9
+ import type { DaemonPidInfo } from '../daemon/pid.js';
10
+ import { type DaemonPingResult } from '../daemon/types.js';
11
+ import { connectPowerSync } from '../powersync/runtime.js';
12
+ import { type NoteTokenIndexInspection } from '../powersync/tokenIndex.js';
13
+ import type { CommandDescriptor, CommandExecutionContext } from './descriptor/types.js';
14
+ type HealthStatus = 'ok' | 'warn' | 'error' | 'skipped';
15
+ type DoctorFix = {
16
+ target: 'index' | 'upload_queue' | 'daemon';
17
+ status: HealthStatus;
18
+ message: string;
19
+ };
20
+ type DoctorPayload = {
21
+ ok: true;
22
+ healthy: boolean;
23
+ fixed: boolean;
24
+ auth: {
25
+ status: HealthStatus;
26
+ logged_in: boolean;
27
+ verified: boolean;
28
+ user_id: string | null;
29
+ username: string | null;
30
+ email: string | null;
31
+ error?: string;
32
+ };
33
+ sync: {
34
+ status: HealthStatus;
35
+ connected: boolean;
36
+ connecting: boolean;
37
+ has_synced: boolean;
38
+ last_synced_at: string | null;
39
+ upload_queue: number | null;
40
+ downloading: boolean;
41
+ uploading: boolean;
42
+ download_error?: {
43
+ name: string;
44
+ message: string;
45
+ };
46
+ upload_error?: {
47
+ name: string;
48
+ message: string;
49
+ };
50
+ error?: string;
51
+ };
52
+ index: NoteTokenIndexInspection & {
53
+ status: HealthStatus;
54
+ };
55
+ daemon: {
56
+ status: HealthStatus;
57
+ running: boolean;
58
+ pid: number | null;
59
+ port: number | null;
60
+ transport: 'socket';
61
+ socket_path: string | null;
62
+ version: string | null;
63
+ user_id: string | null;
64
+ authenticated: boolean | null;
65
+ version_match: boolean | null;
66
+ account_match: boolean | null;
67
+ token_match: boolean | null;
68
+ runtime_config_match: boolean | null;
69
+ error?: string;
70
+ };
71
+ db: {
72
+ status: HealthStatus;
73
+ path: string;
74
+ integrity: 'ok' | 'error' | 'unknown';
75
+ message?: string;
76
+ };
77
+ fixes: DoctorFix[];
78
+ issues: string[];
79
+ };
80
+ type DoctorRuntime = {
81
+ db: Awaited<ReturnType<typeof connectPowerSync>>['db'];
82
+ dbPath: string;
83
+ config: ResolvedDinoxConfig;
84
+ authError: string | null;
85
+ syncError: string | null;
86
+ offline: boolean;
87
+ timeoutMs: number;
88
+ releaseOwner: () => Promise<void>;
89
+ daemonBefore: DoctorDaemonSnapshot;
90
+ daemonWasStopped: boolean;
91
+ releaseDaemonStartLock: () => Promise<void>;
92
+ daemonStartLockReleased: boolean;
93
+ released: boolean;
94
+ };
95
+ type DoctorDaemonSnapshot = {
96
+ info: DaemonPingResult | null;
97
+ pidInfo: DaemonPidInfo | null;
98
+ socketExists: boolean;
99
+ };
100
+ type DoctorPreparationDependencies = {
101
+ loadConfig: typeof loadConfig;
102
+ resolveConfig: typeof resolveConfig;
103
+ hydrateAuthIdentity: typeof hydrateResolvedAuthIdentity;
104
+ acquireDaemonStartLock: typeof acquireDaemonStartLock;
105
+ captureDaemonSnapshot: typeof captureDaemonSnapshot;
106
+ shutdownDaemon: typeof shutdownDaemonForExclusiveAccess;
107
+ connectPowerSync: typeof connectPowerSync;
108
+ restartDaemon: typeof restartDaemonLocked;
109
+ };
110
+ export declare function prepareDoctorRuntime(context: CommandExecutionContext, overrides?: Partial<DoctorPreparationDependencies>): Promise<DoctorRuntime>;
111
+ declare function captureDaemonSnapshot(): Promise<DoctorDaemonSnapshot>;
112
+ export declare function applyDatabaseFixes(runtime: DoctorRuntime, payload: DoctorPayload): Promise<void>;
113
+ export declare function releaseDoctorRuntime(runtime: DoctorRuntime): Promise<void>;
114
+ export declare function releaseDoctorDaemonStartLock(runtime: DoctorRuntime): Promise<void>;
115
+ type DoctorDaemonDependencies = {
116
+ restart: typeof restartDaemonLocked;
117
+ capture: typeof captureDaemonSnapshot;
118
+ };
119
+ export declare function applyDoctorDaemonLifecycle(runtime: DoctorRuntime, payload: DoctorPayload, fixRequested: boolean, dependencies?: DoctorDaemonDependencies): Promise<void>;
120
+ export declare function finalizeDoctorPayload(payload: DoctorPayload): DoctorPayload;
121
+ export declare const doctorCommandDescriptor: CommandDescriptor;
122
+ export declare function registerDoctorCommand(program: Command): void;
123
+ export {};