syncorejs 0.2.2 → 0.2.3

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 (140) hide show
  1. package/dist/_vendor/cli/app.d.mts.map +1 -1
  2. package/dist/_vendor/cli/app.mjs +8 -5
  3. package/dist/_vendor/cli/app.mjs.map +1 -1
  4. package/dist/_vendor/cli/context.mjs.map +1 -1
  5. package/dist/_vendor/cli/dev-session.mjs.map +1 -1
  6. package/dist/_vendor/cli/doctor.mjs.map +1 -1
  7. package/dist/_vendor/cli/errors.mjs.map +1 -1
  8. package/dist/_vendor/cli/help.mjs.map +1 -1
  9. package/dist/_vendor/cli/index.mjs +9 -2
  10. package/dist/_vendor/cli/index.mjs.map +1 -1
  11. package/dist/_vendor/cli/messages.mjs.map +1 -1
  12. package/dist/_vendor/cli/preflight.mjs.map +1 -1
  13. package/dist/_vendor/cli/project.mjs +20 -20
  14. package/dist/_vendor/cli/project.mjs.map +1 -1
  15. package/dist/_vendor/cli/render.mjs.map +1 -1
  16. package/dist/_vendor/cli/targets.mjs.map +1 -1
  17. package/dist/_vendor/core/cli.d.mts +8 -2
  18. package/dist/_vendor/core/cli.d.mts.map +1 -1
  19. package/dist/_vendor/core/cli.mjs +238 -64
  20. package/dist/_vendor/core/cli.mjs.map +1 -1
  21. package/dist/_vendor/core/devtools-auth.mjs.map +1 -1
  22. package/dist/_vendor/core/runtime/components.d.mts.map +1 -1
  23. package/dist/_vendor/core/runtime/components.mjs.map +1 -1
  24. package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
  25. package/dist/_vendor/core/runtime/devtools.mjs +130 -23
  26. package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
  27. package/dist/_vendor/core/runtime/functions.d.mts +388 -6
  28. package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
  29. package/dist/_vendor/core/runtime/functions.mjs +72 -1
  30. package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
  31. package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
  32. package/dist/_vendor/core/runtime/id.mjs.map +1 -1
  33. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +11 -5
  34. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
  35. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +123 -20
  36. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
  37. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +56 -8
  38. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
  39. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +49 -14
  40. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -1
  41. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +4 -7
  42. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -1
  43. package/dist/_vendor/core/runtime/internal/engines/shared.mjs +76 -1
  44. package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
  45. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +1 -0
  46. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
  47. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +4 -3
  48. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
  49. package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -1
  50. package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -1
  51. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +4 -0
  52. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -1
  53. package/dist/_vendor/core/runtime/runtime.d.mts +1040 -9
  54. package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
  55. package/dist/_vendor/core/runtime/runtime.mjs +63 -0
  56. package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
  57. package/dist/_vendor/core/transport.d.mts +2 -0
  58. package/dist/_vendor/core/transport.d.mts.map +1 -1
  59. package/dist/_vendor/core/transport.mjs +33 -24
  60. package/dist/_vendor/core/transport.mjs.map +1 -1
  61. package/dist/_vendor/devtools-protocol/index.d.ts +149 -4
  62. package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
  63. package/dist/_vendor/devtools-protocol/index.js.map +1 -1
  64. package/dist/_vendor/next/config.d.ts +3 -4
  65. package/dist/_vendor/next/config.d.ts.map +1 -1
  66. package/dist/_vendor/next/config.js +37 -19
  67. package/dist/_vendor/next/config.js.map +1 -1
  68. package/dist/_vendor/next/index.d.ts +109 -29
  69. package/dist/_vendor/next/index.d.ts.map +1 -1
  70. package/dist/_vendor/next/index.js +77 -17
  71. package/dist/_vendor/next/index.js.map +1 -1
  72. package/dist/_vendor/platform-expo/index.d.ts +146 -27
  73. package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
  74. package/dist/_vendor/platform-expo/index.js +76 -10
  75. package/dist/_vendor/platform-expo/index.js.map +1 -1
  76. package/dist/_vendor/platform-expo/react.js.map +1 -1
  77. package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
  78. package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
  79. package/dist/_vendor/platform-node/index.d.mts +173 -9
  80. package/dist/_vendor/platform-node/index.d.mts.map +1 -1
  81. package/dist/_vendor/platform-node/index.mjs +225 -94
  82. package/dist/_vendor/platform-node/index.mjs.map +1 -1
  83. package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
  84. package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
  85. package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
  86. package/dist/_vendor/platform-web/external-change.d.ts +41 -0
  87. package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
  88. package/dist/_vendor/platform-web/external-change.js +30 -0
  89. package/dist/_vendor/platform-web/external-change.js.map +1 -1
  90. package/dist/_vendor/platform-web/index.d.ts +307 -35
  91. package/dist/_vendor/platform-web/index.d.ts.map +1 -1
  92. package/dist/_vendor/platform-web/index.js +189 -23
  93. package/dist/_vendor/platform-web/index.js.map +1 -1
  94. package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
  95. package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
  96. package/dist/_vendor/platform-web/indexeddb.js +10 -0
  97. package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
  98. package/dist/_vendor/platform-web/opfs.d.ts +13 -0
  99. package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
  100. package/dist/_vendor/platform-web/opfs.js +12 -0
  101. package/dist/_vendor/platform-web/opfs.js.map +1 -1
  102. package/dist/_vendor/platform-web/persistence.d.ts +54 -0
  103. package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
  104. package/dist/_vendor/platform-web/persistence.js +15 -0
  105. package/dist/_vendor/platform-web/persistence.js.map +1 -1
  106. package/dist/_vendor/platform-web/react.d.ts +1 -2
  107. package/dist/_vendor/platform-web/react.d.ts.map +1 -1
  108. package/dist/_vendor/platform-web/react.js +2 -4
  109. package/dist/_vendor/platform-web/react.js.map +1 -1
  110. package/dist/_vendor/platform-web/sqljs.js +10 -1
  111. package/dist/_vendor/platform-web/sqljs.js.map +1 -1
  112. package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
  113. package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
  114. package/dist/_vendor/platform-web/worker.d.ts +60 -9
  115. package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
  116. package/dist/_vendor/platform-web/worker.js +37 -4
  117. package/dist/_vendor/platform-web/worker.js.map +1 -1
  118. package/dist/_vendor/react/index.d.ts +196 -13
  119. package/dist/_vendor/react/index.d.ts.map +1 -1
  120. package/dist/_vendor/react/index.js +208 -17
  121. package/dist/_vendor/react/index.js.map +1 -1
  122. package/dist/_vendor/schema/definition.d.ts +129 -0
  123. package/dist/_vendor/schema/definition.d.ts.map +1 -1
  124. package/dist/_vendor/schema/definition.js +99 -0
  125. package/dist/_vendor/schema/definition.js.map +1 -1
  126. package/dist/_vendor/schema/planner.d.ts.map +1 -1
  127. package/dist/_vendor/schema/planner.js.map +1 -1
  128. package/dist/_vendor/schema/validators.d.ts +180 -4
  129. package/dist/_vendor/schema/validators.d.ts.map +1 -1
  130. package/dist/_vendor/schema/validators.js +35 -1
  131. package/dist/_vendor/schema/validators.js.map +1 -1
  132. package/dist/_vendor/svelte/index.d.ts +205 -7
  133. package/dist/_vendor/svelte/index.d.ts.map +1 -1
  134. package/dist/_vendor/svelte/index.js +199 -6
  135. package/dist/_vendor/svelte/index.js.map +1 -1
  136. package/dist/browser.d.ts.map +1 -1
  137. package/dist/cli.js +3 -1
  138. package/dist/cli.js.map +1 -1
  139. package/dist/index.d.ts +1 -1
  140. package/package.json +24 -21
