syncorejs 0.2.1 → 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.
- package/README.md +2 -1
- package/dist/_vendor/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +330 -46
- package/dist/_vendor/cli/app.mjs.map +1 -1
- package/dist/_vendor/cli/context.mjs +27 -9
- package/dist/_vendor/cli/context.mjs.map +1 -1
- package/dist/_vendor/cli/dev-session.mjs.map +1 -1
- package/dist/_vendor/cli/doctor.mjs +513 -46
- package/dist/_vendor/cli/doctor.mjs.map +1 -1
- package/dist/_vendor/cli/errors.mjs.map +1 -1
- package/dist/_vendor/cli/help.mjs.map +1 -1
- package/dist/_vendor/cli/index.mjs +9 -2
- package/dist/_vendor/cli/index.mjs.map +1 -1
- package/dist/_vendor/cli/messages.mjs +5 -4
- package/dist/_vendor/cli/messages.mjs.map +1 -1
- package/dist/_vendor/cli/preflight.mjs.map +1 -1
- package/dist/_vendor/cli/project.mjs +125 -27
- package/dist/_vendor/cli/project.mjs.map +1 -1
- package/dist/_vendor/cli/render.mjs +57 -9
- package/dist/_vendor/cli/render.mjs.map +1 -1
- package/dist/_vendor/cli/targets.mjs +4 -3
- package/dist/_vendor/cli/targets.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts +20 -4
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +458 -133
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/devtools-auth.mjs +60 -0
- package/dist/_vendor/core/devtools-auth.mjs.map +1 -0
- package/dist/_vendor/core/index.d.mts +5 -3
- package/dist/_vendor/core/index.mjs +22 -2
- package/dist/_vendor/core/index.mjs.map +1 -1
- package/dist/_vendor/core/runtime/components.d.mts +111 -0
- package/dist/_vendor/core/runtime/components.d.mts.map +1 -0
- package/dist/_vendor/core/runtime/components.mjs +186 -0
- package/dist/_vendor/core/runtime/components.mjs.map +1 -0
- package/dist/_vendor/core/runtime/devtools.d.mts +4 -4
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +178 -60
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +398 -16
- package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs +74 -3
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/id.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +83 -0
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +720 -0
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +234 -0
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +255 -0
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +200 -0
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +252 -0
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +145 -0
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +221 -0
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs +32 -0
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs +61 -0
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +41 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -0
- package/dist/_vendor/core/runtime/runtime.d.mts +1187 -202
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +73 -1365
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts +113 -0
- package/dist/_vendor/core/transport.d.mts.map +1 -0
- package/dist/_vendor/core/transport.mjs +428 -0
- package/dist/_vendor/core/transport.mjs.map +1 -0
- package/dist/_vendor/devtools-protocol/index.d.ts +187 -4
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- package/dist/_vendor/devtools-protocol/index.js +25 -9
- package/dist/_vendor/devtools-protocol/index.js.map +1 -1
- package/dist/_vendor/next/config.d.ts +3 -4
- package/dist/_vendor/next/config.d.ts.map +1 -1
- package/dist/_vendor/next/config.js +37 -19
- package/dist/_vendor/next/config.js.map +1 -1
- package/dist/_vendor/next/index.d.ts +109 -29
- package/dist/_vendor/next/index.d.ts.map +1 -1
- package/dist/_vendor/next/index.js +104 -26
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +156 -37
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +80 -12
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-expo/react.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/react.js +11 -10
- package/dist/_vendor/platform-expo/react.js.map +1 -1
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
- package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-node/index.d.mts +192 -24
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +236 -97
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs +15 -2
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc.d.mts +11 -35
- package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc.mjs +3 -273
- package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +43 -1
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
- package/dist/_vendor/platform-web/external-change.js +32 -1
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +323 -51
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +233 -30
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
- package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.js +10 -0
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.d.ts +13 -0
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +12 -0
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +54 -0
- package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
- package/dist/_vendor/platform-web/persistence.js +15 -0
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.d.ts +1 -2
- package/dist/_vendor/platform-web/react.d.ts.map +1 -1
- package/dist/_vendor/platform-web/react.js +27 -13
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/platform-web/sqljs.js +10 -1
- package/dist/_vendor/platform-web/sqljs.js.map +1 -1
- package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
- package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
- package/dist/_vendor/platform-web/worker.d.ts +71 -44
- package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
- package/dist/_vendor/platform-web/worker.js +40 -271
- package/dist/_vendor/platform-web/worker.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +222 -23
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +476 -63
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/schema/definition.d.ts +151 -37
- package/dist/_vendor/schema/definition.d.ts.map +1 -1
- package/dist/_vendor/schema/definition.js +102 -20
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/index.d.ts +4 -4
- package/dist/_vendor/schema/index.js +2 -2
- package/dist/_vendor/schema/planner.d.ts +19 -2
- package/dist/_vendor/schema/planner.d.ts.map +1 -1
- package/dist/_vendor/schema/planner.js +79 -3
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.d.ts +279 -83
- package/dist/_vendor/schema/validators.d.ts.map +1 -1
- package/dist/_vendor/schema/validators.js +330 -38
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +245 -19
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +443 -20
- package/dist/_vendor/svelte/index.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/components.d.ts +2 -0
- package/dist/components.js +2 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/package.json +29 -21
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ npx syncorejs dev
|
|
|
18
18
|
## Imports
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
|
-
import { defineSchema, defineTable, query, mutation,
|
|
21
|
+
import { defineSchema, defineTable, query, mutation, s } from "syncorejs";
|
|
22
22
|
import { useQuery, useMutation } from "syncorejs/react";
|
|
23
23
|
import { createBrowserWorkerClient } from "syncorejs/browser";
|
|
24
24
|
import { SyncoreNextProvider } from "syncorejs/next";
|
|
@@ -28,3 +28,4 @@ import { SyncoreNextProvider } from "syncorejs/next";
|
|
|
28
28
|
|
|
29
29
|
- Repository: https://github.com/JPSAUD501/Syncore
|
|
30
30
|
- Quickstarts: https://github.com/JPSAUD501/Syncore/tree/main/docs/quickstarts
|
|
31
|
+
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.mts","names":[],"sources":["../src/app.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"app.d.mts","names":[],"sources":["../src/app.ts"],"mappings":";;;iBAgJsB,aAAA,CAAc,IAAA,cAAsB,OAAO"}
|
package/dist/_vendor/cli/app.mjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { CliContext, openTarget } from "./context.mjs";
|
|
2
2
|
import { printCompactDevPhase, printDevSessionIntro, runShellCommand, withConsoleCapture } from "./dev-session.mjs";
|
|
3
|
-
import { buildRuntimeLookup, connectToProjectHub, createManagedProjectClient, createPublicRuntimeId, exportProjectData, importProjectData, isKnownTemplate, listAvailableTargets, listConnectedClientTargets, listProjectTables, loadImportDocumentBatches, readProjectTable, resolveDashboardUrl, resolveDevtoolsUrl, resolveDocsTarget, resolveProjectFunction, targetSupportsCapability, writeExportData } from "./project.mjs";
|
|
4
|
-
import { buildDevBootstrapNextSteps, buildHubUnavailableNextSteps, buildInitNextSteps, buildTargetCommandNextSteps, templateUsesConnectedClients } from "./messages.mjs";
|
|
5
|
-
import { buildDoctorReport } from "./doctor.mjs";
|
|
3
|
+
import { buildRuntimeLookup, connectToProjectHub, createManagedProjectClient, createPublicRuntimeId, exportProjectData, importProjectData, isKnownTemplate, listAvailableTargets, listConnectedClientTargets, listProjectTables, loadImportDocumentBatches, readProjectTable, resolveActiveDashboardUrl, resolveDashboardUrl, resolveDevtoolsUrl, resolveDocsTarget, resolveProjectFunction, targetSupportsCapability, writeExportData } from "./project.mjs";
|
|
4
|
+
import { buildDevBootstrapNextSteps, buildHubUnavailableNextSteps, buildInitNextSteps, buildTargetCommandNextSteps, templateUsesConnectedClients as templateUsesConnectedClients$1 } from "./messages.mjs";
|
|
5
|
+
import { applyDoctorFixes, buildDoctorReport } from "./doctor.mjs";
|
|
6
6
|
import { applyRootHelp } from "./help.mjs";
|
|
7
|
-
import { printDevReadySummary, printDoctorReport, printTargetsTable, renderOutput } from "./render.mjs";
|
|
7
|
+
import { formatPersistedLogEntry, printDevReadySummary, printDoctorReport, printTargetsTable, renderOutput } from "./render.mjs";
|
|
8
8
|
import { resolveClientRuntime, resolveOperationalTarget } from "./targets.mjs";
|
|
9
9
|
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
10
10
|
import path from "node:path";
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
11
12
|
import { Command } from "commander";
|
|
12
13
|
import { createSchemaSnapshot, diffSchemaSnapshots, renderMigrationSql } from "../core/index.mjs";
|
|
13
|
-
import { VALID_SYNCORE_TEMPLATES, applyProjectMigrations, detectProjectTemplate, formatError, getNextMigrationNumber, hasSyncoreProject, isLocalPortInUse, loadProjectSchema, readStoredSnapshot, resolveRequestedTemplate, runCodegen, runDevProjectBootstrap, scaffoldProject, slugify, startDevHub, writeStoredSnapshot } from "../core/cli.mjs";
|
|
14
|
+
import { VALID_SYNCORE_TEMPLATES, applyProjectMigrations, detectProjectTemplate, fileExists, formatError, getNextMigrationNumber, hasSyncoreProject, isLocalPortInUse, loadProjectSchema, readStoredSnapshot, resolveRequestedTemplate, runCodegen, runDevProjectBootstrap, scaffoldProject, slugify, startDevHub, writeStoredSnapshot } from "../core/cli.mjs";
|
|
14
15
|
//#region src/app.ts
|
|
15
16
|
async function runSyncoreCli(argv = process.argv) {
|
|
16
17
|
const program = buildProgram();
|
|
@@ -91,26 +92,37 @@ function addCodegenCommand(program) {
|
|
|
91
92
|
});
|
|
92
93
|
}
|
|
93
94
|
function addDoctorCommand(program) {
|
|
94
|
-
program.command("doctor").summary("Inspect the current Syncore project state").description("Check project structure, template capabilities, hub state, and available targets.").addHelpText("after", [
|
|
95
|
+
program.command("doctor").summary("Inspect the current Syncore project state").description("Check project structure, template capabilities, hub state, and available targets.").option("--fix", "Apply safe low-risk fixes like codegen and snapshot refresh").addHelpText("after", [
|
|
95
96
|
"",
|
|
96
97
|
"Examples:",
|
|
97
98
|
" npx syncorejs doctor",
|
|
98
|
-
" npx syncorejs doctor --json"
|
|
99
|
-
|
|
99
|
+
" npx syncorejs doctor --json",
|
|
100
|
+
" npx syncorejs doctor --fix"
|
|
101
|
+
].join("\n")).action(async (options, command) => {
|
|
100
102
|
const ctx = createContext(command);
|
|
101
103
|
await executeCommand(ctx, async () => {
|
|
102
|
-
|
|
104
|
+
let report = await buildDoctorReport(ctx.cwd);
|
|
105
|
+
let appliedFixes = [];
|
|
106
|
+
if (options.fix) {
|
|
107
|
+
appliedFixes = await applyDoctorFixes(ctx.cwd, report);
|
|
108
|
+
report = await buildDoctorReport(ctx.cwd);
|
|
109
|
+
}
|
|
103
110
|
if (ctx.json) {
|
|
104
111
|
ctx.printResult({
|
|
105
112
|
command: "doctor",
|
|
106
|
-
|
|
113
|
+
...options.fix && appliedFixes.length > 0 ? { summary: `Applied ${appliedFixes.length} safe fix(es).` } : {},
|
|
114
|
+
data: {
|
|
115
|
+
...report,
|
|
116
|
+
...options.fix ? { appliedFixes } : {}
|
|
117
|
+
}
|
|
107
118
|
});
|
|
108
119
|
return;
|
|
109
120
|
}
|
|
110
|
-
ctx.info(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
ctx.info(report.primaryIssue.summary);
|
|
122
|
+
if (options.fix) if (appliedFixes.length > 0) {
|
|
123
|
+
ctx.success(`Applied ${appliedFixes.length} safe fix(es).`);
|
|
124
|
+
for (const fix of appliedFixes) ctx.info(fix);
|
|
125
|
+
} else ctx.info("No safe fixes were applied.");
|
|
114
126
|
printDoctorReport(report, { verbose: ctx.verbose });
|
|
115
127
|
if (report.workspaceMatches.length > 0) {
|
|
116
128
|
ctx.warn("You appear to be at a workspace root instead of inside an app package.");
|
|
@@ -147,26 +159,31 @@ function addTargetsCommand(program) {
|
|
|
147
159
|
});
|
|
148
160
|
}
|
|
149
161
|
function addDevCommand(program) {
|
|
150
|
-
program.command("dev").summary("Run the Syncore development loop").description("Bootstrap the local Syncore project, start the hub, discover targets, and keep the local workflow in sync.").option("--template <template>", `Template to scaffold when Syncore is missing (${VALID_SYNCORE_TEMPLATES.join(", ")}, or auto)`, "auto").option("--once", "Run bootstrap once and exit").option("--until-success", "Retry bootstrap until it succeeds").option("--run <function>", "Run a Syncore function after bootstrap succeeds").option("--run-sh <command>", "Run a shell command after bootstrap succeeds").option("--open-dashboard", "
|
|
162
|
+
program.command("dev").summary("Run the Syncore development loop").description("Bootstrap the local Syncore project, start the hub, discover targets, and keep the local workflow in sync.").option("--template <template>", `Template to scaffold when Syncore is missing (${VALID_SYNCORE_TEMPLATES.join(", ")}, or auto)`, "auto").option("--once", "Run bootstrap once and exit").option("--until-success", "Retry bootstrap until it succeeds").option("--run <function>", "Run a Syncore function after bootstrap succeeds").option("--run-sh <command>", "Run a shell command after bootstrap succeeds").option("--typecheck <mode>", "Run TypeScript typecheck before entering the local dev loop: enable, try, or disable", "try").option("--tail-logs <mode>", "Control whether runtime logs appear in this terminal: always, errors, or disable", "errors").option("--no-open-dashboard", "Do not open the dashboard automatically after the hub is ready").addHelpText("after", [
|
|
151
163
|
"",
|
|
152
164
|
"Examples:",
|
|
153
165
|
" npx syncorejs dev",
|
|
154
166
|
" npx syncorejs dev --once",
|
|
155
167
|
" npx syncorejs dev --until-success",
|
|
156
168
|
" npx syncorejs dev --run tasks/list",
|
|
157
|
-
" npx syncorejs dev --open-dashboard",
|
|
158
|
-
" npx syncorejs dev --run-sh \"npm run dev\""
|
|
169
|
+
" npx syncorejs dev --no-open-dashboard",
|
|
170
|
+
" npx syncorejs dev --run-sh \"npm run dev\"",
|
|
171
|
+
" npx syncorejs dev --typecheck enable",
|
|
172
|
+
" npx syncorejs dev --tail-logs always"
|
|
159
173
|
].join("\n")).action(async (options, command) => {
|
|
160
174
|
const ctx = createContext(command);
|
|
161
175
|
await executeCommand(ctx, async () => {
|
|
162
176
|
if (options.run && options.runSh) ctx.fail("`syncorejs dev` accepts either --run or --run-sh, not both.");
|
|
163
|
-
const shouldOpenDashboard =
|
|
177
|
+
const shouldOpenDashboard = options.openDashboard ?? true;
|
|
164
178
|
await ensureLocalPortConfiguration(ctx);
|
|
165
179
|
const template = await resolveRequestedTemplate(ctx.cwd, options.template);
|
|
180
|
+
validateDevModes(ctx, options);
|
|
166
181
|
printDevSessionIntro(ctx);
|
|
167
182
|
await ensureDevProjectExists(ctx, template);
|
|
183
|
+
printDevPreflight(ctx, await buildDoctorReport(ctx.cwd));
|
|
184
|
+
const typecheckResult = await runDevTypecheck(ctx, options.typecheck);
|
|
168
185
|
if (options.once) {
|
|
169
|
-
await runDevBootstrapLoop(ctx, template, options.untilSuccess ?? false);
|
|
186
|
+
const bootstrapReport = await runDevBootstrapLoop(ctx, template, options.untilSuccess ?? false, options.tailLogs);
|
|
170
187
|
await runDevFollowup(ctx, options);
|
|
171
188
|
const targets = await listAvailableTargets(ctx.cwd);
|
|
172
189
|
ctx.printResult({
|
|
@@ -179,32 +196,39 @@ function addDevCommand(program) {
|
|
|
179
196
|
projectTargetConfigured: targets.some((target) => target.kind === "project"),
|
|
180
197
|
dashboardUrl: resolveDashboardUrl(),
|
|
181
198
|
devtoolsUrl: resolveDevtoolsUrl(),
|
|
182
|
-
targets
|
|
199
|
+
targets,
|
|
200
|
+
codegenStatus: "refreshed",
|
|
201
|
+
driftStatus: describeDevDriftStatus(bootstrapReport),
|
|
202
|
+
typecheckStatus: describeTypecheckStatus(typecheckResult)
|
|
183
203
|
});
|
|
184
204
|
return;
|
|
185
205
|
}
|
|
186
|
-
await runDevBootstrapLoop(ctx, template, options.untilSuccess ?? false);
|
|
206
|
+
const bootstrapReport = await runDevBootstrapLoop(ctx, template, options.untilSuccess ?? false, options.tailLogs);
|
|
187
207
|
const targets = await listAvailableTargets(ctx.cwd);
|
|
188
208
|
printDevReadySummary(ctx, {
|
|
189
209
|
template,
|
|
190
210
|
projectTargetConfigured: targets.some((target) => target.kind === "project"),
|
|
191
211
|
dashboardUrl: resolveDashboardUrl(),
|
|
192
212
|
devtoolsUrl: resolveDevtoolsUrl(),
|
|
193
|
-
targets
|
|
213
|
+
targets,
|
|
214
|
+
codegenStatus: "refreshed",
|
|
215
|
+
driftStatus: describeDevDriftStatus(bootstrapReport),
|
|
216
|
+
typecheckStatus: describeTypecheckStatus(typecheckResult)
|
|
194
217
|
});
|
|
195
|
-
await startManagedDevHub(ctx, template);
|
|
196
|
-
await
|
|
197
|
-
await monitorLiveDevSession(ctx, template);
|
|
218
|
+
await maybeOpenDashboard(ctx, shouldOpenDashboard, await startManagedDevHub(ctx, template));
|
|
219
|
+
await monitorLiveDevSession(ctx, template, options.tailLogs);
|
|
198
220
|
});
|
|
199
221
|
});
|
|
200
222
|
}
|
|
201
|
-
function
|
|
202
|
-
return context.interactive && Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
203
|
-
}
|
|
204
|
-
async function maybeOpenDashboard(context, shouldOpenDashboard) {
|
|
223
|
+
async function maybeOpenDashboard(context, shouldOpenDashboard, hubSession) {
|
|
205
224
|
if (!shouldOpenDashboard) return;
|
|
206
|
-
|
|
207
|
-
|
|
225
|
+
const targetUrl = hubSession?.authenticatedDashboardUrl ?? await resolveActiveDashboardUrl(context.cwd);
|
|
226
|
+
if (!await waitForDashboardReady(targetUrl)) {
|
|
227
|
+
context.warn("Dashboard did not become ready in time, so it was not opened.");
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (await openTarget(targetUrl)) {
|
|
231
|
+
context.info(`Opened dashboard at ${targetUrl}`);
|
|
208
232
|
return;
|
|
209
233
|
}
|
|
210
234
|
context.warn("Unable to open the dashboard automatically.");
|
|
@@ -291,18 +315,18 @@ function addRunCommand(program) {
|
|
|
291
315
|
const ctx = createContext(command);
|
|
292
316
|
await executeCommand(ctx, async () => {
|
|
293
317
|
if (options.runtime && !options.target) ctx.fail("`syncorejs run --runtime` requires --target.");
|
|
294
|
-
const resolved = await resolveProjectFunction(ctx.cwd, functionName);
|
|
295
318
|
const args = parseJsonObject(argsText, "Function arguments");
|
|
296
|
-
if (options.watch && resolved.definition.kind !== "query") ctx.fail("`syncorejs run --watch` only supports query functions.");
|
|
297
319
|
const target = await resolveOperationalTarget(ctx, options.target, {
|
|
298
320
|
command: "run",
|
|
299
321
|
capability: "run"
|
|
300
322
|
});
|
|
301
323
|
const runtime = resolveClientRuntime(target, options.runtime, { command: "run" });
|
|
302
|
-
ctx.info(options.watch ? `Watching ${resolved.name} on ${target.id}${runtime ? ` (${runtime.id} ${runtime.label})` : ""}.` : `Running ${resolved.name} on ${target.id}${runtime ? ` (${runtime.id} ${runtime.label})` : ""}.`);
|
|
303
324
|
if (target.kind === "project") {
|
|
304
325
|
const managed = await createManagedProjectClient(ctx.cwd);
|
|
305
326
|
try {
|
|
327
|
+
const resolved = await resolveProjectFunction(ctx.cwd, functionName, managed.functions);
|
|
328
|
+
if (options.watch && resolved.definition.kind !== "query") ctx.fail("`syncorejs run --watch` only supports query functions.");
|
|
329
|
+
ctx.info(options.watch ? `Watching ${resolved.name} on ${target.id}.` : `Running ${resolved.name} on ${target.id}.`);
|
|
306
330
|
if (options.watch) {
|
|
307
331
|
const watch = managed.client.watchQuery(resolved.reference, args);
|
|
308
332
|
const render = () => {
|
|
@@ -326,6 +350,9 @@ function addRunCommand(program) {
|
|
|
326
350
|
await managed.dispose();
|
|
327
351
|
}
|
|
328
352
|
}
|
|
353
|
+
const resolved = await resolveProjectFunction(ctx.cwd, functionName);
|
|
354
|
+
if (options.watch && resolved.definition.kind !== "query") ctx.fail("`syncorejs run --watch` only supports query functions.");
|
|
355
|
+
ctx.info(options.watch ? `Watching ${resolved.name} on ${target.id}${runtime ? ` (${runtime.id} ${runtime.label})` : ""}.` : `Running ${resolved.name} on ${target.id}${runtime ? ` (${runtime.id} ${runtime.label})` : ""}.`);
|
|
329
356
|
const hub = await requireHubConnection(ctx);
|
|
330
357
|
try {
|
|
331
358
|
if (options.watch) {
|
|
@@ -395,7 +422,12 @@ function addDataCommand(program) {
|
|
|
395
422
|
data: tables,
|
|
396
423
|
target: target.id
|
|
397
424
|
});
|
|
398
|
-
if (!ctx.json) for (const entry of tables)
|
|
425
|
+
if (!ctx.json) for (const entry of tables) {
|
|
426
|
+
const tableEntry = entry;
|
|
427
|
+
const label = typeof tableEntry.displayName === "string" && tableEntry.displayName.length > 0 && tableEntry.displayName !== tableEntry.name ? `${tableEntry.displayName} -> ${tableEntry.name}` : tableEntry.name;
|
|
428
|
+
const owner = tableEntry.owner === "component" ? ` component:${String(tableEntry.componentPath ?? "unknown")}` : "";
|
|
429
|
+
process.stdout.write(` ${label} (${tableEntry.documentCount} document(s))${owner}\n`);
|
|
430
|
+
}
|
|
399
431
|
return;
|
|
400
432
|
}
|
|
401
433
|
if (target.kind === "project") {
|
|
@@ -506,14 +538,18 @@ function addDashboardCommand(program) {
|
|
|
506
538
|
const ctx = createContext(command);
|
|
507
539
|
await executeCommand(ctx, async () => {
|
|
508
540
|
const url = resolveDashboardUrl();
|
|
541
|
+
const activeUrl = await resolveActiveDashboardUrl(ctx.cwd);
|
|
509
542
|
if (options.open) {
|
|
510
|
-
if (!await openTarget(
|
|
543
|
+
if (!(await waitForDashboardReady(activeUrl) ? await openTarget(activeUrl) : false)) ctx.warn("Unable to open the dashboard automatically.");
|
|
511
544
|
}
|
|
512
545
|
ctx.printResult({
|
|
513
546
|
summary: "Dashboard URL resolved.",
|
|
514
547
|
command: "dashboard",
|
|
515
|
-
data: {
|
|
516
|
-
|
|
548
|
+
data: {
|
|
549
|
+
url: activeUrl,
|
|
550
|
+
baseUrl: url
|
|
551
|
+
},
|
|
552
|
+
nextSteps: [`Open ${activeUrl}`]
|
|
517
553
|
});
|
|
518
554
|
});
|
|
519
555
|
});
|
|
@@ -559,13 +595,15 @@ async function ensureLocalPortConfiguration(context) {
|
|
|
559
595
|
if (Number.isFinite(dashboardPort) && Number.isFinite(devtoolsPort) && dashboardPort === devtoolsPort) context.fail([`Dashboard and devtools cannot share the same port (${dashboardPort}).`, "Set different values for SYNCORE_DASHBOARD_PORT and SYNCORE_DEVTOOLS_PORT, then rerun `npx syncorejs dev`."].join(" "));
|
|
560
596
|
if (Number.isFinite(dashboardPort) && dashboardPort > 0 && Number.isFinite(devtoolsPort) && devtoolsPort > 0 && await isLocalPortInUse(dashboardPort) && !await isLocalPortInUse(devtoolsPort)) context.warn(`Dashboard port ${dashboardPort} is already in use. If Syncore does not start cleanly, set SYNCORE_DASHBOARD_PORT to a different value.`);
|
|
561
597
|
}
|
|
562
|
-
async function runDevBootstrapLoop(context, template, untilSuccess) {
|
|
598
|
+
async function runDevBootstrapLoop(context, template, untilSuccess, tailLogs) {
|
|
563
599
|
while (true) try {
|
|
600
|
+
let sawBootstrapFailure = false;
|
|
564
601
|
printCompactDevPhase(context, "Project");
|
|
565
602
|
printCompactDevPhase(context, "Codegen");
|
|
566
603
|
printCompactDevPhase(context, "Schema");
|
|
567
604
|
await withConsoleCapture((method, message) => {
|
|
568
605
|
if (/destructive schema changes/i.test(message)) {
|
|
606
|
+
sawBootstrapFailure = true;
|
|
569
607
|
context.error("Syncore dev blocked by destructive schema changes.");
|
|
570
608
|
return;
|
|
571
609
|
}
|
|
@@ -573,9 +611,20 @@ async function runDevBootstrapLoop(context, template, untilSuccess) {
|
|
|
573
611
|
context.warn(message.replace(/^Syncore dev warning:\s*/i, ""));
|
|
574
612
|
return;
|
|
575
613
|
}
|
|
576
|
-
if (/bootstrap failed/i.test(message) || method === "error")
|
|
614
|
+
if (/bootstrap failed/i.test(message) || method === "error") {
|
|
615
|
+
sawBootstrapFailure = true;
|
|
616
|
+
context.error(message);
|
|
617
|
+
}
|
|
577
618
|
}, async () => runDevProjectBootstrap(context.cwd, template));
|
|
578
|
-
|
|
619
|
+
const report = await buildDoctorReport(context.cwd);
|
|
620
|
+
if (sawBootstrapFailure || report.status === "schema-destructive-drift") {
|
|
621
|
+
if (tailLogs === "errors") await printRecentRuntimeSignals(context, context.cwd);
|
|
622
|
+
context.fail(report.primaryIssue.summary, 1, report, {
|
|
623
|
+
category: "runtime",
|
|
624
|
+
nextSteps: report.suggestions
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
return report;
|
|
579
628
|
} catch (error) {
|
|
580
629
|
if (!untilSuccess) throw error;
|
|
581
630
|
context.warn(`Syncore dev bootstrap failed, retrying: ${formatError(error)}`);
|
|
@@ -585,7 +634,7 @@ async function runDevBootstrapLoop(context, template, untilSuccess) {
|
|
|
585
634
|
async function startManagedDevHub(context, template) {
|
|
586
635
|
printCompactDevPhase(context, "Hub");
|
|
587
636
|
printCompactDevPhase(context, "Targets");
|
|
588
|
-
await withConsoleCapture((method, message) => {
|
|
637
|
+
return await withConsoleCapture((method, message) => {
|
|
589
638
|
if (/already running/i.test(message)) {
|
|
590
639
|
context.info(message.replaceAll("127.0.0.1", "localhost"));
|
|
591
640
|
return;
|
|
@@ -609,6 +658,28 @@ async function startManagedDevHub(context, template) {
|
|
|
609
658
|
template
|
|
610
659
|
}));
|
|
611
660
|
}
|
|
661
|
+
async function waitForDashboardReady(url, options = {}) {
|
|
662
|
+
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
663
|
+
const intervalMs = options.intervalMs ?? 250;
|
|
664
|
+
const deadline = Date.now() + timeoutMs;
|
|
665
|
+
while (Date.now() < deadline) {
|
|
666
|
+
try {
|
|
667
|
+
const controller = new AbortController();
|
|
668
|
+
const timeout = setTimeout(() => controller.abort(), intervalMs);
|
|
669
|
+
try {
|
|
670
|
+
const response = await fetch(url, {
|
|
671
|
+
signal: controller.signal,
|
|
672
|
+
redirect: "manual"
|
|
673
|
+
});
|
|
674
|
+
if (response.ok || response.status === 304) return true;
|
|
675
|
+
} finally {
|
|
676
|
+
clearTimeout(timeout);
|
|
677
|
+
}
|
|
678
|
+
} catch {}
|
|
679
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
680
|
+
}
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
612
683
|
async function runDevFollowup(context, options) {
|
|
613
684
|
if (options.run) {
|
|
614
685
|
const target = await resolveOperationalTarget(context, void 0, {
|
|
@@ -642,10 +713,13 @@ async function runDevFollowup(context, options) {
|
|
|
642
713
|
}
|
|
643
714
|
if (options.runSh) await runShellCommand(context, options.runSh);
|
|
644
715
|
}
|
|
645
|
-
async function monitorLiveDevSession(context, template) {
|
|
646
|
-
|
|
716
|
+
async function monitorLiveDevSession(context, template, tailLogs) {
|
|
717
|
+
const stopTailing = tailLogs === "always" ? startRuntimeLogTail(context, context.cwd) : void 0;
|
|
718
|
+
if (!templateUsesConnectedClients$1(template)) try {
|
|
647
719
|
await waitForSignal();
|
|
648
720
|
return;
|
|
721
|
+
} finally {
|
|
722
|
+
stopTailing?.();
|
|
649
723
|
}
|
|
650
724
|
let knownTargets = /* @__PURE__ */ new Set();
|
|
651
725
|
let waitingNoticeVisible = false;
|
|
@@ -653,7 +727,10 @@ async function monitorLiveDevSession(context, template) {
|
|
|
653
727
|
const nextTargets = await listConnectedClientTargets();
|
|
654
728
|
const nextIds = new Set(nextTargets.map((target) => target.id));
|
|
655
729
|
for (const target of nextTargets) if (!knownTargets.has(target.id)) context.info(`Client target connected: ${target.id}`);
|
|
656
|
-
for (const targetId of knownTargets) if (!nextIds.has(targetId))
|
|
730
|
+
for (const targetId of knownTargets) if (!nextIds.has(targetId)) {
|
|
731
|
+
context.warn(`Client target disconnected: ${targetId}`);
|
|
732
|
+
if (tailLogs === "errors") await printRecentRuntimeSignals(context, context.cwd);
|
|
733
|
+
}
|
|
657
734
|
if (nextTargets.length === 0 && !waitingNoticeVisible) {
|
|
658
735
|
context.info("Hub ready. Start your app to connect a client target.");
|
|
659
736
|
waitingNoticeVisible = true;
|
|
@@ -668,6 +745,157 @@ async function monitorLiveDevSession(context, template) {
|
|
|
668
745
|
await waitForSignal();
|
|
669
746
|
} finally {
|
|
670
747
|
clearInterval(interval);
|
|
748
|
+
stopTailing?.();
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
function validateDevModes(context, options) {
|
|
752
|
+
if (![
|
|
753
|
+
"enable",
|
|
754
|
+
"try",
|
|
755
|
+
"disable"
|
|
756
|
+
].includes(options.typecheck)) context.fail(`Unknown typecheck mode ${JSON.stringify(options.typecheck)}. Expected enable, try, or disable.`);
|
|
757
|
+
if (![
|
|
758
|
+
"always",
|
|
759
|
+
"errors",
|
|
760
|
+
"disable"
|
|
761
|
+
].includes(options.tailLogs)) context.fail(`Unknown tail log mode ${JSON.stringify(options.tailLogs)}. Expected always, errors, or disable.`);
|
|
762
|
+
}
|
|
763
|
+
function printDevPreflight(context, report) {
|
|
764
|
+
if (report.status === "missing-generated") {
|
|
765
|
+
context.info("Preflight: generated Syncore files are missing; dev will refresh them.");
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
if (report.status === "schema-drift") {
|
|
769
|
+
context.info("Preflight: schema drift detected; dev will refresh local Syncore state where safe.");
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
if (report.status === "waiting-for-client") {
|
|
773
|
+
context.info("Preflight: this template uses client-managed runtimes; connect the app to unlock live targets.");
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
context.info("Preflight: Syncore project structure and local runtime prerequisites were inspected.");
|
|
777
|
+
}
|
|
778
|
+
async function runDevTypecheck(context, mode) {
|
|
779
|
+
if (mode === "disable") return {
|
|
780
|
+
mode,
|
|
781
|
+
attempted: false,
|
|
782
|
+
ok: true,
|
|
783
|
+
summary: "disabled"
|
|
784
|
+
};
|
|
785
|
+
const tsconfigPath = await findTypecheckConfig(context.cwd);
|
|
786
|
+
if (!tsconfigPath) {
|
|
787
|
+
if (mode === "enable") context.fail("Typecheck was enabled but no tsconfig.json was found in this project.");
|
|
788
|
+
context.warn("Typecheck skipped because no tsconfig.json was found.");
|
|
789
|
+
return {
|
|
790
|
+
mode,
|
|
791
|
+
attempted: false,
|
|
792
|
+
ok: true,
|
|
793
|
+
summary: "skipped (no tsconfig)"
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
const tscPath = await findTypeScriptCompiler(context.cwd);
|
|
797
|
+
if (!tscPath) {
|
|
798
|
+
if (mode === "enable") context.fail("Typecheck was enabled but no local TypeScript compiler was found.");
|
|
799
|
+
context.warn("Typecheck skipped because TypeScript is not available in this workspace.");
|
|
800
|
+
return {
|
|
801
|
+
mode,
|
|
802
|
+
attempted: false,
|
|
803
|
+
ok: true,
|
|
804
|
+
summary: "skipped (tsc unavailable)"
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
context.info(`Typecheck: running tsc --noEmit -p ${path.basename(tsconfigPath)}.`);
|
|
808
|
+
const result = await runTypeScriptCompiler(context.cwd, tscPath, tsconfigPath);
|
|
809
|
+
if (result.ok) {
|
|
810
|
+
context.success("Typecheck passed.");
|
|
811
|
+
return {
|
|
812
|
+
mode,
|
|
813
|
+
attempted: true,
|
|
814
|
+
ok: true,
|
|
815
|
+
summary: "passed"
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
const detail = summarizeCompilerOutput(result.output);
|
|
819
|
+
if (mode === "enable") context.fail(`Typecheck failed.${detail ? ` ${detail}` : ""}`, 1, result.output, { category: "validation" });
|
|
820
|
+
context.warn(`Typecheck reported issues but dev will continue.${detail ? ` ${detail}` : ""}`);
|
|
821
|
+
return {
|
|
822
|
+
mode,
|
|
823
|
+
attempted: true,
|
|
824
|
+
ok: false,
|
|
825
|
+
summary: "warning",
|
|
826
|
+
...detail ? { details: detail } : {}
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
async function findTypecheckConfig(cwd) {
|
|
830
|
+
for (const candidate of [
|
|
831
|
+
"tsconfig.json",
|
|
832
|
+
"tsconfig.app.json",
|
|
833
|
+
"tsconfig.main.json",
|
|
834
|
+
"tsconfig.build.json"
|
|
835
|
+
]) {
|
|
836
|
+
const resolved = path.join(cwd, candidate);
|
|
837
|
+
if (await fileExists(resolved)) return resolved;
|
|
838
|
+
}
|
|
839
|
+
return null;
|
|
840
|
+
}
|
|
841
|
+
async function findTypeScriptCompiler(cwd) {
|
|
842
|
+
const executableName = process.platform === "win32" ? "tsc.cmd" : "tsc";
|
|
843
|
+
let current = cwd;
|
|
844
|
+
while (true) {
|
|
845
|
+
const candidate = path.join(current, "node_modules", ".bin", executableName);
|
|
846
|
+
if (await fileExists(candidate)) return candidate;
|
|
847
|
+
const parent = path.dirname(current);
|
|
848
|
+
if (parent === current) break;
|
|
849
|
+
current = parent;
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
async function runTypeScriptCompiler(cwd, compilerPath, tsconfigPath) {
|
|
854
|
+
return await new Promise((resolve, reject) => {
|
|
855
|
+
const isWindowsCmd = process.platform === "win32" && /\.(cmd|bat)$/i.test(compilerPath);
|
|
856
|
+
const child = spawn(compilerPath, [
|
|
857
|
+
"--noEmit",
|
|
858
|
+
"-p",
|
|
859
|
+
tsconfigPath
|
|
860
|
+
], {
|
|
861
|
+
cwd,
|
|
862
|
+
stdio: [
|
|
863
|
+
"ignore",
|
|
864
|
+
"pipe",
|
|
865
|
+
"pipe"
|
|
866
|
+
],
|
|
867
|
+
...isWindowsCmd ? { shell: true } : {}
|
|
868
|
+
});
|
|
869
|
+
let output = "";
|
|
870
|
+
child.stdout.on("data", (chunk) => {
|
|
871
|
+
output += chunk.toString();
|
|
872
|
+
});
|
|
873
|
+
child.stderr.on("data", (chunk) => {
|
|
874
|
+
output += chunk.toString();
|
|
875
|
+
});
|
|
876
|
+
child.once("error", reject);
|
|
877
|
+
child.once("exit", (code) => {
|
|
878
|
+
resolve({
|
|
879
|
+
ok: (code ?? 1) === 0,
|
|
880
|
+
output: output.trim()
|
|
881
|
+
});
|
|
882
|
+
});
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
function summarizeCompilerOutput(output) {
|
|
886
|
+
return output.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
|
|
887
|
+
}
|
|
888
|
+
function describeTypecheckStatus(result) {
|
|
889
|
+
return result.details ? `${result.summary} (${result.details})` : result.summary;
|
|
890
|
+
}
|
|
891
|
+
function describeDevDriftStatus(report) {
|
|
892
|
+
switch (report.drift.state) {
|
|
893
|
+
case "clean": return "clean";
|
|
894
|
+
case "missing-snapshot": return "snapshot refreshed";
|
|
895
|
+
case "snapshot-outdated": return "snapshot refreshed";
|
|
896
|
+
case "migration-pending": return "migration review pending";
|
|
897
|
+
case "destructive": return "blocked";
|
|
898
|
+
default: return "unavailable";
|
|
671
899
|
}
|
|
672
900
|
}
|
|
673
901
|
async function requireHubConnection(context) {
|
|
@@ -777,8 +1005,41 @@ async function readPersistedLogs(cwd) {
|
|
|
777
1005
|
}
|
|
778
1006
|
return (await readFile(logPath, "utf8")).split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line)).filter((entry) => entry.version === 2).filter((entry) => !shouldSuppressLogEntry(entry));
|
|
779
1007
|
}
|
|
1008
|
+
async function printRecentRuntimeSignals(context, cwd, limit = 5) {
|
|
1009
|
+
const recent = (await readPersistedLogs(cwd)).slice(-limit);
|
|
1010
|
+
if (recent.length === 0) return;
|
|
1011
|
+
context.info("Recent runtime signals:");
|
|
1012
|
+
for (const entry of recent) process.stdout.write(` ${formatPersistedLogEntry(entry)}\n`);
|
|
1013
|
+
}
|
|
1014
|
+
function startRuntimeLogTail(context, cwd) {
|
|
1015
|
+
let seenCount = 0;
|
|
1016
|
+
let disposed = false;
|
|
1017
|
+
const poll = async () => {
|
|
1018
|
+
if (disposed) return;
|
|
1019
|
+
const entries = await readPersistedLogs(cwd);
|
|
1020
|
+
const next = entries.slice(seenCount);
|
|
1021
|
+
for (const entry of next) process.stdout.write(`${formatPersistedLogEntry(entry)}\n`);
|
|
1022
|
+
seenCount = entries.length;
|
|
1023
|
+
};
|
|
1024
|
+
const interval = setInterval(() => {
|
|
1025
|
+
poll();
|
|
1026
|
+
}, 1200);
|
|
1027
|
+
poll();
|
|
1028
|
+
return () => {
|
|
1029
|
+
disposed = true;
|
|
1030
|
+
clearInterval(interval);
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
780
1033
|
function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
781
1034
|
const functionName = typeof event.functionName === "string" ? event.functionName : "unknown";
|
|
1035
|
+
const functionComponent = resolveComponentInfoFromFunctionName(functionName);
|
|
1036
|
+
const queryComponent = typeof event.queryId === "string" ? resolveComponentInfoFromFunctionName(formatInvalidatedQueryId(event.queryId)) : void 0;
|
|
1037
|
+
const storageComponent = typeof event.storageId === "string" ? resolveComponentInfoFromScopedValue(event.storageId) : void 0;
|
|
1038
|
+
const componentInfo = typeof event.componentPath === "string" ? {
|
|
1039
|
+
owner: "component",
|
|
1040
|
+
componentPath: event.componentPath,
|
|
1041
|
+
...typeof event.componentName === "string" ? { componentName: event.componentName } : {}
|
|
1042
|
+
} : functionComponent ?? queryComponent ?? storageComponent;
|
|
782
1043
|
const logMessage = typeof event.message === "string" ? event.message : "Syncore log";
|
|
783
1044
|
const resolvedTargetId = event.runtimeId === "syncore-dev-hub" ? "all" : runtimeEntry?.targetId ?? event.runtimeId;
|
|
784
1045
|
const runtimeLabel = event.runtimeId === "syncore-dev-hub" ? "dashboard" : runtimeEntry?.label ?? "runtime";
|
|
@@ -798,6 +1059,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
798
1059
|
...entryBase,
|
|
799
1060
|
eventType: event.type,
|
|
800
1061
|
category: "system",
|
|
1062
|
+
...componentInfo ?? {},
|
|
801
1063
|
message: logMessage,
|
|
802
1064
|
event
|
|
803
1065
|
})) return null;
|
|
@@ -806,6 +1068,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
806
1068
|
...entryBase,
|
|
807
1069
|
eventType: event.type,
|
|
808
1070
|
category: "query",
|
|
1071
|
+
...componentInfo ?? {},
|
|
809
1072
|
message: `${functionName} executed`,
|
|
810
1073
|
event
|
|
811
1074
|
};
|
|
@@ -813,6 +1076,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
813
1076
|
...entryBase,
|
|
814
1077
|
eventType: event.type,
|
|
815
1078
|
category: "system",
|
|
1079
|
+
...componentInfo ?? {},
|
|
816
1080
|
message: `${formatInvalidatedQueryId(event.queryId)} invalidated${typeof event.reason === "string" ? ` (${event.reason})` : ""}`,
|
|
817
1081
|
event
|
|
818
1082
|
};
|
|
@@ -820,6 +1084,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
820
1084
|
...entryBase,
|
|
821
1085
|
eventType: event.type,
|
|
822
1086
|
category: "mutation",
|
|
1087
|
+
...componentInfo ?? {},
|
|
823
1088
|
message: Array.isArray(event.changedTables) && event.changedTables.length > 0 ? `${functionName} committed (${event.changedTables.join(", ")})` : `${functionName} committed`,
|
|
824
1089
|
event
|
|
825
1090
|
};
|
|
@@ -827,6 +1092,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
827
1092
|
...entryBase,
|
|
828
1093
|
eventType: event.type,
|
|
829
1094
|
category: "action",
|
|
1095
|
+
...componentInfo ?? {},
|
|
830
1096
|
message: typeof event.error === "string" && event.error.length > 0 ? `${functionName} failed: ${event.error}` : `${functionName} completed`,
|
|
831
1097
|
event
|
|
832
1098
|
};
|
|
@@ -848,6 +1114,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
848
1114
|
...entryBase,
|
|
849
1115
|
eventType: event.type,
|
|
850
1116
|
category: "system",
|
|
1117
|
+
...componentInfo ?? {},
|
|
851
1118
|
message: `${typeof event.operation === "string" ? event.operation : "update"} ${typeof event.storageId === "string" ? event.storageId : "storage"}`,
|
|
852
1119
|
event
|
|
853
1120
|
};
|
|
@@ -855,6 +1122,7 @@ function normalizeRuntimeEvent(event, runtimeEntry) {
|
|
|
855
1122
|
...entryBase,
|
|
856
1123
|
eventType: event.type,
|
|
857
1124
|
category: "system",
|
|
1125
|
+
...componentInfo ?? {},
|
|
858
1126
|
message: event.type === "log" ? logMessage : humanizeRuntimeEvent(event),
|
|
859
1127
|
event
|
|
860
1128
|
};
|
|
@@ -880,6 +1148,22 @@ function formatInvalidatedQueryId(queryId) {
|
|
|
880
1148
|
if (separatorIndex === -1) return queryId;
|
|
881
1149
|
return queryId.slice(0, separatorIndex);
|
|
882
1150
|
}
|
|
1151
|
+
function resolveComponentInfoFromFunctionName(functionName) {
|
|
1152
|
+
const match = /^components\/(.+)\/(public|internal)\/(.+)$/.exec(functionName);
|
|
1153
|
+
if (!match) return;
|
|
1154
|
+
return {
|
|
1155
|
+
owner: "component",
|
|
1156
|
+
componentPath: match[1] ?? ""
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
function resolveComponentInfoFromScopedValue(value) {
|
|
1160
|
+
const match = /^component:([^:]+):(.+)$/.exec(value);
|
|
1161
|
+
if (!match) return;
|
|
1162
|
+
return {
|
|
1163
|
+
owner: "component",
|
|
1164
|
+
componentPath: match[1] ?? ""
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
883
1167
|
function humanizeRuntimeEvent(event) {
|
|
884
1168
|
if (event.type === "scheduler.tick" && Array.isArray(event.executedJobIds)) return `scheduler tick (${event.executedJobIds.length} job(s))`;
|
|
885
1169
|
return event.type.replaceAll(".", " ");
|
|
@@ -949,7 +1233,7 @@ function parseJsonObject(input, label) {
|
|
|
949
1233
|
try {
|
|
950
1234
|
parsed = JSON.parse(input);
|
|
951
1235
|
} catch (error) {
|
|
952
|
-
throw new Error(`${label} must be valid JSON: ${formatError(error)}
|
|
1236
|
+
throw new Error(`${label} must be valid JSON: ${formatError(error)}`, { cause: error });
|
|
953
1237
|
}
|
|
954
1238
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`${label} must be a JSON object.`);
|
|
955
1239
|
return parsed;
|