@spooky-sync/core 0.0.1-canary.69 → 0.0.1-canary.70
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/index.d.ts +102 -2
- package/dist/index.js +1066 -129
- package/dist/otel/index.d.ts +1 -1
- package/dist/types.d.ts +74 -1
- package/package.json +2 -2
- package/src/build-globals.d.ts +6 -0
- package/src/events/index.ts +3 -0
- package/src/modules/cache/index.ts +13 -6
- package/src/modules/crdt/index.ts +9 -1
- package/src/modules/data/data.status.test.ts +108 -0
- package/src/modules/data/index.ts +436 -56
- package/src/modules/data/window-query.test.ts +52 -0
- package/src/modules/data/window-query.ts +130 -0
- package/src/modules/devtools/index.ts +54 -1
- package/src/modules/devtools/versions.test.ts +74 -0
- package/src/modules/devtools/versions.ts +81 -0
- package/src/modules/sync/engine.ts +43 -29
- package/src/modules/sync/sync.ts +247 -55
- package/src/modules/sync/utils.test.ts +80 -0
- package/src/modules/sync/utils.ts +72 -0
- package/src/services/database/local.test.ts +33 -0
- package/src/services/database/local.ts +182 -23
- package/src/services/persistence/resilient.ts +8 -1
- package/src/services/stream-processor/index.ts +148 -5
- package/src/services/stream-processor/permissions.test.ts +47 -0
- package/src/services/stream-processor/permissions.ts +53 -0
- package/src/services/stream-processor/stream-processor.batch.test.ts +136 -0
- package/src/services/stream-processor/wasm-types.ts +16 -0
- package/src/sp00ky.ts +86 -6
- package/src/types.ts +85 -0
- package/src/utils/index.ts +13 -3
- package/tsdown.config.ts +54 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { A as Logger$1, C as RunOptions, D as StoreType, E as Sp00kyQueryResultPromise, M as EventSystem, O as TimingPhase, S as RegistrationTimings, T as Sp00kyQueryResult, _ as QueryTimeToLive, a as MutationCallback, b as RecordVersionArray, c as PersistenceClient, d as QueryConfig, f as QueryConfigRecord, g as QueryStatusCallback, h as QueryStatus, i as MATERIALIZATION_SAMPLE_WINDOW, j as EventDefinition, k as UpdateOptions, l as PhaseStat, m as QueryState, n as EventSubscriptionOptions, o as MutationEvent, p as QueryHash, r as Level, s as MutationEventType, t as DebounceOptions, u as PinoTransmit, v as QueryTimings, w as Sp00kyConfig, x as RecordVersionDiff, y as QueryUpdateCallback } from "./types.js";
|
|
2
2
|
import * as surrealdb0 from "surrealdb";
|
|
3
3
|
import { Duration, RecordId, Surreal as Surreal$1, SurrealTransaction } from "surrealdb";
|
|
4
4
|
import { AccessDefinition, BackendNames, BackendRoutes, BucketNames, ColumnSchema, GetTable, QueryBuilder, QueryOptions, RoutePayload, SchemaStructure, TableModel, TableNames, TypeNameToTypeMap } from "@spooky-sync/query-builder";
|
|
@@ -57,7 +57,23 @@ declare class LocalDatabaseService extends AbstractDatabaseService {
|
|
|
57
57
|
constructor(config: Sp00kyConfig<any>['database'], logger: Logger$1);
|
|
58
58
|
getConfig(): Sp00kyConfig<any>['database'];
|
|
59
59
|
connect(): Promise<void>;
|
|
60
|
+
private unloadCloseRegistered;
|
|
61
|
+
/**
|
|
62
|
+
* Close the local DB on page unload so the SurrealDB-WASM worker releases its
|
|
63
|
+
* IndexedDB connection cleanly. Without this, the previous page's connection
|
|
64
|
+
* lingers; the next load's `client.connect` opens the store but the first
|
|
65
|
+
* write transaction in `client.use` hits an "IndexedDB error" — which then
|
|
66
|
+
* (mis)triggered the corrupt-store recovery and WIPED the cache on every
|
|
67
|
+
* reload, making warm loads as slow as cold ones. `pagehide` is the reliable
|
|
68
|
+
* unload signal (fires on bfcache + normal navigation); `close()` is async but
|
|
69
|
+
* the WASM worker initiates the IndexedDB connection teardown synchronously.
|
|
70
|
+
*/
|
|
71
|
+
private registerUnloadClose;
|
|
72
|
+
private openStore;
|
|
60
73
|
}
|
|
74
|
+
/** True for the SurrealDB-WASM error raised when its IndexedDB-backed key-value
|
|
75
|
+
* store can't be opened (corrupt / version-incompatible / blocked). Exported
|
|
76
|
+
* for unit testing the error-message match. */
|
|
61
77
|
//#endregion
|
|
62
78
|
//#region src/services/database/remote.d.ts
|
|
63
79
|
declare class RemoteDatabaseService extends AbstractDatabaseService {
|
|
@@ -77,6 +93,12 @@ interface WasmStreamUpdate {
|
|
|
77
93
|
query_id: string;
|
|
78
94
|
result_hash: string;
|
|
79
95
|
result_data: RecordVersionArray;
|
|
96
|
+
timing_store_apply_ms?: number;
|
|
97
|
+
timing_circuit_step_ms?: number;
|
|
98
|
+
timing_transform_ms?: number;
|
|
99
|
+
timing_parse_ms?: number;
|
|
100
|
+
timing_plan_ms?: number;
|
|
101
|
+
timing_snapshot_ms?: number;
|
|
80
102
|
}
|
|
81
103
|
//#endregion
|
|
82
104
|
//#region src/services/stream-processor/index.d.ts
|
|
@@ -103,6 +125,19 @@ interface StreamUpdate {
|
|
|
103
125
|
* for the initial register_view snapshot.
|
|
104
126
|
*/
|
|
105
127
|
materializationTimeMs?: number;
|
|
128
|
+
/** SSP internal sub-phase timings (ms) for this ingest, from the WASM binding. */
|
|
129
|
+
storeApplyMs?: number;
|
|
130
|
+
circuitStepMs?: number;
|
|
131
|
+
transformMs?: number;
|
|
132
|
+
/**
|
|
133
|
+
* One-shot registration timings (ms). Only set on the StreamUpdate returned
|
|
134
|
+
* by `registerQueryPlan` (the register_view snapshot), not on ingest updates.
|
|
135
|
+
*/
|
|
136
|
+
registration?: {
|
|
137
|
+
parseMs: number;
|
|
138
|
+
planMs: number;
|
|
139
|
+
snapshotMs: number;
|
|
140
|
+
};
|
|
106
141
|
}
|
|
107
142
|
type StreamProcessorEvents = {
|
|
108
143
|
stream_update: EventDefinition<'stream_update', StreamUpdate[]>;
|
|
@@ -122,6 +157,8 @@ declare class StreamProcessorService {
|
|
|
122
157
|
private processor;
|
|
123
158
|
private isInitialized;
|
|
124
159
|
private receivers;
|
|
160
|
+
private batching;
|
|
161
|
+
private batchBuffer;
|
|
125
162
|
constructor(events: EventSystem<StreamProcessorEvents>, db: LocalDatabaseService, persistenceClient: PersistenceClient, logger: Logger);
|
|
126
163
|
/**
|
|
127
164
|
* Add a receiver for stream updates.
|
|
@@ -129,12 +166,53 @@ declare class StreamProcessorService {
|
|
|
129
166
|
*/
|
|
130
167
|
addReceiver(receiver: StreamUpdateReceiver): void;
|
|
131
168
|
private notifyUpdates;
|
|
169
|
+
private dispatchUpdates;
|
|
170
|
+
/**
|
|
171
|
+
* Ingest a batch of record changes as a single bulk operation, firing only
|
|
172
|
+
* one coalesced `StreamUpdate` per affected query once every record has been
|
|
173
|
+
* ingested (instead of one update per record). Use this whenever multiple
|
|
174
|
+
* records land at once — e.g. sync fetching N missing rows — so a list query
|
|
175
|
+
* re-runs and the UI re-renders once for the whole batch rather than
|
|
176
|
+
* row-by-row.
|
|
177
|
+
*
|
|
178
|
+
* Internally opens a coalescing window, ingests each record, then flushes;
|
|
179
|
+
* processor state is persisted once for the whole batch. No-op for an empty
|
|
180
|
+
* batch.
|
|
181
|
+
*/
|
|
182
|
+
ingestMany(records: Array<{
|
|
183
|
+
table: string;
|
|
184
|
+
op: 'CREATE' | 'UPDATE' | 'DELETE';
|
|
185
|
+
id: string;
|
|
186
|
+
record: any;
|
|
187
|
+
}>): void;
|
|
188
|
+
/**
|
|
189
|
+
* Open a coalescing window. While open, the per-record stream updates
|
|
190
|
+
* emitted by `ingest` are buffered (one entry per queryHash) instead of
|
|
191
|
+
* dispatched. Always paired with `flushCoalescing()` in a try/finally by
|
|
192
|
+
* `ingestMany` so the window always closes — otherwise the processor stays
|
|
193
|
+
* stuck buffering forever.
|
|
194
|
+
*
|
|
195
|
+
* No-op if a window is already open (nested batches aren't expected here).
|
|
196
|
+
*/
|
|
197
|
+
private beginCoalescing;
|
|
198
|
+
/**
|
|
199
|
+
* Close the coalescing window and flush: dispatch one coalesced
|
|
200
|
+
* `StreamUpdate` per buffered queryHash, then persist processor state once
|
|
201
|
+
* for the whole batch (instead of once per ingest).
|
|
202
|
+
*/
|
|
203
|
+
private flushCoalescing;
|
|
132
204
|
/**
|
|
133
205
|
* Initialize the WASM module and processor.
|
|
134
206
|
* This must be called before using other methods.
|
|
135
207
|
*/
|
|
136
208
|
init(): Promise<void>;
|
|
137
209
|
loadState(): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Seed per-table `select` permission predicates ({ [table]: whereText }).
|
|
212
|
+
* Must run after the processor exists and before any `register_view`, else
|
|
213
|
+
* non-`_00_` tables are default-denied and registration fails.
|
|
214
|
+
*/
|
|
215
|
+
setPermissions(permissions: Record<string, string>): void;
|
|
138
216
|
saveState(): Promise<void>;
|
|
139
217
|
/**
|
|
140
218
|
* Ingest a record change into the processor.
|
|
@@ -409,6 +487,28 @@ declare class Sp00kyClient<S extends SchemaStructure> {
|
|
|
409
487
|
subscribe(queryHash: string, callback: (records: Record<string, any>[]) => void, options?: {
|
|
410
488
|
immediate?: boolean;
|
|
411
489
|
}): Promise<() => void>;
|
|
490
|
+
/**
|
|
491
|
+
* Opt-in eager teardown for a query whose last subscriber has gone away
|
|
492
|
+
* (e.g. a viewport-windowed list cancelling an off-screen window). No-op
|
|
493
|
+
* while any subscriber remains. Tears down the remote `_00_query` view +
|
|
494
|
+
* local WASM view instead of waiting for the TTL sweep. Default behavior
|
|
495
|
+
* (no call here) keeps the view resident for cheap re-subscription.
|
|
496
|
+
*/
|
|
497
|
+
deregisterQuery(queryHash: string): void;
|
|
498
|
+
/**
|
|
499
|
+
* Subscribe to a query's fetch-status changes (idle/fetching). With
|
|
500
|
+
* `{ immediate: true }` the callback fires synchronously with the current
|
|
501
|
+
* status. Powers the `useQuery` hook's `isFetching()` accessor.
|
|
502
|
+
*/
|
|
503
|
+
subscribeQueryStatus(queryHash: string, callback: QueryStatusCallback, options?: {
|
|
504
|
+
immediate?: boolean;
|
|
505
|
+
}): () => void;
|
|
506
|
+
/**
|
|
507
|
+
* Report the frontend processing time (ms) a client framework spent applying
|
|
508
|
+
* an update for a query (e.g. `useQuery`'s `reconcile()`), so DevTools/MCP can
|
|
509
|
+
* surface the "frontend" phase of the per-query timing breakdown.
|
|
510
|
+
*/
|
|
511
|
+
reportFrontendTiming(queryHash: string, ms: number): void;
|
|
412
512
|
run<B extends BackendNames<S>, R extends BackendRoutes<S, B>>(backend: B, path: R, payload: RoutePayload<S, B, R>, options?: RunOptions): Promise<void>;
|
|
413
513
|
bucket<B extends BucketNames<S>>(name: B): BucketHandle;
|
|
414
514
|
create(id: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
@@ -438,4 +538,4 @@ declare function textToHtml(text: string): string;
|
|
|
438
538
|
*/
|
|
439
539
|
|
|
440
540
|
//#endregion
|
|
441
|
-
export { AuthEventSystem, AuthEventTypeMap, AuthEventTypes, AuthService, BucketHandle, CURSOR_COLORS, CrdtField, CrdtManager, DebounceOptions, EventSubscriptionOptions, Level, MATERIALIZATION_SAMPLE_WINDOW, MutationCallback, MutationEvent, MutationEventType, PersistenceClient, PinoTransmit, QueryConfig, QueryConfigRecord, QueryHash, QueryState, QueryTimeToLive, QueryUpdateCallback, RecordVersionArray, RecordVersionDiff, RunOptions, Sp00kyClient, Sp00kyConfig, Sp00kyQueryResult, Sp00kyQueryResultPromise, StoreType, UpdateOptions, createAuthEventSystem, cursorColorFromName, fileToUint8Array, textToHtml };
|
|
541
|
+
export { AuthEventSystem, AuthEventTypeMap, AuthEventTypes, AuthService, BucketHandle, CURSOR_COLORS, CrdtField, CrdtManager, DebounceOptions, EventSubscriptionOptions, Level, MATERIALIZATION_SAMPLE_WINDOW, MutationCallback, MutationEvent, MutationEventType, PersistenceClient, PhaseStat, PinoTransmit, QueryConfig, QueryConfigRecord, QueryHash, QueryState, QueryStatus, QueryStatusCallback, QueryTimeToLive, QueryTimings, QueryUpdateCallback, RecordVersionArray, RecordVersionDiff, RegistrationTimings, RunOptions, Sp00kyClient, Sp00kyConfig, Sp00kyQueryResult, Sp00kyQueryResultPromise, StoreType, TimingPhase, UpdateOptions, createAuthEventSystem, cursorColorFromName, fileToUint8Array, textToHtml };
|