@@ -1 +1 @@
1
- {"version":3,"file":"context.mjs","names":[],"sources":["../src/context.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport readline from \"node:readline/promises\";\nimport { CliError, type CliErrorCategory, normalizeCliError } from \"./errors.js\";\n\nconst ANSI = {\n reset: \"\\u001b[0m\",\n bold: \"\\u001b[1m\",\n yellow: \"\\u001b[33m\",\n cyan: \"\\u001b[36m\",\n green: \"\\u001b[32m\",\n red: \"\\u001b[31m\",\n magenta: \"\\u001b[35m\",\n dim: \"\\u001b[2m\"\n} as const;\n\nfunction supportsColor(stream: NodeJS.WriteStream): boolean {\n return Boolean(stream.isTTY) && process.env.NO_COLOR !== \"1\" && process.env.TERM !== \"dumb\";\n}\n\nfunction formatPrefix(\n stream: NodeJS.WriteStream,\n level: \"info\" | \"done\" | \"warn\" | \"error\" | \"next\" | \"work\" | \"fail\"\n): string {\n const plain = `[${level}]`;\n if (!supportsColor(stream)) {\n return plain;\n }\n const levelColor =\n level === \"info\"\n ? ANSI.cyan\n : level === \"done\"\n ? ANSI.green\n : level === \"warn\"\n ? ANSI.yellow\n : level === \"error\" || level === \"fail\"\n ? ANSI.red\n : level === \"next\"\n ? ANSI.magenta\n : ANSI.dim;\n return `${levelColor}[${level}]${ANSI.reset}`;\n}\n\nexport interface GlobalCliOptions {\n cwd?: string;\n json?: boolean;\n verbose?: boolean;\n interactive?: boolean;\n yes?: boolean;\n}\n\nexport interface CliChoice<TValue> {\n label: string;\n value: TValue;\n description?: string;\n}\n\nexport interface CliResult<TValue = unknown> {\n command?: string;\n summary?: string;\n target?: string;\n data?: TValue;\n nextSteps?: string[];\n}\n\nexport class CliContext {\n readonly cwd: string;\n readonly json: boolean;\n readonly verbose: boolean;\n readonly interactive: boolean;\n readonly yes: boolean;\n\n constructor(options: GlobalCliOptions = {}) {\n this.cwd = path.resolve(options.cwd ?? process.cwd());\n this.json = options.json ?? false;\n this.verbose = options.verbose ?? false;\n this.yes = options.yes ?? false;\n this.interactive =\n options.interactive === false\n ? false\n : process.env.SYNCORE_FORCE_INTERACTIVE === \"1\"\n ? true\n : Boolean(process.stdin.isTTY && process.stdout.isTTY && !this.json);\n }\n\n info(message: string): void {\n if (!this.json) {\n process.stdout.write(`${formatPrefix(process.stdout, \"info\")} ${message}\\n`);\n }\n }\n\n success(message: string): void {\n if (!this.json) {\n process.stdout.write(`${formatPrefix(process.stdout, \"done\")} ${message}\\n`);\n }\n }\n\n warn(message: string): void {\n if (!this.json) {\n process.stderr.write(`${formatPrefix(process.stderr, \"warn\")} ${message}\\n`);\n }\n }\n\n error(message: string): void {\n if (!this.json) {\n process.stderr.write(`${formatPrefix(process.stderr, \"error\")} ${message}\\n`);\n }\n }\n\n nextStep(message: string): void {\n if (!this.json) {\n process.stdout.write(`${formatPrefix(process.stdout, \"next\")} ${message}\\n`);\n }\n }\n\n printJson(payload: unknown): void {\n process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`);\n }\n\n printResult<TValue>(result: CliResult<TValue>): void {\n if (this.json) {\n this.printJson({\n ok: true,\n cwd: this.cwd,\n ...(result.command ? { command: result.command } : {}),\n ...(result.target ? { target: result.target } : {}),\n ...(result.summary ? { summary: result.summary } : {}),\n ...(result.data !== undefined ? { data: result.data } : {}),\n ...(result.nextSteps ? { nextSteps: result.nextSteps } : {})\n });\n return;\n }\n\n if (result.summary) {\n this.success(result.summary);\n }\n if (result.nextSteps) {\n for (const step of result.nextSteps) {\n this.nextStep(step);\n }\n }\n }\n\n fail(\n message: string,\n exitCode = 1,\n details?: unknown,\n options: {\n category?: CliErrorCategory;\n nextSteps?: string[];\n } = {}\n ): never {\n const errorOptions = {\n exitCode,\n details,\n ...(options.category ? { category: options.category } : {}),\n ...(options.nextSteps ? { nextSteps: options.nextSteps } : {})\n };\n throw new CliError(message, errorOptions);\n }\n\n handleError(error: unknown): void {\n const cliError = normalizeCliError(error);\n\n if (this.json) {\n this.printJson({\n ok: false,\n cwd: this.cwd,\n error: {\n category: cliError.category,\n message: cliError.message,\n exitCode: cliError.exitCode,\n ...(cliError.details !== undefined ? { details: cliError.details } : {}),\n ...(cliError.nextSteps ? { nextSteps: cliError.nextSteps } : {})\n }\n });\n } else {\n this.error(cliError.message);\n if (cliError.nextSteps) {\n for (const step of cliError.nextSteps) {\n this.nextStep(step);\n }\n }\n if (this.verbose && cliError.details !== undefined) {\n this.error(JSON.stringify(cliError.details, null, 2));\n }\n }\n\n process.exitCode = cliError.exitCode;\n }\n\n async confirm(message: string, defaultValue = true): Promise<boolean> {\n if (this.yes) {\n return true;\n }\n if (!this.interactive) {\n return false;\n }\n\n const suffix = defaultValue ? \"Y/n\" : \"y/N\";\n const answer = await this.input(`${message} [${suffix}]`, {\n defaultValue: defaultValue ? \"y\" : \"n\"\n });\n const normalized = answer.trim().toLowerCase();\n if (normalized.length === 0) {\n return defaultValue;\n }\n return normalized === \"y\" || normalized === \"yes\";\n }\n\n async input(\n message: string,\n options: {\n defaultValue?: string;\n allowEmpty?: boolean;\n } = {}\n ): Promise<string> {\n if (!this.interactive) {\n this.fail(`Cannot prompt in non-interactive mode: ${message}`);\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n });\n\n try {\n const prompt =\n options.defaultValue !== undefined\n ? `${message} (${options.defaultValue}): `\n : `${message}: `;\n const answer = await rl.question(prompt);\n if (answer.length === 0 && options.defaultValue !== undefined) {\n return options.defaultValue;\n }\n if (answer.length === 0 && !options.allowEmpty) {\n this.fail(`A value is required for: ${message}`);\n }\n return answer;\n } finally {\n rl.close();\n }\n }\n\n async select<TValue>(\n message: string,\n choices: CliChoice<TValue>[],\n defaultValue?: TValue\n ): Promise<TValue> {\n if (!this.interactive) {\n this.fail(`Cannot prompt in non-interactive mode: ${message}`);\n }\n if (choices.length === 0) {\n this.fail(`No choices are available for: ${message}`);\n }\n\n this.info(message);\n choices.forEach((choice, index) => {\n const suffix = choice.description ? ` - ${choice.description}` : \"\";\n process.stdout.write(` ${index + 1}. ${choice.label}${suffix}\\n`);\n });\n\n const defaultIndex = defaultValue\n ? Math.max(\n choices.findIndex((choice) => choice.value === defaultValue),\n 0\n )\n : 0;\n const rawValue = await this.input(`Choose 1-${choices.length}`, {\n defaultValue: String(defaultIndex + 1)\n });\n const index = Number.parseInt(rawValue, 10);\n if (Number.isNaN(index) || index < 1 || index > choices.length) {\n this.fail(`Expected a value between 1 and ${choices.length}.`);\n }\n return choices[index - 1]!.value;\n }\n\n async withSpinner<TValue>(\n label: string,\n action: () => Promise<TValue>\n ): Promise<TValue> {\n if (!this.interactive) {\n this.info(label);\n return await action();\n }\n\n const frames = [\"-\", \"\\\\\", \"|\", \"/\"];\n let index = 0;\n process.stderr.write(`${formatPrefix(process.stderr, \"work\")} ${label}`);\n const timer = setInterval(() => {\n process.stderr.write(\n `\\r${formatPrefix(process.stderr, \"work\")} ${frames[index % frames.length]} ${label}`\n );\n index += 1;\n }, 80);\n\n try {\n const result = await action();\n clearInterval(timer);\n process.stderr.write(`\\r${formatPrefix(process.stderr, \"done\")} ${label}\\n`);\n return result;\n } catch (error) {\n clearInterval(timer);\n process.stderr.write(`\\r${formatPrefix(process.stderr, \"fail\")} ${label}\\n`);\n throw error;\n }\n }\n}\n\nexport async function openTarget(target: string): Promise<boolean> {\n const command =\n process.platform === \"win32\"\n ? {\n file: \"cmd\",\n args: [\"/c\", \"start\", \"\", target]\n }\n : process.platform === \"darwin\"\n ? {\n file: \"open\",\n args: [target]\n }\n : {\n file: \"xdg-open\",\n args: [target]\n };\n\n return await new Promise((resolve) => {\n const child = spawn(command.file, command.args, {\n detached: true,\n stdio: \"ignore\"\n });\n child.once(\"error\", () => resolve(false));\n child.once(\"spawn\", () => {\n child.unref();\n resolve(true);\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"context.mjs","names":[],"sources":["../src/context.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport readline from \"node:readline/promises\";\nimport { CliError, type CliErrorCategory, normalizeCliError } from \"./errors.js\";\n\nconst ANSI = {\n reset: \"\\u001b[0m\",\n bold: \"\\u001b[1m\",\n yellow: \"\\u001b[33m\",\n cyan: \"\\u001b[36m\",\n green: \"\\u001b[32m\",\n red: \"\\u001b[31m\",\n magenta: \"\\u001b[35m\",\n dim: \"\\u001b[2m\"\n} as const;\n\nfunction supportsColor(stream: NodeJS.WriteStream): boolean {\n return Boolean(stream.isTTY) && process.env.NO_COLOR !== \"1\" && process.env.TERM !== \"dumb\";\n}\n\nfunction formatPrefix(\n stream: NodeJS.WriteStream,\n level: \"info\" | \"done\" | \"warn\" | \"error\" | \"next\" | \"work\" | \"fail\"\n): string {\n const plain = `[${level}]`;\n if (!supportsColor(stream)) {\n return plain;\n }\n const levelColor =\n level === \"info\"\n ? ANSI.cyan\n : level === \"done\"\n ? ANSI.green\n : level === \"warn\"\n ? ANSI.yellow\n : level === \"error\" || level === \"fail\"\n ? ANSI.red\n : level === \"next\"\n ? ANSI.magenta\n : ANSI.dim;\n return `${levelColor}[${level}]${ANSI.reset}`;\n}\n\nexport interface GlobalCliOptions {\n cwd?: string;\n json?: boolean;\n verbose?: boolean;\n interactive?: boolean;\n yes?: boolean;\n}\n\nexport interface CliChoice<TValue> {\n label: string;\n value: TValue;\n description?: string;\n}\n\nexport interface CliResult<TValue = unknown> {\n command?: string;\n summary?: string;\n target?: string;\n data?: TValue;\n nextSteps?: string[];\n}\n\nexport class CliContext {\n readonly cwd: string;\n readonly json: boolean;\n readonly verbose: boolean;\n readonly interactive: boolean;\n readonly yes: boolean;\n\n constructor(options: GlobalCliOptions = {}) {\n this.cwd = path.resolve(options.cwd ?? process.cwd());\n this.json = options.json ?? false;\n this.verbose = options.verbose ?? false;\n this.yes = options.yes ?? false;\n this.interactive =\n options.interactive === false\n ? false\n : process.env.SYNCORE_FORCE_INTERACTIVE === \"1\"\n ? true\n : Boolean(process.stdin.isTTY && process.stdout.isTTY && !this.json);\n }\n\n info(message: string): void {\n if (!this.json) {\n process.stdout.write(`${formatPrefix(process.stdout, \"info\")} ${message}\\n`);\n }\n }\n\n success(message: string): void {\n if (!this.json) {\n process.stdout.write(`${formatPrefix(process.stdout, \"done\")} ${message}\\n`);\n }\n }\n\n warn(message: string): void {\n if (!this.json) {\n process.stderr.write(`${formatPrefix(process.stderr, \"warn\")} ${message}\\n`);\n }\n }\n\n error(message: string): void {\n if (!this.json) {\n process.stderr.write(`${formatPrefix(process.stderr, \"error\")} ${message}\\n`);\n }\n }\n\n nextStep(message: string): void {\n if (!this.json) {\n process.stdout.write(`${formatPrefix(process.stdout, \"next\")} ${message}\\n`);\n }\n }\n\n printJson(payload: unknown): void {\n process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`);\n }\n\n printResult<TValue>(result: CliResult<TValue>): void {\n if (this.json) {\n this.printJson({\n ok: true,\n cwd: this.cwd,\n ...(result.command ? { command: result.command } : {}),\n ...(result.target ? { target: result.target } : {}),\n ...(result.summary ? { summary: result.summary } : {}),\n ...(result.data !== undefined ? { data: result.data } : {}),\n ...(result.nextSteps ? { nextSteps: result.nextSteps } : {})\n });\n return;\n }\n\n if (result.summary) {\n this.success(result.summary);\n }\n if (result.nextSteps) {\n for (const step of result.nextSteps) {\n this.nextStep(step);\n }\n }\n }\n\n fail(\n message: string,\n exitCode = 1,\n details?: unknown,\n options: {\n category?: CliErrorCategory;\n nextSteps?: string[];\n } = {}\n ): never {\n const errorOptions = {\n exitCode,\n details,\n ...(options.category ? { category: options.category } : {}),\n ...(options.nextSteps ? { nextSteps: options.nextSteps } : {})\n };\n throw new CliError(message, errorOptions);\n }\n\n handleError(error: unknown): void {\n const cliError = normalizeCliError(error);\n\n if (this.json) {\n this.printJson({\n ok: false,\n cwd: this.cwd,\n error: {\n category: cliError.category,\n message: cliError.message,\n exitCode: cliError.exitCode,\n ...(cliError.details !== undefined ? { details: cliError.details } : {}),\n ...(cliError.nextSteps ? { nextSteps: cliError.nextSteps } : {})\n }\n });\n } else {\n this.error(cliError.message);\n if (cliError.nextSteps) {\n for (const step of cliError.nextSteps) {\n this.nextStep(step);\n }\n }\n if (this.verbose && cliError.details !== undefined) {\n this.error(JSON.stringify(cliError.details, null, 2));\n }\n }\n\n process.exitCode = cliError.exitCode;\n }\n\n async confirm(message: string, defaultValue = true): Promise<boolean> {\n if (this.yes) {\n return true;\n }\n if (!this.interactive) {\n return false;\n }\n\n const suffix = defaultValue ? \"Y/n\" : \"y/N\";\n const answer = await this.input(`${message} [${suffix}]`, {\n defaultValue: defaultValue ? \"y\" : \"n\"\n });\n const normalized = answer.trim().toLowerCase();\n if (normalized.length === 0) {\n return defaultValue;\n }\n return normalized === \"y\" || normalized === \"yes\";\n }\n\n async input(\n message: string,\n options: {\n defaultValue?: string;\n allowEmpty?: boolean;\n } = {}\n ): Promise<string> {\n if (!this.interactive) {\n this.fail(`Cannot prompt in non-interactive mode: ${message}`);\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n });\n\n try {\n const prompt =\n options.defaultValue !== undefined\n ? `${message} (${options.defaultValue}): `\n : `${message}: `;\n const answer = await rl.question(prompt);\n if (answer.length === 0 && options.defaultValue !== undefined) {\n return options.defaultValue;\n }\n if (answer.length === 0 && !options.allowEmpty) {\n this.fail(`A value is required for: ${message}`);\n }\n return answer;\n } finally {\n rl.close();\n }\n }\n\n async select<TValue>(\n message: string,\n choices: CliChoice<TValue>[],\n defaultValue?: TValue\n ): Promise<TValue> {\n if (!this.interactive) {\n this.fail(`Cannot prompt in non-interactive mode: ${message}`);\n }\n if (choices.length === 0) {\n this.fail(`No choices are available for: ${message}`);\n }\n\n this.info(message);\n choices.forEach((choice, index) => {\n const suffix = choice.description ? ` - ${choice.description}` : \"\";\n process.stdout.write(` ${index + 1}. ${choice.label}${suffix}\\n`);\n });\n\n const defaultIndex = defaultValue\n ? Math.max(\n choices.findIndex((choice) => choice.value === defaultValue),\n 0\n )\n : 0;\n const rawValue = await this.input(`Choose 1-${choices.length}`, {\n defaultValue: String(defaultIndex + 1)\n });\n const index = Number.parseInt(rawValue, 10);\n if (Number.isNaN(index) || index < 1 || index > choices.length) {\n this.fail(`Expected a value between 1 and ${choices.length}.`);\n }\n return choices[index - 1]!.value;\n }\n\n async withSpinner<TValue>(\n label: string,\n action: () => Promise<TValue>\n ): Promise<TValue> {\n if (!this.interactive) {\n this.info(label);\n return await action();\n }\n\n const frames = [\"-\", \"\\\\\", \"|\", \"/\"];\n let index = 0;\n process.stderr.write(`${formatPrefix(process.stderr, \"work\")} ${label}`);\n const timer = setInterval(() => {\n process.stderr.write(\n `\\r${formatPrefix(process.stderr, \"work\")} ${frames[index % frames.length]} ${label}`\n );\n index += 1;\n }, 80);\n\n try {\n const result = await action();\n clearInterval(timer);\n process.stderr.write(`\\r${formatPrefix(process.stderr, \"done\")} ${label}\\n`);\n return result;\n } catch (error) {\n clearInterval(timer);\n process.stderr.write(`\\r${formatPrefix(process.stderr, \"fail\")} ${label}\\n`);\n throw error;\n }\n }\n}\n\nexport async function openTarget(target: string): Promise<boolean> {\n const command =\n process.platform === \"win32\"\n ? {\n file: \"cmd\",\n args: [\"/c\", \"start\", \"\", target]\n }\n : process.platform === \"darwin\"\n ? {\n file: \"open\",\n args: [target]\n }\n : {\n file: \"xdg-open\",\n args: [target]\n };\n\n return await new Promise((resolve) => {\n const child = spawn(command.file, command.args, {\n detached: true,\n stdio: \"ignore\"\n });\n child.once(\"error\", () => resolve(false));\n child.once(\"spawn\", () => {\n child.unref();\n resolve(true);\n });\n });\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev-session.mjs","names":[],"sources":["../src/dev-session.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\n\nimport type { CliContext } from \"./context.js\";\n\ntype ConsoleMethod = \"log\" | \"warn\" | \"error\";\n\nexport async function withConsoleCapture<TValue>(\n onMessage: (method: ConsoleMethod, message: string) => void,\n action: () => Promise<TValue>\n): Promise<TValue> {\n const originalLog = console.log;\n const originalWarn = console.warn;\n const originalError = console.error;\n\n const capture =\n (method: ConsoleMethod) =>\n (...args: unknown[]) => {\n const message = args\n .map((value) => (typeof value === \"string\" ? value : String(value)))\n .join(\" \")\n .trim();\n if (message.length > 0) {\n onMessage(method, message);\n }\n };\n\n console.log = capture(\"log\");\n console.warn = capture(\"warn\");\n console.error = capture(\"error\");\n\n try {\n return await action();\n } finally {\n console.log = originalLog;\n console.warn = originalWarn;\n console.error = originalError;\n }\n}\n\nexport function printDevSessionIntro(context: CliContext): void {\n context.info(\"Starting Syncore local dev session...\");\n}\n\nexport function printCompactDevPhase(context: CliContext, label: string): void {\n context.info(label);\n}\n\nexport async function runShellCommand(\n context: CliContext,\n command: string\n): Promise<void> {\n context.info(`Starting host command after Syncore bootstrap: ${command}`);\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, {\n cwd: context.cwd,\n shell: true,\n stdio: \"inherit\"\n });\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => {\n if ((code ?? 1) !== 0) {\n reject(new Error(`Shell command failed with exit code ${code ?? 1}.`));\n return;\n }\n resolve();\n });\n });\n}\n\n"],"mappings":";;AAMA,eAAsB,mBACpB,WACA,QACiB;CACjB,MAAM,cAAc,QAAQ;CAC5B,MAAM,eAAe,QAAQ;CAC7B,MAAM,gBAAgB,QAAQ;CAE9B,MAAM,WACH,YACA,GAAG,SAAoB;EACtB,MAAM,UAAU,KACb,KAAK,UAAW,OAAO,UAAU,WAAW,QAAQ,OAAO,MAAM,CAAE,CACnE,KAAK,IAAI,CACT,MAAM;AACT,MAAI,QAAQ,SAAS,EACnB,WAAU,QAAQ,QAAQ;;AAIhC,SAAQ,MAAM,QAAQ,MAAM;AAC5B,SAAQ,OAAO,QAAQ,OAAO;AAC9B,SAAQ,QAAQ,QAAQ,QAAQ;AAEhC,KAAI;AACF,SAAO,MAAM,QAAQ;WACb;AACR,UAAQ,MAAM;AACd,UAAQ,OAAO;AACf,UAAQ,QAAQ;;;AAIpB,SAAgB,qBAAqB,SAA2B;AAC9D,SAAQ,KAAK,wCAAwC;;AAGvD,SAAgB,qBAAqB,SAAqB,OAAqB;AAC7E,SAAQ,KAAK,MAAM;;AAGrB,eAAsB,gBACpB,SACA,SACe;AACf,SAAQ,KAAK,kDAAkD,UAAU;AACzE,OAAM,IAAI,SAAe,SAAS,WAAW;EAC3C,MAAM,QAAQ,MAAM,SAAS;GAC3B,KAAK,QAAQ;GACb,OAAO;GACP,OAAO;GACR,CAAC;AACF,QAAM,KAAK,SAAS,OAAO;AAC3B,QAAM,KAAK,SAAS,SAAS;AAC3B,QAAK,QAAQ,OAAO,GAAG;AACrB,2BAAO,IAAI,MAAM,uCAAuC,QAAQ,EAAE,GAAG,CAAC;AACtE;;AAEF,YAAS;IACT;GACF"}
1
+ {"version":3,"file":"dev-session.mjs","names":[],"sources":["../src/dev-session.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\n\nimport type { CliContext } from \"./context.js\";\n\ntype ConsoleMethod = \"log\" | \"warn\" | \"error\";\n\nexport async function withConsoleCapture<TValue>(\n onMessage: (method: ConsoleMethod, message: string) => void,\n action: () => Promise<TValue>\n): Promise<TValue> {\n const originalLog = console.log;\n const originalWarn = console.warn;\n const originalError = console.error;\n\n const capture =\n (method: ConsoleMethod) =>\n (...args: unknown[]) => {\n const message = args\n .map((value) => (typeof value === \"string\" ? value : String(value)))\n .join(\" \")\n .trim();\n if (message.length > 0) {\n onMessage(method, message);\n }\n };\n\n console.log = capture(\"log\");\n console.warn = capture(\"warn\");\n console.error = capture(\"error\");\n\n try {\n return await action();\n } finally {\n console.log = originalLog;\n console.warn = originalWarn;\n console.error = originalError;\n }\n}\n\nexport function printDevSessionIntro(context: CliContext): void {\n context.info(\"Starting Syncore local dev session...\");\n}\n\nexport function printCompactDevPhase(context: CliContext, label: string): void {\n context.info(label);\n}\n\nexport async function runShellCommand(\n context: CliContext,\n command: string\n): Promise<void> {\n context.info(`Starting host command after Syncore bootstrap: ${command}`);\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, {\n cwd: context.cwd,\n shell: true,\n stdio: \"inherit\"\n });\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => {\n if ((code ?? 1) !== 0) {\n reject(new Error(`Shell command failed with exit code ${code ?? 1}.`));\n return;\n }\n resolve();\n });\n });\n}\n\n"],"mappings":";;AAMA,eAAsB,mBACpB,WACA,QACiB;CACjB,MAAM,cAAc,QAAQ;CAC5B,MAAM,eAAe,QAAQ;CAC7B,MAAM,gBAAgB,QAAQ;CAE9B,MAAM,WACH,YACA,GAAG,SAAoB;EACtB,MAAM,UAAU,KACb,KAAK,UAAW,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK,CAAE,EAClE,KAAK,GAAG,EACR,KAAK;EACR,IAAI,QAAQ,SAAS,GACnB,UAAU,QAAQ,OAAO;CAE7B;CAEF,QAAQ,MAAM,QAAQ,KAAK;CAC3B,QAAQ,OAAO,QAAQ,MAAM;CAC7B,QAAQ,QAAQ,QAAQ,OAAO;CAE/B,IAAI;EACF,OAAO,MAAM,OAAO;CACtB,UAAU;EACR,QAAQ,MAAM;EACd,QAAQ,OAAO;EACf,QAAQ,QAAQ;CAClB;AACF;AAEA,SAAgB,qBAAqB,SAA2B;CAC9D,QAAQ,KAAK,uCAAuC;AACtD;AAEA,SAAgB,qBAAqB,SAAqB,OAAqB;CAC7E,QAAQ,KAAK,KAAK;AACpB;AAEA,eAAsB,gBACpB,SACA,SACe;CACf,QAAQ,KAAK,kDAAkD,SAAS;CACxE,MAAM,IAAI,SAAe,SAAS,WAAW;EAC3C,MAAM,QAAQ,MAAM,SAAS;GAC3B,KAAK,QAAQ;GACb,OAAO;GACP,OAAO;EACT,CAAC;EACD,MAAM,KAAK,SAAS,MAAM;EAC1B,MAAM,KAAK,SAAS,SAAS;GAC3B,KAAK,QAAQ,OAAO,GAAG;IACrB,uBAAO,IAAI,MAAM,uCAAuC,QAAQ,EAAE,EAAE,CAAC;IACrE;GACF;GACA,QAAQ;EACV,CAAC;CACH,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.mjs","names":["templateUsesConnectedClients"],"sources":["../src/doctor.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n createSchemaSnapshot,\n diffSchemaSnapshots,\n type SchemaSnapshot\n} from \"@syncore/core\";\nimport {\n detectProjectTemplate,\n fileExists,\n formatError,\n hasSyncoreProject,\n isLocalPortInUse,\n loadProjectSchema,\n readStoredSnapshot,\n runCodegen,\n writeStoredSnapshot\n} from \"@syncore/core/cli\";\nimport type {\n ClientTargetDescriptor,\n SyncoreTargetDescriptor,\n WorkspaceProjectMatch\n} from \"./project.js\";\nimport {\n findWorkspaceSyncoreProjects,\n listConnectedClientTargets,\n resolveDashboardUrl,\n resolveDevtoolsUrl,\n resolveProjectTargetDescriptor\n} from \"./project.js\";\nimport { templateUsesConnectedClients } from \"./messages.js\";\n\nexport type DoctorStatus =\n | \"ready\"\n | \"workspace-root\"\n | \"missing-project\"\n | \"missing-generated\"\n | \"schema-drift\"\n | \"schema-destructive-drift\"\n | \"hub-down\"\n | \"waiting-for-client\";\n\nexport type DoctorCheckCategory = \"project\" | \"generated\" | \"schema\";\nexport type DiagnosticCategory =\n | \"project\"\n | \"generated\"\n | \"schema\"\n | \"hub\"\n | \"runtime\"\n | \"persistence\"\n | \"client\";\nexport type DiagnosticSeverity = \"info\" | \"warning\" | \"error\";\nexport type DiagnosticStatus = \"pass\" | \"warn\" | \"fail\";\n\nexport interface DoctorCheck {\n category: DoctorCheckCategory;\n path: string;\n ok: boolean;\n}\n\nexport interface JourneyDiagnostic {\n id: string;\n category: DiagnosticCategory;\n severity: DiagnosticSeverity;\n status: DiagnosticStatus;\n summary: string;\n details?: string;\n suggestedAction?: string;\n canAutoFix: boolean;\n fixCommand?: string;\n}\n\nexport interface DoctorPrimaryIssue {\n code: DoctorStatus;\n summary: string;\n details: string;\n impact: string;\n suggestedAction?: string;\n}\n\nexport interface RuntimeSignalEntry {\n timestamp: number;\n category: \"query\" | \"mutation\" | \"action\" | \"system\";\n message: string;\n targetId: string;\n runtimeLabel?: string;\n}\n\nexport interface RuntimeSignals {\n logFilePath: string;\n logFilePresent: boolean;\n logEntryCount: number;\n recent: RuntimeSignalEntry[];\n sessionState: \"present\" | \"missing\" | \"invalid\";\n sessionPath: string;\n}\n\nexport interface DriftState {\n state:\n | \"clean\"\n | \"missing-snapshot\"\n | \"snapshot-outdated\"\n | \"migration-pending\"\n | \"destructive\"\n | \"unavailable\";\n currentSchemaHash: string | null;\n storedSchemaHash: string | null;\n statements: string[];\n warnings: string[];\n destructiveChanges: string[];\n details?: string;\n}\n\nexport interface DoctorReport {\n cwd: string;\n template: string;\n status: DoctorStatus;\n primaryIssue: DoctorPrimaryIssue;\n diagnostics: JourneyDiagnostic[];\n autoFixesAvailable: boolean;\n drift: DriftState;\n runtimeSignals: RuntimeSignals;\n checks: DoctorCheck[];\n workspaceMatches: WorkspaceProjectMatch[];\n suggestions: string[];\n projectTarget: Awaited<ReturnType<typeof resolveProjectTargetDescriptor>>;\n targets: SyncoreTargetDescriptor[];\n hub: {\n url: string;\n dashboardUrl: string;\n running: boolean;\n dashboardRunning: boolean;\n ports: {\n devtools: number;\n dashboard: number;\n };\n };\n}\n\ninterface SessionInspection {\n state: RuntimeSignals[\"sessionState\"];\n path: string;\n}\n\ninterface LoadedSchemaDrift {\n currentSnapshot: SchemaSnapshot | null;\n storedSnapshot: SchemaSnapshot | null;\n drift: DriftState;\n}\n\ninterface PersistedLogEntryLike {\n version?: number;\n timestamp: number;\n category: \"query\" | \"mutation\" | \"action\" | \"system\";\n message: string;\n targetId?: string;\n runtimeLabel?: string;\n}\n\nconst STRUCTURE_CHECKS = [\n { category: \"project\" as const, path: \"syncore.config.ts\" },\n { category: \"schema\" as const, path: path.join(\"syncore\", \"schema.ts\") },\n {\n category: \"project\" as const,\n path: path.join(\"syncore\", \"components.ts\"),\n optional: true\n },\n { category: \"project\" as const, path: path.join(\"syncore\", \"functions\") },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"api.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"components.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"schema.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"functions.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"server.ts\")\n },\n { category: \"schema\" as const, path: path.join(\"syncore\", \"migrations\") }\n] as const;\n\nexport async function buildDoctorReport(cwd: string): Promise<DoctorReport> {\n const template = await detectProjectTemplate(cwd);\n const checks = await Promise.all(\n STRUCTURE_CHECKS.map(async (entry) => ({\n category: entry.category,\n path: entry.path.replaceAll(\"\\\\\", \"/\"),\n ok:\n (await fileExists(path.join(cwd, entry.path))) ||\n (\"optional\" in entry && entry.optional === true)\n }))\n );\n const hasProject = await hasSyncoreProject(cwd);\n\n let projectTarget: Awaited<ReturnType<typeof resolveProjectTargetDescriptor>> = null;\n let persistenceDetails: string | undefined;\n try {\n projectTarget = await resolveProjectTargetDescriptor(cwd);\n if (projectTarget) {\n persistenceDetails = `Database path: ${projectTarget.databasePath}. Storage directory: ${projectTarget.storageDirectory}.`;\n }\n } catch (error) {\n persistenceDetails = formatError(error);\n }\n const usesConnectedClients =\n templateUsesConnectedClients(template) ||\n (!projectTarget && template !== \"node\");\n\n const clientTargets = await listConnectedClientTargets();\n const targets: SyncoreTargetDescriptor[] = [\n ...(projectTarget ? [projectTarget] : []),\n ...clientTargets\n ];\n\n const devtoolsUrl = resolveDevtoolsUrl();\n const dashboardUrl = resolveDashboardUrl();\n const hubPort = Number.parseInt(new URL(devtoolsUrl).port, 10);\n const dashboardPort = Number.parseInt(new URL(dashboardUrl).port, 10);\n const hub = {\n url: devtoolsUrl,\n dashboardUrl,\n running:\n Number.isFinite(hubPort) && hubPort > 0\n ? await isLocalPortInUse(hubPort)\n : false,\n dashboardRunning:\n Number.isFinite(dashboardPort) && dashboardPort > 0\n ? await isLocalPortInUse(dashboardPort)\n : false,\n ports: {\n devtools: hubPort,\n dashboard: dashboardPort\n }\n };\n\n const workspaceMatches = hasProject ? [] : await findWorkspaceSyncoreProjects(cwd);\n const runtimeSignals = await inspectRuntimeSignals(cwd);\n const loadedDrift = await loadSchemaDrift(cwd, checks);\n const drift = loadedDrift?.drift ?? {\n state: \"unavailable\",\n currentSchemaHash: null,\n storedSchemaHash: null,\n statements: [],\n warnings: [],\n destructiveChanges: [],\n details: \"Syncore could not inspect schema drift yet.\"\n };\n\n const diagnostics = buildDiagnostics({\n checks,\n drift,\n hasProject,\n hub,\n projectTarget,\n runtimeSignals,\n template,\n usesConnectedClients,\n clientTargets,\n ...(persistenceDetails ? { persistenceDetails } : {})\n });\n\n const primaryIssue = resolvePrimaryIssue({\n checks,\n diagnostics,\n drift,\n hasProject,\n hubRunning: hub.running,\n usesConnectedClients,\n clientTargets,\n workspaceMatches\n });\n\n const suggestions = collectSuggestions(primaryIssue, diagnostics, workspaceMatches);\n\n return {\n cwd,\n template,\n status: primaryIssue.code,\n primaryIssue,\n diagnostics,\n autoFixesAvailable: diagnostics.some(\n (diagnostic) => diagnostic.canAutoFix && diagnostic.status !== \"pass\"\n ),\n drift,\n runtimeSignals,\n checks,\n workspaceMatches,\n suggestions,\n projectTarget,\n targets,\n hub\n };\n}\n\nexport async function applyDoctorFixes(\n cwd: string,\n report?: DoctorReport\n): Promise<string[]> {\n const appliedFixes: string[] = [];\n const currentReport = report ?? (await buildDoctorReport(cwd));\n const missingGenerated = currentReport.checks.some(\n (check) => check.category === \"generated\" && !check.ok\n );\n\n if (missingGenerated) {\n await runCodegen(cwd);\n appliedFixes.push(\"Regenerated syncore/_generated/*.\");\n }\n\n const refreshedReport =\n missingGenerated || !report ? await buildDoctorReport(cwd) : currentReport;\n if (\n refreshedReport.drift.state === \"missing-snapshot\" ||\n refreshedReport.drift.state === \"snapshot-outdated\" ||\n refreshedReport.drift.state === \"migration-pending\"\n ) {\n const generatedSchemaPath = path.join(cwd, \"syncore\", \"_generated\", \"schema.ts\");\n if (await fileExists(generatedSchemaPath)) {\n const schema = await loadProjectSchema(cwd);\n const snapshot = createSchemaSnapshot(schema);\n await writeStoredSnapshot(cwd, snapshot);\n appliedFixes.push(\"Refreshed the stored schema snapshot.\");\n }\n }\n\n return appliedFixes;\n}\n\nasync function inspectRuntimeSignals(cwd: string): Promise<RuntimeSignals> {\n const session = await inspectDevtoolsSession(cwd);\n const logFilePath = path.join(cwd, \".syncore\", \"logs\", \"runtime.jsonl\");\n if (!(await fileExists(logFilePath))) {\n return {\n logFilePath,\n logFilePresent: false,\n logEntryCount: 0,\n recent: [],\n sessionState: session.state,\n sessionPath: session.path\n };\n }\n\n try {\n const source = await readFile(logFilePath, \"utf8\");\n const entries = source\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as PersistedLogEntryLike)\n .filter((entry) => entry.version === 2);\n\n return {\n logFilePath,\n logFilePresent: true,\n logEntryCount: entries.length,\n recent: entries.slice(-5).map((entry) => ({\n timestamp: entry.timestamp,\n category: entry.category,\n message: entry.message,\n targetId: entry.targetId ?? \"unknown\",\n ...(entry.runtimeLabel ? { runtimeLabel: entry.runtimeLabel } : {})\n })),\n sessionState: session.state,\n sessionPath: session.path\n };\n } catch (error) {\n return {\n logFilePath,\n logFilePresent: true,\n logEntryCount: 0,\n recent: [\n {\n timestamp: Date.now(),\n category: \"system\",\n message: `Unable to read runtime log history: ${formatError(error)}`,\n targetId: \"system\"\n }\n ],\n sessionState: session.state,\n sessionPath: session.path\n };\n }\n}\n\nasync function inspectDevtoolsSession(cwd: string): Promise<SessionInspection> {\n const sessionPath = path.join(cwd, \".syncore\", \"devtools-session.json\");\n if (!(await fileExists(sessionPath))) {\n return { state: \"missing\", path: sessionPath };\n }\n\n try {\n const source = await readFile(sessionPath, \"utf8\");\n const parsed = JSON.parse(source) as Partial<{\n dashboardUrl: string;\n authenticatedDashboardUrl: string;\n devtoolsUrl: string;\n token: string;\n }>;\n const valid =\n typeof parsed.dashboardUrl === \"string\" &&\n typeof parsed.authenticatedDashboardUrl === \"string\" &&\n typeof parsed.devtoolsUrl === \"string\" &&\n typeof parsed.token === \"string\";\n return {\n state: valid ? \"present\" : \"invalid\",\n path: sessionPath\n };\n } catch {\n return { state: \"invalid\", path: sessionPath };\n }\n}\n\nasync function loadSchemaDrift(\n cwd: string,\n checks: DoctorCheck[]\n): Promise<LoadedSchemaDrift | null> {\n const generatedSchemaPresent = checks.some(\n (check) => check.path === \"syncore/_generated/schema.ts\" && check.ok\n );\n if (!generatedSchemaPresent) {\n return null;\n }\n\n try {\n const schema = await loadProjectSchema(cwd);\n const currentSnapshot = createSchemaSnapshot(schema);\n const storedSnapshot = await readStoredSnapshot(cwd);\n const plan = diffSchemaSnapshots(storedSnapshot, currentSnapshot);\n const state =\n plan.destructiveChanges.length > 0\n ? \"destructive\"\n : !storedSnapshot\n ? \"missing-snapshot\"\n : storedSnapshot.hash !== currentSnapshot.hash && plan.statements.length > 0\n ? \"migration-pending\"\n : storedSnapshot.hash !== currentSnapshot.hash\n ? \"snapshot-outdated\"\n : \"clean\";\n return {\n currentSnapshot,\n storedSnapshot,\n drift: {\n state,\n currentSchemaHash: currentSnapshot.hash,\n storedSchemaHash: storedSnapshot?.hash ?? null,\n statements: plan.statements,\n warnings: plan.warnings,\n destructiveChanges: plan.destructiveChanges,\n details:\n state === \"clean\"\n ? \"Local schema snapshot matches the generated Syncore schema.\"\n : describeDriftState(state, plan.statements.length, plan.warnings.length)\n }\n };\n } catch (error) {\n return {\n currentSnapshot: null,\n storedSnapshot: null,\n drift: {\n state: \"unavailable\",\n currentSchemaHash: null,\n storedSchemaHash: null,\n statements: [],\n warnings: [],\n destructiveChanges: [],\n details: `Syncore could not load the generated schema: ${formatError(error)}`\n }\n };\n }\n}\n\nfunction describeDriftState(\n state: DriftState[\"state\"],\n statementCount: number,\n warningCount: number\n): string {\n if (state === \"missing-snapshot\") {\n return \"No stored schema snapshot was found yet.\";\n }\n if (state === \"migration-pending\") {\n return `Schema drift detected with ${statementCount} SQL statement(s) pending and ${warningCount} warning(s).`;\n }\n if (state === \"snapshot-outdated\") {\n return \"The stored schema snapshot differs from the generated schema, but no SQL statements are pending.\";\n }\n if (state === \"destructive\") {\n return \"The current schema diff includes destructive changes that require manual review.\";\n }\n return \"Syncore could not inspect schema drift.\";\n}\n\nfunction buildDiagnostics(input: {\n checks: DoctorCheck[];\n drift: DriftState;\n hasProject: boolean;\n hub: DoctorReport[\"hub\"];\n persistenceDetails?: string;\n projectTarget: DoctorReport[\"projectTarget\"];\n runtimeSignals: RuntimeSignals;\n template: string;\n usesConnectedClients: boolean;\n clientTargets: ClientTargetDescriptor[];\n}): JourneyDiagnostic[] {\n const diagnostics: JourneyDiagnostic[] = [];\n const missingProjectPaths = input.checks.filter(\n (check) => (check.category === \"project\" || check.category === \"schema\") && !check.ok\n );\n diagnostics.push(\n missingProjectPaths.length === 0 && input.hasProject\n ? {\n id: \"project.structure\",\n category: \"project\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Syncore project structure is present.\",\n details: \"Core project files are available in this directory.\",\n canAutoFix: false\n }\n : {\n id: \"project.structure\",\n category: \"project\",\n severity: \"error\",\n status: \"fail\",\n summary: \"Syncore project structure is incomplete or missing.\",\n details:\n missingProjectPaths.length > 0\n ? `Missing: ${missingProjectPaths.map((check) => check.path).join(\", \")}.`\n : \"This directory does not contain a full Syncore project yet.\",\n suggestedAction: \"Run `npx syncorejs init` or restore the missing project files.\",\n canAutoFix: false\n }\n );\n\n const missingGenerated = input.checks.filter(\n (check) => check.category === \"generated\" && !check.ok\n );\n diagnostics.push(\n missingGenerated.length === 0\n ? {\n id: \"generated.files\",\n category: \"generated\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Generated Syncore files are present.\",\n details: \"syncore/_generated looks available for runtime and type-driven tooling.\",\n canAutoFix: false\n }\n : {\n id: \"generated.files\",\n category: \"generated\",\n severity: \"error\",\n status: \"fail\",\n summary: \"Generated Syncore files are missing.\",\n details: `Missing: ${missingGenerated.map((check) => check.path).join(\", \")}.`,\n suggestedAction: \"Run `npx syncorejs codegen` or `npx syncorejs doctor --fix`.\",\n canAutoFix: true,\n fixCommand: \"npx syncorejs doctor --fix\"\n }\n );\n\n diagnostics.push(buildSchemaDiagnostic(input.drift));\n\n diagnostics.push(\n input.projectTarget\n ? {\n id: \"persistence.project-target\",\n category: \"persistence\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Project target persistence is configured.\",\n ...(input.persistenceDetails ? { details: input.persistenceDetails } : {}),\n canAutoFix: false\n }\n : input.usesConnectedClients\n ? {\n id: \"persistence.project-target\",\n category: \"persistence\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Persistence is client-managed for this template.\",\n details:\n \"This app template expects a connected client runtime to provide local storage and runtime state.\",\n canAutoFix: false\n }\n : {\n id: \"persistence.project-target\",\n category: \"persistence\",\n severity: \"error\",\n status: \"fail\",\n summary: \"No local project target is configured.\",\n details:\n input.persistenceDetails ??\n \"Syncore could not resolve a project target database and storage directory.\",\n suggestedAction:\n \"Check syncore.config.ts and make sure projectTarget.databasePath and projectTarget.storageDirectory are valid.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(\n input.hub.running\n ? {\n id: \"hub.devtools\",\n category: \"hub\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Local devtools hub is running.\",\n details: `Devtools: ${input.hub.url}. Dashboard: ${input.hub.dashboardUrl}.`,\n canAutoFix: false\n }\n : {\n id: \"hub.devtools\",\n category: \"hub\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"Local devtools hub is not running.\",\n details: `Expected devtools endpoint: ${input.hub.url}.`,\n suggestedAction: \"Run `npx syncorejs dev` to start the local hub and dashboard.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(\n input.hub.dashboardRunning\n ? {\n id: \"hub.dashboard\",\n category: \"hub\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Dashboard shell is responding.\",\n details: input.hub.dashboardUrl,\n canAutoFix: false\n }\n : {\n id: \"hub.dashboard\",\n category: \"hub\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"Dashboard shell is not responding yet.\",\n details: `Expected dashboard URL: ${input.hub.dashboardUrl}.`,\n suggestedAction: \"Run `npx syncorejs dev` or inspect whether the dashboard port is already taken.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(\n input.usesConnectedClients\n ? input.clientTargets.length > 0\n ? {\n id: \"client.runtime\",\n category: \"client\",\n severity: \"info\",\n status: \"pass\",\n summary: \"At least one client runtime is connected.\",\n details: `Connected targets: ${input.clientTargets.map((target) => target.id).join(\", \")}.`,\n canAutoFix: false\n }\n : {\n id: \"client.runtime\",\n category: \"client\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"This template is waiting for a connected client runtime.\",\n details:\n \"Syncore is ready to inspect or operate on your app once a browser tab, worker, Electron shell, or Expo runtime connects.\",\n suggestedAction:\n \"Start your app host, then run `npx syncorejs targets` to inspect connected client targets.\",\n canAutoFix: false\n }\n : {\n id: \"client.runtime\",\n category: \"client\",\n severity: \"info\",\n status: \"pass\",\n summary: \"This template does not require a connected client runtime.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(buildRuntimeDiagnostic(input.runtimeSignals));\n\n return diagnostics;\n}\n\nfunction buildSchemaDiagnostic(drift: DriftState): JourneyDiagnostic {\n if (drift.state === \"clean\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Schema snapshot is in sync.\",\n ...(drift.details ? { details: drift.details } : {}),\n canAutoFix: false\n };\n }\n if (drift.state === \"destructive\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"error\",\n status: \"fail\",\n summary: \"Schema drift includes destructive changes.\",\n details: drift.destructiveChanges.join(\"; \"),\n suggestedAction:\n \"Review the schema change manually and create or edit a migration before continuing.\",\n canAutoFix: false\n };\n }\n if (drift.state === \"missing-snapshot\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"No stored schema snapshot was found.\",\n ...(drift.details ? { details: drift.details } : {}),\n suggestedAction:\n \"Run `npx syncorejs doctor --fix` to refresh the snapshot, or generate a migration if you intend to persist the change.\",\n canAutoFix: true,\n fixCommand: \"npx syncorejs doctor --fix\"\n };\n }\n if (drift.state === \"snapshot-outdated\" || drift.state === \"migration-pending\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"warning\",\n status: \"warn\",\n summary:\n drift.state === \"migration-pending\"\n ? \"Schema drift has pending migration statements.\"\n : \"Stored schema snapshot differs from the generated schema.\",\n ...(drift.details ? { details: drift.details } : {}),\n suggestedAction:\n drift.state === \"migration-pending\"\n ? \"Run `npx syncorejs migrate status` to inspect the diff, then `npx syncorejs doctor --fix` only if you just want to refresh the stored snapshot.\"\n : \"Run `npx syncorejs doctor --fix` to refresh the stored snapshot safely.\",\n canAutoFix: true,\n fixCommand: \"npx syncorejs doctor --fix\"\n };\n }\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"Schema drift could not be inspected yet.\",\n ...(drift.details ? { details: drift.details } : {}),\n suggestedAction:\n \"Restore generated files or rerun `npx syncorejs codegen`, then run `npx syncorejs doctor` again.\",\n canAutoFix: false\n };\n}\n\nfunction buildRuntimeDiagnostic(runtimeSignals: RuntimeSignals): JourneyDiagnostic {\n if (runtimeSignals.sessionState === \"invalid\") {\n return {\n id: \"runtime.session\",\n category: \"runtime\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"The saved devtools session file is invalid.\",\n details: runtimeSignals.sessionPath,\n suggestedAction:\n \"Restart `npx syncorejs dev` to regenerate the session state for the local hub.\",\n canAutoFix: false\n };\n }\n if (runtimeSignals.logEntryCount === 0) {\n return {\n id: \"runtime.signals\",\n category: \"runtime\",\n severity: \"info\",\n status: \"pass\",\n summary: \"No recent runtime signals were recorded yet.\",\n details: runtimeSignals.logFilePresent\n ? \"The runtime log file exists but has no recorded entries yet.\"\n : \"No runtime log file has been created yet.\",\n canAutoFix: false\n };\n }\n const latest = runtimeSignals.recent[runtimeSignals.recent.length - 1];\n return {\n id: \"runtime.signals\",\n category: \"runtime\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Recent runtime signals are available.\",\n ...(latest\n ? {\n details: `Latest: ${latest.category} on ${latest.targetId} at ${new Date(latest.timestamp).toISOString()}: ${latest.message}`\n }\n : {}),\n canAutoFix: false\n };\n}\n\nfunction resolvePrimaryIssue(input: {\n checks: DoctorCheck[];\n diagnostics: JourneyDiagnostic[];\n drift: DriftState;\n hasProject: boolean;\n hubRunning: boolean;\n usesConnectedClients: boolean;\n clientTargets: ClientTargetDescriptor[];\n workspaceMatches: WorkspaceProjectMatch[];\n}): DoctorPrimaryIssue {\n if (!input.hasProject && input.workspaceMatches.length > 0) {\n return {\n code: \"workspace-root\",\n summary: \"You are at a workspace root, not inside a Syncore app package.\",\n details: `Found ${input.workspaceMatches.length} Syncore package(s) under this workspace.`,\n impact: \"Project-specific diagnostics and runtime operations are ambiguous from the workspace root.\",\n suggestedAction: `Run the command with --cwd ${input.workspaceMatches[0]!.relativePath} or change into that package directory.`\n };\n }\n\n const missingProjectPaths = input.checks.filter(\n (check) => (check.category === \"project\" || check.category === \"schema\") && !check.ok\n );\n if (!input.hasProject || missingProjectPaths.length > 0) {\n return {\n code: \"missing-project\",\n summary: \"Syncore project files are missing or incomplete.\",\n details:\n missingProjectPaths.length > 0\n ? `Missing: ${missingProjectPaths.map((check) => check.path).join(\", \")}.`\n : \"This directory does not contain a complete Syncore project yet.\",\n impact: \"The CLI cannot bootstrap the local runtime or inspect schema and persistence reliably.\",\n suggestedAction: \"Run `npx syncorejs init` or restore the missing project files.\"\n };\n }\n\n const missingGenerated = input.checks.filter(\n (check) => check.category === \"generated\" && !check.ok\n );\n if (missingGenerated.length > 0) {\n return {\n code: \"missing-generated\",\n summary: \"Generated Syncore files are missing.\",\n details: `Missing: ${missingGenerated.map((check) => check.path).join(\", \")}.`,\n impact: \"Type-driven runtime loading and schema inspection may be stale or unavailable.\",\n suggestedAction: \"Run `npx syncorejs doctor --fix` or `npx syncorejs codegen`.\"\n };\n }\n\n if (input.drift.state === \"destructive\") {\n return {\n code: \"schema-destructive-drift\",\n summary: \"Schema drift is blocked by destructive changes.\",\n details: input.drift.destructiveChanges.join(\"; \"),\n impact: \"Syncore cannot safely advance the local schema automatically.\",\n suggestedAction: \"Review the schema change manually and generate a migration before continuing.\"\n };\n }\n\n if (input.usesConnectedClients && input.clientTargets.length === 0) {\n return {\n code: \"waiting-for-client\",\n summary: \"This app is waiting for a connected local runtime.\",\n details:\n input.hubRunning\n ? \"Client-managed templates only become fully operational after the app host connects to the local Syncore hub.\"\n : \"This template depends on a client-managed runtime, and no app runtime is connected yet.\",\n impact: \"Worker, bridge IPC, storage, and client-side data inspection stay unavailable until a runtime connects.\",\n suggestedAction:\n input.hubRunning\n ? \"Start your app host, then run `npx syncorejs targets` to inspect connected runtimes.\"\n : \"Run `npx syncorejs dev`, start your app host, then run `npx syncorejs targets` to inspect connected runtimes.\"\n };\n }\n\n if (\n input.drift.state === \"missing-snapshot\" ||\n input.drift.state === \"snapshot-outdated\" ||\n input.drift.state === \"migration-pending\"\n ) {\n return {\n code: \"schema-drift\",\n summary: \"The local schema snapshot is out of sync.\",\n details: input.drift.details ?? \"Schema drift was detected.\",\n impact: \"The local dev loop can become confusing because the stored snapshot no longer matches the generated schema.\",\n suggestedAction:\n input.drift.state === \"migration-pending\"\n ? \"Run `npx syncorejs migrate status` to inspect the diff, then use `npx syncorejs doctor --fix` if you only need to refresh the stored snapshot.\"\n : \"Run `npx syncorejs doctor --fix` to refresh the stored snapshot safely.\"\n };\n }\n\n if (!input.hubRunning) {\n return {\n code: \"hub-down\",\n summary: \"The local devtools hub is not running.\",\n details: \"Syncore can inspect project state, but runtime and client diagnostics are limited until the hub starts.\",\n impact: \"Commands that depend on live targets, logs, or IPC visibility will have reduced signal.\",\n suggestedAction: \"Run `npx syncorejs dev` to start the local hub.\"\n };\n }\n\n return {\n code: \"ready\",\n summary: \"Syncore is ready for the local development loop.\",\n details: \"Project structure, generated files, schema state, and runtime prerequisites look healthy.\",\n impact: \"You can use `syncorejs dev`, inspect targets, and operate on the local runtime.\",\n suggestedAction: \"Run `npx syncorejs dev` to keep codegen, schema, and the local hub in sync.\"\n };\n}\n\nfunction collectSuggestions(\n primaryIssue: DoctorPrimaryIssue,\n diagnostics: JourneyDiagnostic[],\n workspaceMatches: WorkspaceProjectMatch[]\n): string[] {\n const suggestions = new Set<string>();\n if (primaryIssue.suggestedAction) {\n suggestions.add(primaryIssue.suggestedAction);\n }\n if (primaryIssue.code === \"workspace-root\" && workspaceMatches.length > 0) {\n suggestions.add(\n `Run the command with --cwd ${workspaceMatches[0]!.relativePath} or change into a package directory.`\n );\n }\n for (const diagnostic of diagnostics) {\n if (diagnostic.status === \"pass\") {\n continue;\n }\n if (diagnostic.suggestedAction) {\n suggestions.add(diagnostic.suggestedAction);\n }\n }\n return [...suggestions];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"doctor.mjs","names":["templateUsesConnectedClients"],"sources":["../src/doctor.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n createSchemaSnapshot,\n diffSchemaSnapshots,\n type SchemaSnapshot\n} from \"@syncore/core\";\nimport {\n detectProjectTemplate,\n fileExists,\n formatError,\n hasSyncoreProject,\n isLocalPortInUse,\n loadProjectSchema,\n readStoredSnapshot,\n runCodegen,\n writeStoredSnapshot\n} from \"@syncore/core/cli\";\nimport type {\n ClientTargetDescriptor,\n SyncoreTargetDescriptor,\n WorkspaceProjectMatch\n} from \"./project.js\";\nimport {\n findWorkspaceSyncoreProjects,\n listConnectedClientTargets,\n resolveDashboardUrl,\n resolveDevtoolsUrl,\n resolveProjectTargetDescriptor\n} from \"./project.js\";\nimport { templateUsesConnectedClients } from \"./messages.js\";\n\nexport type DoctorStatus =\n | \"ready\"\n | \"workspace-root\"\n | \"missing-project\"\n | \"missing-generated\"\n | \"schema-drift\"\n | \"schema-destructive-drift\"\n | \"hub-down\"\n | \"waiting-for-client\";\n\nexport type DoctorCheckCategory = \"project\" | \"generated\" | \"schema\";\nexport type DiagnosticCategory =\n | \"project\"\n | \"generated\"\n | \"schema\"\n | \"hub\"\n | \"runtime\"\n | \"persistence\"\n | \"client\";\nexport type DiagnosticSeverity = \"info\" | \"warning\" | \"error\";\nexport type DiagnosticStatus = \"pass\" | \"warn\" | \"fail\";\n\nexport interface DoctorCheck {\n category: DoctorCheckCategory;\n path: string;\n ok: boolean;\n}\n\nexport interface JourneyDiagnostic {\n id: string;\n category: DiagnosticCategory;\n severity: DiagnosticSeverity;\n status: DiagnosticStatus;\n summary: string;\n details?: string;\n suggestedAction?: string;\n canAutoFix: boolean;\n fixCommand?: string;\n}\n\nexport interface DoctorPrimaryIssue {\n code: DoctorStatus;\n summary: string;\n details: string;\n impact: string;\n suggestedAction?: string;\n}\n\nexport interface RuntimeSignalEntry {\n timestamp: number;\n category: \"query\" | \"mutation\" | \"action\" | \"system\";\n message: string;\n targetId: string;\n runtimeLabel?: string;\n}\n\nexport interface RuntimeSignals {\n logFilePath: string;\n logFilePresent: boolean;\n logEntryCount: number;\n recent: RuntimeSignalEntry[];\n sessionState: \"present\" | \"missing\" | \"invalid\";\n sessionPath: string;\n}\n\nexport interface DriftState {\n state:\n | \"clean\"\n | \"missing-snapshot\"\n | \"snapshot-outdated\"\n | \"migration-pending\"\n | \"destructive\"\n | \"unavailable\";\n currentSchemaHash: string | null;\n storedSchemaHash: string | null;\n statements: string[];\n warnings: string[];\n destructiveChanges: string[];\n details?: string;\n}\n\nexport interface DoctorReport {\n cwd: string;\n template: string;\n status: DoctorStatus;\n primaryIssue: DoctorPrimaryIssue;\n diagnostics: JourneyDiagnostic[];\n autoFixesAvailable: boolean;\n drift: DriftState;\n runtimeSignals: RuntimeSignals;\n checks: DoctorCheck[];\n workspaceMatches: WorkspaceProjectMatch[];\n suggestions: string[];\n projectTarget: Awaited<ReturnType<typeof resolveProjectTargetDescriptor>>;\n targets: SyncoreTargetDescriptor[];\n hub: {\n url: string;\n dashboardUrl: string;\n running: boolean;\n dashboardRunning: boolean;\n ports: {\n devtools: number;\n dashboard: number;\n };\n };\n}\n\ninterface SessionInspection {\n state: RuntimeSignals[\"sessionState\"];\n path: string;\n}\n\ninterface LoadedSchemaDrift {\n currentSnapshot: SchemaSnapshot | null;\n storedSnapshot: SchemaSnapshot | null;\n drift: DriftState;\n}\n\ninterface PersistedLogEntryLike {\n version?: number;\n timestamp: number;\n category: \"query\" | \"mutation\" | \"action\" | \"system\";\n message: string;\n targetId?: string;\n runtimeLabel?: string;\n}\n\nconst STRUCTURE_CHECKS = [\n { category: \"project\" as const, path: \"syncore.config.ts\" },\n { category: \"schema\" as const, path: path.join(\"syncore\", \"schema.ts\") },\n {\n category: \"project\" as const,\n path: path.join(\"syncore\", \"components.ts\"),\n optional: true\n },\n { category: \"project\" as const, path: path.join(\"syncore\", \"functions\") },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"api.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"components.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"schema.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"functions.ts\")\n },\n {\n category: \"generated\" as const,\n path: path.join(\"syncore\", \"_generated\", \"server.ts\")\n },\n { category: \"schema\" as const, path: path.join(\"syncore\", \"migrations\") }\n] as const;\n\nexport async function buildDoctorReport(cwd: string): Promise<DoctorReport> {\n const template = await detectProjectTemplate(cwd);\n const checks = await Promise.all(\n STRUCTURE_CHECKS.map(async (entry) => ({\n category: entry.category,\n path: entry.path.replaceAll(\"\\\\\", \"/\"),\n ok:\n (await fileExists(path.join(cwd, entry.path))) ||\n (\"optional\" in entry && entry.optional === true)\n }))\n );\n const hasProject = await hasSyncoreProject(cwd);\n\n let projectTarget: Awaited<ReturnType<typeof resolveProjectTargetDescriptor>> = null;\n let persistenceDetails: string | undefined;\n try {\n projectTarget = await resolveProjectTargetDescriptor(cwd);\n if (projectTarget) {\n persistenceDetails = `Database path: ${projectTarget.databasePath}. Storage directory: ${projectTarget.storageDirectory}.`;\n }\n } catch (error) {\n persistenceDetails = formatError(error);\n }\n const usesConnectedClients =\n templateUsesConnectedClients(template) ||\n (!projectTarget && template !== \"node\");\n\n const clientTargets = await listConnectedClientTargets();\n const targets: SyncoreTargetDescriptor[] = [\n ...(projectTarget ? [projectTarget] : []),\n ...clientTargets\n ];\n\n const devtoolsUrl = resolveDevtoolsUrl();\n const dashboardUrl = resolveDashboardUrl();\n const hubPort = Number.parseInt(new URL(devtoolsUrl).port, 10);\n const dashboardPort = Number.parseInt(new URL(dashboardUrl).port, 10);\n const hub = {\n url: devtoolsUrl,\n dashboardUrl,\n running:\n Number.isFinite(hubPort) && hubPort > 0\n ? await isLocalPortInUse(hubPort)\n : false,\n dashboardRunning:\n Number.isFinite(dashboardPort) && dashboardPort > 0\n ? await isLocalPortInUse(dashboardPort)\n : false,\n ports: {\n devtools: hubPort,\n dashboard: dashboardPort\n }\n };\n\n const workspaceMatches = hasProject ? [] : await findWorkspaceSyncoreProjects(cwd);\n const runtimeSignals = await inspectRuntimeSignals(cwd);\n const loadedDrift = await loadSchemaDrift(cwd, checks);\n const drift = loadedDrift?.drift ?? {\n state: \"unavailable\",\n currentSchemaHash: null,\n storedSchemaHash: null,\n statements: [],\n warnings: [],\n destructiveChanges: [],\n details: \"Syncore could not inspect schema drift yet.\"\n };\n\n const diagnostics = buildDiagnostics({\n checks,\n drift,\n hasProject,\n hub,\n projectTarget,\n runtimeSignals,\n template,\n usesConnectedClients,\n clientTargets,\n ...(persistenceDetails ? { persistenceDetails } : {})\n });\n\n const primaryIssue = resolvePrimaryIssue({\n checks,\n diagnostics,\n drift,\n hasProject,\n hubRunning: hub.running,\n usesConnectedClients,\n clientTargets,\n workspaceMatches\n });\n\n const suggestions = collectSuggestions(primaryIssue, diagnostics, workspaceMatches);\n\n return {\n cwd,\n template,\n status: primaryIssue.code,\n primaryIssue,\n diagnostics,\n autoFixesAvailable: diagnostics.some(\n (diagnostic) => diagnostic.canAutoFix && diagnostic.status !== \"pass\"\n ),\n drift,\n runtimeSignals,\n checks,\n workspaceMatches,\n suggestions,\n projectTarget,\n targets,\n hub\n };\n}\n\nexport async function applyDoctorFixes(\n cwd: string,\n report?: DoctorReport\n): Promise<string[]> {\n const appliedFixes: string[] = [];\n const currentReport = report ?? (await buildDoctorReport(cwd));\n const missingGenerated = currentReport.checks.some(\n (check) => check.category === \"generated\" && !check.ok\n );\n\n if (missingGenerated) {\n await runCodegen(cwd);\n appliedFixes.push(\"Regenerated syncore/_generated/*.\");\n }\n\n const refreshedReport =\n missingGenerated || !report ? await buildDoctorReport(cwd) : currentReport;\n if (\n refreshedReport.drift.state === \"missing-snapshot\" ||\n refreshedReport.drift.state === \"snapshot-outdated\" ||\n refreshedReport.drift.state === \"migration-pending\"\n ) {\n const generatedSchemaPath = path.join(cwd, \"syncore\", \"_generated\", \"schema.ts\");\n if (await fileExists(generatedSchemaPath)) {\n const schema = await loadProjectSchema(cwd);\n const snapshot = createSchemaSnapshot(schema);\n await writeStoredSnapshot(cwd, snapshot);\n appliedFixes.push(\"Refreshed the stored schema snapshot.\");\n }\n }\n\n return appliedFixes;\n}\n\nasync function inspectRuntimeSignals(cwd: string): Promise<RuntimeSignals> {\n const session = await inspectDevtoolsSession(cwd);\n const logFilePath = path.join(cwd, \".syncore\", \"logs\", \"runtime.jsonl\");\n if (!(await fileExists(logFilePath))) {\n return {\n logFilePath,\n logFilePresent: false,\n logEntryCount: 0,\n recent: [],\n sessionState: session.state,\n sessionPath: session.path\n };\n }\n\n try {\n const source = await readFile(logFilePath, \"utf8\");\n const entries = source\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as PersistedLogEntryLike)\n .filter((entry) => entry.version === 2);\n\n return {\n logFilePath,\n logFilePresent: true,\n logEntryCount: entries.length,\n recent: entries.slice(-5).map((entry) => ({\n timestamp: entry.timestamp,\n category: entry.category,\n message: entry.message,\n targetId: entry.targetId ?? \"unknown\",\n ...(entry.runtimeLabel ? { runtimeLabel: entry.runtimeLabel } : {})\n })),\n sessionState: session.state,\n sessionPath: session.path\n };\n } catch (error) {\n return {\n logFilePath,\n logFilePresent: true,\n logEntryCount: 0,\n recent: [\n {\n timestamp: Date.now(),\n category: \"system\",\n message: `Unable to read runtime log history: ${formatError(error)}`,\n targetId: \"system\"\n }\n ],\n sessionState: session.state,\n sessionPath: session.path\n };\n }\n}\n\nasync function inspectDevtoolsSession(cwd: string): Promise<SessionInspection> {\n const sessionPath = path.join(cwd, \".syncore\", \"devtools-session.json\");\n if (!(await fileExists(sessionPath))) {\n return { state: \"missing\", path: sessionPath };\n }\n\n try {\n const source = await readFile(sessionPath, \"utf8\");\n const parsed = JSON.parse(source) as Partial<{\n dashboardUrl: string;\n authenticatedDashboardUrl: string;\n devtoolsUrl: string;\n token: string;\n }>;\n const valid =\n typeof parsed.dashboardUrl === \"string\" &&\n typeof parsed.authenticatedDashboardUrl === \"string\" &&\n typeof parsed.devtoolsUrl === \"string\" &&\n typeof parsed.token === \"string\";\n return {\n state: valid ? \"present\" : \"invalid\",\n path: sessionPath\n };\n } catch {\n return { state: \"invalid\", path: sessionPath };\n }\n}\n\nasync function loadSchemaDrift(\n cwd: string,\n checks: DoctorCheck[]\n): Promise<LoadedSchemaDrift | null> {\n const generatedSchemaPresent = checks.some(\n (check) => check.path === \"syncore/_generated/schema.ts\" && check.ok\n );\n if (!generatedSchemaPresent) {\n return null;\n }\n\n try {\n const schema = await loadProjectSchema(cwd);\n const currentSnapshot = createSchemaSnapshot(schema);\n const storedSnapshot = await readStoredSnapshot(cwd);\n const plan = diffSchemaSnapshots(storedSnapshot, currentSnapshot);\n const state =\n plan.destructiveChanges.length > 0\n ? \"destructive\"\n : !storedSnapshot\n ? \"missing-snapshot\"\n : storedSnapshot.hash !== currentSnapshot.hash && plan.statements.length > 0\n ? \"migration-pending\"\n : storedSnapshot.hash !== currentSnapshot.hash\n ? \"snapshot-outdated\"\n : \"clean\";\n return {\n currentSnapshot,\n storedSnapshot,\n drift: {\n state,\n currentSchemaHash: currentSnapshot.hash,\n storedSchemaHash: storedSnapshot?.hash ?? null,\n statements: plan.statements,\n warnings: plan.warnings,\n destructiveChanges: plan.destructiveChanges,\n details:\n state === \"clean\"\n ? \"Local schema snapshot matches the generated Syncore schema.\"\n : describeDriftState(state, plan.statements.length, plan.warnings.length)\n }\n };\n } catch (error) {\n return {\n currentSnapshot: null,\n storedSnapshot: null,\n drift: {\n state: \"unavailable\",\n currentSchemaHash: null,\n storedSchemaHash: null,\n statements: [],\n warnings: [],\n destructiveChanges: [],\n details: `Syncore could not load the generated schema: ${formatError(error)}`\n }\n };\n }\n}\n\nfunction describeDriftState(\n state: DriftState[\"state\"],\n statementCount: number,\n warningCount: number\n): string {\n if (state === \"missing-snapshot\") {\n return \"No stored schema snapshot was found yet.\";\n }\n if (state === \"migration-pending\") {\n return `Schema drift detected with ${statementCount} SQL statement(s) pending and ${warningCount} warning(s).`;\n }\n if (state === \"snapshot-outdated\") {\n return \"The stored schema snapshot differs from the generated schema, but no SQL statements are pending.\";\n }\n if (state === \"destructive\") {\n return \"The current schema diff includes destructive changes that require manual review.\";\n }\n return \"Syncore could not inspect schema drift.\";\n}\n\nfunction buildDiagnostics(input: {\n checks: DoctorCheck[];\n drift: DriftState;\n hasProject: boolean;\n hub: DoctorReport[\"hub\"];\n persistenceDetails?: string;\n projectTarget: DoctorReport[\"projectTarget\"];\n runtimeSignals: RuntimeSignals;\n template: string;\n usesConnectedClients: boolean;\n clientTargets: ClientTargetDescriptor[];\n}): JourneyDiagnostic[] {\n const diagnostics: JourneyDiagnostic[] = [];\n const missingProjectPaths = input.checks.filter(\n (check) => (check.category === \"project\" || check.category === \"schema\") && !check.ok\n );\n diagnostics.push(\n missingProjectPaths.length === 0 && input.hasProject\n ? {\n id: \"project.structure\",\n category: \"project\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Syncore project structure is present.\",\n details: \"Core project files are available in this directory.\",\n canAutoFix: false\n }\n : {\n id: \"project.structure\",\n category: \"project\",\n severity: \"error\",\n status: \"fail\",\n summary: \"Syncore project structure is incomplete or missing.\",\n details:\n missingProjectPaths.length > 0\n ? `Missing: ${missingProjectPaths.map((check) => check.path).join(\", \")}.`\n : \"This directory does not contain a full Syncore project yet.\",\n suggestedAction: \"Run `npx syncorejs init` or restore the missing project files.\",\n canAutoFix: false\n }\n );\n\n const missingGenerated = input.checks.filter(\n (check) => check.category === \"generated\" && !check.ok\n );\n diagnostics.push(\n missingGenerated.length === 0\n ? {\n id: \"generated.files\",\n category: \"generated\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Generated Syncore files are present.\",\n details: \"syncore/_generated looks available for runtime and type-driven tooling.\",\n canAutoFix: false\n }\n : {\n id: \"generated.files\",\n category: \"generated\",\n severity: \"error\",\n status: \"fail\",\n summary: \"Generated Syncore files are missing.\",\n details: `Missing: ${missingGenerated.map((check) => check.path).join(\", \")}.`,\n suggestedAction: \"Run `npx syncorejs codegen` or `npx syncorejs doctor --fix`.\",\n canAutoFix: true,\n fixCommand: \"npx syncorejs doctor --fix\"\n }\n );\n\n diagnostics.push(buildSchemaDiagnostic(input.drift));\n\n diagnostics.push(\n input.projectTarget\n ? {\n id: \"persistence.project-target\",\n category: \"persistence\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Project target persistence is configured.\",\n ...(input.persistenceDetails ? { details: input.persistenceDetails } : {}),\n canAutoFix: false\n }\n : input.usesConnectedClients\n ? {\n id: \"persistence.project-target\",\n category: \"persistence\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Persistence is client-managed for this template.\",\n details:\n \"This app template expects a connected client runtime to provide local storage and runtime state.\",\n canAutoFix: false\n }\n : {\n id: \"persistence.project-target\",\n category: \"persistence\",\n severity: \"error\",\n status: \"fail\",\n summary: \"No local project target is configured.\",\n details:\n input.persistenceDetails ??\n \"Syncore could not resolve a project target database and storage directory.\",\n suggestedAction:\n \"Check syncore.config.ts and make sure projectTarget.databasePath and projectTarget.storageDirectory are valid.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(\n input.hub.running\n ? {\n id: \"hub.devtools\",\n category: \"hub\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Local devtools hub is running.\",\n details: `Devtools: ${input.hub.url}. Dashboard: ${input.hub.dashboardUrl}.`,\n canAutoFix: false\n }\n : {\n id: \"hub.devtools\",\n category: \"hub\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"Local devtools hub is not running.\",\n details: `Expected devtools endpoint: ${input.hub.url}.`,\n suggestedAction: \"Run `npx syncorejs dev` to start the local hub and dashboard.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(\n input.hub.dashboardRunning\n ? {\n id: \"hub.dashboard\",\n category: \"hub\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Dashboard shell is responding.\",\n details: input.hub.dashboardUrl,\n canAutoFix: false\n }\n : {\n id: \"hub.dashboard\",\n category: \"hub\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"Dashboard shell is not responding yet.\",\n details: `Expected dashboard URL: ${input.hub.dashboardUrl}.`,\n suggestedAction: \"Run `npx syncorejs dev` or inspect whether the dashboard port is already taken.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(\n input.usesConnectedClients\n ? input.clientTargets.length > 0\n ? {\n id: \"client.runtime\",\n category: \"client\",\n severity: \"info\",\n status: \"pass\",\n summary: \"At least one client runtime is connected.\",\n details: `Connected targets: ${input.clientTargets.map((target) => target.id).join(\", \")}.`,\n canAutoFix: false\n }\n : {\n id: \"client.runtime\",\n category: \"client\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"This template is waiting for a connected client runtime.\",\n details:\n \"Syncore is ready to inspect or operate on your app once a browser tab, worker, Electron shell, or Expo runtime connects.\",\n suggestedAction:\n \"Start your app host, then run `npx syncorejs targets` to inspect connected client targets.\",\n canAutoFix: false\n }\n : {\n id: \"client.runtime\",\n category: \"client\",\n severity: \"info\",\n status: \"pass\",\n summary: \"This template does not require a connected client runtime.\",\n canAutoFix: false\n }\n );\n\n diagnostics.push(buildRuntimeDiagnostic(input.runtimeSignals));\n\n return diagnostics;\n}\n\nfunction buildSchemaDiagnostic(drift: DriftState): JourneyDiagnostic {\n if (drift.state === \"clean\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Schema snapshot is in sync.\",\n ...(drift.details ? { details: drift.details } : {}),\n canAutoFix: false\n };\n }\n if (drift.state === \"destructive\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"error\",\n status: \"fail\",\n summary: \"Schema drift includes destructive changes.\",\n details: drift.destructiveChanges.join(\"; \"),\n suggestedAction:\n \"Review the schema change manually and create or edit a migration before continuing.\",\n canAutoFix: false\n };\n }\n if (drift.state === \"missing-snapshot\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"No stored schema snapshot was found.\",\n ...(drift.details ? { details: drift.details } : {}),\n suggestedAction:\n \"Run `npx syncorejs doctor --fix` to refresh the snapshot, or generate a migration if you intend to persist the change.\",\n canAutoFix: true,\n fixCommand: \"npx syncorejs doctor --fix\"\n };\n }\n if (drift.state === \"snapshot-outdated\" || drift.state === \"migration-pending\") {\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"warning\",\n status: \"warn\",\n summary:\n drift.state === \"migration-pending\"\n ? \"Schema drift has pending migration statements.\"\n : \"Stored schema snapshot differs from the generated schema.\",\n ...(drift.details ? { details: drift.details } : {}),\n suggestedAction:\n drift.state === \"migration-pending\"\n ? \"Run `npx syncorejs migrate status` to inspect the diff, then `npx syncorejs doctor --fix` only if you just want to refresh the stored snapshot.\"\n : \"Run `npx syncorejs doctor --fix` to refresh the stored snapshot safely.\",\n canAutoFix: true,\n fixCommand: \"npx syncorejs doctor --fix\"\n };\n }\n return {\n id: \"schema.drift\",\n category: \"schema\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"Schema drift could not be inspected yet.\",\n ...(drift.details ? { details: drift.details } : {}),\n suggestedAction:\n \"Restore generated files or rerun `npx syncorejs codegen`, then run `npx syncorejs doctor` again.\",\n canAutoFix: false\n };\n}\n\nfunction buildRuntimeDiagnostic(runtimeSignals: RuntimeSignals): JourneyDiagnostic {\n if (runtimeSignals.sessionState === \"invalid\") {\n return {\n id: \"runtime.session\",\n category: \"runtime\",\n severity: \"warning\",\n status: \"warn\",\n summary: \"The saved devtools session file is invalid.\",\n details: runtimeSignals.sessionPath,\n suggestedAction:\n \"Restart `npx syncorejs dev` to regenerate the session state for the local hub.\",\n canAutoFix: false\n };\n }\n if (runtimeSignals.logEntryCount === 0) {\n return {\n id: \"runtime.signals\",\n category: \"runtime\",\n severity: \"info\",\n status: \"pass\",\n summary: \"No recent runtime signals were recorded yet.\",\n details: runtimeSignals.logFilePresent\n ? \"The runtime log file exists but has no recorded entries yet.\"\n : \"No runtime log file has been created yet.\",\n canAutoFix: false\n };\n }\n const latest = runtimeSignals.recent[runtimeSignals.recent.length - 1];\n return {\n id: \"runtime.signals\",\n category: \"runtime\",\n severity: \"info\",\n status: \"pass\",\n summary: \"Recent runtime signals are available.\",\n ...(latest\n ? {\n details: `Latest: ${latest.category} on ${latest.targetId} at ${new Date(latest.timestamp).toISOString()}: ${latest.message}`\n }\n : {}),\n canAutoFix: false\n };\n}\n\nfunction resolvePrimaryIssue(input: {\n checks: DoctorCheck[];\n diagnostics: JourneyDiagnostic[];\n drift: DriftState;\n hasProject: boolean;\n hubRunning: boolean;\n usesConnectedClients: boolean;\n clientTargets: ClientTargetDescriptor[];\n workspaceMatches: WorkspaceProjectMatch[];\n}): DoctorPrimaryIssue {\n if (!input.hasProject && input.workspaceMatches.length > 0) {\n return {\n code: \"workspace-root\",\n summary: \"You are at a workspace root, not inside a Syncore app package.\",\n details: `Found ${input.workspaceMatches.length} Syncore package(s) under this workspace.`,\n impact: \"Project-specific diagnostics and runtime operations are ambiguous from the workspace root.\",\n suggestedAction: `Run the command with --cwd ${input.workspaceMatches[0]!.relativePath} or change into that package directory.`\n };\n }\n\n const missingProjectPaths = input.checks.filter(\n (check) => (check.category === \"project\" || check.category === \"schema\") && !check.ok\n );\n if (!input.hasProject || missingProjectPaths.length > 0) {\n return {\n code: \"missing-project\",\n summary: \"Syncore project files are missing or incomplete.\",\n details:\n missingProjectPaths.length > 0\n ? `Missing: ${missingProjectPaths.map((check) => check.path).join(\", \")}.`\n : \"This directory does not contain a complete Syncore project yet.\",\n impact: \"The CLI cannot bootstrap the local runtime or inspect schema and persistence reliably.\",\n suggestedAction: \"Run `npx syncorejs init` or restore the missing project files.\"\n };\n }\n\n const missingGenerated = input.checks.filter(\n (check) => check.category === \"generated\" && !check.ok\n );\n if (missingGenerated.length > 0) {\n return {\n code: \"missing-generated\",\n summary: \"Generated Syncore files are missing.\",\n details: `Missing: ${missingGenerated.map((check) => check.path).join(\", \")}.`,\n impact: \"Type-driven runtime loading and schema inspection may be stale or unavailable.\",\n suggestedAction: \"Run `npx syncorejs doctor --fix` or `npx syncorejs codegen`.\"\n };\n }\n\n if (input.drift.state === \"destructive\") {\n return {\n code: \"schema-destructive-drift\",\n summary: \"Schema drift is blocked by destructive changes.\",\n details: input.drift.destructiveChanges.join(\"; \"),\n impact: \"Syncore cannot safely advance the local schema automatically.\",\n suggestedAction: \"Review the schema change manually and generate a migration before continuing.\"\n };\n }\n\n if (input.usesConnectedClients && input.clientTargets.length === 0) {\n return {\n code: \"waiting-for-client\",\n summary: \"This app is waiting for a connected local runtime.\",\n details:\n input.hubRunning\n ? \"Client-managed templates only become fully operational after the app host connects to the local Syncore hub.\"\n : \"This template depends on a client-managed runtime, and no app runtime is connected yet.\",\n impact: \"Worker, bridge IPC, storage, and client-side data inspection stay unavailable until a runtime connects.\",\n suggestedAction:\n input.hubRunning\n ? \"Start your app host, then run `npx syncorejs targets` to inspect connected runtimes.\"\n : \"Run `npx syncorejs dev`, start your app host, then run `npx syncorejs targets` to inspect connected runtimes.\"\n };\n }\n\n if (\n input.drift.state === \"missing-snapshot\" ||\n input.drift.state === \"snapshot-outdated\" ||\n input.drift.state === \"migration-pending\"\n ) {\n return {\n code: \"schema-drift\",\n summary: \"The local schema snapshot is out of sync.\",\n details: input.drift.details ?? \"Schema drift was detected.\",\n impact: \"The local dev loop can become confusing because the stored snapshot no longer matches the generated schema.\",\n suggestedAction:\n input.drift.state === \"migration-pending\"\n ? \"Run `npx syncorejs migrate status` to inspect the diff, then use `npx syncorejs doctor --fix` if you only need to refresh the stored snapshot.\"\n : \"Run `npx syncorejs doctor --fix` to refresh the stored snapshot safely.\"\n };\n }\n\n if (!input.hubRunning) {\n return {\n code: \"hub-down\",\n summary: \"The local devtools hub is not running.\",\n details: \"Syncore can inspect project state, but runtime and client diagnostics are limited until the hub starts.\",\n impact: \"Commands that depend on live targets, logs, or IPC visibility will have reduced signal.\",\n suggestedAction: \"Run `npx syncorejs dev` to start the local hub.\"\n };\n }\n\n return {\n code: \"ready\",\n summary: \"Syncore is ready for the local development loop.\",\n details: \"Project structure, generated files, schema state, and runtime prerequisites look healthy.\",\n impact: \"You can use `syncorejs dev`, inspect targets, and operate on the local runtime.\",\n suggestedAction: \"Run `npx syncorejs dev` to keep codegen, schema, and the local hub in sync.\"\n };\n}\n\nfunction collectSuggestions(\n primaryIssue: DoctorPrimaryIssue,\n diagnostics: JourneyDiagnostic[],\n workspaceMatches: WorkspaceProjectMatch[]\n): string[] {\n const suggestions = new Set<string>();\n if (primaryIssue.suggestedAction) {\n suggestions.add(primaryIssue.suggestedAction);\n }\n if (primaryIssue.code === \"workspace-root\" && workspaceMatches.length > 0) {\n suggestions.add(\n `Run the command with --cwd ${workspaceMatches[0]!.relativePath} or change into a package directory.`\n );\n }\n for (const diagnostic of diagnostics) {\n if (diagnostic.status === \"pass\") {\n continue;\n }\n if (diagnostic.suggestedAction) {\n suggestions.add(diagnostic.suggestedAction);\n }\n }\n return [...suggestions];\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["export type CliErrorCategory =\n | \"usage\"\n | \"context\"\n | \"validation\"\n | \"target\"\n | \"hub\"\n | \"runtime\"\n | \"system\";\n\nexport interface CliErrorOptions {\n exitCode?: number;\n category?: CliErrorCategory;\n details?: unknown;\n nextSteps?: string[];\n}\n\nexport class CliError extends Error {\n readonly exitCode: number;\n readonly category: CliErrorCategory;\n readonly details: unknown;\n readonly nextSteps: string[] | undefined;\n\n constructor(message: string, options: CliErrorOptions = {}) {\n super(message);\n this.exitCode = options.exitCode ?? 1;\n this.category = options.category ?? \"system\";\n this.details = options.details;\n this.nextSteps = options.nextSteps;\n }\n}\n\nexport function normalizeCliError(error: unknown): CliError {\n if (error instanceof CliError) {\n return error;\n }\n\n return new CliError(error instanceof Error ? error.message : String(error));\n}\n"],"mappings":";AAgBA,IAAa,WAAb,cAA8B,MAAM;CAClC;CACA;CACA;CACA;CAEA,YAAY,SAAiB,UAA2B,EAAE,EAAE;AAC1D,QAAM,QAAQ;AACd,OAAK,WAAW,QAAQ,YAAY;AACpC,OAAK,WAAW,QAAQ,YAAY;AACpC,OAAK,UAAU,QAAQ;AACvB,OAAK,YAAY,QAAQ;;;AAI7B,SAAgB,kBAAkB,OAA0B;AAC1D,KAAI,iBAAiB,SACnB,QAAO;AAGT,QAAO,IAAI,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["export type CliErrorCategory =\n | \"usage\"\n | \"context\"\n | \"validation\"\n | \"target\"\n | \"hub\"\n | \"runtime\"\n | \"system\";\n\nexport interface CliErrorOptions {\n exitCode?: number;\n category?: CliErrorCategory;\n details?: unknown;\n nextSteps?: string[];\n}\n\nexport class CliError extends Error {\n readonly exitCode: number;\n readonly category: CliErrorCategory;\n readonly details: unknown;\n readonly nextSteps: string[] | undefined;\n\n constructor(message: string, options: CliErrorOptions = {}) {\n super(message);\n this.exitCode = options.exitCode ?? 1;\n this.category = options.category ?? \"system\";\n this.details = options.details;\n this.nextSteps = options.nextSteps;\n }\n}\n\nexport function normalizeCliError(error: unknown): CliError {\n if (error instanceof CliError) {\n return error;\n }\n\n return new CliError(error instanceof Error ? error.message : String(error));\n}\n"],"mappings":";AAgBA,IAAa,WAAb,cAA8B,MAAM;CAClC;CACA;CACA;CACA;CAEA,YAAY,SAAiB,UAA2B,CAAC,GAAG;EAC1D,MAAM,OAAO;EACb,KAAK,WAAW,QAAQ,YAAY;EACpC,KAAK,WAAW,QAAQ,YAAY;EACpC,KAAK,UAAU,QAAQ;EACvB,KAAK,YAAY,QAAQ;CAC3B;AACF;AAEA,SAAgB,kBAAkB,OAA0B;CAC1D,IAAI,iBAAiB,UACnB,OAAO;CAGT,OAAO,IAAI,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAC5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"help.mjs","names":[],"sources":["../src/help.ts"],"sourcesContent":["import type { Command } from \"commander\";\n\nimport { CLI_VERSION } from \"./preflight.js\";\n\nconst ROOT_DESCRIPTION = [\n \"Local-first product CLI for Syncore projects.\"\n].join(\"\\n\");\n\nconst ROOT_HELP_AFTER = [\n \"\",\n \"Command groups:\",\n \" Setup: init, dev, codegen, migrate\",\n \" Inspect: doctor, targets, logs\",\n \" Operate: run, data, import, export\",\n \" Reference: dashboard, docs\",\n \"\",\n \"Examples:\",\n \" npx syncorejs dev\",\n \" npx syncorejs targets\",\n \" npx syncorejs run tasks/list --target project\",\n \" npx syncorejs run tasks/list --target 10427\",\n \" npx syncorejs data tasks --target project\",\n \" npx syncorejs logs --target all --watch\"\n].join(\"\\n\");\n\nexport function applyRootHelp(program: Command): void {\n program\n .description(ROOT_DESCRIPTION)\n .version(CLI_VERSION)\n .addHelpText(\"after\", ROOT_HELP_AFTER);\n}\n"],"mappings":";;AAIA,MAAM,mBAAmB,CACvB,gDACD,CAAC,KAAK,KAAK;AAEZ,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC,KAAK,KAAK;AAEZ,SAAgB,cAAc,SAAwB;AACpD,SACG,YAAY,iBAAiB,CAC7B,QAAQ,YAAY,CACpB,YAAY,SAAS,gBAAgB"}
1
+ {"version":3,"file":"help.mjs","names":[],"sources":["../src/help.ts"],"sourcesContent":["import type { Command } from \"commander\";\n\nimport { CLI_VERSION } from \"./preflight.js\";\n\nconst ROOT_DESCRIPTION = [\n \"Local-first product CLI for Syncore projects.\"\n].join(\"\\n\");\n\nconst ROOT_HELP_AFTER = [\n \"\",\n \"Command groups:\",\n \" Setup: init, dev, codegen, migrate\",\n \" Inspect: doctor, targets, logs\",\n \" Operate: run, data, import, export\",\n \" Reference: dashboard, docs\",\n \"\",\n \"Examples:\",\n \" npx syncorejs dev\",\n \" npx syncorejs targets\",\n \" npx syncorejs run tasks/list --target project\",\n \" npx syncorejs run tasks/list --target 10427\",\n \" npx syncorejs data tasks --target project\",\n \" npx syncorejs logs --target all --watch\"\n].join(\"\\n\");\n\nexport function applyRootHelp(program: Command): void {\n program\n .description(ROOT_DESCRIPTION)\n .version(CLI_VERSION)\n .addHelpText(\"after\", ROOT_HELP_AFTER);\n}\n"],"mappings":";;AAIA,MAAM,mBAAmB,CACvB,+CACF,EAAE,KAAK,IAAI;AAEX,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,EAAE,KAAK,IAAI;AAEX,SAAgB,cAAc,SAAwB;CACpD,QACG,YAAY,gBAAgB,EAC5B,QAAQ,WAAW,EACnB,YAAY,SAAS,eAAe;AACzC"}
@@ -10,9 +10,16 @@ ensureSupportedNodeVersion();
10
10
  function isDirectInvocation(moduleUrl) {
11
11
  const entry = process.argv[1];
12
12
  if (!entry) return false;
13
- return realpathSync(path.resolve(entry)) === realpathSync(path.resolve(fileURLToPath(moduleUrl)));
13
+ if (path.normalize(path.resolve(entry)).toLowerCase().endsWith(path.join("packages", "cli", "src", "index.ts"))) return true;
14
+ try {
15
+ return realpathSync(path.resolve(entry)) === realpathSync(path.resolve(fileURLToPath(moduleUrl)));
16
+ } catch {
17
+ return false;
18
+ }
14
19
  }
