syncorejs 0.1.0 → 0.2.0
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/{core/src/cli.d.ts → _vendor/cli/app.d.mts} +4 -2
- package/dist/_vendor/cli/app.d.mts.map +1 -0
- package/dist/_vendor/cli/app.mjs +997 -0
- package/dist/_vendor/cli/app.mjs.map +1 -0
- package/dist/_vendor/cli/context.mjs +180 -0
- package/dist/_vendor/cli/context.mjs.map +1 -0
- package/dist/_vendor/cli/dev-session.mjs +49 -0
- package/dist/_vendor/cli/dev-session.mjs.map +1 -0
- package/dist/_vendor/cli/doctor.mjs +80 -0
- package/dist/_vendor/cli/doctor.mjs.map +1 -0
- package/dist/_vendor/cli/errors.mjs +22 -0
- package/dist/_vendor/cli/errors.mjs.map +1 -0
- package/dist/_vendor/cli/help.mjs +26 -0
- package/dist/_vendor/cli/help.mjs.map +1 -0
- package/dist/_vendor/cli/index.d.mts +2 -0
- package/dist/_vendor/cli/index.mjs +23 -0
- package/dist/_vendor/cli/index.mjs.map +1 -0
- package/dist/_vendor/cli/messages.mjs +32 -0
- package/dist/_vendor/cli/messages.mjs.map +1 -0
- package/dist/_vendor/cli/preflight.mjs +35 -0
- package/dist/_vendor/cli/preflight.mjs.map +1 -0
- package/dist/_vendor/cli/project.mjs +583 -0
- package/dist/_vendor/cli/project.mjs.map +1 -0
- package/dist/_vendor/cli/render.mjs +133 -0
- package/dist/_vendor/cli/render.mjs.map +1 -0
- package/dist/_vendor/cli/targets.mjs +87 -0
- package/dist/_vendor/cli/targets.mjs.map +1 -0
- package/dist/_vendor/core/cli.d.mts +59 -1
- package/dist/_vendor/core/cli.d.mts.map +1 -1
- package/dist/_vendor/core/cli.mjs +528 -75
- package/dist/_vendor/core/cli.mjs.map +1 -1
- package/dist/_vendor/core/index.d.mts +12 -4
- package/dist/_vendor/core/index.d.mts.map +1 -0
- package/dist/_vendor/core/index.mjs +4 -3
- package/dist/_vendor/core/index.mjs.map +1 -1
- package/dist/_vendor/core/runtime/devtools.d.mts +32 -6
- package/dist/_vendor/core/runtime/devtools.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/devtools.mjs +397 -182
- package/dist/_vendor/core/runtime/devtools.mjs.map +1 -1
- package/dist/_vendor/core/runtime/functions.mjs.map +1 -1
- package/dist/_vendor/core/runtime/runtime.d.mts +89 -7
- package/dist/_vendor/core/runtime/runtime.d.mts.map +1 -1
- package/dist/_vendor/core/runtime/runtime.mjs +303 -32
- package/dist/_vendor/core/runtime/runtime.mjs.map +1 -1
- package/dist/_vendor/devtools-protocol/index.d.ts +189 -82
- package/dist/_vendor/devtools-protocol/index.d.ts.map +1 -1
- package/dist/_vendor/devtools-protocol/index.js +39 -0
- package/dist/_vendor/devtools-protocol/index.js.map +1 -0
- package/dist/_vendor/next/config.d.ts.map +1 -1
- package/dist/_vendor/next/config.js +2 -5
- package/dist/_vendor/next/config.js.map +1 -1
- package/dist/_vendor/platform-expo/index.d.ts +15 -5
- package/dist/_vendor/platform-expo/index.d.ts.map +1 -1
- package/dist/_vendor/platform-expo/index.js +33 -3
- package/dist/_vendor/platform-expo/index.js.map +1 -1
- package/dist/_vendor/platform-expo/react.js.map +1 -1
- package/dist/_vendor/platform-node/index.d.mts +10 -5
- package/dist/_vendor/platform-node/index.d.mts.map +1 -1
- package/dist/_vendor/platform-node/index.mjs +145 -35
- package/dist/_vendor/platform-node/index.mjs.map +1 -1
- package/dist/_vendor/platform-node/ipc-react.mjs.map +1 -1
- package/dist/_vendor/platform-web/external-change.d.ts +39 -0
- package/dist/_vendor/platform-web/external-change.d.ts.map +1 -0
- package/dist/_vendor/platform-web/external-change.js +61 -0
- package/dist/_vendor/platform-web/external-change.js.map +1 -0
- package/dist/_vendor/platform-web/index.d.ts +27 -5
- package/dist/_vendor/platform-web/index.d.ts.map +1 -1
- package/dist/_vendor/platform-web/index.js +310 -44
- package/dist/_vendor/platform-web/index.js.map +1 -1
- package/dist/_vendor/platform-web/indexeddb.js.map +1 -1
- package/dist/_vendor/platform-web/opfs.js.map +1 -1
- package/dist/_vendor/platform-web/persistence.js.map +1 -1
- package/dist/_vendor/platform-web/react.js.map +1 -1
- package/dist/_vendor/platform-web/sqljs.js +22 -2
- package/dist/_vendor/platform-web/sqljs.js.map +1 -1
- package/dist/_vendor/schema/definition.js.map +1 -1
- package/dist/_vendor/schema/planner.js.map +1 -1
- package/dist/_vendor/schema/validators.js.map +1 -1
- package/dist/browser-react.d.ts +1 -1
- package/dist/browser-react.js +1 -1
- package/dist/browser.d.ts +6 -7
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +4 -5
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +12 -3
- package/dist/cli.js.map +1 -1
- package/dist/expo-react.d.ts +1 -1
- package/dist/expo-react.js +1 -1
- package/dist/expo.d.ts +1 -2
- package/dist/expo.js +1 -2
- package/dist/index.d.ts +3 -7
- package/dist/index.js +3 -8
- package/dist/next-config.d.ts +1 -2
- package/dist/next-config.js +1 -2
- package/dist/next.d.ts +1 -3
- package/dist/next.js +1 -3
- package/dist/node-ipc-react.d.ts +1 -1
- package/dist/node-ipc-react.js +1 -1
- package/dist/node-ipc.d.ts +1 -2
- package/dist/node-ipc.js +1 -2
- package/dist/node.d.ts +1 -4
- package/dist/node.js +1 -3
- package/dist/react.d.ts +1 -2
- package/dist/react.js +1 -2
- package/dist/svelte.d.ts +1 -2
- package/dist/svelte.js +1 -2
- package/package.json +6 -3
- package/dist/core/src/cli.d.ts.map +0 -1
- package/dist/core/src/cli.js +0 -1196
- package/dist/core/src/cli.js.map +0 -1
- package/dist/core/src/index.js +0 -7
- package/dist/core/src/runtime/devtools.d.ts +0 -7
- package/dist/core/src/runtime/devtools.d.ts.map +0 -1
- package/dist/core/src/runtime/devtools.js +0 -300
- package/dist/core/src/runtime/devtools.js.map +0 -1
- package/dist/core/src/runtime/functions.d.ts +0 -123
- package/dist/core/src/runtime/functions.d.ts.map +0 -1
- package/dist/core/src/runtime/functions.js +0 -71
- package/dist/core/src/runtime/functions.js.map +0 -1
- package/dist/core/src/runtime/id.d.ts +0 -13
- package/dist/core/src/runtime/id.d.ts.map +0 -1
- package/dist/core/src/runtime/id.js +0 -28
- package/dist/core/src/runtime/id.js.map +0 -1
- package/dist/core/src/runtime/runtime.d.ts +0 -371
- package/dist/core/src/runtime/runtime.d.ts.map +0 -1
- package/dist/core/src/runtime/runtime.js +0 -1143
- package/dist/core/src/runtime/runtime.js.map +0 -1
- package/dist/devtools-protocol/src/index.d.ts +0 -201
- package/dist/devtools-protocol/src/index.d.ts.map +0 -1
- package/dist/next/src/config.d.ts +0 -17
- package/dist/next/src/config.d.ts.map +0 -1
- package/dist/next/src/config.js +0 -73
- package/dist/next/src/config.js.map +0 -1
- package/dist/next/src/index.d.ts +0 -80
- package/dist/next/src/index.d.ts.map +0 -1
- package/dist/next/src/index.js +0 -82
- package/dist/next/src/index.js.map +0 -1
- package/dist/platform-expo/src/index.d.ts +0 -96
- package/dist/platform-expo/src/index.d.ts.map +0 -1
- package/dist/platform-expo/src/index.js +0 -198
- package/dist/platform-expo/src/index.js.map +0 -1
- package/dist/platform-expo/src/react.d.ts +0 -26
- package/dist/platform-expo/src/react.d.ts.map +0 -1
- package/dist/platform-expo/src/react.js +0 -30
- package/dist/platform-expo/src/react.js.map +0 -1
- package/dist/platform-node/src/index.d.ts +0 -145
- package/dist/platform-node/src/index.d.ts.map +0 -1
- package/dist/platform-node/src/index.js +0 -407
- package/dist/platform-node/src/index.js.map +0 -1
- package/dist/platform-node/src/ipc-react.d.ts +0 -25
- package/dist/platform-node/src/ipc-react.d.ts.map +0 -1
- package/dist/platform-node/src/ipc-react.js +0 -21
- package/dist/platform-node/src/ipc-react.js.map +0 -1
- package/dist/platform-node/src/ipc.d.ts +0 -76
- package/dist/platform-node/src/ipc.d.ts.map +0 -1
- package/dist/platform-node/src/ipc.js +0 -344
- package/dist/platform-node/src/ipc.js.map +0 -1
- package/dist/platform-web/src/index.d.ts +0 -106
- package/dist/platform-web/src/index.d.ts.map +0 -1
- package/dist/platform-web/src/index.js +0 -311
- package/dist/platform-web/src/index.js.map +0 -1
- package/dist/platform-web/src/indexeddb.js +0 -125
- package/dist/platform-web/src/indexeddb.js.map +0 -1
- package/dist/platform-web/src/opfs.js +0 -146
- package/dist/platform-web/src/opfs.js.map +0 -1
- package/dist/platform-web/src/persistence.d.ts +0 -20
- package/dist/platform-web/src/persistence.d.ts.map +0 -1
- package/dist/platform-web/src/persistence.js +0 -23
- package/dist/platform-web/src/persistence.js.map +0 -1
- package/dist/platform-web/src/react.d.ts +0 -35
- package/dist/platform-web/src/react.d.ts.map +0 -1
- package/dist/platform-web/src/react.js +0 -42
- package/dist/platform-web/src/react.js.map +0 -1
- package/dist/platform-web/src/sqljs.js +0 -133
- package/dist/platform-web/src/sqljs.js.map +0 -1
- package/dist/platform-web/src/worker.d.ts +0 -79
- package/dist/platform-web/src/worker.d.ts.map +0 -1
- package/dist/platform-web/src/worker.js +0 -308
- package/dist/platform-web/src/worker.js.map +0 -1
- package/dist/react/src/index.d.ts +0 -59
- package/dist/react/src/index.d.ts.map +0 -1
- package/dist/react/src/index.js +0 -151
- package/dist/react/src/index.js.map +0 -1
- package/dist/schema/src/definition.d.ts +0 -98
- package/dist/schema/src/definition.d.ts.map +0 -1
- package/dist/schema/src/definition.js +0 -84
- package/dist/schema/src/definition.js.map +0 -1
- package/dist/schema/src/planner.d.ts +0 -42
- package/dist/schema/src/planner.d.ts.map +0 -1
- package/dist/schema/src/planner.js +0 -131
- package/dist/schema/src/planner.js.map +0 -1
- package/dist/schema/src/validators.d.ts +0 -194
- package/dist/schema/src/validators.d.ts.map +0 -1
- package/dist/schema/src/validators.js +0 -158
- package/dist/schema/src/validators.js.map +0 -1
- package/dist/svelte/src/index.d.ts +0 -44
- package/dist/svelte/src/index.d.ts.map +0 -1
- package/dist/svelte/src/index.js +0 -75
- package/dist/svelte/src/index.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateId } from "./id.mjs";
|
|
2
|
-
import { createSchemaSnapshot, diffSchemaSnapshots, parseSchemaSnapshot, renderCreateSearchIndexStatement, renderMigrationSql, searchIndexTableName } from "../../schema/index.js";
|
|
2
|
+
import { createSchemaSnapshot, describeValidator, diffSchemaSnapshots, parseSchemaSnapshot, renderCreateSearchIndexStatement, renderMigrationSql, searchIndexTableName } from "../../schema/index.js";
|
|
3
3
|
import { fromZonedTime, toZonedTime } from "date-fns-tz";
|
|
4
4
|
//#region src/runtime/runtime.ts
|
|
5
5
|
const DEFAULT_MISFIRE_POLICY = { type: "catch_up" };
|
|
@@ -224,9 +224,17 @@ var SyncoreRuntime = class {
|
|
|
224
224
|
activeQueries = /* @__PURE__ */ new Map();
|
|
225
225
|
disabledSearchIndexes = /* @__PURE__ */ new Set();
|
|
226
226
|
recentEvents = [];
|
|
227
|
+
devtoolsListeners = /* @__PURE__ */ new Set();
|
|
228
|
+
devtoolsInvalidationListeners = /* @__PURE__ */ new Set();
|
|
229
|
+
externalChangeSourceId = generateId();
|
|
230
|
+
detachExternalChangeListener;
|
|
231
|
+
pendingExternalChangePromise;
|
|
232
|
+
queuedExternalChange;
|
|
227
233
|
schedulerTimer;
|
|
228
234
|
recurringJobs;
|
|
229
235
|
schedulerPollIntervalMs;
|
|
236
|
+
driverDatabasePath;
|
|
237
|
+
prepared = false;
|
|
230
238
|
started = false;
|
|
231
239
|
constructor(options) {
|
|
232
240
|
this.options = options;
|
|
@@ -235,17 +243,19 @@ var SyncoreRuntime = class {
|
|
|
235
243
|
this.recurringJobs = options.scheduler?.recurringJobs ?? [];
|
|
236
244
|
this.schedulerPollIntervalMs = options.scheduler?.pollIntervalMs ?? 1e3;
|
|
237
245
|
this.capabilities = Object.freeze(this.buildCapabilities());
|
|
246
|
+
this.driverDatabasePath = inferDriverDatabasePath(options.driver);
|
|
247
|
+
this.options.devtools?.attachRuntime?.(this);
|
|
238
248
|
}
|
|
239
249
|
/**
|
|
240
250
|
* Start the local Syncore runtime.
|
|
241
251
|
*/
|
|
242
252
|
async start() {
|
|
243
253
|
if (this.started) return;
|
|
244
|
-
await this.
|
|
245
|
-
await this.reconcileStorageState();
|
|
246
|
-
await this.applySchema();
|
|
247
|
-
await this.syncRecurringJobs();
|
|
254
|
+
await this.prepareForDirectAccess();
|
|
248
255
|
await this.runPluginHook("onStart");
|
|
256
|
+
this.detachExternalChangeListener = this.options.externalChangeSignal?.subscribe((event) => {
|
|
257
|
+
this.handleExternalChangeEvent(event);
|
|
258
|
+
});
|
|
249
259
|
this.schedulerTimer = setInterval(() => {
|
|
250
260
|
this.processDueJobs();
|
|
251
261
|
}, this.schedulerPollIntervalMs);
|
|
@@ -257,6 +267,14 @@ var SyncoreRuntime = class {
|
|
|
257
267
|
timestamp: Date.now()
|
|
258
268
|
});
|
|
259
269
|
}
|
|
270
|
+
async prepareForDirectAccess() {
|
|
271
|
+
if (this.prepared) return;
|
|
272
|
+
await this.ensureSystemTables();
|
|
273
|
+
await this.reconcileStorageState();
|
|
274
|
+
await this.applySchema();
|
|
275
|
+
await this.syncRecurringJobs();
|
|
276
|
+
this.prepared = true;
|
|
277
|
+
}
|
|
260
278
|
/**
|
|
261
279
|
* Stop the local Syncore runtime and release any open resources.
|
|
262
280
|
*/
|
|
@@ -266,6 +284,8 @@ var SyncoreRuntime = class {
|
|
|
266
284
|
this.schedulerTimer = void 0;
|
|
267
285
|
}
|
|
268
286
|
if (this.started) await this.runPluginHook("onStop");
|
|
287
|
+
this.detachExternalChangeListener?.();
|
|
288
|
+
this.detachExternalChangeListener = void 0;
|
|
269
289
|
await this.options.driver.close?.();
|
|
270
290
|
if (this.started) this.emitDevtools({
|
|
271
291
|
type: "runtime.disconnected",
|
|
@@ -285,31 +305,140 @@ var SyncoreRuntime = class {
|
|
|
285
305
|
watchQuery: (reference, ...args) => this.watchQuery(reference, normalizeOptionalArgs(args))
|
|
286
306
|
};
|
|
287
307
|
}
|
|
288
|
-
|
|
308
|
+
async getDevtoolsLiveQuerySnapshot() {
|
|
309
|
+
return {
|
|
310
|
+
summary: this.getRuntimeSummary(),
|
|
311
|
+
activeQueries: this.getActiveQueryInfos(),
|
|
312
|
+
schemaTables: await this.getSchemaTablesForDevtools()
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
getRuntimeSummary() {
|
|
289
316
|
return {
|
|
290
317
|
runtimeId: this.runtimeId,
|
|
291
318
|
platform: this.platform,
|
|
292
319
|
connectedAt: Date.now(),
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
functionName: query.functionName,
|
|
296
|
-
dependencyKeys: [...query.dependencyKeys],
|
|
297
|
-
lastRunAt: query.lastRunAt
|
|
298
|
-
})),
|
|
299
|
-
pendingJobs: [],
|
|
300
|
-
recentEvents: [...this.recentEvents]
|
|
320
|
+
activeQueryCount: this.activeQueries.size,
|
|
321
|
+
recentEventCount: this.recentEvents.length
|
|
301
322
|
};
|
|
302
323
|
}
|
|
324
|
+
getActiveQueryInfos() {
|
|
325
|
+
return [...this.activeQueries.values()].map((query) => ({
|
|
326
|
+
id: query.id,
|
|
327
|
+
functionName: query.functionName,
|
|
328
|
+
dependencyKeys: [...query.dependencyKeys],
|
|
329
|
+
lastRunAt: query.lastRunAt
|
|
330
|
+
}));
|
|
331
|
+
}
|
|
332
|
+
getDriverDatabasePath() {
|
|
333
|
+
return this.driverDatabasePath;
|
|
334
|
+
}
|
|
335
|
+
async cancelScheduledJob(id) {
|
|
336
|
+
await this.prepareForDirectAccess();
|
|
337
|
+
if (((await this.options.driver.run(`UPDATE "_scheduled_functions"
|
|
338
|
+
SET status = 'cancelled', updated_at = ?
|
|
339
|
+
WHERE id = ? AND status = 'scheduled'`, [Date.now(), id])).changes ?? 0) > 0) {
|
|
340
|
+
this.notifySchedulerJobsChanged();
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
async updateScheduledJob(options) {
|
|
346
|
+
await this.prepareForDirectAccess();
|
|
347
|
+
const existing = await this.options.driver.get(`SELECT status, recurring_name FROM "_scheduled_functions" WHERE id = ?`, [options.id]);
|
|
348
|
+
if (!existing || existing.status !== "scheduled" || !existing.recurring_name) return false;
|
|
349
|
+
const now = Date.now();
|
|
350
|
+
const runAt = options.runAt ?? computeNextRun(options.schedule, now);
|
|
351
|
+
if (((await this.options.driver.run(`UPDATE "_scheduled_functions"
|
|
352
|
+
SET args_json = ?, run_at = ?, updated_at = ?, schedule_json = ?, timezone = ?, misfire_policy = ?, window_ms = ?
|
|
353
|
+
WHERE id = ? AND status = 'scheduled' AND recurring_name IS NOT NULL`, [
|
|
354
|
+
stableStringify(options.args),
|
|
355
|
+
runAt,
|
|
356
|
+
now,
|
|
357
|
+
stableStringify(options.schedule),
|
|
358
|
+
"timezone" in options.schedule ? options.schedule.timezone ?? null : null,
|
|
359
|
+
options.misfirePolicy.type,
|
|
360
|
+
options.misfirePolicy.type === "windowed" ? options.misfirePolicy.windowMs : null,
|
|
361
|
+
options.id
|
|
362
|
+
])).changes ?? 0) > 0) {
|
|
363
|
+
this.notifySchedulerJobsChanged();
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
subscribeToDevtoolsEvents(listener) {
|
|
369
|
+
this.devtoolsListeners.add(listener);
|
|
370
|
+
return () => {
|
|
371
|
+
this.devtoolsListeners.delete(listener);
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
subscribeToDevtoolsInvalidations(listener) {
|
|
375
|
+
this.devtoolsInvalidationListeners.add(listener);
|
|
376
|
+
return () => {
|
|
377
|
+
this.devtoolsInvalidationListeners.delete(listener);
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
notifyDevtoolsScopes(scopes) {
|
|
381
|
+
const scopeSet = new Set(scopes);
|
|
382
|
+
if (scopeSet.size === 0) return;
|
|
383
|
+
for (const listener of this.devtoolsInvalidationListeners) listener(scopeSet);
|
|
384
|
+
}
|
|
385
|
+
async runDevtoolsMutation(callback, meta = {}) {
|
|
386
|
+
const mutationId = generateId();
|
|
387
|
+
const startedAt = Date.now();
|
|
388
|
+
const changedTables = /* @__PURE__ */ new Set();
|
|
389
|
+
const storageChanges = [];
|
|
390
|
+
const result = await this.options.driver.withTransaction(async () => callback({ db: this.createDatabaseWriter({
|
|
391
|
+
mutationDepth: 1,
|
|
392
|
+
changedTables,
|
|
393
|
+
storageChanges
|
|
394
|
+
}) }));
|
|
395
|
+
await this.refreshInvalidatedQueries(changedTables, mutationId);
|
|
396
|
+
if (storageChanges.length > 0) await this.refreshAllActiveQueries();
|
|
397
|
+
if (changedTables.size > 0) await this.publishExternalChange({
|
|
398
|
+
scope: "database",
|
|
399
|
+
reason: "commit",
|
|
400
|
+
changedTables: [...changedTables]
|
|
401
|
+
});
|
|
402
|
+
await this.publishStorageChanges(storageChanges);
|
|
403
|
+
this.emitDevtools({
|
|
404
|
+
type: "mutation.committed",
|
|
405
|
+
runtimeId: this.runtimeId,
|
|
406
|
+
mutationId,
|
|
407
|
+
functionName: "__devtools__/mutation",
|
|
408
|
+
changedTables: [...changedTables],
|
|
409
|
+
durationMs: Date.now() - startedAt,
|
|
410
|
+
timestamp: Date.now(),
|
|
411
|
+
...meta.origin ? { origin: meta.origin } : {}
|
|
412
|
+
});
|
|
413
|
+
return result;
|
|
414
|
+
}
|
|
415
|
+
async forceRefreshDevtools(reason, meta = {}) {
|
|
416
|
+
await this.refreshAllActiveQueries();
|
|
417
|
+
await this.publishExternalChange({
|
|
418
|
+
scope: "database",
|
|
419
|
+
reason: "reconcile"
|
|
420
|
+
});
|
|
421
|
+
this.notifyDevtoolsScopes(["all"]);
|
|
422
|
+
this.emitDevtools({
|
|
423
|
+
type: "log",
|
|
424
|
+
runtimeId: this.runtimeId,
|
|
425
|
+
level: "info",
|
|
426
|
+
message: reason,
|
|
427
|
+
timestamp: Date.now(),
|
|
428
|
+
...meta.origin ? { origin: meta.origin } : {}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
303
431
|
getRuntimeId() {
|
|
304
432
|
return this.runtimeId;
|
|
305
433
|
}
|
|
306
|
-
async runQuery(reference, args = {}) {
|
|
434
|
+
async runQuery(reference, args = {}, meta = {}) {
|
|
307
435
|
const definition = this.resolveFunction(reference, "query");
|
|
308
436
|
const dependencyCollector = /* @__PURE__ */ new Set();
|
|
309
437
|
const startedAt = Date.now();
|
|
310
438
|
const result = await this.invokeFunction(definition, args, {
|
|
311
439
|
mutationDepth: 0,
|
|
312
440
|
changedTables: /* @__PURE__ */ new Set(),
|
|
441
|
+
storageChanges: [],
|
|
313
442
|
dependencyCollector
|
|
314
443
|
});
|
|
315
444
|
this.emitDevtools({
|
|
@@ -319,20 +448,30 @@ var SyncoreRuntime = class {
|
|
|
319
448
|
functionName: reference.name,
|
|
320
449
|
dependencies: [...dependencyCollector],
|
|
321
450
|
durationMs: Date.now() - startedAt,
|
|
322
|
-
timestamp: Date.now()
|
|
451
|
+
timestamp: Date.now(),
|
|
452
|
+
...meta.origin ? { origin: meta.origin } : {}
|
|
323
453
|
});
|
|
324
454
|
return result;
|
|
325
455
|
}
|
|
326
|
-
async runMutation(reference, args = {}) {
|
|
456
|
+
async runMutation(reference, args = {}, meta = {}) {
|
|
327
457
|
const definition = this.resolveFunction(reference, "mutation");
|
|
328
458
|
const mutationId = generateId();
|
|
329
459
|
const startedAt = Date.now();
|
|
330
460
|
const changedTables = /* @__PURE__ */ new Set();
|
|
461
|
+
const storageChanges = [];
|
|
331
462
|
const result = await this.options.driver.withTransaction(async () => this.invokeFunction(definition, args, {
|
|
332
463
|
mutationDepth: 1,
|
|
333
|
-
changedTables
|
|
464
|
+
changedTables,
|
|
465
|
+
storageChanges
|
|
334
466
|
}));
|
|
335
467
|
await this.refreshInvalidatedQueries(changedTables, mutationId);
|
|
468
|
+
if (storageChanges.length > 0) await this.refreshAllActiveQueries();
|
|
469
|
+
if (changedTables.size > 0) await this.publishExternalChange({
|
|
470
|
+
scope: "database",
|
|
471
|
+
reason: "commit",
|
|
472
|
+
changedTables: [...changedTables]
|
|
473
|
+
});
|
|
474
|
+
await this.publishStorageChanges(storageChanges);
|
|
336
475
|
this.emitDevtools({
|
|
337
476
|
type: "mutation.committed",
|
|
338
477
|
runtimeId: this.runtimeId,
|
|
@@ -340,18 +479,20 @@ var SyncoreRuntime = class {
|
|
|
340
479
|
functionName: reference.name,
|
|
341
480
|
changedTables: [...changedTables],
|
|
342
481
|
durationMs: Date.now() - startedAt,
|
|
343
|
-
timestamp: Date.now()
|
|
482
|
+
timestamp: Date.now(),
|
|
483
|
+
...meta.origin ? { origin: meta.origin } : {}
|
|
344
484
|
});
|
|
345
485
|
return result;
|
|
346
486
|
}
|
|
347
|
-
async runAction(reference, args = {}) {
|
|
487
|
+
async runAction(reference, args = {}, meta = {}) {
|
|
348
488
|
const definition = this.resolveFunction(reference, "action");
|
|
349
489
|
const actionId = generateId();
|
|
350
490
|
const startedAt = Date.now();
|
|
351
491
|
try {
|
|
352
492
|
const result = await this.invokeFunction(definition, args, {
|
|
353
493
|
mutationDepth: 0,
|
|
354
|
-
changedTables: /* @__PURE__ */ new Set()
|
|
494
|
+
changedTables: /* @__PURE__ */ new Set(),
|
|
495
|
+
storageChanges: []
|
|
355
496
|
});
|
|
356
497
|
this.emitDevtools({
|
|
357
498
|
type: "action.completed",
|
|
@@ -359,7 +500,8 @@ var SyncoreRuntime = class {
|
|
|
359
500
|
actionId,
|
|
360
501
|
functionName: reference.name,
|
|
361
502
|
durationMs: Date.now() - startedAt,
|
|
362
|
-
timestamp: Date.now()
|
|
503
|
+
timestamp: Date.now(),
|
|
504
|
+
...meta.origin ? { origin: meta.origin } : {}
|
|
363
505
|
});
|
|
364
506
|
return result;
|
|
365
507
|
} catch (error) {
|
|
@@ -370,6 +512,7 @@ var SyncoreRuntime = class {
|
|
|
370
512
|
functionName: reference.name,
|
|
371
513
|
durationMs: Date.now() - startedAt,
|
|
372
514
|
timestamp: Date.now(),
|
|
515
|
+
...meta.origin ? { origin: meta.origin } : {},
|
|
373
516
|
error: error instanceof Error ? error.message : String(error)
|
|
374
517
|
});
|
|
375
518
|
throw error;
|
|
@@ -470,7 +613,7 @@ var SyncoreRuntime = class {
|
|
|
470
613
|
}
|
|
471
614
|
createContext(kind, state) {
|
|
472
615
|
const db = kind === "mutation" ? this.createDatabaseWriter(state) : this.createDatabaseReader(state);
|
|
473
|
-
const storage = this.createStorageApi();
|
|
616
|
+
const storage = this.createStorageApi(state);
|
|
474
617
|
const scheduler = this.createSchedulerApi();
|
|
475
618
|
return {
|
|
476
619
|
db,
|
|
@@ -482,7 +625,8 @@ var SyncoreRuntime = class {
|
|
|
482
625
|
const normalizedArgs = normalizeOptionalArgs(args);
|
|
483
626
|
if (kind === "mutation") return this.options.driver.withSavepoint(`sp_${generateId().replace(/-/g, "_")}`, () => this.invokeFunction(this.resolveFunction(reference, "mutation"), normalizedArgs, {
|
|
484
627
|
mutationDepth: state.mutationDepth + 1,
|
|
485
|
-
changedTables: state.changedTables
|
|
628
|
+
changedTables: state.changedTables,
|
|
629
|
+
storageChanges: state.storageChanges
|
|
486
630
|
}));
|
|
487
631
|
return this.runMutation(reference, normalizedArgs);
|
|
488
632
|
},
|
|
@@ -552,7 +696,7 @@ var SyncoreRuntime = class {
|
|
|
552
696
|
}
|
|
553
697
|
};
|
|
554
698
|
}
|
|
555
|
-
createStorageApi() {
|
|
699
|
+
createStorageApi(state) {
|
|
556
700
|
return {
|
|
557
701
|
put: async (input) => {
|
|
558
702
|
const id = generateId();
|
|
@@ -582,6 +726,10 @@ var SyncoreRuntime = class {
|
|
|
582
726
|
operation: "put",
|
|
583
727
|
timestamp: Date.now()
|
|
584
728
|
});
|
|
729
|
+
state.storageChanges.push({
|
|
730
|
+
storageId: id,
|
|
731
|
+
reason: "storage-put"
|
|
732
|
+
});
|
|
585
733
|
return id;
|
|
586
734
|
},
|
|
587
735
|
get: async (id) => {
|
|
@@ -611,6 +759,10 @@ var SyncoreRuntime = class {
|
|
|
611
759
|
operation: "delete",
|
|
612
760
|
timestamp: Date.now()
|
|
613
761
|
});
|
|
762
|
+
state.storageChanges.push({
|
|
763
|
+
storageId: id,
|
|
764
|
+
reason: "storage-delete"
|
|
765
|
+
});
|
|
614
766
|
}
|
|
615
767
|
};
|
|
616
768
|
}
|
|
@@ -630,10 +782,13 @@ var SyncoreRuntime = class {
|
|
|
630
782
|
return this.scheduleJob(value, reference, functionArgs, misfirePolicy);
|
|
631
783
|
},
|
|
632
784
|
cancel: async (id) => {
|
|
633
|
-
await this.
|
|
785
|
+
await this.cancelScheduledJob(id);
|
|
634
786
|
}
|
|
635
787
|
};
|
|
636
788
|
}
|
|
789
|
+
notifySchedulerJobsChanged() {
|
|
790
|
+
this.notifyDevtoolsScopes(["scheduler.jobs"]);
|
|
791
|
+
}
|
|
637
792
|
async ensureSystemTables() {
|
|
638
793
|
await this.options.driver.exec(`
|
|
639
794
|
CREATE TABLE IF NOT EXISTS "_syncore_migrations" (
|
|
@@ -802,6 +957,7 @@ var SyncoreRuntime = class {
|
|
|
802
957
|
misfirePolicy.type,
|
|
803
958
|
misfirePolicy.type === "windowed" ? misfirePolicy.windowMs : null
|
|
804
959
|
]);
|
|
960
|
+
this.notifySchedulerJobsChanged();
|
|
805
961
|
return id;
|
|
806
962
|
}
|
|
807
963
|
async syncRecurringJobs() {
|
|
@@ -825,6 +981,7 @@ var SyncoreRuntime = class {
|
|
|
825
981
|
job.misfirePolicy.type,
|
|
826
982
|
job.misfirePolicy.type === "windowed" ? job.misfirePolicy.windowMs : null
|
|
827
983
|
]);
|
|
984
|
+
this.notifySchedulerJobsChanged();
|
|
828
985
|
}
|
|
829
986
|
}
|
|
830
987
|
async processDueJobs() {
|
|
@@ -850,6 +1007,7 @@ var SyncoreRuntime = class {
|
|
|
850
1007
|
await this.advanceOrFinalizeJob(job, "completed", now);
|
|
851
1008
|
} catch (error) {
|
|
852
1009
|
await this.options.driver.run(`UPDATE "_scheduled_functions" SET status = 'failed', updated_at = ? WHERE id = ?`, [Date.now(), job.id]);
|
|
1010
|
+
this.notifySchedulerJobsChanged();
|
|
853
1011
|
this.emitDevtools({
|
|
854
1012
|
type: "log",
|
|
855
1013
|
runtimeId: this.runtimeId,
|
|
@@ -859,12 +1017,15 @@ var SyncoreRuntime = class {
|
|
|
859
1017
|
});
|
|
860
1018
|
}
|
|
861
1019
|
}
|
|
862
|
-
if (executedJobIds.length > 0)
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1020
|
+
if (executedJobIds.length > 0) {
|
|
1021
|
+
this.emitDevtools({
|
|
1022
|
+
type: "scheduler.tick",
|
|
1023
|
+
runtimeId: this.runtimeId,
|
|
1024
|
+
executedJobIds,
|
|
1025
|
+
timestamp: Date.now()
|
|
1026
|
+
});
|
|
1027
|
+
this.notifySchedulerJobsChanged();
|
|
1028
|
+
}
|
|
868
1029
|
}
|
|
869
1030
|
async advanceOrFinalizeJob(job, terminalStatus, executedAt) {
|
|
870
1031
|
if (!job.recurring_name || !job.schedule_json) {
|
|
@@ -874,6 +1035,7 @@ var SyncoreRuntime = class {
|
|
|
874
1035
|
executedAt,
|
|
875
1036
|
job.id
|
|
876
1037
|
]);
|
|
1038
|
+
this.notifySchedulerJobsChanged();
|
|
877
1039
|
return;
|
|
878
1040
|
}
|
|
879
1041
|
const nextRunAt = computeNextRun(JSON.parse(job.schedule_json), executedAt + 1);
|
|
@@ -885,6 +1047,7 @@ var SyncoreRuntime = class {
|
|
|
885
1047
|
executedAt,
|
|
886
1048
|
job.id
|
|
887
1049
|
]);
|
|
1050
|
+
this.notifySchedulerJobsChanged();
|
|
888
1051
|
}
|
|
889
1052
|
async refreshInvalidatedQueries(changedTables, mutationId) {
|
|
890
1053
|
for (const query of this.activeQueries.values()) {
|
|
@@ -914,6 +1077,94 @@ var SyncoreRuntime = class {
|
|
|
914
1077
|
}
|
|
915
1078
|
for (const listener of record.listeners) listener();
|
|
916
1079
|
}
|
|
1080
|
+
async handleExternalChangeEvent(event) {
|
|
1081
|
+
if (event.sourceId === this.externalChangeSourceId) return;
|
|
1082
|
+
const result = this.options.externalChangeApplier ? await this.options.externalChangeApplier.applyExternalChange(event) : {
|
|
1083
|
+
databaseChanged: event.scope === "database" || event.scope === "all",
|
|
1084
|
+
storageChanged: event.scope === "storage" || event.scope === "all"
|
|
1085
|
+
};
|
|
1086
|
+
await this.processExternalChangeResult(result);
|
|
1087
|
+
}
|
|
1088
|
+
async processExternalChangeResult(result) {
|
|
1089
|
+
if (!result.databaseChanged && !result.storageChanged) return;
|
|
1090
|
+
if (this.pendingExternalChangePromise) {
|
|
1091
|
+
this.queuedExternalChange = {
|
|
1092
|
+
databaseChanged: (this.queuedExternalChange?.databaseChanged ?? false) || result.databaseChanged,
|
|
1093
|
+
storageChanged: (this.queuedExternalChange?.storageChanged ?? false) || result.storageChanged
|
|
1094
|
+
};
|
|
1095
|
+
return this.pendingExternalChangePromise;
|
|
1096
|
+
}
|
|
1097
|
+
this.pendingExternalChangePromise = (async () => {
|
|
1098
|
+
if (result.databaseChanged || result.storageChanged) await this.refreshAllActiveQueries();
|
|
1099
|
+
})();
|
|
1100
|
+
try {
|
|
1101
|
+
await this.pendingExternalChangePromise;
|
|
1102
|
+
} finally {
|
|
1103
|
+
this.pendingExternalChangePromise = void 0;
|
|
1104
|
+
const queued = this.queuedExternalChange;
|
|
1105
|
+
this.queuedExternalChange = void 0;
|
|
1106
|
+
if (queued) await this.processExternalChangeResult(queued);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
async publishExternalChange(event) {
|
|
1110
|
+
await this.options.externalChangeSignal?.publish({
|
|
1111
|
+
...event,
|
|
1112
|
+
sourceId: this.externalChangeSourceId,
|
|
1113
|
+
timestamp: Date.now()
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
async publishStorageChanges(storageChanges) {
|
|
1117
|
+
for (const change of storageChanges) await this.publishExternalChange({
|
|
1118
|
+
scope: "storage",
|
|
1119
|
+
reason: change.reason,
|
|
1120
|
+
storageIds: [change.storageId]
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
async refreshAllActiveQueries() {
|
|
1124
|
+
for (const query of this.activeQueries.values()) await this.rerunActiveQuery(query);
|
|
1125
|
+
}
|
|
1126
|
+
async getSchemaTablesForDevtools() {
|
|
1127
|
+
const tables = [];
|
|
1128
|
+
for (const name of this.options.schema.tableNames()) {
|
|
1129
|
+
const table = this.getTableDefinition(name);
|
|
1130
|
+
const validatorDesc = describeValidator(table.validator);
|
|
1131
|
+
const fields = validatorDesc.kind === "object" ? Object.entries(validatorDesc.shape).map(([fieldName, fieldDesc]) => {
|
|
1132
|
+
const desc = fieldDesc;
|
|
1133
|
+
const optional = desc.kind === "optional";
|
|
1134
|
+
return {
|
|
1135
|
+
name: fieldName,
|
|
1136
|
+
type: optional ? desc.inner?.kind ?? "any" : desc.kind,
|
|
1137
|
+
optional
|
|
1138
|
+
};
|
|
1139
|
+
}) : [];
|
|
1140
|
+
fields.unshift({
|
|
1141
|
+
name: "_id",
|
|
1142
|
+
type: "string",
|
|
1143
|
+
optional: false
|
|
1144
|
+
}, {
|
|
1145
|
+
name: "_creationTime",
|
|
1146
|
+
type: "number",
|
|
1147
|
+
optional: false
|
|
1148
|
+
});
|
|
1149
|
+
let documentCount = 0;
|
|
1150
|
+
try {
|
|
1151
|
+
documentCount = (await this.options.driver.get(`SELECT COUNT(*) as count FROM ${quoteIdentifier(name)}`))?.count ?? 0;
|
|
1152
|
+
} catch {
|
|
1153
|
+
documentCount = 0;
|
|
1154
|
+
}
|
|
1155
|
+
tables.push({
|
|
1156
|
+
name,
|
|
1157
|
+
fields,
|
|
1158
|
+
indexes: table.indexes.map((index) => ({
|
|
1159
|
+
name: index.name,
|
|
1160
|
+
fields: index.fields,
|
|
1161
|
+
unique: false
|
|
1162
|
+
})),
|
|
1163
|
+
documentCount
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
return tables;
|
|
1167
|
+
}
|
|
917
1168
|
async collectQueryDependencies(functionName, args) {
|
|
918
1169
|
const definition = this.resolveFunction({
|
|
919
1170
|
kind: "query",
|
|
@@ -923,6 +1174,7 @@ var SyncoreRuntime = class {
|
|
|
923
1174
|
await this.invokeFunction(definition, args, {
|
|
924
1175
|
mutationDepth: 0,
|
|
925
1176
|
changedTables: /* @__PURE__ */ new Set(),
|
|
1177
|
+
storageChanges: [],
|
|
926
1178
|
dependencyCollector
|
|
927
1179
|
});
|
|
928
1180
|
return dependencyCollector;
|
|
@@ -979,6 +1231,8 @@ var SyncoreRuntime = class {
|
|
|
979
1231
|
this.recentEvents.unshift(event);
|
|
980
1232
|
this.recentEvents.splice(24);
|
|
981
1233
|
this.options.devtools?.emit(event);
|
|
1234
|
+
this.notifyDevtoolsScopes(devtoolsScopesForEvent(event));
|
|
1235
|
+
for (const listener of this.devtoolsListeners) listener(event);
|
|
982
1236
|
}
|
|
983
1237
|
createPluginContext() {
|
|
984
1238
|
return {
|
|
@@ -1037,6 +1291,23 @@ function sortValue(value) {
|
|
|
1037
1291
|
if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
|
|
1038
1292
|
return value;
|
|
1039
1293
|
}
|
|
1294
|
+
function devtoolsScopesForEvent(event) {
|
|
1295
|
+
switch (event.type) {
|
|
1296
|
+
case "runtime.connected":
|
|
1297
|
+
case "runtime.disconnected": return new Set(["runtime.summary", "runtime.activeQueries"]);
|
|
1298
|
+
case "query.executed":
|
|
1299
|
+
case "query.invalidated": return new Set(["runtime.summary", "runtime.activeQueries"]);
|
|
1300
|
+
case "mutation.committed": return new Set(["runtime.summary", ...event.changedTables.map((table) => `table:${table}`)]);
|
|
1301
|
+
case "scheduler.tick": return new Set(["scheduler.jobs", "runtime.summary"]);
|
|
1302
|
+
case "storage.updated": return new Set(["runtime.summary"]);
|
|
1303
|
+
case "action.completed":
|
|
1304
|
+
case "log": return new Set(["runtime.summary"]);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
function inferDriverDatabasePath(driver) {
|
|
1308
|
+
const candidate = driver;
|
|
1309
|
+
return candidate.databasePath ?? candidate.filename;
|
|
1310
|
+
}
|
|
1040
1311
|
function omitSystemFields(document) {
|
|
1041
1312
|
const clone = { ...document };
|
|
1042
1313
|
delete clone._id;
|