@dvina/sdk 4.1.59 → 4.1.66
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/_generated_documents-VM6RSSXR.js +1 -0
- package/dist/adapters/angular/index.d.ts +2 -2
- package/dist/adapters/angular/index.js +1 -159
- package/dist/adapters/react/index.js +1 -49
- package/dist/billing/index.js +1 -5
- package/dist/chunk-5E7LX4YQ.js +1 -0
- package/dist/chunk-D2L26FRK.js +5 -0
- package/dist/chunk-EK7ODJWE.js +1 -0
- package/dist/chunk-G34ETQUN.js +1 -0
- package/dist/chunk-H3TI6B7T.js +1 -0
- package/dist/chunk-IIQ3WGOJ.js +1 -0
- package/dist/chunk-IO56LXKJ.js +1 -0
- package/dist/chunk-SJ6Q5IDB.js +31 -0
- package/dist/{client-D309vpHA.d.ts → client-CEoJfTM9.d.ts} +2 -257
- package/dist/{index-fFR5so7x.d.ts → index-BzmzBgTh.d.ts} +1 -1
- package/dist/index.d.ts +7 -134
- package/dist/index.js +1 -10
- package/dist/inference/index.js +1 -5
- package/dist/package.json +12 -48
- package/dist/pagination/index.d.ts +2 -2
- package/dist/pagination/index.js +1 -5
- package/dist/{sync-engine-BIaOIpU3.d.ts → sync-engine-Bh0UcTVd.d.ts} +13 -0
- package/package.json +13 -49
- package/dist/_generated_documents-GHGFCEAV.js +0 -4
- package/dist/_generated_documents-GHGFCEAV.js.map +0 -1
- package/dist/_generated_documents-Z5MUI5BE.cjs +0 -2777
- package/dist/_generated_documents-Z5MUI5BE.cjs.map +0 -1
- package/dist/adapters/angular/index.cjs +0 -163
- package/dist/adapters/angular/index.cjs.map +0 -1
- package/dist/adapters/angular/index.d.cts +0 -254
- package/dist/adapters/angular/index.js.map +0 -1
- package/dist/adapters/react/index.cjs +0 -51
- package/dist/adapters/react/index.cjs.map +0 -1
- package/dist/adapters/react/index.d.cts +0 -62
- package/dist/adapters/react/index.js.map +0 -1
- package/dist/billing/index.cjs +0 -26
- package/dist/billing/index.cjs.map +0 -1
- package/dist/billing/index.d.cts +0 -328
- package/dist/billing/index.js.map +0 -1
- package/dist/chunk-2J5WONKO.cjs +0 -1608
- package/dist/chunk-2J5WONKO.cjs.map +0 -1
- package/dist/chunk-342BFYZZ.cjs +0 -98
- package/dist/chunk-342BFYZZ.cjs.map +0 -1
- package/dist/chunk-5WRI5ZAA.js +0 -29
- package/dist/chunk-5WRI5ZAA.js.map +0 -1
- package/dist/chunk-7XBJ77RJ.js +0 -103
- package/dist/chunk-7XBJ77RJ.js.map +0 -1
- package/dist/chunk-AE5KAIKK.js +0 -24
- package/dist/chunk-AE5KAIKK.js.map +0 -1
- package/dist/chunk-COFT5ZYL.js +0 -23777
- package/dist/chunk-COFT5ZYL.js.map +0 -1
- package/dist/chunk-DZUJEN5N.cjs +0 -32
- package/dist/chunk-DZUJEN5N.cjs.map +0 -1
- package/dist/chunk-FOKGSMXS.cjs +0 -27
- package/dist/chunk-FOKGSMXS.cjs.map +0 -1
- package/dist/chunk-HHBDJ65K.cjs +0 -24198
- package/dist/chunk-HHBDJ65K.cjs.map +0 -1
- package/dist/chunk-KEM6SUTS.js +0 -92
- package/dist/chunk-KEM6SUTS.js.map +0 -1
- package/dist/chunk-KSVHC4YE.cjs +0 -1841
- package/dist/chunk-KSVHC4YE.cjs.map +0 -1
- package/dist/chunk-KV5SP7RP.cjs +0 -114
- package/dist/chunk-KV5SP7RP.cjs.map +0 -1
- package/dist/chunk-NH4SMZCW.js +0 -1148
- package/dist/chunk-NH4SMZCW.js.map +0 -1
- package/dist/chunk-PDM2KR7T.js +0 -392
- package/dist/chunk-PDM2KR7T.js.map +0 -1
- package/dist/chunk-UELAE75E.cjs +0 -408
- package/dist/chunk-UELAE75E.cjs.map +0 -1
- package/dist/chunk-WX7EFPHT.js +0 -1600
- package/dist/chunk-WX7EFPHT.js.map +0 -1
- package/dist/client-BRIS6DdR.d.cts +0 -8159
- package/dist/client-Bb2gD6Iz.d.cts +0 -488
- package/dist/error-CsVoUTY8.d.cts +0 -95
- package/dist/index-D_Z25Pa1.d.cts +0 -79
- package/dist/index.cjs +0 -2039
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -3823
- package/dist/index.js.map +0 -1
- package/dist/inference/index.cjs +0 -70
- package/dist/inference/index.cjs.map +0 -1
- package/dist/inference/index.d.cts +0 -80
- package/dist/inference/index.js.map +0 -1
- package/dist/pagination/index.cjs +0 -34
- package/dist/pagination/index.cjs.map +0 -1
- package/dist/pagination/index.d.cts +0 -6
- package/dist/pagination/index.js.map +0 -1
- package/dist/sync-engine-gpxyhQBl.d.cts +0 -478
- package/dist/types-Chg8ASmf.d.cts +0 -116
|
@@ -1,478 +0,0 @@
|
|
|
1
|
-
import { DocumentNode } from 'graphql';
|
|
2
|
-
import * as dexie from 'dexie';
|
|
3
|
-
import { Dexie, Table } from 'dexie';
|
|
4
|
-
import { D as DvinaError, a as DvinaAuthenticationError } from './error-CsVoUTY8.cjs';
|
|
5
|
-
import { a as DvinaQueryRef, M as MutationOptions } from './types-Chg8ASmf.cjs';
|
|
6
|
-
|
|
7
|
-
/** Cached result metadata for a specific query + variables combination */
|
|
8
|
-
interface QueryResultEntry {
|
|
9
|
-
/** Hash of document name + serialized variables */
|
|
10
|
-
key: string;
|
|
11
|
-
/** The entity table these IDs refer to (e.g. 'chats', 'reports') */
|
|
12
|
-
entityType: string;
|
|
13
|
-
/** Ordered list of entity IDs returned by this query */
|
|
14
|
-
entityIds: string[];
|
|
15
|
-
/** Relay PageInfo for cursor-based pagination */
|
|
16
|
-
pageInfo?: {
|
|
17
|
-
hasNextPage: boolean;
|
|
18
|
-
hasPreviousPage: boolean;
|
|
19
|
-
startCursor?: string | null;
|
|
20
|
-
endCursor?: string | null;
|
|
21
|
-
};
|
|
22
|
-
/** Total count if the server returned it */
|
|
23
|
-
totalCount?: number;
|
|
24
|
-
/** Lower-bound sync cursor where this query membership is known to be valid. */
|
|
25
|
-
querySyncId?: string;
|
|
26
|
-
/** Timestamp of the last server fetch */
|
|
27
|
-
fetchedAt: number;
|
|
28
|
-
}
|
|
29
|
-
interface PendingMutationEntry {
|
|
30
|
-
/** Auto-incremented ID */
|
|
31
|
-
id?: number;
|
|
32
|
-
/** Mutation operation name */
|
|
33
|
-
operationName: string;
|
|
34
|
-
/** Serialized DocumentNode name (to re-resolve at replay time) */
|
|
35
|
-
documentName: string;
|
|
36
|
-
/** Serialized variables */
|
|
37
|
-
variables: Record<string, unknown>;
|
|
38
|
-
/** Timestamp when the mutation was queued */
|
|
39
|
-
queuedAt: number;
|
|
40
|
-
/** Number of retry attempts so far */
|
|
41
|
-
retries: number;
|
|
42
|
-
}
|
|
43
|
-
interface SyncMetadataEntry {
|
|
44
|
-
/** Metadata key (e.g. 'lastSyncTimestamp', 'schemaVersion') */
|
|
45
|
-
key: string;
|
|
46
|
-
/** Arbitrary value */
|
|
47
|
-
value: unknown;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Base entity record stored in Dexie.
|
|
51
|
-
*
|
|
52
|
-
* Most entities use `id` as primary key, but some use alternative keys:
|
|
53
|
-
* - `DataSourceTypeDetails` uses `type` (enum string)
|
|
54
|
-
* - `ReportMember` uses compound key `[reportId, insightId]`
|
|
55
|
-
*
|
|
56
|
-
* Use `getPrimaryKeyField()` / `resolvePrimaryKey()` for PK-safe access.
|
|
57
|
-
*/
|
|
58
|
-
interface EntityRecord {
|
|
59
|
-
__typename?: string;
|
|
60
|
-
[key: string]: unknown;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* The Dvina IndexedDB database.
|
|
64
|
-
*
|
|
65
|
-
* One database per workspace+user, lazily created on first access.
|
|
66
|
-
* Entity tables are auto-generated from the GraphQL schema (via `_generated_store.ts`).
|
|
67
|
-
* Meta tables (`_queryResults`, `_pendingMutations`, `_sync`) support
|
|
68
|
-
* the SyncEngine's caching and offline mutation queue.
|
|
69
|
-
*
|
|
70
|
-
* Uses Dexie v4 — we create an instance with `new Dexie(name)` and define
|
|
71
|
-
* the schema via `.version().stores()`.
|
|
72
|
-
*/
|
|
73
|
-
declare class DvinaDatabase {
|
|
74
|
-
readonly db: Dexie;
|
|
75
|
-
private readonly _dbName;
|
|
76
|
-
/**
|
|
77
|
-
* Resolves when the schema-hash check is complete.
|
|
78
|
-
* Consumers that depend on a consistent schema should await this before
|
|
79
|
-
* performing reads/writes. The factory function `getOrCreateDatabase`
|
|
80
|
-
* handles this automatically.
|
|
81
|
-
*/
|
|
82
|
-
readonly ready: Promise<void>;
|
|
83
|
-
constructor(workspaceId: string, userId: string);
|
|
84
|
-
/**
|
|
85
|
-
* Verify that the stored schema hash matches the current codegen hash.
|
|
86
|
-
* If the hashes differ the database is deleted and recreated so that
|
|
87
|
-
* stale indexes / missing tables never cause silent data corruption.
|
|
88
|
-
*
|
|
89
|
-
* On a fresh database (no stored hash) the current hash is persisted.
|
|
90
|
-
*/
|
|
91
|
-
private _ensureSchemaCompatibility;
|
|
92
|
-
get _queryResults(): Table<QueryResultEntry, string, QueryResultEntry>;
|
|
93
|
-
get _pendingMutations(): Table<PendingMutationEntry, number, PendingMutationEntry>;
|
|
94
|
-
get _sync(): Table<SyncMetadataEntry, string, SyncMetadataEntry>;
|
|
95
|
-
/** Get a table by name (generic accessor for all entity tables) */
|
|
96
|
-
table<T = unknown, TKey = unknown>(tableName: string): Table<T, TKey>;
|
|
97
|
-
/** Access all tables */
|
|
98
|
-
get allTables(): Table[];
|
|
99
|
-
/** Run a read-write transaction across specified tables */
|
|
100
|
-
transaction<U>(mode: 'rw' | 'r', tables: Table[], scope: () => PromiseLike<U> | U): dexie.PromiseExtended<U>;
|
|
101
|
-
/** Close the database connection and evict from the module-level cache. */
|
|
102
|
-
close(): void;
|
|
103
|
-
/** Get the last processed sync event ID, or '0' if none. */
|
|
104
|
-
getLastSyncId(): Promise<string>;
|
|
105
|
-
/** Persist the last processed sync event ID. */
|
|
106
|
-
setLastSyncId(syncId: string): Promise<void>;
|
|
107
|
-
/** Get the last applied remote cache epoch, or 0 if none. */
|
|
108
|
-
getCacheEpoch(): Promise<number>;
|
|
109
|
-
/** Persist the last applied remote cache epoch. */
|
|
110
|
-
setCacheEpoch(cacheEpoch: number): Promise<void>;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Get or create a DvinaDatabase instance.
|
|
114
|
-
*
|
|
115
|
-
* Databases are cached by name to avoid opening multiple connections
|
|
116
|
-
* to the same IndexedDB database. The returned promise resolves once
|
|
117
|
-
* the schema-hash compatibility check is complete; after that the
|
|
118
|
-
* database is guaranteed to match the current codegen schema.
|
|
119
|
-
*
|
|
120
|
-
* @param token - A valid JWT from which workspaceId and userId are extracted
|
|
121
|
-
* @returns The DvinaDatabase instance after schema compatibility is ensured
|
|
122
|
-
*/
|
|
123
|
-
declare function getOrCreateDatabase(token: string): Promise<DvinaDatabase>;
|
|
124
|
-
/**
|
|
125
|
-
* Close and remove a cached database instance.
|
|
126
|
-
* Useful for logout / workspace switching.
|
|
127
|
-
*/
|
|
128
|
-
declare function closeDatabase(token: string): void;
|
|
129
|
-
/**
|
|
130
|
-
* Delete the IndexedDB database entirely.
|
|
131
|
-
* Use with caution — this wipes all cached data for the workspace+user.
|
|
132
|
-
*/
|
|
133
|
-
declare function deleteDatabase(token: string): Promise<void>;
|
|
134
|
-
|
|
135
|
-
interface HttpTransportOptions {
|
|
136
|
-
/** Full GraphQL HTTP endpoint URL (e.g. 'https://api.dvina.ai/graphql') */
|
|
137
|
-
url: string;
|
|
138
|
-
/**
|
|
139
|
-
* Returns an auth token.
|
|
140
|
-
* When called with `{ forceRefresh: true }`, the callback must bypass any
|
|
141
|
-
* cache and obtain a brand-new token (e.g. via Auth0's silent refresh).
|
|
142
|
-
*/
|
|
143
|
-
getToken: (options?: {
|
|
144
|
-
forceRefresh?: boolean;
|
|
145
|
-
}) => Promise<string>;
|
|
146
|
-
/** Returns the preferred language, or undefined */
|
|
147
|
-
getLanguage: () => string | undefined;
|
|
148
|
-
/** Returns the current client platform. */
|
|
149
|
-
getPlatform?: () => 'web' | 'ios' | 'android';
|
|
150
|
-
/** Returns the user's IANA timezone when available. */
|
|
151
|
-
getUserTimezone?: () => string | undefined;
|
|
152
|
-
/**
|
|
153
|
-
* Optional global error callback. Called with the final error right before
|
|
154
|
-
* it is thrown to the caller. Useful for centralized error reporting / UI alerts.
|
|
155
|
-
*
|
|
156
|
-
* **Not** called for transient errors that are retried internally (e.g.
|
|
157
|
-
* intermediate 401s that trigger a token refresh, or network retries).
|
|
158
|
-
* Only invoked for the terminal error that will actually propagate.
|
|
159
|
-
*/
|
|
160
|
-
onError?: (error: DvinaError) => void;
|
|
161
|
-
}
|
|
162
|
-
interface HttpTransport {
|
|
163
|
-
/** Execute a GraphQL query or mutation */
|
|
164
|
-
request: <T>(document: DocumentNode, variables?: Record<string, unknown>) => Promise<T>;
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Create a fetch-based GraphQL HTTP transport with:
|
|
168
|
-
* - Auth header injection (Bearer token)
|
|
169
|
-
* - Language header injection
|
|
170
|
-
* - Retry on network errors (status 0, up to 4 attempts with linear backoff)
|
|
171
|
-
* - Auth error handling (401/UNAUTHENTICATED → token refresh → retry)
|
|
172
|
-
*/
|
|
173
|
-
declare function createHttpTransport(options: HttpTransportOptions): HttpTransport;
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* SSE transport for delta sync.
|
|
177
|
-
*
|
|
178
|
-
* Connects to the backend SSE endpoint and emits sync events.
|
|
179
|
-
*
|
|
180
|
-
* Features:
|
|
181
|
-
* - Fetch-based SSE with Authorization header (no query parameter token exposure)
|
|
182
|
-
* - Automatic reconnection with exponential backoff
|
|
183
|
-
* - Auth failure detection with short-delay retry for token refresh
|
|
184
|
-
* - Automatic re-registration and periodic refresh of active query subscriptions
|
|
185
|
-
* - Event listener pattern for processing sync events
|
|
186
|
-
*/
|
|
187
|
-
|
|
188
|
-
interface SseSyncEvent {
|
|
189
|
-
id: string;
|
|
190
|
-
type: 'upsert' | 'delete';
|
|
191
|
-
modelName: string;
|
|
192
|
-
entityId: string;
|
|
193
|
-
payload: Record<string, unknown> | null;
|
|
194
|
-
}
|
|
195
|
-
interface SseQueryEvent {
|
|
196
|
-
type: 'add' | 'remove' | 'resync';
|
|
197
|
-
subscriptionId: string;
|
|
198
|
-
entityId?: string;
|
|
199
|
-
entityType: string;
|
|
200
|
-
}
|
|
201
|
-
type RealtimeEventTopic = 'active-chats' | 'active-tabs' | 'desktop-device-presence' | 'token-usage-status';
|
|
202
|
-
interface SseRealtimeEvent {
|
|
203
|
-
topic: RealtimeEventTopic;
|
|
204
|
-
type: string;
|
|
205
|
-
data: unknown;
|
|
206
|
-
}
|
|
207
|
-
interface SubscriptionDescriptor {
|
|
208
|
-
id: string;
|
|
209
|
-
entityType: string;
|
|
210
|
-
operationName: string;
|
|
211
|
-
modelName: string;
|
|
212
|
-
filter?: Record<string, unknown>;
|
|
213
|
-
querySyncId?: string;
|
|
214
|
-
}
|
|
215
|
-
interface SseTransportOptions {
|
|
216
|
-
/** Full SSE endpoint URL (e.g. 'https://api.dvina.ai/api/sync/stream') */
|
|
217
|
-
url: string;
|
|
218
|
-
/** Returns an auth token. */
|
|
219
|
-
getToken: (options?: {
|
|
220
|
-
forceRefresh?: boolean;
|
|
221
|
-
}) => Promise<string>;
|
|
222
|
-
/** Called when a sync event is received. Processing is awaited to preserve stream order. */
|
|
223
|
-
onEvent: (event: SseSyncEvent) => void | Promise<void>;
|
|
224
|
-
/** Called when a query event is received (server-driven subscription update). Processing is awaited to preserve stream order. */
|
|
225
|
-
onQueryEvent?: (event: SseQueryEvent) => void | Promise<void>;
|
|
226
|
-
/** Called when a user-scoped realtime event is received. Processing is awaited to preserve stream order. */
|
|
227
|
-
onRealtimeEvent?: (event: SseRealtimeEvent) => void | Promise<void>;
|
|
228
|
-
/** Called when the initial cursor is received (fresh connection) */
|
|
229
|
-
onCursor?: (syncId: string) => void;
|
|
230
|
-
/** Called when the server signals that the sync gap is unrecoverable and a full resync is needed */
|
|
231
|
-
onFullResync?: () => void;
|
|
232
|
-
/** Called after a reconnect successfully re-registers active subscriptions */
|
|
233
|
-
onReconnect?: () => void;
|
|
234
|
-
/** Called on connection state changes */
|
|
235
|
-
onStateChange?: (state: 'connecting' | 'connected' | 'disconnected') => void;
|
|
236
|
-
/** Called when auth recovery fails permanently */
|
|
237
|
-
onError?: (error: DvinaAuthenticationError) => void;
|
|
238
|
-
}
|
|
239
|
-
interface SseTransport {
|
|
240
|
-
/** Start the SSE connection */
|
|
241
|
-
connect(lastSyncId?: string): Promise<void>;
|
|
242
|
-
/** Close the SSE connection */
|
|
243
|
-
disconnect(): void;
|
|
244
|
-
/** Force a reconnect using the latest cursor and subscriptions */
|
|
245
|
-
reconnect(): void;
|
|
246
|
-
/** Whether the transport is currently connected */
|
|
247
|
-
readonly connected: boolean;
|
|
248
|
-
/** Register a query subscription (fire-and-forget POST) */
|
|
249
|
-
subscribe(descriptor: SubscriptionDescriptor): void;
|
|
250
|
-
/** Unregister a query subscription (fire-and-forget POST) */
|
|
251
|
-
unsubscribe(subscriptionId: string): void;
|
|
252
|
-
/** Register a realtime event topic on the existing sync stream. */
|
|
253
|
-
subscribeEvent(topic: RealtimeEventTopic): void;
|
|
254
|
-
/** Unregister a realtime event topic from the existing sync stream. */
|
|
255
|
-
unsubscribeEvent(topic: RealtimeEventTopic): void;
|
|
256
|
-
}
|
|
257
|
-
declare function createSseTransport(options: SseTransportOptions): SseTransport;
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Convention-based cache rules generated by codegen.
|
|
261
|
-
* These tell the SyncEngine how to update the local store after a mutation.
|
|
262
|
-
*/
|
|
263
|
-
interface CacheRuleCreate {
|
|
264
|
-
type: 'create';
|
|
265
|
-
/** Dexie table name for the created entity (e.g. 'chats') */
|
|
266
|
-
entityType: string;
|
|
267
|
-
/** Query result keys to prepend the new entity to (e.g. ['chats']) */
|
|
268
|
-
connectionFields: string[];
|
|
269
|
-
}
|
|
270
|
-
interface CacheRuleUpdate {
|
|
271
|
-
type: 'update';
|
|
272
|
-
/** Dexie table name for the updated entity */
|
|
273
|
-
entityType: string;
|
|
274
|
-
}
|
|
275
|
-
interface CacheRuleDelete {
|
|
276
|
-
type: 'delete';
|
|
277
|
-
/** Dexie table name for the deleted entity */
|
|
278
|
-
entityType: string;
|
|
279
|
-
/** Query result keys to remove the entity from */
|
|
280
|
-
connectionFields: string[];
|
|
281
|
-
/** Related entity types to cascade-delete alongside the parent entity */
|
|
282
|
-
cascadeDelete?: CacheCascadeDeleteRule[];
|
|
283
|
-
}
|
|
284
|
-
interface CacheCascadeDeleteRule {
|
|
285
|
-
/** Dexie table name for the related entity to remove */
|
|
286
|
-
entityType: string;
|
|
287
|
-
/** Explicit foreign-key fields to match against the parent ID */
|
|
288
|
-
relationFields?: string[];
|
|
289
|
-
/** Nested cascade rules for children of this related entity */
|
|
290
|
-
cascadeDelete?: CacheCascadeDeleteRule[];
|
|
291
|
-
}
|
|
292
|
-
type CacheRule = CacheRuleCreate | CacheRuleUpdate | CacheRuleDelete;
|
|
293
|
-
interface SyncEngineOptions {
|
|
294
|
-
/** The Dexie database instance */
|
|
295
|
-
db: DvinaDatabase;
|
|
296
|
-
/** HTTP transport for queries and mutations */
|
|
297
|
-
httpTransport: HttpTransport;
|
|
298
|
-
/** Optional SSE transport for delta sync (browser-only) */
|
|
299
|
-
sseTransport?: SseTransport;
|
|
300
|
-
}
|
|
301
|
-
interface WatchedRelationMetadata {
|
|
302
|
-
fieldName: string;
|
|
303
|
-
entityType: string;
|
|
304
|
-
requiredFields: string[];
|
|
305
|
-
isConnection: boolean;
|
|
306
|
-
isList: boolean;
|
|
307
|
-
hasNestedIncludes: boolean;
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* The SyncEngine is the central orchestrator for all data operations in the SDK.
|
|
311
|
-
*
|
|
312
|
-
* It sits between the generated SDK classes and the transport/store layers:
|
|
313
|
-
*
|
|
314
|
-
* ```
|
|
315
|
-
* SDK classes → SyncEngine → HTTP Transport (server)
|
|
316
|
-
* → Dexie (local store)
|
|
317
|
-
* → liveQuery (reactivity)
|
|
318
|
-
* ```
|
|
319
|
-
*
|
|
320
|
-
* Responsibilities:
|
|
321
|
-
* 1. **query()** — Fetch from server → normalize → write to Dexie → return data
|
|
322
|
-
* 2. **watch()** — Create a Dexie liveQuery, fetch from server on cold start,
|
|
323
|
-
* auto-update on any store change
|
|
324
|
-
* 3. **mutate()** — Optimistic write → server call → commit/rollback
|
|
325
|
-
* 4. **Cache rules** — Convention-based auto cache updates for CRUD mutations
|
|
326
|
-
*/
|
|
327
|
-
declare class SyncEngine {
|
|
328
|
-
private _db;
|
|
329
|
-
private _sse?;
|
|
330
|
-
private _cache;
|
|
331
|
-
private _queryExecutor;
|
|
332
|
-
private _mutationExecutor;
|
|
333
|
-
/**
|
|
334
|
-
* Maps subscriptionId → queryKey for routing server-driven query events
|
|
335
|
-
* to the correct cache entry. Populated by watch() when a subscription
|
|
336
|
-
* descriptor is provided, cleaned up on dispose().
|
|
337
|
-
*/
|
|
338
|
-
private _subscriptionToQueryKey;
|
|
339
|
-
/** Active subscription metadata used for targeted revalidation fallback. */
|
|
340
|
-
private _subscriptionToQuery;
|
|
341
|
-
/** Last per-query revalidation timestamp to avoid refetch storms. */
|
|
342
|
-
private _lastRevalidatedAt;
|
|
343
|
-
/** Retry timers for recovery refetches that failed and need another attempt. */
|
|
344
|
-
private _revalidationRetryTimers;
|
|
345
|
-
/**
|
|
346
|
-
* Last mutation/sync touch timestamp by entity type.
|
|
347
|
-
* Used to detect stale cached query results on watch re-entry.
|
|
348
|
-
*/
|
|
349
|
-
private _entityTypeTouchedAt;
|
|
350
|
-
constructor(options: SyncEngineOptions);
|
|
351
|
-
/**
|
|
352
|
-
* Start the SSE delta sync connection.
|
|
353
|
-
* Reads the last sync cursor from Dexie and connects to the SSE endpoint.
|
|
354
|
-
* Incoming events are automatically written to Dexie, triggering liveQuery updates.
|
|
355
|
-
*/
|
|
356
|
-
startSync(): Promise<void>;
|
|
357
|
-
/**
|
|
358
|
-
* Stop the SSE delta sync connection.
|
|
359
|
-
*/
|
|
360
|
-
stopSync(): void;
|
|
361
|
-
/**
|
|
362
|
-
* Handle a full-resync signal from the server.
|
|
363
|
-
*
|
|
364
|
-
* Clears all cached entities and query results, restarts delta sync, and
|
|
365
|
-
* refetches active subscription-backed queries once so filtered connections
|
|
366
|
-
* are rebuilt from source of truth instead of waiting for future delta events.
|
|
367
|
-
*/
|
|
368
|
-
handleFullResync(): Promise<void>;
|
|
369
|
-
/**
|
|
370
|
-
* Ordinary transport reconnects should recover from the sync cursor and
|
|
371
|
-
* server-side subscription state without eagerly refetching every active query.
|
|
372
|
-
*/
|
|
373
|
-
handleTransportReconnect(): Promise<void>;
|
|
374
|
-
/**
|
|
375
|
-
* Process an incoming SSE sync event.
|
|
376
|
-
* Writes the entity to Dexie and updates the sync cursor atomically.
|
|
377
|
-
*/
|
|
378
|
-
processSyncEvent(event: SseSyncEvent): Promise<void>;
|
|
379
|
-
/**
|
|
380
|
-
* Execute a query: fetch from server → normalize → write to Dexie → return raw data.
|
|
381
|
-
*
|
|
382
|
-
* For connection queries, also writes the ordered entity IDs to `_queryResults`
|
|
383
|
-
* so that `watch()` can reconstruct the same ordered list from the store.
|
|
384
|
-
*/
|
|
385
|
-
query<T>(document: DocumentNode, variables?: Record<string, unknown>, operationName?: string): Promise<T>;
|
|
386
|
-
/**
|
|
387
|
-
* Create a reactive query that auto-updates when the underlying store changes.
|
|
388
|
-
*
|
|
389
|
-
* **Cold start**: The first emission waits for the server fetch to complete.
|
|
390
|
-
* After that, Dexie's `liveQuery` handles reactivity — any write to a table
|
|
391
|
-
* accessed by the query factory triggers a re-emission.
|
|
392
|
-
*
|
|
393
|
-
* When a `subscriptionDescriptor` is provided, the watch registers a
|
|
394
|
-
* server-driven subscription via the SSE transport. The server evaluates
|
|
395
|
-
* Prisma filters on create/update/upsert events and sends targeted
|
|
396
|
-
* `query-add` / `query-remove`
|
|
397
|
-
* events back, which this engine routes to the correct cache entry.
|
|
398
|
-
*
|
|
399
|
-
* @param document - The GraphQL query document
|
|
400
|
-
* @param variables - Query variables
|
|
401
|
-
* @param operationName - The operation name (used as the query result cache key)
|
|
402
|
-
* @param buildResult - A function that reads from Dexie and returns the raw response shape.
|
|
403
|
-
* @param subscriptionDescriptor - Optional server-driven subscription metadata for filtered queries.
|
|
404
|
-
*/
|
|
405
|
-
watch<T>(document: DocumentNode, variables: Record<string, unknown> | undefined, operationName: string, buildResult: (db: DvinaDatabase) => Promise<T> | T, subscriptionDescriptor?: SubscriptionDescriptor, relationMetadata?: WatchedRelationMetadata[]): DvinaQueryRef<T>;
|
|
406
|
-
private _subscribeWithQuerySyncId;
|
|
407
|
-
/**
|
|
408
|
-
* Execute a mutation with optional optimistic update and automatic cache rule.
|
|
409
|
-
*
|
|
410
|
-
* Flow:
|
|
411
|
-
* 1. **Optimistic write** (if cache rule is create/update/delete) — immediately
|
|
412
|
-
* update Dexie so all watchers see the change
|
|
413
|
-
* 2. **Server call** — send the mutation to the server
|
|
414
|
-
* 3. **Commit** — normalize server response and write to Dexie (replacing optimistic data)
|
|
415
|
-
* 4. **Rollback** (on error) — restore the original state in Dexie
|
|
416
|
-
*/
|
|
417
|
-
mutate<T>(document: DocumentNode, variables?: Record<string, unknown>, cacheRule?: CacheRule, options?: MutationOptions | Record<string, unknown>): Promise<T>;
|
|
418
|
-
/** Direct access to the Dexie database (for advanced use cases) */
|
|
419
|
-
get db(): DvinaDatabase;
|
|
420
|
-
/**
|
|
421
|
-
* Read a single entity from the store by table name and primary key.
|
|
422
|
-
*
|
|
423
|
-
* @param tableName - Dexie table name (e.g. 'chats', 'reportMembers')
|
|
424
|
-
* @param pk - Primary key value. String for simple keys, string[] for compound keys.
|
|
425
|
-
*/
|
|
426
|
-
getEntity(tableName: string, pk: string | string[]): Promise<EntityRecord | undefined>;
|
|
427
|
-
/**
|
|
428
|
-
* Read query result metadata from the store.
|
|
429
|
-
*/
|
|
430
|
-
getQueryResult(operationName: string, variables?: Record<string, unknown>): Promise<QueryResultEntry | undefined>;
|
|
431
|
-
/**
|
|
432
|
-
* Invalidate (delete) a query result, forcing the next watch() to refetch.
|
|
433
|
-
*/
|
|
434
|
-
invalidateQuery(operationName: string, variables?: Record<string, unknown>): Promise<void>;
|
|
435
|
-
/**
|
|
436
|
-
* Clear all data from the store (but keep the database structure).
|
|
437
|
-
* Useful for logout scenarios.
|
|
438
|
-
*/
|
|
439
|
-
clearAll(): Promise<void>;
|
|
440
|
-
/**
|
|
441
|
-
* Process a server-driven query event (query-add / query-remove).
|
|
442
|
-
*
|
|
443
|
-
* The server evaluates Prisma filters on create/update/upsert events and sends targeted
|
|
444
|
-
* events to subscriptions that match. This method routes the event to the
|
|
445
|
-
* correct query result cache entry using the subscriptionId → queryKey map.
|
|
446
|
-
*/
|
|
447
|
-
processQueryEvent(event: SseQueryEvent): Promise<void>;
|
|
448
|
-
/**
|
|
449
|
-
* Handle an upsert sync event: normalize the payload and write to Dexie.
|
|
450
|
-
*
|
|
451
|
-
* The updated entity type is marked as touched so cached query results can
|
|
452
|
-
* be revalidated lazily when those queries become active again.
|
|
453
|
-
*/
|
|
454
|
-
private _processSyncUpsert;
|
|
455
|
-
private _markEntityTypeTouched;
|
|
456
|
-
private _revalidateSubscriptionIfStale;
|
|
457
|
-
private _revalidateAllActiveSubscriptions;
|
|
458
|
-
private _revalidateSubscriptions;
|
|
459
|
-
private _revalidateSubscriptionQuery;
|
|
460
|
-
private _scheduleRevalidationRetry;
|
|
461
|
-
private _clearRevalidationRetry;
|
|
462
|
-
private _getActiveSubscriptionByQueryKey;
|
|
463
|
-
private _hasActiveSubscriptionForQueryKey;
|
|
464
|
-
private _hasOtherActiveSubscriptionForQueryKey;
|
|
465
|
-
private _getActiveSubscriptionsForEntityType;
|
|
466
|
-
private _materializeWatchedRelations;
|
|
467
|
-
private _resolveStoredRelationFallback;
|
|
468
|
-
private _subscriptionNeedsRevalidation;
|
|
469
|
-
private _canMaterializeRelationRecord;
|
|
470
|
-
private _buildMaterializedRelationRecord;
|
|
471
|
-
private _inferParentLinkField;
|
|
472
|
-
/**
|
|
473
|
-
* Handle a delete sync event: remove entity from Dexie and query results.
|
|
474
|
-
*/
|
|
475
|
-
private _processSyncDelete;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
export { type CacheRule as C, DvinaDatabase as D, type RealtimeEventTopic as R, SyncEngine as S, type SseRealtimeEvent as a, type CacheRuleCreate as b, createHttpTransport as c, type CacheRuleDelete as d, type CacheRuleUpdate as e, type SseQueryEvent as f, type SseSyncEvent as g, type SseTransport as h, type SseTransportOptions as i, type SubscriptionDescriptor as j, closeDatabase as k, createSseTransport as l, deleteDatabase as m, getOrCreateDatabase as n };
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { DocumentNode } from 'graphql';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Options passed to `fetch()` and `watch()` terminal methods on query/mutation builders.
|
|
5
|
-
*/
|
|
6
|
-
interface FetchOptions {
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Options passed to SDK mutations.
|
|
10
|
-
*
|
|
11
|
-
* `optimisticData` is written to the local SyncEngine store before the network
|
|
12
|
-
* request starts. `onOptimisticApplied` runs after that local write completes.
|
|
13
|
-
*/
|
|
14
|
-
interface MutationOptions {
|
|
15
|
-
optimisticData?: Record<string, unknown>;
|
|
16
|
-
onOptimisticApplied?: () => void;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Core transport abstraction.
|
|
20
|
-
* The SDK routes all GraphQL operations through this function.
|
|
21
|
-
*
|
|
22
|
-
* @template T - The expected response data shape
|
|
23
|
-
*/
|
|
24
|
-
type DvinaRequest = <T>(document: DocumentNode, variables?: Record<string, unknown>, options?: FetchOptions) => Promise<T>;
|
|
25
|
-
/**
|
|
26
|
-
* Subscription transport abstraction.
|
|
27
|
-
* Returns an `AsyncIterable` that yields values as the server pushes them
|
|
28
|
-
* over WebSocket (graphql-ws protocol).
|
|
29
|
-
*
|
|
30
|
-
* @template T - The expected payload shape per emission
|
|
31
|
-
*/
|
|
32
|
-
type DvinaSubscribe = <T>(document: DocumentNode, variables?: Record<string, unknown>) => AsyncIterable<T>;
|
|
33
|
-
/**
|
|
34
|
-
* Store-reactive query reference. Implements `AsyncIterable` so it can be consumed
|
|
35
|
-
* with `for await...of` in any JavaScript environment, and converted to framework
|
|
36
|
-
* primitives via adapters (`toSignal` for Angular, `useLiveQuery` for React).
|
|
37
|
-
*
|
|
38
|
-
* Backed by Dexie's `liveQuery` — each store change yields a new value.
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```typescript
|
|
42
|
-
* // Vanilla / Node.js
|
|
43
|
-
* const ref = sdk.reports({ first: 20 }).watch();
|
|
44
|
-
* for await (const reports of ref) {
|
|
45
|
-
* console.log(reports.nodes);
|
|
46
|
-
* }
|
|
47
|
-
*
|
|
48
|
-
* // Angular (via @dvina/sdk/angular adapter)
|
|
49
|
-
* reports = toSignal(this.sdk.reports({ first: 20 }).watch());
|
|
50
|
-
* // template: {{ reports()?.nodes }}
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
interface DvinaAsyncRef<T> extends AsyncIterable<T> {
|
|
54
|
-
/** The most recently emitted value, or `undefined` if no value has been emitted yet. */
|
|
55
|
-
readonly current: T | undefined;
|
|
56
|
-
/** Dispose of this ref and terminate active async iteration. */
|
|
57
|
-
dispose(): void;
|
|
58
|
-
}
|
|
59
|
-
interface DvinaQueryRef<T> extends DvinaAsyncRef<T> {
|
|
60
|
-
/** Force re-fetch from network, replacing cached data. New value will be yielded. */
|
|
61
|
-
refetch(variables?: Record<string, unknown>): Promise<T>;
|
|
62
|
-
/** Fetch additional pages and merge into cache. New value will be yielded. */
|
|
63
|
-
fetchMore(variables: Record<string, unknown>): Promise<void>;
|
|
64
|
-
/**
|
|
65
|
-
* Dispose of this query ref, unsubscribing from the underlying liveQuery.
|
|
66
|
-
* Any active `for await` loops will terminate. Always call this when done
|
|
67
|
-
* (framework adapters handle this automatically via lifecycle hooks).
|
|
68
|
-
*/
|
|
69
|
-
dispose(): void;
|
|
70
|
-
/** AsyncIterable protocol — enables `for await (const value of ref) { ... }` */
|
|
71
|
-
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
72
|
-
}
|
|
73
|
-
type WithIncludes<T, TIncluded> = [keyof TIncluded] extends [never] ? T : Omit<T, keyof TIncluded> & TIncluded;
|
|
74
|
-
/**
|
|
75
|
-
* Utility type that applies included relation types to each node in a Connection.
|
|
76
|
-
*
|
|
77
|
-
* When a connection query includes relations (e.g. `sdk.chats().agent().fetch()`),
|
|
78
|
-
* the included data lives on each node, not on the connection itself.
|
|
79
|
-
* This type overrides the `nodes` array so each node has the included relations
|
|
80
|
-
* as properties (using `Omit` to replace lazy-fetch methods with concrete types).
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```typescript
|
|
84
|
-
* // Without includes:
|
|
85
|
-
* ChatConnection // nodes: Chat[]
|
|
86
|
-
*
|
|
87
|
-
* // With includes:
|
|
88
|
-
* ConnectionWithNodes<ChatConnection, { agent: Agent }>
|
|
89
|
-
* // nodes: (Omit<Chat, 'agent'> & { agent: Agent })[]
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
type ConnectionWithNodes<C, TNodeExtras> = [keyof TNodeExtras] extends [never] ? C : C extends {
|
|
93
|
-
nodes: (infer N)[];
|
|
94
|
-
} ? Omit<C, 'nodes'> & {
|
|
95
|
-
nodes: WithIncludes<N, TNodeExtras>[];
|
|
96
|
-
} : C;
|
|
97
|
-
/**
|
|
98
|
-
* Pagination variables following the Relay spec.
|
|
99
|
-
*/
|
|
100
|
-
interface ConnectionVariables {
|
|
101
|
-
after?: string | null;
|
|
102
|
-
before?: string | null;
|
|
103
|
-
first?: number | null;
|
|
104
|
-
last?: number | null;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* PageInfo following the Relay spec.
|
|
108
|
-
*/
|
|
109
|
-
interface PageInfoData {
|
|
110
|
-
hasNextPage: boolean;
|
|
111
|
-
hasPreviousPage: boolean;
|
|
112
|
-
startCursor?: string | null;
|
|
113
|
-
endCursor?: string | null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export type { ConnectionVariables as C, DvinaAsyncRef as D, FetchOptions as F, MutationOptions as M, PageInfoData as P, WithIncludes as W, DvinaQueryRef as a, DvinaRequest as b, DvinaSubscribe as c, ConnectionWithNodes as d };
|