@gonvex/protocol 0.1.31 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +237 -102
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -30,7 +30,7 @@ The package includes:
30
30
  - function manifest types
31
31
  - WebSocket client and server message unions
32
32
  - live-query result, progress, patch, and revision frames
33
- - durable sync open/batch-open, snapshot, delta, reset, ready, and cursor types
33
+ - Replica Collection open/batch-open, snapshot, delta, reset, ready, and cursor types
34
34
  - browser telemetry and message trace types
35
35
 
36
36
  ## Related Packages
package/dist/index.d.ts CHANGED
@@ -1,15 +1,72 @@
1
- export type FunctionKind = "query" | "mutation" | "action" | "http" | "internalMutation" | "liveGrid" | "sync";
1
+ export type FunctionKind = "query" | "reducer" | "action";
2
+ export type ExecutionScope = "tenant" | "control";
2
3
  export type JsonValue = null | boolean | number | string | JsonValue[] | {
3
4
  [key: string]: JsonValue;
4
5
  };
6
+ /** The recursive, language-neutral value schema used by TypeScript modules. */
7
+ export type ModuleSchema = StringSchema | NumberSchema | BooleanSchema | NullSchema | AnySchema | IdSchema | LiteralSchema | ArraySchema | ObjectSchema | RecordSchema | OptionalSchema;
8
+ export type StringSchema = {
9
+ kind: "string";
10
+ format?: "email" | "uri" | "uuid" | "datetime";
11
+ minLength?: number;
12
+ maxLength?: number;
13
+ };
14
+ export type NumberSchema = {
15
+ kind: "number";
16
+ integer?: boolean;
17
+ minimum?: number;
18
+ maximum?: number;
19
+ };
20
+ export type BooleanSchema = {
21
+ kind: "boolean";
22
+ };
23
+ export type NullSchema = {
24
+ kind: "null";
25
+ };
26
+ export type AnySchema = {
27
+ kind: "any";
28
+ };
29
+ export type IdSchema = {
30
+ kind: "id";
31
+ entity: string;
32
+ };
33
+ export type LiteralSchema = {
34
+ kind: "literal";
35
+ value: JsonValue;
36
+ };
37
+ export type ArraySchema = {
38
+ kind: "array";
39
+ items: ModuleSchema;
40
+ };
41
+ export type ObjectSchema = {
42
+ kind: "object";
43
+ fields: Record<string, ModuleSchema>;
44
+ allowUnknown?: boolean;
45
+ };
46
+ export type RecordSchema = {
47
+ kind: "record";
48
+ values: ModuleSchema;
49
+ };
50
+ export type OptionalSchema = {
51
+ kind: "optional";
52
+ value: ModuleSchema;
53
+ };
5
54
  export type FunctionManifestEntry = {
6
55
  kind: FunctionKind;
7
56
  handler: string;
8
57
  file: string;
58
+ args?: ModuleSchema;
59
+ result?: ModuleSchema;
60
+ internal?: boolean;
61
+ delivery?: "oneShot" | "live" | "replica";
9
62
  dependencies?: FunctionDependencies;
10
- sync?: SyncDefinition;
63
+ replica?: ReplicaCollectionDefinition;
64
+ /** Reducer delivery policy declared by a TypeScript module. */
65
+ offline?: JsonValue;
66
+ /** Ordered atomic optimistic transaction declared by a TypeScript module. */
67
+ optimistic?: JsonValue;
11
68
  };
