@rocicorp/zero 0.17.2025031200 → 0.17.2025031300

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 (90) hide show
  1. package/out/advanced.js +1 -1
  2. package/out/{chunk-2Y24MEEQ.js → chunk-5X3DESC6.js} +1 -1
  3. package/out/{chunk-2Y24MEEQ.js.map → chunk-5X3DESC6.js.map} +1 -1
  4. package/out/{chunk-6CQ6CUML.js → chunk-7ARRNDLF.js} +37 -15
  5. package/out/{chunk-6CQ6CUML.js.map → chunk-7ARRNDLF.js.map} +3 -3
  6. package/out/{chunk-VNV6U5BQ.js → chunk-APXCO5Z2.js} +296 -134
  7. package/out/chunk-APXCO5Z2.js.map +7 -0
  8. package/out/react.js +7 -1
  9. package/out/react.js.map +2 -2
  10. package/out/replicache/src/dag/lazy-store.d.ts +2 -2
  11. package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
  12. package/out/replicache/src/db/write.d.ts +1 -1
  13. package/out/replicache/src/db/write.d.ts.map +1 -1
  14. package/out/replicache/src/persist/persist.d.ts +2 -1
  15. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  16. package/out/replicache/src/persist/refresh.d.ts +7 -1
  17. package/out/replicache/src/persist/refresh.d.ts.map +1 -1
  18. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  19. package/out/replicache/src/replicache-options.d.ts +10 -5
  20. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  21. package/out/replicache/src/sync/pull.d.ts +2 -0
  22. package/out/replicache/src/sync/pull.d.ts.map +1 -1
  23. package/out/solid.js +16 -8
  24. package/out/solid.js.map +2 -2
  25. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +3 -0
  26. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  27. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
  28. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  29. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  30. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +1 -0
  31. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  32. package/out/zero-client/src/client/context.d.ts +7 -3
  33. package/out/zero-client/src/client/context.d.ts.map +1 -1
  34. package/out/zero-client/src/client/custom.d.ts +5 -4
  35. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  36. package/out/zero-client/src/client/ivm-branch.d.ts +6 -3
  37. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  38. package/out/zero-client/src/client/query-manager.d.ts +1 -0
  39. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  40. package/out/zero-client/src/client/zero-rep.d.ts +15 -0
  41. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -0
  42. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  43. package/out/zero-pg/src/custom.d.ts +2 -1
  44. package/out/zero-pg/src/custom.d.ts.map +1 -1
  45. package/out/zero-pg/src/custom.js +4 -1
  46. package/out/zero-pg/src/custom.js.map +1 -1
  47. package/out/zero-pg/src/query.d.ts +4 -2
  48. package/out/zero-pg/src/query.d.ts.map +1 -1
  49. package/out/zero-pg/src/query.js +3 -0
  50. package/out/zero-pg/src/query.js.map +1 -1
  51. package/out/zero-pg/src/web.d.ts +2 -1
  52. package/out/zero-pg/src/web.d.ts.map +1 -1
  53. package/out/zero-pg/src/web.js +59 -35
  54. package/out/zero-pg/src/web.js.map +1 -1
  55. package/out/zero-react/src/use-query.d.ts.map +1 -1
  56. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  57. package/out/zero.js +3 -3
  58. package/out/zql/src/ivm/memory-source.d.ts +3 -3
  59. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  60. package/out/zql/src/ivm/memory-source.js +16 -0
  61. package/out/zql/src/ivm/memory-source.js.map +1 -1
  62. package/out/zql/src/ivm/source.d.ts +5 -1
  63. package/out/zql/src/ivm/source.d.ts.map +1 -1
  64. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  65. package/out/zql/src/ivm/view-apply-change.js +40 -8
  66. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  67. package/out/zql/src/query/expression.d.ts +20 -0
  68. package/out/zql/src/query/expression.d.ts.map +1 -1
  69. package/out/zql/src/query/expression.js +1 -1
  70. package/out/zql/src/query/expression.js.map +1 -1
  71. package/out/zql/src/query/query-impl.d.ts +3 -0
  72. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  73. package/out/zql/src/query/query-impl.js +3 -0
  74. package/out/zql/src/query/query-impl.js.map +1 -1
  75. package/out/zql/src/query/query-internal.d.ts +1 -0
  76. package/out/zql/src/query/query-internal.d.ts.map +1 -1
  77. package/out/zql/src/query/static-query.d.ts +2 -0
  78. package/out/zql/src/query/static-query.d.ts.map +1 -1
  79. package/out/zql/src/query/static-query.js +3 -0
  80. package/out/zql/src/query/static-query.js.map +1 -1
  81. package/out/zql/src/query/ttl.d.ts +1 -0
  82. package/out/zql/src/query/ttl.d.ts.map +1 -1
  83. package/out/zql/src/query/ttl.js +22 -0
  84. package/out/zql/src/query/ttl.js.map +1 -1
  85. package/out/zqlite/src/table-source.d.ts +3 -3
  86. package/out/zqlite/src/table-source.d.ts.map +1 -1
  87. package/out/zqlite/src/table-source.js +17 -0
  88. package/out/zqlite/src/table-source.js.map +1 -1
  89. package/package.json +1 -1
  90. package/out/chunk-VNV6U5BQ.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-6CQ6CUML.js";
