syncorejs 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/_vendor/cli/app.d.mts.map +1 -1
  2. package/dist/_vendor/cli/app.mjs +8 -5
  3. package/dist/_vendor/cli/app.mjs.map +1 -1
  4. package/dist/_vendor/cli/context.mjs.map +1 -1
  5. package/dist/_vendor/cli/dev-session.mjs.map +1 -1
  6. package/dist/_vendor/cli/doctor.mjs.map +1 -1
  7. package/dist/_vendor/cli/errors.mjs.map +1 -1
  8. package/dist/_vendor/cli/help.mjs.map +1 -1
  9. package/dist/_vendor/cli/index.mjs +9 -2
  10. package/dist/_vendor/cli/index.mjs.map +1 -1
  11. package/dist/_vendor/cli/messages.mjs.map +1 -1
  12. package/dist/_vendor/cli/preflight.mjs.map +1 -1
  13. package/dist/_vendor/cli/project.mjs +20 -20
  14. package/dist/_vendor/cli/project.mjs.map +1 -1
  15. package/dist/_vendor/cli/render.mjs.map +1 -1
  16. package/dist/_vendor/cli/targets.mjs.map +1 -1
  17. package/dist/_vendor/core/cli.d.mts +8 -2
  18. package/dist/_vendor/core/cli.d.mts.map +1 -1
  19. package/dist/_vendor/core/cli.mjs +510 -71
  20. package/dist/_vendor/core/cli.mjs.map +1 -1
  21. package/dist/_vendor/core/devtools-auth.mjs.map +1 -1
  22. package/dist/_vendor/core/index.d.mts +3 -3
  23. package/dist/_vendor/core/runtime/components.d.mts.map +1 -1
  24. package/dist/_vendor/core/runtime/components.mjs.map +1 -1
  25. package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
  26. package/dist/_vendor/core/runtime/devtools.mjs +261 -23
  27. package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
  28. package/dist/_vendor/core/runtime/functions.d.mts +388 -6
  29. package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
  30. package/dist/_vendor/core/runtime/functions.mjs +72 -1
  31. package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
  32. package/dist/_vendor/core/runtime/id.d.mts.map +1 -1
  33. package/dist/_vendor/core/runtime/id.mjs.map +1 -1
  34. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs +12 -6
  35. package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
  36. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +123 -20
  37. package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
  38. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +56 -8
  39. package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
  40. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +49 -14
  41. package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -1
  42. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +4 -7
  43. package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -1
  44. package/dist/_vendor/core/runtime/internal/engines/shared.mjs +81 -2
  45. package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
  46. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +100 -13
  47. package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
  48. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +42 -7
  49. package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
  50. package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -1
  51. package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -1
  52. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +4 -0
  53. package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -1
  54. package/dist/_vendor/core/runtime/runtime.d.mts +1100 -12
  55. package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
  56. package/dist/_vendor/core/runtime/runtime.mjs +63 -0
  57. package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
  58. package/dist/_vendor/core/transport.d.mts +2 -0
  59. package/dist/_vendor/core/transport.d.mts.map +1 -1
  60. package/dist/_vendor/core/transport.mjs +61 -27
  61. package/dist/_vendor/core/transport.mjs.map +1 -1
  62. package/dist/_vendor/devtools-protocol/index.d.ts +223 -4
  63. package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
  64. package/dist/_vendor/devtools-protocol/index.js.map +1 -1
  65. package/dist/_vendor/next/config.d.ts +3 -4
  66. package/dist/_vendor/next/config.d.ts.map +1 -1
  67. package/dist/_vendor/next/config.js +37 -19
  68. package/dist/_vendor/next/config.js.map +1 -1
  69. package/dist/_vendor/next/index.d.ts +109 -29
  70. package/dist/_vendor/next/index.d.ts.map +1 -1
  71. package/dist/_vendor/next/index.js +86 -18
  72. package/dist/_vendor/next/index.js.map +1 -1
  73. package/dist/_vendor/platform-expo/index.d.ts +146 -27
  74. package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
  75. package/dist/_vendor/platform-expo/index.js +81 -10
  76. package/dist/_vendor/platform-expo/index.js.map +1 -1
  77. package/dist/_vendor/platform-expo/react.js.map +1 -1
  78. package/dist/_vendor/platform-expo/web-sqljs-wasm.js +16 -0
  79. package/dist/_vendor/platform-expo/web-sqljs-wasm.js.map +1 -0
  80. package/dist/_vendor/platform-node/index.d.mts +174 -9
  81. package/dist/_vendor/platform-node/index.d.mts.map +1 -1
  82. package/dist/_vendor/platform-node/index.mjs +251 -95
  83. package/dist/_vendor/platform-node/index.mjs.map +1 -1
  84. package/dist/_vendor/platform-node/ipc-react.mjs +4 -0
  85. package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
  86. package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
  87. package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
  88. package/dist/_vendor/platform-web/external-change.d.ts +41 -0
  89. package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
  90. package/dist/_vendor/platform-web/external-change.js +30 -0
  91. package/dist/_vendor/platform-web/external-change.js.map +1 -1
  92. package/dist/_vendor/platform-web/index.d.ts +312 -37
  93. package/dist/_vendor/platform-web/index.d.ts.map +1 -1
  94. package/dist/_vendor/platform-web/index.js +247 -25
  95. package/dist/_vendor/platform-web/index.js.map +1 -1
  96. package/dist/_vendor/platform-web/indexeddb.d.ts +12 -0
  97. package/dist/_vendor/platform-web/indexeddb.d.ts.map +1 -1
  98. package/dist/_vendor/platform-web/indexeddb.js +10 -0
  99. package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
  100. package/dist/_vendor/platform-web/opfs.d.ts +16 -1
  101. package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
  102. package/dist/_vendor/platform-web/opfs.js +41 -3
  103. package/dist/_vendor/platform-web/opfs.js.map +1 -1
  104. package/dist/_vendor/platform-web/persistence.d.ts +85 -1
  105. package/dist/_vendor/platform-web/persistence.d.ts.map +1 -1
  106. package/dist/_vendor/platform-web/persistence.js +15 -0
  107. package/dist/_vendor/platform-web/persistence.js.map +1 -1
  108. package/dist/_vendor/platform-web/react.d.ts +1 -2
  109. package/dist/_vendor/platform-web/react.d.ts.map +1 -1
  110. package/dist/_vendor/platform-web/react.js +11 -5
  111. package/dist/_vendor/platform-web/react.js.map +1 -1
  112. package/dist/_vendor/platform-web/sqljs.js +10 -1
  113. package/dist/_vendor/platform-web/sqljs.js.map +1 -1
  114. package/dist/_vendor/platform-web/web-sqljs-wasm.js +8 -0
  115. package/dist/_vendor/platform-web/web-sqljs-wasm.js.map +1 -0
  116. package/dist/_vendor/platform-web/worker.d.ts +60 -9
  117. package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
  118. package/dist/_vendor/platform-web/worker.js +37 -4
  119. package/dist/_vendor/platform-web/worker.js.map +1 -1
  120. package/dist/_vendor/react/index.d.ts +197 -13
  121. package/dist/_vendor/react/index.d.ts.map +1 -1
  122. package/dist/_vendor/react/index.js +209 -17
  123. package/dist/_vendor/react/index.js.map +1 -1
  124. package/dist/_vendor/schema/definition.d.ts +129 -0
  125. package/dist/_vendor/schema/definition.d.ts.map +1 -1
  126. package/dist/_vendor/schema/definition.js +99 -0
  127. package/dist/_vendor/schema/definition.js.map +1 -1
  128. package/dist/_vendor/schema/planner.d.ts.map +1 -1
  129. package/dist/_vendor/schema/planner.js.map +1 -1
  130. package/dist/_vendor/schema/validators.d.ts +180 -4
  131. package/dist/_vendor/schema/validators.d.ts.map +1 -1
  132. package/dist/_vendor/schema/validators.js +35 -1
  133. package/dist/_vendor/schema/validators.js.map +1 -1
  134. package/dist/_vendor/svelte/index.d.ts +207 -7
  135. package/dist/_vendor/svelte/index.d.ts.map +1 -1
  136. package/dist/_vendor/svelte/index.js +201 -6
  137. package/dist/_vendor/svelte/index.js.map +1 -1
  138. package/dist/browser.d.ts.map +1 -1
  139. package/dist/cli.js +3 -1
  140. package/dist/cli.js.map +1 -1
  141. package/dist/index.d.ts +1 -1
  142. package/package.json +24 -21
