@rocicorp/zero 1.12.0-canary.1 → 1.12.0-canary.3

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 (36) hide show
  1. package/out/zero/package.js +1 -1
  2. package/out/zero/package.js.map +1 -1
  3. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +18 -0
  4. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  5. package/out/zero-cache/src/services/view-syncer/client-handler.js +46 -20
  6. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  7. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  8. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  9. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -3
  10. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  11. package/out/zero-cache/src/services/view-syncer/snapshotter.js +5 -2
  12. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  13. package/out/zero-client/src/client/version.js +1 -1
  14. package/out/zero-protocol/src/inspect-down.d.ts +81 -81
  15. package/out/zero-protocol/src/poke.d.ts +6 -6
  16. package/out/zero-protocol/src/up.d.ts +60 -60
  17. package/out/zql/src/ivm/cap.js +2 -4
  18. package/out/zql/src/ivm/cap.js.map +1 -1
  19. package/out/zql/src/ivm/take.js +2 -4
  20. package/out/zql/src/ivm/take.js.map +1 -1
  21. package/out/zqlite/src/database-storage.d.ts.map +1 -1
  22. package/out/zqlite/src/database-storage.js +38 -6
  23. package/out/zqlite/src/database-storage.js.map +1 -1
  24. package/out/zqlite/src/fetch-sql.d.ts +27 -0
  25. package/out/zqlite/src/fetch-sql.d.ts.map +1 -0
  26. package/out/zqlite/src/fetch-sql.js +112 -0
  27. package/out/zqlite/src/fetch-sql.js.map +1 -0
  28. package/out/zqlite/src/query-builder.d.ts +11 -1
  29. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  30. package/out/zqlite/src/query-builder.js +22 -7
  31. package/out/zqlite/src/query-builder.js.map +1 -1
  32. package/out/zqlite/src/table-source.d.ts +9 -2
  33. package/out/zqlite/src/table-source.d.ts.map +1 -1
  34. package/out/zqlite/src/table-source.js +11 -14
  35. package/out/zqlite/src/table-source.js.map +1 -1
  36. package/package.json +1 -1
@@ -100,33 +100,6 @@ export declare const inspectAnalyzeQueryDownSchema: v.ObjectType<Omit<{
100
100
  type: "attempt-start";
101
101
  attemptNumber: number;
102
102
  totalAttempts: number;
103
- } | {
104
- type: "connection-selected";
105
- attemptNumber: number;
106
- connection: string;
107
- cost: number;
108
- isRoot: boolean;
109
- } | {
110
- type: "plan-failed";
111
- attemptNumber: number;
112
- reason: string;
113
- } | {
114
- type: "best-plan-selected";
115
- bestAttemptNumber: number;
116
- totalCost: number;
117
- flipPattern: number;
118
- joinStates: {
119
- join: string;
120
- type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
121
- }[];
122
- } | {
123
- type: "node-constraint";
124
- attemptNumber?: number | undefined;
125
- nodeType: "connection" | "fan-in" | "fan-out" | "filter" | "join" | "terminus" | v.Unrecognized<string>;
126
- node: string;
127
- branchPattern: number[];
128
- constraint?: Record<string, unknown> | null | undefined;
129
- from: string;
130
103
  } | {
131
104
  type: "connection-costs";
132
105
  attemptNumber: number;
@@ -152,6 +125,12 @@ export declare const inspectAnalyzeQueryDownSchema: v.ObjectType<Omit<{
152
125
  limit?: number | undefined;
153
126
  }>;
154
127
  }[];
128
+ } | {
129
+ type: "connection-selected";
130
+ attemptNumber: number;
131
+ connection: string;
132
+ cost: number;
133
+ isRoot: boolean;
155
134
  } | {
156
135
  type: "constraints-propagated";
157
136
  attemptNumber: number;
@@ -176,6 +155,19 @@ export declare const inspectAnalyzeQueryDownSchema: v.ObjectType<Omit<{
176
155
  join: string;
177
156
  type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
178
157
  }[];
158
+ } | {
159
+ type: "plan-failed";
160
+ attemptNumber: number;
161
+ reason: string;
162
+ } | {
163
+ type: "best-plan-selected";
164
+ bestAttemptNumber: number;
165
+ totalCost: number;
166
+ flipPattern: number;
167
+ joinStates: {
168
+ join: string;
169
+ type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
170
+ }[];
179
171
  } | {
180
172
  type: "node-cost";
181
173
  attemptNumber?: number | undefined;
@@ -194,6 +186,14 @@ export declare const inspectAnalyzeQueryDownSchema: v.ObjectType<Omit<{
194
186
  filters?: import("./ast.ts").Condition | undefined;
195
187
  ordering?: readonly (readonly [string, "asc" | "desc"])[] | undefined;
196
188
  joinType?: "flipped" | "semi" | "unflippable" | v.Unrecognized<string> | undefined;
189
+ } | {
190
+ type: "node-constraint";
191
+ attemptNumber?: number | undefined;
192
+ nodeType: "connection" | "fan-in" | "fan-out" | "filter" | "join" | "terminus" | v.Unrecognized<string>;
193
+ node: string;
194
+ branchPattern: number[];
195
+ constraint?: Record<string, unknown> | null | undefined;
196
+ from: string;
197
197
  })[]>;
198
198
  }, undefined>;
199
199
  }, undefined>;
