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
|
@@ -3,6 +3,7 @@ import { generateId } from "./runtime/id.mjs";
|
|
|
3
3
|
import { SyncoreRuntime } from "./runtime/runtime.mjs";
|
|
4
4
|
import { createDevtoolsCommandHandler, createDevtoolsSubscriptionHost } from "./runtime/devtools.mjs";
|
|
5
5
|
import { src_exports } from "./index.mjs";
|
|
6
|
+
import { generateDevtoolsToken, isAllowedDashboardOrigin, isAuthorizedDashboardRequest, sanitizeDevtoolsToken } from "./devtools-auth.mjs";
|
|
6
7
|
import { appendFile, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
7
8
|
import { createServer } from "node:http";
|
|
8
9
|
import { connect } from "node:net";
|
|
@@ -12,16 +13,22 @@ import { DatabaseSync } from "node:sqlite";
|
|
|
12
13
|
import { Command } from "commander";
|
|
13
14
|
import { tsImport } from "tsx/esm/api";
|
|
14
15
|
import WebSocket, { WebSocketServer } from "ws";
|
|
15
|
-
import { createPublicRuntimeId, createPublicTargetId } from "../devtools-protocol/index.js";
|
|
16
|
+
import { SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_PROTOCOL_VERSION, createPublicRuntimeId, createPublicTargetId } from "../devtools-protocol/index.js";
|
|
16
17
|
//#region src/cli.ts
|
|
17
|
-
|
|
18
|
+
function templateUsesConnectedClients(template) {
|
|
19
|
+
return template === "react-web" || template === "svelte" || template === "expo" || template === "next";
|
|
20
|
+
}
|
|
21
|
+
const loadedTypeScriptModules = /* @__PURE__ */ new Map();
|
|
22
|
+
const COMBINED_DEV_COMMAND = "concurrently --kill-others-on-fail --names syncore,app --prefix-colors yellow,cyan \"npm run syncorejs:dev\" \"npm run dev:app\"";
|
|
18
23
|
const program = new Command();
|
|
19
24
|
const CORE_PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
25
|
+
const DEVTOOLS_SESSION_FILE = path.join(".syncore", "devtools-session.json");
|
|
20
26
|
const SYNCORE_MIGRATION_SNAPSHOT_FILE_NAME = "_schema_snapshot.json";
|
|
21
27
|
const VALID_SYNCORE_TEMPLATES = [
|
|
22
28
|
"minimal",
|
|
23
29
|
"node",
|
|
24
30
|
"react-web",
|
|
31
|
+
"svelte",
|
|
25
32
|
"expo",
|
|
26
33
|
"electron",
|
|
27
34
|
"next"
|
|
@@ -123,8 +130,10 @@ if (isCliEntryPoint()) await runSyncoreCli();
|
|
|
123
130
|
async function runCodegen(cwd) {
|
|
124
131
|
const functionsDir = path.join(cwd, "syncore", "functions");
|
|
125
132
|
const generatedDir = path.join(cwd, "syncore", "_generated");
|
|
133
|
+
const componentsManifestPath = path.join(cwd, "syncore", "components.ts");
|
|
126
134
|
await mkdir(generatedDir, { recursive: true });
|
|
127
135
|
const functionImportExtension = await resolveFunctionImportExtension(cwd);
|
|
136
|
+
const hasComponentsManifest = await hasNonEmptyComponentsManifest(componentsManifestPath);
|
|
128
137
|
const files = await listTypeScriptFiles(functionsDir);
|
|
129
138
|
const functionEntries = [];
|
|
130
139
|
for (const file of files) {
|
|
@@ -148,6 +157,8 @@ async function runCodegen(cwd) {
|
|
|
148
157
|
``,
|
|
149
158
|
`import { createFunctionReferenceFor } from "syncorejs";`,
|
|
150
159
|
`import type { FunctionReferenceFor } from "syncorejs";`,
|
|
160
|
+
`export { components } from "./components${functionImportExtension}";`,
|
|
161
|
+
``,
|
|
151
162
|
...renderFunctionTypeImports(functionEntries, functionImportExtension),
|
|
152
163
|
``,
|
|
153
164
|
...renderGeneratedApiInterfaces(functionEntries),
|
|
@@ -174,9 +185,12 @@ async function runCodegen(cwd) {
|
|
|
174
185
|
` */`,
|
|
175
186
|
``,
|
|
176
187
|
`import type { SyncoreFunctionRegistry } from "syncorejs";`,
|
|
177
|
-
|
|
188
|
+
`import { composeProjectFunctionRegistry } from "syncorejs";`,
|
|
189
|
+
...renderGeneratedManifestImportLines(hasComponentsManifest, functionImportExtension),
|
|
178
190
|
...renderFunctionImports(functionEntries, functionImportExtension),
|
|
179
191
|
``,
|
|
192
|
+
...renderGeneratedManifestDeclarationLines(hasComponentsManifest),
|
|
193
|
+
``,
|
|
180
194
|
...renderGeneratedFunctionsInterface(functionEntries),
|
|
181
195
|
``,
|
|
182
196
|
`/**`,
|
|
@@ -184,9 +198,72 @@ async function runCodegen(cwd) {
|
|
|
184
198
|
` *`,
|
|
185
199
|
` * Most application code should import from \`./api\` instead of using this map directly.`,
|
|
186
200
|
` */`,
|
|
187
|
-
`
|
|
201
|
+
`const rootFunctions: SyncoreRootFunctionsRegistry = {`,
|
|
188
202
|
...functionEntries.map((entry) => ` ${JSON.stringify(`${entry.pathParts.join("/")}/${entry.exportName}`)}: ${renderFunctionImportName(entry)},`),
|
|
189
203
|
`} as const;`,
|
|
204
|
+
``,
|
|
205
|
+
`export const functions: SyncoreFunctionRegistry = composeProjectFunctionRegistry(rootFunctions, componentsManifest);`,
|
|
206
|
+
``
|
|
207
|
+
].join("\n");
|
|
208
|
+
const schemaSource = [
|
|
209
|
+
`/**`,
|
|
210
|
+
` * Generated composed Syncore schema including installed components.`,
|
|
211
|
+
` *`,
|
|
212
|
+
` * THIS CODE IS AUTOMATICALLY GENERATED.`,
|
|
213
|
+
` *`,
|
|
214
|
+
` * To regenerate, run \`npx syncorejs dev\` or \`npx syncorejs codegen\`.`,
|
|
215
|
+
` * @module`,
|
|
216
|
+
` */`,
|
|
217
|
+
``,
|
|
218
|
+
`import { composeProjectSchema } from "syncorejs";`,
|
|
219
|
+
`import rootSchema from "../schema${functionImportExtension}";`,
|
|
220
|
+
...renderGeneratedManifestImportLines(hasComponentsManifest, functionImportExtension),
|
|
221
|
+
``,
|
|
222
|
+
...renderGeneratedManifestDeclarationLines(hasComponentsManifest),
|
|
223
|
+
``,
|
|
224
|
+
`const schema = composeProjectSchema(rootSchema, componentsManifest);`,
|
|
225
|
+
``,
|
|
226
|
+
`export default schema;`,
|
|
227
|
+
``
|
|
228
|
+
].join("\n");
|
|
229
|
+
const componentsSource = [
|
|
230
|
+
`/**`,
|
|
231
|
+
` * Generated installed-component helpers for this Syncore app.`,
|
|
232
|
+
` *`,
|
|
233
|
+
` * THIS CODE IS AUTOMATICALLY GENERATED.`,
|
|
234
|
+
` *`,
|
|
235
|
+
` * To regenerate, run \`npx syncorejs dev\` or \`npx syncorejs codegen\`.`,
|
|
236
|
+
` * @module`,
|
|
237
|
+
` */`,
|
|
238
|
+
``,
|
|
239
|
+
`import { createInstalledComponentsApi, resolveComponentsManifest } from "syncorejs";`,
|
|
240
|
+
...renderGeneratedManifestImportLines(hasComponentsManifest, functionImportExtension),
|
|
241
|
+
``,
|
|
242
|
+
...renderGeneratedManifestDeclarationLines(hasComponentsManifest),
|
|
243
|
+
``,
|
|
244
|
+
`export const components = createInstalledComponentsApi(componentsManifest);`,
|
|
245
|
+
``,
|
|
246
|
+
`export const resolvedComponents = resolveComponentsManifest(componentsManifest);`,
|
|
247
|
+
``,
|
|
248
|
+
`export default resolvedComponents;`,
|
|
249
|
+
``
|
|
250
|
+
].join("\n");
|
|
251
|
+
const runtimeSource = [
|
|
252
|
+
`/**`,
|
|
253
|
+
` * Generated local runtime bundle for Syncore CLI and Node adapters.`,
|
|
254
|
+
` *`,
|
|
255
|
+
` * THIS CODE IS AUTOMATICALLY GENERATED.`,
|
|
256
|
+
` *`,
|
|
257
|
+
` * To regenerate, run \`npx syncorejs dev\` or \`npx syncorejs codegen\`.`,
|
|
258
|
+
` * @module`,
|
|
259
|
+
` */`,
|
|
260
|
+
``,
|
|
261
|
+
`import schema from "./schema${functionImportExtension}";`,
|
|
262
|
+
`import { functions } from "./functions${functionImportExtension}";`,
|
|
263
|
+
...hasComponentsManifest ? [`import { resolvedComponents } from "./components${functionImportExtension}";`] : [`const resolvedComponents = [] as const;`],
|
|
264
|
+
``,
|
|
265
|
+
`export { functions, schema };`,
|
|
266
|
+
`export const components = resolvedComponents;`,
|
|
190
267
|
``
|
|
191
268
|
].join("\n");
|
|
192
269
|
const serverSource = [
|
|
@@ -213,7 +290,7 @@ async function runCodegen(cwd) {
|
|
|
213
290
|
` ValidatorMap`,
|
|
214
291
|
`} from "syncorejs";`,
|
|
215
292
|
``,
|
|
216
|
-
`export { createFunctionReference, createFunctionReferenceFor,
|
|
293
|
+
`export { createFunctionReference, createFunctionReferenceFor, s } from "syncorejs";`,
|
|
217
294
|
``,
|
|
218
295
|
`/**`,
|
|
219
296
|
` * The context object available inside Syncore query handlers in this app.`,
|
|
@@ -240,22 +317,14 @@ async function runCodegen(cwd) {
|
|
|
240
317
|
` * @param config - The query definition, including args and a handler.`,
|
|
241
318
|
` * @returns The wrapped query. Export it from \`syncore/functions\` to add it to the generated API.`,
|
|
242
319
|
` */`,
|
|
243
|
-
`export
|
|
244
|
-
`
|
|
245
|
-
`
|
|
246
|
-
`
|
|
247
|
-
`
|
|
248
|
-
`
|
|
249
|
-
`
|
|
250
|
-
`
|
|
251
|
-
`) {`,
|
|
252
|
-
` return baseQuery(config as never) as SyncoreFunctionDefinition<`,
|
|
253
|
-
` "query",`,
|
|
254
|
-
` QueryCtx,`,
|
|
255
|
-
` InferArgs<TArgsShape>,`,
|
|
256
|
-
` TResult`,
|
|
257
|
-
` >;`,
|
|
258
|
-
`}`,
|
|
320
|
+
`export const query = baseQuery as {`,
|
|
321
|
+
` <TValidator extends Validator<unknown, unknown, string>, TResult>(`,
|
|
322
|
+
` config: FunctionConfig<QueryCtx, Infer<TValidator>, TResult> & { args: TValidator }`,
|
|
323
|
+
` ): SyncoreFunctionDefinition<"query", QueryCtx, Infer<TValidator>, TResult>;`,
|
|
324
|
+
` <TArgsShape extends ValidatorMap, TResult>(`,
|
|
325
|
+
` config: FunctionConfig<QueryCtx, InferArgs<TArgsShape>, TResult> & { args: TArgsShape }`,
|
|
326
|
+
` ): SyncoreFunctionDefinition<"query", QueryCtx, InferArgs<TArgsShape>, TResult>;`,
|
|
327
|
+
`};`,
|
|
259
328
|
``,
|
|
260
329
|
`/**`,
|
|
261
330
|
` * Define a mutation in this Syncore app's public API.`,
|
|
@@ -265,22 +334,14 @@ async function runCodegen(cwd) {
|
|
|
265
334
|
` * @param config - The mutation definition, including args and a handler.`,
|
|
266
335
|
` * @returns The wrapped mutation. Export it from \`syncore/functions\` to add it to the generated API.`,
|
|
267
336
|
` */`,
|
|
268
|
-
`export
|
|
269
|
-
`
|
|
270
|
-
`
|
|
271
|
-
`
|
|
272
|
-
`
|
|
273
|
-
`
|
|
274
|
-
`
|
|
275
|
-
`
|
|
276
|
-
`) {`,
|
|
277
|
-
` return baseMutation(config as never) as SyncoreFunctionDefinition<`,
|
|
278
|
-
` "mutation",`,
|
|
279
|
-
` MutationCtx,`,
|
|
280
|
-
` InferArgs<TArgsShape>,`,
|
|
281
|
-
` TResult`,
|
|
282
|
-
` >;`,
|
|
283
|
-
`}`,
|
|
337
|
+
`export const mutation = baseMutation as {`,
|
|
338
|
+
` <TValidator extends Validator<unknown, unknown, string>, TResult>(`,
|
|
339
|
+
` config: FunctionConfig<MutationCtx, Infer<TValidator>, TResult> & { args: TValidator }`,
|
|
340
|
+
` ): SyncoreFunctionDefinition<"mutation", MutationCtx, Infer<TValidator>, TResult>;`,
|
|
341
|
+
` <TArgsShape extends ValidatorMap, TResult>(`,
|
|
342
|
+
` config: FunctionConfig<MutationCtx, InferArgs<TArgsShape>, TResult> & { args: TArgsShape }`,
|
|
343
|
+
` ): SyncoreFunctionDefinition<"mutation", MutationCtx, InferArgs<TArgsShape>, TResult>;`,
|
|
344
|
+
`};`,
|
|
284
345
|
``,
|
|
285
346
|
`/**`,
|
|
286
347
|
` * Define an action in this Syncore app's public API.`,
|
|
@@ -290,27 +351,28 @@ async function runCodegen(cwd) {
|
|
|
290
351
|
` * @param config - The action definition, including args and a handler.`,
|
|
291
352
|
` * @returns The wrapped action. Export it from \`syncore/functions\` to add it to the generated API.`,
|
|
292
353
|
` */`,
|
|
293
|
-
`export
|
|
294
|
-
`
|
|
295
|
-
`
|
|
296
|
-
`
|
|
297
|
-
`
|
|
298
|
-
`
|
|
299
|
-
`
|
|
300
|
-
`
|
|
301
|
-
`) {`,
|
|
302
|
-
` return baseAction(config as never) as SyncoreFunctionDefinition<`,
|
|
303
|
-
` "action",`,
|
|
304
|
-
` ActionCtx,`,
|
|
305
|
-
` InferArgs<TArgsShape>,`,
|
|
306
|
-
` TResult`,
|
|
307
|
-
` >;`,
|
|
308
|
-
`}`,
|
|
354
|
+
`export const action = baseAction as {`,
|
|
355
|
+
` <TValidator extends Validator<unknown, unknown, string>, TResult>(`,
|
|
356
|
+
` config: FunctionConfig<ActionCtx, Infer<TValidator>, TResult> & { args: TValidator }`,
|
|
357
|
+
` ): SyncoreFunctionDefinition<"action", ActionCtx, Infer<TValidator>, TResult>;`,
|
|
358
|
+
` <TArgsShape extends ValidatorMap, TResult>(`,
|
|
359
|
+
` config: FunctionConfig<ActionCtx, InferArgs<TArgsShape>, TResult> & { args: TArgsShape }`,
|
|
360
|
+
` ): SyncoreFunctionDefinition<"action", ActionCtx, InferArgs<TArgsShape>, TResult>;`,
|
|
361
|
+
`};`,
|
|
309
362
|
``
|
|
310
363
|
].join("\n");
|
|
311
|
-
await
|
|
312
|
-
await
|
|
313
|
-
await
|
|
364
|
+
await writeGeneratedFile(path.join(generatedDir, "api.ts"), apiSource);
|
|
365
|
+
await writeGeneratedFile(path.join(generatedDir, "components.ts"), componentsSource);
|
|
366
|
+
await writeGeneratedFile(path.join(generatedDir, "functions.ts"), functionsSource);
|
|
367
|
+
await writeGeneratedFile(path.join(generatedDir, "runtime.ts"), runtimeSource);
|
|
368
|
+
await writeGeneratedFile(path.join(generatedDir, "schema.ts"), schemaSource);
|
|
369
|
+
await writeGeneratedFile(path.join(generatedDir, "server.ts"), serverSource);
|
|
370
|
+
}
|
|
371
|
+
async function writeGeneratedFile(filePath, source) {
|
|
372
|
+
try {
|
|
373
|
+
if (await readFile(filePath, "utf8") === source) return;
|
|
374
|
+
} catch {}
|
|
375
|
+
await writeFile(filePath, source);
|
|
314
376
|
}
|
|
315
377
|
async function scaffoldProject(cwd, options) {
|
|
316
378
|
const files = buildTemplateFiles(options.template);
|
|
@@ -345,19 +407,26 @@ function buildTemplateFiles(template) {
|
|
|
345
407
|
},
|
|
346
408
|
{
|
|
347
409
|
path: path.join("syncore", "schema.ts"),
|
|
348
|
-
content: `import { defineSchema, defineTable,
|
|
410
|
+
content: `import { defineSchema, defineTable, s } from "syncorejs";
|
|
349
411
|
|
|
350
412
|
export default defineSchema({
|
|
351
413
|
tasks: defineTable({
|
|
352
|
-
text:
|
|
353
|
-
done:
|
|
414
|
+
text: s.string(),
|
|
415
|
+
done: s.boolean()
|
|
354
416
|
}).index("by_done", ["done"])
|
|
355
417
|
});
|
|
418
|
+
`
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
path: path.join("syncore", "components.ts"),
|
|
422
|
+
content: `import { defineComponents } from "syncorejs";
|
|
423
|
+
|
|
424
|
+
export default defineComponents({});
|
|
356
425
|
`
|
|
357
426
|
},
|
|
358
427
|
{
|
|
359
428
|
path: path.join("syncore", "functions", "tasks.ts"),
|
|
360
|
-
content: `import { mutation, query,
|
|
429
|
+
content: `import { mutation, query, s } from "../_generated/server";
|
|
361
430
|
|
|
362
431
|
export const list = query({
|
|
363
432
|
args: {},
|
|
@@ -366,7 +435,7 @@ export const list = query({
|
|
|
366
435
|
});
|
|
367
436
|
|
|
368
437
|
export const create = mutation({
|
|
369
|
-
args: { text:
|
|
438
|
+
args: { text: s.string() },
|
|
370
439
|
handler: async (ctx, args) =>
|
|
371
440
|
ctx.db.insert("tasks", { text: args.text, done: false })
|
|
372
441
|
});
|
|
@@ -380,15 +449,13 @@ export const create = mutation({
|
|
|
380
449
|
content: `/// <reference lib="webworker" />
|
|
381
450
|
|
|
382
451
|
import { createBrowserWorkerRuntime } from "syncorejs/browser";
|
|
383
|
-
import schema from "../syncore/schema";
|
|
452
|
+
import schema from "../syncore/_generated/schema";
|
|
384
453
|
import { functions } from "../syncore/_generated/functions";
|
|
385
454
|
|
|
386
455
|
void createBrowserWorkerRuntime({
|
|
387
456
|
endpoint: self,
|
|
388
457
|
schema,
|
|
389
|
-
functions
|
|
390
|
-
databaseName: "syncore-app",
|
|
391
|
-
persistenceMode: "opfs"
|
|
458
|
+
functions
|
|
392
459
|
});
|
|
393
460
|
`
|
|
394
461
|
}, {
|
|
@@ -410,14 +477,12 @@ export function AppSyncoreProvider({ children }: { children: ReactNode }) {
|
|
|
410
477
|
files.push({
|
|
411
478
|
path: path.join("lib", "syncore.ts"),
|
|
412
479
|
content: `import { createExpoSyncoreBootstrap } from "syncorejs/expo";
|
|
413
|
-
import schema from "../syncore/schema";
|
|
480
|
+
import schema from "../syncore/_generated/schema";
|
|
414
481
|
import { functions } from "../syncore/_generated/functions";
|
|
415
482
|
|
|
416
483
|
export const syncore = createExpoSyncoreBootstrap({
|
|
417
484
|
schema,
|
|
418
|
-
functions
|
|
419
|
-
databaseName: "syncore-app.db",
|
|
420
|
-
storageDirectoryName: "syncore-app-storage"
|
|
485
|
+
functions
|
|
421
486
|
});
|
|
422
487
|
`
|
|
423
488
|
});
|
|
@@ -428,17 +493,13 @@ export const syncore = createExpoSyncoreBootstrap({
|
|
|
428
493
|
content: `/* eslint-disable */
|
|
429
494
|
|
|
430
495
|
import { createBrowserWorkerRuntime } from "syncorejs/browser";
|
|
431
|
-
import schema from "../syncore/schema";
|
|
496
|
+
import schema from "../syncore/_generated/schema";
|
|
432
497
|
import { functions } from "../syncore/_generated/functions";
|
|
433
498
|
|
|
434
499
|
void createBrowserWorkerRuntime({
|
|
435
500
|
endpoint: self,
|
|
436
501
|
schema,
|
|
437
|
-
functions
|
|
438
|
-
databaseName: "syncore-app",
|
|
439
|
-
persistenceDatabaseName: "syncore-app",
|
|
440
|
-
locateFile: () => "/sql-wasm.wasm",
|
|
441
|
-
platform: "browser-worker"
|
|
502
|
+
functions
|
|
442
503
|
});
|
|
443
504
|
`
|
|
444
505
|
}, {
|
|
@@ -469,7 +530,7 @@ export function AppSyncoreProvider({ children }: { children: ReactNode }) {
|
|
|
469
530
|
content: `import path from "node:path";
|
|
470
531
|
import { withNodeSyncoreClient } from "syncorejs/node";
|
|
471
532
|
import { api } from "./syncore/_generated/api.ts";
|
|
472
|
-
import schema from "./syncore/schema.ts";
|
|
533
|
+
import schema from "./syncore/_generated/schema.ts";
|
|
473
534
|
import { functions } from "./syncore/_generated/functions.ts";
|
|
474
535
|
|
|
475
536
|
await withNodeSyncoreClient(
|
|
@@ -493,7 +554,7 @@ await withNodeSyncoreClient(
|
|
|
493
554
|
content: `import path from "node:path";
|
|
494
555
|
import { app } from "electron";
|
|
495
556
|
import { createNodeSyncoreRuntime } from "syncorejs/node";
|
|
496
|
-
import schema from "../syncore/schema.js";
|
|
557
|
+
import schema from "../syncore/_generated/schema.js";
|
|
497
558
|
import { functions } from "../syncore/_generated/functions.js";
|
|
498
559
|
|
|
499
560
|
export function createAppSyncoreRuntime() {
|
|
@@ -506,6 +567,50 @@ export function createAppSyncoreRuntime() {
|
|
|
506
567
|
platform: "electron-main"
|
|
507
568
|
});
|
|
508
569
|
}
|
|
570
|
+
`
|
|
571
|
+
});
|
|
572
|
+
break;
|
|
573
|
+
case "svelte":
|
|
574
|
+
files.push({
|
|
575
|
+
path: path.join("src", "syncore.worker.ts"),
|
|
576
|
+
content: `/// <reference lib="webworker" />
|
|
577
|
+
|
|
578
|
+
import { createBrowserWorkerRuntime } from "syncorejs/browser";
|
|
579
|
+
import schema from "../syncore/_generated/schema";
|
|
580
|
+
import { functions } from "../syncore/_generated/functions";
|
|
581
|
+
|
|
582
|
+
void createBrowserWorkerRuntime({
|
|
583
|
+
endpoint: self,
|
|
584
|
+
schema,
|
|
585
|
+
functions
|
|
586
|
+
});
|
|
587
|
+
`
|
|
588
|
+
}, {
|
|
589
|
+
path: path.join("src", "SyncoreProvider.svelte"),
|
|
590
|
+
content: `<script lang="ts">
|
|
591
|
+
import { onDestroy } from "svelte";
|
|
592
|
+
import type { Snippet } from "svelte";
|
|
593
|
+
import { createBrowserWorkerClient } from "syncorejs/browser";
|
|
594
|
+
import { setSyncoreClient } from "syncorejs/svelte";
|
|
595
|
+
|
|
596
|
+
interface Props {
|
|
597
|
+
children?: Snippet;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
const { children }: Props = $props();
|
|
601
|
+
|
|
602
|
+
const managed = createBrowserWorkerClient({
|
|
603
|
+
workerUrl: new URL("./syncore.worker.ts", import.meta.url)
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
setSyncoreClient(managed.client);
|
|
607
|
+
|
|
608
|
+
onDestroy(() => {
|
|
609
|
+
void managed.dispose();
|
|
610
|
+
});
|
|
611
|
+
<\/script>
|
|
612
|
+
|
|
613
|
+
{@render children?.()}
|
|
509
614
|
`
|
|
510
615
|
});
|
|
511
616
|
break;
|
|
@@ -554,7 +659,8 @@ async function detectProjectTemplate(cwd) {
|
|
|
554
659
|
if ("expo" in dependencies || "react-native" in dependencies) return "expo";
|
|
555
660
|
if ("electron" in dependencies) return "electron";
|
|
556
661
|
if ("next" in dependencies) return "next";
|
|
557
|
-
if ("
|
|
662
|
+
if ("svelte" in dependencies || "@sveltejs/vite-plugin-svelte" in dependencies || "@sveltejs/kit" in dependencies || await fileExists(path.join(cwd, "src", "SyncoreProvider.svelte"))) return "svelte";
|
|
663
|
+
if ("vite" in dependencies || "@vitejs/plugin-react" in dependencies || await fileExists(path.join(cwd, "src", "syncore.worker.ts")) || await fileExists(path.join(cwd, "src", "syncore-provider.tsx")) || await fileExists(path.join(cwd, "src", "main.tsx")) && "react" in dependencies) return "react-web";
|
|
558
664
|
if (packageJson) return "node";
|
|
559
665
|
return "minimal";
|
|
560
666
|
}
|
|
@@ -569,7 +675,16 @@ async function readPackageJson(cwd) {
|
|
|
569
675
|
}
|
|
570
676
|
async function ensurePackageScripts(cwd, template) {
|
|
571
677
|
const packageJsonPath = path.join(cwd, "package.json");
|
|
572
|
-
if (!await fileExists(packageJsonPath))
|
|
678
|
+
if (!await fileExists(packageJsonPath)) {
|
|
679
|
+
await writeFile(packageJsonPath, `${JSON.stringify({
|
|
680
|
+
type: "module",
|
|
681
|
+
scripts: {
|
|
682
|
+
"syncorejs:dev": "syncorejs dev",
|
|
683
|
+
"syncorejs:codegen": "syncorejs codegen"
|
|
684
|
+
}
|
|
685
|
+
}, null, 2)}\n`);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
573
688
|
const packageJson = await readPackageJson(cwd);
|
|
574
689
|
if (!packageJson) return;
|
|
575
690
|
const nextPackageJson = {
|
|
@@ -602,7 +717,7 @@ function maybeAddManagedDevScripts(packageJson, template) {
|
|
|
602
717
|
scripts.dev = combinedDevCommand();
|
|
603
718
|
}
|
|
604
719
|
function supportsManagedCombinedDev(template) {
|
|
605
|
-
return template === "next" || template === "react-web" || template === "electron";
|
|
720
|
+
return template === "next" || template === "react-web" || template === "svelte" || template === "electron";
|
|
606
721
|
}
|
|
607
722
|
function combinedDevCommand() {
|
|
608
723
|
return COMBINED_DEV_COMMAND;
|
|
@@ -651,7 +766,7 @@ async function importJsonlIntoProject(cwd, tableName, sourcePath) {
|
|
|
651
766
|
try {
|
|
652
767
|
parsed = JSON.parse(line);
|
|
653
768
|
} catch (error) {
|
|
654
|
-
throw new Error(`Invalid JSON on line ${lineNumber} of ${sourcePath}: ${formatError(error)}
|
|
769
|
+
throw new Error(`Invalid JSON on line ${lineNumber} of ${sourcePath}: ${formatError(error)}`, { cause: error });
|
|
655
770
|
}
|
|
656
771
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`Line ${lineNumber} of ${sourcePath} must contain a JSON object.`);
|
|
657
772
|
const payload = { ...parsed };
|
|
@@ -768,12 +883,19 @@ function renderGeneratedFunctionsInterface(functionEntries) {
|
|
|
768
883
|
`/**`,
|
|
769
884
|
` * Type-safe runtime definitions for every function exported from \`syncore/functions\`.`,
|
|
770
885
|
` */`,
|
|
771
|
-
`export interface
|
|
886
|
+
`export interface SyncoreRootFunctionsRegistry extends SyncoreFunctionRegistry {`
|
|
772
887
|
];
|
|
773
888
|
for (const entry of functionEntries.slice().sort((left, right) => `${left.pathParts.join("/")}/${left.exportName}`.localeCompare(`${right.pathParts.join("/")}/${right.exportName}`))) lines.push(` /**`, ` * Runtime definition for the public Syncore ${entry.kind} \`${entry.pathParts.join("/")}/${entry.exportName}\`.`, ` */`, ` readonly ${JSON.stringify(`${entry.pathParts.join("/")}/${entry.exportName}`)}: typeof ${renderFunctionImportName(entry)};`);
|
|
774
889
|
lines.push(`}`);
|
|
775
890
|
return [lines.join("\n")];
|
|
776
891
|
}
|
|
892
|
+
function renderGeneratedManifestImportLines(hasComponentsManifest, extension) {
|
|
893
|
+
if (!hasComponentsManifest) return [];
|
|
894
|
+
return [`import componentsManifest from "../components${extension}";`];
|
|
895
|
+
}
|
|
896
|
+
function renderGeneratedManifestDeclarationLines(hasComponentsManifest) {
|
|
897
|
+
return hasComponentsManifest ? [] : [`const componentsManifest = {} as const;`];
|
|
898
|
+
}
|
|
777
899
|
function renderApiInterfaceName(node) {
|
|
778
900
|
if (node.pathParts.length === 0) return "SyncoreApi";
|
|
779
901
|
return `SyncoreApi__${node.pathParts.map(toTypeNamePart).join("__")}`;
|
|
@@ -831,15 +953,28 @@ function requireProjectTargetConfig(config) {
|
|
|
831
953
|
if (!projectTarget) throw new Error("This Syncore project does not define a projectTarget. Use a connected client target instead.");
|
|
832
954
|
return projectTarget;
|
|
833
955
|
}
|
|
834
|
-
async function
|
|
956
|
+
async function loadProjectRootSchema(cwd) {
|
|
835
957
|
const schema = await loadDefaultExport(path.join(cwd, "syncore", "schema.ts"));
|
|
836
958
|
if (!schema || typeof schema !== "object" || typeof schema.tableNames !== "function") throw new Error("syncore/schema.ts must default export defineSchema(...).");
|
|
837
959
|
return schema;
|
|
838
960
|
}
|
|
961
|
+
async function loadProjectComponentsManifest(cwd) {
|
|
962
|
+
const filePath = path.join(cwd, "syncore", "components.ts");
|
|
963
|
+
if (!await fileExists(filePath)) return {};
|
|
964
|
+
const manifest = await loadDefaultExport(filePath);
|
|
965
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) throw new Error("syncore/components.ts must default export defineComponents({...}).");
|
|
966
|
+
return manifest;
|
|
967
|
+
}
|
|
968
|
+
async function loadProjectSchema(cwd) {
|
|
969
|
+
const filePath = path.join(cwd, "syncore", "_generated", "schema.ts");
|
|
970
|
+
if (!await fileExists(filePath)) await runCodegen(cwd);
|
|
971
|
+
const schema = await loadDefaultExport(filePath);
|
|
972
|
+
if (!schema || typeof schema !== "object" || typeof schema.tableNames !== "function") throw new Error("syncore/_generated/schema.ts must default export a composed Syncore schema.");
|
|
973
|
+
return schema;
|
|
974
|
+
}
|
|
839
975
|
async function loadDefaultExport(filePath) {
|
|
840
976
|
if (!await fileExists(filePath)) throw new Error(`Missing file: ${path.relative(process.cwd(), filePath)}`);
|
|
841
|
-
const
|
|
842
|
-
const loaded = await tsImport(moduleUrl, { parentURL: import.meta.url });
|
|
977
|
+
const loaded = await loadTypeScriptModule(filePath);
|
|
843
978
|
if (!("default" in loaded)) throw new Error(`File ${path.relative(process.cwd(), filePath)} must have a default export.`);
|
|
844
979
|
const resolvedDefault = unwrapDefaultExport(loaded.default);
|
|
845
980
|
if (resolvedDefault === void 0) throw new Error(`File ${path.relative(process.cwd(), filePath)} exported undefined.`);
|
|
@@ -847,24 +982,94 @@ async function loadDefaultExport(filePath) {
|
|
|
847
982
|
}
|
|
848
983
|
async function loadNamedExport(filePath, exportName) {
|
|
849
984
|
if (!await fileExists(filePath)) throw new Error(`Missing file: ${path.relative(process.cwd(), filePath)}`);
|
|
850
|
-
const
|
|
851
|
-
const loaded = await tsImport(moduleUrl, { parentURL: import.meta.url });
|
|
985
|
+
const loaded = await loadTypeScriptModule(filePath);
|
|
852
986
|
const defaultExport = loaded.default && typeof loaded.default === "object" && exportName in loaded.default ? loaded.default[exportName] : void 0;
|
|
853
987
|
if (!(exportName in loaded) && defaultExport === void 0) throw new Error(`File ${path.relative(process.cwd(), filePath)} must export ${exportName}.`);
|
|
854
988
|
const resolvedValue = unwrapDefaultExport(loaded[exportName] ?? defaultExport);
|
|
855
989
|
if (resolvedValue === void 0) throw new Error(`File ${path.relative(process.cwd(), filePath)} exported undefined for ${exportName}.`);
|
|
856
990
|
return resolvedValue;
|
|
857
991
|
}
|
|
992
|
+
async function hasNonEmptyComponentsManifest(filePath) {
|
|
993
|
+
if (!await fileExists(filePath)) return false;
|
|
994
|
+
const source = await readFile(filePath, "utf8");
|
|
995
|
+
return !/defineComponents\s*\(\s*\{\s*\}\s*\)/.test(source);
|
|
996
|
+
}
|
|
997
|
+
async function loadTypeScriptModule(filePath) {
|
|
998
|
+
const fileStat = await stat(filePath);
|
|
999
|
+
const cached = loadedTypeScriptModules.get(filePath);
|
|
1000
|
+
if (cached && cached.mtimeMs === fileStat.mtimeMs) return await cached.loaded;
|
|
1001
|
+
const moduleUrl = pathToFileURL(filePath).href;
|
|
1002
|
+
const loaded = tsImport(moduleUrl, { parentURL: import.meta.url });
|
|
1003
|
+
loadedTypeScriptModules.set(filePath, {
|
|
1004
|
+
mtimeMs: fileStat.mtimeMs,
|
|
1005
|
+
loaded
|
|
1006
|
+
});
|
|
1007
|
+
return await loaded;
|
|
1008
|
+
}
|
|
858
1009
|
async function loadProjectFunctions(cwd) {
|
|
859
|
-
const
|
|
1010
|
+
const filePath = path.join(cwd, "syncore", "_generated", "functions.ts");
|
|
1011
|
+
if (!await fileExists(filePath)) await runCodegen(cwd);
|
|
1012
|
+
const functions = await loadNamedExport(filePath, "functions");
|
|
860
1013
|
if (!functions || typeof functions !== "object") throw new Error("syncore/_generated/functions.ts must export a functions registry.");
|
|
861
1014
|
return functions;
|
|
862
1015
|
}
|
|
1016
|
+
async function loadProjectResolvedComponents(cwd) {
|
|
1017
|
+
const componentsManifestPath = path.join(cwd, "syncore", "components.ts");
|
|
1018
|
+
if (await fileExists(componentsManifestPath)) {
|
|
1019
|
+
const source = await readFile(componentsManifestPath, "utf8");
|
|
1020
|
+
if (/defineComponents\s*\(\s*\{\s*\}\s*\)/.test(source)) return [];
|
|
1021
|
+
}
|
|
1022
|
+
const filePath = path.join(cwd, "syncore", "_generated", "components.ts");
|
|
1023
|
+
if (!await fileExists(filePath)) await runCodegen(cwd);
|
|
1024
|
+
const components = await loadNamedExport(filePath, "resolvedComponents");
|
|
1025
|
+
if (!Array.isArray(components)) throw new Error("syncore/_generated/components.ts must export resolvedComponents.");
|
|
1026
|
+
return components;
|
|
1027
|
+
}
|
|
1028
|
+
async function loadProjectRuntime(cwd) {
|
|
1029
|
+
const filePath = path.join(cwd, "syncore", "_generated", "runtime.ts");
|
|
1030
|
+
if (!await fileExists(filePath)) await runCodegen(cwd);
|
|
1031
|
+
const loaded = await loadTypeScriptModule(filePath);
|
|
1032
|
+
const schema = unwrapDefaultExport(loaded.schema);
|
|
1033
|
+
const functions = unwrapDefaultExport(loaded.functions);
|
|
1034
|
+
const components = unwrapDefaultExport(loaded.components);
|
|
1035
|
+
if (!schema || typeof schema !== "object" || typeof schema.tableNames !== "function") throw new Error("syncore/_generated/runtime.ts must export a composed Syncore schema.");
|
|
1036
|
+
if (!functions || typeof functions !== "object") throw new Error("syncore/_generated/runtime.ts must export a functions registry.");
|
|
1037
|
+
if (!Array.isArray(components)) throw new Error("syncore/_generated/runtime.ts must export resolved components.");
|
|
1038
|
+
return {
|
|
1039
|
+
schema,
|
|
1040
|
+
functions,
|
|
1041
|
+
components
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
var HubExternalChangeSignal = class {
|
|
1045
|
+
publishToHub;
|
|
1046
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1047
|
+
constructor(publishToHub) {
|
|
1048
|
+
this.publishToHub = publishToHub;
|
|
1049
|
+
}
|
|
1050
|
+
subscribe(listener) {
|
|
1051
|
+
this.listeners.add(listener);
|
|
1052
|
+
return () => {
|
|
1053
|
+
this.listeners.delete(listener);
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
publish(event) {
|
|
1057
|
+
return this.publishToHub(event);
|
|
1058
|
+
}
|
|
1059
|
+
receive(event) {
|
|
1060
|
+
for (const listener of this.listeners) listener(event);
|
|
1061
|
+
}
|
|
1062
|
+
close() {
|
|
1063
|
+
this.listeners.clear();
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
863
1066
|
var HubSqliteDriver = class {
|
|
1067
|
+
databasePath;
|
|
864
1068
|
database;
|
|
865
1069
|
transactionDepth = 0;
|
|
866
|
-
constructor(
|
|
867
|
-
this.
|
|
1070
|
+
constructor(databasePath) {
|
|
1071
|
+
this.databasePath = databasePath;
|
|
1072
|
+
this.database = new DatabaseSync(databasePath);
|
|
868
1073
|
this.database.exec("PRAGMA foreign_keys = ON;");
|
|
869
1074
|
this.database.exec("PRAGMA journal_mode = WAL;");
|
|
870
1075
|
}
|
|
@@ -917,6 +1122,7 @@ var HubSqliteDriver = class {
|
|
|
917
1122
|
}
|
|
918
1123
|
};
|
|
919
1124
|
var HubFileStorageAdapter = class {
|
|
1125
|
+
directory;
|
|
920
1126
|
constructor(directory) {
|
|
921
1127
|
this.directory = directory;
|
|
922
1128
|
}
|
|
@@ -1030,11 +1236,10 @@ const hubDevtoolsSqlSupport = {
|
|
|
1030
1236
|
}
|
|
1031
1237
|
}
|
|
1032
1238
|
};
|
|
1033
|
-
async function createProjectTargetBackend(cwd) {
|
|
1239
|
+
async function createProjectTargetBackend(cwd, externalChangeSignal) {
|
|
1034
1240
|
const projectTarget = resolveProjectTargetConfig(await loadProjectConfig(cwd));
|
|
1035
1241
|
if (!projectTarget) return null;
|
|
1036
|
-
const schema = await
|
|
1037
|
-
const functions = await loadProjectFunctions(cwd);
|
|
1242
|
+
const { schema, functions, components } = await loadProjectRuntime(cwd);
|
|
1038
1243
|
const databasePath = path.resolve(cwd, projectTarget.databasePath);
|
|
1039
1244
|
const storageDirectory = path.resolve(cwd, projectTarget.storageDirectory);
|
|
1040
1245
|
await mkdir(path.dirname(databasePath), { recursive: true });
|
|
@@ -1043,35 +1248,42 @@ async function createProjectTargetBackend(cwd) {
|
|
|
1043
1248
|
const runtime = new SyncoreRuntime({
|
|
1044
1249
|
schema,
|
|
1045
1250
|
functions,
|
|
1251
|
+
components,
|
|
1046
1252
|
driver,
|
|
1047
1253
|
storage: new HubFileStorageAdapter(storageDirectory),
|
|
1048
|
-
platform: "project"
|
|
1254
|
+
platform: "project",
|
|
1255
|
+
...externalChangeSignal ? { externalChangeSignal } : {}
|
|
1049
1256
|
});
|
|
1050
|
-
await runtime.
|
|
1257
|
+
await runtime.start();
|
|
1051
1258
|
const commandHandler = createDevtoolsCommandHandler({
|
|
1052
1259
|
driver,
|
|
1053
1260
|
schema,
|
|
1054
1261
|
functions,
|
|
1055
|
-
runtime,
|
|
1262
|
+
admin: runtime.getAdmin(),
|
|
1056
1263
|
sql: hubDevtoolsSqlSupport
|
|
1057
1264
|
});
|
|
1058
1265
|
const subscriptionHost = createDevtoolsSubscriptionHost({
|
|
1059
1266
|
driver,
|
|
1060
1267
|
schema,
|
|
1061
1268
|
functions,
|
|
1062
|
-
runtime,
|
|
1269
|
+
admin: runtime.getAdmin(),
|
|
1063
1270
|
sql: hubDevtoolsSqlSupport
|
|
1064
1271
|
});
|
|
1065
1272
|
return {
|
|
1066
1273
|
hello: {
|
|
1067
1274
|
type: "hello",
|
|
1275
|
+
protocolVersion: SYNCORE_DEVTOOLS_PROTOCOL_VERSION,
|
|
1276
|
+
minSupportedProtocolVersion: SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION,
|
|
1277
|
+
maxSupportedProtocolVersion: SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION,
|
|
1068
1278
|
runtimeId: PROJECT_TARGET_RUNTIME_ID,
|
|
1069
1279
|
platform: "project",
|
|
1070
1280
|
sessionLabel: "Project Target",
|
|
1071
1281
|
targetKind: "project",
|
|
1282
|
+
runtimeRole: "project-target",
|
|
1072
1283
|
storageProtocol: "file",
|
|
1073
1284
|
databaseLabel: path.basename(databasePath),
|
|
1074
|
-
storageIdentity: `file::${databasePath}
|
|
1285
|
+
storageIdentity: `file::${databasePath}`,
|
|
1286
|
+
capabilities: createProjectDevtoolsCapabilities()
|
|
1075
1287
|
},
|
|
1076
1288
|
handleCommand: commandHandler,
|
|
1077
1289
|
subscribe(subscriptionId, payload, listener) {
|
|
@@ -1086,6 +1298,24 @@ async function createProjectTargetBackend(cwd) {
|
|
|
1086
1298
|
}
|
|
1087
1299
|
};
|
|
1088
1300
|
}
|
|
1301
|
+
function createProjectDevtoolsCapabilities() {
|
|
1302
|
+
return {
|
|
1303
|
+
sql: {
|
|
1304
|
+
read: true,
|
|
1305
|
+
write: true,
|
|
1306
|
+
live: true
|
|
1307
|
+
},
|
|
1308
|
+
data: {
|
|
1309
|
+
browse: true,
|
|
1310
|
+
mutate: true,
|
|
1311
|
+
importExport: true
|
|
1312
|
+
},
|
|
1313
|
+
scheduler: {
|
|
1314
|
+
read: true,
|
|
1315
|
+
edit: true
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1089
1319
|
function normalizeStorageInput(input) {
|
|
1090
1320
|
if (typeof input === "string") return Buffer.from(input);
|
|
1091
1321
|
if (input instanceof Uint8Array) return input;
|
|
@@ -1208,16 +1438,24 @@ function formatError(error) {
|
|
|
1208
1438
|
}
|
|
1209
1439
|
async function isLocalPortInUse(port) {
|
|
1210
1440
|
return await new Promise((resolve) => {
|
|
1441
|
+
let settled = false;
|
|
1211
1442
|
const socket = connect({
|
|
1212
1443
|
host: "127.0.0.1",
|
|
1213
1444
|
port
|
|
1214
1445
|
});
|
|
1446
|
+
const finish = (inUse) => {
|
|
1447
|
+
if (settled) return;
|
|
1448
|
+
settled = true;
|
|
1449
|
+
clearTimeout(timeout);
|
|
1450
|
+
socket.destroy();
|
|
1451
|
+
resolve(inUse);
|
|
1452
|
+
};
|
|
1453
|
+
const timeout = setTimeout(() => finish(false), 100);
|
|
1215
1454
|
socket.once("connect", () => {
|
|
1216
|
-
|
|
1217
|
-
resolve(true);
|
|
1455
|
+
finish(true);
|
|
1218
1456
|
});
|
|
1219
1457
|
socket.once("error", () => {
|
|
1220
|
-
|
|
1458
|
+
finish(false);
|
|
1221
1459
|
});
|
|
1222
1460
|
});
|
|
1223
1461
|
}
|
|
@@ -1239,22 +1477,26 @@ function applyMigrationSql(database, sql, fileName) {
|
|
|
1239
1477
|
async function startDevHub(options) {
|
|
1240
1478
|
const dashboardPort = resolvePortFromEnv("SYNCORE_DASHBOARD_PORT", 4310);
|
|
1241
1479
|
const devtoolsPort = resolvePortFromEnv("SYNCORE_DEVTOOLS_PORT", 4311);
|
|
1480
|
+
const dashboardUrl = `http://localhost:${dashboardPort}`;
|
|
1481
|
+
const devtoolsUrl = `ws://127.0.0.1:${devtoolsPort}`;
|
|
1242
1482
|
const logsDirectory = path.join(options.cwd, ".syncore", "logs");
|
|
1243
1483
|
const logFilePath = path.join(logsDirectory, "runtime.jsonl");
|
|
1484
|
+
const hubAccessToken = sanitizeDevtoolsToken(process.env.SYNCORE_DEVTOOLS_TOKEN) ?? generateDevtoolsToken();
|
|
1485
|
+
const sessionState = {
|
|
1486
|
+
dashboardUrl,
|
|
1487
|
+
authenticatedDashboardUrl: `${dashboardUrl}/?token=${hubAccessToken}`,
|
|
1488
|
+
devtoolsUrl,
|
|
1489
|
+
token: hubAccessToken
|
|
1490
|
+
};
|
|
1244
1491
|
await mkdir(logsDirectory, { recursive: true });
|
|
1245
1492
|
await writeFile(logFilePath, "");
|
|
1246
1493
|
await runDevProjectBootstrap(options.cwd, options.template);
|
|
1247
1494
|
await setupDevProjectWatch(options.cwd, options.template);
|
|
1248
1495
|
if (await isLocalPortInUse(devtoolsPort)) {
|
|
1249
1496
|
console.log(`Syncore devtools hub already running at ws://localhost:${devtoolsPort}. Reusing existing hub/dashboard.`);
|
|
1250
|
-
return;
|
|
1251
|
-
}
|
|
1252
|
-
let projectTargetBackend = null;
|
|
1253
|
-
try {
|
|
1254
|
-
projectTargetBackend = await createProjectTargetBackend(options.cwd);
|
|
1255
|
-
} catch (error) {
|
|
1256
|
-
console.warn(`Project target fallback unavailable: ${formatError(error)}`);
|
|
1497
|
+
return await readDevtoolsSessionState(options.cwd) ?? sessionState;
|
|
1257
1498
|
}
|
|
1499
|
+
await writeDevtoolsSessionState(options.cwd, sessionState);
|
|
1258
1500
|
const httpServer = createServer((_request, response) => {
|
|
1259
1501
|
response.writeHead(200, { "content-type": "application/json" });
|
|
1260
1502
|
response.end(JSON.stringify({
|
|
@@ -1269,8 +1511,19 @@ async function startDevHub(options) {
|
|
|
1269
1511
|
const socketRuntimeIds = /* @__PURE__ */ new Map();
|
|
1270
1512
|
const dashboardSockets = /* @__PURE__ */ new Set();
|
|
1271
1513
|
const dashboardSubscriptions = /* @__PURE__ */ new Map();
|
|
1514
|
+
let relayExternalChange = () => {};
|
|
1515
|
+
const projectTargetExternalChangeSignal = new HubExternalChangeSignal((event) => relayExternalChange(PROJECT_TARGET_RUNTIME_ID, runtimeHellos.get(PROJECT_TARGET_RUNTIME_ID)?.storageIdentity ?? "", event));
|
|
1516
|
+
let projectTargetBackend = null;
|
|
1517
|
+
try {
|
|
1518
|
+
projectTargetBackend = await createProjectTargetBackend(options.cwd, projectTargetExternalChangeSignal);
|
|
1519
|
+
} catch (error) {
|
|
1520
|
+
console.warn(`Project target fallback unavailable: ${formatError(error)}`);
|
|
1521
|
+
}
|
|
1272
1522
|
const hello = {
|
|
1273
1523
|
type: "hello",
|
|
1524
|
+
protocolVersion: SYNCORE_DEVTOOLS_PROTOCOL_VERSION,
|
|
1525
|
+
minSupportedProtocolVersion: SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION,
|
|
1526
|
+
maxSupportedProtocolVersion: SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION,
|
|
1274
1527
|
runtimeId: "syncore-dev-hub",
|
|
1275
1528
|
platform: "dev"
|
|
1276
1529
|
};
|
|
@@ -1278,12 +1531,30 @@ async function startDevHub(options) {
|
|
|
1278
1531
|
runtimeHellos.set(PROJECT_TARGET_RUNTIME_ID, projectTargetBackend.hello);
|
|
1279
1532
|
runtimeEvents.set(PROJECT_TARGET_RUNTIME_ID, []);
|
|
1280
1533
|
}
|
|
1534
|
+
relayExternalChange = (sourceRuntimeId, storageIdentity, event) => {
|
|
1535
|
+
if (!storageIdentity) return;
|
|
1536
|
+
const message = {
|
|
1537
|
+
type: "external.change",
|
|
1538
|
+
runtimeId: sourceRuntimeId,
|
|
1539
|
+
storageIdentity,
|
|
1540
|
+
event
|
|
1541
|
+
};
|
|
1542
|
+
for (const [runtimeId, runtimeHello] of runtimeHellos) {
|
|
1543
|
+
if (runtimeId === sourceRuntimeId || runtimeHello.storageIdentity !== storageIdentity) continue;
|
|
1544
|
+
if (runtimeId === PROJECT_TARGET_RUNTIME_ID) {
|
|
1545
|
+
projectTargetExternalChangeSignal.receive(event);
|
|
1546
|
+
continue;
|
|
1547
|
+
}
|
|
1548
|
+
const targetSocket = runtimeSockets.get(runtimeId);
|
|
1549
|
+
if (targetSocket?.readyState === WebSocket.OPEN) targetSocket.send(JSON.stringify(message));
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1281
1552
|
const appendHubLog = async (event) => {
|
|
1282
1553
|
const runtimeHello = runtimeHellos.get(event.runtimeId);
|
|
1283
|
-
const clientRuntimeIds = [...runtimeHellos.values()].filter((hello) => hello.runtimeId !== "syncore-dev-hub"
|
|
1284
|
-
const clientTargetKeys = [...runtimeHellos.values()].filter((hello) => hello.runtimeId !== "syncore-dev-hub"
|
|
1554
|
+
const clientRuntimeIds = [...runtimeHellos.values()].filter((hello) => hello.runtimeId !== "syncore-dev-hub").map((hello) => hello.runtimeId).sort();
|
|
1555
|
+
const clientTargetKeys = [...runtimeHellos.values()].filter((hello) => hello.runtimeId !== "syncore-dev-hub").map((hello) => hello.storageIdentity ?? `runtime::${hello.runtimeId}`).sort();
|
|
1285
1556
|
const targetIdentity = runtimeHello?.storageIdentity ?? `runtime::${event.runtimeId}`;
|
|
1286
|
-
const targetId = event.runtimeId === "syncore-dev-hub" ? "all" :
|
|
1557
|
+
const targetId = event.runtimeId === "syncore-dev-hub" ? "all" : createPublicTargetId(targetIdentity, clientTargetKeys);
|
|
1287
1558
|
const publicRuntimeId = event.runtimeId === "syncore-dev-hub" ? void 0 : createPublicRuntimeId(event.runtimeId, clientRuntimeIds);
|
|
1288
1559
|
const category = event.type === "query.executed" ? "query" : event.type === "mutation.committed" ? "mutation" : event.type === "action.completed" ? "action" : "system";
|
|
1289
1560
|
const message = event.type === "log" ? event.message : event.type === "query.executed" || event.type === "mutation.committed" || event.type === "action.completed" ? event.functionName : event.type;
|
|
@@ -1300,7 +1571,18 @@ async function startDevHub(options) {
|
|
|
1300
1571
|
event
|
|
1301
1572
|
})}\n`);
|
|
1302
1573
|
};
|
|
1303
|
-
websocketServer.on("connection", (socket) => {
|
|
1574
|
+
websocketServer.on("connection", (socket, request) => {
|
|
1575
|
+
const isBrowserDashboardClient = isAllowedDashboardOrigin(request.headers.origin, dashboardPort);
|
|
1576
|
+
const isAuthorizedDashboardClient = !isBrowserDashboardClient || isAuthorizedDashboardRequest({
|
|
1577
|
+
requestUrl: request.url,
|
|
1578
|
+
originHeader: request.headers.origin,
|
|
1579
|
+
dashboardPort,
|
|
1580
|
+
expectedToken: hubAccessToken
|
|
1581
|
+
});
|
|
1582
|
+
if (isBrowserDashboardClient && !isAuthorizedDashboardClient) {
|
|
1583
|
+
socket.close(1008, "Unauthorized devtools client");
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1304
1586
|
dashboardSockets.add(socket);
|
|
1305
1587
|
socket.send(JSON.stringify(hello));
|
|
1306
1588
|
for (const runtimeHello of runtimeHellos.values()) socket.send(JSON.stringify(runtimeHello));
|
|
@@ -1318,10 +1600,20 @@ async function startDevHub(options) {
|
|
|
1318
1600
|
if (rawPayload.length === 0) return;
|
|
1319
1601
|
const message = JSON.parse(rawPayload);
|
|
1320
1602
|
if (message.type === "ping") {
|
|
1603
|
+
if (!isAuthorizedDashboardClient) {
|
|
1604
|
+
socket.close(1008, "Unauthorized devtools client");
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1321
1607
|
socket.send(JSON.stringify({ type: "pong" }));
|
|
1322
1608
|
return;
|
|
1323
1609
|
}
|
|
1610
|
+
if (message.type === "external.change") {
|
|
1611
|
+
const storageIdentity = runtimeHellos.get(message.runtimeId)?.storageIdentity ?? message.storageIdentity;
|
|
1612
|
+
if (storageIdentity && storageIdentity === message.storageIdentity) relayExternalChange(message.runtimeId, storageIdentity, message.event);
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1324
1615
|
if (message.type === "command") {
|
|
1616
|
+
if (!isAuthorizedDashboardClient) return;
|
|
1325
1617
|
const targetRuntimeId = message.targetRuntimeId;
|
|
1326
1618
|
if (!targetRuntimeId) return;
|
|
1327
1619
|
if (targetRuntimeId === PROJECT_TARGET_RUNTIME_ID && projectTargetBackend) {
|
|
@@ -1342,6 +1634,7 @@ async function startDevHub(options) {
|
|
|
1342
1634
|
return;
|
|
1343
1635
|
}
|
|
1344
1636
|
if (message.type === "subscribe") {
|
|
1637
|
+
if (!isAuthorizedDashboardClient) return;
|
|
1345
1638
|
const targetRuntimeId = message.targetRuntimeId;
|
|
1346
1639
|
if (!targetRuntimeId) return;
|
|
1347
1640
|
const subscriptions = dashboardSubscriptions.get(socket) ?? /* @__PURE__ */ new Map();
|
|
@@ -1375,6 +1668,7 @@ async function startDevHub(options) {
|
|
|
1375
1668
|
return;
|
|
1376
1669
|
}
|
|
1377
1670
|
if (message.type === "unsubscribe") {
|
|
1671
|
+
if (!isAuthorizedDashboardClient) return;
|
|
1378
1672
|
const subscriptions = dashboardSubscriptions.get(socket);
|
|
1379
1673
|
const subscription = subscriptions?.get(message.subscriptionId);
|
|
1380
1674
|
if (!subscription) return;
|
|
@@ -1419,8 +1713,8 @@ async function startDevHub(options) {
|
|
|
1419
1713
|
if (message.type === "event" && message.event.type === "runtime.disconnected") runtimeHellos.delete(message.event.runtimeId);
|
|
1420
1714
|
if (message.type === "event" && message.event.runtimeId !== "syncore-dev-hub") {
|
|
1421
1715
|
const history = runtimeEvents.get(message.event.runtimeId) ?? [];
|
|
1422
|
-
history.
|
|
1423
|
-
runtimeEvents.set(message.event.runtimeId, history.slice(
|
|
1716
|
+
history.push(message.event);
|
|
1717
|
+
runtimeEvents.set(message.event.runtimeId, history.slice(-200));
|
|
1424
1718
|
if (message.event.type === "runtime.disconnected") runtimeEvents.delete(message.event.runtimeId);
|
|
1425
1719
|
appendHubLog(message.event);
|
|
1426
1720
|
} else if (message.type === "event") appendHubLog(message.event);
|
|
@@ -1481,25 +1775,29 @@ async function startDevHub(options) {
|
|
|
1481
1775
|
console.error(`Syncore devtools hub failed: ${formatError(error)}`);
|
|
1482
1776
|
process.exit(1);
|
|
1483
1777
|
});
|
|
1484
|
-
|
|
1485
|
-
(
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
const dashboardRoot = path.resolve(CORE_PACKAGE_ROOT, "..", "..", "apps", "dashboard");
|
|
1491
|
-
if (await fileExists(path.join(dashboardRoot, "vite.config.ts"))) try {
|
|
1492
|
-
await (await (await import("vite")).createServer({
|
|
1493
|
-
configFile: path.join(dashboardRoot, "vite.config.ts"),
|
|
1494
|
-
root: dashboardRoot,
|
|
1495
|
-
server: { port: dashboardPort }
|
|
1496
|
-
})).listen();
|
|
1497
|
-
console.log(`Dashboard shell: http://localhost:${dashboardPort}`);
|
|
1498
|
-
} catch (error) {
|
|
1499
|
-
console.log(`Dashboard source not started automatically: ${formatError(error)}`);
|
|
1500
|
-
}
|
|
1501
|
-
})();
|
|
1778
|
+
await new Promise((resolve, reject) => {
|
|
1779
|
+
httpServer.once("error", reject);
|
|
1780
|
+
httpServer.listen(devtoolsPort, "127.0.0.1", () => {
|
|
1781
|
+
httpServer.off("error", reject);
|
|
1782
|
+
resolve();
|
|
1783
|
+
});
|
|
1502
1784
|
});
|
|
1785
|
+
console.log(`Syncore devtools hub: ws://localhost:${devtoolsPort}`);
|
|
1786
|
+
console.log(`Devtools dashboard token: ${hubAccessToken}`);
|
|
1787
|
+
console.log(`Electron/Node runtimes: set devtoolsUrl to ws://localhost:${devtoolsPort}.`);
|
|
1788
|
+
console.log(`Web/Next apps: connect the dashboard or worker bridge to ws://localhost:${devtoolsPort}.`);
|
|
1789
|
+
console.log("Expo apps: use the same hub URL through LAN or adb reverse while developing.");
|
|
1790
|
+
const dashboardRoot = path.resolve(CORE_PACKAGE_ROOT, "..", "..", "apps", "dashboard");
|
|
1791
|
+
if (await fileExists(path.join(dashboardRoot, "vite.config.ts"))) try {
|
|
1792
|
+
await (await (await import("vite")).createServer({
|
|
1793
|
+
configFile: path.join(dashboardRoot, "vite.config.ts"),
|
|
1794
|
+
root: dashboardRoot,
|
|
1795
|
+
server: { port: dashboardPort }
|
|
1796
|
+
})).listen();
|
|
1797
|
+
console.log(`Dashboard shell: ${sessionState.authenticatedDashboardUrl}`);
|
|
1798
|
+
} catch (error) {
|
|
1799
|
+
console.log(`Dashboard source not started automatically: ${formatError(error)}`);
|
|
1800
|
+
}
|
|
1503
1801
|
const close = () => {
|
|
1504
1802
|
projectTargetBackend?.dispose();
|
|
1505
1803
|
websocketServer.close();
|
|
@@ -1508,6 +1806,29 @@ async function startDevHub(options) {
|
|
|
1508
1806
|
};
|
|
1509
1807
|
process.on("SIGINT", close);
|
|
1510
1808
|
process.on("SIGTERM", close);
|
|
1809
|
+
return sessionState;
|
|
1810
|
+
}
|
|
1811
|
+
async function writeDevtoolsSessionState(cwd, state) {
|
|
1812
|
+
const sessionPath = path.join(cwd, DEVTOOLS_SESSION_FILE);
|
|
1813
|
+
await mkdir(path.dirname(sessionPath), { recursive: true });
|
|
1814
|
+
await writeFile(sessionPath, `${JSON.stringify(state, null, 2)}\n`);
|
|
1815
|
+
}
|
|
1816
|
+
async function readDevtoolsSessionState(cwd) {
|
|
1817
|
+
const sessionPath = path.join(cwd, DEVTOOLS_SESSION_FILE);
|
|
1818
|
+
if (!await fileExists(sessionPath)) return null;
|
|
1819
|
+
try {
|
|
1820
|
+
const source = await readFile(sessionPath, "utf8");
|
|
1821
|
+
const parsed = JSON.parse(source);
|
|
1822
|
+
if (typeof parsed.dashboardUrl !== "string" || typeof parsed.authenticatedDashboardUrl !== "string" || typeof parsed.devtoolsUrl !== "string" || typeof parsed.token !== "string") return null;
|
|
1823
|
+
return {
|
|
1824
|
+
dashboardUrl: parsed.dashboardUrl,
|
|
1825
|
+
authenticatedDashboardUrl: parsed.authenticatedDashboardUrl,
|
|
1826
|
+
devtoolsUrl: parsed.devtoolsUrl,
|
|
1827
|
+
token: parsed.token
|
|
1828
|
+
};
|
|
1829
|
+
} catch {
|
|
1830
|
+
return null;
|
|
1831
|
+
}
|
|
1511
1832
|
}
|
|
1512
1833
|
async function setupDevProjectWatch(cwd, template) {
|
|
1513
1834
|
const snapshot = await createDevWatchSnapshot(cwd);
|
|
@@ -1558,6 +1879,10 @@ async function runDevProjectBootstrap(cwd, template) {
|
|
|
1558
1879
|
else console.log("Schema snapshot updated.");
|
|
1559
1880
|
}
|
|
1560
1881
|
for (const warning of plan.warnings) console.warn(`Syncore dev warning: ${warning}`);
|
|
1882
|
+
if (templateUsesConnectedClients(template)) {
|
|
1883
|
+
console.log("Syncore dev is ready. Codegen refreshed; waiting for a connected client runtime to apply schema locally.");
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1561
1886
|
const appliedCount = await applyProjectMigrations(cwd);
|
|
1562
1887
|
console.log(`Syncore dev is ready. Codegen refreshed; ${appliedCount} migration(s) applied.`);
|
|
1563
1888
|
} catch (error) {
|
|
@@ -1644,6 +1969,6 @@ function toSearchValue(value) {
|
|
|
1644
1969
|
return stableStringify(value);
|
|
1645
1970
|
}
|
|
1646
1971
|
//#endregion
|
|
1647
|
-
export { SYNCORE_MIGRATION_SNAPSHOT_FILE_NAME, VALID_SYNCORE_TEMPLATES, applyProjectMigrations, detectProjectTemplate, fileExists, formatError, getNextMigrationNumber, hasSyncoreProject, importJsonlIntoProject, isLocalPortInUse, loadProjectConfig, loadProjectFunctions, loadProjectSchema, logScaffoldResult, readPackageJson, readStoredSnapshot, resolveDefaultSeedFile, resolvePortFromEnv, resolveProjectTargetConfig, resolveRequestedTemplate, runCodegen, runDevProjectBootstrap, runSyncoreCli, scaffoldProject, slugify, startDevHub, writeStoredSnapshot };
|
|
1972
|
+
export { SYNCORE_MIGRATION_SNAPSHOT_FILE_NAME, VALID_SYNCORE_TEMPLATES, applyProjectMigrations, detectProjectTemplate, fileExists, formatError, getNextMigrationNumber, hasSyncoreProject, importJsonlIntoProject, isLocalPortInUse, loadProjectComponentsManifest, loadProjectConfig, loadProjectFunctions, loadProjectResolvedComponents, loadProjectRootSchema, loadProjectRuntime, loadProjectSchema, logScaffoldResult, readPackageJson, readStoredSnapshot, resolveDefaultSeedFile, resolvePortFromEnv, resolveProjectTargetConfig, resolveRequestedTemplate, runCodegen, runDevProjectBootstrap, runSyncoreCli, scaffoldProject, slugify, startDevHub, templateUsesConnectedClients, writeStoredSnapshot };
|
|
1648
1973
|
|
|
1649
1974
|
//# sourceMappingURL=cli.mjs.map
|