@rocicorp/zero 0.17.2025031401 → 0.17.2025031900

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 (43) hide show
  1. package/out/advanced.js +1 -1
  2. package/out/{chunk-SVJISXWE.js → chunk-7ARRNDLF.js} +56 -49
  3. package/out/{chunk-SVJISXWE.js.map → chunk-7ARRNDLF.js.map} +3 -3
  4. package/out/{chunk-UZE45UK4.js → chunk-VEVC5RHF.js} +53 -66
  5. package/out/chunk-VEVC5RHF.js.map +7 -0
  6. package/out/replicache/src/persist/refresh.d.ts.map +1 -1
  7. package/out/replicache/src/replicache-options.d.ts +2 -1
  8. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  9. package/out/shared/src/custom-key-map.d.ts +2 -2
  10. package/out/shared/src/custom-key-map.d.ts.map +1 -1
  11. package/out/shared/src/custom-key-map.js.map +1 -1
  12. package/out/shared/src/custom-key-set.d.ts +2 -2
  13. package/out/shared/src/custom-key-set.d.ts.map +1 -1
  14. package/out/shared/src/custom-key-set.js.map +1 -1
  15. package/out/solid.js +2 -2
  16. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  17. package/out/zero-cache/src/config/zero-config.js +2 -0
  18. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  19. package/out/zero-cache/src/scripts/deploy-permissions.js +1 -1
  20. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  21. package/out/zero-client/src/client/custom.d.ts +13 -9
  22. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  23. package/out/zero-client/src/client/ivm-branch.d.ts +2 -1
  24. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  25. package/out/zero-client/src/client/zero-rep.d.ts +2 -1
  26. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  27. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  28. package/out/zero-schema/src/builder/schema-builder.d.ts +0 -1
  29. package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
  30. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  31. package/out/zero.js +2 -2
  32. package/out/zql/src/ivm/schema.d.ts +2 -2
  33. package/out/zql/src/ivm/schema.d.ts.map +1 -1
  34. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  35. package/out/zql/src/ivm/view-apply-change.js +54 -34
  36. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  37. package/out/zql/src/query/query-impl.d.ts +1 -1
  38. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  39. package/out/zql/src/query/query-impl.js.map +1 -1
  40. package/out/zql/src/query/query.d.ts +1 -1
  41. package/out/zql/src/query/query.d.ts.map +1 -1
  42. package/package.json +3 -4
  43. package/out/chunk-UZE45UK4.js.map +0 -7
package/out/advanced.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./chunk-ULOTOBTC.js";
2
2
  import {
3
3
  applyChange
4
- } from "./chunk-SVJISXWE.js";
4
+ } from "./chunk-7ARRNDLF.js";
5
5
  import "./chunk-424PT5DM.js";
6
6
  export {
7
7
  applyChange
@@ -180,12 +180,17 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
180
180
  refCountMap.set(newEntry, 1);
181
181
  }
182
182
  } else {
183
- insertAndUpdateRefCount(
184
- refCountMap,
185
- getChildEntryList(parentEntry, relationship),
186
- newEntry,
187
- schema.compareRows
188
- );
183
+ const view = getChildEntryList(parentEntry, relationship);
184
+ const { pos, found } = binarySearch(view, newEntry, schema.compareRows);
185
+ let deleteCount = 0;
186
+ let rc = 1;
187
+ if (found) {
188
+ deleteCount = 1;
189
+ rc = must(refCountMap.get(view[pos])) + 1;
190
+ refCountMap.delete(view[pos]);
191
+ }
192
+ view.splice(pos, deleteCount, newEntry);
193
+ refCountMap.set(newEntry, rc);
189
194
  }
190
195
  for (const [relationship2, children] of Object.entries(
191
196
  change.node.relationships
@@ -222,12 +227,20 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
222
227
  refCountMap.set(oldEntry, rc - 1);
223
228
  }
224
229
  } else {
225
- removeAndsUpdateRefCount(
226
- refCountMap,
227
- getChildEntryList(parentEntry, relationship),
230
+ const view = getChildEntryList(parentEntry, relationship);
231
+ const { pos, found } = binarySearch(
232
+ view,
228
233
  change.node.row,
229
234
  schema.compareRows
230
235
  );
236
+ assert(found, "node does not exist");
237
+ const rc = must(refCountMap.get(view[pos]));
238
+ if (rc === 1) {
239
+ refCountMap.delete(view[pos]);
240
+ view.splice(pos, 1);
241
+ } else {
242
+ refCountMap.set(view[pos], rc - 1);
243
+ }
231
244
  }
232
245
  drainStreams(change.node);
233
246
  break;
@@ -284,7 +297,7 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
284
297
  change.oldNode.row,
285
298
  schema.compareRows
286
299
  );
287
- assert(found, "node does not exist");
300
+ assert(found, "node does not exists");
288
301
  const rc = must(refCountMap.get(view[pos]));
289
302
  refCountMap.delete(view[pos]);
290
303
  view[pos] = makeEntryPreserveRelationships(
@@ -294,23 +307,42 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
294
307
  );
295
308
  refCountMap.set(view[pos], rc);
296
309
  } else {
297
- const oldEntry = removeAndsUpdateRefCount(
298
- refCountMap,
310
+ const { pos, found } = binarySearch(
299
311
  view,
300
312
  change.oldNode.row,
301
313
  schema.compareRows
302
314
  );
303
- const newEntry = makeEntryPreserveRelationships(
304
- change.node.row,
305
- oldEntry,
306
- format.relationships
307
- );
308
- insertAndUpdateRefCount(
309
- refCountMap,
310
- view,
311
- newEntry,
312
- schema.compareRows
313
- );
315
+ assert(found, "node does not exists");
316
+ const oldEntry = view[pos];
317
+ const rc = must(refCountMap.get(oldEntry));
318
+ if (rc === 1) {
319
+ refCountMap.delete(oldEntry);
320
+ view.splice(pos, 1);
321
+ } else {
322
+ refCountMap.set(oldEntry, rc - 1);
323
+ }
324
+ {
325
+ const { pos: pos2, found: found2 } = binarySearch(
326
+ view,
327
+ change.node.row,
328
+ schema.compareRows
329
+ );
330
+ let rc2 = 1;
331
+ const newEntry = makeEntryPreserveRelationships(
332
+ change.node.row,
333
+ oldEntry,
334
+ format.relationships
335
+ );
336
+ let deleteCount = 0;
337
+ if (found2) {
338
+ deleteCount = 1;
339
+ const existing = view[pos2];
340
+ rc2 = must(refCountMap.get(existing)) + 1;
341
+ refCountMap.delete(existing);
342
+ }
343
+ view.splice(pos2, deleteCount, newEntry);
344
+ refCountMap.set(newEntry, rc2);
345
+ }
314
346
  }
315
347
  }
316
348
  break;
@@ -319,31 +351,6 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
319
351
  unreachable(change);
320
352
  }
321
353
  }