@@ -266,33 +266,6 @@ export declare const inspectDownBodySchema: v.UnionType<[v.ObjectType<Omit<{
266
266
  type: "attempt-start";
267
267
  attemptNumber: number;
268
268
  totalAttempts: number;
269
- } | {
270
- type: "connection-selected";
271
- attemptNumber: number;
272
- connection: string;
273
- cost: number;
274
- isRoot: boolean;
275
- } | {
276
- type: "plan-failed";
277
- attemptNumber: number;
278
- reason: string;
279
- } | {
280
- type: "best-plan-selected";
281
- bestAttemptNumber: number;
282
- totalCost: number;
283
- flipPattern: number;
284
- joinStates: {
285
- join: string;
286
- type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
287
- }[];
288
- } | {
289
- type: "node-constraint";
290
- attemptNumber?: number | undefined;
291
- nodeType: "connection" | "fan-in" | "fan-out" | "filter" | "join" | "terminus" | v.Unrecognized<string>;
292
- node: string;
293
- branchPattern: number[];
294
- constraint?: Record<string, unknown> | null | undefined;
295
- from: string;
296
269
  } | {
297
270
  type: "connection-costs";
298
271
  attemptNumber: number;
@@ -318,6 +291,12 @@ export declare const inspectDownBodySchema: v.UnionType<[v.ObjectType<Omit<{
318
291
  limit?: number | undefined;
319
292
  }>;
320
293
  }[];
294
+ } | {
295
+ type: "connection-selected";
296
+ attemptNumber: number;
297
+ connection: string;
298
+ cost: number;
299
+ isRoot: boolean;
321
300
  } | {
322
301
  type: "constraints-propagated";
323
302
  attemptNumber: number;
@@ -342,6 +321,19 @@ export declare const inspectDownBodySchema: v.UnionType<[v.ObjectType<Omit<{
342
321
  join: string;
343
322
  type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
344
323
  }[];
324
+ } | {
325
+ type: "plan-failed";
326
+ attemptNumber: number;
327
+ reason: string;
328
+ } | {
329
+ type: "best-plan-selected";
330
+ bestAttemptNumber: number;
331
+ totalCost: number;
332
+ flipPattern: number;
333
+ joinStates: {
334
+ join: string;
335
+ type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
336
+ }[];
345
337
  } | {
346
338
  type: "node-cost";
347
339
  attemptNumber?: number | undefined;
@@ -360,6 +352,14 @@ export declare const inspectDownBodySchema: v.UnionType<[v.ObjectType<Omit<{
360
352
  filters?: import("./ast.ts").Condition | undefined;
361
353
  ordering?: readonly (readonly [string, "asc" | "desc"])[] | undefined;
362
354
  joinType?: "flipped" | "semi" | "unflippable" | v.Unrecognized<string> | undefined;
355
+ } | {
356
+ type: "node-constraint";
357
+ attemptNumber?: number | undefined;
358
+ nodeType: "connection" | "fan-in" | "fan-out" | "filter" | "join" | "terminus" | v.Unrecognized<string>;
359
+ node: string;
360
+ branchPattern: number[];
361
+ constraint?: Record<string, unknown> | null | undefined;
362
+ from: string;
363
363
  })[]>;
364
364
  }, undefined>;
365
365
  }, undefined>, v.ObjectType<Omit<{
@@ -429,33 +429,6 @@ export declare const inspectDownMessageSchema: v.TupleType<[v.Type<"inspect">, v
429
429
  type: "attempt-start";
430
430
  attemptNumber: number;
431
431
  totalAttempts: number;
432
- } | {
433
- type: "connection-selected";
434
- attemptNumber: number;
435
- connection: string;
436
- cost: number;
437
- isRoot: boolean;
438
- } | {
439
- type: "plan-failed";
440
- attemptNumber: number;
441
- reason: string;
442
- } | {
443
- type: "best-plan-selected";
444
- bestAttemptNumber: number;
445
- totalCost: number;
446
- flipPattern: number;
447
- joinStates: {
448
- join: string;
449
- type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
450
- }[];
451
- } | {
452
- type: "node-constraint";
453
- attemptNumber?: number | undefined;
454
- nodeType: "connection" | "fan-in" | "fan-out" | "filter" | "join" | "terminus" | v.Unrecognized<string>;
455
- node: string;
456
- branchPattern: number[];
457
- constraint?: Record<string, unknown> | null | undefined;
458
- from: string;
459
432
  } | {
460
433
  type: "connection-costs";
461
434
  attemptNumber: number;
@@ -481,6 +454,12 @@ export declare const inspectDownMessageSchema: v.TupleType<[v.Type<"inspect">, v
481
454
  limit?: number | undefined;
482
455
  }>;
483
456
  }[];
457
+ } | {
458
+ type: "connection-selected";
459
+ attemptNumber: number;
460
+ connection: string;
461
+ cost: number;
462
+ isRoot: boolean;
484
463
  } | {
485
464
  type: "constraints-propagated";
486
465
  attemptNumber: number;
@@ -505,6 +484,19 @@ export declare const inspectDownMessageSchema: v.TupleType<[v.Type<"inspect">, v
505
484
  join: string;
506
485
  type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
507
486
  }[];
487
+ } | {
488
+ type: "plan-failed";
489
+ attemptNumber: number;
490
+ reason: string;
491
+ } | {
492
+ type: "best-plan-selected";
493
+ bestAttemptNumber: number;
494
+ totalCost: number;
495
+ flipPattern: number;
496
+ joinStates: {
497
+ join: string;
498
+ type: "flipped" | "semi" | "unflippable" | v.Unrecognized<string>;
499
+ }[];
508
500
  } | {
509
501
  type: "node-cost";
510
502
  attemptNumber?: number | undefined;
@@ -523,6 +515,14 @@ export declare const inspectDownMessageSchema: v.TupleType<[v.Type<"inspect">, v
523
515
  filters?: import("./ast.ts").Condition | undefined;
524
516
  ordering?: readonly (readonly [string, "asc" | "desc"])[] | undefined;
525
517
  joinType?: "flipped" | "semi" | "unflippable" | v.Unrecognized<string> | undefined;
518
+ } | {
519
+ type: "node-constraint";
520
+ attemptNumber?: number | undefined;
521
+ nodeType: "connection" | "fan-in" | "fan-out" | "filter" | "join" | "terminus" | v.Unrecognized<string>;
522
+ node: string;
523
+ branchPattern: number[];
524
+ constraint?: Record<string, unknown> | null | undefined;
525
+ from: string;
526
526
  })[]>;
527
527
  }, undefined>;