@@ -1,106 +1,43 @@
1
1
  import { SyncoreRendererClient, attachNodeIpcRuntime, createNodeIpcMessageEndpoint, createRendererSyncoreBridgeClient, createRendererSyncoreClient, createRendererSyncoreWindowClient, installSyncoreWindowBridge } from "./ipc.mjs";
2
- import { createRequire } from "node:module";
3
- import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
2
+ import { mkdir, open, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
3
+ import { createHash } from "node:crypto";
4
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
5
  import path from "node:path";
5
6
  import { DatabaseSync } from "node:sqlite";
6
7
  import WebSocket from "ws";
7
8
  import { SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_PROTOCOL_VERSION } from "../devtools-protocol/index.js";
8
9
  import { SyncoreRuntime, createDevtoolsCommandHandler, createDevtoolsSubscriptionHost } from "../core/index.mjs";
9
10
  //#region src/index.ts
10
- const { Parser: NodeSqlParser } = createRequire(import.meta.url)("node-sql-parser");
11
- const nodeSqlParser = new NodeSqlParser();
12
- const nodeDevtoolsSqlSupport = {
13
- analyzeSqlStatement(query) {
14
- const ast = nodeSqlParser.astify(query, { database: "sqlite" });
15
- if (Array.isArray(ast)) throw new Error("Only a single SQL statement is supported.");
16
- switch (ast.type) {
17
- case "select": return buildReadAnalysis(ast);
18
- case "update":
19
- case "delete":
20
- case "insert":
21
- case "replace": return buildWriteAnalysis(extractTables(ast.table), false);
22
- case "create":
23
- case "drop":
24
- case "alter": return buildWriteAnalysis(extractTables(ast.table), true);
25
- default: throw new Error(`Unsupported SQL statement type: ${String(ast.type)}`);
26
- }
27
- },
28
- ensureSqlMode(analysis, expected) {
29
- if (expected === "watch") {
30
- if (analysis.mode !== "read") throw new Error("Live mode supports read-only SQL only.");
31
- return;
32
- }
33
- if (analysis.mode !== expected) {
34
- if (expected === "read") throw new Error("Use SQL Write for mutating statements.");
35
- throw new Error("Use SQL Read or SQL Live for read-only statements.");
36
- }
37
- },
38
- runReadonlyQuery(databasePath, query) {
39
- const analysis = this.analyzeSqlStatement(query);
40
- this.ensureSqlMode(analysis, "read");
41
- const database = new DatabaseSync(databasePath, { readOnly: true });
42
- try {
43
- const statement = database.prepare(query);
44
- const rows = statement.all();
45
- const columnsMeta = statement.columns();
46
- const columns = columnsMeta.map((column) => column.name);
47
- const observedTables = Array.from(new Set(columnsMeta.map((column) => column.table).filter((table) => typeof table === "string")));
48
- return {
49
- columns,
50
- rows: rows.map((row) => columns.map((column) => row[column])),
51
- observedTables: observedTables.length > 0 ? observedTables : analysis.readTables
52
- };
53
- } finally {
54
- database.close();
55
- }
56
- }
57
- };
11
+ const DEVTOOLS_META_DIRECTORY = ".syncore-devtools";
12
+ const DATA_SOURCE_ALIAS_PREFIX = "data-source-alias";
58
13
  function normalizeData(input) {
59
14
  if (typeof input === "string") return Buffer.from(input);
60
15
  if (input instanceof Uint8Array) return input;
61
16
  return new Uint8Array(input);
62
17
  }
63
- function buildReadAnalysis(ast) {
64
- const readTables = Array.from(new Set(extractReadTables(ast)));
65
- return {
66
- mode: "read",
67
- readTables,
68
- writeTables: [],
69
- schemaChanged: false,
70
- observedScopes: readTables.length > 0 ? readTables.map((table) => `table:${table}`) : ["all"]
71
- };
72
- }
73
- function buildWriteAnalysis(tables, schemaChanged) {
74
- const uniqueTables = Array.from(new Set(tables));
75
- return {
76
- mode: schemaChanged ? "ddl" : "write",
77
- readTables: [],
78
- writeTables: uniqueTables,
79
- schemaChanged,
80
- observedScopes: schemaChanged ? ["schema.tables", ...uniqueTables.map((table) => `table:${table}`)] : uniqueTables.length > 0 ? uniqueTables.map((table) => `table:${table}`) : ["all"]
81
- };
82
- }
83
- function extractReadTables(ast) {
84
- return (ast.from ?? []).flatMap((entry) => {
85
- if (entry.table) return [entry.table];
86
- if (entry.expr?.ast) return extractReadTables(entry.expr.ast);
87
- return [];
88
- }).filter((table) => table !== "dual");
89
- }
90
- function extractTables(table) {
91
- if (Array.isArray(table)) return table.map((entry) => entry?.table).filter((value) => typeof value === "string");
92
- if (table && typeof table === "object") return typeof table.table === "string" ? [table.table] : [];
93
- if (typeof table === "string") return [table];
94
- return [];
95
- }
96
18
  function toSqlParameters(params) {
97
19
  return params;
98
20
  }
21
+ /**
22
+ * SQLite driver backed by Node.js’s built-in `node:sqlite` module (Node 22+).
23
+ *
24
+ * Opens the database at `databasePath` with `WAL` journal mode and foreign-key
25
+ * enforcement enabled. The file is created if it does not exist.
26
+ *
27
+ * ```ts
28
+ * const driver = new NodeSqliteDriver("./data/app.db");
29
+ * ```
30
+ *
31
+ * In most cases you should use {@link createNodeSyncoreRuntime} which
32
+ * instantiates this driver automatically from your `databasePath` option.
33
+ */
99
34
  var NodeSqliteDriver = class {
35
+ databasePath;
100
36
  database;
101
37
  transactionDepth = 0;
102
- constructor(filename) {
103
- this.database = new DatabaseSync(filename);
38
+ constructor(databasePath) {
39
+ this.databasePath = databasePath;
40
+ this.database = new DatabaseSync(databasePath);
104
41
  this.database.exec("PRAGMA foreign_keys = ON;");
105
42
  this.database.exec("PRAGMA journal_mode = WAL;");
106
43
  }
@@ -152,7 +89,21 @@ var NodeSqliteDriver = class {
152
89
  this.database.close();
153
90
  }
154
91
  };
92
+ /**
93
+ * Blob storage adapter that reads and writes files in a local directory.
94
+ *
95
+ * Each stored object is saved as a flat file named by its ID inside
96
+ * `directory`. The directory is created automatically on first write.
97
+ *
98
+ * ```ts
99
+ * const storage = new NodeFileStorageAdapter("./data/storage");
100
+ * ```
101
+ *
102
+ * In most cases you should use {@link createNodeSyncoreRuntime} which
103
+ * instantiates this adapter automatically from your `storageDirectory` option.
104
+ */
155
105
  var NodeFileStorageAdapter = class {
106
+ directory;
156
107
  constructor(directory) {
157
108
  this.directory = directory;
158
109
  }
@@ -191,6 +142,19 @@ var NodeFileStorageAdapter = class {
191
142
  return null;
192
143
  }
193
144
  }
145
+ async readRange(id, offset, length) {
146
+ let handle;
147
+ try {
148
+ handle = await open(this.filePath(id), "r");
149
+ const buffer = Buffer.alloc(Math.max(length, 0));
150
+ const result = await handle.read(buffer, 0, buffer.byteLength, Math.max(offset, 0));
151
+ return buffer.subarray(0, result.bytesRead);
152
+ } catch {
153
+ return null;
154
+ } finally {
155
+ await handle?.close();
156
+ }
157
+ }
194
158
  async delete(id) {
195
159
  await rm(this.filePath(id), { force: true });
196
160
  }
@@ -212,11 +176,137 @@ var NodeFileStorageAdapter = class {
212
176
  }
213
177
  }
214
178
  };