15
- if (isDirectInvocation(import.meta.url)) runSyncoreCli().catch((error) => {
20
+ if (isDirectInvocation(import.meta.url)) runSyncoreCli().then(() => {
21
+ process.exit(process.exitCode ?? 0);
22
+ }).catch((error) => {
16
23
  process.nextTick(() => {
17
24
  throw error;
18
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { runSyncoreCli } from \"./app.js\";\nimport { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ensureSupportedNodeVersion, installCliWarningFilters } from \"./preflight.js\";\n\nexport { runSyncoreCli };\n\ninstallCliWarningFilters();\nensureSupportedNodeVersion();\n\nfunction isDirectInvocation(moduleUrl: string): boolean {\n const entry = process.argv[1];\n if (!entry) {\n return false;\n }\n return (\n realpathSync(path.resolve(entry)) ===\n realpathSync(path.resolve(fileURLToPath(moduleUrl)))\n );\n}\n\nif (isDirectInvocation(import.meta.url)) {\n void runSyncoreCli().catch((error) => {\n process.nextTick(() => {\n throw error;\n });\n });\n}\n"],"mappings":";;;;;;;AAUA,0BAA0B;AAC1B,4BAA4B;AAE5B,SAAS,mBAAmB,WAA4B;CACtD,MAAM,QAAQ,QAAQ,KAAK;AAC3B,KAAI,CAAC,MACH,QAAO;AAET,QACE,aAAa,KAAK,QAAQ,MAAM,CAAC,KACjC,aAAa,KAAK,QAAQ,cAAc,UAAU,CAAC,CAAC;;AAIxD,IAAI,mBAAmB,OAAO,KAAK,IAAI,CAChC,gBAAe,CAAC,OAAO,UAAU;AACpC,SAAQ,eAAe;AACrB,QAAM;GACN;EACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { runSyncoreCli } from \"./app.js\";\nimport { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ensureSupportedNodeVersion, installCliWarningFilters } from \"./preflight.js\";\n\nexport { runSyncoreCli };\n\ninstallCliWarningFilters();\nensureSupportedNodeVersion();\n\nfunction isDirectInvocation(moduleUrl: string): boolean {\n const entry = process.argv[1];\n if (!entry) {\n return false;\n }\n\n const normalizedEntry = path.normalize(path.resolve(entry)).toLowerCase();\n if (normalizedEntry.endsWith(path.join(\"packages\", \"cli\", \"src\", \"index.ts\"))) {\n return true;\n }\n\n try {\n return (\n realpathSync(path.resolve(entry)) ===\n realpathSync(path.resolve(fileURLToPath(moduleUrl)))\n );\n } catch {\n return false;\n }\n}\n\nif (isDirectInvocation(import.meta.url)) {\n void runSyncoreCli()\n .then(() => {\n process.exit(process.exitCode ?? 0);\n })\n .catch((error) => {\n process.nextTick(() => {\n throw error;\n });\n });\n}\n"],"mappings":";;;;;;;AAUA,yBAAyB;AACzB,2BAA2B;AAE3B,SAAS,mBAAmB,WAA4B;CACtD,MAAM,QAAQ,QAAQ,KAAK;CAC3B,IAAI,CAAC,OACH,OAAO;CAIT,IADwB,KAAK,UAAU,KAAK,QAAQ,KAAK,CAAC,EAAE,YAC1C,EAAE,SAAS,KAAK,KAAK,YAAY,OAAO,OAAO,UAAU,CAAC,GAC1E,OAAO;CAGT,IAAI;EACF,OACE,aAAa,KAAK,QAAQ,KAAK,CAAC,MAChC,aAAa,KAAK,QAAQ,cAAc,SAAS,CAAC,CAAC;CAEvD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,IAAI,mBAAmB,OAAO,KAAK,GAAG,GACpC,cAAmB,EAChB,WAAW;CACV,QAAQ,KAAK,QAAQ,YAAY,CAAC;AACpC,CAAC,EACA,OAAO,UAAU;CAChB,QAAQ,eAAe;EACrB,MAAM;CACR,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"messages.mjs","names":["templateUsesConnectedClients","coreTemplateUsesConnectedClients"],"sources":["../src/messages.ts"],"sourcesContent":["import {\n type SyncoreTemplateName,\n templateUsesConnectedClients as coreTemplateUsesConnectedClients\n} from \"@syncore/core/cli\";\n\nexport function buildInitNextSteps(template: SyncoreTemplateName): string[] {\n if (templateUsesConnectedClients(template)) {\n return [\n \"Run `npx syncorejs dev` to start the hub and keep generated code in sync.\",\n \"After your app connects, run `npx syncorejs targets` to inspect connected client targets.\"\n ];\n }\n\n return [\n \"Run `npx syncorejs dev` to start the local loop.\",\n \"Operational commands default to `project` when it is the only target.\"\n ];\n}\n\nexport function buildDevBootstrapNextSteps(): string[] {\n return [\n \"Run `npx syncorejs dashboard --open` to inspect the dashboard.\",\n \"Run `npx syncorejs targets` to inspect available targets.\",\n \"Run `npx syncorejs doctor` to inspect project health.\"\n ];\n}\n\nexport function buildTargetCommandNextSteps(targetId?: string): string[] {\n if (targetId) {\n return [`Use \\`npx syncorejs run --target ${targetId} <function>\\` to operate on a specific target.`];\n }\n return [\n \"Run `npx syncorejs dev` and connect an app runtime, or define a projectTarget for Node/Electron projects.\"\n ];\n}\n\nexport function buildSelectTargetNextSteps(): string[] {\n return [\n \"Run `npx syncorejs targets` to inspect the available targets.\",\n \"Rerun the command with `--target <id>` to choose one explicitly.\"\n ];\n}\n\nexport function buildHubUnavailableNextSteps(): string[] {\n return [\n \"Run `npx syncorejs dev` to start the local devtools hub.\",\n \"Then rerun `npx syncorejs targets` to confirm the available targets.\"\n ];\n}\n\nexport function buildNoTargetsNextSteps(): string[] {\n return [\n \"Run `npx syncorejs dev` to start the local hub.\",\n \"Then run `npx syncorejs targets` to inspect the available targets.\"\n ];\n}\n\nexport function templateUsesConnectedClients(template: string): boolean {\n return coreTemplateUsesConnectedClients(template as SyncoreTemplateName);\n}\n"],"mappings":";;AAKA,SAAgB,mBAAmB,UAAyC;AAC1E,KAAIA,+BAA6B,SAAS,CACxC,QAAO,CACL,6EACA,4FACD;AAGH,QAAO,CACL,oDACA,wEACD;;AAGH,SAAgB,6BAAuC;AACrD,QAAO;EACL;EACA;EACA;EACD;;AAGH,SAAgB,4BAA4B,UAA6B;AACvE,KAAI,SACF,QAAO,CAAC,oCAAoC,SAAS,gDAAgD;AAEvG,QAAO,CACL,4GACD;;AAGH,SAAgB,6BAAuC;AACrD,QAAO,CACL,iEACA,mEACD;;AAGH,SAAgB,+BAAyC;AACvD,QAAO,CACL,4DACA,uEACD;;AAGH,SAAgB,0BAAoC;AAClD,QAAO,CACL,mDACA,qEACD;;AAGH,SAAgBA,+BAA6B,UAA2B;AACtE,QAAOC,6BAAiC,SAAgC"}
1
+ {"version":3,"file":"messages.mjs","names":["templateUsesConnectedClients","coreTemplateUsesConnectedClients"],"sources":["../src/messages.ts"],"sourcesContent":["import {\n type SyncoreTemplateName,\n templateUsesConnectedClients as coreTemplateUsesConnectedClients\n} from \"@syncore/core/cli\";\n\nexport function buildInitNextSteps(template: SyncoreTemplateName): string[] {\n if (templateUsesConnectedClients(template)) {\n return [\n \"Run `npx syncorejs dev` to start the hub and keep generated code in sync.\",\n \"After your app connects, run `npx syncorejs targets` to inspect connected client targets.\"\n ];\n }\n\n return [\n \"Run `npx syncorejs dev` to start the local loop.\",\n \"Operational commands default to `project` when it is the only target.\"\n ];\n}\n\nexport function buildDevBootstrapNextSteps(): string[] {\n return [\n \"Run `npx syncorejs dashboard --open` to inspect the dashboard.\",\n \"Run `npx syncorejs targets` to inspect available targets.\",\n \"Run `npx syncorejs doctor` to inspect project health.\"\n ];\n}\n\nexport function buildTargetCommandNextSteps(targetId?: string): string[] {\n if (targetId) {\n return [`Use \\`npx syncorejs run --target ${targetId} <function>\\` to operate on a specific target.`];\n }\n return [\n \"Run `npx syncorejs dev` and connect an app runtime, or define a projectTarget for Node/Electron projects.\"\n ];\n}\n\nexport function buildSelectTargetNextSteps(): string[] {\n return [\n \"Run `npx syncorejs targets` to inspect the available targets.\",\n \"Rerun the command with `--target <id>` to choose one explicitly.\"\n ];\n}\n\nexport function buildHubUnavailableNextSteps(): string[] {\n return [\n \"Run `npx syncorejs dev` to start the local devtools hub.\",\n \"Then rerun `npx syncorejs targets` to confirm the available targets.\"\n ];\n}\n\nexport function buildNoTargetsNextSteps(): string[] {\n return [\n \"Run `npx syncorejs dev` to start the local hub.\",\n \"Then run `npx syncorejs targets` to inspect the available targets.\"\n ];\n}\n\nexport function templateUsesConnectedClients(template: string): boolean {\n return coreTemplateUsesConnectedClients(template as SyncoreTemplateName);\n}\n"],"mappings":";;AAKA,SAAgB,mBAAmB,UAAyC;CAC1E,IAAIA,+BAA6B,QAAQ,GACvC,OAAO,CACL,6EACA,2FACF;CAGF,OAAO,CACL,oDACA,uEACF;AACF;AAEA,SAAgB,6BAAuC;CACrD,OAAO;EACL;EACA;EACA;CACF;AACF;AAEA,SAAgB,4BAA4B,UAA6B;CACvE,IAAI,UACF,OAAO,CAAC,oCAAoC,SAAS,+CAA+C;CAEtG,OAAO,CACL,2GACF;AACF;AAEA,SAAgB,6BAAuC;CACrD,OAAO,CACL,iEACA,kEACF;AACF;AAEA,SAAgB,+BAAyC;CACvD,OAAO,CACL,4DACA,sEACF;AACF;AAEA,SAAgB,0BAAoC;CAClD,OAAO,CACL,mDACA,oEACF;AACF;AAEA,SAAgBA,+BAA6B,UAA2B;CACtE,OAAOC,6BAAiC,QAA+B;AACzE"}
@@ -1 +1 @@
1
- {"version":3,"file":"preflight.mjs","names":[],"sources":["../src/preflight.ts"],"sourcesContent":["import process from \"node:process\";\n\nconst MINIMUM_NODE_MAJOR = 22;\n\nexport const CLI_VERSION = \"0.1.0\";\n\nexport function installCliWarningFilters(): void {\n const originalEmitWarning = process.emitWarning.bind(process);\n const originalEmit = process.emit.bind(process);\n\n function shouldSuppressSQLiteWarning(warning: unknown): boolean {\n const message =\n typeof warning === \"string\"\n ? warning\n : warning instanceof Error\n ? warning.message\n : String(warning);\n return /SQLite is an experimental feature/i.test(message);\n }\n\n process.emitWarning = ((warning: string | Error, ...args: unknown[]) => {\n if (shouldSuppressSQLiteWarning(warning)) {\n return;\n }\n\n return (originalEmitWarning as (...input: unknown[]) => void)(warning, ...args);\n }) as typeof process.emitWarning;\n\n process.emit = ((event: string | symbol, ...args: unknown[]) => {\n if (event === \"warning\" && shouldSuppressSQLiteWarning(args[0])) {\n return false;\n }\n return (originalEmit as (...input: unknown[]) => boolean)(event, ...args);\n }) as typeof process.emit;\n}\n\nexport function ensureSupportedNodeVersion(): void {\n const major = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (Number.isNaN(major) || major < MINIMUM_NODE_MAJOR) {\n const message = [\n `Syncore requires Node ${MINIMUM_NODE_MAJOR}+ and detected ${process.versions.node}.`,\n \"Upgrade Node and rerun the command.\",\n \"The Syncore CLI depends on the stable Node 22 runtime surface, including local SQLite support.\"\n ].join(\"\\n\");\n throw new Error(message);\n }\n}\n\n"],"mappings":";;AAEA,MAAM,qBAAqB;AAE3B,MAAa,cAAc;AAE3B,SAAgB,2BAAiC;CAC/C,MAAM,sBAAsB,QAAQ,YAAY,KAAK,QAAQ;CAC7D,MAAM,eAAe,QAAQ,KAAK,KAAK,QAAQ;CAE/C,SAAS,4BAA4B,SAA2B;EAC9D,MAAM,UACJ,OAAO,YAAY,WACf,UACA,mBAAmB,QACjB,QAAQ,UACR,OAAO,QAAQ;AACvB,SAAO,qCAAqC,KAAK,QAAQ;;AAG3D,SAAQ,gBAAgB,SAAyB,GAAG,SAAoB;AACtE,MAAI,4BAA4B,QAAQ,CACtC;AAGF,SAAQ,oBAAsD,SAAS,GAAG,KAAK;;AAGjF,SAAQ,SAAS,OAAwB,GAAG,SAAoB;AAC9D,MAAI,UAAU,aAAa,4BAA4B,KAAK,GAAG,CAC7D,QAAO;AAET,SAAQ,aAAkD,OAAO,GAAG,KAAK;;;AAI7E,SAAgB,6BAAmC;CACjD,MAAM,QAAQ,OAAO,SAAS,QAAQ,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,KAAK,GAAG;AAC7E,KAAI,OAAO,MAAM,MAAM,IAAI,QAAQ,oBAAoB;EACrD,MAAM,UAAU;GACd,yBAAyB,mBAAmB,iBAAiB,QAAQ,SAAS,KAAK;GACnF;GACA;GACD,CAAC,KAAK,KAAK;AACZ,QAAM,IAAI,MAAM,QAAQ"}
1
+ {"version":3,"file":"preflight.mjs","names":[],"sources":["../src/preflight.ts"],"sourcesContent":["import process from \"node:process\";\n\nconst MINIMUM_NODE_MAJOR = 22;\n\nexport const CLI_VERSION = \"0.1.0\";\n\nexport function installCliWarningFilters(): void {\n const originalEmitWarning = process.emitWarning.bind(process);\n const originalEmit = process.emit.bind(process);\n\n function shouldSuppressSQLiteWarning(warning: unknown): boolean {\n const message =\n typeof warning === \"string\"\n ? warning\n : warning instanceof Error\n ? warning.message\n : String(warning);\n return /SQLite is an experimental feature/i.test(message);\n }\n\n process.emitWarning = ((warning: string | Error, ...args: unknown[]) => {\n if (shouldSuppressSQLiteWarning(warning)) {\n return;\n }\n\n return (originalEmitWarning as (...input: unknown[]) => void)(warning, ...args);\n }) as typeof process.emitWarning;\n\n process.emit = ((event: string | symbol, ...args: unknown[]) => {\n if (event === \"warning\" && shouldSuppressSQLiteWarning(args[0])) {\n return false;\n }\n return (originalEmit as (...input: unknown[]) => boolean)(event, ...args);\n }) as typeof process.emit;\n}\n\nexport function ensureSupportedNodeVersion(): void {\n const major = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (Number.isNaN(major) || major < MINIMUM_NODE_MAJOR) {\n const message = [\n `Syncore requires Node ${MINIMUM_NODE_MAJOR}+ and detected ${process.versions.node}.`,\n \"Upgrade Node and rerun the command.\",\n \"The Syncore CLI depends on the stable Node 22 runtime surface, including local SQLite support.\"\n ].join(\"\\n\");\n throw new Error(message);\n }\n}\n\n"],"mappings":";;AAEA,MAAM,qBAAqB;AAE3B,MAAa,cAAc;AAE3B,SAAgB,2BAAiC;CAC/C,MAAM,sBAAsB,QAAQ,YAAY,KAAK,OAAO;CAC5D,MAAM,eAAe,QAAQ,KAAK,KAAK,OAAO;CAE9C,SAAS,4BAA4B,SAA2B;EAC9D,MAAM,UACJ,OAAO,YAAY,WACf,UACA,mBAAmB,QACjB,QAAQ,UACR,OAAO,OAAO;EACtB,OAAO,qCAAqC,KAAK,OAAO;CAC1D;CAEA,QAAQ,gBAAgB,SAAyB,GAAG,SAAoB;EACtE,IAAI,4BAA4B,OAAO,GACrC;EAGF,OAAQ,oBAAsD,SAAS,GAAG,IAAI;CAChF;CAEA,QAAQ,SAAS,OAAwB,GAAG,SAAoB;EAC9D,IAAI,UAAU,aAAa,4BAA4B,KAAK,EAAE,GAC5D,OAAO;EAET,OAAQ,aAAkD,OAAO,GAAG,IAAI;CAC1E;AACF;AAEA,SAAgB,6BAAmC;CACjD,MAAM,QAAQ,OAAO,SAAS,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,MAAM,KAAK,EAAE;CAC5E,IAAI,OAAO,MAAM,KAAK,KAAK,QAAQ,oBAAoB;EACrD,MAAM,UAAU;GACd,yBAAyB,mBAAmB,iBAAiB,QAAQ,SAAS,KAAK;GACnF;GACA;EACF,EAAE,KAAK,IAAI;EACX,MAAM,IAAI,MAAM,OAAO;CACzB;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { VALID_SYNCORE_TEMPLATES, detectProjectTemplate, fileExists, importJsonlIntoProject, isLocalPortInUse, loadProjectConfig, loadProjectFunctions, loadProjectResolvedComponents, loadProjectSchema, resolvePortFromEnv, resolveProjectTargetConfig, runCodegen } from "../core/cli.mjs";
3
+ import { VALID_SYNCORE_TEMPLATES, detectProjectTemplate, fileExists, importJsonlIntoProject, isLocalPortInUse, loadProjectConfig, loadProjectFunctions, loadProjectRuntime, loadProjectSchema, resolvePortFromEnv, resolveProjectTargetConfig, runCodegen } from "../core/cli.mjs";
4
4
  import os from "node:os";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import AdmZip from "adm-zip";
@@ -67,24 +67,23 @@ async function resolveProjectTargetDescriptor(cwd) {
67
67
  };
68
68
  }
69
69
  async function createManagedProjectClient(cwd) {
70
- const [paths, schema, functions, components] = await Promise.all([
71
- requireProjectPaths(cwd),
72
- loadProjectSchema(cwd),
73
- loadRuntimeProjectFunctions(cwd),
74
- loadProjectResolvedComponents(cwd)
75
- ]);
76
- return await createManagedNodeSyncoreClient({
77
- databasePath: paths.databasePath,
78
- storageDirectory: paths.storageDirectory,
79
- schema,
80
- functions,
81
- components,
82
- devtools: false,
83
- platform: "cli"
84
- });
70
+ const paths = await requireProjectPaths(cwd);
71
+ const { schema, functions, components } = await loadProjectRuntime(cwd);
72
+ return {
73
+ ...await createManagedNodeSyncoreClient({
74
+ databasePath: paths.databasePath,
75
+ storageDirectory: paths.storageDirectory,
76
+ schema,
77
+ functions,
78
+ components,
79
+ devtools: false,
80
+ platform: "cli"
81
+ }),
82
+ functions
83
+ };
85
84
  }
86
- async function resolveProjectFunction(cwd, requestedName) {
87
- const functions = await loadRuntimeProjectFunctions(cwd);
85
+ async function resolveProjectFunction(cwd, requestedName, preloadedFunctions) {
86
+ const functions = preloadedFunctions ?? await loadRuntimeProjectFunctions(cwd);
88
87
  const normalizedName = normalizeFunctionName(requestedName, functions);
89
88
  const definition = functions[normalizedName];
90
89
  if (!definition) {
@@ -256,12 +255,13 @@ async function loadImportDocumentBatches(cwd, sourcePath, options = {}) {
256
255
  async function findWorkspaceSyncoreProjects(cwd) {
257
256
  const packageJsonPath = path.join(cwd, "package.json");
258
257
  if (!await fileExists(packageJsonPath)) return [];
259
- let workspaces = [];
258
+ let packageJson;
260
259
  try {
261
- workspaces = JSON.parse(await readFile(packageJsonPath, "utf8")).workspaces ?? [];
260
+ packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
262
261
  } catch {
263
262
  return [];
264
263
  }
264
+ const workspaces = packageJson.workspaces ?? [];
265
265
  const directories = /* @__PURE__ */ new Set();
266
266
  for (const workspace of workspaces) {
267
267
  const prefix = workspace.replace(/\/\*+$/, "");