528
528
  }, undefined>, v.ObjectType<Omit<{
@@ -85,14 +85,14 @@ export declare const pokePartBodySchema: v.ObjectType<{
85
85
  clientID: string;
86
86
  };
87
87
  result: {
88
- data?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
89
- } | {
90
88
  error: "app";
91
89
  message?: string | undefined;
92
90
  details?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
93
91
  } | {
94
92
  error: "alreadyProcessed" | "oooMutation";
95
93
  details?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
94
+ } | {
95
+ data?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
96
96
  };
97
97
  };
98
98
  } | {
@@ -156,14 +156,14 @@ export declare const pokePartsSchema: v.ArrayType<v.ObjectType<{
156
156
  clientID: string;
157
157
  };
158
158
  result: {
159
- data?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
160
- } | {
161
159
  error: "app";
162
160
  message?: string | undefined;
163
161
  details?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
164
162
  } | {
165
163
  error: "alreadyProcessed" | "oooMutation";
166
164
  details?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
165
+ } | {
166
+ data?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
167
167
  };
168
168
  };
169
169
  } | {
@@ -240,14 +240,14 @@ export declare const pokePartMessageSchema: v.TupleType<[v.Type<"pokePart">, v.O
240
240
  clientID: string;
241
241
  };
242
242
  result: {
243
- data?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
244
- } | {
245
243
  error: "app";
246
244
  message?: string | undefined;
247
245
  details?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
248
246
  } | {
249
247
  error: "alreadyProcessed" | "oooMutation";
250
248
  details?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
249
+ } | {
250
+ data?: import("../../shared/src/json.ts").ReadonlyJSONValue | undefined;
251
251
  };
252
252
  };
