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.
- package/dist/_vendor/cli/app.d.mts.map +1 -1
- package/dist/_vendor/cli/app.mjs +8 -5
- package/dist/_vendor/cli/app.mjs.map +1 -1
- 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.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.map +1 -1
- package/dist/_vendor/cli/preflight.mjs.map +1 -1
- package/dist/_vendor/cli/project.mjs +20 -20
- package/dist/_vendor/cli/project.mjs.map +1 -1
- package/dist/_vendor/cli/render.mjs.map +1 -1
- package/dist/_vendor/cli/targets.mjs.map +1 -1
- package/dist/_vendor/core/cli.d.mts +8 -2
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +510 -71
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/devtools-auth.mjs.map +1 -1
- package/dist/_vendor/core/index.d.mts +3 -3
- package/dist/_vendor/core/runtime/components.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/components.mjs.map +1 -1
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +261 -23
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.d.mts +388 -6
- package/dist/_vendor/core/runtime/functions.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs +72 -1
- 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 +12 -6
- package/dist/_vendor/core/runtime/internal/engines/devtoolsEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs +123 -20
- package/dist/_vendor/core/runtime/internal/engines/executionEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs +56 -8
- package/dist/_vendor/core/runtime/internal/engines/reactivityEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs +49 -14
- package/dist/_vendor/core/runtime/internal/engines/schedulerEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs +4 -7
- package/dist/_vendor/core/runtime/internal/engines/schemaEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs +81 -2
- package/dist/_vendor/core/runtime/internal/engines/shared.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs +100 -13
- package/dist/_vendor/core/runtime/internal/engines/storageEngine.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs +42 -7
- package/dist/_vendor/core/runtime/internal/runtimeKernel.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/runtimeStatus.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/systemMeta.mjs.map +1 -1
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs +4 -0
- package/dist/_vendor/core/runtime/internal/transactionCoordinator.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +1100 -12
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +63 -0
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/core/transport.d.mts +2 -0
- package/dist/_vendor/core/transport.d.mts.map +1 -1
- package/dist/_vendor/core/transport.mjs +61 -27
- package/dist/_vendor/core/transport.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +223 -4
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- 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 +86 -18
- package/dist/_vendor/next/index.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +146 -27
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +81 -10
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- 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 +174 -9
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +251 -95
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs +4 -0
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc.d.mts.map +1 -1
- package/dist/_vendor/platform-node/ipc.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +41 -0
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -1
- package/dist/_vendor/platform-web/external-change.js +30 -0
- package/dist/_vendor/platform-web/external-change.js.map +1 -1
- package/dist/_vendor/platform-web/index.d.ts +312 -37
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +247 -25
- 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 +16 -1
- package/dist/_vendor/platform-web/opfs.d.ts.map +1 -1
- package/dist/_vendor/platform-web/opfs.js +41 -3
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.d.ts +85 -1
- 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 +11 -5
- 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 +60 -9
- package/dist/_vendor/platform-web/worker.d.ts.map +1 -1
- package/dist/_vendor/platform-web/worker.js +37 -4
- package/dist/_vendor/platform-web/worker.js.map +1 -1
- package/dist/_vendor/react/index.d.ts +197 -13
- package/dist/_vendor/react/index.d.ts.map +1 -1
- package/dist/_vendor/react/index.js +209 -17
- package/dist/_vendor/react/index.js.map +1 -1
- package/dist/_vendor/schema/definition.d.ts +129 -0
- package/dist/_vendor/schema/definition.d.ts.map +1 -1
- package/dist/_vendor/schema/definition.js +99 -0
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/planner.d.ts.map +1 -1
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.d.ts +180 -4
- package/dist/_vendor/schema/validators.d.ts.map +1 -1
- package/dist/_vendor/schema/validators.js +35 -1
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/_vendor/svelte/index.d.ts +207 -7
- package/dist/_vendor/svelte/index.d.ts.map +1 -1
- package/dist/_vendor/svelte/index.js +201 -6
- 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/index.d.ts +1 -1
- package/package.json +24 -21
|
@@ -1,106 +1,43 @@
|
|
|
1
1
|
import { SyncoreRendererClient, attachNodeIpcRuntime, createNodeIpcMessageEndpoint, createRendererSyncoreBridgeClient, createRendererSyncoreClient, createRendererSyncoreWindowClient, installSyncoreWindowBridge } from "./ipc.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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
|
|
11
|
-
const
|
|
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(
|
|
103
|
-
this.
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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() {
|