12
- export type SyncDefinition = {
69
+ export type ReplicaCollectionDefinition = {
13
70
  table: string;
14
71
  key: string;
15
72
  columns: string[];
@@ -23,30 +80,68 @@ export type SyncDefinition = {
23
80
  maxBytes?: number;
24
81
  retentionMs?: number;
25
82
  };
26
- export type SyncCursor = {
83
+ export type ReplicaCursor = {
27
84
  epoch: string;
28
85
  revision: number;
29
86
  };
87
+ export type ReplicaChange = {
88
+ entity: string;
89
+ id: string;
90
+ operation: "insert" | "update" | "delete";
91
+ oldValue?: JsonValue;
92
+ newValue?: JsonValue;
93
+ changedColumns?: string[];
94
+ };
30
95
  export type FunctionDependencies = {
31
- reads?: Array<{
32
- table: string;
33
- columns?: string[];
34
- filters?: string[];
35
- ordersBy?: string[];
36
- windowed?: boolean;
37
- predicate?: string;
38
- }>;
39
- writes?: Array<{
40
- table: string;
41
- columns?: string[];
42
- }>;
43
- readsEphemeral?: boolean;
44
- writesEphemeral?: boolean;
45
96
  shareByPermissions?: boolean;
46
- shareByVisibility?: string;
97
+ liveQueryPlan?: LiveQueryPlan;
98
+ nonOptimisticReason?: string;
47
99
  shareResultFrom?: string;
48
100
  shareResultField?: string;
49
101
  };
102
+ export type LiveQueryPlan = {
103
+ table: string;
104
+ key: string;
105
+ columns?: string[];
106
+ resultPath?: string[];
107
+ where?: LiveExpression;
108
+ search?: {
109
+ argument: string;
110
+ columns: string[];
111
+ };
112
+ filters?: {
113
+ argument: string;
114
+ allowedColumns: string[];
115
+ allowedOperators: FilterOperator[];
116
+ };
117
+ sort?: {
118
+ columnArgument: string;
119
+ directionArgument: string;
120
+ defaultColumn: string;
121
+ defaultDirection: "asc" | "desc";
122
+ allowedColumns: string[];
123
+ };
124
+ window?: {
125
+ offsetArgument: string;
126
+ limitArgument: string;
127
+ defaultLimit: number;
128
+ maxLimit: number;
129
+ count?: "exact";
130
+ };
131
+ serverOnly?: boolean;
132
+ };
133
+ export type FilterOperator = "contains" | "notContains" | "equals" | "notEquals" | "startsWith" | "endsWith" | "empty" | "notEmpty" | "oneOf" | "lessThan" | "lessThanOrEqual" | "greaterThan" | "greaterThanOrEqual" | "inRange";
134
+ export type LiveExpression = {
135
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "contains" | "containsInsensitive" | "range" | "and" | "or" | "not" | "server";
136
+ column?: string;
137
+ value?: LiveValue;
138
+ valueTo?: LiveValue;
139
+ children?: LiveExpression[];
140
+ };
141
+ export type LiveValue = {
142
+ argument?: string;
143
+ literal?: JsonValue;
144
+ };
50
145
  export type SubscriptionRevision = {
51
146
  epoch: string;
52
147
  sequence: number;
@@ -54,8 +149,8 @@ export type SubscriptionRevision = {
54
149
  export type MessageTrace = {
55
150
  clientSentAtMs?: number;
56
151
  serverReceivedAtMs?: number;
57
- serverMutationStartedAtMs?: number;
58
- serverMutationCommittedAtMs?: number;
152
+ serverReducerStartedAtMs?: number;
153
+ serverReducerCommittedAtMs?: number;
59
154
  serverCompletedAtMs?: number;
60
155
  serverBroadcastScheduledAtMs?: number;
61
156
  serverChangeCommittedAtMs?: number;
@@ -81,71 +176,69 @@ export type BrowserTelemetryInfo = {
81
176
  connectionType?: string;
82
177
  effectiveConnectionType?: string;
83
178
  };
84
- export type QueryCacheDirective = {
179
+ export type ReplicaDirective = {
85
180
  protocolVersion: 1;
86
181
  scope: string;
87
- /**
88
- * Visibility-only scope (project/tenant/user/permissions, no code epoch)
89
- * under which sync collections are persisted and resumed. Unlike `scope`,
90
- * it survives deploys; resume safety comes from the server's authoritative
91
- * reconcile. Absent on runtimes that predate deploy-stable sync scopes.
92
- */
93
- syncScope?: string;
182
+ /** Visibility-only scope for persistent, authoritatively reconciled rows. */
183
+ visibilityScope: string;
94
184
  epoch: string;
95
- maxAgeMs: number;
96
185
  };
97
186
  export type ServerCapabilities = {
98
187
  /** WebSocket protocol generation implemented by this runtime. */
99
188
  protocolVersion?: number;
100
189
  /** Exact runtime build identifier, normally the deployed Git commit SHA. */
101
190
  runtimeVersion?: string;
102
- syncBatch?: 1;
103
- /** sync.ready frames always carry a collection integrity digest. */
104
- syncIntegrity?: 1;
191
+ replicaBatch?: 1;
192
+ /** replica.ready frames always carry a collection integrity digest. */
193
+ replicaIntegrity?: 1;
105
194
  /** Server accepts `query.subscribeMany` batched subscription frames. */
106
195
  queryBatch?: 1;
107
196
  /** Server emits several independent query updates in one WebSocket frame. */
108
197
  queryResultBatch?: 1;
109
- /** Server accepts `mutation.callMany` batched offline-queue flushes. */
110
- mutationBatch?: 1;
111
- /** Server emits connection-level sync revision watermarks. */
112
- syncWatermark?: 1;
198
+ /** Server accepts `reducer.callMany` batched command-outbox flushes. */
199
+ reducerBatch?: 1;
200
+ /** Server emits connection-level replica revision watermarks. */
201
+ replicaWatermark?: 1;
113
202
  };
114
203
  export type QuerySubscribeRequest = {
115
204
  id: string;
116
205
  path: string;
117
206
  args: JsonValue;
118
- cacheRevision?: string;
207
+ scope?: ExecutionScope;
208
+ windowRevision?: string;
119
209
  };
120
- export type MutationCallRequest = {
210
+ export type ReducerCallRequest = {
121
211
  id: string;
122
212
  path: string;
123
213
  args: JsonValue;
214
+ scope?: ExecutionScope;
124
215
  trace?: MessageTrace;
216
+ /** Stable key for a replayable command; see the `reducer.call` message. */
217
+ idempotencyKey?: string;
125
218
  };
126
- export type SyncOpenRequest = {
219
+ export type ReplicaOpenRequest = {
127
220
  id: string;
128
221
  path: string;
129
222
  args: JsonValue;
130
- cursor?: SyncCursor;
223
+ cursor?: ReplicaCursor;
131
224
  keys?: string[];
132
225
  hashes?: Record<string, string>;
133
226
  digest?: string;
134
227
  fullIntegrity?: boolean;
135
228
  };
136
- export type SyncReady = {
229
+ export type ReplicaReady = {
137
230
  id: string;
138
231
  path?: string;
139
- cursor: SyncCursor;
232
+ cursor: ReplicaCursor;
140
233
  mode?: "eager" | "progressive";
141
- digest?: string;
234
+ digest: string;
142
235
  truncated?: boolean;
143
236
  };
144
237
  export type ClientCapabilities = {
145
- /** Client accepts coalesced `sync.readyMany` server frames. */
146
- syncReadyMany?: 1;
147
- /** Client accepts connection-level `sync.watermark` server frames. */
148
- syncWatermark?: 1;
238
+ /** Client accepts coalesced `replica.readyMany` server frames. */
239
+ replicaReadyMany?: 1;
240
+ /** Client accepts connection-level `replica.watermark` server frames. */
241
+ replicaWatermark?: 1;
149
242
  /** Client accepts keyed patches for object results with a `page` row array. */
150
243
  queryPagePatch?: 1;
151
244
  /** Client atomically applies keyed patches to named arrays in object results. */
@@ -177,57 +270,86 @@ export type ClientMessage = {
177
270
  token?: string;
178
271
  project?: string;
179
272
  tenant?: string;
273
+ controlOnly?: boolean;
180
274
  device?: BrowserTelemetryInfo;
181
275
  capabilities?: ClientCapabilities;
276
+ } | {
277
+ type: "query.call";
278
+ id: string;
279
+ path: string;
280
+ args: JsonValue;
281
+ scope?: ExecutionScope;
182
282
  } | {
183
283
  type: "query.subscribe";
184
284
  id: string;
185
285
  path: string;
186
286
  args: JsonValue;
187
- cacheRevision?: string;
287
+ scope?: ExecutionScope;
288
+ windowRevision?: string;
188
289
  } | {
189
290
  type: "query.unsubscribe";
190
291
  id: string;
191
292
  } | {
192
- type: "sync.open";
293
+ type: "replica.open";
193
294
  id: string;
194
295
  path: string;
195
296
  args: JsonValue;
196
- cursor?: SyncCursor;
297
+ cursor?: ReplicaCursor;
197
298
  keys?: string[];
198
299
  hashes?: Record<string, string>;
199
300
  digest?: string;
200
301
  fullIntegrity?: boolean;
201
302
  } | {
202
- type: "sync.openMany";
203
- opens: SyncOpenRequest[];
303
+ type: "replica.openMany";
304
+ opens: ReplicaOpenRequest[];
204
305
  } | {
205
306
  type: "query.subscribeMany";
206
307
  subscribes: QuerySubscribeRequest[];
207
308
  } | {
208
- type: "sync.close";
309
+ type: "replica.close";
209
310
  id: string;
210
311
  } | {
211
- type: "mutation.call";
312
+ type: "reducer.call";
212
313
  id: string;
213
314
  path: string;
214
315
  args: JsonValue;
316
+ scope?: ExecutionScope;
215
317
  trace?: MessageTrace;
318
+ /**
319
+ * Stable key for a replayable command from the client outbox. The runtime
320
+ * executes the reducer once per key and serves the stored result to
321
+ * every duplicate delivery.
322
+ */
323
+ idempotencyKey?: string;
216
324
  } | {
217
- type: "mutation.callMany";
218
- calls: MutationCallRequest[];
325
+ type: "reducer.callMany";
326
+ calls: ReducerCallRequest[];
219
327
  } | {
220
328
  type: "action.call";
221
329
  id: string;
222
330
  path: string;
223
331
  args: JsonValue;
332
+ scope?: ExecutionScope;
333
+ idempotencyKey?: string;
224
334
  trace?: MessageTrace;
335
+ } | {
336
+ type: "error.register";
337
+ id: string;
338
+ release?: string;
339
+ environment?: string;
340
+ } | {
341
+ type: "error.envelope";
342
+ id: string;
343
+ events: JsonValue[];
344
+ } | {
345
+ type: "error.heartbeat";
346
+ id: string;
225
347
  } | {
226
348
  type: "telemetry.event";
227
349
  id: string;
228
- kind: "query" | "mutation" | "action";
350
+ kind: "query" | "reducer" | "action";
229
351
  path: string;
230
- reason?: "initial" | "invalidate" | "recover";
352
+ reason?: "initial" | "change" | "recover";
231
353
  outcome: "ok" | "error";
232
354
  error?: string;
233
355
  clientSentAtMs?: number;
@@ -245,10 +367,10 @@ export type ServerMessage = {
245
367
  ids: string[];
246
368
  path?: string;
247
369
  result?: JsonValue;
248
- reason?: "initial" | "invalidate" | "recover";
370
+ reason?: "initial" | "change" | "recover";
249
371
  trace?: MessageTrace;
250
- cacheScope?: string;
251
- cacheRevision?: string;
372
+ replicaScope?: string;
373
+ windowRevision?: string;
252
374
  subscriptionRevision?: SubscriptionRevision;
253
375
  baseRevision?: SubscriptionRevision;
254
376
  throughRevision?: SubscriptionRevision;
@@ -259,16 +381,18 @@ export type ServerMessage = {
259
381
  prepend?: string[];
260
382
  append?: string[];
261
383
  collections?: Record<string, KeyedCollectionPatch>;
262
- mutationIds?: string[];
384
+ originCommandIds?: string[];
385
+ } | {
386
+ type: "replica.transaction";
387
+ cursor: ReplicaCursor;
388
+ originCommandId?: string;
389
+ changes: ReplicaChange[];
263
390
  } | {
264
391
  type: "session.ready";
265
392
  project?: string;
266
393
  tenant?: string;
267
- queryCache?: QueryCacheDirective;
394
+ replica?: ReplicaDirective;
268
395
  capabilities?: ServerCapabilities;
269
- } | {
270
- type: "session.scope";
271
- queryCache?: QueryCacheDirective;
272
396
  } | {
273
397
  type: "auth.result";
274
398
  id: string;
@@ -277,30 +401,40 @@ export type ServerMessage = {
277
401
  type: "auth.error";
278
402
  id: string;
279
403
  error: string;
404
+ } | {
405
+ type: "error.ack";
406
+ id: string;
407
+ accepted?: number;
408
+ fingerprints?: string[];
409
+ error?: string;
410
+ } | {
411
+ type: "support.command";
412
+ id: string;
413
+ result: JsonValue;
280
414
  } | {
281
415
  type: "query.result";
282
416
  id: string;
283
417
  path?: string;
284
418
  result: JsonValue;
285
- reason?: "initial" | "invalidate" | "recover";
419
+ reason?: "initial" | "change" | "recover";
286
420
  trace?: MessageTrace;
287
- cacheScope?: string;
288
- cacheRevision?: string;
421
+ replicaScope?: string;
422
+ windowRevision?: string;
289
423
  subscriptionRevision?: SubscriptionRevision;
290
- mutationIds?: string[];
424
+ originCommandIds?: string[];
291
425
  } | {
292
426
  type: "query.progress";
293
427
  id: string;
294
428
  path?: string;
295
- reason?: "initial" | "invalidate" | "recover";
429
+ reason?: "initial" | "change" | "recover";
296
430
  throughRevision: SubscriptionRevision;
297
431
  trace?: MessageTrace;
298
- mutationIds?: string[];
432
+ originCommandIds?: string[];
299
433
  } | {
300
434
  type: "query.patch";
301
435
  id: string;
302
436
  path?: string;
303
- reason?: "initial" | "invalidate" | "recover";
437
+ reason?: "initial" | "change" | "recover";
304
438
  baseRevision: SubscriptionRevision;
305
439
  subscriptionRevision: SubscriptionRevision;
306
440
  inserted?: JsonValue[];
@@ -309,15 +443,15 @@ export type ServerMessage = {
309
443
  order?: string[];
310
444
  prepend?: string[];
311
445
  append?: string[];
312
- cacheScope?: string;
313
- cacheRevision?: string;
446
+ replicaScope?: string;
447
+ windowRevision?: string;
314
448
  trace?: MessageTrace;
315
- mutationIds?: string[];
449
+ originCommandIds?: string[];
316
450
  } | {
317
451
  type: "query.pagePatch";
318
452
  id: string;
319
453
  path?: string;
320
- reason?: "initial" | "invalidate" | "recover";
454
+ reason?: "initial" | "change" | "recover";
321
455
  baseRevision: SubscriptionRevision;
322
456
  subscriptionRevision: SubscriptionRevision;
323
457
  result?: JsonValue;
@@ -327,28 +461,28 @@ export type ServerMessage = {
327
461
  order?: string[];
328
462
  prepend?: string[];
329
463
  append?: string[];
330
- cacheScope?: string;
331
- cacheRevision?: string;
464
+ replicaScope?: string;
465
+ windowRevision?: string;
332
466
  trace?: MessageTrace;
333
- mutationIds?: string[];
467
+ originCommandIds?: string[];
334
468
  } | {
335
469
  type: "query.objectPatch";
336
470
  id: string;
337
471
  path?: string;
338
- reason?: "initial" | "invalidate" | "recover";
472
+ reason?: "initial" | "change" | "recover";
339
473
  baseRevision: SubscriptionRevision;
340
474
  subscriptionRevision: SubscriptionRevision;
341
475
  collections: Record<string, KeyedCollectionPatch>;
342
- cacheScope?: string;
343
- cacheRevision?: string;
476
+ replicaScope?: string;
477
+ windowRevision?: string;
344
478
  trace?: MessageTrace;
345
- mutationIds?: string[];
479
+ originCommandIds?: string[];
346
480
  } | {
347
- type: "sync.snapshot";
481
+ type: "replica.snapshot";
348
482
  id: string;
349
483
  path?: string;
350
484
  result: JsonValue[];
351
- cursor: SyncCursor;
485
+ cursor: ReplicaCursor;
352
486
  key: string;
353
487
  orderBy?: string;
354
488
  orderDirection?: "asc" | "desc";
@@ -357,40 +491,39 @@ export type ServerMessage = {
357
491
  maxBytes?: number;
358
492
  hashes?: Record<string, string>;
359
493
  } | {
360
- type: "sync.delta";
494
+ type: "replica.delta";
361
495
  id: string;
362
496
  path?: string;
363
- cursor: SyncCursor;
497
+ cursor: ReplicaCursor;
364
498
  upserts?: JsonValue[];
365
499
  deleted?: string[];
366
- mutationIds?: string[];
500
+ originCommandIds?: string[];
367
501
  hashes?: Record<string, string>;
368
502
  digest?: string;
369
503
  } | ({
370
- type: "sync.ready";
371
- digest?: string;
372
- } & SyncReady) | {
373
- type: "sync.readyMany";
374
- ready: SyncReady[];
504
+ type: "replica.ready";
505
+ } & ReplicaReady) | {
506
+ type: "replica.readyMany";
507
+ ready: ReplicaReady[];
375
508
  } | {
376
- type: "sync.watermark";
509
+ type: "replica.watermark";
377
510
  revision: number;
378
511
  } | {
379
- type: "sync.needHashes";
512
+ type: "replica.needHashes";
380
513
  id: string;
381
514
  path?: string;
382
515
  } | {
383
- type: "sync.syncing";
516
+ type: "replica.syncing";
384
517
  id: string;
385
518
  path?: string;
386
519
  reason: "disconnected" | "reconciling" | "listener-reconnecting" | "integrity-reconciling";
387
520
  } | {
388
- type: "sync.reset";
521
+ type: "replica.reset";
389
522
  id: string;
390
523
  path?: string;
391
524
  reason: "cursor-expired" | "definition-changed" | "visibility-changed" | "integrity-mismatch" | "integrity-missing" | "recover";
392
525
  } | {
393
- type: "sync.error";
526
+ type: "replica.error";
394
527
  id: string;
395
528
  path?: string;
396
529
  error: string;
@@ -400,13 +533,15 @@ export type ServerMessage = {
400
533
  path?: string;
401
534
  error: string;
402
535
  } | {
403
- type: "mutation.result";
536
+ type: "reducer.result";
404
537
  id: string;
405
538
  path?: string;
406
539
  result: JsonValue;
540
+ originCommandId: string;
541
+ committedRevision?: number;
407
542
  trace?: MessageTrace;
408
543
  } | {
409
- type: "mutation.error";
544
+ type: "reducer.error";
410
545
  id: string;
411
546
  path?: string;
412
547
  error: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonvex/protocol",
3
- "version": "0.1.31",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"