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
|
@@ -1,105 +1,43 @@
|
|
|
1
1
|
import { SyncoreRendererClient, attachNodeIpcRuntime, createNodeIpcMessageEndpoint, createRendererSyncoreBridgeClient, createRendererSyncoreClient, createRendererSyncoreWindowClient, installSyncoreWindowBridge } from "./ipc.mjs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
2
|
import { mkdir, 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";
|
|
8
|
+
import { SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION, SYNCORE_DEVTOOLS_PROTOCOL_VERSION } from "../devtools-protocol/index.js";
|
|
7
9
|
import { SyncoreRuntime, createDevtoolsCommandHandler, createDevtoolsSubscriptionHost } from "../core/index.mjs";
|
|
8
10
|
//#region src/index.ts
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const nodeDevtoolsSqlSupport = {
|
|
12
|
-
analyzeSqlStatement(query) {
|
|
13
|
-
const ast = nodeSqlParser.astify(query, { database: "sqlite" });
|
|
14
|
-
if (Array.isArray(ast)) throw new Error("Only a single SQL statement is supported.");
|
|
15
|
-
switch (ast.type) {
|
|
16
|
-
case "select": return buildReadAnalysis(ast);
|
|
17
|
-
case "update":
|
|
18
|
-
case "delete":
|
|
19
|
-
case "insert":
|
|
20
|
-
case "replace": return buildWriteAnalysis(extractTables(ast.table), false);
|
|
21
|
-
case "create":
|
|
22
|
-
case "drop":
|
|
23
|
-
case "alter": return buildWriteAnalysis(extractTables(ast.table), true);
|
|
24
|
-
default: throw new Error(`Unsupported SQL statement type: ${String(ast.type)}`);
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
ensureSqlMode(analysis, expected) {
|
|
28
|
-
if (expected === "watch") {
|
|
29
|
-
if (analysis.mode !== "read") throw new Error("Live mode supports read-only SQL only.");
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (analysis.mode !== expected) {
|
|
33
|
-
if (expected === "read") throw new Error("Use SQL Write for mutating statements.");
|
|
34
|
-
throw new Error("Use SQL Read or SQL Live for read-only statements.");
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
runReadonlyQuery(databasePath, query) {
|
|
38
|
-
const analysis = this.analyzeSqlStatement(query);
|
|
39
|
-
this.ensureSqlMode(analysis, "read");
|
|
40
|
-
const database = new DatabaseSync(databasePath, { readOnly: true });
|
|
41
|
-
try {
|
|
42
|
-
const statement = database.prepare(query);
|
|
43
|
-
const rows = statement.all();
|
|
44
|
-
const columnsMeta = statement.columns();
|
|
45
|
-
const columns = columnsMeta.map((column) => column.name);
|
|
46
|
-
const observedTables = Array.from(new Set(columnsMeta.map((column) => column.table).filter((table) => typeof table === "string")));
|
|
47
|
-
return {
|
|
48
|
-
columns,
|
|
49
|
-
rows: rows.map((row) => columns.map((column) => row[column])),
|
|
50
|
-
observedTables: observedTables.length > 0 ? observedTables : analysis.readTables
|
|
51
|
-
};
|
|
52
|
-
} finally {
|
|
53
|
-
database.close();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
11
|
+
const DEVTOOLS_META_DIRECTORY = ".syncore-devtools";
|
|
12
|
+
const DATA_SOURCE_ALIAS_PREFIX = "data-source-alias";
|
|
57
13
|
function normalizeData(input) {
|
|
58
14
|
if (typeof input === "string") return Buffer.from(input);
|
|
59
15
|
if (input instanceof Uint8Array) return input;
|
|
60
16
|
return new Uint8Array(input);
|
|
61
17
|
}
|
|
62
|
-
function buildReadAnalysis(ast) {
|
|
63
|
-
const readTables = Array.from(new Set(extractReadTables(ast)));
|
|
64
|
-
return {
|
|
65
|
-
mode: "read",
|
|
66
|
-
readTables,
|
|
67
|
-
writeTables: [],
|
|
68
|
-
schemaChanged: false,
|
|
69
|
-
observedScopes: readTables.length > 0 ? readTables.map((table) => `table:${table}`) : ["all"]
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function buildWriteAnalysis(tables, schemaChanged) {
|
|
73
|
-
const uniqueTables = Array.from(new Set(tables));
|
|
74
|
-
return {
|
|
75
|
-
mode: schemaChanged ? "ddl" : "write",
|
|
76
|
-
readTables: [],
|
|
77
|
-
writeTables: uniqueTables,
|
|
78
|
-
schemaChanged,
|
|
79
|
-
observedScopes: schemaChanged ? ["schema.tables", ...uniqueTables.map((table) => `table:${table}`)] : uniqueTables.length > 0 ? uniqueTables.map((table) => `table:${table}`) : ["all"]
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
function extractReadTables(ast) {
|
|
83
|
-
return (ast.from ?? []).flatMap((entry) => {
|
|
84
|
-
if (entry.table) return [entry.table];
|
|
85
|
-
if (entry.expr?.ast) return extractReadTables(entry.expr.ast);
|
|
86
|
-
return [];
|
|
87
|
-
}).filter((table) => table !== "dual");
|
|
88
|
-
}
|
|
89
|
-
function extractTables(table) {
|
|
90
|
-
if (Array.isArray(table)) return table.map((entry) => entry?.table).filter((value) => typeof value === "string");
|
|
91
|
-
if (table && typeof table === "object") return typeof table.table === "string" ? [table.table] : [];
|
|
92
|
-
if (typeof table === "string") return [table];
|
|
93
|
-
return [];
|
|
94
|
-
}
|
|
95
18
|
function toSqlParameters(params) {
|
|
96
19
|
return params;
|
|
97
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
|
+
*/
|
|
98
34
|
var NodeSqliteDriver = class {
|
|
35
|
+
databasePath;
|
|
99
36
|
database;
|
|
100
37
|
transactionDepth = 0;
|
|
101
|
-
constructor(
|
|
102
|
-
this.
|
|
38
|
+
constructor(databasePath) {
|
|
39
|
+
this.databasePath = databasePath;
|
|
40
|
+
this.database = new DatabaseSync(databasePath);
|
|
103
41
|
this.database.exec("PRAGMA foreign_keys = ON;");
|
|
104
42
|
this.database.exec("PRAGMA journal_mode = WAL;");
|
|
105
43
|
}
|
|
@@ -151,7 +89,21 @@ var NodeSqliteDriver = class {
|
|
|
151
89
|
this.database.close();
|
|
152
90
|
}
|
|
153
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
|
+
*/
|
|
154
105
|
var NodeFileStorageAdapter = class {
|
|
106
|
+
directory;
|
|
155
107
|
constructor(directory) {
|
|
156
108
|
this.directory = directory;
|
|
157
109
|
}
|
|
@@ -211,11 +163,137 @@ var NodeFileStorageAdapter = class {
|
|
|
211
163
|
}
|
|
212
164
|
}
|
|
213
165
|
};
|
|
166
|
+
const SESSION_ADJECTIVES = [
|
|
167
|
+
"Acrobatic",
|
|
168
|
+
"Bold",
|
|
169
|
+
"Cosmic",
|
|
170
|
+
"Daring",
|
|
171
|
+
"Electric",
|
|
172
|
+
"Fierce",
|
|
173
|
+
"Golden",
|
|
174
|
+
"Hidden",
|
|
175
|
+
"Iron",
|
|
176
|
+
"Jade",
|
|
177
|
+
"Keen",
|
|
178
|
+
"Lunar",
|
|
179
|
+
"Mystic",
|
|
180
|
+
"Noble",
|
|
181
|
+
"Orbital",
|
|
182
|
+
"Primal",
|
|
183
|
+
"Quick",
|
|
184
|
+
"Radiant",
|
|
185
|
+
"Shadow",
|
|
186
|
+
"Turbo",
|
|
187
|
+
"Ultra",
|
|
188
|
+
"Vivid",
|
|
189
|
+
"Wicked",
|
|
190
|
+
"Xenon",
|
|
191
|
+
"Zen",
|
|
192
|
+
"Arctic",
|
|
193
|
+
"Binary",
|
|
194
|
+
"Cyber",
|
|
195
|
+
"Digital",
|
|
196
|
+
"Ember",
|
|
197
|
+
"Frozen",
|
|
198
|
+
"Galactic",
|
|
199
|
+
"Hyper",
|
|
200
|
+
"Infra",
|
|
201
|
+
"Jumbo",
|
|
202
|
+
"Kinetic",
|
|
203
|
+
"Liquid",
|
|
204
|
+
"Magnetic",
|
|
205
|
+
"Neon",
|
|
206
|
+
"Onyx",
|
|
207
|
+
"Phantom",
|
|
208
|
+
"Quantum",
|
|
209
|
+
"Rapid",
|
|
210
|
+
"Sonic",
|
|
211
|
+
"Titan",
|
|
212
|
+
"Velvet",
|
|
213
|
+
"Wild",
|
|
214
|
+
"Blazing",
|
|
215
|
+
"Crystal",
|
|
216
|
+
"Dynamic"
|
|
217
|
+
];
|
|
218
|
+
const SESSION_NOUNS = [
|
|
219
|
+
"Phoenix",
|
|
220
|
+
"Dragon",
|
|
221
|
+
"Developer",
|
|
222
|
+
"Hacker",
|
|
223
|
+
"Wizard",
|
|
224
|
+
"Runner",
|
|
225
|
+
"Ranger",
|
|
226
|
+
"Maverick",
|
|
227
|
+
"Spartan",
|
|
228
|
+
"Viking",
|
|
229
|
+
"Sentinel",
|
|
230
|
+
"Guardian",
|
|
231
|
+
"Nomad",
|
|
232
|
+
"Cipher",
|
|
233
|
+
"Vector",
|
|
234
|
+
"Matrix",
|
|
235
|
+
"Prism",
|
|
236
|
+
"Nebula",
|
|
237
|
+
"Comet",
|
|
238
|
+
"Pulse",
|
|
239
|
+
"Vertex",
|
|
240
|
+
"Flux",
|
|
241
|
+
"Storm",
|
|
242
|
+
"Blaze",
|
|
243
|
+
"Frost",
|
|
244
|
+
"Thunder",
|
|
245
|
+
"Drift"
|
|
246
|
+
];
|
|
247
|
+
function generateUniqueSessionName() {
|
|
248
|
+
return `${SESSION_ADJECTIVES[Math.floor(Math.random() * SESSION_ADJECTIVES.length)]} ${SESSION_NOUNS[Math.floor(Math.random() * SESSION_NOUNS.length)]}`;
|
|
249
|
+
}
|
|
250
|
+
function resolvePersistedDataSourceAlias(storageDirectory, storageIdentity) {
|
|
251
|
+
const metaDirectory = path.join(storageDirectory, DEVTOOLS_META_DIRECTORY);
|
|
252
|
+
const aliasId = createHash("sha256").update(storageIdentity).digest("hex").slice(0, 16);
|
|
253
|
+
const aliasPath = path.join(metaDirectory, `${DATA_SOURCE_ALIAS_PREFIX}-${aliasId}.txt`);
|
|
254
|
+
try {
|
|
255
|
+
const existing = readFileSync(aliasPath, "utf8").trim();
|
|
256
|
+
if (existing.length > 0) return existing;
|
|
257
|
+
} catch {}
|
|
258
|
+
const nextValue = generateUniqueSessionName();
|
|
259
|
+
try {
|
|
260
|
+
mkdirSync(metaDirectory, { recursive: true });
|
|
261
|
+
writeFileSync(aliasPath, nextValue, "utf8");
|
|
262
|
+
} catch {}
|
|
263
|
+
return nextValue;
|
|
264
|
+
}
|
|
214
265
|
/**
|
|
215
|
-
* Create a Node or Electron
|
|
266
|
+
* Create a Syncore runtime for Node.js (or Electron’s main process) backed by
|
|
267
|
+
* the built-in `node:sqlite` driver and local file storage.
|
|
268
|
+
*
|
|
269
|
+
* This is the recommended entry point for Node and Electron apps. It wires up
|
|
270
|
+
* the SQL driver, storage adapter, devtools WebSocket connection, and
|
|
271
|
+
* cross-process change signals automatically.
|
|
272
|
+
*
|
|
273
|
+
* ```ts
|
|
274
|
+
* import path from "node:path";
|
|
275
|
+
* import { createNodeSyncoreRuntime } from "syncorejs/node";
|
|
276
|
+
* import schema from "./syncore/schema";
|
|
277
|
+
* import { functions } from "./syncore/_generated/functions";
|
|
278
|
+
*
|
|
279
|
+
* const runtime = createNodeSyncoreRuntime({
|
|
280
|
+
* databasePath: path.join(app.getPath("userData"), "db.sqlite"),
|
|
281
|
+
* storageDirectory: path.join(app.getPath("userData"), "storage"),
|
|
282
|
+
* schema,
|
|
283
|
+
* functions,
|
|
284
|
+
* });
|
|
285
|
+
*
|
|
286
|
+
* await runtime.start();
|
|
287
|
+
* const client = runtime.createClient();
|
|
288
|
+
* ```
|
|
289
|
+
*
|
|
290
|
+
* @param options - Configuration object. See {@link CreateNodeRuntimeOptions}.
|
|
291
|
+
* @returns A configured (but not yet started) {@link SyncoreRuntime}. Call
|
|
292
|
+
* `await runtime.start()` before using the client.
|
|
216
293
|
*/
|
|
217
294
|
function createNodeSyncoreRuntime(options) {
|
|
218
295
|
const resolvedDevtoolsUrl = options.devtoolsUrl ?? resolveDefaultNodeDevtoolsUrl();
|
|
296
|
+
const storageIdentity = `file::${path.resolve(options.databasePath)}`;
|
|
219
297
|
const websocketDevtools = options.devtools === void 0 && resolvedDevtoolsUrl && shouldAutoConnectNodeDevtools() ? createNodeWebSocketDevtoolsSink({
|
|
220
298
|
url: resolvedDevtoolsUrl,
|
|
221
299
|
...options.appName ? { appName: options.appName } : {},
|
|
@@ -224,19 +302,23 @@ function createNodeSyncoreRuntime(options) {
|
|
|
224
302
|
targetKind: "client",
|
|
225
303
|
storageProtocol: "file",
|
|
226
304
|
databaseLabel: path.basename(options.databasePath),
|
|
227
|
-
|
|
305
|
+
dataSourceAlias: resolvePersistedDataSourceAlias(options.storageDirectory, storageIdentity),
|
|
306
|
+
storageIdentity,
|
|
307
|
+
runtimeRole: "app",
|
|
308
|
+
capabilities: createNodeDevtoolsCapabilities()
|
|
228
309
|
}) : void 0;
|
|
229
310
|
const runtimeOptions = {
|
|
230
311
|
schema: options.schema,
|
|
231
312
|
functions: options.functions,
|
|
313
|
+
...options.components ? { components: options.components } : {},
|
|
232
314
|
driver: new NodeSqliteDriver(options.databasePath),
|
|
233
315
|
storage: new NodeFileStorageAdapter(options.storageDirectory),
|
|
234
316
|
platform: options.platform ?? "node"
|
|
235
317
|
};
|
|
236
318
|
if (options.capabilities) runtimeOptions.capabilities = options.capabilities;
|
|
237
|
-
if (options.experimentalPlugins) runtimeOptions.experimentalPlugins = options.experimentalPlugins;
|
|
238
319
|
const resolvedDevtools = options.devtools === false ? void 0 : options.devtools ?? websocketDevtools;
|
|
239
320
|
if (resolvedDevtools) runtimeOptions.devtools = resolvedDevtools;
|
|
321
|
+
if (websocketDevtools?.externalChangeSignal) runtimeOptions.externalChangeSignal = websocketDevtools.externalChangeSignal;
|
|
240
322
|
if (options.scheduler) runtimeOptions.scheduler = options.scheduler;
|
|
241
323
|
const runtime = new SyncoreRuntime(runtimeOptions);
|
|
242
324
|
websocketDevtools?.attachRuntime(runtime);
|
|
@@ -245,15 +327,13 @@ function createNodeSyncoreRuntime(options) {
|
|
|
245
327
|
driver: runtimeOptions.driver,
|
|
246
328
|
schema: options.schema,
|
|
247
329
|
functions: options.functions,
|
|
248
|
-
runtime
|
|
249
|
-
sql: nodeDevtoolsSqlSupport
|
|
330
|
+
admin: runtime.getAdmin()
|
|
250
331
|
}));
|
|
251
332
|
websocketDevtools.attachSubscriptionHost(createDevtoolsSubscriptionHost({
|
|
252
333
|
driver: runtimeOptions.driver,
|
|
253
334
|
schema: options.schema,
|
|
254
335
|
functions: options.functions,
|
|
255
|
-
runtime
|
|
256
|
-
sql: nodeDevtoolsSqlSupport
|
|
336
|
+
admin: runtime.getAdmin()
|
|
257
337
|
}));
|
|
258
338
|
const stop = runtime.stop.bind(runtime);
|
|
259
339
|
runtime.stop = async () => {
|
|
@@ -323,7 +403,8 @@ function bindElectronWindowToSyncoreRuntime(options) {
|
|
|
323
403
|
if (!options.onRendererMessage) {
|
|
324
404
|
if (!options.ipcMain) throw new Error("bindElectronWindowToSyncoreRuntime requires either onRendererMessage() or ipcMain.");
|
|
325
405
|
const listeners = /* @__PURE__ */ new Set();
|
|
326
|
-
const handleRendererMessage = (
|
|
406
|
+
const handleRendererMessage = (event, message) => {
|
|
407
|
+
if (event.sender !== options.window.webContents) return;
|
|
327
408
|
for (const listener of listeners) listener(message);
|
|
328
409
|
};
|
|
329
410
|
options.ipcMain.on(channel, handleRendererMessage);
|
|
@@ -361,6 +442,7 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
361
442
|
let getSummary;
|
|
362
443
|
let onCommand;
|
|
363
444
|
let subscriptionHost;
|
|
445
|
+
const externalChangeListeners = /* @__PURE__ */ new Set();
|
|
364
446
|
const pendingMessages = [];
|
|
365
447
|
let latestHello;
|
|
366
448
|
const connect = () => {
|
|
@@ -369,15 +451,21 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
369
451
|
socket.on("open", () => {
|
|
370
452
|
if (latestHello) sendNow({
|
|
371
453
|
type: "hello",
|
|
454
|
+
protocolVersion: SYNCORE_DEVTOOLS_PROTOCOL_VERSION,
|
|
455
|
+
minSupportedProtocolVersion: SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION,
|
|
456
|
+
maxSupportedProtocolVersion: SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION,
|
|
372
457
|
runtimeId: latestHello.runtimeId,
|
|
373
458
|
platform: latestHello.platform,
|
|
374
459
|
...options.appName ? { appName: options.appName } : {},
|
|
375
460
|
...options.origin ? { origin: options.origin } : {},
|
|
376
461
|
...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {},
|
|
377
462
|
...options.targetKind ? { targetKind: options.targetKind } : {},
|
|
463
|
+
...options.runtimeRole ? { runtimeRole: options.runtimeRole } : {},
|
|
378
464
|
...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
|
|
379
465
|
...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
|
|
380
|
-
...options.
|
|
466
|
+
...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
|
|
467
|
+
...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
|
|
468
|
+
capabilities: options.capabilities ?? createNodeDevtoolsCapabilities()
|
|
381
469
|
});
|
|
382
470
|
flushPendingMessages();
|
|
383
471
|
});
|
|
@@ -386,6 +474,7 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
386
474
|
if (rawPayload.length === 0) return;
|
|
387
475
|
const message = JSON.parse(rawPayload);
|
|
388
476
|
if (message.type === "ping") send({ type: "pong" });
|
|
477
|
+
else if (message.type === "external.change") for (const listener of externalChangeListeners) listener(message.event);
|
|
389
478
|
else if (message.type === "command" && onCommand) onCommand(message.payload).then((responsePayload) => {
|
|
390
479
|
const runtimeId = latestHello?.runtimeId ?? getSummary?.().runtimeId;
|
|
391
480
|
if (!runtimeId) return;
|
|
@@ -448,7 +537,7 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
448
537
|
pendingMessages.push(message);
|
|
449
538
|
};
|
|
450
539
|
connect();
|
|
451
|
-
|
|
540
|
+
const sink = {
|
|
452
541
|
emit(event) {
|
|
453
542
|
if (event.type === "runtime.connected") {
|
|
454
543
|
latestHello = {
|
|
@@ -457,15 +546,21 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
457
546
|
};
|
|
458
547
|
send({
|
|
459
548
|
type: "hello",
|
|
549
|
+
protocolVersion: SYNCORE_DEVTOOLS_PROTOCOL_VERSION,
|
|
550
|
+
minSupportedProtocolVersion: SYNCORE_DEVTOOLS_MIN_SUPPORTED_PROTOCOL_VERSION,
|
|
551
|
+
maxSupportedProtocolVersion: SYNCORE_DEVTOOLS_MAX_SUPPORTED_PROTOCOL_VERSION,
|
|
460
552
|
runtimeId: event.runtimeId,
|
|
461
553
|
platform: event.platform,
|
|
462
554
|
...options.appName ? { appName: options.appName } : {},
|
|
463
555
|
...options.origin ? { origin: options.origin } : {},
|
|
464
556
|
...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {},
|
|
465
557
|
...options.targetKind ? { targetKind: options.targetKind } : {},
|
|
558
|
+
...options.runtimeRole ? { runtimeRole: options.runtimeRole } : {},
|
|
466
559
|
...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
|
|
467
560
|
...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
|
|
468
|
-
...options.
|
|
561
|
+
...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
|
|
562
|
+
...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
|
|
563
|
+
capabilities: options.capabilities ?? createNodeDevtoolsCapabilities()
|
|
469
564
|
});
|
|
470
565
|
}
|
|
471
566
|
send({
|
|
@@ -474,7 +569,7 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
474
569
|
});
|
|
475
570
|
},
|
|
476
571
|
attachRuntime(runtime) {
|
|
477
|
-
getSummary = () => withRuntimeSummaryMeta(runtime.getRuntimeSummary(), options);
|
|
572
|
+
getSummary = () => withRuntimeSummaryMeta(runtime.getAdmin().getRuntimeSummary(), options);
|
|
478
573
|
},
|
|
479
574
|
attachCommandHandler(handler) {
|
|
480
575
|
onCommand = handler;
|
|
@@ -489,6 +584,28 @@ function createNodeWebSocketDevtoolsSink(options) {
|
|
|
489
584
|
socket?.close();
|
|
490
585
|
}
|
|
491
586
|
};
|
|
587
|
+
if (options.storageIdentity) sink.externalChangeSignal = {
|
|
588
|
+
subscribe(listener) {
|
|
589
|
+
externalChangeListeners.add(listener);
|
|
590
|
+
return () => {
|
|
591
|
+
externalChangeListeners.delete(listener);
|
|
592
|
+
};
|
|
593
|
+
},
|
|
594
|
+
publish(event) {
|
|
595
|
+
const runtimeId = latestHello?.runtimeId ?? getSummary?.().runtimeId;
|
|
596
|
+
if (!runtimeId) return;
|
|
597
|
+
send({
|
|
598
|
+
type: "external.change",
|
|
599
|
+
runtimeId,
|
|
600
|
+
storageIdentity: options.storageIdentity,
|
|
601
|
+
event
|
|
602
|
+
});
|
|
603
|
+
},
|
|
604
|
+
close() {
|
|
605
|
+
externalChangeListeners.clear();
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
return sink;
|
|
492
609
|
}
|
|
493
610
|
function withRuntimeSummaryMeta(summary, options) {
|
|
494
611
|
return {
|
|
@@ -497,9 +614,31 @@ function withRuntimeSummaryMeta(summary, options) {
|
|
|
497
614
|
...options.origin ? { origin: options.origin } : {},
|
|
498
615
|
...options.sessionLabel ? { sessionLabel: options.sessionLabel } : {},
|
|
499
616
|
...options.targetKind ? { targetKind: options.targetKind } : {},
|
|
617
|
+
...options.runtimeRole ? { runtimeRole: options.runtimeRole } : {},
|
|
500
618
|
...options.storageProtocol ? { storageProtocol: options.storageProtocol } : {},
|
|
501
619
|
...options.databaseLabel ? { databaseLabel: options.databaseLabel } : {},
|
|
502
|
-
...options.
|
|
620
|
+
...options.dataSourceAlias ? { dataSourceAlias: options.dataSourceAlias } : {},
|
|
621
|
+
...options.storageIdentity ? { storageIdentity: options.storageIdentity } : {},
|
|
622
|
+
capabilities: options.capabilities ?? createNodeDevtoolsCapabilities()
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function createNodeDevtoolsCapabilities() {
|
|
626
|
+
return {
|
|
627
|
+
sql: {
|
|
628
|
+
read: false,
|
|
629
|
+
write: false,
|
|
630
|
+
live: false,
|
|
631
|
+
reason: "SQL Console is provided by the Project Target for this data source."
|
|
632
|
+
},
|
|
633
|
+
data: {
|
|
634
|
+
browse: true,
|
|
635
|
+
mutate: true,
|
|
636
|
+
importExport: true
|
|
637
|
+
},
|
|
638
|
+
scheduler: {
|
|
639
|
+
read: true,
|
|
640
|
+
edit: true
|
|
641
|
+
}
|
|
503
642
|
};
|
|
504
643
|
}
|
|
505
644
|
function shouldAutoConnectNodeDevtools() {
|