@spooky-sync/core 0.0.1-canary.38 → 0.0.1-canary.381
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/AGENTS.md +91 -0
- package/README.md +59 -16
- package/dist/index.d.ts +2238 -144
- package/dist/index.js +18149 -2475
- package/dist/live.d.ts +149 -0
- package/dist/live.js +739 -0
- package/dist/otel/index.d.ts +1 -1
- package/dist/pure.d.ts +401 -0
- package/dist/pure.js +24 -0
- package/dist/sqlite-open.js +392 -0
- package/dist/sqlite-worker.d.ts +1 -0
- package/dist/sqlite-worker.js +439 -0
- package/dist/sw.d.ts +207 -0
- package/dist/sw.js +393 -0
- package/dist/tabs-broker-worker.d.ts +8 -0
- package/dist/tabs-broker-worker.js +477 -0
- package/dist/types.d.ts +2082 -39
- package/dist/worker-edges.js +498 -0
- package/dist/worker-impersonation.js +60 -0
- package/dist/worker-ref-tables.d.ts +48 -0
- package/dist/worker-types.d.ts +112 -0
- package/dist/worker-types.js +73 -0
- package/package.json +28 -7
- package/scripts/check-broker-bundle.mjs +33 -0
- package/scripts/check-worker-entries.mjs +173 -0
- package/skills/sp00ky-core/SKILL.md +42 -8
- package/skills/sp00ky-core/references/config.md +8 -2
- package/src/boot/auth-flip.saga.test.ts +174 -0
- package/src/boot/auth-flip.saga.ts +77 -0
- package/src/boot/boot.saga.test.ts +203 -0
- package/src/boot/boot.saga.ts +146 -0
- package/src/boot/bucket-switch.saga.test.ts +191 -0
- package/src/boot/bucket-switch.saga.ts +151 -0
- package/src/boot/preload.saga.test.ts +96 -0
- package/src/boot/preload.saga.ts +45 -0
- package/src/bucket-blurhash.test.ts +148 -0
- package/src/build-globals.d.ts +12 -0
- package/src/client/bucket-handle.test.ts +195 -0
- package/src/client/bucket-handle.ts +352 -0
- package/src/client/router.test.ts +59 -0
- package/src/client/router.ts +104 -0
- package/src/client/runtime.test.ts +319 -0
- package/src/client/runtime.ts +307 -0
- package/src/client/services.test.ts +74 -0
- package/src/client/services.ts +437 -0
- package/src/client/sp00ky-client.test.ts +428 -0
- package/src/client/sp00ky-client.ts +737 -0
- package/src/events/index.ts +3 -0
- package/src/index.ts +86 -1
- package/src/kernel/constants.test.ts +19 -0
- package/src/kernel/constants.ts +94 -0
- package/src/kernel/effects.test.ts +40 -0
- package/src/kernel/effects.ts +171 -0
- package/src/kernel/events.ts +60 -0
- package/src/kernel/interpreter.test.ts +116 -0
- package/src/kernel/interpreter.ts +148 -0
- package/src/kernel/saga.test.ts +89 -0
- package/src/kernel/saga.ts +73 -0
- package/src/live/index.test.ts +512 -0
- package/src/live/index.ts +1059 -0
- package/src/modules/app-release/index.test.ts +125 -0
- package/src/modules/app-release/index.ts +209 -0
- package/src/modules/auth/auth.local-first.test.ts +228 -0
- package/src/modules/auth/auth.session-recheck.test.ts +140 -0
- package/src/modules/auth/events/index.ts +7 -1
- package/src/modules/auth/impersonation-banner.ts +443 -0
- package/src/modules/auth/impersonation.integration.test.ts +209 -0
- package/src/modules/auth/impersonation.test.ts +377 -0
- package/src/modules/auth/impersonation.ts +179 -0
- package/src/modules/auth/index.ts +538 -14
- package/src/modules/channel/channel.test.ts +752 -0
- package/src/modules/channel/index.ts +1153 -0
- package/src/modules/channel/webrtc.ts +472 -0
- package/src/modules/crdt/acceptance.ts +75 -0
- package/src/modules/crdt/bytes.ts +50 -0
- package/src/modules/crdt/crdt-field.ts +125 -0
- package/src/modules/crdt/crdt.test.ts +546 -0
- package/src/modules/crdt/hash.ts +103 -0
- package/src/modules/crdt/index.ts +821 -0
- package/src/modules/crdt/loro-loader.ts +25 -0
- package/src/modules/crdt/mirror.ts +37 -0
- package/src/modules/devtools/flags.ts +349 -0
- package/src/modules/devtools/index.ts +746 -93
- package/src/modules/devtools/mutations.test.ts +92 -0
- package/src/modules/devtools/mutations.ts +160 -0
- package/src/modules/devtools/notify-throttle.test.ts +166 -0
- package/src/modules/devtools/state-shape.test.ts +263 -0
- package/src/modules/devtools/storage-info.test.ts +79 -0
- package/src/modules/devtools/storage-info.ts +168 -0
- package/src/modules/devtools/versions.test.ts +74 -0
- package/src/modules/devtools/versions.ts +110 -0
- package/src/modules/feature-flag/index.test.ts +298 -0
- package/src/modules/feature-flag/index.ts +316 -0
- package/src/modules/ref-tables.test.ts +93 -0
- package/src/modules/ref-tables.ts +91 -0
- package/src/modules/web-push/index.test.ts +824 -0
- package/src/modules/web-push/index.ts +1027 -0
- package/src/mutation/ingest-outage.integration.test.ts +400 -0
- package/src/mutation/jobs.test.ts +25 -0
- package/src/mutation/jobs.ts +41 -0
- package/src/mutation/mutation-id.test.ts +37 -0
- package/src/mutation/mutation-id.ts +35 -0
- package/src/mutation/pending-writes.integration.test.ts +175 -0
- package/src/mutation/push.saga.test.ts +361 -0
- package/src/mutation/push.saga.ts +245 -0
- package/src/mutation/rows.test.ts +278 -0
- package/src/mutation/rows.ts +515 -0
- package/src/mutation/tray.saga.test.ts +63 -0
- package/src/mutation/tray.saga.ts +48 -0
- package/src/mutation/write.saga.test.ts +436 -0
- package/src/mutation/write.saga.ts +384 -0
- package/src/pure.ts +66 -0
- package/src/push/types.ts +174 -0
- package/src/query/anon-query-isolation.integration.test.ts +531 -0
- package/src/query/env.test.ts +23 -0
- package/src/query/env.ts +65 -0
- package/src/query/fetch.saga.test.ts +199 -0
- package/src/query/fetch.saga.ts +120 -0
- package/src/query/hash.test.ts +14 -0
- package/src/query/hash.ts +18 -0
- package/src/query/id-set-plan.test.ts +132 -0
- package/src/query/lifecycle.saga.test.ts +274 -0
- package/src/query/lifecycle.saga.ts +186 -0
- package/src/query/list-ref-live.integration.test.ts +203 -0
- package/src/query/materialize.saga.test.ts +200 -0
- package/src/query/materialize.saga.ts +102 -0
- package/src/query/materialize.test.ts +58 -0
- package/src/query/materialize.ts +57 -0
- package/src/query/membership.saga.test.ts +514 -0
- package/src/query/membership.saga.ts +339 -0
- package/src/query/membership.test.ts +151 -0
- package/src/query/membership.ts +234 -0
- package/src/query/register.saga.test.ts +369 -0
- package/src/query/register.saga.ts +293 -0
- package/src/query/render-set.test.ts +47 -0
- package/src/query/render-set.ts +71 -0
- package/src/query/session-guard.integration.test.ts +304 -0
- package/src/query/sql.test.ts +118 -0
- package/src/query/sql.ts +174 -0
- package/src/query/window-query.test.ts +70 -0
- package/src/query/window-query.ts +208 -0
- package/src/services/blobs/blob-cache.test.ts +359 -0
- package/src/services/blobs/blob-cache.ts +603 -0
- package/src/services/blobs/blob-manifest.ts +227 -0
- package/src/services/blobs/blob-store.test.ts +77 -0
- package/src/services/blobs/blob-store.ts +359 -0
- package/src/services/blobs/blob.fixture.ts +90 -0
- package/src/services/blobs/index.ts +70 -0
- package/src/services/database/cache-engine.ts +209 -0
- package/src/services/database/connection-supervisor.test.ts +318 -0
- package/src/services/database/connection-supervisor.ts +422 -0
- package/src/services/database/database.query-timeout.test.ts +140 -0
- package/src/services/database/database.responses.test.ts +43 -0
- package/src/services/database/database.ts +151 -56
- package/src/services/database/engine-factory.ts +33 -0
- package/src/services/database/errors.ts +34 -0
- package/src/services/database/index.ts +7 -0
- package/src/services/database/landed-body-clear.integration.test.ts +236 -0
- package/src/services/database/local-migrator.integration.test.ts +110 -0
- package/src/services/database/local-migrator.ts +54 -9
- package/src/services/database/local.test.ts +150 -0
- package/src/services/database/local.ts +503 -59
- package/src/services/database/plan-render.test.ts +159 -0
- package/src/services/database/plan-render.ts +108 -0
- package/src/services/database/relation-resolver.test.ts +484 -0
- package/src/services/database/relation-resolver.ts +0 -0
- package/src/services/database/remote.ts +283 -4
- package/src/services/database/sqlite-cache-engine.test.ts +628 -0
- package/src/services/database/sqlite-cache-engine.timeout.test.ts +61 -0
- package/src/services/database/sqlite-cache-engine.ts +1401 -0
- package/src/services/database/sqlite-column-reset.integration.test.ts +100 -0
- package/src/services/database/sqlite-column-reset.ts +91 -0
- package/src/services/database/sqlite-devtools-queries.integration.test.ts +143 -0
- package/src/services/database/sqlite-devtools-queries.test.ts +154 -0
- package/src/services/database/sqlite-lock-verify.test.ts +33 -0
- package/src/services/database/sqlite-lock-verify.ts +45 -0
- package/src/services/database/sqlite-open.test.ts +150 -0
- package/src/services/database/sqlite-open.ts +164 -0
- package/src/services/database/sqlite-plan-sql.test.ts +164 -0
- package/src/services/database/sqlite-plan-sql.ts +196 -0
- package/src/services/database/sqlite-projection.test.ts +121 -0
- package/src/services/database/sqlite-select.integration.test.ts +185 -0
- package/src/services/database/sqlite-select.test.ts +261 -0
- package/src/services/database/sqlite-select.ts +131 -0
- package/src/services/database/sqlite-transport.fixture.ts +30 -0
- package/src/services/database/sqlite-transport.ts +224 -0
- package/src/services/database/sqlite-worker.ts +437 -0
- package/src/services/database/surql-translate.ts +417 -0
- package/src/services/database/surreal-cache-engine.ts +163 -0
- package/src/services/logger/index.test.ts +132 -0
- package/src/services/logger/index.ts +187 -6
- package/src/services/persistence/resilient.ts +8 -1
- package/src/services/persistence/surrealdb.ts +2 -2
- package/src/services/stream-processor/index.ts +801 -63
- 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 +186 -0
- package/src/services/stream-processor/stream-processor.prime.test.ts +234 -0
- package/src/services/stream-processor/stream-processor.reset.test.ts +226 -0
- package/src/services/stream-processor/wasm-types.ts +57 -1
- package/src/services/tabs/broker-client.ts +284 -0
- package/src/services/tabs/broker.test.ts +381 -0
- package/src/services/tabs/coordinator.test.ts +386 -0
- package/src/services/tabs/coordinator.ts +646 -0
- package/src/services/tabs/fake-ports.fixture.ts +112 -0
- package/src/services/tabs/leader-locks.ts +75 -0
- package/src/services/tabs/protocol.ts +262 -0
- package/src/services/tabs/support.ts +36 -0
- package/src/services/tabs/tabs-broker-worker.ts +652 -0
- package/src/sp00ky.ts +5 -394
- package/src/state/client-state.ts +231 -0
- package/src/state/lifecycle.test.ts +184 -0
- package/src/state/lifecycle.ts +127 -0
- package/src/state/reducers.test.ts +337 -0
- package/src/state/reducers.ts +571 -0
- package/src/state/selectors.test.ts +203 -0
- package/src/state/selectors.ts +264 -0
- package/src/sw/index.test.ts +582 -0
- package/src/sw/index.ts +607 -0
- package/src/sw/store.ts +96 -0
- package/src/sync/connection.saga.test.ts +97 -0
- package/src/sync/connection.saga.ts +89 -0
- package/src/sync/live.saga.test.ts +229 -0
- package/src/sync/live.saga.ts +116 -0
- package/src/sync/policy.health.test.ts +56 -0
- package/src/sync/policy.test.ts +663 -0
- package/src/sync/policy.ts +515 -0
- package/src/sync/poll.saga.test.ts +51 -0
- package/src/sync/poll.saga.ts +36 -0
- package/src/sync/tabs.saga.test.ts +78 -0
- package/src/sync/tabs.saga.ts +96 -0
- package/src/testing/adapters.ts +137 -0
- package/src/testing/build.ts +63 -0
- package/src/testing/fake-services.ts +63 -0
- package/src/testing/run-pure.test.ts +92 -0
- package/src/testing/run-pure.ts +128 -0
- package/src/testing/services.ts +17 -0
- package/src/types.ts +694 -7
- package/src/utils/blurhash.ts +90 -0
- package/src/utils/edges.ts +57 -0
- package/src/utils/error-classification.test.ts +116 -0
- package/src/utils/error-classification.ts +74 -0
- package/src/utils/index.ts +83 -6
- package/src/utils/parser.test.ts +67 -102
- package/src/utils/parser.ts +63 -2
- package/src/utils/semver.test.ts +32 -0
- package/src/utils/semver.ts +30 -0
- package/src/utils/sha256.ts +15 -0
- package/src/utils/surql.ts +22 -11
- package/src/utils/utils.test.ts +3 -2
- package/tsdown.config.ts +117 -3
- package/vitest.config.ts +48 -0
- package/src/modules/cache/index.ts +0 -241
- package/src/modules/cache/types.ts +0 -19
- package/src/modules/data/data.test.ts +0 -58
- package/src/modules/data/index.ts +0 -882
- package/src/modules/sync/engine.ts +0 -173
- package/src/modules/sync/events/index.ts +0 -78
- package/src/modules/sync/index.ts +0 -3
- package/src/modules/sync/queue/index.ts +0 -2
- package/src/modules/sync/queue/queue-down.ts +0 -90
- package/src/modules/sync/queue/queue-up.ts +0 -224
- package/src/modules/sync/scheduler.ts +0 -84
- package/src/modules/sync/sync.ts +0 -422
- package/src/modules/sync/utils.test.ts +0 -311
- package/src/modules/sync/utils.ts +0 -169
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import type { LocalDatabaseService } from '../../services/database/index';
|
|
2
|
-
import type {
|
|
3
|
-
StreamProcessorService,
|
|
4
|
-
StreamUpdate,
|
|
5
|
-
StreamUpdateReceiver,
|
|
6
|
-
} from '../../services/stream-processor/index';
|
|
7
|
-
import type { Logger } from '../../services/logger/index';
|
|
8
|
-
import { parseRecordIdString, encodeRecordId, surql } from '../../utils/index';
|
|
9
|
-
import type { CacheRecord, QueryConfig } from './types';
|
|
10
|
-
import type { RecordVersionArray } from '../../types';
|
|
11
|
-
|
|
12
|
-
export * from './types';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* CacheModule - Centralized storage and DBSP ingestion
|
|
16
|
-
*
|
|
17
|
-
* Single responsibility: Handle all local storage operations and DBSP ingestion.
|
|
18
|
-
* This module acts as the bridge between data operations and persistence.
|
|
19
|
-
*/
|
|
20
|
-
export class CacheModule implements StreamUpdateReceiver {
|
|
21
|
-
private logger: Logger;
|
|
22
|
-
private streamUpdateCallback: (update: StreamUpdate) => void;
|
|
23
|
-
private versionLookups: Record<string, number> = {};
|
|
24
|
-
|
|
25
|
-
constructor(
|
|
26
|
-
private local: LocalDatabaseService,
|
|
27
|
-
private streamProcessor: StreamProcessorService,
|
|
28
|
-
streamUpdateCallback: (update: StreamUpdate) => void,
|
|
29
|
-
logger: Logger
|
|
30
|
-
) {
|
|
31
|
-
this.logger = logger.child({ service: 'CacheModule' });
|
|
32
|
-
this.streamUpdateCallback = streamUpdateCallback;
|
|
33
|
-
// Register as receiver for DBSP stream updates
|
|
34
|
-
this.streamProcessor.addReceiver(this);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Implements StreamUpdateReceiver interface
|
|
39
|
-
* Called directly by StreamProcessor when views change
|
|
40
|
-
*/
|
|
41
|
-
onStreamUpdate(update: StreamUpdate): void {
|
|
42
|
-
this.logger.debug(
|
|
43
|
-
{
|
|
44
|
-
queryHash: update.queryHash,
|
|
45
|
-
arrayLength: update.localArray?.length,
|
|
46
|
-
Category: 'sp00ky-client::CacheModule::onStreamUpdate',
|
|
47
|
-
},
|
|
48
|
-
'Stream update received'
|
|
49
|
-
);
|
|
50
|
-
this.streamUpdateCallback(update);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public lookup(recordId: string): number {
|
|
54
|
-
return this.versionLookups[recordId] ?? 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Save a single record to local DB and ingest into DBSP
|
|
59
|
-
* Used by mutations (create/update)
|
|
60
|
-
*/
|
|
61
|
-
async save(cacheRecord: CacheRecord, skipDbInsert: boolean = false): Promise<void> {
|
|
62
|
-
return this.saveBatch([cacheRecord], skipDbInsert);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Save multiple records in a batch
|
|
67
|
-
* More efficient than calling save() multiple times
|
|
68
|
-
* Used by sync operations
|
|
69
|
-
*/
|
|
70
|
-
async saveBatch(records: CacheRecord[], skipDbInsert: boolean = false): Promise<void> {
|
|
71
|
-
if (records.length === 0) return;
|
|
72
|
-
|
|
73
|
-
this.logger.debug(
|
|
74
|
-
{
|
|
75
|
-
count: records.length,
|
|
76
|
-
Category: 'sp00ky-client::CacheModule::saveBatch',
|
|
77
|
-
},
|
|
78
|
-
'Saving record batch'
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
const populatedRecords = records.map((record) => {
|
|
83
|
-
if (!record.version) throw new Error('Record version is required');
|
|
84
|
-
return {
|
|
85
|
-
...record,
|
|
86
|
-
record: {
|
|
87
|
-
...record.record,
|
|
88
|
-
_00_rv: record.version,
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
if (!skipDbInsert) {
|
|
94
|
-
const query = surql.seal<void>(
|
|
95
|
-
surql.tx(
|
|
96
|
-
populatedRecords.map((_, i) => {
|
|
97
|
-
return surql.upsert(`id${i}`, `content${i}`);
|
|
98
|
-
})
|
|
99
|
-
)
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const params = populatedRecords.reduce(
|
|
103
|
-
(acc, record, i) => {
|
|
104
|
-
const { id, ...content } = record.record;
|
|
105
|
-
return {
|
|
106
|
-
...acc,
|
|
107
|
-
[`id${i}`]: id,
|
|
108
|
-
[`content${i}`]: content,
|
|
109
|
-
};
|
|
110
|
-
},
|
|
111
|
-
{} as Record<string, any>
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
await this.local.execute(query, params);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 2. Batch ingest into DBSP (use populatedRecords which has _00_rv set)
|
|
118
|
-
for (const record of populatedRecords) {
|
|
119
|
-
const recordId = encodeRecordId(record.record.id);
|
|
120
|
-
this.versionLookups[recordId] = record.version;
|
|
121
|
-
this.streamProcessor.ingest(record.table, record.op, recordId, record.record);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
this.logger.debug(
|
|
125
|
-
{ count: records.length, Category: 'sp00ky-client::CacheModule::saveBatch' },
|
|
126
|
-
'Batch saved successfully'
|
|
127
|
-
);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
this.logger.error(
|
|
130
|
-
{ err, count: records.length, Category: 'sp00ky-client::CacheModule::saveBatch' },
|
|
131
|
-
'Failed to save batch'
|
|
132
|
-
);
|
|
133
|
-
throw err;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Delete a record from local DB and ingest deletion into DBSP
|
|
139
|
-
*/
|
|
140
|
-
async delete(table: string, id: string, skipDbDelete: boolean = false, recordData: Record<string, any> = {}): Promise<void> {
|
|
141
|
-
this.logger.debug(
|
|
142
|
-
{ table, id, Category: 'sp00ky-client::CacheModule::delete' },
|
|
143
|
-
'Deleting record'
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
// 1. Delete from local database
|
|
148
|
-
if (!skipDbDelete) {
|
|
149
|
-
await this.local.query('DELETE $id', { id: parseRecordIdString(id) });
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 2. Ingest deletion into DBSP (pass record data so predicates can be matched)
|
|
153
|
-
delete this.versionLookups[id];
|
|
154
|
-
this.streamProcessor.ingest(table, 'DELETE', id, recordData);
|
|
155
|
-
|
|
156
|
-
this.logger.debug(
|
|
157
|
-
{ table, id, Category: 'sp00ky-client::CacheModule::delete' },
|
|
158
|
-
'Record deleted successfully'
|
|
159
|
-
);
|
|
160
|
-
} catch (err) {
|
|
161
|
-
this.logger.error(
|
|
162
|
-
{ err, table, id, Category: 'sp00ky-client::CacheModule::delete' },
|
|
163
|
-
'Failed to delete record'
|
|
164
|
-
);
|
|
165
|
-
throw err;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Register a query with DBSP to create a materialized view
|
|
171
|
-
* Returns the initial result array
|
|
172
|
-
*/
|
|
173
|
-
registerQuery(config: QueryConfig): { localArray: RecordVersionArray } {
|
|
174
|
-
this.logger.debug(
|
|
175
|
-
{
|
|
176
|
-
queryHash: config.queryHash,
|
|
177
|
-
surql: config.surql,
|
|
178
|
-
Category: 'sp00ky-client::CacheModule::registerQuery',
|
|
179
|
-
},
|
|
180
|
-
'Registering query'
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
const update = this.streamProcessor.registerQueryPlan({
|
|
185
|
-
queryHash: config.queryHash,
|
|
186
|
-
surql: config.surql,
|
|
187
|
-
params: config.params,
|
|
188
|
-
ttl: config.ttl,
|
|
189
|
-
lastActiveAt: config.lastActiveAt,
|
|
190
|
-
localArray: [],
|
|
191
|
-
remoteArray: [],
|
|
192
|
-
meta: {
|
|
193
|
-
tableName: '',
|
|
194
|
-
},
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
if (!update) {
|
|
198
|
-
throw new Error('Failed to register query with DBSP');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
this.logger.debug(
|
|
202
|
-
{
|
|
203
|
-
queryHash: config.queryHash,
|
|
204
|
-
arrayLength: update.localArray?.length,
|
|
205
|
-
Category: 'sp00ky-client::CacheModule::registerQuery',
|
|
206
|
-
},
|
|
207
|
-
'Query registered successfully'
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
return { localArray: update.localArray };
|
|
211
|
-
} catch (err) {
|
|
212
|
-
this.logger.error(
|
|
213
|
-
{ err, queryHash: config.queryHash, Category: 'sp00ky-client::CacheModule::registerQuery' },
|
|
214
|
-
'Failed to register query'
|
|
215
|
-
);
|
|
216
|
-
throw err;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Unregister a query from DBSP
|
|
222
|
-
*/
|
|
223
|
-
unregisterQuery(queryHash: string): void {
|
|
224
|
-
this.logger.debug(
|
|
225
|
-
{ queryHash, Category: 'sp00ky-client::CacheModule::unregisterQuery' },
|
|
226
|
-
'Unregistering query'
|
|
227
|
-
);
|
|
228
|
-
try {
|
|
229
|
-
this.streamProcessor.unregisterQueryPlan(queryHash);
|
|
230
|
-
this.logger.debug(
|
|
231
|
-
{ queryHash, Category: 'sp00ky-client::CacheModule::unregisterQuery' },
|
|
232
|
-
'Query unregistered successfully'
|
|
233
|
-
);
|
|
234
|
-
} catch (err) {
|
|
235
|
-
this.logger.error(
|
|
236
|
-
{ err, queryHash, Category: 'sp00ky-client::CacheModule::unregisterQuery' },
|
|
237
|
-
'Failed to unregister query'
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { RecordId, Duration } from 'surrealdb';
|
|
2
|
-
import type { QueryTimeToLive } from '../../types';
|
|
3
|
-
|
|
4
|
-
export type RecordWithId = Record<string, any> & { id: RecordId<string> };
|
|
5
|
-
|
|
6
|
-
export interface QueryConfig {
|
|
7
|
-
queryHash: string;
|
|
8
|
-
surql: string;
|
|
9
|
-
params: Record<string, any>;
|
|
10
|
-
ttl: QueryTimeToLive | Duration;
|
|
11
|
-
lastActiveAt: Date;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface CacheRecord {
|
|
15
|
-
table: string;
|
|
16
|
-
op: 'CREATE' | 'UPDATE' | 'DELETE';
|
|
17
|
-
record: RecordWithId;
|
|
18
|
-
version: number;
|
|
19
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { parseUpdateOptions } from './index';
|
|
3
|
-
|
|
4
|
-
describe('parseUpdateOptions', () => {
|
|
5
|
-
it('returns empty options when no debounce', () => {
|
|
6
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice' });
|
|
7
|
-
expect(result).toEqual({});
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('returns empty options when options is undefined', () => {
|
|
11
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice' }, undefined);
|
|
12
|
-
expect(result).toEqual({});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('returns empty options when debounced is false', () => {
|
|
16
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice' }, { debounced: false });
|
|
17
|
-
expect(result).toEqual({});
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('debounced: true uses default delay (200) and key = id', () => {
|
|
21
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice' }, { debounced: true });
|
|
22
|
-
expect(result).toEqual({
|
|
23
|
-
debounced: {
|
|
24
|
-
delay: 200,
|
|
25
|
-
key: 'user:1',
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('supports custom delay', () => {
|
|
31
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice' }, {
|
|
32
|
-
debounced: { delay: 500 },
|
|
33
|
-
});
|
|
34
|
-
expect(result.debounced?.delay).toBe(500);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('supports custom key type recordId', () => {
|
|
38
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice', age: 30 }, {
|
|
39
|
-
debounced: { key: 'recordId' },
|
|
40
|
-
});
|
|
41
|
-
expect(result.debounced?.key).toBe('user:1');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('key: recordId_x_fields generates composite key from id + sorted field names', () => {
|
|
45
|
-
const result = parseUpdateOptions(
|
|
46
|
-
'user:1',
|
|
47
|
-
{ name: 'Alice', age: 30, email: 'a@b.com' },
|
|
48
|
-
{ debounced: { key: 'recordId_x_fields' } }
|
|
49
|
-
);
|
|
50
|
-
expect(result.debounced?.key).toBe('user:1::age#email#name');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('uses defaults when debounced is object with no key or delay', () => {
|
|
54
|
-
const result = parseUpdateOptions('user:1', { name: 'Alice' }, { debounced: {} });
|
|
55
|
-
expect(result.debounced?.delay).toBe(200);
|
|
56
|
-
expect(result.debounced?.key).toBe('user:1');
|
|
57
|
-
});
|
|
58
|
-
});
|