@spooky-sync/core 0.0.1-canary.35 → 0.0.1-canary.37
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 +6 -6
- package/dist/index.js +11 -10
- package/dist/otel/index.js +3 -3
- package/dist/types.d.ts +3 -1
- package/package.json +1 -1
- package/src/events/events.test.ts +2 -1
- package/src/modules/auth/events/index.ts +2 -1
- package/src/modules/auth/index.ts +5 -8
- package/src/modules/cache/index.ts +5 -5
- package/src/modules/cache/types.ts +2 -2
- package/src/modules/data/index.ts +15 -12
- package/src/modules/devtools/index.ts +6 -6
- package/src/modules/sync/engine.ts +6 -6
- package/src/modules/sync/events/index.ts +3 -2
- package/src/modules/sync/queue/queue-down.ts +4 -3
- package/src/modules/sync/queue/queue-up.ts +6 -5
- package/src/modules/sync/scheduler.ts +2 -2
- package/src/modules/sync/sync.ts +10 -9
- package/src/modules/sync/utils.test.ts +2 -2
- package/src/modules/sync/utils.ts +7 -5
- package/src/otel/index.ts +10 -7
- package/src/services/database/database.ts +7 -7
- package/src/services/database/events/index.ts +2 -1
- package/src/services/database/local-migrator.ts +8 -8
- package/src/services/database/local.ts +5 -4
- package/src/services/database/remote.ts +4 -4
- package/src/services/logger/index.ts +3 -2
- package/src/services/persistence/localstorage.ts +2 -2
- package/src/services/persistence/resilient.ts +2 -2
- package/src/services/persistence/surrealdb.ts +3 -3
- package/src/services/stream-processor/index.ts +7 -6
- package/src/services/stream-processor/stream-processor.test.ts +1 -1
- package/src/services/stream-processor/wasm-types.ts +1 -1
- package/src/sp00ky.ts +8 -9
- package/src/types.ts +7 -5
- package/src/utils/index.ts +6 -6
- package/src/utils/parser.ts +2 -1
- package/src/utils/surql.ts +15 -15
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { C as Logger$1, S as UpdateOptions, T as EventSystem, _ as RunOptions, a as MutationEvent, b as Sp00kyQueryResultPromise, c as PinoTransmit, d as QueryHash, f as QueryState, g as RecordVersionDiff, h as RecordVersionArray, i as MutationCallback, l as QueryConfig, m as QueryUpdateCallback, n as EventSubscriptionOptions, o as MutationEventType, p as QueryTimeToLive, r as Level, s as PersistenceClient, t as DebounceOptions, u as QueryConfigRecord, v as Sp00kyConfig, w as EventDefinition, x as StoreType, y as Sp00kyQueryResult } from "./types.js";
|
|
2
2
|
import * as surrealdb0 from "surrealdb";
|
|
3
|
-
import { Duration, RecordId, Surreal, SurrealTransaction } from "surrealdb";
|
|
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";
|
|
5
5
|
import { Logger } from "pino";
|
|
6
6
|
|
|
@@ -31,13 +31,13 @@ interface SealedQuery<T = void> {
|
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region src/services/database/database.d.ts
|
|
33
33
|
declare abstract class AbstractDatabaseService {
|
|
34
|
-
protected client: Surreal;
|
|
34
|
+
protected client: Surreal$1;
|
|
35
35
|
protected logger: Logger$1;
|
|
36
36
|
protected events: DatabaseEventSystem;
|
|
37
37
|
protected abstract eventType: typeof DatabaseEventTypes.LocalQuery | typeof DatabaseEventTypes.RemoteQuery;
|
|
38
|
-
constructor(client: Surreal, logger: Logger$1, events: DatabaseEventSystem);
|
|
38
|
+
constructor(client: Surreal$1, logger: Logger$1, events: DatabaseEventSystem);
|
|
39
39
|
abstract connect(): Promise<void>;
|
|
40
|
-
getClient(): Surreal;
|
|
40
|
+
getClient(): Surreal$1;
|
|
41
41
|
getEvents(): DatabaseEventSystem;
|
|
42
42
|
tx(): Promise<SurrealTransaction>;
|
|
43
43
|
private queryQueue;
|
|
@@ -221,8 +221,8 @@ declare class Sp00kyClient<S extends SchemaStructure> {
|
|
|
221
221
|
private logger;
|
|
222
222
|
auth: AuthService<S>;
|
|
223
223
|
streamProcessor: StreamProcessorService;
|
|
224
|
-
get remoteClient(): Surreal;
|
|
225
|
-
get localClient(): Surreal;
|
|
224
|
+
get remoteClient(): surrealdb0.Surreal;
|
|
225
|
+
get localClient(): surrealdb0.Surreal;
|
|
226
226
|
get pendingMutationCount(): number;
|
|
227
227
|
subscribeToPendingMutations(cb: (count: number) => void): () => void;
|
|
228
228
|
constructor(config: Sp00kyConfig<S>);
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ const surql = {
|
|
|
28
28
|
return `SELECT ${returnValues.join(",")} FROM ONLY $${idVar}`;
|
|
29
29
|
},
|
|
30
30
|
selectByFieldsAnd(table, whereVar, returnValues) {
|
|
31
|
-
return `SELECT ${returnValues.map((
|
|
31
|
+
return `SELECT ${returnValues.map((rv) => typeof rv === "string" ? rv : `${rv.field} as ${rv.alias}`).join(",")} FROM ${table} WHERE ${whereVar.map((wv) => typeof wv === "string" ? `${wv} = $${wv}` : `${wv.field} = $${wv.variable}`).join(" AND ")}`;
|
|
32
32
|
},
|
|
33
33
|
create(idVar, dataVar) {
|
|
34
34
|
return `CREATE ONLY $${idVar} CONTENT $${dataVar}`;
|
|
@@ -43,7 +43,7 @@ const surql = {
|
|
|
43
43
|
return `UPDATE ONLY $${idVar} MERGE $${dataVar}`;
|
|
44
44
|
},
|
|
45
45
|
updateSet(idVar, keyDataVar) {
|
|
46
|
-
return `UPDATE $${idVar} SET ${keyDataVar.map((
|
|
46
|
+
return `UPDATE $${idVar} SET ${keyDataVar.map((kdv) => typeof kdv === "string" ? `${kdv} = $${kdv}` : "statement" in kdv ? kdv.statement : `${kdv.key} = $${kdv.variable}`).join(", ")}`;
|
|
47
47
|
},
|
|
48
48
|
delete(idVar) {
|
|
49
49
|
return `DELETE $${idVar}`;
|
|
@@ -157,7 +157,7 @@ function parseDuration(duration) {
|
|
|
157
157
|
if (typeof duration !== "string") return 6e5;
|
|
158
158
|
const match = duration.match(/^(\d+)([smh])$/);
|
|
159
159
|
if (!match) return 6e5;
|
|
160
|
-
const val = parseInt(match[1], 10);
|
|
160
|
+
const val = Number.parseInt(match[1], 10);
|
|
161
161
|
switch (match[2]) {
|
|
162
162
|
case "s": return val * 1e3;
|
|
163
163
|
case "h": return val * 36e5;
|
|
@@ -426,6 +426,7 @@ var DataModule = class {
|
|
|
426
426
|
max_retries: options?.max_retries ?? 3,
|
|
427
427
|
retry_strategy: options?.retry_strategy ?? "linear"
|
|
428
428
|
};
|
|
429
|
+
if (options?.timeout != null) record.timeout = options.timeout;
|
|
429
430
|
if (options?.assignedTo) record.assigned_to = options.assignedTo;
|
|
430
431
|
const recordId = `${tableName}:${generateId()}`;
|
|
431
432
|
await this.create(recordId, record);
|
|
@@ -742,7 +743,7 @@ function parseUpdateOptions(id, data, options) {
|
|
|
742
743
|
let pushEventOptions = {};
|
|
743
744
|
if (options?.debounced) pushEventOptions = { debounced: {
|
|
744
745
|
delay: options.debounced !== true ? options.debounced?.delay ?? 200 : 200,
|
|
745
|
-
key: (options.debounced !== true ? options.debounced?.key ?? id : id) === "recordId_x_fields" ? `${id}::${Object.keys(data).
|
|
746
|
+
key: (options.debounced !== true ? options.debounced?.key ?? id : id) === "recordId_x_fields" ? `${id}::${Object.keys(data).toSorted().join("#")}` : id
|
|
746
747
|
} };
|
|
747
748
|
return pushEventOptions;
|
|
748
749
|
}
|
|
@@ -1173,20 +1174,20 @@ var LocalMigrator = class {
|
|
|
1173
1174
|
try {
|
|
1174
1175
|
const [lastSchemaRecord] = await this.localDb.query(`SELECT hash, created_at FROM ONLY _00_schema ORDER BY created_at DESC LIMIT 1;`);
|
|
1175
1176
|
return lastSchemaRecord?.hash === hash;
|
|
1176
|
-
} catch (
|
|
1177
|
+
} catch (_error) {
|
|
1177
1178
|
return false;
|
|
1178
1179
|
}
|
|
1179
1180
|
}
|
|
1180
1181
|
async recreateDatabase(database) {
|
|
1181
1182
|
try {
|
|
1182
1183
|
await this.localDb.query(`DEFINE DATABASE _00_temp;`);
|
|
1183
|
-
} catch (
|
|
1184
|
+
} catch (_e) {}
|
|
1184
1185
|
try {
|
|
1185
1186
|
await this.localDb.query(`
|
|
1186
1187
|
USE DB _00_temp;
|
|
1187
1188
|
REMOVE DATABASE ${database};
|
|
1188
1189
|
`);
|
|
1189
|
-
} catch (
|
|
1190
|
+
} catch (_e) {}
|
|
1190
1191
|
await this.localDb.query(`
|
|
1191
1192
|
DEFINE DATABASE ${database};
|
|
1192
1193
|
USE DB ${database};
|
|
@@ -1480,8 +1481,8 @@ var ArraySyncer = class {
|
|
|
1480
1481
|
remoteArray;
|
|
1481
1482
|
needsSort = false;
|
|
1482
1483
|
constructor(localArray, remoteArray) {
|
|
1483
|
-
this.remoteArray = remoteArray.
|
|
1484
|
-
this.localArray = localArray.
|
|
1484
|
+
this.remoteArray = remoteArray.toSorted((a, b) => a[0].localeCompare(b[0]));
|
|
1485
|
+
this.localArray = localArray.toSorted((a, b) => a[0].localeCompare(b[0]));
|
|
1485
1486
|
}
|
|
1486
1487
|
/**
|
|
1487
1488
|
* Inserts an item into the local array
|
|
@@ -2401,7 +2402,7 @@ var AuthService = class {
|
|
|
2401
2402
|
await this.persistenceClient.remove("sp00ky_auth_token");
|
|
2402
2403
|
try {
|
|
2403
2404
|
await this.remote.getClient().invalidate();
|
|
2404
|
-
} catch (
|
|
2405
|
+
} catch (_e) {}
|
|
2405
2406
|
this.notifyListeners();
|
|
2406
2407
|
}
|
|
2407
2408
|
async setSession(token, user) {
|
package/dist/otel/index.js
CHANGED
|
@@ -50,9 +50,9 @@ function createOtelTransmit(endpoint, level = "info") {
|
|
|
50
50
|
const messages = [...logEvent.messages];
|
|
51
51
|
const severityNumber = mapLevelToSeverityNumber(levelLabel);
|
|
52
52
|
let body = "";
|
|
53
|
-
const
|
|
54
|
-
if (typeof
|
|
55
|
-
else if (
|
|
53
|
+
const lastMsg = messages.pop();
|
|
54
|
+
if (typeof lastMsg === "string") body = lastMsg;
|
|
55
|
+
else if (lastMsg) body = JSON.stringify(lastMsg);
|
|
56
56
|
let category = "sp00ky-client::unknown";
|
|
57
57
|
const attributes = {};
|
|
58
58
|
for (const msg of messages) if (typeof msg === "object") {
|
package/dist/types.d.ts
CHANGED
|
@@ -228,7 +228,7 @@ interface Sp00kyConfig<S extends SchemaStructure> {
|
|
|
228
228
|
/** The compiled SURQL schema string. */
|
|
229
229
|
schemaSurql: string;
|
|
230
230
|
/** Logging level. */
|
|
231
|
-
logLevel: Level;
|
|
231
|
+
logLevel: Level$1;
|
|
232
232
|
/**
|
|
233
233
|
* Persistence client to use.
|
|
234
234
|
* Can be a custom implementation, 'surrealdb' (default), or 'localstorage'.
|
|
@@ -331,6 +331,8 @@ interface RunOptions {
|
|
|
331
331
|
assignedTo?: string;
|
|
332
332
|
max_retries?: number;
|
|
333
333
|
retry_strategy?: 'linear' | 'exponential';
|
|
334
|
+
/** Timeout in seconds for the backend HTTP call. Only used if the backend allows timeout override. */
|
|
335
|
+
timeout?: number;
|
|
334
336
|
}
|
|
335
337
|
/**
|
|
336
338
|
* Options for update operations.
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import type { EventDefinition } from './index';
|
|
3
|
+
import { EventSystem } from './index';
|
|
3
4
|
|
|
4
5
|
// Define test event types
|
|
5
6
|
type TestEvents = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { EventDefinition, EventSystem } from '../../../events/index';
|
|
2
|
+
import { createEventSystem } from '../../../events/index';
|
|
2
3
|
|
|
3
4
|
export const AuthEventTypes = {
|
|
4
5
|
AuthStateChanged: 'AUTH_STATE_CHANGED',
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { RemoteDatabaseService } from '../../services/database/remote';
|
|
2
|
-
import {
|
|
3
|
-
import { DataModule } from '../data/index';
|
|
4
|
-
import {
|
|
1
|
+
import type { RemoteDatabaseService } from '../../services/database/remote';
|
|
2
|
+
import type {
|
|
5
3
|
SchemaStructure,
|
|
6
4
|
AccessDefinition,
|
|
7
5
|
ColumnSchema,
|
|
8
6
|
TypeNameToTypeMap,
|
|
9
7
|
} from '@spooky-sync/query-builder';
|
|
10
|
-
import { Logger } from '../../services/logger/index';
|
|
11
|
-
import { encodeRecordId } from '../../utils/index';
|
|
8
|
+
import type { Logger } from '../../services/logger/index';
|
|
12
9
|
export * from './events/index';
|
|
13
10
|
import { AuthEventTypes, createAuthEventSystem } from './events/index';
|
|
14
|
-
import { PersistenceClient } from '../../types';
|
|
11
|
+
import type { PersistenceClient } from '../../types';
|
|
15
12
|
|
|
16
13
|
// Helper to pretty print types
|
|
17
14
|
type Prettify<T> = {
|
|
@@ -175,7 +172,7 @@ export class AuthService<S extends SchemaStructure> {
|
|
|
175
172
|
|
|
176
173
|
try {
|
|
177
174
|
await this.remote.getClient().invalidate();
|
|
178
|
-
} catch (
|
|
175
|
+
} catch (_e) {
|
|
179
176
|
// Ignore invalidation errors
|
|
180
177
|
}
|
|
181
178
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { LocalDatabaseService } from '../../services/database/index';
|
|
2
|
-
import {
|
|
1
|
+
import type { LocalDatabaseService } from '../../services/database/index';
|
|
2
|
+
import type {
|
|
3
3
|
StreamProcessorService,
|
|
4
4
|
StreamUpdate,
|
|
5
5
|
StreamUpdateReceiver,
|
|
6
6
|
} from '../../services/stream-processor/index';
|
|
7
|
-
import { Logger } from '../../services/logger/index';
|
|
7
|
+
import type { Logger } from '../../services/logger/index';
|
|
8
8
|
import { parseRecordIdString, encodeRecordId, surql } from '../../utils/index';
|
|
9
|
-
import { CacheRecord, QueryConfig } from './types';
|
|
10
|
-
import { RecordVersionArray } from '../../types';
|
|
9
|
+
import type { CacheRecord, QueryConfig } from './types';
|
|
10
|
+
import type { RecordVersionArray } from '../../types';
|
|
11
11
|
|
|
12
12
|
export * from './types';
|
|
13
13
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RecordId, Duration } from 'surrealdb';
|
|
2
|
-
import { QueryTimeToLive
|
|
1
|
+
import type { RecordId, Duration } from 'surrealdb';
|
|
2
|
+
import type { QueryTimeToLive } from '../../types';
|
|
3
3
|
|
|
4
4
|
export type RecordWithId = Record<string, any> & { id: RecordId<string> };
|
|
5
5
|
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { RecordId, Duration } from 'surrealdb';
|
|
2
|
-
import {
|
|
2
|
+
import type {
|
|
3
3
|
SchemaStructure,
|
|
4
4
|
TableNames,
|
|
5
5
|
BackendNames,
|
|
6
6
|
BackendRoutes,
|
|
7
7
|
RoutePayload,
|
|
8
8
|
} from '@spooky-sync/query-builder';
|
|
9
|
-
import { LocalDatabaseService } from '../../services/database/index';
|
|
10
|
-
import { CacheModule, RecordWithId } from '../cache/index';
|
|
11
|
-
import { Logger } from '../../services/logger/index';
|
|
12
|
-
import { StreamUpdate } from '../../services/stream-processor/index';
|
|
13
|
-
import {
|
|
14
|
-
MutationEvent,
|
|
9
|
+
import type { LocalDatabaseService } from '../../services/database/index';
|
|
10
|
+
import type { CacheModule, RecordWithId } from '../cache/index';
|
|
11
|
+
import type { Logger } from '../../services/logger/index';
|
|
12
|
+
import type { StreamUpdate } from '../../services/stream-processor/index';
|
|
13
|
+
import type {
|
|
15
14
|
QueryConfig,
|
|
16
15
|
QueryHash,
|
|
17
16
|
QueryState,
|
|
@@ -21,8 +20,7 @@ import {
|
|
|
21
20
|
RecordVersionArray,
|
|
22
21
|
QueryConfigRecord,
|
|
23
22
|
UpdateOptions,
|
|
24
|
-
RunOptions
|
|
25
|
-
} from '../../types';
|
|
23
|
+
RunOptions} from '../../types';
|
|
26
24
|
import {
|
|
27
25
|
parseRecordIdString,
|
|
28
26
|
extractIdPart,
|
|
@@ -34,8 +32,8 @@ import {
|
|
|
34
32
|
extractTablePart,
|
|
35
33
|
generateId,
|
|
36
34
|
} from '../../utils/index';
|
|
37
|
-
import { CreateEvent, DeleteEvent, UpdateEvent } from '../sync/index';
|
|
38
|
-
import { PushEventOptions } from '../../events/index';
|
|
35
|
+
import type { CreateEvent, DeleteEvent, UpdateEvent } from '../sync/index';
|
|
36
|
+
import type { PushEventOptions } from '../../events/index';
|
|
39
37
|
|
|
40
38
|
/**
|
|
41
39
|
* DataModule - Unified query and mutation management
|
|
@@ -173,6 +171,7 @@ export class DataModule<S extends SchemaStructure> {
|
|
|
173
171
|
if (op === 'UPDATE') {
|
|
174
172
|
// Clear existing timer if any
|
|
175
173
|
if (this.debounceTimers.has(queryHash)) {
|
|
174
|
+
// oxlint-disable-next-line no-non-null-assertion -- guarded by .has() check above
|
|
176
175
|
clearTimeout(this.debounceTimers.get(queryHash)!);
|
|
177
176
|
}
|
|
178
177
|
|
|
@@ -370,6 +369,10 @@ export class DataModule<S extends SchemaStructure> {
|
|
|
370
369
|
retry_strategy: options?.retry_strategy ?? 'linear',
|
|
371
370
|
};
|
|
372
371
|
|
|
372
|
+
if (options?.timeout != null) {
|
|
373
|
+
record.timeout = options.timeout;
|
|
374
|
+
}
|
|
375
|
+
|
|
373
376
|
if (options?.assignedTo) {
|
|
374
377
|
record.assigned_to = options.assignedTo;
|
|
375
378
|
}
|
|
@@ -866,7 +869,7 @@ export function parseUpdateOptions(
|
|
|
866
869
|
const delay = options.debounced !== true ? (options.debounced?.delay ?? 200) : 200;
|
|
867
870
|
const keyType = options.debounced !== true ? (options.debounced?.key ?? id) : id;
|
|
868
871
|
const key =
|
|
869
|
-
keyType === 'recordId_x_fields' ? `${id}::${Object.keys(data).
|
|
872
|
+
keyType === 'recordId_x_fields' ? `${id}::${Object.keys(data).toSorted().join('#')}` : id;
|
|
870
873
|
|
|
871
874
|
pushEventOptions = {
|
|
872
875
|
debounced: {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { LocalDatabaseService, RemoteDatabaseService } from '../../services/database/index';
|
|
2
|
-
import { Logger } from '../../services/logger/index';
|
|
3
|
-
import { SchemaStructure } from '@spooky-sync/query-builder';
|
|
1
|
+
import type { LocalDatabaseService, RemoteDatabaseService } from '../../services/database/index';
|
|
2
|
+
import type { Logger } from '../../services/logger/index';
|
|
3
|
+
import type { SchemaStructure } from '@spooky-sync/query-builder';
|
|
4
4
|
import { RecordId } from 'surrealdb';
|
|
5
|
-
import { StreamUpdate, StreamUpdateReceiver } from '../../services/stream-processor/index';
|
|
5
|
+
import type { StreamUpdate, StreamUpdateReceiver } from '../../services/stream-processor/index';
|
|
6
6
|
import { encodeRecordId } from '../../utils/index';
|
|
7
7
|
|
|
8
8
|
// DevTools interfaces (matching extension expectations)
|
|
@@ -13,8 +13,8 @@ export interface DevToolsEvent {
|
|
|
13
13
|
payload: any;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
import { DataModule } from '../data/index';
|
|
17
|
-
import { AuthService } from '../auth/index';
|
|
16
|
+
import type { DataModule } from '../data/index';
|
|
17
|
+
import type { AuthService } from '../auth/index';
|
|
18
18
|
import { AuthEventTypes } from '../auth/events/index';
|
|
19
19
|
|
|
20
20
|
export class DevToolsService implements StreamUpdateReceiver {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RecordId } from 'surrealdb';
|
|
2
|
-
import { SchemaStructure } from '@spooky-sync/query-builder';
|
|
3
|
-
import { RemoteDatabaseService } from '../../services/database/index';
|
|
4
|
-
import { CacheModule, CacheRecord, RecordWithId } from '../cache/index';
|
|
5
|
-
import { RecordVersionDiff } from '../../types';
|
|
6
|
-
import { Logger } from '../../services/logger/index';
|
|
1
|
+
import type { RecordId } from 'surrealdb';
|
|
2
|
+
import type { SchemaStructure } from '@spooky-sync/query-builder';
|
|
3
|
+
import type { RemoteDatabaseService } from '../../services/database/index';
|
|
4
|
+
import type { CacheModule, CacheRecord, RecordWithId } from '../cache/index';
|
|
5
|
+
import type { RecordVersionDiff } from '../../types';
|
|
6
|
+
import type { Logger } from '../../services/logger/index';
|
|
7
7
|
import { SyncEventTypes, createSyncEventSystem } from './events/index';
|
|
8
8
|
import { encodeRecordId } from '../../utils/index';
|
|
9
9
|
import { cleanRecord } from '../../utils/parser';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { EventDefinition, EventSystem } from '../../../events/index';
|
|
2
|
+
import { createEventSystem } from '../../../events/index';
|
|
3
|
+
import type { RecordVersionArray } from '../../../types';
|
|
3
4
|
|
|
4
5
|
export const SyncQueueEventTypes = {
|
|
5
6
|
MutationEnqueued: 'MUTATION_ENQUEUED',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { LocalDatabaseService } from '../../../services/database/index';
|
|
1
|
+
import type { LocalDatabaseService } from '../../../services/database/index';
|
|
2
|
+
import type {
|
|
3
|
+
SyncQueueEventSystem} from '../events/index';
|
|
2
4
|
import {
|
|
3
5
|
createSyncQueueEventSystem,
|
|
4
|
-
SyncQueueEventSystem,
|
|
5
6
|
SyncQueueEventTypes,
|
|
6
7
|
} from '../events/index';
|
|
7
|
-
import { Logger } from '../../../services/logger/index';
|
|
8
|
+
import type { Logger } from '../../../services/logger/index';
|
|
8
9
|
|
|
9
10
|
export type RegisterEvent = {
|
|
10
11
|
type: 'register';
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { RecordId } from 'surrealdb';
|
|
2
|
-
import { LocalDatabaseService } from '../../../services/database/index';
|
|
1
|
+
import type { RecordId } from 'surrealdb';
|
|
2
|
+
import type { LocalDatabaseService } from '../../../services/database/index';
|
|
3
|
+
import type {
|
|
4
|
+
SyncQueueEventSystem} from '../events/index';
|
|
3
5
|
import {
|
|
4
6
|
createSyncQueueEventSystem,
|
|
5
|
-
SyncQueueEventSystem,
|
|
6
7
|
SyncQueueEventTypes,
|
|
7
8
|
} from '../events/index';
|
|
8
9
|
import { parseRecordIdString, extractTablePart, classifySyncError } from '../../../utils/index';
|
|
9
|
-
import { Logger } from '../../../services/logger/index';
|
|
10
|
-
import { PushEventOptions } from '../../../events/index';
|
|
10
|
+
import type { Logger } from '../../../services/logger/index';
|
|
11
|
+
import type { PushEventOptions } from '../../../events/index';
|
|
11
12
|
|
|
12
13
|
export type CreateEvent = {
|
|
13
14
|
type: 'create';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Logger } from '../../services/logger/index';
|
|
2
|
-
import { UpQueue, DownQueue, DownEvent, UpEvent, RollbackCallback } from './queue/index';
|
|
1
|
+
import type { Logger } from '../../services/logger/index';
|
|
2
|
+
import type { UpQueue, DownQueue, DownEvent, UpEvent, RollbackCallback } from './queue/index';
|
|
3
3
|
import { SyncQueueEventTypes } from './events/index';
|
|
4
4
|
|
|
5
5
|
/**
|
package/src/modules/sync/sync.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { LocalDatabaseService, RemoteDatabaseService } from '../../services/database/index';
|
|
2
|
-
import {
|
|
1
|
+
import type { LocalDatabaseService, RemoteDatabaseService } from '../../services/database/index';
|
|
2
|
+
import type { RecordVersionArray } from '../../types';
|
|
3
3
|
import { createSyncEventSystem, SyncEventTypes, SyncQueueEventTypes } from './events/index';
|
|
4
|
-
import { Logger } from '../../services/logger/index';
|
|
5
|
-
import { DownEvent,
|
|
6
|
-
import {
|
|
4
|
+
import type { Logger } from '../../services/logger/index';
|
|
5
|
+
import type { DownEvent, UpEvent} from './queue/index';
|
|
6
|
+
import { DownQueue, UpQueue } from './queue/index';
|
|
7
|
+
import type { RecordId, Uuid } from 'surrealdb';
|
|
7
8
|
import { ArraySyncer, createDiffFromDbOp } from './utils';
|
|
8
9
|
import { SyncEngine } from './engine';
|
|
9
10
|
import { SyncScheduler } from './scheduler';
|
|
10
|
-
import { SchemaStructure } from '@spooky-sync/query-builder';
|
|
11
|
-
import { CacheModule } from '../cache/index';
|
|
12
|
-
import { DataModule } from '../data/index';
|
|
13
|
-
import { encodeRecordId, extractTablePart,
|
|
11
|
+
import type { SchemaStructure } from '@spooky-sync/query-builder';
|
|
12
|
+
import type { CacheModule } from '../cache/index';
|
|
13
|
+
import type { DataModule } from '../data/index';
|
|
14
|
+
import { encodeRecordId, extractTablePart, surql } from '../../utils/index';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* The main synchronization engine for Sp00ky.
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
createDiffFromDbOp,
|
|
7
7
|
ArraySyncer,
|
|
8
8
|
} from './utils';
|
|
9
|
-
import { RecordVersionArray, RecordVersionDiff } from '../../types';
|
|
9
|
+
import type { RecordVersionArray, RecordVersionDiff } from '../../types';
|
|
10
10
|
import { encodeRecordId } from '../../utils/index';
|
|
11
11
|
|
|
12
12
|
function rid(table: string, id: string): RecordId<string> {
|
|
@@ -305,7 +305,7 @@ describe('ArraySyncer', () => {
|
|
|
305
305
|
expect(diff!.removed).toHaveLength(3);
|
|
306
306
|
// Check they come in sorted order
|
|
307
307
|
const removedIds = diff!.removed.map((r) => encodeRecordId(r));
|
|
308
|
-
const sorted = [...removedIds].
|
|
308
|
+
const sorted = [...removedIds].toSorted();
|
|
309
309
|
expect(removedIds).toEqual(sorted);
|
|
310
310
|
});
|
|
311
311
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RecordId } from 'surrealdb';
|
|
2
|
-
import { RecordVersionArray, RecordVersionDiff } from '../../types';
|
|
1
|
+
import type { RecordId } from 'surrealdb';
|
|
2
|
+
import type { RecordVersionArray, RecordVersionDiff } from '../../types';
|
|
3
3
|
import { parseRecordIdString, encodeRecordId } from '../../utils/index';
|
|
4
4
|
|
|
5
5
|
export class ArraySyncer {
|
|
@@ -8,8 +8,8 @@ export class ArraySyncer {
|
|
|
8
8
|
private needsSort = false;
|
|
9
9
|
|
|
10
10
|
constructor(localArray: RecordVersionArray, remoteArray: RecordVersionArray) {
|
|
11
|
-
this.remoteArray = remoteArray.
|
|
12
|
-
this.localArray = localArray.
|
|
11
|
+
this.remoteArray = remoteArray.toSorted((a, b) => a[0].localeCompare(b[0]));
|
|
12
|
+
this.localArray = localArray.toSorted((a, b) => a[0].localeCompare(b[0]));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -92,10 +92,12 @@ export function diffRecordVersionArray(
|
|
|
92
92
|
return {
|
|
93
93
|
added: added.map((id) => ({
|
|
94
94
|
id: parseRecordIdString(id),
|
|
95
|
+
// oxlint-disable-next-line no-non-null-assertion
|
|
95
96
|
version: remoteMap.get(id)!,
|
|
96
97
|
})),
|
|
97
98
|
updated: updated.map((id) => ({
|
|
98
99
|
id: parseRecordIdString(id),
|
|
100
|
+
// oxlint-disable-next-line no-non-null-assertion
|
|
99
101
|
version: remoteMap.get(id)!,
|
|
100
102
|
})),
|
|
101
103
|
removed: removed.map(parseRecordIdString),
|
|
@@ -126,7 +128,7 @@ export function applyRecordVersionDiff(
|
|
|
126
128
|
currentMap.set(encodeRecordId(item.id), item.version);
|
|
127
129
|
}
|
|
128
130
|
|
|
129
|
-
return Array.from(currentMap).
|
|
131
|
+
return Array.from(currentMap).toSorted((a, b) => a[0].localeCompare(b[0]));
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
export function createDiffFromDbOp(
|
package/src/otel/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Level } from 'pino';
|
|
2
|
-
import { PinoTransmit } from '../types';
|
|
1
|
+
import type { Level } from 'pino';
|
|
2
|
+
import type { PinoTransmit } from '../types';
|
|
3
3
|
|
|
4
4
|
// Map pino levels to OTEL severity numbers
|
|
5
5
|
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#severity-fields
|
|
@@ -74,6 +74,7 @@ export function createOtelTransmit(endpoint: string, level: Level = 'info'): Pin
|
|
|
74
74
|
return {
|
|
75
75
|
level: level,
|
|
76
76
|
send: (levelLabel: string, logEvent: any) => {
|
|
77
|
+
// oxlint-disable-next-line promise/always-return
|
|
77
78
|
otelReady.then((getOtelLogger) => {
|
|
78
79
|
try {
|
|
79
80
|
const messages = [...logEvent.messages];
|
|
@@ -81,12 +82,12 @@ export function createOtelTransmit(endpoint: string, level: Level = 'info'): Pin
|
|
|
81
82
|
|
|
82
83
|
// Construct the message body
|
|
83
84
|
let body = '';
|
|
84
|
-
const
|
|
85
|
+
const lastMsg = messages.pop();
|
|
85
86
|
|
|
86
|
-
if (typeof
|
|
87
|
-
body =
|
|
88
|
-
} else if (
|
|
89
|
-
body = JSON.stringify(
|
|
87
|
+
if (typeof lastMsg === 'string') {
|
|
88
|
+
body = lastMsg;
|
|
89
|
+
} else if (lastMsg) {
|
|
90
|
+
body = JSON.stringify(lastMsg);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
let category = 'sp00ky-client::unknown';
|
|
@@ -114,9 +115,11 @@ export function createOtelTransmit(endpoint: string, level: Level = 'info'): Pin
|
|
|
114
115
|
timestamp: new Date(logEvent.ts),
|
|
115
116
|
});
|
|
116
117
|
} catch (e) {
|
|
118
|
+
// oxlint-disable-next-line no-console
|
|
117
119
|
console.warn('Failed to transmit log to OTEL endpoint', e);
|
|
118
120
|
}
|
|
119
121
|
}).catch((e) => {
|
|
122
|
+
// oxlint-disable-next-line no-console
|
|
120
123
|
console.warn('Failed to load OpenTelemetry modules', e);
|
|
121
124
|
});
|
|
122
125
|
},
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { Surreal, SurrealTransaction } from 'surrealdb';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { Surreal, SurrealTransaction } from 'surrealdb';
|
|
2
|
+
import type { Logger } from '../logger/index';
|
|
3
|
+
import type {
|
|
4
4
|
DatabaseEventSystem,
|
|
5
|
-
DatabaseEventTypes
|
|
6
|
-
|
|
7
|
-
} from './events/index';
|
|
8
|
-
import { SealedQuery } from '../../utils/surql';
|
|
5
|
+
DatabaseEventTypes} from './events/index';
|
|
6
|
+
import type { SealedQuery } from '../../utils/surql';
|
|
9
7
|
|
|
10
8
|
export abstract class AbstractDatabaseService {
|
|
11
9
|
protected client: Surreal;
|
|
@@ -43,6 +41,7 @@ export abstract class AbstractDatabaseService {
|
|
|
43
41
|
async query<T extends unknown[]>(query: string, vars?: Record<string, unknown>): Promise<T> {
|
|
44
42
|
return new Promise((resolve, reject) => {
|
|
45
43
|
this.queryQueue = this.queryQueue
|
|
44
|
+
// oxlint-disable-next-line promise/always-return
|
|
46
45
|
.then(async () => {
|
|
47
46
|
const startTime = performance.now();
|
|
48
47
|
try {
|
|
@@ -87,6 +86,7 @@ export abstract class AbstractDatabaseService {
|
|
|
87
86
|
{ query, vars, err, Category: 'sp00ky-client::Database::query' },
|
|
88
87
|
'Query execution failed'
|
|
89
88
|
);
|
|
89
|
+
// oxlint-disable-next-line no-multiple-resolved -- resolve/reject are in try/catch, mutually exclusive
|
|
90
90
|
reject(err);
|
|
91
91
|
}
|
|
92
92
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { EventDefinition, EventSystem } from '../../../events/index';
|
|
2
|
+
import { createEventSystem } from '../../../events/index';
|
|
2
3
|
|
|
3
4
|
export const DatabaseEventTypes = {
|
|
4
5
|
LocalQuery: 'DATABASE_LOCAL_QUERY',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import { LocalDatabaseService } from './local';
|
|
1
|
+
import type { Logger} from '../logger/index';
|
|
2
|
+
import { createLogger } from '../logger/index';
|
|
3
|
+
import type { LocalDatabaseService } from './local';
|
|
4
4
|
|
|
5
5
|
export interface SchemaRecord {
|
|
6
6
|
hash: string;
|
|
@@ -23,8 +23,8 @@ export class LocalMigrator {
|
|
|
23
23
|
logger: Logger
|
|
24
24
|
) {
|
|
25
25
|
this.logger = logger.child({ service: 'LocalMigrator' });
|
|
26
|
-
logger?.child({ service: 'LocalMigrator' }) ??
|
|
27
|
-
createLogger('info').child({ service: 'LocalMigrator' });
|
|
26
|
+
void (logger?.child({ service: 'LocalMigrator' }) ??
|
|
27
|
+
createLogger('info').child({ service: 'LocalMigrator' }));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
async provision(schemaSurql: string): Promise<void> {
|
|
@@ -94,7 +94,7 @@ export class LocalMigrator {
|
|
|
94
94
|
`SELECT hash, created_at FROM ONLY _00_schema ORDER BY created_at DESC LIMIT 1;`
|
|
95
95
|
);
|
|
96
96
|
return lastSchemaRecord?.hash === hash;
|
|
97
|
-
} catch (
|
|
97
|
+
} catch (_error) {
|
|
98
98
|
return false;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -102,7 +102,7 @@ export class LocalMigrator {
|
|
|
102
102
|
private async recreateDatabase(database: string) {
|
|
103
103
|
try {
|
|
104
104
|
await this.localDb.query(`DEFINE DATABASE _00_temp;`);
|
|
105
|
-
} catch (
|
|
105
|
+
} catch (_e) {
|
|
106
106
|
// Ignore if exists
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -111,7 +111,7 @@ export class LocalMigrator {
|
|
|
111
111
|
USE DB _00_temp;
|
|
112
112
|
REMOVE DATABASE ${database};
|
|
113
113
|
`);
|
|
114
|
-
} catch (
|
|
114
|
+
} catch (_e) {
|
|
115
115
|
// Ignore error if database doesn't exist
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Diagnostic} from 'surrealdb';
|
|
2
|
+
import { applyDiagnostics, DateTime, RecordId, Surreal } from 'surrealdb';
|
|
2
3
|
import { createWasmWorkerEngines } from '@surrealdb/wasm';
|
|
3
|
-
import { Sp00kyConfig } from '../../types';
|
|
4
|
-
import { Logger } from '../logger/index';
|
|
4
|
+
import type { Sp00kyConfig } from '../../types';
|
|
5
|
+
import type { Logger } from '../logger/index';
|
|
5
6
|
import { AbstractDatabaseService } from './database';
|
|
6
7
|
import { createDatabaseEventSystem, DatabaseEventTypes } from './events/index';
|
|
7
|
-
import { encodeRecordId
|
|
8
|
+
import { encodeRecordId } from '../../utils/index';
|
|
8
9
|
|
|
9
10
|
export class LocalDatabaseService extends AbstractDatabaseService {
|
|
10
11
|
private config: Sp00kyConfig<any>['database'];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Diagnostic} from 'surrealdb';
|
|
1
3
|
import {
|
|
2
4
|
applyDiagnostics,
|
|
3
5
|
createRemoteEngines,
|
|
4
|
-
Diagnostic,
|
|
5
6
|
Surreal,
|
|
6
|
-
SurrealTransaction,
|
|
7
7
|
} from 'surrealdb';
|
|
8
|
-
import { Sp00kyConfig } from '../../types';
|
|
9
|
-
import { Logger } from '../logger/index';
|
|
8
|
+
import type { Sp00kyConfig } from '../../types';
|
|
9
|
+
import type { Logger } from '../logger/index';
|
|
10
10
|
import { AbstractDatabaseService } from './database';
|
|
11
11
|
import { createDatabaseEventSystem, DatabaseEventTypes } from './events/index';
|
|
12
12
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import pino, { Level, type Logger as PinoLogger, type LoggerOptions } from 'pino';
|
|
2
|
-
import { PinoTransmit } from '../../types';
|
|
1
|
+
import pino, { type Level, type Logger as PinoLogger, type LoggerOptions } from 'pino';
|
|
2
|
+
import type { PinoTransmit } from '../../types';
|
|
3
3
|
|
|
4
4
|
export type Logger = PinoLogger;
|
|
5
5
|
|
|
@@ -7,6 +7,7 @@ export function createLogger(level: Level = 'info', transmit?: PinoTransmit): Lo
|
|
|
7
7
|
const browserConfig: LoggerOptions['browser'] = {
|
|
8
8
|
asObject: true,
|
|
9
9
|
write: (o: any) => {
|
|
10
|
+
// oxlint-disable-next-line no-console
|
|
10
11
|
console.log(JSON.stringify(o));
|
|
11
12
|
},
|
|
12
13
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Logger } from 'pino';
|
|
2
|
-
import { PersistenceClient } from '../../types';
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { PersistenceClient } from '../../types';
|
|
3
3
|
|
|
4
4
|
export class LocalStoragePersistenceClient implements PersistenceClient {
|
|
5
5
|
private logger: Logger;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Logger } from 'pino';
|
|
2
|
-
import { PersistenceClient } from '../../types';
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { PersistenceClient } from '../../types';
|
|
3
3
|
|
|
4
4
|
export class ResilientPersistenceClient implements PersistenceClient {
|
|
5
5
|
private logger: Logger;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PersistenceClient } from '../../types';
|
|
1
|
+
import type { PersistenceClient } from '../../types';
|
|
2
2
|
import { parseRecordIdString, surql } from '../../utils/index';
|
|
3
|
-
import { Logger } from 'pino';
|
|
4
|
-
import { AbstractDatabaseService } from '../database/database';
|
|
3
|
+
import type { Logger } from 'pino';
|
|
4
|
+
import type { AbstractDatabaseService } from '../database/database';
|
|
5
5
|
|
|
6
6
|
export class SurrealDBPersistenceClient implements PersistenceClient {
|
|
7
7
|
private logger: Logger;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
// oxlint-disable-next-line no-named-as-default -- WASM module default export convention
|
|
1
2
|
import init, { Sp00kyProcessor } from '@spooky-sync/ssp-wasm';
|
|
2
|
-
import { EventDefinition, EventSystem } from '../../events/index';
|
|
3
|
-
import { Logger } from 'pino';
|
|
4
|
-
import { LocalDatabaseService } from '../database/index';
|
|
5
|
-
import { WasmProcessor, WasmStreamUpdate } from './wasm-types';
|
|
6
|
-
import { Duration } from 'surrealdb';
|
|
7
|
-
import { PersistenceClient, QueryTimeToLive, RecordVersionArray } from '../../types';
|
|
3
|
+
import type { EventDefinition, EventSystem } from '../../events/index';
|
|
4
|
+
import type { Logger } from 'pino';
|
|
5
|
+
import type { LocalDatabaseService } from '../database/index';
|
|
6
|
+
import type { WasmProcessor, WasmStreamUpdate } from './wasm-types';
|
|
7
|
+
import type { Duration } from 'surrealdb';
|
|
8
|
+
import type { PersistenceClient, QueryTimeToLive, RecordVersionArray } from '../../types';
|
|
8
9
|
|
|
9
10
|
// Simple interface for query plan registration (replaces Incantation class)
|
|
10
11
|
interface QueryPlanConfig {
|
|
@@ -127,7 +127,7 @@ describe('StreamProcessor Ingest Behavior', () => {
|
|
|
127
127
|
const params = { id: new MockRecordId('user', '2dng4ngbicbl0scod87i') };
|
|
128
128
|
const normalizedParams = normalizeValue(params);
|
|
129
129
|
|
|
130
|
-
const
|
|
130
|
+
const _ingestedRecord = {
|
|
131
131
|
id: 'user:2dng4ngbicbl0scod87i',
|
|
132
132
|
username: 'sara',
|
|
133
133
|
};
|
package/src/sp00ky.ts
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import { DataModule } from './modules/data/index';
|
|
2
|
-
import {
|
|
2
|
+
import type {
|
|
3
3
|
Sp00kyConfig,
|
|
4
4
|
QueryTimeToLive,
|
|
5
5
|
Sp00kyQueryResultPromise,
|
|
6
6
|
PersistenceClient,
|
|
7
|
-
MutationEvent,
|
|
8
7
|
UpdateOptions,
|
|
9
|
-
RunOptions
|
|
10
|
-
} from './types';
|
|
8
|
+
RunOptions} from './types';
|
|
11
9
|
import {
|
|
12
10
|
LocalDatabaseService,
|
|
13
11
|
LocalMigrator,
|
|
14
12
|
RemoteDatabaseService,
|
|
15
13
|
} from './services/database/index';
|
|
16
|
-
import {
|
|
17
|
-
import { Sp00kySync
|
|
18
|
-
import {
|
|
14
|
+
import type { UpEvent } from './modules/sync/index';
|
|
15
|
+
import { Sp00kySync } from './modules/sync/index';
|
|
16
|
+
import type {
|
|
19
17
|
GetTable,
|
|
20
18
|
InnerQuery,
|
|
21
|
-
QueryBuilder,
|
|
22
19
|
QueryOptions,
|
|
23
20
|
SchemaStructure,
|
|
24
21
|
TableModel,
|
|
@@ -26,7 +23,9 @@ import {
|
|
|
26
23
|
BucketNames,
|
|
27
24
|
BackendNames,
|
|
28
25
|
BackendRoutes,
|
|
29
|
-
RoutePayload
|
|
26
|
+
RoutePayload} from '@spooky-sync/query-builder';
|
|
27
|
+
import {
|
|
28
|
+
QueryBuilder
|
|
30
29
|
} from '@spooky-sync/query-builder';
|
|
31
30
|
|
|
32
31
|
import { DevToolsService } from './modules/devtools/index';
|
package/src/types.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RecordId, SchemaStructure } from '@spooky-sync/query-builder';
|
|
2
|
-
import { Level,
|
|
3
|
-
import { PushEventOptions } from './events/index';
|
|
4
|
-
import { UpEvent } from './modules/sync/index';
|
|
1
|
+
import type { RecordId, SchemaStructure } from '@spooky-sync/query-builder';
|
|
2
|
+
import type { Level, LoggerOptions } from 'pino';
|
|
3
|
+
import type { PushEventOptions } from './events/index';
|
|
4
|
+
import type { UpEvent } from './modules/sync/index';
|
|
5
5
|
|
|
6
|
-
export type { Level }
|
|
6
|
+
export type { Level };
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A pino browser transmit object for forwarding logs to an external sink (e.g. OpenTelemetry).
|
|
@@ -214,6 +214,8 @@ export interface RunOptions {
|
|
|
214
214
|
assignedTo?: string;
|
|
215
215
|
max_retries?: number;
|
|
216
216
|
retry_strategy?: 'linear' | 'exponential';
|
|
217
|
+
/** Timeout in seconds for the backend HTTP call. Only used if the backend allows timeout override. */
|
|
218
|
+
timeout?: number;
|
|
217
219
|
}
|
|
218
220
|
|
|
219
221
|
/**
|
package/src/utils/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { GetTable, SchemaStructure, TableModel, TableNames } from '@spooky-sync/query-builder';
|
|
1
|
+
import type { GetTable, SchemaStructure, TableModel, TableNames } from '@spooky-sync/query-builder';
|
|
2
2
|
import { Uuid, RecordId, Duration } from 'surrealdb';
|
|
3
|
-
import { Logger } from '../services/logger/index';
|
|
4
|
-
import { QueryTimeToLive } from '../types';
|
|
3
|
+
import type { Logger } from '../services/logger/index';
|
|
4
|
+
import type { QueryTimeToLive } from '../types';
|
|
5
5
|
|
|
6
6
|
export * from './surql';
|
|
7
7
|
export * from './parser';
|
|
@@ -74,12 +74,12 @@ export function decodeFromSp00ky<S extends SchemaStructure, T extends TableNames
|
|
|
74
74
|
for (const field of Object.keys(table.columns)) {
|
|
75
75
|
const column = table.columns[field] as any;
|
|
76
76
|
const relation = schema.relationships.find((r) => r.from === tableName && r.field === field);
|
|
77
|
-
if ((column.recordId || relation) && encoded[field]
|
|
77
|
+
if ((column.recordId || relation) && encoded[field] !== null && encoded[field] !== undefined) {
|
|
78
78
|
if (encoded[field] instanceof RecordId) {
|
|
79
79
|
encoded[field] = `${encoded[field].table.toString()}:${encoded[field].id}`;
|
|
80
80
|
} else if (
|
|
81
81
|
relation &&
|
|
82
|
-
(encoded[field] instanceof Object || encoded[field]
|
|
82
|
+
(encoded[field] instanceof Object || Array.isArray(encoded[field]))
|
|
83
83
|
) {
|
|
84
84
|
if (Array.isArray(encoded[field])) {
|
|
85
85
|
encoded[field] = encoded[field].map((item) =>
|
|
@@ -117,7 +117,7 @@ export function parseDuration(duration: QueryTimeToLive | Duration): number {
|
|
|
117
117
|
|
|
118
118
|
const match = duration.match(/^(\d+)([smh])$/);
|
|
119
119
|
if (!match) return 600000;
|
|
120
|
-
const val = parseInt(match[1], 10);
|
|
120
|
+
const val = Number.parseInt(match[1], 10);
|
|
121
121
|
const unit = match[2];
|
|
122
122
|
switch (unit) {
|
|
123
123
|
case 's':
|
package/src/utils/parser.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ColumnSchema
|
|
1
|
+
import type { ColumnSchema} from '@spooky-sync/query-builder';
|
|
2
|
+
import { RecordId } from '@spooky-sync/query-builder';
|
|
2
3
|
import { parseRecordIdString } from './index';
|
|
3
4
|
import { DateTime } from 'surrealdb';
|
|
4
5
|
|
package/src/utils/surql.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MutationEventType } from '../types';
|
|
1
|
+
import type { MutationEventType } from '../types';
|
|
2
2
|
|
|
3
3
|
// ==================== TYPES ====================
|
|
4
4
|
|
|
@@ -90,16 +90,16 @@ export const surql: SurqlHelper = {
|
|
|
90
90
|
returnValues: ({ field: string; alias: string } | string)[]
|
|
91
91
|
) {
|
|
92
92
|
return `SELECT ${returnValues
|
|
93
|
-
.map((
|
|
94
|
-
typeof
|
|
95
|
-
?
|
|
96
|
-
: `${
|
|
93
|
+
.map((rv) =>
|
|
94
|
+
typeof rv === 'string'
|
|
95
|
+
? rv
|
|
96
|
+
: `${rv.field} as ${rv.alias}`
|
|
97
97
|
)
|
|
98
98
|
.join(',')} FROM ${table} WHERE ${whereVar
|
|
99
|
-
.map((
|
|
100
|
-
typeof
|
|
101
|
-
? `${
|
|
102
|
-
: `${
|
|
99
|
+
.map((wv) =>
|
|
100
|
+
typeof wv === 'string'
|
|
101
|
+
? `${wv} = $${wv}`
|
|
102
|
+
: `${wv.field} = $${wv.variable}`
|
|
103
103
|
)
|
|
104
104
|
.join(' AND ')}`;
|
|
105
105
|
},
|
|
@@ -136,12 +136,12 @@ export const surql: SurqlHelper = {
|
|
|
136
136
|
keyDataVar: ({ key: string; variable: string } | { statement: string } | string)[]
|
|
137
137
|
) {
|
|
138
138
|
return `UPDATE $${idVar} SET ${keyDataVar
|
|
139
|
-
.map((
|
|
140
|
-
typeof
|
|
141
|
-
? `${
|
|
142
|
-
: 'statement' in
|
|
143
|
-
?
|
|
144
|
-
: `${
|
|
139
|
+
.map((kdv) =>
|
|
140
|
+
typeof kdv === 'string'
|
|
141
|
+
? `${kdv} = $${kdv}`
|
|
142
|
+
: 'statement' in kdv
|
|
143
|
+
? kdv.statement
|
|
144
|
+
: `${kdv.key} = $${kdv.variable}`
|
|
145
145
|
)
|
|
146
146
|
.join(', ')}`;
|
|
147
147
|
},
|