253
253
  } | {
@@ -4,17 +4,17 @@ export declare const upstreamSchema: v.Type<v.UnrecognizedTuple | ["ackMutationR
4
4
  clientID: string;
5
5
  }] | ["changeDesiredQueries", {
6
6
  desiredQueriesPatch: ({
7
+ op: "del";
8
+ hash: string;
9
+ } | {
10
+ op: "clear";
11
+ } | {
7
12
  op: "put";
8
13
  hash: string;
9
14
  ttl?: number | undefined;
10
15
  ast?: import("./ast.ts").AST | undefined;
11
16
  name?: string | undefined;
12
17
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
13
- } | {
14
- op: "del";
15
- hash: string;
16
- } | {
17
- op: "clear";
18
18
  })[];
19
19
  traceparent?: string | undefined;
20
20
  }] | ["closeConnection", unknown[]] | ["deleteClients", {
@@ -22,17 +22,17 @@ export declare const upstreamSchema: v.Type<v.UnrecognizedTuple | ["ackMutationR
22
22
  readonly clientGroupIDs?: readonly string[] | undefined;
23
23
  }] | ["initConnection", {
24
24
  desiredQueriesPatch: ({
25
+ op: "del";
26
+ hash: string;
27
+ } | {
28
+ op: "clear";
29
+ } | {
25
30
  op: "put";
26
31
  hash: string;
27
32
  ttl?: number | undefined;
28
33
  ast?: import("./ast.ts").AST | undefined;
29
34
  name?: string | undefined;
30
35
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
31
- } | {
32
- op: "del";
33
- hash: string;
34
- } | {
35
- op: "clear";
36
36
  })[];
37
37
  clientSchema?: {
38
38
  tables: Record<string, {
@@ -135,17 +135,17 @@ export declare const upstreamSchema: v.Type<v.UnrecognizedTuple | ["ackMutationR
135
135
  clientID: string;
136
136
  }] | ["changeDesiredQueries", {
137
137
  desiredQueriesPatch: ({
138
+ op: "del";
139
+ hash: string;
140
+ } | {
141
+ op: "clear";
142
+ } | {
138
143
  op: "put";
139
144
  hash: string;
140
145
  ttl?: number | undefined;
141
146
  ast?: import("./ast.ts").AST | undefined;
142
147
  name?: string | undefined;
143
148
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
144
- } | {
145
- op: "del";
146
- hash: string;
147
- } | {
148
- op: "clear";
149
149
  })[];
150
150
  traceparent?: string | undefined;
151
151
  }] | ["closeConnection", unknown[]] | ["deleteClients", {
@@ -153,17 +153,17 @@ export declare const upstreamSchema: v.Type<v.UnrecognizedTuple | ["ackMutationR
153
153
  readonly clientGroupIDs?: readonly string[] | undefined;
154
154
  }] | ["initConnection", {
155
155
  desiredQueriesPatch: ({
156
+ op: "del";
157
+ hash: string;
158
+ } | {
159
+ op: "clear";
160
+ } | {
156
161
  op: "put";
157
162
  hash: string;
158
163
  ttl?: number | undefined;
159
164
  ast?: import("./ast.ts").AST | undefined;
160
165
  name?: string | undefined;
161
166
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
162
- } | {
163
- op: "del";
164
- hash: string;
165
- } | {
166
- op: "clear";
167
167
  })[];
168
168
  clientSchema?: {
169
169
  tables: Record<string, {
@@ -265,17 +265,17 @@ export declare const upstreamSchema: v.Type<v.UnrecognizedTuple | ["ackMutationR
265
265
  clientID: string;
266
266
  }] | ["changeDesiredQueries", {
267
267
  desiredQueriesPatch: ({
268
+ op: "del";
269
+ hash: string;
270
+ } | {
271
+ op: "clear";
272
+ } | {
268
273
  op: "put";
269
274
  hash: string;
270
275
  ttl?: number | undefined;
271
276
  ast?: import("./ast.ts").AST | undefined;
272
277
  name?: string | undefined;
273
278
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
274
- } | {
275
- op: "del";
276
- hash: string;
277
- } | {
278
- op: "clear";
279
279
  })[];
280
280
  traceparent?: string | undefined;
281
281
  }] | ["closeConnection", unknown[]] | ["deleteClients", {
@@ -283,17 +283,17 @@ export declare const upstreamSchema: v.Type<v.UnrecognizedTuple | ["ackMutationR
283
283
  readonly clientGroupIDs?: readonly string[] | undefined;
284
284
  }] | ["initConnection", {
285
285
  desiredQueriesPatch: ({
286
+ op: "del";
287
+ hash: string;
288
+ } | {
289
+ op: "clear";
290
+ } | {
286
291
  op: "put";
287
292
  hash: string;
288
293
  ttl?: number | undefined;
289
294
  ast?: import("./ast.ts").AST | undefined;
290
295
  name?: string | undefined;
291
296
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
292
- } | {
293
- op: "del";
294
- hash: string;
295
- } | {
296
- op: "clear";
297
297
  })[];
298
298
  clientSchema?: {
299
299
  tables: Record<string, {
@@ -397,17 +397,17 @@ export declare const upstreamSchemaWithUnparsedAnalyzeQuery: v.Type<v.Unrecogniz
397
397
  clientID: string;
398
398
  }] | ["changeDesiredQueries", {
399
399
  desiredQueriesPatch: ({
400
+ op: "del";
401
+ hash: string;
402
+ } | {
403
+ op: "clear";
404
+ } | {
400
405
  op: "put";
401
406
  hash: string;
402
407
  ttl?: number | undefined;
403
408
  ast?: import("./ast.ts").AST | undefined;
404
409
  name?: string | undefined;
405
410
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
406
- } | {
407
- op: "del";
408
- hash: string;
409
- } | {
410
- op: "clear";
411
411
  })[];
412
412
  traceparent?: string | undefined;
413
413
  }] | ["closeConnection", unknown[]] | ["deleteClients", {
@@ -415,17 +415,17 @@ export declare const upstreamSchemaWithUnparsedAnalyzeQuery: v.Type<v.Unrecogniz
415
415
  readonly clientGroupIDs?: readonly string[] | undefined;
416
416
  }] | ["initConnection", {
417
417
  desiredQueriesPatch: ({
418
+ op: "del";
419
+ hash: string;
420
+ } | {
421
+ op: "clear";
422
+ } | {
418
423
  op: "put";
419
424
  hash: string;
420
425
  ttl?: number | undefined;
421
426
  ast?: import("./ast.ts").AST | undefined;
422
427
  name?: string | undefined;
423
428
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
424
- } | {
425
- op: "del";
426
- hash: string;
427
- } | {
428
- op: "clear";
429
429
  })[];
430
430
  clientSchema?: {
431
431
  tables: Record<string, {
@@ -528,17 +528,17 @@ export declare const upstreamSchemaWithUnparsedAnalyzeQuery: v.Type<v.Unrecogniz
528
528
  clientID: string;
529
529
  }] | ["changeDesiredQueries", {
530
530
  desiredQueriesPatch: ({
531
+ op: "del";
532
+ hash: string;
533
+ } | {
534
+ op: "clear";
535
+ } | {
531
536
  op: "put";
532
537
  hash: string;
533
538
  ttl?: number | undefined;
534
539
  ast?: import("./ast.ts").AST | undefined;
535
540
  name?: string | undefined;
536
541
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
537
- } | {
538
- op: "del";
539
- hash: string;
540
- } | {
541
- op: "clear";
542
542
  })[];
543
543
  traceparent?: string | undefined;
544
544
  }] | ["closeConnection", unknown[]] | ["deleteClients", {
@@ -546,17 +546,17 @@ export declare const upstreamSchemaWithUnparsedAnalyzeQuery: v.Type<v.Unrecogniz
546
546
  readonly clientGroupIDs?: readonly string[] | undefined;
547
547
  }] | ["initConnection", {
548
548
  desiredQueriesPatch: ({
549
+ op: "del";
550
+ hash: string;
551
+ } | {
552
+ op: "clear";
553
+ } | {
549
554
  op: "put";
550
555
  hash: string;
551
556
  ttl?: number | undefined;
552
557
  ast?: import("./ast.ts").AST | undefined;
553
558
  name?: string | undefined;
554
559
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
555
- } | {
556
- op: "del";
557
- hash: string;
558
- } | {
559
- op: "clear";
560
560
  })[];
561
561
  clientSchema?: {
562
562
  tables: Record<string, {
@@ -658,17 +658,17 @@ export declare const upstreamSchemaWithUnparsedAnalyzeQuery: v.Type<v.Unrecogniz
658
658
  clientID: string;
659
659
  }] | ["changeDesiredQueries", {
660
660
  desiredQueriesPatch: ({
661
+ op: "del";
662
+ hash: string;
663
+ } | {
664
+ op: "clear";
665
+ } | {
661
666
  op: "put";
662
667
  hash: string;
663
668
  ttl?: number | undefined;
664
669
  ast?: import("./ast.ts").AST | undefined;
665
670
  name?: string | undefined;
666
671
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
667
- } | {
668
- op: "del";
669
- hash: string;
670
- } | {
671
- op: "clear";
672
672
  })[];
673
673
  traceparent?: string | undefined;
674
674
  }] | ["closeConnection", unknown[]] | ["deleteClients", {
@@ -676,17 +676,17 @@ export declare const upstreamSchemaWithUnparsedAnalyzeQuery: v.Type<v.Unrecogniz
676
676
  readonly clientGroupIDs?: readonly string[] | undefined;
677
677
  }] | ["initConnection", {
678
678
  desiredQueriesPatch: ({
679
+ op: "del";
680
+ hash: string;
681
+ } | {
682
+ op: "clear";
683
+ } | {
679
684
  op: "put";
680
685
  hash: string;
681
686
  ttl?: number | undefined;
682
687
  ast?: import("./ast.ts").AST | undefined;
683
688
  name?: string | undefined;
684
689
  args?: readonly import("../../shared/src/json.ts").ReadonlyJSONValue[] | undefined;
685
- } | {
686
- op: "del";
687
- hash: string;
688
- } | {
689
- op: "clear";
690
690
  })[];
691
691
  clientSchema?: {
692
692
  tables: Record<string, {
@@ -51,7 +51,7 @@ var Cap = class {
51
51
  const capStateKey = getCapStateKey(this.#partitionKey, req.constraint);
52
52
  const capState = this.#storage.get(capStateKey);
53
53
  if (!capState) {
54
- yield* this.#initialFetch(req);
54
+ yield* this.#initialFetch(req, capStateKey);
55
55
  return;
56
56
  }
57
57
  if (capState.size === 0) return;
@@ -70,11 +70,9 @@ var Cap = class {
70
70
  }
71
71
  }
72
72
  }
73
- *#initialFetch(req) {
73
+ *#initialFetch(req, capStateKey) {
74
74
  if (this.#limit === 0) return;
75
75
  assert(constraintMatchesPartitionKey(req.constraint, this.#partitionKey), "Constraint should match partition key");
76
- const capStateKey = getCapStateKey(this.#partitionKey, req.constraint);
77
- assert(this.#storage.get(capStateKey) === void 0, "Cap state should be undefined");
78
76
  let size = 0;
79
77
  const pks = [];
80
78
  let downstreamEarlyReturn = true;
@@ -1 +1 @@
1
- {"version":3,"file":"cap.js","names":["#input","#storage","#limit","#partitionKey","#partitionKeyComparator","#primaryKey","#output","#initialFetch","#pushEditChange"],"sources":["../../../../../zql/src/ivm/cap.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {makeAddChange, type Change, type EditChange} from './change.ts';\nimport type {Constraint} from './constraint.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type InputBase,\n type Operator,\n type Output,\n type Storage,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\nimport {\n constraintMatchesPartitionKey,\n makePartitionKeyComparator,\n type PartitionKey,\n} from './take.ts';\n\ntype CapState = {\n size: number;\n pks: string[];\n};\n\ninterface CapStorage {\n get(key: string): CapState | undefined;\n set(key: string, value: CapState): void;\n del(key: string): void;\n destroy(): void;\n}\n\n/**\n * The Cap operator is a count-based limiter for EXISTS subqueries that\n * does not require ordering. Unlike Take, it tracks membership by primary\n * key set rather than by a sorted bound. This means:\n *\n * - No comparator needed (no ordering requirement)\n * - No `start` or `reverse` fetch support\n * - No `#rowHiddenFromFetch` complexity (we can defer when adding to the pk set)\n *\n * Cap is used in EXISTS child pipelines where only the count of matching\n * rows matters, not their order. This allows SQLite to skip ORDER BY\n * entirely, enabling much faster query plans.\n *\n * Cap can count rows globally or by unique value of some partition key\n * (same as Take).\n */\nexport class Cap implements Operator {\n readonly #input: Input;\n readonly #storage: CapStorage;\n readonly #limit: number;\n readonly #partitionKey: PartitionKey | undefined;\n readonly #partitionKeyComparator: Comparator | undefined;\n readonly #primaryKey: PrimaryKey;\n\n #output: Output = throwOutput;\n\n constructor(\n input: Input,\n storage: Storage,\n limit: number,\n partitionKey?: PartitionKey,\n ) {\n assert(limit >= 0, 'Limit must be non-negative');\n input.setOutput(this);\n this.#input = input;\n this.#storage = storage as CapStorage;\n this.#limit = limit;\n this.#partitionKey = partitionKey;\n this.#partitionKeyComparator =\n partitionKey && makePartitionKeyComparator(partitionKey);\n this.#primaryKey = input.getSchema().primaryKey;\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n assert(!req.start, 'Cap does not support start');\n assert(!req.reverse, 'Cap does not support reverse');\n\n // Cap is only built for non-flipped EXISTS subqueries, whose only\n // downstream consumer is a Join that always fetches with a constraint\n // built from the correlation's childField — which is Cap's partition\n // key. So either partitionKey is undefined, or constraint matches.\n assert(\n !this.#partitionKey ||\n (req.constraint !== undefined &&\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey)),\n 'Cap fetch: constraint must match partition key when partitioned',\n );\n\n const capStateKey = getCapStateKey(this.#partitionKey, req.constraint);\n const capState = this.#storage.get(capStateKey);\n if (!capState) {\n yield* this.#initialFetch(req);\n return;\n }\n if (capState.size === 0) {\n return;\n }\n // PK-based point lookups: fetch each tracked row by its PK directly,\n // rather than scanning the partition and filtering.\n for (const pk of capState.pks) {\n const pkConstraint = deserializePKToConstraint(pk, this.#primaryKey);\n // Preserve req.constraint (the partition key) so upstream partitioned\n // operators (e.g. Take) retain their partition scope and do not throw.\n const constraint = req.constraint\n ? {...req.constraint, ...pkConstraint}\n : pkConstraint;\n for (const inputNode of this.#input.fetch({constraint})) {\n if (inputNode === 'yield') {\n yield inputNode;\n continue;\n }\n yield inputNode;\n }\n }\n }\n\n *#initialFetch(req: FetchRequest): Stream<Node | 'yield'> {\n if (this.#limit === 0) {\n return;\n }\n\n assert(\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey),\n 'Constraint should match partition key',\n );\n\n const capStateKey = getCapStateKey(this.#partitionKey, req.constraint);\n assert(\n this.#storage.get(capStateKey) === undefined,\n 'Cap state should be undefined',\n );\n\n let size = 0;\n const pks: string[] = [];\n let downstreamEarlyReturn = true;\n let exceptionThrown = false;\n try {\n for (const inputNode of this.#input.fetch(req)) {\n if (inputNode === 'yield') {\n yield 'yield';\n continue;\n }\n yield inputNode;\n pks.push(serializePK(inputNode.row, this.#primaryKey));\n size++;\n if (size === this.#limit) {\n break;\n }\n }\n downstreamEarlyReturn = false;\n } catch (e) {\n exceptionThrown = true;\n throw e;\n } finally {\n if (!exceptionThrown) {\n this.#storage.set(capStateKey, {size, pks});\n // If it becomes necessary to support downstream early return, this\n // assert should be removed, and replaced with code that consumes\n // the input stream until limit is reached or the input stream is\n // exhausted so that capState is properly hydrated.\n assert(\n !downstreamEarlyReturn,\n 'Unexpected early return prevented full hydration',\n );\n }\n }\n }\n\n *push(change: Change): Stream<'yield'> {\n if (change[ChangeIndex.TYPE] === ChangeType.EDIT) {\n yield* this.#pushEditChange(change);\n return;\n }\n\n const capStateKey = getCapStateKey(\n this.#partitionKey,\n change[ChangeIndex.NODE].row,\n );\n const capState = this.#storage.get(capStateKey);\n if (!capState) {\n return;\n }\n\n const pk = serializePK(change[ChangeIndex.NODE].row, this.#primaryKey);\n\n if (change[ChangeIndex.TYPE] === ChangeType.ADD) {\n if (capState.size < this.#limit) {\n const pks = [...capState.pks, pk];\n this.#storage.set(capStateKey, {size: capState.size + 1, pks});\n yield* this.#output.push(change, this);\n return;\n }\n // Full — drop\n return;\n } else if (change[ChangeIndex.TYPE] === ChangeType.REMOVE) {\n const pkIndex = capState.pks.indexOf(pk);\n if (pkIndex === -1) {\n // Not in our set — drop\n return;\n }\n // Remove from set\n const pks = [...capState.pks];\n pks.splice(pkIndex, 1);\n const newSize = capState.size - 1;\n\n // Try to refill: fetch from input with partition constraint,\n // find first row NOT in PK set\n const pkSet = new Set(pks);\n const constraint = this.#partitionKey\n ? (Object.fromEntries(\n this.#partitionKey.map(\n key => [key, change[ChangeIndex.NODE].row[key]] as const,\n ),\n ) as Constraint)\n : undefined;\n\n let replacement: Node | undefined;\n for (const node of this.#input.fetch({constraint})) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n const nodePK = serializePK(node.row, this.#primaryKey);\n if (!pkSet.has(nodePK)) {\n replacement = node;\n break;\n }\n }\n\n if (replacement) {\n // Store state WITHOUT replacement during remove forward,\n // matching Take's pattern of hiding in-flight changes from re-fetches.\n this.#storage.set(capStateKey, {size: newSize, pks});\n yield* this.#output.push(change, this);\n // Now add replacement to set and forward the add.\n const replacementPK = serializePK(replacement.row, this.#primaryKey);\n pks.push(replacementPK);\n this.#storage.set(capStateKey, {size: newSize + 1, pks});\n yield* this.#output.push(makeAddChange(replacement), this);\n } else {\n this.#storage.set(capStateKey, {size: newSize, pks});\n yield* this.#output.push(change, this);\n }\n } else if (change[ChangeIndex.TYPE] === ChangeType.CHILD) {\n const pkSet = new Set(capState.pks);\n if (pkSet.has(pk)) {\n yield* this.#output.push(change, this);\n }\n }\n }\n\n #pushEditChange(change: EditChange): Stream<'yield'> {\n assert(\n !this.#partitionKeyComparator ||\n this.#partitionKeyComparator(\n change[ChangeIndex.OLD_NODE].row,\n change[ChangeIndex.NODE].row,\n ) === 0,\n 'Unexpected change of partition key',\n );\n const capStateKey = getCapStateKey(\n this.#partitionKey,\n change[ChangeIndex.OLD_NODE].row,\n );\n const capState = this.#storage.get(capStateKey);\n if (!capState) {\n return emptyArray;\n }\n\n const oldPK = serializePK(\n change[ChangeIndex.OLD_NODE].row,\n this.#primaryKey,\n );\n const pkSet = new Set(capState.pks);\n if (pkSet.has(oldPK)) {\n // Update the PK in our set if it changed\n const newPK = serializePK(change[ChangeIndex.NODE].row, this.#primaryKey);\n if (oldPK !== newPK) {\n const pks = capState.pks.map(p => (p === oldPK ? newPK : p));\n this.#storage.set(capStateKey, {size: capState.size, pks});\n }\n return this.#output.push(change, this);\n }\n // If not in our set, drop\n return emptyArray;\n }\n\n destroy(): void {\n this.#input.destroy();\n this.#storage.destroy();\n }\n\n *reconcile(_pusher: InputBase): Stream<'yield'> {\n if (this.#output.reconcile) {\n yield* this.#output.reconcile(this);\n }\n }\n}\n\nfunction getCapStateKey(\n partitionKey: PartitionKey | undefined,\n rowOrConstraint: Row | Constraint | undefined,\n): string {\n const partitionValues: Value[] = [];\n\n if (partitionKey && rowOrConstraint) {\n for (const key of partitionKey) {\n partitionValues.push(rowOrConstraint[key]);\n }\n }\n\n return JSON.stringify(['cap', ...partitionValues]);\n}\n\nfunction serializePK(row: Row, primaryKey: PrimaryKey): string {\n return JSON.stringify(primaryKey.map(k => row[k]));\n}\n\nfunction deserializePKToConstraint(\n pk: string,\n primaryKey: PrimaryKey,\n): Constraint {\n const values = JSON.parse(pk) as Value[];\n const constraint: Record<string, Value> = {};\n for (let i = 0; i < primaryKey.length; i++) {\n constraint[primaryKey[i]] = values[i];\n }\n return constraint;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cap.js","names":["#input","#storage","#limit","#partitionKey","#partitionKeyComparator","#primaryKey","#output","#initialFetch","#pushEditChange"],"sources":["../../../../../zql/src/ivm/cap.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {makeAddChange, type Change, type EditChange} from './change.ts';\nimport type {Constraint} from './constraint.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type InputBase,\n type Operator,\n type Output,\n type Storage,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\nimport {\n constraintMatchesPartitionKey,\n makePartitionKeyComparator,\n type PartitionKey,\n} from './take.ts';\n\ntype CapState = {\n size: number;\n pks: string[];\n};\n\ninterface CapStorage {\n get(key: string): CapState | undefined;\n set(key: string, value: CapState): void;\n del(key: string): void;\n destroy(): void;\n}\n\n/**\n * The Cap operator is a count-based limiter for EXISTS subqueries that\n * does not require ordering. Unlike Take, it tracks membership by primary\n * key set rather than by a sorted bound. This means:\n *\n * - No comparator needed (no ordering requirement)\n * - No `start` or `reverse` fetch support\n * - No `#rowHiddenFromFetch` complexity (we can defer when adding to the pk set)\n *\n * Cap is used in EXISTS child pipelines where only the count of matching\n * rows matters, not their order. This allows SQLite to skip ORDER BY\n * entirely, enabling much faster query plans.\n *\n * Cap can count rows globally or by unique value of some partition key\n * (same as Take).\n */\nexport class Cap implements Operator {\n readonly #input: Input;\n readonly #storage: CapStorage;\n readonly #limit: number;\n readonly #partitionKey: PartitionKey | undefined;\n readonly #partitionKeyComparator: Comparator | undefined;\n readonly #primaryKey: PrimaryKey;\n\n #output: Output = throwOutput;\n\n constructor(\n input: Input,\n storage: Storage,\n limit: number,\n partitionKey?: PartitionKey,\n ) {\n assert(limit >= 0, 'Limit must be non-negative');\n input.setOutput(this);\n this.#input = input;\n this.#storage = storage as CapStorage;\n this.#limit = limit;\n this.#partitionKey = partitionKey;\n this.#partitionKeyComparator =\n partitionKey && makePartitionKeyComparator(partitionKey);\n this.#primaryKey = input.getSchema().primaryKey;\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n assert(!req.start, 'Cap does not support start');\n assert(!req.reverse, 'Cap does not support reverse');\n\n // Cap is only built for non-flipped EXISTS subqueries, whose only\n // downstream consumer is a Join that always fetches with a constraint\n // built from the correlation's childField — which is Cap's partition\n // key. So either partitionKey is undefined, or constraint matches.\n assert(\n !this.#partitionKey ||\n (req.constraint !== undefined &&\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey)),\n 'Cap fetch: constraint must match partition key when partitioned',\n );\n\n const capStateKey = getCapStateKey(this.#partitionKey, req.constraint);\n const capState = this.#storage.get(capStateKey);\n if (!capState) {\n yield* this.#initialFetch(req, capStateKey);\n return;\n }\n if (capState.size === 0) {\n return;\n }\n // PK-based point lookups: fetch each tracked row by its PK directly,\n // rather than scanning the partition and filtering.\n for (const pk of capState.pks) {\n const pkConstraint = deserializePKToConstraint(pk, this.#primaryKey);\n // Preserve req.constraint (the partition key) so upstream partitioned\n // operators (e.g. Take) retain their partition scope and do not throw.\n const constraint = req.constraint\n ? {...req.constraint, ...pkConstraint}\n : pkConstraint;\n for (const inputNode of this.#input.fetch({constraint})) {\n if (inputNode === 'yield') {\n yield inputNode;\n continue;\n }\n yield inputNode;\n }\n }\n }\n\n *#initialFetch(\n req: FetchRequest,\n capStateKey: string,\n ): Stream<Node | 'yield'> {\n if (this.#limit === 0) {\n return;\n }\n\n assert(\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey),\n 'Constraint should match partition key',\n );\n\n // The caller (fetch) has already checked that there is no state for\n // capStateKey.\n\n let size = 0;\n const pks: string[] = [];\n let downstreamEarlyReturn = true;\n let exceptionThrown = false;\n try {\n for (const inputNode of this.#input.fetch(req)) {\n if (inputNode === 'yield') {\n yield 'yield';\n continue;\n }\n yield inputNode;\n pks.push(serializePK(inputNode.row, this.#primaryKey));\n size++;\n if (size === this.#limit) {\n break;\n }\n }\n downstreamEarlyReturn = false;\n } catch (e) {\n exceptionThrown = true;\n throw e;\n } finally {\n if (!exceptionThrown) {\n this.#storage.set(capStateKey, {size, pks});\n // If it becomes necessary to support downstream early return, this\n // assert should be removed, and replaced with code that consumes\n // the input stream until limit is reached or the input stream is\n // exhausted so that capState is properly hydrated.\n assert(\n !downstreamEarlyReturn,\n 'Unexpected early return prevented full hydration',\n );\n }\n }\n }\n\n *push(change: Change): Stream<'yield'> {\n if (change[ChangeIndex.TYPE] === ChangeType.EDIT) {\n yield* this.#pushEditChange(change);\n return;\n }\n\n const capStateKey = getCapStateKey(\n this.#partitionKey,\n change[ChangeIndex.NODE].row,\n );\n const capState = this.#storage.get(capStateKey);\n if (!capState) {\n return;\n }\n\n const pk = serializePK(change[ChangeIndex.NODE].row, this.#primaryKey);\n\n if (change[ChangeIndex.TYPE] === ChangeType.ADD) {\n if (capState.size < this.#limit) {\n const pks = [...capState.pks, pk];\n this.#storage.set(capStateKey, {size: capState.size + 1, pks});\n yield* this.#output.push(change, this);\n return;\n }\n // Full — drop\n return;\n } else if (change[ChangeIndex.TYPE] === ChangeType.REMOVE) {\n const pkIndex = capState.pks.indexOf(pk);\n if (pkIndex === -1) {\n // Not in our set — drop\n return;\n }\n // Remove from set\n const pks = [...capState.pks];\n pks.splice(pkIndex, 1);\n const newSize = capState.size - 1;\n\n // Try to refill: fetch from input with partition constraint,\n // find first row NOT in PK set\n const pkSet = new Set(pks);\n const constraint = this.#partitionKey\n ? (Object.fromEntries(\n this.#partitionKey.map(\n key => [key, change[ChangeIndex.NODE].row[key]] as const,\n ),\n ) as Constraint)\n : undefined;\n\n let replacement: Node | undefined;\n for (const node of this.#input.fetch({constraint})) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n const nodePK = serializePK(node.row, this.#primaryKey);\n if (!pkSet.has(nodePK)) {\n replacement = node;\n break;\n }\n }\n\n if (replacement) {\n // Store state WITHOUT replacement during remove forward,\n // matching Take's pattern of hiding in-flight changes from re-fetches.\n this.#storage.set(capStateKey, {size: newSize, pks});\n yield* this.#output.push(change, this);\n // Now add replacement to set and forward the add.\n const replacementPK = serializePK(replacement.row, this.#primaryKey);\n pks.push(replacementPK);\n this.#storage.set(capStateKey, {size: newSize + 1, pks});\n yield* this.#output.push(makeAddChange(replacement), this);\n } else {\n this.#storage.set(capStateKey, {size: newSize, pks});\n yield* this.#output.push(change, this);\n }\n } else if (change[ChangeIndex.TYPE] === ChangeType.CHILD) {\n const pkSet = new Set(capState.pks);\n if (pkSet.has(pk)) {\n yield* this.#output.push(change, this);\n }\n }\n }\n\n #pushEditChange(change: EditChange): Stream<'yield'> {\n assert(\n !this.#partitionKeyComparator ||\n this.#partitionKeyComparator(\n change[ChangeIndex.OLD_NODE].row,\n change[ChangeIndex.NODE].row,\n ) === 0,\n 'Unexpected change of partition key',\n );\n const capStateKey = getCapStateKey(\n this.#partitionKey,\n change[ChangeIndex.OLD_NODE].row,\n );\n const capState = this.#storage.get(capStateKey);\n if (!capState) {\n return emptyArray;\n }\n\n const oldPK = serializePK(\n change[ChangeIndex.OLD_NODE].row,\n this.#primaryKey,\n );\n const pkSet = new Set(capState.pks);\n if (pkSet.has(oldPK)) {\n // Update the PK in our set if it changed\n const newPK = serializePK(change[ChangeIndex.NODE].row, this.#primaryKey);\n if (oldPK !== newPK) {\n const pks = capState.pks.map(p => (p === oldPK ? newPK : p));\n this.#storage.set(capStateKey, {size: capState.size, pks});\n }\n return this.#output.push(change, this);\n }\n // If not in our set, drop\n return emptyArray;\n }\n\n destroy(): void {\n this.#input.destroy();\n this.#storage.destroy();\n }\n\n *reconcile(_pusher: InputBase): Stream<'yield'> {\n if (this.#output.reconcile) {\n yield* this.#output.reconcile(this);\n }\n }\n}\n\nfunction getCapStateKey(\n partitionKey: PartitionKey | undefined,\n rowOrConstraint: Row | Constraint | undefined,\n): string {\n const partitionValues: Value[] = [];\n\n if (partitionKey && rowOrConstraint) {\n for (const key of partitionKey) {\n partitionValues.push(rowOrConstraint[key]);\n }\n }\n\n return JSON.stringify(['cap', ...partitionValues]);\n}\n\nfunction serializePK(row: Row, primaryKey: PrimaryKey): string {\n return JSON.stringify(primaryKey.map(k => row[k]));\n}\n\nfunction deserializePKToConstraint(\n pk: string,\n primaryKey: PrimaryKey,\n): Constraint {\n const values = JSON.parse(pk) as Value[];\n const constraint: Record<string, Value> = {};\n for (let i = 0; i < primaryKey.length; i++) {\n constraint[primaryKey[i]] = values[i];\n }\n return constraint;\n}\n"],"mappings":"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"}