179
+ const SESSION_ADJECTIVES = [
180
+ "Acrobatic",
181
+ "Bold",
182
+ "Cosmic",
183
+ "Daring",
184
+ "Electric",
185
+ "Fierce",
186
+ "Golden",
187
+ "Hidden",
188
+ "Iron",
189
+ "Jade",
190
+ "Keen",
191
+ "Lunar",
192
+ "Mystic",
193
+ "Noble",
194
+ "Orbital",
195
+ "Primal",
196
+ "Quick",
197
+ "Radiant",
198
+ "Shadow",
199
+ "Turbo",
200
+ "Ultra",
201
+ "Vivid",
202
+ "Wicked",
203
+ "Xenon",
204
+ "Zen",
205
+ "Arctic",
206
+ "Binary",
207
+ "Cyber",
208
+ "Digital",
209
+ "Ember",
210
+ "Frozen",
211
+ "Galactic",
212
+ "Hyper",
213
+ "Infra",
214
+ "Jumbo",
215
+ "Kinetic",
216
+ "Liquid",
217
+ "Magnetic",
218
+ "Neon",
219
+ "Onyx",
220
+ "Phantom",
221
+ "Quantum",
222
+ "Rapid",
223
+ "Sonic",
224
+ "Titan",
225
+ "Velvet",
226
+ "Wild",
227
+ "Blazing",
228
+ "Crystal",
229
+ "Dynamic"
230
+ ];
231
+ const SESSION_NOUNS = [
232
+ "Phoenix",
233
+ "Dragon",
234
+ "Developer",
235
+ "Hacker",
236
+ "Wizard",
237
+ "Runner",
238
+ "Ranger",
239
+ "Maverick",
240
+ "Spartan",
241
+ "Viking",
242
+ "Sentinel",
243
+ "Guardian",
244
+ "Nomad",
245
+ "Cipher",
246
+ "Vector",
247
+ "Matrix",
248
+ "Prism",
249
+ "Nebula",
250
+ "Comet",
251
+ "Pulse",
252
+ "Vertex",
253
+ "Flux",
254
+ "Storm",
255
+ "Blaze",
256
+ "Frost",
257
+ "Thunder",
258
+ "Drift"
259
+ ];
260
+ function generateUniqueSessionName() {
261
+ return `${SESSION_ADJECTIVES[Math.floor(Math.random() * SESSION_ADJECTIVES.length)]} ${SESSION_NOUNS[Math.floor(Math.random() * SESSION_NOUNS.length)]}`;
262
+ }
263
+ function resolvePersistedDataSourceAlias(storageDirectory, storageIdentity) {
264
+ const metaDirectory = path.join(storageDirectory, DEVTOOLS_META_DIRECTORY);
265
+ const aliasId = createHash("sha256").update(storageIdentity).digest("hex").slice(0, 16);
266
+ const aliasPath = path.join(metaDirectory, `${DATA_SOURCE_ALIAS_PREFIX}-${aliasId}.txt`);
267
+ try {
268
+ const existing = readFileSync(aliasPath, "utf8").trim();
269
+ if (existing.length > 0) return existing;
270
+ } catch {}
271
+ const nextValue = generateUniqueSessionName();
272
+ try {
273
+ mkdirSync(metaDirectory, { recursive: true });
274
+ writeFileSync(aliasPath, nextValue, "utf8");
275
+ } catch {}
276
+ return nextValue;
277
+ }
215
278
  /**
216
- * Create a Node or Electron runtime backed by SQLite and local file storage.
279
+ * Create a Syncore runtime for Node.js (or Electron’s main process) backed by
280
+ * the built-in `node:sqlite` driver and local file storage.
281
+ *
282
+ * This is the recommended entry point for Node and Electron apps. It wires up
283
+ * the SQL driver, storage adapter, devtools WebSocket connection, and
284
+ * cross-process change signals automatically.
285
+ *
286
+ * ```ts
287
+ * import path from "node:path";
288
+ * import { createNodeSyncoreRuntime } from "syncorejs/node";
289
+ * import schema from "./syncore/schema";
290
+ * import { functions } from "./syncore/_generated/functions";
291
+ *
292
+ * const runtime = createNodeSyncoreRuntime({
293
+ * databasePath: path.join(app.getPath("userData"), "db.sqlite"),
294
+ * storageDirectory: path.join(app.getPath("userData"), "storage"),
295
+ * schema,
296
+ * functions,
297
+ * });
298
+ *
299
+ * await runtime.start();
300
+ * const client = runtime.createClient();
301
+ * ```
302
+ *
303
+ * @param options - Configuration object. See {@link CreateNodeRuntimeOptions}.
304
+ * @returns A configured (but not yet started) SyncoreRuntime. Call
305
+ * `await runtime.start()` before using the client.
217
306
  */