4
+ } from "./chunk-7ARRNDLF.js";
5
5
  import "./chunk-424PT5DM.js";
6
6
  export {
7
7
  applyChange
@@ -42,4 +42,4 @@ export {
42
42
  parseTTL,
43
43
  compareTTL
44
44
  };
45
- //# sourceMappingURL=chunk-2Y24MEEQ.js.map
45
+ //# sourceMappingURL=chunk-5X3DESC6.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../zql/src/query/ttl.ts", "../../shared/src/has-own.ts"],
4
- "sourcesContent": ["export type TimeUnit = 's' | 'm' | 'h' | 'd' | 'y';\n\n/**\n * Time To Live. This is used for query expiration.\n * - `forever` means the query will never expire.\n * - `none` means the query will expire immediately.\n * - A number means the query will expire after that many milliseconds.\n * - A negative number means the query will never expire, this is same as 'forever'.\n * - A string like `1s` means the query will expire after that many seconds.\n * - A string like `1m` means the query will expire after that many minutes.\n * - A string like `1h` means the query will expire after that many hours.\n * - A string like `1d` means the query will expire after that many days.\n * - A string like `1y` means the query will expire after that many years.\n */\nexport type TTL = `${number}${TimeUnit}` | 'forever' | 'none' | number;\n\nexport const DEFAULT_TTL: TTL = 'none';\n\nconst multiplier = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n y: 365 * 24 * 60 * 60 * 1000,\n} as const;\n\nexport function parseTTL(ttl: TTL): number {\n if (typeof ttl === 'number') {\n return Number.isNaN(ttl) ? 0 : !Number.isFinite(ttl) || ttl < 0 ? -1 : ttl;\n }\n if (ttl === 'none') {\n return 0;\n }\n if (ttl === 'forever') {\n return -1;\n }\n const multi = multiplier[ttl[ttl.length - 1] as TimeUnit];\n return Number(ttl.slice(0, -1)) * multi;\n}\n\nexport function compareTTL(a: TTL, b: TTL): number {\n const ap = parseTTL(a);\n const bp = parseTTL(b);\n if (ap === -1 && bp !== -1) {\n return 1;\n }\n if (ap !== -1 && bp === -1) {\n return -1;\n }\n return ap - bp;\n}\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\nconst objectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Object.hasOwn polyfill\n */\nexport const hasOwn: (object: any, key: PropertyKey) => boolean =\n (Object as any).hasOwn ||\n ((object, key) => objectPrototypeHasOwnProperty.call(object, key));\n"],
4
+ "sourcesContent": ["export type TimeUnit = 's' | 'm' | 'h' | 'd' | 'y';\n\n/**\n * Time To Live. This is used for query expiration.\n * - `forever` means the query will never expire.\n * - `none` means the query will expire immediately.\n * - A number means the query will expire after that many milliseconds.\n * - A negative number means the query will never expire, this is same as 'forever'.\n * - A string like `1s` means the query will expire after that many seconds.\n * - A string like `1m` means the query will expire after that many minutes.\n * - A string like `1h` means the query will expire after that many hours.\n * - A string like `1d` means the query will expire after that many days.\n * - A string like `1y` means the query will expire after that many years.\n */\nexport type TTL = `${number}${TimeUnit}` | 'forever' | 'none' | number;\n\nexport const DEFAULT_TTL: TTL = 'none';\n\nconst multiplier = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n y: 365 * 24 * 60 * 60 * 1000,\n} as const;\n\nexport function parseTTL(ttl: TTL): number {\n if (typeof ttl === 'number') {\n return Number.isNaN(ttl) ? 0 : !Number.isFinite(ttl) || ttl < 0 ? -1 : ttl;\n }\n if (ttl === 'none') {\n return 0;\n }\n if (ttl === 'forever') {\n return -1;\n }\n const multi = multiplier[ttl[ttl.length - 1] as TimeUnit];\n return Number(ttl.slice(0, -1)) * multi;\n}\n\nexport function compareTTL(a: TTL, b: TTL): number {\n const ap = parseTTL(a);\n const bp = parseTTL(b);\n if (ap === -1 && bp !== -1) {\n return 1;\n }\n if (ap !== -1 && bp === -1) {\n return -1;\n }\n return ap - bp;\n}\n\nexport function normalizeTTL(ttl: TTL): string | number {\n if (typeof ttl === 'string') {\n return ttl;\n }\n\n if (ttl < 0) {\n return 'forever';\n }\n\n if (ttl === 0) {\n return 'none';\n }\n\n let shortest = ttl.toString();\n const lengthOfNumber = shortest.length;\n for (const unit of ['y', 'd', 'h', 'm', 's'] as const) {\n const multi = multiplier[unit];\n const value = ttl / multi;\n const candidate = `${value}${unit}`;\n if (candidate.length < shortest.length) {\n shortest = candidate;\n }\n }\n\n return shortest.length < lengthOfNumber ? shortest : ttl;\n}\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\nconst objectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Object.hasOwn polyfill\n */\nexport const hasOwn: (object: any, key: PropertyKey) => boolean =\n (Object as any).hasOwn ||\n ((object, key) => objectPrototypeHasOwnProperty.call(object, key));\n"],
5
5
  "mappings": ";AAgBO,IAAM,cAAmB;AAEhC,IAAM,aAAa;AAAA,EACjB,GAAG;AAAA,EACH,GAAG,KAAK;AAAA,EACR,GAAG,KAAK,KAAK;AAAA,EACb,GAAG,KAAK,KAAK,KAAK;AAAA,EAClB,GAAG,MAAM,KAAK,KAAK,KAAK;AAC1B;AAEO,SAAS,SAAS,KAAkB;AACzC,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,OAAO,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK;AAAA,EACzE;AACA,MAAI,QAAQ,QAAQ;AAClB,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW;AACrB,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,WAAW,IAAI,IAAI,SAAS,CAAC,CAAa;AACxD,SAAO,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI;AACpC;AAEO,SAAS,WAAW,GAAQ,GAAgB;AACjD,QAAM,KAAK,SAAS,CAAC;AACrB,QAAM,KAAK,SAAS,CAAC;AACrB,MAAI,OAAO,MAAM,OAAO,IAAI;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,OAAO,IAAI;AAC1B,WAAO;AAAA,EACT;AACA,SAAO,KAAK;AACd;;;ACjDA,IAAM,gCAAgC,OAAO,UAAU;AAKhD,IAAM,SACV,OAAe,WACf,CAAC,QAAQ,QAAQ,8BAA8B,KAAK,QAAQ,GAAG;",
6
6
  "names": []
7
7
  }