322
- function insertAndUpdateRefCount(refCountMap, view, newEntry, compareRows) {
323
- const { pos, found } = binarySearch(view, newEntry, compareRows);
324
- let deleteCount = 0;
325
- let rc = 1;
326
- if (found) {
327
- deleteCount = 1;
328
- rc = must(refCountMap.get(view[pos])) + 1;
329
- refCountMap.delete(view[pos]);
330
- }
331
- view.splice(pos, deleteCount, newEntry);
332
- refCountMap.set(newEntry, rc);
333
- }
334
- function removeAndsUpdateRefCount(refCountMap, view, target, compareRows) {
335
- const { pos, found } = binarySearch(view, target, compareRows);
336
- assert(found, "node does not exist");
337
- const oldEntry = view[pos];
338
- const rc = must(refCountMap.get(oldEntry));
339
- if (rc === 1) {
340
- refCountMap.delete(oldEntry);
341
- view.splice(pos, 1);
342
- } else {
343
- refCountMap.set(oldEntry, rc - 1);
344
- }
345
- return oldEntry;
346
- }
347
354
  function binarySearch(view, target, comparator) {
348
355
  let low = 0;
349
356
  let high = view.length - 1;
@@ -398,4 +405,4 @@ export {
398
405
  drainStreams,
399
406
  applyChange
400
407
  };
401
- //# sourceMappingURL=chunk-SVJISXWE.js.map
408
+ //# sourceMappingURL=chunk-7ARRNDLF.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../shared/src/asserts.ts", "../../shared/src/must.ts", "../../zql/src/ivm/data.ts", "../../zql/src/ivm/view-apply-change.ts"],
4
- "sourcesContent": ["export function assert(\n b: unknown,\n msg: string | (() => string) = 'Assertion failed',\n): asserts b {\n if (!b) {\n throw new Error(typeof msg === 'string' ? msg : msg());\n }\n}\n\nexport function assertString(v: unknown): asserts v is string {\n assertType(v, 'string');\n}\n\nexport function assertNumber(v: unknown): asserts v is number {\n assertType(v, 'number');\n}\n\nexport function assertBoolean(v: unknown): asserts v is boolean {\n assertType(v, 'boolean');\n}\n\nfunction assertType(v: unknown, t: string) {\n if (typeof v !== t) {\n throwInvalidType(v, t);\n }\n}\n\nexport function assertObject(v: unknown): asserts v is Record<string, unknown> {\n if (v === null) {\n throwInvalidType(v, 'object');\n }\n assertType(v, 'object');\n}\n\nexport function assertArray(v: unknown): asserts v is unknown[] {\n if (!Array.isArray(v)) {\n throwInvalidType(v, 'array');\n }\n}\n\nexport function invalidType(v: unknown, t: string): string {\n let s = 'Invalid type: ';\n if (v === null || v === undefined) {\n s += v;\n } else {\n s += `${typeof v} \\`${v}\\``;\n }\n return s + `, expected ${t}`;\n}\n\nexport function throwInvalidType(v: unknown, t: string): never {\n throw new Error(invalidType(v, t));\n}\n\nexport function assertNotNull<T>(v: T | null): asserts v is T {\n if (v === null) {\n throw new Error('Expected non-null value');\n }\n}\n\nexport function assertUndefined<T>(\n v: T | undefined,\n msg = 'Expected undefined value',\n): asserts v is T {\n if (v !== undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertNotUndefined<T>(\n v: T | undefined,\n msg = 'Expected non undefined value',\n): asserts v is T {\n if (v === undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertInstanceof<T>(\n v: unknown,\n t: new (...args: unknown[]) => T,\n): asserts v is T {\n if (!(v instanceof t)) {\n throw new Error(`Expected instanceof ${t.name}`);\n }\n}\n\nexport function assertUint8Array(v: unknown): asserts v is Uint8Array {\n assertInstanceof(v, Uint8Array);\n}\n\nexport function unreachable(): never;\nexport function unreachable(v: never): never;\nexport function unreachable(_?: never): never {\n throw new Error('Unreachable');\n}\n\nexport function notImplemented(): never {\n throw new Error('Not implemented');\n}\n", "export function must<T>(v: T | undefined | null, msg?: string): T {\n // eslint-disable-next-line eqeqeq\n if (v == null) {\n throw new Error(msg ?? `Unexpected ${v} value`);\n }\n return v;\n}\n", "import {compareUTF8} from 'compare-utf8';\nimport {\n assertBoolean,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport type {Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n relationships: Record<string, () => Stream<Node>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n if (typeof a === 'boolean') {\n assertBoolean(b);\n return a ? 1 : -1;\n }\n if (typeof a === 'number') {\n assertNumber(b);\n return a - b;\n }\n if (typeof a === 'string') {\n assertString(b);\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(\n order: Ordering,\n reverse?: boolean | undefined,\n): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n const result = ord[1] === 'asc' ? comp : -comp;\n return reverse ? -result : result;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n // eslint-disable-next-line eqeqeq\n if (a == null || b == null) {\n return false;\n }\n return a === b;\n}\n\nexport function drainStreams(node: Node) {\n for (const stream of Object.values(node.relationships)) {\n for (const node of stream()) {\n drainStreams(node);\n }\n }\n}\n", "import {\n assert,\n assertArray,\n assertObject,\n unreachable,\n} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {drainStreams, type Comparator, type Node} from './data.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Entry, EntryList, Format} from './view.ts';\n\n/**\n * `applyChange` does not consume the `relationships` of `ChildChange#node`,\n * `EditChange#node` and `EditChange#oldNode`. The `ViewChange` type\n * documents and enforces this via the type system.\n */\nexport type ViewChange =\n | AddViewChange\n | RemoveViewChange\n | ChildViewChange\n | EditViewChange;\n\nexport type RowOnlyNode = {row: Row};\n\nexport type AddViewChange = {\n type: 'add';\n node: Node;\n};\n\nexport type RemoveViewChange = {\n type: 'remove';\n node: Node;\n};\n\ntype ChildViewChange = {\n type: 'child';\n node: RowOnlyNode;\n child: {\n relationshipName: string;\n change: ViewChange;\n };\n};\n\ntype EditViewChange = {\n type: 'edit';\n node: RowOnlyNode;\n oldNode: RowOnlyNode;\n};\n\n/**\n * This is a subset of WeakMap but restricted to what we need.\n */\nexport interface RefCountMap {\n get(entry: Entry): number | undefined;\n set(entry: Entry, refCount: number): void;\n delete(entry: Entry): boolean;\n}\n\nexport function applyChange(\n parentEntry: Entry,\n change: ViewChange,\n schema: SourceSchema,\n relationship: string,\n format: Format,\n refCountMap: RefCountMap,\n) {\n if (schema.isHidden) {\n switch (change.type) {\n case 'add':\n case 'remove':\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n const childSchema = must(schema.relationships[relationship]);\n for (const node of children()) {\n applyChange(\n parentEntry,\n {type: change.type, node},\n childSchema,\n relationship,\n format,\n refCountMap,\n );\n }\n }\n return;\n case 'edit':\n // If hidden at this level it means that the hidden row was changed. If\n // the row was changed in such a way that it would change the\n // relationships then the edit would have been split into remove and\n // add.\n return;\n case 'child': {\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n applyChange(\n parentEntry,\n change.child.change,\n childSchema,\n relationship,\n format,\n refCountMap,\n );\n return;\n }\n default:\n unreachable(change);\n }\n }\n\n const {singular, relationships: childFormats} = format;\n switch (change.type) {\n case 'add': {\n // TODO: Only create a new entry if we need to mutate the existing one.\n const newEntry: Entry = {\n ...change.node.row,\n };\n if (singular) {\n const oldEntry = parentEntry[relationship] as Entry | undefined;\n if (oldEntry !== undefined) {\n assert(\n schema.compareRows(oldEntry, newEntry) === 0,\n 'single output already exists',\n );\n // adding same again.\n const rc = must(refCountMap.get(oldEntry));\n refCountMap.delete(oldEntry);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = newEntry;\n refCountMap.set(newEntry, rc + 1);\n } else {\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = newEntry;\n refCountMap.set(newEntry, 1);\n }\n } else {\n insertAndUpdateRefCount(\n refCountMap,\n getChildEntryList(parentEntry, relationship),\n newEntry,\n schema.compareRows,\n );\n }\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n // TODO: Is there a flag to make TypeScript complain that dictionary access might be undefined?\n const childSchema = must(schema.relationships[relationship]);\n const childFormat = childFormats[relationship];\n if (childFormat === undefined) {\n continue;\n }\n\n const newView = childFormat.singular ? undefined : ([] as EntryList);\n // @ts-expect-error newEntry is readonly\n newEntry[relationship] = newView;\n for (const node of children()) {\n applyChange(\n newEntry,\n {type: 'add', node},\n childSchema,\n relationship,\n childFormat,\n refCountMap,\n );\n }\n }\n break;\n }\n case 'remove': {\n if (singular) {\n const oldEntry = parentEntry[relationship] as Entry | undefined;\n assert(oldEntry !== undefined, 'node does not exist');\n const rc = must(refCountMap.get(oldEntry));\n if (rc === 1) {\n refCountMap.delete(oldEntry);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = undefined;\n } else {\n refCountMap.set(oldEntry, rc - 1);\n }\n } else {\n removeAndsUpdateRefCount(\n refCountMap,\n getChildEntryList(parentEntry, relationship),\n change.node.row,\n schema.compareRows,\n );\n }\n // Needed to ensure cleanup of operator state is fully done.\n drainStreams(change.node);\n break;\n }\n case 'child': {\n let existing: Entry;\n if (singular) {\n assertObject(parentEntry[relationship]);\n existing = parentEntry[relationship];\n } else {\n const view = getChildEntryList(parentEntry, relationship);\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n existing = view[pos];\n }\n\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n const childFormat = format.relationships[change.child.relationshipName];\n if (childFormat !== undefined) {\n applyChange(\n existing,\n change.child.change,\n childSchema,\n change.child.relationshipName,\n childFormat,\n refCountMap,\n );\n }\n break;\n }\n case 'edit': {\n if (singular) {\n const existing = parentEntry[relationship];\n assertEntry(existing);\n const rc = must(refCountMap.get(existing));\n const newEntry = {\n ...existing,\n ...change.node.row,\n };\n refCountMap.set(newEntry, rc);\n refCountMap.delete(existing);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = newEntry;\n } else {\n const view = parentEntry[relationship];\n assertEntryList(view);\n // If the order changed due to the edit, we need to remove and reinsert.\n if (schema.compareRows(change.oldNode.row, change.node.row) === 0) {\n const {pos, found} = binarySearch(\n view,\n change.oldNode.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n const rc = must(refCountMap.get(view[pos]));\n refCountMap.delete(view[pos]);\n // @ts-expect-error view is readonly\n view[pos] = makeEntryPreserveRelationships(\n change.node.row,\n view[pos],\n format.relationships,\n );\n refCountMap.set(view[pos], rc);\n } else {\n // Remove\n const oldEntry = removeAndsUpdateRefCount(\n refCountMap,\n view,\n change.oldNode.row,\n schema.compareRows,\n );\n\n // Insert\n const newEntry = makeEntryPreserveRelationships(\n change.node.row,\n oldEntry,\n format.relationships,\n );\n insertAndUpdateRefCount(\n refCountMap,\n view,\n newEntry,\n schema.compareRows,\n );\n }\n }\n break;\n }\n default:\n unreachable(change);\n }\n}\n\nfunction insertAndUpdateRefCount(\n refCountMap: RefCountMap,\n view: EntryList,\n newEntry: Entry,\n compareRows: Comparator,\n): void {\n const {pos, found} = binarySearch(view, newEntry, compareRows);\n\n let deleteCount = 0;\n let rc = 1;\n if (found) {\n deleteCount = 1;\n rc = must(refCountMap.get(view[pos])) + 1;\n refCountMap.delete(view[pos]);\n }\n\n // @ts-expect-error view is readonly\n view.splice(pos, deleteCount, newEntry);\n refCountMap.set(newEntry, rc);\n}\n\nfunction removeAndsUpdateRefCount(\n refCountMap: RefCountMap,\n view: EntryList,\n target: Row,\n compareRows: Comparator,\n): Entry {\n const {pos, found} = binarySearch(view, target, compareRows);\n assert(found, 'node does not exist');\n const oldEntry = view[pos];\n const rc = must(refCountMap.get(oldEntry));\n if (rc === 1) {\n refCountMap.delete(oldEntry);\n // @ts-expect-error view is readonly\n view.splice(pos, 1);\n } else {\n refCountMap.set(oldEntry, rc - 1);\n }\n\n return oldEntry;\n}\n\n// TODO: Do not return an object. It puts unnecessary pressure on the GC.\nfunction binarySearch(view: EntryList, target: Entry, comparator: Comparator) {\n let low = 0;\n let high = view.length - 1;\n while (low <= high) {\n const mid = (low + high) >>> 1;\n const comparison = comparator(view[mid] as Row, target as Row);\n if (comparison < 0) {\n low = mid + 1;\n } else if (comparison > 0) {\n high = mid - 1;\n } else {\n return {pos: mid, found: true};\n }\n }\n return {pos: low, found: false};\n}\n\nfunction makeEntryPreserveRelationships(\n row: Row,\n entry: Entry,\n relationships: {[key: string]: Format},\n): Entry {\n const result: Entry = {...row};\n for (const relationship in relationships) {\n assert(!(relationship in row), 'Relationship already exists');\n // @ts-expect-error entry is readonly\n result[relationship] = entry[relationship];\n }\n return result;\n}\n\nfunction getChildEntryList(\n parentEntry: Entry,\n relationship: string,\n): EntryList {\n const view = parentEntry[relationship];\n assertArray(view);\n return view as EntryList;\n}\n\nfunction assertEntryList(v: unknown): asserts v is EntryList {\n assertArray(v);\n}\n\nfunction assertEntry(v: unknown): asserts v is Entry {\n assertObject(v);\n}\n"],
5
- "mappings": ";AAAO,SAAS,OACd,GACA,MAA+B,oBACpB;AACX,MAAI,CAAC,GAAG;AACN,UAAM,IAAI,MAAM,OAAO,QAAQ,WAAW,MAAM,IAAI,CAAC;AAAA,EACvD;AACF;AAEO,SAAS,aAAa,GAAiC;AAC5D,aAAW,GAAG,QAAQ;AACxB;AAEO,SAAS,aAAa,GAAiC;AAC5D,aAAW,GAAG,QAAQ;AACxB;AAEO,SAAS,cAAc,GAAkC;AAC9D,aAAW,GAAG,SAAS;AACzB;AAEA,SAAS,WAAW,GAAY,GAAW;AACzC,MAAI,OAAO,MAAM,GAAG;AAClB,qBAAiB,GAAG,CAAC;AAAA,EACvB;AACF;AAEO,SAAS,aAAa,GAAkD;AAC7E,MAAI,MAAM,MAAM;AACd,qBAAiB,GAAG,QAAQ;AAAA,EAC9B;AACA,aAAW,GAAG,QAAQ;AACxB;AAEO,SAAS,YAAY,GAAoC;AAC9D,MAAI,CAAC,MAAM,QAAQ,CAAC,GAAG;AACrB,qBAAiB,GAAG,OAAO;AAAA,EAC7B;AACF;AAEO,SAAS,YAAY,GAAY,GAAmB;AACzD,MAAI,IAAI;AACR,MAAI,MAAM,QAAQ,MAAM,QAAW;AACjC,SAAK;AAAA,EACP,OAAO;AACL,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC;AAAA,EACzB;AACA,SAAO,IAAI,cAAc,CAAC;AAC5B;AAEO,SAAS,iBAAiB,GAAY,GAAkB;AAC7D,QAAM,IAAI,MAAM,YAAY,GAAG,CAAC,CAAC;AACnC;AAEO,SAAS,cAAiB,GAA6B;AAC5D,MAAI,MAAM,MAAM;AACd,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AACF;AAmCO,SAAS,YAAY,GAAkB;AAC5C,QAAM,IAAI,MAAM,aAAa;AAC/B;;;AC/FO,SAAS,KAAQ,GAAyB,KAAiB;AAEhE,MAAI,KAAK,MAAM;AACb,UAAM,IAAI,MAAM,OAAO,cAAc,CAAC,QAAQ;AAAA,EAChD;AACA,SAAO;AACT;;;ACNA,SAAQ,mBAAkB;AA+BnB,SAAS,cAAc,GAAU,GAAkB;AACxD,MAAI,mBAAmB,CAAC;AACxB,MAAI,mBAAmB,CAAC;AAExB,MAAI,MAAM,GAAG;AACX,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,WAAW;AAC1B,kBAAc,CAAC;AACf,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AACd,WAAO,IAAI;AAAA,EACb;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AASd,WAAO,YAAY,GAAG,CAAC;AAAA,EACzB;AACA,QAAM,IAAI,MAAM,qBAAqB,CAAC,EAAE;AAC1C;AASO,SAAS,mBAAmB,GAA2B;AAC5D,SAAO,KAAK;AACd;AAIO,SAAS,eACd,OACA,SACY;AACZ,SAAO,CAAC,GAAG,MAAM;AAEf,eAAW,OAAO,OAAO;AACvB,YAAM,QAAQ,IAAI,CAAC;AACnB,YAAM,OAAO,cAAc,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAC7C,UAAI,SAAS,GAAG;AACd,cAAM,SAAS,IAAI,CAAC,MAAM,QAAQ,OAAO,CAAC;AAC1C,eAAO,UAAU,CAAC,SAAS;AAAA,MAC7B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAQO,SAAS,YAAY,GAAU,GAAmB;AAEvD,MAAI,KAAK,QAAQ,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AACA,SAAO,MAAM;AACf;AAEO,SAAS,aAAa,MAAY;AACvC,aAAW,UAAU,OAAO,OAAO,KAAK,aAAa,GAAG;AACtD,eAAWA,SAAQ,OAAO,GAAG;AAC3B,mBAAaA,KAAI;AAAA,IACnB;AAAA,EACF;AACF;;;AC3DO,SAAS,YACd,aACA,QACA,QACA,cACA,QACA,aACA;AACA,MAAI,OAAO,UAAU;AACnB,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AACH,mBAAW,CAACC,eAAc,QAAQ,KAAK,OAAO;AAAA,UAC5C,OAAO,KAAK;AAAA,QACd,GAAG;AACD,gBAAM,cAAc,KAAK,OAAO,cAAcA,aAAY,CAAC;AAC3D,qBAAW,QAAQ,SAAS,GAAG;AAC7B;AAAA,cACE;AAAA,cACA,EAAC,MAAM,OAAO,MAAM,KAAI;AAAA,cACxB;AAAA,cACAA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF,KAAK;AAKH;AAAA,MACF,KAAK,SAAS;AACZ,cAAM,cAAc;AAAA,UAClB,OAAO,cAAc,OAAO,MAAM,gBAAgB;AAAA,QACpD;AACA;AAAA,UACE;AAAA,UACA,OAAO,MAAM;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA;AACE,oBAAY,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,QAAM,EAAC,UAAU,eAAe,aAAY,IAAI;AAChD,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,OAAO;AAEV,YAAM,WAAkB;AAAA,QACtB,GAAG,OAAO,KAAK;AAAA,MACjB;AACA,UAAI,UAAU;AACZ,cAAM,WAAW,YAAY,YAAY;AACzC,YAAI,aAAa,QAAW;AAC1B;AAAA,YACE,OAAO,YAAY,UAAU,QAAQ,MAAM;AAAA,YAC3C;AAAA,UACF;AAEA,gBAAM,KAAK,KAAK,YAAY,IAAI,QAAQ,CAAC;AACzC,sBAAY,OAAO,QAAQ;AAE3B,sBAAY,YAAY,IAAI;AAC5B,sBAAY,IAAI,UAAU,KAAK,CAAC;AAAA,QAClC,OAAO;AAEL,sBAAY,YAAY,IAAI;AAC5B,sBAAY,IAAI,UAAU,CAAC;AAAA,QAC7B;AAAA,MACF,OAAO;AACL;AAAA,UACE;AAAA,UACA,kBAAkB,aAAa,YAAY;AAAA,UAC3C;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF;AACA,iBAAW,CAACA,eAAc,QAAQ,KAAK,OAAO;AAAA,QAC5C,OAAO,KAAK;AAAA,MACd,GAAG;AAED,cAAM,cAAc,KAAK,OAAO,cAAcA,aAAY,CAAC;AAC3D,cAAM,cAAc,aAAaA,aAAY;AAC7C,YAAI,gBAAgB,QAAW;AAC7B;AAAA,QACF;AAEA,cAAM,UAAU,YAAY,WAAW,SAAa,CAAC;AAErD,iBAASA,aAAY,IAAI;AACzB,mBAAW,QAAQ,SAAS,GAAG;AAC7B;AAAA,YACE;AAAA,YACA,EAAC,MAAM,OAAO,KAAI;AAAA,YAClB;AAAA,YACAA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,UAAI,UAAU;AACZ,cAAM,WAAW,YAAY,YAAY;AACzC,eAAO,aAAa,QAAW,qBAAqB;AACpD,cAAM,KAAK,KAAK,YAAY,IAAI,QAAQ,CAAC;AACzC,YAAI,OAAO,GAAG;AACZ,sBAAY,OAAO,QAAQ;AAE3B,sBAAY,YAAY,IAAI;AAAA,QAC9B,OAAO;AACL,sBAAY,IAAI,UAAU,KAAK,CAAC;AAAA,QAClC;AAAA,MACF,OAAO;AACL;AAAA,UACE;AAAA,UACA,kBAAkB,aAAa,YAAY;AAAA,UAC3C,OAAO,KAAK;AAAA,UACZ,OAAO;AAAA,QACT;AAAA,MACF;AAEA,mBAAa,OAAO,IAAI;AACxB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,UAAI;AACJ,UAAI,UAAU;AACZ,qBAAa,YAAY,YAAY,CAAC;AACtC,mBAAW,YAAY,YAAY;AAAA,MACrC,OAAO;AACL,cAAM,OAAO,kBAAkB,aAAa,YAAY;AACxD,cAAM,EAAC,KAAK,MAAK,IAAI;AAAA,UACnB;AAAA,UACA,OAAO,KAAK;AAAA,UACZ,OAAO;AAAA,QACT;AACA,eAAO,OAAO,qBAAqB;AACnC,mBAAW,KAAK,GAAG;AAAA,MACrB;AAEA,YAAM,cAAc;AAAA,QAClB,OAAO,cAAc,OAAO,MAAM,gBAAgB;AAAA,MACpD;AACA,YAAM,cAAc,OAAO,cAAc,OAAO,MAAM,gBAAgB;AACtE,UAAI,gBAAgB,QAAW;AAC7B;AAAA,UACE;AAAA,UACA,OAAO,MAAM;AAAA,UACb;AAAA,UACA,OAAO,MAAM;AAAA,UACb;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,UAAI,UAAU;AACZ,cAAM,WAAW,YAAY,YAAY;AACzC,oBAAY,QAAQ;AACpB,cAAM,KAAK,KAAK,YAAY,IAAI,QAAQ,CAAC;AACzC,cAAM,WAAW;AAAA,UACf,GAAG;AAAA,UACH,GAAG,OAAO,KAAK;AAAA,QACjB;AACA,oBAAY,IAAI,UAAU,EAAE;AAC5B,oBAAY,OAAO,QAAQ;AAE3B,oBAAY,YAAY,IAAI;AAAA,MAC9B,OAAO;AACL,cAAM,OAAO,YAAY,YAAY;AACrC,wBAAgB,IAAI;AAEpB,YAAI,OAAO,YAAY,OAAO,QAAQ,KAAK,OAAO,KAAK,GAAG,MAAM,GAAG;AACjE,gBAAM,EAAC,KAAK,MAAK,IAAI;AAAA,YACnB;AAAA,YACA,OAAO,QAAQ;AAAA,YACf,OAAO;AAAA,UACT;AACA,iBAAO,OAAO,qBAAqB;AACnC,gBAAM,KAAK,KAAK,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC;AAC1C,sBAAY,OAAO,KAAK,GAAG,CAAC;AAE5B,eAAK,GAAG,IAAI;AAAA,YACV,OAAO,KAAK;AAAA,YACZ,KAAK,GAAG;AAAA,YACR,OAAO;AAAA,UACT;AACA,sBAAY,IAAI,KAAK,GAAG,GAAG,EAAE;AAAA,QAC/B,OAAO;AAEL,gBAAM,WAAW;AAAA,YACf;AAAA,YACA;AAAA,YACA,OAAO,QAAQ;AAAA,YACf,OAAO;AAAA,UACT;AAGA,gBAAM,WAAW;AAAA,YACf,OAAO,KAAK;AAAA,YACZ;AAAA,YACA,OAAO;AAAA,UACT;AACA;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA;AACE,kBAAY,MAAM;AAAA,EACtB;AACF;AAEA,SAAS,wBACP,aACA,MACA,UACA,aACM;AACN,QAAM,EAAC,KAAK,MAAK,IAAI,aAAa,MAAM,UAAU,WAAW;AAE7D,MAAI,cAAc;AAClB,MAAI,KAAK;AACT,MAAI,OAAO;AACT,kBAAc;AACd,SAAK,KAAK,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI;AACxC,gBAAY,OAAO,KAAK,GAAG,CAAC;AAAA,EAC9B;AAGA,OAAK,OAAO,KAAK,aAAa,QAAQ;AACtC,cAAY,IAAI,UAAU,EAAE;AAC9B;AAEA,SAAS,yBACP,aACA,MACA,QACA,aACO;AACP,QAAM,EAAC,KAAK,MAAK,IAAI,aAAa,MAAM,QAAQ,WAAW;AAC3D,SAAO,OAAO,qBAAqB;AACnC,QAAM,WAAW,KAAK,GAAG;AACzB,QAAM,KAAK,KAAK,YAAY,IAAI,QAAQ,CAAC;AACzC,MAAI,OAAO,GAAG;AACZ,gBAAY,OAAO,QAAQ;AAE3B,SAAK,OAAO,KAAK,CAAC;AAAA,EACpB,OAAO;AACL,gBAAY,IAAI,UAAU,KAAK,CAAC;AAAA,EAClC;AAEA,SAAO;AACT;AAGA,SAAS,aAAa,MAAiB,QAAe,YAAwB;AAC5E,MAAI,MAAM;AACV,MAAI,OAAO,KAAK,SAAS;AACzB,SAAO,OAAO,MAAM;AAClB,UAAM,MAAO,MAAM,SAAU;AAC7B,UAAM,aAAa,WAAW,KAAK,GAAG,GAAU,MAAa;AAC7D,QAAI,aAAa,GAAG;AAClB,YAAM,MAAM;AAAA,IACd,WAAW,aAAa,GAAG;AACzB,aAAO,MAAM;AAAA,IACf,OAAO;AACL,aAAO,EAAC,KAAK,KAAK,OAAO,KAAI;AAAA,IAC/B;AAAA,EACF;AACA,SAAO,EAAC,KAAK,KAAK,OAAO,MAAK;AAChC;AAEA,SAAS,+BACP,KACA,OACA,eACO;AACP,QAAM,SAAgB,EAAC,GAAG,IAAG;AAC7B,aAAW,gBAAgB,eAAe;AACxC,WAAO,EAAE,gBAAgB,MAAM,6BAA6B;AAE5D,WAAO,YAAY,IAAI,MAAM,YAAY;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,kBACP,aACA,cACW;AACX,QAAM,OAAO,YAAY,YAAY;AACrC,cAAY,IAAI;AAChB,SAAO;AACT;AAEA,SAAS,gBAAgB,GAAoC;AAC3D,cAAY,CAAC;AACf;AAEA,SAAS,YAAY,GAAgC;AACnD,eAAa,CAAC;AAChB;",
6
- "names": ["node", "relationship"]
4
+ "sourcesContent": ["export function assert(\n b: unknown,\n msg: string | (() => string) = 'Assertion failed',\n): asserts b {\n if (!b) {\n throw new Error(typeof msg === 'string' ? msg : msg());\n }\n}\n\nexport function assertString(v: unknown): asserts v is string {\n assertType(v, 'string');\n}\n\nexport function assertNumber(v: unknown): asserts v is number {\n assertType(v, 'number');\n}\n\nexport function assertBoolean(v: unknown): asserts v is boolean {\n assertType(v, 'boolean');\n}\n\nfunction assertType(v: unknown, t: string) {\n if (typeof v !== t) {\n throwInvalidType(v, t);\n }\n}\n\nexport function assertObject(v: unknown): asserts v is Record<string, unknown> {\n if (v === null) {\n throwInvalidType(v, 'object');\n }\n assertType(v, 'object');\n}\n\nexport function assertArray(v: unknown): asserts v is unknown[] {\n if (!Array.isArray(v)) {\n throwInvalidType(v, 'array');\n }\n}\n\nexport function invalidType(v: unknown, t: string): string {\n let s = 'Invalid type: ';\n if (v === null || v === undefined) {\n s += v;\n } else {\n s += `${typeof v} \\`${v}\\``;\n }\n return s + `, expected ${t}`;\n}\n\nexport function throwInvalidType(v: unknown, t: string): never {\n throw new Error(invalidType(v, t));\n}\n\nexport function assertNotNull<T>(v: T | null): asserts v is T {\n if (v === null) {\n throw new Error('Expected non-null value');\n }\n}\n\nexport function assertUndefined<T>(\n v: T | undefined,\n msg = 'Expected undefined value',\n): asserts v is T {\n if (v !== undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertNotUndefined<T>(\n v: T | undefined,\n msg = 'Expected non undefined value',\n): asserts v is T {\n if (v === undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertInstanceof<T>(\n v: unknown,\n t: new (...args: unknown[]) => T,\n): asserts v is T {\n if (!(v instanceof t)) {\n throw new Error(`Expected instanceof ${t.name}`);\n }\n}\n\nexport function assertUint8Array(v: unknown): asserts v is Uint8Array {\n assertInstanceof(v, Uint8Array);\n}\n\nexport function unreachable(): never;\nexport function unreachable(v: never): never;\nexport function unreachable(_?: never): never {\n throw new Error('Unreachable');\n}\n\nexport function notImplemented(): never {\n throw new Error('Not implemented');\n}\n", "export function must<T>(v: T | undefined | null, msg?: string): T {\n // eslint-disable-next-line eqeqeq\n if (v == null) {\n throw new Error(msg ?? `Unexpected ${v} value`);\n }\n return v;\n}\n", "import {compareUTF8} from 'compare-utf8';\nimport {\n assertBoolean,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport type {Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n relationships: Record<string, () => Stream<Node>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n if (typeof a === 'boolean') {\n assertBoolean(b);\n return a ? 1 : -1;\n }\n if (typeof a === 'number') {\n assertNumber(b);\n return a - b;\n }\n if (typeof a === 'string') {\n assertString(b);\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(\n order: Ordering,\n reverse?: boolean | undefined,\n): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n const result = ord[1] === 'asc' ? comp : -comp;\n return reverse ? -result : result;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n // eslint-disable-next-line eqeqeq\n if (a == null || b == null) {\n return false;\n }\n return a === b;\n}\n\nexport function drainStreams(node: Node) {\n for (const stream of Object.values(node.relationships)) {\n for (const node of stream()) {\n drainStreams(node);\n }\n }\n}\n", "import {\n assert,\n assertArray,\n assertObject,\n unreachable,\n} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {drainStreams, type Comparator, type Node} from './data.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Entry, EntryList, Format} from './view.ts';\n\n/**\n * `applyChange` does not consume the `relationships` of `ChildChange#node`,\n * `EditChange#node` and `EditChange#oldNode`. The `ViewChange` type\n * documents and enforces this via the type system.\n */\nexport type ViewChange =\n | AddViewChange\n | RemoveViewChange\n | ChildViewChange\n | EditViewChange;\n\nexport type RowOnlyNode = {row: Row};\n\nexport type AddViewChange = {\n type: 'add';\n node: Node;\n};\n\nexport type RemoveViewChange = {\n type: 'remove';\n node: Node;\n};\n\ntype ChildViewChange = {\n type: 'child';\n node: RowOnlyNode;\n child: {\n relationshipName: string;\n change: ViewChange;\n };\n};\n\ntype EditViewChange = {\n type: 'edit';\n node: RowOnlyNode;\n oldNode: RowOnlyNode;\n};\n\n/**\n * This is a subset of WeakMap but restricted to what we need.\n */\nexport interface RefCountMap {\n get(entry: Entry): number | undefined;\n set(entry: Entry, refCount: number): void;\n delete(entry: Entry): boolean;\n}\n\nexport function applyChange(\n parentEntry: Entry,\n change: ViewChange,\n schema: SourceSchema,\n relationship: string,\n format: Format,\n refCountMap: RefCountMap,\n) {\n if (schema.isHidden) {\n switch (change.type) {\n case 'add':\n case 'remove':\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n const childSchema = must(schema.relationships[relationship]);\n for (const node of children()) {\n applyChange(\n parentEntry,\n {type: change.type, node},\n childSchema,\n relationship,\n format,\n refCountMap,\n );\n }\n }\n return;\n case 'edit':\n // If hidden at this level it means that the hidden row was changed. If\n // the row was changed in such a way that it would change the\n // relationships then the edit would have been split into remove and\n // add.\n return;\n case 'child': {\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n applyChange(\n parentEntry,\n change.child.change,\n childSchema,\n relationship,\n format,\n refCountMap,\n );\n return;\n }\n default:\n unreachable(change);\n }\n }\n\n const {singular, relationships: childFormats} = format;\n switch (change.type) {\n case 'add': {\n // TODO: Only create a new entry if we need to mutate the existing one.\n const newEntry: Entry = {\n ...change.node.row,\n };\n if (singular) {\n const oldEntry = parentEntry[relationship] as Entry | undefined;\n if (oldEntry !== undefined) {\n assert(\n schema.compareRows(oldEntry, newEntry) === 0,\n 'single output already exists',\n );\n // adding same again.\n const rc = must(refCountMap.get(oldEntry));\n refCountMap.delete(oldEntry);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = newEntry;\n refCountMap.set(newEntry, rc + 1);\n } else {\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = newEntry;\n refCountMap.set(newEntry, 1);\n }\n } else {\n const view = getChildEntryList(parentEntry, relationship);\n const {pos, found} = binarySearch(view, newEntry, schema.compareRows);\n\n let deleteCount = 0;\n let rc = 1;\n if (found) {\n deleteCount = 1;\n rc = must(refCountMap.get(view[pos])) + 1;\n refCountMap.delete(view[pos]);\n }\n\n // @ts-expect-error view is readonly\n view.splice(pos, deleteCount, newEntry);\n refCountMap.set(newEntry, rc);\n }\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n // TODO: Is there a flag to make TypeScript complain that dictionary access might be undefined?\n const childSchema = must(schema.relationships[relationship]);\n const childFormat = childFormats[relationship];\n if (childFormat === undefined) {\n continue;\n }\n\n const newView = childFormat.singular ? undefined : ([] as EntryList);\n // @ts-expect-error newEntry is readonly\n newEntry[relationship] = newView;\n for (const node of children()) {\n applyChange(\n newEntry,\n {type: 'add', node},\n childSchema,\n relationship,\n childFormat,\n refCountMap,\n );\n }\n }\n break;\n }\n case 'remove': {\n if (singular) {\n const oldEntry = parentEntry[relationship] as Entry | undefined;\n assert(oldEntry !== undefined, 'node does not exist');\n const rc = must(refCountMap.get(oldEntry));\n if (rc === 1) {\n refCountMap.delete(oldEntry);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = undefined;\n } else {\n refCountMap.set(oldEntry, rc - 1);\n }\n } else {\n const view = getChildEntryList(parentEntry, relationship);\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n const rc = must(refCountMap.get(view[pos]));\n if (rc === 1) {\n refCountMap.delete(view[pos]);\n // @ts-expect-error view is readonly\n view.splice(pos, 1);\n } else {\n refCountMap.set(view[pos], rc - 1);\n }\n }\n // Needed to ensure cleanup of operator state is fully done.\n drainStreams(change.node);\n break;\n }\n case 'child': {\n let existing: Entry;\n if (singular) {\n assertObject(parentEntry[relationship]);\n existing = parentEntry[relationship];\n } else {\n const view = getChildEntryList(parentEntry, relationship);\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n existing = view[pos];\n }\n\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n const childFormat = format.relationships[change.child.relationshipName];\n if (childFormat !== undefined) {\n applyChange(\n existing,\n change.child.change,\n childSchema,\n change.child.relationshipName,\n childFormat,\n refCountMap,\n );\n }\n break;\n }\n case 'edit': {\n if (singular) {\n const existing = parentEntry[relationship];\n assertEntry(existing);\n const rc = must(refCountMap.get(existing));\n const newEntry = {\n ...existing,\n ...change.node.row,\n };\n refCountMap.set(newEntry, rc);\n refCountMap.delete(existing);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = newEntry;\n } else {\n const view = parentEntry[relationship];\n assertEntryList(view);\n // If the order changed due to the edit, we need to remove and reinsert.\n if (schema.compareRows(change.oldNode.row, change.node.row) === 0) {\n const {pos, found} = binarySearch(\n view,\n change.oldNode.row,\n schema.compareRows,\n );\n assert(found, 'node does not exists');\n const rc = must(refCountMap.get(view[pos]));\n refCountMap.delete(view[pos]);\n // @ts-expect-error view is readonly\n view[pos] = makeEntryPreserveRelationships(\n change.node.row,\n view[pos],\n format.relationships,\n );\n refCountMap.set(view[pos], rc);\n } else {\n // Remove\n const {pos, found} = binarySearch(\n view,\n change.oldNode.row,\n schema.compareRows,\n );\n assert(found, 'node does not exists');\n const oldEntry = view[pos];\n const rc = must(refCountMap.get(oldEntry));\n if (rc === 1) {\n refCountMap.delete(oldEntry);\n // @ts-expect-error view is readonly\n view.splice(pos, 1);\n } else {\n refCountMap.set(oldEntry, rc - 1);\n }\n\n // Insert\n {\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n let rc = 1;\n const newEntry = makeEntryPreserveRelationships(\n change.node.row,\n oldEntry,\n format.relationships,\n );\n let deleteCount = 0;\n if (found) {\n // We changed a row to a row that already exists. The existing row\n // should increase its ref count.\n deleteCount = 1;\n const existing = view[pos];\n rc = must(refCountMap.get(existing)) + 1;\n refCountMap.delete(existing);\n }\n // @ts-expect-error view is readonly\n view.splice(pos, deleteCount, newEntry);\n refCountMap.set(newEntry, rc);\n }\n }\n }\n break;\n }\n default:\n unreachable(change);\n }\n}\n\n// TODO: Do not return an object. It puts unnecessary pressure on the GC.\nfunction binarySearch(view: EntryList, target: Entry, comparator: Comparator) {\n let low = 0;\n let high = view.length - 1;\n while (low <= high) {\n const mid = (low + high) >>> 1;\n const comparison = comparator(view[mid] as Row, target as Row);\n if (comparison < 0) {\n low = mid + 1;\n } else if (comparison > 0) {\n high = mid - 1;\n } else {\n return {pos: mid, found: true};\n }\n }\n return {pos: low, found: false};\n}\n\nfunction makeEntryPreserveRelationships(\n row: Row,\n entry: Entry,\n relationships: {[key: string]: Format},\n): Entry {\n const result: Entry = {...row};\n for (const relationship in relationships) {\n assert(!(relationship in row), 'Relationship already exists');\n // @ts-expect-error entry is readonly\n result[relationship] = entry[relationship];\n }\n return result;\n}\n\nfunction getChildEntryList(\n parentEntry: Entry,\n relationship: string,\n): EntryList {\n const view = parentEntry[relationship] as unknown;\n assertArray(view);\n return view as EntryList;\n}\n\nfunction assertEntryList(v: unknown): asserts v is EntryList {\n assertArray(v);\n}\n\nfunction assertEntry(v: unknown): asserts v is Entry {\n assertObject(v);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["node", "relationship", "pos", "found", "rc"]
7
7
  }
@@ -21,7 +21,7 @@ import {
21
21
  throwInvalidType,
22
22
  unreachable,
23
23
  valuesEqual
24
- } from "./chunk-SVJISXWE.js";
24
+ } from "./chunk-7ARRNDLF.js";
25
25
  import {
26
26
  __export,
27
27
  __reExport
@@ -6315,7 +6315,7 @@ async function persistDD31(lc, clientID, memdag, perdag, mutators, closed, forma
6315
6315
  return;
6316
6316
  }
6317
6317
  let memdagBaseSnapshotPersisted = false;
6318
- const zeroDataForMemdagBaseSnapshot = getZeroData && await getZeroData(memdagBaseSnapshot.chunk.hash);
6318
+ const zeroDataForMemdagBaseSnapshot = getZeroData && await getZeroData("rebase", memdagBaseSnapshot.chunk.hash);
6319
6319
  await withWrite(perdag, async (perdagWrite) => {
6320
6320
  const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] = await getClientGroupInfo(perdagWrite, mainClientGroupID);
6321
6321
  let newMainClientGroupHeadHash = latestPerdagMainClientGroupHeadCommit.chunk.hash;
@@ -6368,7 +6368,7 @@ async function persistDD31(lc, clientID, memdag, perdag, mutators, closed, forma
6368
6368
  }
6369
6369
  let zeroDataForPerdagHeadCommit;
6370
6370
  if (!memdagBaseSnapshotPersisted) {
6371
- zeroDataForPerdagHeadCommit = getZeroData && await getZeroData(newMainClientGroupHeadHash, {
6371
+ zeroDataForPerdagHeadCommit = getZeroData && await getZeroData("rebase", newMainClientGroupHeadHash, {
6372
6372
  openLazySourceRead: perdagWrite
6373
6373
  });
6374
6374
  }
@@ -6575,9 +6575,13 @@ async function refresh(lc, memdag, perdag, clientID, mutators, diffConfig, close
6575
6575
  await Promise.all(ps);
6576
6576
  let newMemdagHeadHash = perdagClientGroupHeadHash;
6577
6577
  if (newMemdagMutations.length > 0) {
6578
- const zeroData2 = await zero?.getTxData?.(newMemdagHeadHash, {
6579
- openLazyRead: memdagWrite
6580
- });
6578
+ const zeroData2 = await zero?.getTxData?.(
6579
+ "rebase",
6580
+ newMemdagHeadHash,
6581
+ {
6582
+ openLazyRead: memdagWrite
6583
+ }
6584
+ );
6581
6585
  for (let i = newMemdagMutations.length - 1; i >= 0; i--) {
6582
6586
  newMemdagHeadHash = (await rebaseMutationAndPutCommit(
6583
6587
  newMemdagMutations[i],
@@ -7620,7 +7624,7 @@ var ReplicacheImpl = class {
7620
7624
  void this.#schedulePersist();
7621
7625
  return;
7622
7626
  }
7623
- const zeroData2 = await this.#zero?.getTxData?.(syncHead);
7627
+ const zeroData2 = await this.#zero?.getTxData?.("rebase", syncHead);
7624
7628
  for (const mutation of replayMutations) {
7625
7629
  if (this.#subscriptions.hasPendingSubscriptionRuns) {
7626
7630
  await Promise.resolve();
@@ -8186,7 +8190,7 @@ var ReplicacheImpl = class {
8186
8190
  clientID,
8187
8191
  await dbWrite.getMutationID(),
8188
8192
  "initial",
8189
- await this.#zero?.getTxData(headHash, {
8193
+ await this.#zero?.getTxData("initial", headHash, {
8190
8194
  openLazyRead: dagWrite
8191
8195
  }),
8192
8196
  dbWrite,
@@ -13682,7 +13686,14 @@ var IVMSourceBranch = class _IVMSourceBranch {
13682
13686
  /**
13683
13687
  * Fork the branch and patch it up to match the desired head.
13684
13688
  */
13685
- async forkToHead(store, desiredHead, readOptions) {
13689
+ async forkToHead(reason, store, desiredHead, readOptions) {
13690
+ if (reason === "initial") {
13691
+ assert(
13692
+ this.hash === desiredHead,
13693
+ "main branch must be at desired head for `initial`"
13694
+ );
13695
+ return this;
13696
+ }
13686
13697
  const fork = this.fork();
13687
13698
  if (fork.hash === desiredHead) {
13688
13699
  return fork;
@@ -14103,7 +14114,12 @@ var TransactionImpl = class {
14103
14114
  this.mutate = makeSchemaCRUD(
14104
14115
  schema,
14105
14116
  repTx,
14106
- must(
14117
+ // CRUD operators should not mutate the IVM store directly
14118
+ // for `initial`. The IVM store will be updated via calls to `advance`
14119
+ // after the transaction has been committed to the Replicache b-tree.
14120
+ // Mutating the IVM store in the mutator would cause us to synchronously
14121
+ // notify listeners of IVM while we're inside of the Replicache DB transaction.
14122
+ repTx.reason === "initial" ? void 0 : must(
14107
14123
  castedRepTx[zeroData],
14108
14124
  "zero was not set on replicache internal options!"
14109
14125
  )
@@ -14499,7 +14515,7 @@ function makeMessage(message, context, logLevel) {
14499
14515
  }
14500
14516
 
14501
14517
  // ../zero-client/src/client/version.ts
14502
- var version2 = "0.17.2025031401";
14518
+ var version2 = "0.17.2025031900";
14503
14519
 
14504
14520
  // ../zero-client/src/client/log-options.ts
14505
14521
  var LevelFilterLogSink = class {
@@ -15451,11 +15467,12 @@ var ZeroRep = class {
15451
15467
  this.#store = store;
15452
15468
  this.#context.processChanges(void 0, hash2, diffs);
15453
15469
  }
15454
- getTxData = (desiredHead, readOptions) => {
15470
+ getTxData = (reason, desiredHead, readOptions) => {
15455
15471
  if (!this.#customMutatorsEnabled) {
15456
15472
  return;
15457
15473
  }
15458
15474
  return this.#ivmMain.forkToHead(
15475
+ reason,
15459
15476
  must(this.#store),
15460
15477
  desiredHead,
15461
15478
  readOptions
@@ -15656,45 +15673,19 @@ var Zero = class {
15656
15673
  [CRUD_MUTATION_NAME]: makeCRUDMutator(schema)
15657
15674
  };
15658
15675
  this.#ivmMain = new IVMSourceBranch(schema.tables);
15659
- function assertUnique(key) {
15660
- assert(
15661
- replicacheMutators[key] === void 0,
15662
- `A mutator, or mutator namespace, has already been defined for ${key}`
15663
- );
15664
- }
15665
15676
  const lc = new LogContext4(logOptions.logLevel, {}, logOptions.logSink);
15666
- if (options.mutators) {
15667
- for (const [namespaceOrKey, mutatorOrMutators] of Object.entries(
15668
- options.mutators
15677
+ for (const [namespace, mutatorsForNamespace] of Object.entries(
15678
+ options.mutators ?? {}
15679
+ )) {
15680
+ for (const [name, mutator] of Object.entries(
15681
+ mutatorsForNamespace
15669
15682
  )) {
15670
- if (typeof mutatorOrMutators === "function") {
15671
- const key = namespaceOrKey;
15672
- assertUnique(key);
15673
- replicacheMutators[key] = makeReplicacheMutator(
15674
- lc,
15675
- mutatorOrMutators,
15676
- schema,
15677
- slowMaterializeThreshold
15678
- );
15679
- continue;
15680
- }
15681
- if (typeof mutatorOrMutators === "object") {
15682
- for (const [name, mutator] of Object.entries(mutatorOrMutators)) {
15683
- const key = customMutatorKey(
15684
- namespaceOrKey,
15685
- name
15686
- );
15687
- assertUnique(key);
15688
- replicacheMutators[key] = makeReplicacheMutator(
15689
- lc,
15690
- mutator,
15691
- schema,
15692
- slowMaterializeThreshold
15693
- );
15694
- }
15695
- continue;
15696
- }
15697
- unreachable(mutatorOrMutators);
15683
+ replicacheMutators[customMutatorKey(namespace, name)] = makeReplicacheMutator(
15684
+ lc,
15685
+ mutator,
15686
+ schema,
15687
+ slowMaterializeThreshold
15688
+ );
15698
15689
  }
15699
15690
  }
15700
15691
  this.storageKey = storageKey ?? "";
@@ -15768,23 +15759,19 @@ var Zero = class {
15768
15759
  if (options.mutators) {
15769
15760
  mutate = {};
15770
15761
  mutateBatch = void 0;
15771
- for (const [namespaceOrKey, mutatorsOrMutator] of Object.entries(
15772
- options.mutators
15762
+ }
15763
+ for (const [namespace, mutatorsForNamespace] of Object.entries(
15764
+ options.mutators ?? {}
15765
+ )) {
15766
+ let existing = mutate[namespace];
15767
+ if (existing === void 0) {
15768
+ existing = {};
15769
+ mutate[namespace] = existing;
15770
+ }
15771
+ for (const name of Object.keys(
15772
+ mutatorsForNamespace
15773
15773
  )) {
15774
- if (typeof mutatorsOrMutator === "function") {
15775
- mutate[namespaceOrKey] = must(rep.mutate[namespaceOrKey]);
15776
- continue;
15777
- }
15778
- let existing = mutate[namespaceOrKey];
15779
- if (existing === void 0) {
15780
- existing = {};
15781
- mutate[namespaceOrKey] = existing;
15782
- }
15783
- for (const name of Object.keys(mutatorsOrMutator)) {
15784
- existing[name] = must(
15785
- rep.mutate[customMutatorKey(namespaceOrKey, name)]
15786
- );
15787
- }
15774
+ existing[name] = must(rep.mutate[customMutatorKey(namespace, name)]);
15788
15775
  }
15789
15776
  }
15790
15777
  this.mutate = mutate;
@@ -16804,4 +16791,4 @@ export {
16804
16791
  escapeLike,
16805
16792
  Zero
16806
16793
  };
16807
- //# sourceMappingURL=chunk-UZE45UK4.js.map
16794
+ //# sourceMappingURL=chunk-VEVC5RHF.js.map