218
307
  function createNodeSyncoreRuntime(options) {
219
308
  const resolvedDevtoolsUrl = options.devtoolsUrl ?? resolveDefaultNodeDevtoolsUrl();
309
+ const storageIdentity = `file::${path.resolve(options.databasePath)}`;
220
310
  const websocketDevtools = options.devtools === void 0 && resolvedDevtoolsUrl && shouldAutoConnectNodeDevtools() ? createNodeWebSocketDevtoolsSink({
221
311
  url: resolvedDevtoolsUrl,
222
312
  ...options.appName ? { appName: options.appName } : {},
@@ -225,7 +315,10 @@ function createNodeSyncoreRuntime(options) {
225
315
  targetKind: "client",
226
316
  storageProtocol: "file",
227
317
  databaseLabel: path.basename(options.databasePath),
228
- storageIdentity: `file::${path.resolve(options.databasePath)}`
318
+ dataSourceAlias: resolvePersistedDataSourceAlias(options.storageDirectory, storageIdentity),
319
+ storageIdentity,
320
+ runtimeRole: "app",
321
+ capabilities: createNodeDevtoolsCapabilities()
229
322
  }) : void 0;
230
323
  const runtimeOptions = {
231
324
  schema: options.schema,
@@ -233,11 +326,17 @@ function createNodeSyncoreRuntime(options) {
233
326
  ...options.components ? { components: options.components } : {},
234
327
  driver: new NodeSqliteDriver(options.databasePath),
235
328
  storage: new NodeFileStorageAdapter(options.storageDirectory),
329
+ runtimeCapabilities: { storage: {
330
+ available: true,
331
+ protocol: "file",
332
+ supportsRange: true
333
+ } },
236
334
  platform: options.platform ?? "node"
237
335
  };
238
336
  if (options.capabilities) runtimeOptions.capabilities = options.capabilities;
239
337
  const resolvedDevtools = options.devtools === false ? void 0 : options.devtools ?? websocketDevtools;
240
338
  if (resolvedDevtools) runtimeOptions.devtools = resolvedDevtools;
339
+ if (websocketDevtools?.externalChangeSignal) runtimeOptions.externalChangeSignal = websocketDevtools.externalChangeSignal;
241
340
  if (options.scheduler) runtimeOptions.scheduler = options.scheduler;
242
341
  const runtime = new SyncoreRuntime(runtimeOptions);
243
342
  websocketDevtools?.attachRuntime(runtime);
@@ -246,15 +345,13 @@ function createNodeSyncoreRuntime(options) {
246
345
  driver: runtimeOptions.driver,
247
346
  schema: options.schema,
248
347
  functions: options.functions,
249
- admin: runtime.getAdmin(),
250
- sql: nodeDevtoolsSqlSupport
348
+ admin: runtime.getAdmin()
251
349
  }));
252
350
  websocketDevtools.attachSubscriptionHost(createDevtoolsSubscriptionHost({
253
351
  driver: runtimeOptions.driver,
254
352
  schema: options.schema,
255
353
  functions: options.functions,
256
- admin: runtime.getAdmin(),
257
- sql: nodeDevtoolsSqlSupport
354
+ admin: runtime.getAdmin()
258
355
  }));
259
356
  const stop = runtime.stop.bind(runtime);
260
357
  runtime.stop = async () => {
@@ -363,6 +460,7 @@ function createNodeWebSocketDevtoolsSink(options) {
363
460
  let getSummary;
364
461
  let onCommand;
365
462
  let subscriptionHost;
463
+ const externalChangeListeners = /* @__PURE__ */ new Set();
366
464
  const pendingMessages = [];
367
465
  let latestHello;
368
466
  const connect = () => {
@@ -380,9 +478,12 @@ function createNodeWebSocketDevtoolsSink(options) {
380
478
  ...options.origin ? { origin: options.origin } : {},
381
479
  ...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {},
382
480
  ...options.targetKind ? { targetKind: options.targetKind } : {},
481
+ ...options.runtimeRole ? { runtimeRole: options.runtimeRole } : {},
383
482
  ...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
384
483
  ...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
385
- ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {}
484
+ ...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
485
+ ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
486
+ capabilities: options.capabilities ?? createNodeDevtoolsCapabilities()
386
487
  });
387
488
  flushPendingMessages();
388
489
  });
@@ -391,6 +492,7 @@ function createNodeWebSocketDevtoolsSink(options) {
391
492
  if (rawPayload.length === 0) return;
392
493
  const message = JSON.parse(rawPayload);
393
494
  if (message.type === "ping") send({ type: "pong" });
495
+ else if (message.type === "external.change") for (const listener of externalChangeListeners) listener(message.event);
394
496
  else if (message.type === "command" && onCommand) onCommand(message.payload).then((responsePayload) => {
395
497
  const runtimeId = latestHello?.runtimeId ?? getSummary?.().runtimeId;
396
498
  if (!runtimeId) return;
@@ -453,7 +555,7 @@ function createNodeWebSocketDevtoolsSink(options) {
453
555
  pendingMessages.push(message);
454
556
  };
455
557
  connect();
456
- return {
558
+ const sink = {
457
559
  emit(event) {
458
560
  if (event.type === "runtime.connected") {
459
561
  latestHello = {
@@ -471,9 +573,12 @@ function createNodeWebSocketDevtoolsSink(options) {
471
573
  ...options.origin ? { origin: options.origin } : {},
472
574
  ...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {},
473
575
  ...options.targetKind ? { targetKind: options.targetKind } : {},
576
+ ...options.runtimeRole ? { runtimeRole: options.runtimeRole } : {},
474
577
  ...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
475
578
  ...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
476
- ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {}
579
+ ...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
580
+ ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
581
+ capabilities: options.capabilities ?? createNodeDevtoolsCapabilities()
477
582
  });
478
583
  }
479
584
  send({
@@ -497,6 +602,28 @@ function createNodeWebSocketDevtoolsSink(options) {
497
602
  socket?.close();
498
603
  }
499
604
  };
605
+ if (options.storageIdentity) sink.externalChangeSignal = {
606
+ subscribe(listener) {
607
+ externalChangeListeners.add(listener);
608
+ return () => {
609
+ externalChangeListeners.delete(listener);
610
+ };
611
+ },
612
+ publish(event) {
613
+ const runtimeId = latestHello?.runtimeId ?? getSummary?.().runtimeId;
614
+ if (!runtimeId) return;
615
+ send({
616
+ type: "external.change",
617
+ runtimeId,
618
+ storageIdentity: options.storageIdentity,
619
+ event
620
+ });
621
+ },
622
+ close() {
623
+ externalChangeListeners.clear();
624
+ }
625
+ };
626
+ return sink;
500
627
  }
501
628
  function withRuntimeSummaryMeta(summary, options) {
502
629
  return {
@@ -505,9 +632,38 @@ function withRuntimeSummaryMeta(summary, options) {
505
632
  ...options.origin ? { origin: options.origin } : {},
506
633
  ...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {},
507
634
  ...options.targetKind ? { targetKind: options.targetKind } : {},
635
+ ...options.runtimeRole ? { runtimeRole: options.runtimeRole } : {},
508
636
  ...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
509
637
  ...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
510
- ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {}
638
+ ...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
639
+ ...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
640
+ capabilities: options.capabilities ?? createNodeDevtoolsCapabilities()
641
+ };
642
+ }
643
+ function createNodeDevtoolsCapabilities() {
644
+ return {
645
+ sql: {
646
+ read: false,
647
+ write: false,
648
+ live: false,
649
+ reason: "SQL Console is provided by the Project Target for this data source."
650
+ },
651
+ data: {
652
+ browse: true,
653
+ mutate: true,
654
+ importExport: true
655
+ },
656
+ storage: {
657
+ browse: true,
658
+ download: true,
659
+ readRange: true,
660
+ delete: true,
661
+ maxPreviewBytes: 8e4
662
+ },
663
+ scheduler: {
664
+ read: true,
665
+ edit: true
666
+ }
511
667
  };
512
668
  }
513
669
  function shouldAutoConnectNodeDevtools() {