@@ -278,14 +278,19 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
278
278
  }
279
279
  case "edit": {
280
280
  if (singular) {
281
- assertObject(parentEntry[relationship]);
282
- parentEntry[relationship] = {
283
- ...parentEntry[relationship],
281
+ const existing = parentEntry[relationship];
282
+ assertEntry(existing);
283
+ const rc = must(refCountMap.get(existing));
284
+ const newEntry = {
285
+ ...existing,
284
286
  ...change.node.row
285
287
  };
288
+ refCountMap.set(newEntry, rc);
289
+ refCountMap.delete(existing);
290
+ parentEntry[relationship] = newEntry;
286
291
  } else {
287
292
  const view = parentEntry[relationship];
288
- assertArray(view);
293
+ assertEntryList(view);
289
294
  if (schema.compareRows(change.oldNode.row, change.node.row) === 0) {
290
295
  const { pos, found } = binarySearch(
291
296
  view,
@@ -309,23 +314,34 @@ function applyChange(parentEntry, change, schema, relationship, format, refCount
309
314
  );
310
315
  assert(found, "node does not exists");
311
316
  const oldEntry = view[pos];
312
- view.splice(pos, 1);
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
+ }
313
324
  {
314
325
  const { pos: pos2, found: found2 } = binarySearch(
315
326
  view,
316
327
  change.node.row,
317
328
  schema.compareRows
318
329
  );
319
- assert(!found2, "node already exists");
320
- view.splice(
321
- pos2,
322
- 0,
323
- makeEntryPreserveRelationships(
324
- change.node.row,
325
- oldEntry,
326
- format.relationships
327
- )
330
+ let rc2 = 1;
331
+ const newEntry = makeEntryPreserveRelationships(
332
+ change.node.row,
333
+ oldEntry,
334
+ format.relationships
328
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);
329
345
  }
330
346
  }
331
347
  }
@@ -364,6 +380,12 @@ function getChildEntryList(parentEntry, relationship) {
364
380
  assertArray(view);
365
381
  return view;
366
382
  }
383
+ function assertEntryList(v) {
384
+ assertArray(v);
385
+ }
386
+ function assertEntry(v) {
387
+ assertObject(v);
388
+ }
367
389
 
368
390
  export {
369
391
  assert,
@@ -383,4 +405,4 @@ export {
383
405
  drainStreams,
384
406
  applyChange
385
407
  };
386
- //# sourceMappingURL=chunk-6CQ6CUML.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 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 assertObject(parentEntry[relationship]);\n // @ts-expect-error parentEntry is readonly\n parentEntry[relationship] = {\n ...parentEntry[relationship],\n ...change.node.row,\n };\n } else {\n const view = parentEntry[relationship] as EntryList | undefined;\n assertArray(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 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 view.splice(pos, 1);\n\n // Insert\n {\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n assert(!found, 'node already exists');\n view.splice(\n pos,\n 0,\n makeEntryPreserveRelationships(\n change.node.row,\n oldEntry,\n format.relationships,\n ),\n );\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"],
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,cAAM,OAAO,kBAAkB,aAAa,YAAY;AACxD,cAAM,EAAC,KAAK,MAAK,IAAI,aAAa,MAAM,UAAU,OAAO,WAAW;AAEpE,YAAI,cAAc;AAClB,YAAI,KAAK;AACT,YAAI,OAAO;AACT,wBAAc;AACd,eAAK,KAAK,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI;AACxC,sBAAY,OAAO,KAAK,GAAG,CAAC;AAAA,QAC9B;AAGA,aAAK,OAAO,KAAK,aAAa,QAAQ;AACtC,oBAAY,IAAI,UAAU,EAAE;AAAA,MAC9B;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,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,cAAM,KAAK,KAAK,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC;AAC1C,YAAI,OAAO,GAAG;AACZ,sBAAY,OAAO,KAAK,GAAG,CAAC;AAE5B,eAAK,OAAO,KAAK,CAAC;AAAA,QACpB,OAAO;AACL,sBAAY,IAAI,KAAK,GAAG,GAAG,KAAK,CAAC;AAAA,QACnC;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,qBAAa,YAAY,YAAY,CAAC;AAEtC,oBAAY,YAAY,IAAI;AAAA,UAC1B,GAAG,YAAY,YAAY;AAAA,UAC3B,GAAG,OAAO,KAAK;AAAA,QACjB;AAAA,MACF,OAAO;AACL,cAAM,OAAO,YAAY,YAAY;AACrC,oBAAY,IAAI;AAEhB,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,sBAAsB;AACpC,gBAAM,KAAK,KAAK,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC;AAC1C,sBAAY,OAAO,KAAK,GAAG,CAAC;AAC5B,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,EAAC,KAAK,MAAK,IAAI;AAAA,YACnB;AAAA,YACA,OAAO,QAAQ;AAAA,YACf,OAAO;AAAA,UACT;AACA,iBAAO,OAAO,sBAAsB;AACpC,gBAAM,WAAW,KAAK,GAAG;AACzB,eAAK,OAAO,KAAK,CAAC;AAGlB;AACE,kBAAM,EAAC,KAAAC,MAAK,OAAAC,OAAK,IAAI;AAAA,cACnB;AAAA,cACA,OAAO,KAAK;AAAA,cACZ,OAAO;AAAA,YACT;AACA,mBAAO,CAACA,QAAO,qBAAqB;AACpC,iBAAK;AAAA,cACHD;AAAA,cACA;AAAA,cACA;AAAA,gBACE,OAAO,KAAK;AAAA,gBACZ;AAAA,gBACA,OAAO;AAAA,cACT;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA;AACE,kBAAY,MAAM;AAAA,EACtB;AACF;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;",
6
- "names": ["node", "relationship", "pos", "found"]
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
  }