@rocicorp/zero 0.24.2025100802 → 0.24.2025101200

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 (203) hide show
  1. package/out/ast-to-zql/src/ast-to-zql.js +1 -1
  2. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  3. package/out/{chunk-UEUKOYBK.js → chunk-5J6ROZSO.js} +4527 -167
  4. package/out/chunk-5J6ROZSO.js.map +7 -0
  5. package/out/{chunk-7XZMNWUY.js → chunk-6AP73APB.js} +15 -8
  6. package/out/chunk-6AP73APB.js.map +7 -0
  7. package/out/chunk-HLJ3FQU5.js +4122 -0
  8. package/out/chunk-HLJ3FQU5.js.map +7 -0
  9. package/out/{lazy-inspector-T5SHTECY.js → lazy-inspector-YKNSCAI3.js} +21 -3
  10. package/out/lazy-inspector-YKNSCAI3.js.map +7 -0
  11. package/out/react-native.js +1 -71
  12. package/out/react-native.js.map +4 -4
  13. package/out/react.js +2 -2
  14. package/out/replicache/src/btree/read.d.ts.map +1 -1
  15. package/out/replicache/src/btree/write.d.ts.map +1 -1
  16. package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
  17. package/out/replicache/src/persist/gather-not-cached-visitor.d.ts.map +1 -1
  18. package/out/shared/src/size-of-value.d.ts.map +1 -0
  19. package/out/solid.js +7 -7
  20. package/out/solid.js.map +2 -2
  21. package/out/zero/package.json +8 -7
  22. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  23. package/out/zero-cache/src/config/zero-config.js +1 -0
  24. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  25. package/out/zero-cache/src/server/inspector-delegate.d.ts +10 -0
  26. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  27. package/out/zero-cache/src/server/inspector-delegate.js +33 -0
  28. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  29. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  30. package/out/zero-cache/src/server/syncer.js +8 -3
  31. package/out/zero-cache/src/server/syncer.js.map +1 -1
  32. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  33. package/out/zero-cache/src/services/analyze.js +2 -2
  34. package/out/zero-cache/src/services/analyze.js.map +1 -1
  35. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  36. package/out/zero-cache/src/services/change-source/pg/change-source.js +1 -1
  37. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  38. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +1 -1
  39. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  40. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +5 -1
  41. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  42. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +6 -5
  43. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  44. package/out/zero-cache/src/services/change-streamer/storer.d.ts +1 -1
  45. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/change-streamer/storer.js +26 -22
  47. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  48. package/out/zero-cache/src/services/mutagen/pusher.d.ts +44 -36
  49. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  50. package/out/zero-cache/src/services/run-ast.d.ts +21 -0
  51. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -0
  52. package/out/zero-cache/src/services/run-ast.js +91 -0
  53. package/out/zero-cache/src/services/run-ast.js.map +1 -0
  54. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +10 -0
  55. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -0
  56. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +95 -0
  57. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -0
  58. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +6 -5
  59. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  60. package/out/zero-cache/src/services/view-syncer/view-syncer.js +59 -115
  61. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  62. package/out/zero-client/src/client/inspector/inspector.d.ts +4 -0
  63. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  64. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +4 -1
  65. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  66. package/out/zero-client/src/client/zero.d.ts +4 -4
  67. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  68. package/out/zero-client/src/mod.d.ts +1 -1
  69. package/out/zero-client/src/mod.d.ts.map +1 -1
  70. package/out/zero-events/src/index.d.ts +4 -6
  71. package/out/zero-events/src/index.d.ts.map +1 -1
  72. package/out/zero-events/src/index.js +1 -27
  73. package/out/zero-events/src/index.js.map +1 -1
  74. package/out/zero-events/src/status.d.ts +43 -111
  75. package/out/zero-events/src/status.d.ts.map +1 -1
  76. package/out/zero-events/src/status.js +2 -73
  77. package/out/zero-events/src/status.js.map +1 -1
  78. package/out/zero-events/src/util.d.ts +26 -0
  79. package/out/zero-events/src/util.d.ts.map +1 -0
  80. package/out/zero-events/src/util.js +2 -0
  81. package/out/zero-events/src/util.js.map +1 -0
  82. package/out/zero-protocol/src/ast.d.ts +2 -1
  83. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  84. package/out/zero-protocol/src/ast.js +1 -0
  85. package/out/zero-protocol/src/ast.js.map +1 -1
  86. package/out/zero-protocol/src/down.d.ts +5 -0
  87. package/out/zero-protocol/src/down.d.ts.map +1 -1
  88. package/out/zero-protocol/src/inspect-down.d.ts +17 -0
  89. package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
  90. package/out/zero-protocol/src/inspect-down.js +5 -1
  91. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  92. package/out/zero-protocol/src/inspect-up.d.ts +18 -6
  93. package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
  94. package/out/zero-protocol/src/inspect-up.js +6 -1
  95. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  96. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  97. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  98. package/out/zero-protocol/src/protocol-version.js +2 -1
  99. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  100. package/out/zero-protocol/src/push.d.ts +1 -1
  101. package/out/zero-protocol/src/push.d.ts.map +1 -1
  102. package/out/zero-protocol/src/up.d.ts +5 -2
  103. package/out/zero-protocol/src/up.d.ts.map +1 -1
  104. package/out/zero-react-native/src/mod.d.ts +0 -1
  105. package/out/zero-react-native/src/mod.d.ts.map +1 -1
  106. package/out/zero-schema/src/builder/schema-builder.d.ts +3 -25
  107. package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
  108. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  109. package/out/zero-schema/src/name-mapper.d.ts +2 -19
  110. package/out/zero-schema/src/name-mapper.d.ts.map +1 -1
  111. package/out/zero-schema/src/name-mapper.js +2 -44
  112. package/out/zero-schema/src/name-mapper.js.map +1 -1
  113. package/out/zero-schema/src/permissions.d.ts +1 -0
  114. package/out/zero-schema/src/permissions.d.ts.map +1 -1
  115. package/out/zero-schema/src/schema-config.d.ts +1 -1
  116. package/out/zero-schema/src/table-schema.d.ts +3 -55
  117. package/out/zero-schema/src/table-schema.d.ts.map +1 -1
  118. package/out/zero-schema/src/table-schema.js +0 -6
  119. package/out/zero-schema/src/table-schema.js.map +1 -1
  120. package/out/zero-server/src/process-mutations.d.ts +1 -1
  121. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  122. package/out/zero-server/src/query.d.ts +2 -2
  123. package/out/zero-server/src/query.d.ts.map +1 -1
  124. package/out/zero-server/src/query.js +2 -1
  125. package/out/zero-server/src/query.js.map +1 -1
  126. package/out/zero-server/src/zql-database.d.ts +1 -1
  127. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  128. package/out/zero-server/src/zql-database.js +10 -0
  129. package/out/zero-server/src/zql-database.js.map +1 -1
  130. package/out/zero-solid/src/use-query.d.ts +3 -1
  131. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  132. package/out/zero-solid/src/use-zero.d.ts +4 -1
  133. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  134. package/out/zero-types/src/format.d.ts +11 -0
  135. package/out/zero-types/src/format.d.ts.map +1 -0
  136. package/out/zero-types/src/format.js +5 -0
  137. package/out/zero-types/src/format.js.map +1 -0
  138. package/out/zero-types/src/name-mapper.d.ts +19 -0
  139. package/out/zero-types/src/name-mapper.d.ts.map +1 -0
  140. package/out/zero-types/src/name-mapper.js +45 -0
  141. package/out/zero-types/src/name-mapper.js.map +1 -0
  142. package/out/zero-types/src/schema-value.d.ts +36 -0
  143. package/out/zero-types/src/schema-value.d.ts.map +1 -0
  144. package/out/zero-types/src/schema-value.js +2 -0
  145. package/out/zero-types/src/schema-value.js.map +1 -0
  146. package/out/zero-types/src/schema.d.ts +54 -0
  147. package/out/zero-types/src/schema.d.ts.map +1 -0
  148. package/out/zero-types/src/schema.js +2 -0
  149. package/out/zero-types/src/schema.js.map +1 -0
  150. package/out/zero.js +4 -5
  151. package/out/zql/src/ivm/default-format.d.ts +2 -0
  152. package/out/zql/src/ivm/default-format.d.ts.map +1 -0
  153. package/out/zql/src/ivm/default-format.js +2 -0
  154. package/out/zql/src/ivm/default-format.js.map +1 -0
  155. package/out/zql/src/ivm/memory-source.d.ts +2 -2
  156. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  157. package/out/zql/src/ivm/memory-source.js +2 -2
  158. package/out/zql/src/ivm/memory-source.js.map +1 -1
  159. package/out/zql/src/ivm/schema.d.ts +1 -1
  160. package/out/zql/src/ivm/schema.d.ts.map +1 -1
  161. package/out/zql/src/ivm/view.d.ts +3 -5
  162. package/out/zql/src/ivm/view.d.ts.map +1 -1
  163. package/out/zql/src/mutate/custom.d.ts +2 -2
  164. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  165. package/out/zql/src/mutate/custom.js.map +1 -1
  166. package/out/zql/src/query/expression.d.ts +1 -1
  167. package/out/zql/src/query/expression.d.ts.map +1 -1
  168. package/out/zql/src/query/named.d.ts +2 -3
  169. package/out/zql/src/query/named.d.ts.map +1 -1
  170. package/out/zql/src/query/named.js.map +1 -1
  171. package/out/zql/src/query/query-delegate.d.ts +1 -1
  172. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  173. package/out/zql/src/query/query-impl.d.ts +4 -10
  174. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  175. package/out/zql/src/query/query-impl.js +12 -19
  176. package/out/zql/src/query/query-impl.js.map +1 -1
  177. package/out/zql/src/query/query.d.ts +7 -5
  178. package/out/zql/src/query/query.d.ts.map +1 -1
  179. package/out/zql/src/query/query.js.map +1 -1
  180. package/out/zql/src/query/static-query.d.ts +1 -1
  181. package/out/zql/src/query/static-query.d.ts.map +1 -1
  182. package/out/zql/src/query/static-query.js +2 -1
  183. package/out/zql/src/query/static-query.js.map +1 -1
  184. package/out/zqlite/src/explain-queries.d.ts +4 -0
  185. package/out/zqlite/src/explain-queries.d.ts.map +1 -0
  186. package/out/zqlite/src/explain-queries.js +18 -0
  187. package/out/zqlite/src/explain-queries.js.map +1 -0
  188. package/out/zqlite/src/mod.d.ts +2 -1
  189. package/out/zqlite/src/mod.d.ts.map +1 -1
  190. package/out/zqlite/src/mod.js +2 -1
  191. package/out/zqlite/src/mod.js.map +1 -1
  192. package/package.json +8 -7
  193. package/out/chunk-7XZMNWUY.js.map +0 -7
  194. package/out/chunk-INWZY4XP.js +0 -8496
  195. package/out/chunk-INWZY4XP.js.map +0 -7
  196. package/out/chunk-UEUKOYBK.js.map +0 -7
  197. package/out/lazy-inspector-T5SHTECY.js.map +0 -7
  198. package/out/replicache/src/kv/op-sqlite/store.d.ts +0 -14
  199. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +0 -1
  200. package/out/replicache/src/kv/op-sqlite/types.d.ts +0 -13
  201. package/out/replicache/src/kv/op-sqlite/types.d.ts.map +0 -1
  202. package/out/replicache/src/size-of-value.d.ts.map +0 -1
  203. /package/out/{replicache → shared}/src/size-of-value.d.ts +0 -0
@@ -11,16 +11,20 @@ import {
11
11
  ClientStateNotFoundError,
12
12
  DD31,
13
13
  DEFAULT_HEAD_NAME,
14
+ DEFAULT_PRELOAD_TTL_MS,
15
+ DEFAULT_TTL_MS,
14
16
  DiffsMap,
15
17
  ENTITIES_KEY_PREFIX,
16
18
  GOT_QUERIES_KEY_PREFIX,
17
19
  Inspector,
18
20
  Latest,
19
21
  MUTATIONS_KEY_PREFIX,
22
+ SUBQ_PREFIX,
20
23
  TDigest,
21
24
  V6,
22
25
  V7,
23
26
  addDiffsForIndexes,
27
+ areEqual,
24
28
  assertClientV6,
25
29
  assertCookie,
26
30
  assertHasClientState,
@@ -28,7 +32,6 @@ import {
28
32
  assertJSONObject,
29
33
  assertJSONValue,
30
34
  assertLocalMetaDD31,
31
- assertOrderingIncludesPK,
32
35
  assertRefs,
33
36
  assertSnapshotCommitDD31,
34
37
  assertSnapshotMetaDD31,
@@ -48,24 +51,16 @@ import {
48
51
  compareCookies,
49
52
  compareCookiesForSnapshots,
50
53
  compareTTL,
51
- compareValues,
52
- constraintMatchesPrimaryKey,
53
- constraintMatchesRow,
54
54
  createChunk,
55
- createPredicate,
56
55
  decodeIndexKey,
57
56
  deepEqual,
58
- delegateSymbol,
59
57
  desiredQueriesPrefixForClient,
60
58
  diff,
61
59
  diff2,
62
60
  diffCommits,
63
61
  disableClientGroup,
64
- emptyFunction,
65
62
  emptyHash,
66
- emptyObject,
67
63
  encodeIndexScanKey,
68
- filterPush,
69
64
  getClientGroup,
70
65
  getClientGroupForClient,
71
66
  getClientGroupIDForClient,
@@ -75,8 +70,6 @@ import {
75
70
  getSizeOfValue,
76
71
  h64,
77
72
  hasClientState,
78
- hashOfAST,
79
- hashOfNameAndArgs,
80
73
  initClientV6,
81
74
  inspectDownMessageSchema,
82
75
  isLocalMetaDD31,
@@ -88,24 +81,21 @@ import {
88
81
  localMutationsDD31,
89
82
  localMutationsGreaterThan,
90
83
  makeClientID,
91
- makeComparator,
92
84
  mapAST,
93
85
  mapAllEntries,
94
86
  mapEntries,
95
- materialize,
87
+ mergeIterables,
96
88
  must,
97
89
  mustGetChunk,
98
90
  mustGetClient,
99
91
  mustGetHeadHash,
100
92
  nanoid,
101
- newQuery,
102
93
  newRandomHash,
103
94
  newWriteLocal,
104
95
  newWriteSnapshotDD31,
105
96
  normalizeAST,
106
97
  once,
107
98
  parse,
108
- primaryKeyConstraintFromFilters,
109
99
  primaryKeySchema,
110
100
  primaryKeyValueRecordSchema,
111
101
  readFromDefaultHead,
@@ -122,23 +112,22 @@ import {
122
112
  sourceNameFromKey,
123
113
  stringCompare,
124
114
  test,
125
- throwOutput,
126
115
  toDesiredQueriesKey,
127
116
  toGotQueriesKey,
128
117
  toMutationResponseKey,
129
118
  toPrimaryKeyString,
130
- transformFilters,
119
+ toStaticParam,
131
120
  using,
132
121
  valita_exports,
133
- valuesEqual,
134
122
  withRead,
135
123
  withWrite,
136
124
  withWriteNoImplicitCommit,
137
125
  wrapIterable
138
- } from "./chunk-INWZY4XP.js";
126
+ } from "./chunk-HLJ3FQU5.js";
139
127
  import {
140
128
  assert,
141
129
  assertArray,
130
+ assertBoolean,
142
131
  assertNotNull,
143
132
  assertNumber,
144
133
  assertObject,
@@ -1859,6 +1848,334 @@ function clientSchemaFrom(schema) {
1859
1848
  return { clientSchema, hash };
1860
1849
  }
1861
1850
 
1851
+ // ../zql/src/ivm/data.ts
1852
+ import { compareUTF8 } from "compare-utf8";
1853
+ function compareValues(a, b) {
1854
+ a = normalizeUndefined(a);
1855
+ b = normalizeUndefined(b);
1856
+ if (a === b) {
1857
+ return 0;
1858
+ }
1859
+ if (a === null) {
1860
+ return -1;
1861
+ }
1862
+ if (b === null) {
1863
+ return 1;
1864
+ }
1865
+ if (typeof a === "boolean") {
1866
+ assertBoolean(b);
1867
+ return a ? 1 : -1;
1868
+ }
1869
+ if (typeof a === "number") {
1870
+ assertNumber(b);
1871
+ return a - b;
1872
+ }
1873
+ if (typeof a === "string") {
1874
+ assertString(b);
1875
+ return compareUTF8(a, b);
1876
+ }
1877
+ throw new Error(`Unsupported type: ${a}`);
1878
+ }
1879
+ function normalizeUndefined(v) {
1880
+ return v ?? null;
1881
+ }
1882
+ function makeComparator(order, reverse) {
1883
+ return (a, b) => {
1884
+ for (const ord of order) {
1885
+ const field = ord[0];
1886
+ const comp = compareValues(a[field], b[field]);
1887
+ if (comp !== 0) {
1888
+ const result = ord[1] === "asc" ? comp : -comp;
1889
+ return reverse ? -result : result;
1890
+ }
1891
+ }
1892
+ return 0;
1893
+ };
1894
+ }
1895
+ function valuesEqual(a, b) {
1896
+ if (a == null || b == null) {
1897
+ return false;
1898
+ }
1899
+ return a === b;
1900
+ }
1901
+ function drainStreams(node) {
1902
+ for (const stream of Object.values(node.relationships)) {
1903
+ for (const node2 of stream()) {
1904
+ drainStreams(node2);
1905
+ }
1906
+ }
1907
+ }
1908
+
1909
+ // ../zql/src/ivm/view-apply-change.ts
1910
+ var refCountSymbol = Symbol("rc");
1911
+ var idSymbol = Symbol("id");
1912
+ function applyChange(parentEntry, change, schema, relationship, format, withIDs = false) {
1913
+ if (schema.isHidden) {
1914
+ switch (change.type) {
1915
+ case "add":
1916
+ case "remove":
1917
+ for (const [relationship2, children] of Object.entries(
1918
+ change.node.relationships
1919
+ )) {
1920
+ const childSchema = must(schema.relationships[relationship2]);
1921
+ for (const node of children()) {
1922
+ applyChange(
1923
+ parentEntry,
1924
+ { type: change.type, node },
1925
+ childSchema,
1926
+ relationship2,
1927
+ format,
1928
+ withIDs
1929
+ );
1930
+ }
1931
+ }
1932
+ return;
1933
+ case "edit":
1934
+ return;
1935
+ case "child": {
1936
+ const childSchema = must(
1937
+ schema.relationships[change.child.relationshipName]
1938
+ );
1939
+ applyChange(
1940
+ parentEntry,
1941
+ change.child.change,
1942
+ childSchema,
1943
+ relationship,
1944
+ format,
1945
+ withIDs
1946
+ );
1947
+ return;
1948
+ }
1949
+ default:
1950
+ unreachable(change);
1951
+ }
1952
+ }
1953
+ const { singular, relationships: childFormats } = format;
1954
+ switch (change.type) {
1955
+ case "add": {
1956
+ let newEntry;
1957
+ if (singular) {
1958
+ const oldEntry = parentEntry[relationship];
1959
+ if (oldEntry !== void 0) {
1960
+ assert(
1961
+ schema.compareRows(oldEntry, change.node.row) === 0,
1962
+ `Singular relationship '${relationship}' should not have multiple rows. You may need to declare this relationship with the \`many\` helper instead of the \`one\` helper in your schema.`
1963
+ );
1964
+ oldEntry[refCountSymbol]++;
1965
+ } else {
1966
+ newEntry = makeNewMetaEntry(change.node.row, schema, withIDs, 1);
1967
+ parentEntry[relationship] = newEntry;
1968
+ }
1969
+ } else {
1970
+ newEntry = add(
1971
+ change.node.row,
1972
+ getChildEntryList(parentEntry, relationship),
1973
+ schema,
1974
+ withIDs
1975
+ );
1976
+ }
1977
+ if (newEntry) {
1978
+ for (const [relationship2, children] of Object.entries(
1979
+ change.node.relationships
1980
+ )) {
1981
+ const childSchema = must(schema.relationships[relationship2]);
1982
+ const childFormat = childFormats[relationship2];
1983
+ if (childFormat === void 0) {
1984
+ continue;
1985
+ }
1986
+ const newView = childFormat.singular ? void 0 : [];
1987
+ newEntry[relationship2] = newView;
1988
+ for (const node of children()) {
1989
+ applyChange(
1990
+ newEntry,
1991
+ { type: "add", node },
1992
+ childSchema,
1993
+ relationship2,
1994
+ childFormat,
1995
+ withIDs
1996
+ );
1997
+ }
1998
+ }
1999
+ }
2000
+ break;
2001
+ }
2002
+ case "remove": {
2003
+ if (singular) {
2004
+ const oldEntry = parentEntry[relationship];
2005
+ assert(oldEntry !== void 0, "node does not exist");
2006
+ const rc = oldEntry[refCountSymbol];
2007
+ if (rc === 1) {
2008
+ parentEntry[relationship] = void 0;
2009
+ }
2010
+ oldEntry[refCountSymbol]--;
2011
+ } else {
2012
+ removeAndUpdateRefCount(
2013
+ getChildEntryList(parentEntry, relationship),
2014
+ change.node.row,
2015
+ schema.compareRows
2016
+ );
2017
+ }
2018
+ drainStreams(change.node);
2019
+ break;
2020
+ }
2021
+ case "child": {
2022
+ let existing;
2023
+ if (singular) {
2024
+ existing = getSingularEntry(parentEntry, relationship);
2025
+ } else {
2026
+ const view = getChildEntryList(parentEntry, relationship);
2027
+ const { pos, found } = binarySearch2(
2028
+ view,
2029
+ change.node.row,
2030
+ schema.compareRows
2031
+ );
2032
+ assert(found, "node does not exist");
2033
+ existing = view[pos];
2034
+ }
2035
+ const childSchema = must(
2036
+ schema.relationships[change.child.relationshipName]
2037
+ );
2038
+ const childFormat = format.relationships[change.child.relationshipName];
2039
+ if (childFormat !== void 0) {
2040
+ applyChange(
2041
+ existing,
2042
+ change.child.change,
2043
+ childSchema,
2044
+ change.child.relationshipName,
2045
+ childFormat,
2046
+ withIDs
2047
+ );
2048
+ }
2049
+ break;
2050
+ }
2051
+ case "edit": {
2052
+ if (singular) {
2053
+ const existing = parentEntry[relationship];
2054
+ assertMetaEntry(existing);
2055
+ applyEdit(existing, change, schema, withIDs);
2056
+ } else {
2057
+ const view = getChildEntryList(parentEntry, relationship);
2058
+ if (schema.compareRows(change.oldNode.row, change.node.row) !== 0) {
2059
+ const { pos: oldPos, found: oldFound } = binarySearch2(
2060
+ view,
2061
+ change.oldNode.row,
2062
+ schema.compareRows
2063
+ );
2064
+ assert(oldFound, "old node does not exist");
2065
+ const oldEntry = view[oldPos];
2066
+ const { pos, found } = binarySearch2(
2067
+ view,
2068
+ change.node.row,
2069
+ schema.compareRows
2070
+ );
2071
+ if (oldEntry[refCountSymbol] === 1 && (pos === oldPos || pos - 1 === oldPos)) {
2072
+ applyEdit(oldEntry, change, schema, withIDs);
2073
+ } else {
2074
+ oldEntry[refCountSymbol]--;
2075
+ let adjustedPos = pos;
2076
+ if (oldEntry[refCountSymbol] === 0) {
2077
+ view.splice(oldPos, 1);
2078
+ adjustedPos = oldPos < pos ? pos - 1 : pos;
2079
+ }
2080
+ let entryToEdit;
2081
+ if (found) {
2082
+ entryToEdit = view[adjustedPos];
2083
+ } else {
2084
+ view.splice(adjustedPos, 0, oldEntry);
2085
+ entryToEdit = oldEntry;
2086
+ if (oldEntry[refCountSymbol] > 0) {
2087
+ const oldEntryCopy = { ...oldEntry };
2088
+ view[oldPos] = oldEntryCopy;
2089
+ }
2090
+ }
2091
+ entryToEdit[refCountSymbol]++;
2092
+ applyEdit(entryToEdit, change, schema, withIDs);
2093
+ }
2094
+ } else {
2095
+ const { pos, found } = binarySearch2(
2096
+ view,
2097
+ change.oldNode.row,
2098
+ schema.compareRows
2099
+ );
2100
+ assert(found, "node does not exist");
2101
+ applyEdit(view[pos], change, schema, withIDs);
2102
+ }
2103
+ }
2104
+ break;
2105
+ }
2106
+ default:
2107
+ unreachable(change);
2108
+ }
2109
+ }
2110
+ function applyEdit(existing, change, schema, withIDs) {
2111
+ Object.assign(existing, change.node.row);
2112
+ if (withIDs) {
2113
+ existing[idSymbol] = makeID(change.node.row, schema);
2114
+ }
2115
+ }
2116
+ function add(row, view, schema, withIDs) {
2117
+ const { pos, found } = binarySearch2(view, row, schema.compareRows);
2118
+ if (found) {
2119
+ view[pos][refCountSymbol]++;
2120
+ return void 0;
2121
+ }
2122
+ const newEntry = makeNewMetaEntry(row, schema, withIDs, 1);
2123
+ view.splice(pos, 0, newEntry);
2124
+ return newEntry;
2125
+ }
2126
+ function removeAndUpdateRefCount(view, row, compareRows) {
2127
+ const { pos, found } = binarySearch2(view, row, compareRows);
2128
+ assert(found, "node does not exist");
2129
+ const oldEntry = view[pos];
2130
+ const rc = oldEntry[refCountSymbol];
2131
+ if (rc === 1) {
2132
+ view.splice(pos, 1);
2133
+ }
2134
+ oldEntry[refCountSymbol]--;
2135
+ return oldEntry;
2136
+ }
2137
+ function binarySearch2(view, target, comparator2) {
2138
+ let low = 0;
2139
+ let high = view.length - 1;
2140
+ while (low <= high) {
2141
+ const mid = low + high >>> 1;
2142
+ const comparison = comparator2(view[mid], target);
2143
+ if (comparison < 0) {
2144
+ low = mid + 1;
2145
+ } else if (comparison > 0) {
2146
+ high = mid - 1;
2147
+ } else {
2148
+ return { pos: mid, found: true };
2149
+ }
2150
+ }
2151
+ return { pos: low, found: false };
2152
+ }
2153
+ function getChildEntryList(parentEntry, relationship) {
2154
+ const view = parentEntry[relationship];
2155
+ assertArray(view);
2156
+ return view;
2157
+ }
2158
+ function assertMetaEntry(v) {
2159
+ assertNumber(v[refCountSymbol]);
2160
+ }
2161
+ function getSingularEntry(parentEntry, relationship) {
2162
+ const e = parentEntry[relationship];
2163
+ assertNumber(e[refCountSymbol]);
2164
+ return e;
2165
+ }
2166
+ function makeNewMetaEntry(row, schema, withIDs, rc) {
2167
+ if (withIDs) {
2168
+ return { ...row, [refCountSymbol]: rc, [idSymbol]: makeID(row, schema) };
2169
+ }
2170
+ return { ...row, [refCountSymbol]: rc };
2171
+ }
2172
+ function makeID(row, schema) {
2173
+ if (schema.primaryKey.length === 1) {
2174
+ return JSON.stringify(row[schema.primaryKey[0]]);
2175
+ }
2176
+ return JSON.stringify(schema.primaryKey.map((k) => row[k]));
2177
+ }
2178
+
1862
2179
  // ../zero-client/src/client/update-needed-reason-type-enum.ts
1863
2180
  var update_needed_reason_type_enum_exports = {};
1864
2181
  __export(update_needed_reason_type_enum_exports, {
@@ -1872,7 +2189,7 @@ var SchemaVersionNotSupported2 = "SchemaVersionNotSupported";
1872
2189
 
1873
2190
  // ../zero-client/src/client/zero.ts
1874
2191
  import "@rocicorp/logger";
1875
- import { resolver as resolver9 } from "@rocicorp/resolver";
2192
+ import { resolver as resolver10 } from "@rocicorp/resolver";
1876
2193
 
1877
2194
  // ../replicache/src/replicache-impl.ts
1878
2195
  import { Lock } from "@rocicorp/lock";
@@ -4421,7 +4738,7 @@ function setIntervalWithSignal(fn, ms, signal) {
4421
4738
  }
4422
4739
 
4423
4740
  // ../replicache/src/subscriptions.ts
4424
- import { compareUTF8, greaterThan as greaterThan3, lessThan, lessThanEq } from "compare-utf8";
4741
+ import { compareUTF8 as compareUTF82, greaterThan as greaterThan3, lessThan, lessThanEq } from "compare-utf8";
4425
4742
 
4426
4743
  // ../replicache/src/invoke-kind-enum.ts
4427
4744
  var InitialRun = 0;
@@ -4764,7 +5081,7 @@ function watcherMatchesDiff(diff3, prefix, indexName) {
4764
5081
  function diffBinarySearch(diff3, prefix, compareKey) {
4765
5082
  return binarySearch(
4766
5083
  diff3.length,
4767
- (i) => compareUTF8(prefix, compareKey(diff3[i]))
5084
+ (i) => compareUTF82(prefix, compareKey(diff3[i]))
4768
5085
  );
4769
5086
  }
4770
5087
 
@@ -5970,6 +6287,15 @@ function validateOptions(options) {
5970
6287
  }
5971
6288
  }
5972
6289
 
6290
+ // ../shared/src/sentinels.ts
6291
+ function emptyFunction() {
6292
+ }
6293
+ var emptyObject = Object.freeze({});
6294
+ var emptyArray = Object.freeze([]);
6295
+ function identity(x) {
6296
+ return x;
6297
+ }
6298
+
5973
6299
  // ../shared/src/subscribable.ts
5974
6300
  var Subscribable = class {
5975
6301
  _listeners = /* @__PURE__ */ new Set();
@@ -6428,46 +6754,11 @@ var downstreamSchema = valita_exports.union(
6428
6754
  );
6429
6755
 
6430
6756
  // ../zero-protocol/src/protocol-version.ts
6431
- var PROTOCOL_VERSION = 35;
6757
+ var PROTOCOL_VERSION = 36;
6432
6758
  var MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 18;
6433
6759
  assert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);
6434
6760
 
6435
- // ../zero-schema/src/name-mapper.ts
6436
- function clientToServer(tables) {
6437
- return createMapperFrom("client", tables);
6438
- }
6439
- function serverToClient(tables) {
6440
- return createMapperFrom("server", tables);
6441
- }
6442
- function createMapperFrom(src, tables) {
6443
- const mapping = new Map(
6444
- Object.entries(tables).map(
6445
- ([tableName, { serverName: serverTableName, columns }]) => {
6446
- let allColumnsSame = true;
6447
- const names = {};
6448
- for (const [name, { serverName }] of Object.entries(columns)) {
6449
- if (serverName && serverName !== name) {
6450
- allColumnsSame = false;
6451
- }
6452
- if (src === "client") {
6453
- names[name] = serverName ?? name;
6454
- } else {
6455
- names[serverName ?? name] = name;
6456
- }
6457
- }
6458
- return [
6459
- src === "client" ? tableName : serverTableName ?? tableName,
6460
- {
6461
- tableName: src === "client" ? serverTableName ?? tableName : tableName,
6462
- columns: names,
6463
- allColumnsSame
6464
- }
6465
- ];
6466
- }
6467
- )
6468
- );
6469
- return new NameMapper(mapping);
6470
- }
6761
+ // ../zero-types/src/name-mapper.ts
6471
6762
  var NameMapper = class {
6472
6763
  #tables = /* @__PURE__ */ new Map();
6473
6764
  constructor(tables) {
@@ -6513,6 +6804,43 @@ var NameMapper = class {
6513
6804
  }
6514
6805
  };
6515
6806
 
6807
+ // ../zero-schema/src/name-mapper.ts
6808
+ function clientToServer(tables) {
6809
+ return createMapperFrom("client", tables);
6810
+ }
6811
+ function serverToClient(tables) {
6812
+ return createMapperFrom("server", tables);
6813
+ }
6814
+ function createMapperFrom(src, tables) {
6815
+ const mapping = new Map(
6816
+ Object.entries(tables).map(
6817
+ ([tableName, { serverName: serverTableName, columns }]) => {
6818
+ let allColumnsSame = true;
6819
+ const names = {};
6820
+ for (const [name, { serverName }] of Object.entries(columns)) {
6821
+ if (serverName && serverName !== name) {
6822
+ allColumnsSame = false;
6823
+ }
6824
+ if (src === "client") {
6825
+ names[name] = serverName ?? name;
6826
+ } else {
6827
+ names[serverName ?? name] = name;
6828
+ }
6829
+ }
6830
+ return [
6831
+ src === "client" ? tableName : serverTableName ?? tableName,
6832
+ {
6833
+ tableName: src === "client" ? serverTableName ?? tableName : tableName,
6834
+ columns: names,
6835
+ allColumnsSame
6836
+ }
6837
+ ];
6838
+ }
6839
+ )
6840
+ );
6841
+ return new NameMapper(mapping);
6842
+ }
6843
+
6516
6844
  // ../zql/src/mutate/custom.ts
6517
6845
  function customMutatorKey(namespace, name) {
6518
6846
  assert(!namespace.includes("|"), "mutator namespaces must not include a |");
@@ -6525,77 +6853,4099 @@ function isClientMetric(metric) {
6525
6853
  return metric.endsWith("-client") || metric.endsWith("-end-to-end");
6526
6854
  }
6527
6855
 
6528
- // ../zero-client/src/util/socket.ts
6529
- function send(ws, data) {
6530
- ws.send(JSON.stringify(data));
6531
- }
6532
-
6533
- // ../zero-client/src/client/active-clients-manager.ts
6856
+ // ../zql/src/query/query-impl.ts
6534
6857
  import { resolver as resolver7 } from "@rocicorp/resolver";
6535
- var keyPrefix = "zero-active";
6536
- function toLockName(clientGroupID, clientID) {
6537
- return `${keyPrefix}/${clientGroupID}/${clientID}`;
6858
+
6859
+ // ../zero-protocol/src/query-hash.ts
6860
+ var hashCache = /* @__PURE__ */ new WeakMap();
6861
+ function hashOfAST(ast) {
6862
+ const normalized = normalizeAST(ast);
6863
+ const cached = hashCache.get(normalized);
6864
+ if (cached) {
6865
+ return cached;
6866
+ }
6867
+ const hash = h64(JSON.stringify(normalized)).toString(36);
6868
+ hashCache.set(normalized, hash);
6869
+ return hash;
6538
6870
  }
6539
- function toBroadcastChannelName(clientGroupID) {
6540
- return `${keyPrefix}/${clientGroupID}`;
6871
+ function hashOfNameAndArgs(name, args) {
6872
+ const argsString = JSON.stringify(args);
6873
+ return h64(`${name}:${argsString}`).toString(36);
6541
6874
  }
6542
- function fromLockName(lockKey) {
6543
- if (!lockKey || !lockKey.startsWith(keyPrefix)) {
6544
- return void 0;
6875
+
6876
+ // ../zql/src/ivm/filter-operators.ts
6877
+ var throwFilterOutput = {
6878
+ push(_change) {
6879
+ throw new Error("Output not set");
6880
+ },
6881
+ filter(_node, _cleanup) {
6882
+ throw new Error("Output not set");
6545
6883
  }
6546
- const parts = lockKey.slice(keyPrefix.length).split("/");
6547
- if (parts.length !== 3) {
6548
- return void 0;
6884
+ };
6885
+ var FilterStart = class {
6886
+ #input;
6887
+ #output = throwFilterOutput;
6888
+ constructor(input) {
6889
+ this.#input = input;
6890
+ input.setOutput(this);
6549
6891
  }
6550
- return {
6551
- clientGroupID: parts[1],
6552
- clientID: parts[2]
6553
- };
6554
- }
6555
- function ignoreAbortError(e) {
6556
- if (e instanceof Error && e.name === "AbortError") {
6557
- return;
6892
+ setFilterOutput(output) {
6893
+ this.#output = output;
6558
6894
  }
6559
- throw e;
6560
- }
6561
- var ActiveClientsManager = class _ActiveClientsManager {
6562
- clientGroupID;
6563
- clientID;
6564
- #resolver = resolver7();
6565
- #lockManager;
6566
- #activeClients = /* @__PURE__ */ new Set();
6567
- /**
6568
- * A callback that is called when a client is added to the client group.
6569
- * It receives the client ID of the added client.
6570
- */
6571
- onAdd;
6572
- /**
6573
- * A callback that is called when a client is deleted from the client group.
6574
- * It receives the client ID of the deleted client.
6575
- */
6576
- onDelete;
6577
- /**
6578
- * Creates an instance of `ActiveClientsManager` for the specified client
6579
- * group and client ID. It will return a promise that resolves when the
6580
- * instance is ready to use, which means that it has successfully acquired the
6581
- * exclusive lock for the client and has retrieved the list of active clients.
6582
- */
6583
- static async create(clientGroupID, clientID, signal) {
6584
- const instance = new _ActiveClientsManager(clientGroupID, clientID, signal);
6585
- await instance.#init(signal);
6586
- return instance;
6895
+ destroy() {
6896
+ this.#input.destroy();
6587
6897
  }
6588
- constructor(clientGroupID, clientID, signal) {
6589
- this.clientGroupID = clientGroupID;
6590
- this.clientID = clientID;
6591
- this.#lockManager = getClientLockManager(signal);
6592
- this.#activeClients.add(clientID);
6898
+ getSchema() {
6899
+ return this.#input.getSchema();
6593
6900
  }
6594
- async #init(signal) {
6595
- const { clientGroupID, clientID } = this;
6596
- const name = toLockName(clientGroupID, clientID);
6597
- const channel = new bc(toBroadcastChannelName(clientGroupID));
6598
- channel.addEventListener(
6901
+ push(change) {
6902
+ this.#output.push(change, this);
6903
+ }
6904
+ *fetch(req) {
6905
+ for (const node of this.#input.fetch(req)) {
6906
+ if (this.#output.filter(node, false)) {
6907
+ yield node;
6908
+ }
6909
+ }
6910
+ }
6911
+ *cleanup(req) {
6912
+ for (const node of this.#input.cleanup(req)) {
6913
+ if (this.#output.filter(node, true)) {
6914
+ yield node;
6915
+ } else {
6916
+ drainStreams(node);
6917
+ }
6918
+ }
6919
+ }
6920
+ };
6921
+ var FilterEnd = class {
6922
+ #start;
6923
+ #input;
6924
+ #output = throwFilterOutput;
6925
+ constructor(start, input) {
6926
+ this.#start = start;
6927
+ this.#input = input;
6928
+ input.setFilterOutput(this);
6929
+ }
6930
+ *fetch(req) {
6931
+ for (const node of this.#start.fetch(req)) {
6932
+ yield node;
6933
+ }
6934
+ }
6935
+ *cleanup(req) {
6936
+ for (const node of this.#start.cleanup(req)) {
6937
+ yield node;
6938
+ }
6939
+ }
6940
+ filter(_node, _cleanup) {
6941
+ return true;
6942
+ }
6943
+ setOutput(output) {
6944
+ this.#output = output;
6945
+ }
6946
+ destroy() {
6947
+ this.#input.destroy();
6948
+ }
6949
+ getSchema() {
6950
+ return this.#input.getSchema();
6951
+ }
6952
+ push(change) {
6953
+ this.#output.push(change, this);
6954
+ }
6955
+ };
6956
+ function buildFilterPipeline(input, delegate, pipeline) {
6957
+ const filterStart = new FilterStart(input);
6958
+ delegate.addEdge(input, filterStart);
6959
+ const middle = pipeline(filterStart);
6960
+ delegate.addEdge(filterStart, middle);
6961
+ const filterEnd = new FilterEnd(filterStart, middle);
6962
+ delegate.addEdge(middle, filterEnd);
6963
+ return filterEnd;
6964
+ }
6965
+
6966
+ // ../zql/src/ivm/operator.ts
6967
+ var throwOutput = {
6968
+ push(_change) {
6969
+ throw new Error("Output not set");
6970
+ }
6971
+ };
6972
+
6973
+ // ../zql/src/ivm/stream.ts
6974
+ function* take(stream, limit) {
6975
+ if (limit < 1) {
6976
+ return;
6977
+ }
6978
+ let count = 0;
6979
+ for (const v of stream) {
6980
+ yield v;
6981
+ if (++count === limit) {
6982
+ break;
6983
+ }
6984
+ }
6985
+ }
6986
+ function first(stream) {
6987
+ const it = stream[Symbol.iterator]();
6988
+ const { value } = it.next();
6989
+ it.return?.();
6990
+ return value;
6991
+ }
6992
+
6993
+ // ../zql/src/ivm/exists.ts
6994
+ var Exists = class {
6995
+ #input;
6996
+ #relationshipName;
6997
+ #storage;
6998
+ #not;
6999
+ #parentJoinKey;
7000
+ #noSizeReuse;
7001
+ #output = throwFilterOutput;
7002
+ /**
7003
+ * This instance variable is `true` when this operator is processing a `push`,
7004
+ * and is used to disable reuse of cached sizes across rows with the
7005
+ * same parent join key value.
7006
+ * This is necessary because during a push relationships can be inconsistent
7007
+ * due to push communicating changes (which may change multiple Nodes) one
7008
+ * Node at a time.
7009
+ */
7010
+ #inPush = false;
7011
+ constructor(input, storage, relationshipName, parentJoinKey, type) {
7012
+ this.#input = input;
7013
+ this.#relationshipName = relationshipName;
7014
+ this.#input.setFilterOutput(this);
7015
+ this.#storage = storage;
7016
+ assert(
7017
+ this.#input.getSchema().relationships[relationshipName],
7018
+ `Input schema missing ${relationshipName}`
7019
+ );
7020
+ this.#not = type === "NOT EXISTS";
7021
+ this.#parentJoinKey = parentJoinKey;
7022
+ this.#noSizeReuse = areEqual(
7023
+ parentJoinKey,
7024
+ this.#input.getSchema().primaryKey
7025
+ );
7026
+ }
7027
+ setFilterOutput(output) {
7028
+ this.#output = output;
7029
+ }
7030
+ filter(node, cleanup) {
7031
+ const result = this.#filter(node) && this.#output.filter(node, cleanup);
7032
+ if (cleanup) {
7033
+ this.#delSize(node);
7034
+ }
7035
+ return result;
7036
+ }
7037
+ destroy() {
7038
+ this.#input.destroy();
7039
+ }
7040
+ getSchema() {
7041
+ return this.#input.getSchema();
7042
+ }
7043
+ push(change) {
7044
+ assert(!this.#inPush, "Unexpected re-entrancy");
7045
+ this.#inPush = true;
7046
+ try {
7047
+ switch (change.type) {
7048
+ // add, remove and edit cannot change the size of the
7049
+ // this.#relationshipName relationship, so simply #pushWithFilter
7050
+ case "add":
7051
+ case "edit": {
7052
+ this.#pushWithFilter(change);
7053
+ return;
7054
+ }
7055
+ case "remove": {
7056
+ const size = this.#getSize(change.node);
7057
+ if (size === void 0) {
7058
+ return;
7059
+ }
7060
+ this.#pushWithFilter(change, size);
7061
+ this.#delSize(change.node);
7062
+ return;
7063
+ }
7064
+ case "child":
7065
+ if (change.child.relationshipName !== this.#relationshipName || change.child.change.type === "edit" || change.child.change.type === "child") {
7066
+ this.#pushWithFilter(change);
7067
+ return;
7068
+ }
7069
+ switch (change.child.change.type) {
7070
+ case "add": {
7071
+ let size = this.#getSize(change.node);
7072
+ if (size !== void 0) {
7073
+ size++;
7074
+ this.#setSize(change.node, size);
7075
+ } else {
7076
+ size = this.#fetchSize(change.node);
7077
+ }
7078
+ if (size === 1) {
7079
+ if (this.#not) {
7080
+ this.#output.push(
7081
+ {
7082
+ type: "remove",
7083
+ node: {
7084
+ row: change.node.row,
7085
+ relationships: {
7086
+ ...change.node.relationships,
7087
+ [this.#relationshipName]: () => []
7088
+ }
7089
+ }
7090
+ },
7091
+ this
7092
+ );
7093
+ } else {
7094
+ this.#output.push(
7095
+ {
7096
+ type: "add",
7097
+ node: change.node
7098
+ },
7099
+ this
7100
+ );
7101
+ }
7102
+ } else {
7103
+ this.#pushWithFilter(change, size);
7104
+ }
7105
+ return;
7106
+ }
7107
+ case "remove": {
7108
+ let size = this.#getSize(change.node);
7109
+ if (size !== void 0) {
7110
+ assert(size > 0);
7111
+ size--;
7112
+ this.#setSize(change.node, size);
7113
+ } else {
7114
+ size = this.#fetchSize(change.node);
7115
+ }
7116
+ if (size === 0) {
7117
+ if (this.#not) {
7118
+ this.#output.push(
7119
+ {
7120
+ type: "add",
7121
+ node: change.node
7122
+ },
7123
+ this
7124
+ );
7125
+ } else {
7126
+ this.#output.push(
7127
+ {
7128
+ type: "remove",
7129
+ node: {
7130
+ row: change.node.row,
7131
+ relationships: {
7132
+ ...change.node.relationships,
7133
+ [this.#relationshipName]: () => [
7134
+ change.child.change.node
7135
+ ]
7136
+ }
7137
+ }
7138
+ },
7139
+ this
7140
+ );
7141
+ }
7142
+ } else {
7143
+ this.#pushWithFilter(change, size);
7144
+ }
7145
+ return;
7146
+ }
7147
+ }
7148
+ return;
7149
+ default:
7150
+ unreachable(change);
7151
+ }
7152
+ } finally {
7153
+ this.#inPush = false;
7154
+ }
7155
+ }
7156
+ /**
7157
+ * Returns whether or not the node's this.#relationshipName
7158
+ * relationship passes the exist/not exists filter condition.
7159
+ * If the optional `size` is passed it is used.
7160
+ * Otherwise, if there is a stored size for the row it is used.
7161
+ * Otherwise the size is computed by streaming the node's
7162
+ * relationship with this.#relationshipName (this computed size is also
7163
+ * stored).
7164
+ */
7165
+ #filter(node, size) {
7166
+ const exists = (size ?? this.#getOrFetchSize(node)) > 0;
7167
+ return this.#not ? !exists : exists;
7168
+ }
7169
+ /**
7170
+ * Pushes a change if this.#filter is true for its row.
7171
+ */
7172
+ #pushWithFilter(change, size) {
7173
+ if (this.#filter(change.node, size)) {
7174
+ this.#output.push(change, this);
7175
+ }
7176
+ }
7177
+ #getSize(node) {
7178
+ return this.#storage.get(this.#makeSizeStorageKey(node));
7179
+ }
7180
+ #setSize(node, size) {
7181
+ this.#storage.set(this.#makeSizeStorageKey(node), size);
7182
+ }
7183
+ #delSize(node) {
7184
+ this.#storage.del(this.#makeSizeStorageKey(node));
7185
+ }
7186
+ #getOrFetchSize(node) {
7187
+ const size = this.#getSize(node);
7188
+ if (size !== void 0) {
7189
+ return size;
7190
+ }
7191
+ return this.#fetchSize(node);
7192
+ }
7193
+ #fetchSize(node) {
7194
+ if (!this.#noSizeReuse && !this.#inPush) {
7195
+ const cachedSizeEntry = first(
7196
+ this.#storage.scan({
7197
+ prefix: this.#makeSizeStorageKeyPrefix(node)
7198
+ })
7199
+ );
7200
+ if (cachedSizeEntry !== void 0) {
7201
+ this.#setSize(node, cachedSizeEntry[1]);
7202
+ return cachedSizeEntry[1];
7203
+ }
7204
+ }
7205
+ const relationship = node.relationships[this.#relationshipName];
7206
+ assert(relationship);
7207
+ let size = 0;
7208
+ for (const _relatedNode of relationship()) {
7209
+ size++;
7210
+ }
7211
+ this.#setSize(node, size);
7212
+ return size;
7213
+ }
7214
+ #makeSizeStorageKeyPrefix(node) {
7215
+ return `row/${this.#noSizeReuse ? "" : JSON.stringify(this.#getKeyValues(node, this.#parentJoinKey))}/`;
7216
+ }
7217
+ #makeSizeStorageKey(node) {
7218
+ return `${this.#makeSizeStorageKeyPrefix(node)}${JSON.stringify(
7219
+ this.#getKeyValues(node, this.#input.getSchema().primaryKey)
7220
+ )}`;
7221
+ }
7222
+ #getKeyValues(node, def) {
7223
+ const values = [];
7224
+ for (const key of def) {
7225
+ values.push(normalizeUndefined(node.row[key]));
7226
+ }
7227
+ return values;
7228
+ }
7229
+ };
7230
+
7231
+ // ../zql/src/ivm/push-accumulated.ts
7232
+ function pushAccumulatedChanges(accumulatedPushes, output, pusher, fanOutChangeType, mergeRelationships2, addEmptyRelationships) {
7233
+ if (accumulatedPushes.length === 0) {
7234
+ return;
7235
+ }
7236
+ const candidatesToPush = /* @__PURE__ */ new Map();
7237
+ for (const change of accumulatedPushes) {
7238
+ if (fanOutChangeType === "child" && change.type !== "child") {
7239
+ assert(
7240
+ candidatesToPush.has(change.type) === false,
7241
+ () => `Fan-in:child expected at most one ${change.type} when fan-out is of type child`
7242
+ );
7243
+ }
7244
+ const existing = candidatesToPush.get(change.type);
7245
+ let mergedChange = change;
7246
+ if (existing) {
7247
+ mergedChange = mergeRelationships2(existing, change);
7248
+ }
7249
+ candidatesToPush.set(change.type, mergedChange);
7250
+ }
7251
+ accumulatedPushes.length = 0;
7252
+ const types = [...candidatesToPush.keys()];
7253
+ switch (fanOutChangeType) {
7254
+ case "remove":
7255
+ assert(
7256
+ types.length === 1 && types[0] === "remove",
7257
+ "Fan-in:remove expected all removes"
7258
+ );
7259
+ output.push(
7260
+ addEmptyRelationships(must(candidatesToPush.get("remove"))),
7261
+ pusher
7262
+ );
7263
+ return;
7264
+ case "add":
7265
+ assert(
7266
+ types.length === 1 && types[0] === "add",
7267
+ "Fan-in:add expected all adds"
7268
+ );
7269
+ output.push(
7270
+ addEmptyRelationships(must(candidatesToPush.get("add"))),
7271
+ pusher
7272
+ );
7273
+ return;
7274
+ case "edit": {
7275
+ assert(
7276
+ types.every(
7277
+ (type) => type === "add" || type === "remove" || type === "edit"
7278
+ ),
7279
+ "Fan-in:edit expected all adds, removes, or edits"
7280
+ );
7281
+ const addChange = candidatesToPush.get("add");
7282
+ const removeChange = candidatesToPush.get("remove");
7283
+ let editChange = candidatesToPush.get("edit");
7284
+ if (editChange) {
7285
+ if (addChange) {
7286
+ editChange = mergeRelationships2(editChange, addChange);
7287
+ }
7288
+ if (removeChange) {
7289
+ editChange = mergeRelationships2(editChange, removeChange);
7290
+ }
7291
+ output.push(addEmptyRelationships(editChange), pusher);
7292
+ return;
7293
+ }
7294
+ if (addChange && removeChange) {
7295
+ output.push(
7296
+ addEmptyRelationships({
7297
+ type: "edit",
7298
+ node: addChange.node,
7299
+ oldNode: removeChange.node
7300
+ }),
7301
+ pusher
7302
+ );
7303
+ return;
7304
+ }
7305
+ output.push(
7306
+ addEmptyRelationships(must(addChange ?? removeChange)),
7307
+ pusher
7308
+ );
7309
+ return;
7310
+ }
7311
+ case "child": {
7312
+ assert(
7313
+ types.every(
7314
+ (type) => type === "add" || // exists can change child to add or remove
7315
+ type === "remove" || // exists can change child to add or remove
7316
+ type === "child"
7317
+ // other operators may preserve the child change
7318
+ ),
7319
+ "Fan-in:child expected all adds, removes, or children"
7320
+ );
7321
+ assert(
7322
+ types.length <= 2,
7323
+ "Fan-in:child expected at most 2 types on a child change from fan-out"
7324
+ );
7325
+ const childChange = candidatesToPush.get("child");
7326
+ if (childChange) {
7327
+ output.push(childChange, pusher);
7328
+ return;
7329
+ }
7330
+ const addChange = candidatesToPush.get("add");
7331
+ const removeChange = candidatesToPush.get("remove");
7332
+ assert(
7333
+ addChange === void 0 || removeChange === void 0,
7334
+ "Fan-in:child expected either add or remove, not both"
7335
+ );
7336
+ output.push(
7337
+ addEmptyRelationships(must(addChange ?? removeChange)),
7338
+ pusher
7339
+ );
7340
+ return;
7341
+ }
7342
+ default:
7343
+ fanOutChangeType;
7344
+ }
7345
+ }
7346
+ function mergeRelationships(left, right) {
7347
+ if (left.type === right.type) {
7348
+ switch (left.type) {
7349
+ case "add": {
7350
+ return {
7351
+ type: "add",
7352
+ node: {
7353
+ row: left.node.row,
7354
+ relationships: {
7355
+ ...right.node.relationships,
7356
+ ...left.node.relationships
7357
+ }
7358
+ }
7359
+ };
7360
+ }
7361
+ case "remove": {
7362
+ return {
7363
+ type: "remove",
7364
+ node: {
7365
+ row: left.node.row,
7366
+ relationships: {
7367
+ ...right.node.relationships,
7368
+ ...left.node.relationships
7369
+ }
7370
+ }
7371
+ };
7372
+ }
7373
+ case "edit": {
7374
+ assert(right.type === "edit");
7375
+ return {
7376
+ type: "edit",
7377
+ node: {
7378
+ row: left.node.row,
7379
+ relationships: {
7380
+ ...right.node.relationships,
7381
+ ...left.node.relationships
7382
+ }
7383
+ },
7384
+ oldNode: {
7385
+ row: left.oldNode.row,
7386
+ relationships: {
7387
+ ...right.oldNode.relationships,
7388
+ ...left.oldNode.relationships
7389
+ }
7390
+ }
7391
+ };
7392
+ }
7393
+ }
7394
+ }
7395
+ assert(left.type === "edit");
7396
+ switch (right.type) {
7397
+ case "add": {
7398
+ return {
7399
+ type: "edit",
7400
+ node: {
7401
+ ...left.node,
7402
+ relationships: {
7403
+ ...right.node.relationships,
7404
+ ...left.node.relationships
7405
+ }
7406
+ },
7407
+ oldNode: left.oldNode
7408
+ };
7409
+ }
7410
+ case "remove": {
7411
+ return {
7412
+ type: "edit",
7413
+ node: left.node,
7414
+ oldNode: {
7415
+ ...left.oldNode,
7416
+ relationships: {
7417
+ ...right.node.relationships,
7418
+ ...left.oldNode.relationships
7419
+ }
7420
+ }
7421
+ };
7422
+ }
7423
+ }
7424
+ unreachable();
7425
+ }
7426
+ function makeAddEmptyRelationships(schema) {
7427
+ return (change) => {
7428
+ if (Object.keys(schema.relationships).length === 0) {
7429
+ return change;
7430
+ }
7431
+ switch (change.type) {
7432
+ case "add":
7433
+ case "remove": {
7434
+ const ret = {
7435
+ ...change,
7436
+ node: {
7437
+ ...change.node,
7438
+ relationships: {
7439
+ ...change.node.relationships
7440
+ }
7441
+ }
7442
+ };
7443
+ mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));
7444
+ return ret;
7445
+ }
7446
+ case "edit": {
7447
+ const ret = {
7448
+ ...change,
7449
+ node: {
7450
+ ...change.node,
7451
+ relationships: {
7452
+ ...change.node.relationships
7453
+ }
7454
+ },
7455
+ oldNode: {
7456
+ ...change.oldNode,
7457
+ relationships: {
7458
+ ...change.oldNode.relationships
7459
+ }
7460
+ }
7461
+ };
7462
+ mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));
7463
+ mergeEmpty(
7464
+ ret.oldNode.relationships,
7465
+ Object.keys(schema.relationships)
7466
+ );
7467
+ return ret;
7468
+ }
7469
+ case "child":
7470
+ return change;
7471
+ }
7472
+ };
7473
+ }
7474
+ function mergeEmpty(relationships, relationshipNames) {
7475
+ for (const relName of relationshipNames) {
7476
+ if (relationships[relName] === void 0) {
7477
+ relationships[relName] = () => emptyArray;
7478
+ }
7479
+ }
7480
+ }
7481
+
7482
+ // ../zql/src/ivm/fan-in.ts
7483
+ var FanIn = class {
7484
+ #inputs;
7485
+ #schema;
7486
+ #output = throwFilterOutput;
7487
+ #accumulatedPushes = [];
7488
+ constructor(fanOut, inputs) {
7489
+ this.#inputs = inputs;
7490
+ this.#schema = fanOut.getSchema();
7491
+ for (const input of inputs) {
7492
+ input.setFilterOutput(this);
7493
+ assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);
7494
+ }
7495
+ }
7496
+ setFilterOutput(output) {
7497
+ this.#output = output;
7498
+ }
7499
+ destroy() {
7500
+ for (const input of this.#inputs) {
7501
+ input.destroy();
7502
+ }
7503
+ }
7504
+ getSchema() {
7505
+ return this.#schema;
7506
+ }
7507
+ filter(node, cleanup) {
7508
+ return this.#output.filter(node, cleanup);
7509
+ }
7510
+ push(change) {
7511
+ this.#accumulatedPushes.push(change);
7512
+ }
7513
+ fanOutDonePushingToAllBranches(fanOutChangeType) {
7514
+ if (this.#inputs.length === 0) {
7515
+ assert(
7516
+ this.#accumulatedPushes.length === 0,
7517
+ "If there are no inputs then fan-in should not receive any pushes."
7518
+ );
7519
+ return;
7520
+ }
7521
+ pushAccumulatedChanges(
7522
+ this.#accumulatedPushes,
7523
+ this.#output,
7524
+ this,
7525
+ fanOutChangeType,
7526
+ identity,
7527
+ identity
7528
+ );
7529
+ }
7530
+ };
7531
+
7532
+ // ../zql/src/ivm/fan-out.ts
7533
+ var FanOut = class {
7534
+ #input;
7535
+ #outputs = [];
7536
+ #fanIn;
7537
+ #destroyCount = 0;
7538
+ constructor(input) {
7539
+ this.#input = input;
7540
+ input.setFilterOutput(this);
7541
+ }
7542
+ setFanIn(fanIn) {
7543
+ this.#fanIn = fanIn;
7544
+ }
7545
+ setFilterOutput(output) {
7546
+ this.#outputs.push(output);
7547
+ }
7548
+ destroy() {
7549
+ if (this.#destroyCount < this.#outputs.length) {
7550
+ ++this.#destroyCount;
7551
+ if (this.#destroyCount === this.#outputs.length) {
7552
+ this.#input.destroy();
7553
+ }
7554
+ } else {
7555
+ throw new Error("FanOut already destroyed once for each output");
7556
+ }
7557
+ }
7558
+ getSchema() {
7559
+ return this.#input.getSchema();
7560
+ }
7561
+ filter(node, cleanup) {
7562
+ let result = false;
7563
+ for (const output of this.#outputs) {
7564
+ result = output.filter(node, cleanup) || result;
7565
+ if (!cleanup && result) {
7566
+ return true;
7567
+ }
7568
+ }
7569
+ return result;
7570
+ }
7571
+ push(change) {
7572
+ for (const out of this.#outputs) {
7573
+ out.push(change, this);
7574
+ }
7575
+ must(
7576
+ this.#fanIn,
7577
+ "fan-out must have a corresponding fan-in set!"
7578
+ ).fanOutDonePushingToAllBranches(change.type);
7579
+ }
7580
+ };
7581
+
7582
+ // ../zql/src/ivm/maybe-split-and-push-edit-change.ts
7583
+ function maybeSplitAndPushEditChange(change, predicate, output, pusher) {
7584
+ const oldWasPresent = predicate(change.oldNode.row);
7585
+ const newIsPresent = predicate(change.node.row);
7586
+ if (oldWasPresent && newIsPresent) {
7587
+ output.push(change, pusher);
7588
+ } else if (oldWasPresent && !newIsPresent) {
7589
+ output.push(
7590
+ {
7591
+ type: "remove",
7592
+ node: change.oldNode
7593
+ },
7594
+ pusher
7595
+ );
7596
+ } else if (!oldWasPresent && newIsPresent) {
7597
+ output.push(
7598
+ {
7599
+ type: "add",
7600
+ node: change.node
7601
+ },
7602
+ pusher
7603
+ );
7604
+ }
7605
+ }
7606
+
7607
+ // ../zql/src/ivm/filter-push.ts
7608
+ function filterPush(change, output, pusher, predicate) {
7609
+ if (!predicate) {
7610
+ output.push(change, pusher);
7611
+ return;
7612
+ }
7613
+ switch (change.type) {
7614
+ case "add":
7615
+ case "remove":
7616
+ if (predicate(change.node.row)) {
7617
+ output.push(change, pusher);
7618
+ }
7619
+ break;
7620
+ case "child":
7621
+ if (predicate(change.node.row)) {
7622
+ output.push(change, pusher);
7623
+ }
7624
+ break;
7625
+ case "edit":
7626
+ maybeSplitAndPushEditChange(change, predicate, output, pusher);
7627
+ break;
7628
+ default:
7629
+ unreachable(change);
7630
+ }
7631
+ }
7632
+
7633
+ // ../zql/src/ivm/filter.ts
7634
+ var Filter = class {
7635
+ #input;
7636
+ #predicate;
7637
+ #output = throwFilterOutput;
7638
+ constructor(input, predicate) {
7639
+ this.#input = input;
7640
+ this.#predicate = predicate;
7641
+ input.setFilterOutput(this);
7642
+ }
7643
+ filter(node, cleanup) {
7644
+ return this.#predicate(node.row) && this.#output.filter(node, cleanup);
7645
+ }
7646
+ setFilterOutput(output) {
7647
+ this.#output = output;
7648
+ }
7649
+ destroy() {
7650
+ this.#input.destroy();
7651
+ }
7652
+ getSchema() {
7653
+ return this.#input.getSchema();
7654
+ }
7655
+ push(change) {
7656
+ filterPush(change, this.#output, this, this.#predicate);
7657
+ }
7658
+ };
7659
+
7660
+ // ../zql/src/ivm/constraint.ts
7661
+ function constraintMatchesRow(constraint, row) {
7662
+ for (const key in constraint) {
7663
+ if (!valuesEqual(row[key], constraint[key])) {
7664
+ return false;
7665
+ }
7666
+ }
7667
+ return true;
7668
+ }
7669
+ function constraintsAreCompatible(left, right) {
7670
+ for (const key in left) {
7671
+ if (key in right && !valuesEqual(left[key], right[key])) {
7672
+ return false;
7673
+ }
7674
+ }
7675
+ return true;
7676
+ }
7677
+ function constraintMatchesPrimaryKey(constraint, primary) {
7678
+ const constraintKeys = Object.keys(constraint);
7679
+ if (constraintKeys.length !== primary.length) {
7680
+ return false;
7681
+ }
7682
+ constraintKeys.sort(stringCompare);
7683
+ for (let i = 0; i < constraintKeys.length; i++) {
7684
+ if (constraintKeys[i] !== primary[i]) {
7685
+ return false;
7686
+ }
7687
+ }
7688
+ return true;
7689
+ }
7690
+ function pullSimpleAndComponents(condition) {
7691
+ if (condition.type === "and") {
7692
+ return condition.conditions.flatMap(pullSimpleAndComponents);
7693
+ }
7694
+ if (condition.type === "simple") {
7695
+ return [condition];
7696
+ }
7697
+ if (condition.type === "or" && condition.conditions.length === 1) {
7698
+ return pullSimpleAndComponents(condition.conditions[0]);
7699
+ }
7700
+ return [];
7701
+ }
7702
+ function primaryKeyConstraintFromFilters(condition, primary) {
7703
+ if (condition === void 0) {
7704
+ return void 0;
7705
+ }
7706
+ const conditions = pullSimpleAndComponents(condition);
7707
+ if (conditions.length === 0) {
7708
+ return void 0;
7709
+ }
7710
+ const ret = {};
7711
+ for (const subCondition of conditions) {
7712
+ if (subCondition.op === "=") {
7713
+ const column = extractColumn(subCondition);
7714
+ if (column !== void 0) {
7715
+ if (!primary.includes(column.name)) {
7716
+ continue;
7717
+ }
7718
+ ret[column.name] = column.value;
7719
+ }
7720
+ }
7721
+ }
7722
+ if (Object.keys(ret).length !== primary.length) {
7723
+ return void 0;
7724
+ }
7725
+ return ret;
7726
+ }
7727
+ function extractColumn(condition) {
7728
+ if (condition.left.type === "column") {
7729
+ assert(condition.right.type === "literal");
7730
+ return { name: condition.left.name, value: condition.right.value };
7731
+ }
7732
+ return void 0;
7733
+ }
7734
+
7735
+ // ../zql/src/ivm/join-utils.ts
7736
+ function* generateWithOverlay(stream, overlay, schema) {
7737
+ let applied = false;
7738
+ let editOldApplied = false;
7739
+ let editNewApplied = false;
7740
+ for (const node of stream) {
7741
+ let yieldNode = true;
7742
+ if (!applied) {
7743
+ switch (overlay.type) {
7744
+ case "add": {
7745
+ if (schema.compareRows(overlay.node.row, node.row) === 0) {
7746
+ applied = true;
7747
+ yieldNode = false;
7748
+ }
7749
+ break;
7750
+ }
7751
+ case "remove": {
7752
+ if (schema.compareRows(overlay.node.row, node.row) < 0) {
7753
+ applied = true;
7754
+ yield overlay.node;
7755
+ }
7756
+ break;
7757
+ }
7758
+ case "edit": {
7759
+ if (!editOldApplied && schema.compareRows(overlay.oldNode.row, node.row) < 0) {
7760
+ editOldApplied = true;
7761
+ if (editNewApplied) {
7762
+ applied = true;
7763
+ }
7764
+ yield overlay.oldNode;
7765
+ }
7766
+ if (!editNewApplied && schema.compareRows(overlay.node.row, node.row) === 0) {
7767
+ editNewApplied = true;
7768
+ if (editOldApplied) {
7769
+ applied = true;
7770
+ }
7771
+ yieldNode = false;
7772
+ }
7773
+ break;
7774
+ }
7775
+ case "child": {
7776
+ if (schema.compareRows(overlay.node.row, node.row) === 0) {
7777
+ applied = true;
7778
+ yield {
7779
+ row: node.row,
7780
+ relationships: {
7781
+ ...node.relationships,
7782
+ [overlay.child.relationshipName]: () => generateWithOverlay(
7783
+ node.relationships[overlay.child.relationshipName](),
7784
+ overlay.child.change,
7785
+ schema.relationships[overlay.child.relationshipName]
7786
+ )
7787
+ }
7788
+ };
7789
+ yieldNode = false;
7790
+ }
7791
+ break;
7792
+ }
7793
+ }
7794
+ }
7795
+ if (yieldNode) {
7796
+ yield node;
7797
+ }
7798
+ }
7799
+ if (!applied) {
7800
+ if (overlay.type === "remove") {
7801
+ applied = true;
7802
+ yield overlay.node;
7803
+ } else if (overlay.type === "edit") {
7804
+ assert(editNewApplied);
7805
+ editOldApplied = true;
7806
+ applied = true;
7807
+ yield overlay.oldNode;
7808
+ }
7809
+ }
7810
+ assert(applied);
7811
+ }
7812
+ function rowEqualsForCompoundKey(a, b, key) {
7813
+ for (let i = 0; i < key.length; i++) {
7814
+ if (compareValues(a[key[i]], b[key[i]]) !== 0) {
7815
+ return false;
7816
+ }
7817
+ }
7818
+ return true;
7819
+ }
7820
+ function isJoinMatch(parent, parentKey, child, childKey) {
7821
+ for (let i = 0; i < parentKey.length; i++) {
7822
+ if (!valuesEqual(parent[parentKey[i]], child[childKey[i]])) {
7823
+ return false;
7824
+ }
7825
+ }
7826
+ return true;
7827
+ }
7828
+
7829
+ // ../zql/src/ivm/flipped-join.ts
7830
+ var FlippedJoin = class {
7831
+ #parent;
7832
+ #child;
7833
+ #parentKey;
7834
+ #childKey;
7835
+ #relationshipName;
7836
+ #schema;
7837
+ #output = throwOutput;
7838
+ #inprogressChildChange;
7839
+ constructor({
7840
+ parent,
7841
+ child,
7842
+ parentKey,
7843
+ childKey,
7844
+ relationshipName,
7845
+ hidden,
7846
+ system
7847
+ }) {
7848
+ assert(parent !== child, "Parent and child must be different operators");
7849
+ assert(
7850
+ parentKey.length === childKey.length,
7851
+ "The parentKey and childKey keys must have same length"
7852
+ );
7853
+ this.#parent = parent;
7854
+ this.#child = child;
7855
+ this.#parentKey = parentKey;
7856
+ this.#childKey = childKey;
7857
+ this.#relationshipName = relationshipName;
7858
+ const parentSchema = parent.getSchema();
7859
+ const childSchema = child.getSchema();
7860
+ this.#schema = {
7861
+ ...parentSchema,
7862
+ relationships: {
7863
+ ...parentSchema.relationships,
7864
+ [relationshipName]: {
7865
+ ...childSchema,
7866
+ isHidden: hidden,
7867
+ system
7868
+ }
7869
+ }
7870
+ };
7871
+ parent.setOutput({
7872
+ push: (change) => this.#pushParent(change)
7873
+ });
7874
+ child.setOutput({
7875
+ push: (change) => this.#pushChild(change)
7876
+ });
7877
+ }
7878
+ destroy() {
7879
+ this.#child.destroy();
7880
+ this.#parent.destroy();
7881
+ }
7882
+ setOutput(output) {
7883
+ this.#output = output;
7884
+ }
7885
+ getSchema() {
7886
+ return this.#schema;
7887
+ }
7888
+ // TODO: When parentKey is the parent's primary key (or more
7889
+ // generally when the parent cardinality is expected to be small) a different
7890
+ // algorithm should be used: For each child node, fetch all parent nodes
7891
+ // eagerly and then sort using quicksort.
7892
+ *fetch(req) {
7893
+ const childNodes = [...this.#child.fetch({})];
7894
+ if (this.#inprogressChildChange?.change.type === "remove") {
7895
+ const removedNode = this.#inprogressChildChange.change.node;
7896
+ const compare2 = this.#child.getSchema().compareRows;
7897
+ const insertPos = binarySearch(
7898
+ childNodes.length,
7899
+ (i) => compare2(removedNode.row, childNodes[i].row)
7900
+ );
7901
+ childNodes.splice(insertPos, 0, removedNode);
7902
+ }
7903
+ const parentIterators = [];
7904
+ let threw = false;
7905
+ try {
7906
+ for (const childNode of childNodes) {
7907
+ const constraintFromChild = {};
7908
+ for (let i = 0; i < this.#parentKey.length; i++) {
7909
+ constraintFromChild[this.#parentKey[i]] = childNode.row[this.#childKey[i]];
7910
+ }
7911
+ if (req.constraint && !constraintsAreCompatible(constraintFromChild, req.constraint)) {
7912
+ parentIterators.push(emptyArray[Symbol.iterator]());
7913
+ } else {
7914
+ const stream = this.#parent.fetch({
7915
+ ...req,
7916
+ constraint: {
7917
+ ...req.constraint,
7918
+ ...constraintFromChild
7919
+ }
7920
+ });
7921
+ const iterator2 = stream[Symbol.iterator]();
7922
+ parentIterators.push(iterator2);
7923
+ }
7924
+ }
7925
+ const nextParentNodes = [];
7926
+ for (let i = 0; i < parentIterators.length; i++) {
7927
+ const iter = parentIterators[i];
7928
+ const result = iter.next();
7929
+ nextParentNodes[i] = result.done ? null : result.value;
7930
+ }
7931
+ while (true) {
7932
+ let minParentNode = null;
7933
+ let minParentNodeChildIndexes = [];
7934
+ for (let i = 0; i < nextParentNodes.length; i++) {
7935
+ const parentNode = nextParentNodes[i];
7936
+ if (parentNode === null) {
7937
+ continue;
7938
+ }
7939
+ if (minParentNode === null) {
7940
+ minParentNode = parentNode;
7941
+ minParentNodeChildIndexes.push(i);
7942
+ } else {
7943
+ const compareResult = this.#schema.compareRows(parentNode.row, minParentNode.row) * (req.reverse ? -1 : 1);
7944
+ if (compareResult === 0) {
7945
+ minParentNodeChildIndexes.push(i);
7946
+ } else if (compareResult < 0) {
7947
+ minParentNode = parentNode;
7948
+ minParentNodeChildIndexes = [i];
7949
+ }
7950
+ }
7951
+ }
7952
+ if (minParentNode === null) {
7953
+ return;
7954
+ }
7955
+ const relatedChildNodes = [];
7956
+ for (const minParentNodeChildIndex of minParentNodeChildIndexes) {
7957
+ relatedChildNodes.push(childNodes[minParentNodeChildIndex]);
7958
+ const iter = parentIterators[minParentNodeChildIndex];
7959
+ const result = iter.next();
7960
+ nextParentNodes[minParentNodeChildIndex] = result.done ? null : result.value;
7961
+ }
7962
+ let overlaidRelatedChildNodes = relatedChildNodes;
7963
+ if (this.#inprogressChildChange && this.#inprogressChildChange.position && isJoinMatch(
7964
+ this.#inprogressChildChange.change.node.row,
7965
+ this.#childKey,
7966
+ minParentNode.row,
7967
+ this.#parentKey
7968
+ )) {
7969
+ const hasInprogressChildChangeBeenPushedForMinParentNode = this.#parent.getSchema().compareRows(
7970
+ minParentNode.row,
7971
+ this.#inprogressChildChange.position
7972
+ ) <= 0;
7973
+ if (this.#inprogressChildChange.change.type === "remove") {
7974
+ if (hasInprogressChildChangeBeenPushedForMinParentNode) {
7975
+ overlaidRelatedChildNodes = relatedChildNodes.filter(
7976
+ (n) => n !== this.#inprogressChildChange?.change.node
7977
+ );
7978
+ }
7979
+ } else if (!hasInprogressChildChangeBeenPushedForMinParentNode) {
7980
+ overlaidRelatedChildNodes = [
7981
+ ...generateWithOverlay(
7982
+ relatedChildNodes,
7983
+ this.#inprogressChildChange.change,
7984
+ this.#child.getSchema()
7985
+ )
7986
+ ];
7987
+ }
7988
+ }
7989
+ if (overlaidRelatedChildNodes.length > 0) {
7990
+ yield {
7991
+ ...minParentNode,
7992
+ relationships: {
7993
+ ...minParentNode.relationships,
7994
+ [this.#relationshipName]: () => overlaidRelatedChildNodes
7995
+ }
7996
+ };
7997
+ }
7998
+ }
7999
+ } catch (e) {
8000
+ threw = true;
8001
+ for (const iter of parentIterators) {
8002
+ try {
8003
+ iter.throw?.(e);
8004
+ } catch (_cleanupError) {
8005
+ }
8006
+ }
8007
+ throw e;
8008
+ } finally {
8009
+ if (!threw) {
8010
+ for (const iter of parentIterators) {
8011
+ try {
8012
+ iter.return?.();
8013
+ } catch (_cleanupError) {
8014
+ }
8015
+ }
8016
+ }
8017
+ }
8018
+ }
8019
+ *cleanup(_req) {
8020
+ }
8021
+ #pushChild(change) {
8022
+ const pushChildChange = (exists) => {
8023
+ this.#inprogressChildChange = {
8024
+ change,
8025
+ position: void 0
8026
+ };
8027
+ try {
8028
+ const parentNodeStream = this.#parent.fetch({
8029
+ constraint: Object.fromEntries(
8030
+ this.#parentKey.map((key, i) => [
8031
+ key,
8032
+ change.node.row[this.#childKey[i]]
8033
+ ])
8034
+ )
8035
+ });
8036
+ for (const parentNode of parentNodeStream) {
8037
+ this.#inprogressChildChange = {
8038
+ change,
8039
+ position: parentNode.row
8040
+ };
8041
+ const childNodeStream = () => this.#child.fetch({
8042
+ constraint: Object.fromEntries(
8043
+ this.#childKey.map((key, i) => [
8044
+ key,
8045
+ parentNode.row[this.#parentKey[i]]
8046
+ ])
8047
+ )
8048
+ });
8049
+ if (!exists) {
8050
+ for (const childNode of childNodeStream()) {
8051
+ if (this.#child.getSchema().compareRows(childNode.row, change.node.row) !== 0) {
8052
+ exists = true;
8053
+ break;
8054
+ }
8055
+ }
8056
+ }
8057
+ if (exists) {
8058
+ this.#output.push(
8059
+ {
8060
+ type: "child",
8061
+ node: {
8062
+ ...parentNode,
8063
+ relationships: {
8064
+ ...parentNode.relationships,
8065
+ [this.#relationshipName]: childNodeStream
8066
+ }
8067
+ },
8068
+ child: {
8069
+ relationshipName: this.#relationshipName,
8070
+ change
8071
+ }
8072
+ },
8073
+ this
8074
+ );
8075
+ } else {
8076
+ this.#output.push(
8077
+ {
8078
+ ...change,
8079
+ node: {
8080
+ ...parentNode,
8081
+ relationships: {
8082
+ ...parentNode.relationships,
8083
+ [this.#relationshipName]: () => [change.node]
8084
+ }
8085
+ }
8086
+ },
8087
+ this
8088
+ );
8089
+ }
8090
+ }
8091
+ } finally {
8092
+ this.#inprogressChildChange = void 0;
8093
+ }
8094
+ };
8095
+ switch (change.type) {
8096
+ case "add":
8097
+ case "remove":
8098
+ pushChildChange();
8099
+ break;
8100
+ case "edit": {
8101
+ assert(
8102
+ rowEqualsForCompoundKey(
8103
+ change.oldNode.row,
8104
+ change.node.row,
8105
+ this.#childKey
8106
+ ),
8107
+ `Child edit must not change relationship.`
8108
+ );
8109
+ pushChildChange(true);
8110
+ break;
8111
+ }
8112
+ case "child":
8113
+ pushChildChange(true);
8114
+ break;
8115
+ }
8116
+ }
8117
+ #pushParent(change) {
8118
+ const childNodeStream = (node) => () => this.#child.fetch({
8119
+ constraint: Object.fromEntries(
8120
+ this.#childKey.map((key, i) => [key, node.row[this.#parentKey[i]]])
8121
+ )
8122
+ });
8123
+ const flip = (node) => ({
8124
+ ...node,
8125
+ relationships: {
8126
+ ...node.relationships,
8127
+ [this.#relationshipName]: childNodeStream(node)
8128
+ }
8129
+ });
8130
+ if (first(childNodeStream(change.node)()) === void 0) {
8131
+ return;
8132
+ }
8133
+ switch (change.type) {
8134
+ case "add":
8135
+ case "remove":
8136
+ case "child": {
8137
+ this.#output.push(
8138
+ {
8139
+ ...change,
8140
+ node: flip(change.node)
8141
+ },
8142
+ this
8143
+ );
8144
+ break;
8145
+ }
8146
+ case "edit": {
8147
+ assert(
8148
+ rowEqualsForCompoundKey(
8149
+ change.oldNode.row,
8150
+ change.node.row,
8151
+ this.#parentKey
8152
+ ),
8153
+ `Parent edit must not change relationship.`
8154
+ );
8155
+ this.#output.push(
8156
+ {
8157
+ type: "edit",
8158
+ oldNode: flip(change.oldNode),
8159
+ node: flip(change.node)
8160
+ },
8161
+ this
8162
+ );
8163
+ break;
8164
+ }
8165
+ default:
8166
+ unreachable(change);
8167
+ }
8168
+ }
8169
+ };
8170
+
8171
+ // ../zql/src/ivm/join.ts
8172
+ var Join = class {
8173
+ #parent;
8174
+ #child;
8175
+ #storage;
8176
+ #parentKey;
8177
+ #childKey;
8178
+ #relationshipName;
8179
+ #schema;
8180
+ #output = throwOutput;
8181
+ #inprogressChildChange;
8182
+ constructor({
8183
+ parent,
8184
+ child,
8185
+ storage,
8186
+ parentKey,
8187
+ childKey,
8188
+ relationshipName,
8189
+ hidden,
8190
+ system
8191
+ }) {
8192
+ assert(parent !== child, "Parent and child must be different operators");
8193
+ assert(
8194
+ parentKey.length === childKey.length,
8195
+ "The parentKey and childKey keys must have same length"
8196
+ );
8197
+ this.#parent = parent;
8198
+ this.#child = child;
8199
+ this.#storage = storage;
8200
+ this.#parentKey = parentKey;
8201
+ this.#childKey = childKey;
8202
+ this.#relationshipName = relationshipName;
8203
+ const parentSchema = parent.getSchema();
8204
+ const childSchema = child.getSchema();
8205
+ this.#schema = {
8206
+ ...parentSchema,
8207
+ relationships: {
8208
+ ...parentSchema.relationships,
8209
+ [relationshipName]: {
8210
+ ...childSchema,
8211
+ isHidden: hidden,
8212
+ system
8213
+ }
8214
+ }
8215
+ };
8216
+ parent.setOutput({
8217
+ push: (change) => this.#pushParent(change)
8218
+ });
8219
+ child.setOutput({
8220
+ push: (change) => this.#pushChild(change)
8221
+ });
8222
+ }
8223
+ destroy() {
8224
+ this.#parent.destroy();
8225
+ this.#child.destroy();
8226
+ }
8227
+ setOutput(output) {
8228
+ this.#output = output;
8229
+ }
8230
+ getSchema() {
8231
+ return this.#schema;
8232
+ }
8233
+ *fetch(req) {
8234
+ for (const parentNode of this.#parent.fetch(req)) {
8235
+ yield this.#processParentNode(
8236
+ parentNode.row,
8237
+ parentNode.relationships,
8238
+ "fetch"
8239
+ );
8240
+ }
8241
+ }
8242
+ *cleanup(req) {
8243
+ for (const parentNode of this.#parent.cleanup(req)) {
8244
+ yield this.#processParentNode(
8245
+ parentNode.row,
8246
+ parentNode.relationships,
8247
+ "cleanup"
8248
+ );
8249
+ }
8250
+ }
8251
+ #pushParent(change) {
8252
+ switch (change.type) {
8253
+ case "add":
8254
+ this.#output.push(
8255
+ {
8256
+ type: "add",
8257
+ node: this.#processParentNode(
8258
+ change.node.row,
8259
+ change.node.relationships,
8260
+ "fetch"
8261
+ )
8262
+ },
8263
+ this
8264
+ );
8265
+ break;
8266
+ case "remove":
8267
+ this.#output.push(
8268
+ {
8269
+ type: "remove",
8270
+ node: this.#processParentNode(
8271
+ change.node.row,
8272
+ change.node.relationships,
8273
+ "cleanup"
8274
+ )
8275
+ },
8276
+ this
8277
+ );
8278
+ break;
8279
+ case "child":
8280
+ this.#output.push(
8281
+ {
8282
+ type: "child",
8283
+ node: this.#processParentNode(
8284
+ change.node.row,
8285
+ change.node.relationships,
8286
+ "fetch"
8287
+ ),
8288
+ child: change.child
8289
+ },
8290
+ this
8291
+ );
8292
+ break;
8293
+ case "edit": {
8294
+ assert(
8295
+ rowEqualsForCompoundKey(
8296
+ change.oldNode.row,
8297
+ change.node.row,
8298
+ this.#parentKey
8299
+ ),
8300
+ `Parent edit must not change relationship.`
8301
+ );
8302
+ this.#output.push(
8303
+ {
8304
+ type: "edit",
8305
+ oldNode: this.#processParentNode(
8306
+ change.oldNode.row,
8307
+ change.oldNode.relationships,
8308
+ "cleanup"
8309
+ ),
8310
+ node: this.#processParentNode(
8311
+ change.node.row,
8312
+ change.node.relationships,
8313
+ "fetch"
8314
+ )
8315
+ },
8316
+ this
8317
+ );
8318
+ break;
8319
+ }
8320
+ default:
8321
+ unreachable(change);
8322
+ }
8323
+ }
8324
+ #pushChild(change) {
8325
+ const pushChildChange = (childRow, change2) => {
8326
+ this.#inprogressChildChange = {
8327
+ change: change2,
8328
+ position: void 0
8329
+ };
8330
+ try {
8331
+ const parentNodes = this.#parent.fetch({
8332
+ constraint: Object.fromEntries(
8333
+ this.#parentKey.map((key, i) => [key, childRow[this.#childKey[i]]])
8334
+ )
8335
+ });
8336
+ for (const parentNode of parentNodes) {
8337
+ this.#inprogressChildChange.position = parentNode.row;
8338
+ const childChange = {
8339
+ type: "child",
8340
+ node: this.#processParentNode(
8341
+ parentNode.row,
8342
+ parentNode.relationships,
8343
+ "fetch"
8344
+ ),
8345
+ child: {
8346
+ relationshipName: this.#relationshipName,
8347
+ change: change2
8348
+ }
8349
+ };
8350
+ this.#output.push(childChange, this);
8351
+ }
8352
+ } finally {
8353
+ this.#inprogressChildChange = void 0;
8354
+ }
8355
+ };
8356
+ switch (change.type) {
8357
+ case "add":
8358
+ case "remove":
8359
+ pushChildChange(change.node.row, change);
8360
+ break;
8361
+ case "child":
8362
+ pushChildChange(change.node.row, change);
8363
+ break;
8364
+ case "edit": {
8365
+ const childRow = change.node.row;
8366
+ const oldChildRow = change.oldNode.row;
8367
+ assert(
8368
+ rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey),
8369
+ "Child edit must not change relationship."
8370
+ );
8371
+ pushChildChange(childRow, change);
8372
+ break;
8373
+ }
8374
+ default:
8375
+ unreachable(change);
8376
+ }
8377
+ }
8378
+ #processParentNode(parentNodeRow, parentNodeRelations, mode) {
8379
+ let method = mode;
8380
+ let storageUpdated = false;
8381
+ const childStream = () => {
8382
+ if (!storageUpdated) {
8383
+ if (mode === "cleanup") {
8384
+ this.#storage.del(
8385
+ makeStorageKey(
8386
+ this.#parentKey,
8387
+ this.#parent.getSchema().primaryKey,
8388
+ parentNodeRow
8389
+ )
8390
+ );
8391
+ const empty = [
8392
+ ...take(
8393
+ this.#storage.scan({
8394
+ prefix: makeStorageKeyPrefix(parentNodeRow, this.#parentKey)
8395
+ }),
8396
+ 1
8397
+ )
8398
+ ].length === 0;
8399
+ method = empty ? "cleanup" : "fetch";
8400
+ }
8401
+ storageUpdated = true;
8402
+ if (mode === "fetch") {
8403
+ this.#storage.set(
8404
+ makeStorageKey(
8405
+ this.#parentKey,
8406
+ this.#parent.getSchema().primaryKey,
8407
+ parentNodeRow
8408
+ ),
8409
+ true
8410
+ );
8411
+ }
8412
+ }
8413
+ const stream = this.#child[method]({
8414
+ constraint: Object.fromEntries(
8415
+ this.#childKey.map((key, i) => [
8416
+ key,
8417
+ parentNodeRow[this.#parentKey[i]]
8418
+ ])
8419
+ )
8420
+ });
8421
+ if (this.#inprogressChildChange && isJoinMatch(
8422
+ parentNodeRow,
8423
+ this.#parentKey,
8424
+ this.#inprogressChildChange.change.node.row,
8425
+ this.#childKey
8426
+ ) && this.#inprogressChildChange.position && this.#schema.compareRows(
8427
+ parentNodeRow,
8428
+ this.#inprogressChildChange.position
8429
+ ) > 0) {
8430
+ return generateWithOverlay(
8431
+ stream,
8432
+ this.#inprogressChildChange.change,
8433
+ this.#child.getSchema()
8434
+ );
8435
+ }
8436
+ return stream;
8437
+ };
8438
+ return {
8439
+ row: parentNodeRow,
8440
+ relationships: {
8441
+ ...parentNodeRelations,
8442
+ [this.#relationshipName]: childStream
8443
+ }
8444
+ };
8445
+ }
8446
+ };
8447
+ function makeStorageKeyForValues(values) {
8448
+ const json2 = JSON.stringify(["pKeySet", ...values]);
8449
+ return json2.substring(1, json2.length - 1) + ",";
8450
+ }
8451
+ function makeStorageKeyPrefix(row, key) {
8452
+ return makeStorageKeyForValues(key.map((k) => row[k]));
8453
+ }
8454
+ function makeStorageKey(key, primaryKey, row) {
8455
+ const values = key.map((k) => row[k]);
8456
+ for (const key2 of primaryKey) {
8457
+ values.push(row[key2]);
8458
+ }
8459
+ return makeStorageKeyForValues(values);
8460
+ }
8461
+
8462
+ // ../zql/src/ivm/skip.ts
8463
+ var Skip = class {
8464
+ #input;
8465
+ #bound;
8466
+ #comparator;
8467
+ #output = throwOutput;
8468
+ constructor(input, bound) {
8469
+ this.#input = input;
8470
+ this.#bound = bound;
8471
+ this.#comparator = input.getSchema().compareRows;
8472
+ input.setOutput(this);
8473
+ }
8474
+ getSchema() {
8475
+ return this.#input.getSchema();
8476
+ }
8477
+ fetch(req) {
8478
+ return this.#fetchOrCleanup("fetch", req);
8479
+ }
8480
+ cleanup(req) {
8481
+ return this.#fetchOrCleanup("fetch", req);
8482
+ }
8483
+ *#fetchOrCleanup(method, req) {
8484
+ const start = this.#getStart(req);
8485
+ if (start === "empty") {
8486
+ return;
8487
+ }
8488
+ const nodes = this.#input[method]({ ...req, start });
8489
+ if (!req.reverse) {
8490
+ yield* nodes;
8491
+ return;
8492
+ }
8493
+ for (const node of nodes) {
8494
+ if (!this.#shouldBePresent(node.row)) {
8495
+ return;
8496
+ }
8497
+ yield node;
8498
+ }
8499
+ }
8500
+ setOutput(output) {
8501
+ this.#output = output;
8502
+ }
8503
+ destroy() {
8504
+ this.#input.destroy();
8505
+ }
8506
+ #shouldBePresent(row) {
8507
+ const cmp2 = this.#comparator(this.#bound.row, row);
8508
+ return cmp2 < 0 || cmp2 === 0 && !this.#bound.exclusive;
8509
+ }
8510
+ push(change) {
8511
+ const shouldBePresent = (row) => this.#shouldBePresent(row);
8512
+ if (change.type === "edit") {
8513
+ maybeSplitAndPushEditChange(change, shouldBePresent, this.#output, this);
8514
+ return;
8515
+ }
8516
+ change;
8517
+ if (shouldBePresent(change.node.row)) {
8518
+ this.#output.push(change, this);
8519
+ }
8520
+ }
8521
+ #getStart(req) {
8522
+ const boundStart = {
8523
+ row: this.#bound.row,
8524
+ basis: this.#bound.exclusive ? "after" : "at"
8525
+ };
8526
+ if (!req.start) {
8527
+ if (req.reverse) {
8528
+ return void 0;
8529
+ }
8530
+ return boundStart;
8531
+ }
8532
+ const cmp2 = this.#comparator(this.#bound.row, req.start.row);
8533
+ if (!req.reverse) {
8534
+ if (cmp2 > 0) {
8535
+ return boundStart;
8536
+ }
8537
+ if (cmp2 === 0) {
8538
+ if (this.#bound.exclusive || req.start.basis === "after") {
8539
+ return {
8540
+ row: this.#bound.row,
8541
+ basis: "after"
8542
+ };
8543
+ }
8544
+ return boundStart;
8545
+ }
8546
+ return req.start;
8547
+ }
8548
+ req.reverse;
8549
+ if (cmp2 > 0) {
8550
+ return "empty";
8551
+ }
8552
+ if (cmp2 === 0) {
8553
+ if (!this.#bound.exclusive && req.start.basis === "at") {
8554
+ return boundStart;
8555
+ }
8556
+ return "empty";
8557
+ }
8558
+ return req.start;
8559
+ }
8560
+ };
8561
+
8562
+ // ../zql/src/ivm/take.ts
8563
+ var MAX_BOUND_KEY = "maxBound";
8564
+ var Take = class {
8565
+ #input;
8566
+ #storage;
8567
+ #limit;
8568
+ #partitionKey;
8569
+ #partitionKeyComparator;
8570
+ // Fetch overlay needed for some split push cases.
8571
+ #rowHiddenFromFetch;
8572
+ #output = throwOutput;
8573
+ constructor(input, storage, limit, partitionKey) {
8574
+ assert(limit >= 0);
8575
+ assertOrderingIncludesPK(
8576
+ input.getSchema().sort,
8577
+ input.getSchema().primaryKey
8578
+ );
8579
+ input.setOutput(this);
8580
+ this.#input = input;
8581
+ this.#storage = storage;
8582
+ this.#limit = limit;
8583
+ this.#partitionKey = partitionKey;
8584
+ this.#partitionKeyComparator = partitionKey && makePartitionKeyComparator(partitionKey);
8585
+ }
8586
+ setOutput(output) {
8587
+ this.#output = output;
8588
+ }
8589
+ getSchema() {
8590
+ return this.#input.getSchema();
8591
+ }
8592
+ *fetch(req) {
8593
+ if (!this.#partitionKey || req.constraint && constraintMatchesPartitionKey(req.constraint, this.#partitionKey)) {
8594
+ const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);
8595
+ const takeState = this.#storage.get(takeStateKey);
8596
+ if (!takeState) {
8597
+ yield* this.#initialFetch(req);
8598
+ return;
8599
+ }
8600
+ if (takeState.bound === void 0) {
8601
+ return;
8602
+ }
8603
+ for (const inputNode of this.#input.fetch(req)) {
8604
+ if (this.getSchema().compareRows(takeState.bound, inputNode.row) < 0) {
8605
+ return;
8606
+ }
8607
+ if (this.#rowHiddenFromFetch && this.getSchema().compareRows(
8608
+ this.#rowHiddenFromFetch,
8609
+ inputNode.row
8610
+ ) === 0) {
8611
+ continue;
8612
+ }
8613
+ yield inputNode;
8614
+ }
8615
+ return;
8616
+ }
8617
+ const maxBound = this.#storage.get(MAX_BOUND_KEY);
8618
+ if (maxBound === void 0) {
8619
+ return;
8620
+ }
8621
+ for (const inputNode of this.#input.fetch(req)) {
8622
+ if (this.getSchema().compareRows(inputNode.row, maxBound) > 0) {
8623
+ return;
8624
+ }
8625
+ const takeStateKey = getTakeStateKey(this.#partitionKey, inputNode.row);
8626
+ const takeState = this.#storage.get(takeStateKey);
8627
+ if (takeState?.bound !== void 0 && this.getSchema().compareRows(takeState.bound, inputNode.row) >= 0) {
8628
+ yield inputNode;
8629
+ }
8630
+ }
8631
+ }
8632
+ *#initialFetch(req) {
8633
+ assert(req.start === void 0);
8634
+ assert(!req.reverse);
8635
+ assert(constraintMatchesPartitionKey(req.constraint, this.#partitionKey));
8636
+ if (this.#limit === 0) {
8637
+ return;
8638
+ }
8639
+ const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);
8640
+ assert(this.#storage.get(takeStateKey) === void 0);
8641
+ let size = 0;
8642
+ let bound;
8643
+ let downstreamEarlyReturn = true;
8644
+ let exceptionThrown = false;
8645
+ try {
8646
+ for (const inputNode of this.#input.fetch(req)) {
8647
+ yield inputNode;
8648
+ bound = inputNode.row;
8649
+ size++;
8650
+ if (size === this.#limit) {
8651
+ break;
8652
+ }
8653
+ }
8654
+ downstreamEarlyReturn = false;
8655
+ } catch (e) {
8656
+ exceptionThrown = true;
8657
+ throw e;
8658
+ } finally {
8659
+ if (!exceptionThrown) {
8660
+ this.#setTakeState(
8661
+ takeStateKey,
8662
+ size,
8663
+ bound,
8664
+ this.#storage.get(MAX_BOUND_KEY)
8665
+ );
8666
+ assert(
8667
+ !downstreamEarlyReturn,
8668
+ "Unexpected early return prevented full hydration"
8669
+ );
8670
+ }
8671
+ }
8672
+ }
8673
+ *cleanup(req) {
8674
+ assert(req.start === void 0);
8675
+ assert(constraintMatchesPartitionKey(req.constraint, this.#partitionKey));
8676
+ const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);
8677
+ this.#storage.del(takeStateKey);
8678
+ let size = 0;
8679
+ for (const inputNode of this.#input.cleanup(req)) {
8680
+ if (size === this.#limit) {
8681
+ return;
8682
+ }
8683
+ size++;
8684
+ yield inputNode;
8685
+ }
8686
+ }
8687
+ #getStateAndConstraint(row) {
8688
+ const takeStateKey = getTakeStateKey(this.#partitionKey, row);
8689
+ const takeState = this.#storage.get(takeStateKey);
8690
+ let maxBound;
8691
+ let constraint;
8692
+ if (takeState) {
8693
+ maxBound = this.#storage.get(MAX_BOUND_KEY);
8694
+ constraint = this.#partitionKey && Object.fromEntries(
8695
+ this.#partitionKey.map((key) => [key, row[key]])
8696
+ );
8697
+ }
8698
+ return { takeState, takeStateKey, maxBound, constraint };
8699
+ }
8700
+ push(change) {
8701
+ if (change.type === "edit") {
8702
+ this.#pushEditChange(change);
8703
+ return;
8704
+ }
8705
+ const { takeState, takeStateKey, maxBound, constraint } = this.#getStateAndConstraint(change.node.row);
8706
+ if (!takeState) {
8707
+ return;
8708
+ }
8709
+ const { compareRows } = this.getSchema();
8710
+ if (change.type === "add") {
8711
+ if (takeState.size < this.#limit) {
8712
+ this.#setTakeState(
8713
+ takeStateKey,
8714
+ takeState.size + 1,
8715
+ takeState.bound === void 0 || compareRows(takeState.bound, change.node.row) < 0 ? change.node.row : takeState.bound,
8716
+ maxBound
8717
+ );
8718
+ this.#output.push(change, this);
8719
+ return;
8720
+ }
8721
+ if (takeState.bound === void 0 || compareRows(change.node.row, takeState.bound) >= 0) {
8722
+ return;
8723
+ }
8724
+ let beforeBoundNode;
8725
+ let boundNode;
8726
+ if (this.#limit === 1) {
8727
+ boundNode = must(
8728
+ first(
8729
+ this.#input.fetch({
8730
+ start: {
8731
+ row: takeState.bound,
8732
+ basis: "at"
8733
+ },
8734
+ constraint
8735
+ })
8736
+ )
8737
+ );
8738
+ } else {
8739
+ [boundNode, beforeBoundNode] = take(
8740
+ this.#input.fetch({
8741
+ start: {
8742
+ row: takeState.bound,
8743
+ basis: "at"
8744
+ },
8745
+ constraint,
8746
+ reverse: true
8747
+ }),
8748
+ 2
8749
+ );
8750
+ }
8751
+ const removeChange = {
8752
+ type: "remove",
8753
+ node: boundNode
8754
+ };
8755
+ this.#setTakeState(
8756
+ takeStateKey,
8757
+ takeState.size,
8758
+ beforeBoundNode === void 0 || compareRows(change.node.row, beforeBoundNode.row) > 0 ? change.node.row : beforeBoundNode.row,
8759
+ maxBound
8760
+ );
8761
+ this.#withRowHiddenFromFetch(change.node.row, () => {
8762
+ this.#output.push(removeChange, this);
8763
+ });
8764
+ this.#output.push(change, this);
8765
+ } else if (change.type === "remove") {
8766
+ if (takeState.bound === void 0) {
8767
+ return;
8768
+ }
8769
+ const compToBound = compareRows(change.node.row, takeState.bound);
8770
+ if (compToBound > 0) {
8771
+ return;
8772
+ }
8773
+ const [beforeBoundNode] = take(
8774
+ this.#input.fetch({
8775
+ start: {
8776
+ row: takeState.bound,
8777
+ basis: "after"
8778
+ },
8779
+ constraint,
8780
+ reverse: true
8781
+ }),
8782
+ 1
8783
+ );
8784
+ let newBound;
8785
+ if (beforeBoundNode) {
8786
+ const push2 = compareRows(beforeBoundNode.row, takeState.bound) > 0;
8787
+ newBound = {
8788
+ node: beforeBoundNode,
8789
+ push: push2
8790
+ };
8791
+ }
8792
+ if (!newBound?.push) {
8793
+ for (const node of this.#input.fetch({
8794
+ start: {
8795
+ row: takeState.bound,
8796
+ basis: "at"
8797
+ },
8798
+ constraint
8799
+ })) {
8800
+ const push2 = compareRows(node.row, takeState.bound) > 0;
8801
+ newBound = {
8802
+ node,
8803
+ push: push2
8804
+ };
8805
+ if (push2) {
8806
+ break;
8807
+ }
8808
+ }
8809
+ }
8810
+ if (newBound?.push) {
8811
+ this.#output.push(change, this);
8812
+ this.#setTakeState(
8813
+ takeStateKey,
8814
+ takeState.size,
8815
+ newBound.node.row,
8816
+ maxBound
8817
+ );
8818
+ this.#output.push(
8819
+ {
8820
+ type: "add",
8821
+ node: newBound.node
8822
+ },
8823
+ this
8824
+ );
8825
+ return;
8826
+ }
8827
+ this.#setTakeState(
8828
+ takeStateKey,
8829
+ takeState.size - 1,
8830
+ newBound?.node.row,
8831
+ maxBound
8832
+ );
8833
+ this.#output.push(change, this);
8834
+ } else if (change.type === "child") {
8835
+ if (takeState.bound && compareRows(change.node.row, takeState.bound) <= 0) {
8836
+ this.#output.push(change, this);
8837
+ }
8838
+ }
8839
+ }
8840
+ #pushEditChange(change) {
8841
+ assert(
8842
+ !this.#partitionKeyComparator || this.#partitionKeyComparator(change.oldNode.row, change.node.row) === 0,
8843
+ "Unexpected change of partition key"
8844
+ );
8845
+ const { takeState, takeStateKey, maxBound, constraint } = this.#getStateAndConstraint(change.oldNode.row);
8846
+ if (!takeState) {
8847
+ return;
8848
+ }
8849
+ assert(takeState.bound, "Bound should be set");
8850
+ const { compareRows } = this.getSchema();
8851
+ const oldCmp = compareRows(change.oldNode.row, takeState.bound);
8852
+ const newCmp = compareRows(change.node.row, takeState.bound);
8853
+ const replaceBoundAndForwardChange = () => {
8854
+ this.#setTakeState(
8855
+ takeStateKey,
8856
+ takeState.size,
8857
+ change.node.row,
8858
+ maxBound
8859
+ );
8860
+ this.#output.push(change, this);
8861
+ };
8862
+ if (oldCmp === 0) {
8863
+ if (newCmp === 0) {
8864
+ this.#output.push(change, this);
8865
+ return;
8866
+ }
8867
+ if (newCmp < 0) {
8868
+ if (this.#limit === 1) {
8869
+ replaceBoundAndForwardChange();
8870
+ return;
8871
+ }
8872
+ const beforeBoundNode = must(
8873
+ first(
8874
+ this.#input.fetch({
8875
+ start: {
8876
+ row: takeState.bound,
8877
+ basis: "after"
8878
+ },
8879
+ constraint,
8880
+ reverse: true
8881
+ })
8882
+ )
8883
+ );
8884
+ this.#setTakeState(
8885
+ takeStateKey,
8886
+ takeState.size,
8887
+ beforeBoundNode.row,
8888
+ maxBound
8889
+ );
8890
+ this.#output.push(change, this);
8891
+ return;
8892
+ }
8893
+ assert(newCmp > 0);
8894
+ const newBoundNode = must(
8895
+ first(
8896
+ this.#input.fetch({
8897
+ start: {
8898
+ row: takeState.bound,
8899
+ basis: "at"
8900
+ },
8901
+ constraint
8902
+ })
8903
+ )
8904
+ );
8905
+ if (compareRows(newBoundNode.row, change.node.row) === 0) {
8906
+ replaceBoundAndForwardChange();
8907
+ return;
8908
+ }
8909
+ this.#setTakeState(
8910
+ takeStateKey,
8911
+ takeState.size,
8912
+ newBoundNode.row,
8913
+ maxBound
8914
+ );
8915
+ this.#withRowHiddenFromFetch(newBoundNode.row, () => {
8916
+ this.#output.push(
8917
+ {
8918
+ type: "remove",
8919
+ node: change.oldNode
8920
+ },
8921
+ this
8922
+ );
8923
+ });
8924
+ this.#output.push(
8925
+ {
8926
+ type: "add",
8927
+ node: newBoundNode
8928
+ },
8929
+ this
8930
+ );
8931
+ return;
8932
+ }
8933
+ if (oldCmp > 0) {
8934
+ assert(newCmp !== 0, "Invalid state. Row has duplicate primary key");
8935
+ if (newCmp > 0) {
8936
+ return;
8937
+ }
8938
+ assert(newCmp < 0);
8939
+ const [oldBoundNode, newBoundNode] = take(
8940
+ this.#input.fetch({
8941
+ start: {
8942
+ row: takeState.bound,
8943
+ basis: "at"
8944
+ },
8945
+ constraint,
8946
+ reverse: true
8947
+ }),
8948
+ 2
8949
+ );
8950
+ this.#setTakeState(
8951
+ takeStateKey,
8952
+ takeState.size,
8953
+ newBoundNode.row,
8954
+ maxBound
8955
+ );
8956
+ this.#withRowHiddenFromFetch(change.node.row, () => {
8957
+ this.#output.push(
8958
+ {
8959
+ type: "remove",
8960
+ node: oldBoundNode
8961
+ },
8962
+ this
8963
+ );
8964
+ });
8965
+ this.#output.push(
8966
+ {
8967
+ type: "add",
8968
+ node: change.node
8969
+ },
8970
+ this
8971
+ );
8972
+ return;
8973
+ }
8974
+ if (oldCmp < 0) {
8975
+ assert(newCmp !== 0, "Invalid state. Row has duplicate primary key");
8976
+ if (newCmp < 0) {
8977
+ this.#output.push(change, this);
8978
+ return;
8979
+ }
8980
+ assert(newCmp > 0);
8981
+ const afterBoundNode = must(
8982
+ first(
8983
+ this.#input.fetch({
8984
+ start: {
8985
+ row: takeState.bound,
8986
+ basis: "after"
8987
+ },
8988
+ constraint
8989
+ })
8990
+ )
8991
+ );
8992
+ if (compareRows(afterBoundNode.row, change.node.row) === 0) {
8993
+ replaceBoundAndForwardChange();
8994
+ return;
8995
+ }
8996
+ this.#output.push(
8997
+ {
8998
+ type: "remove",
8999
+ node: change.oldNode
9000
+ },
9001
+ this
9002
+ );
9003
+ this.#setTakeState(
9004
+ takeStateKey,
9005
+ takeState.size,
9006
+ afterBoundNode.row,
9007
+ maxBound
9008
+ );
9009
+ this.#output.push(
9010
+ {
9011
+ type: "add",
9012
+ node: afterBoundNode
9013
+ },
9014
+ this
9015
+ );
9016
+ return;
9017
+ }
9018
+ unreachable();
9019
+ }
9020
+ #withRowHiddenFromFetch(row, fn) {
9021
+ this.#rowHiddenFromFetch = row;
9022
+ try {
9023
+ fn();
9024
+ } finally {
9025
+ this.#rowHiddenFromFetch = void 0;
9026
+ }
9027
+ }
9028
+ #setTakeState(takeStateKey, size, bound, maxBound) {
9029
+ this.#storage.set(takeStateKey, {
9030
+ size,
9031
+ bound
9032
+ });
9033
+ if (bound !== void 0 && (maxBound === void 0 || this.getSchema().compareRows(bound, maxBound) > 0)) {
9034
+ this.#storage.set(MAX_BOUND_KEY, bound);
9035
+ }
9036
+ }
9037
+ destroy() {
9038
+ this.#input.destroy();
9039
+ }
9040
+ };
9041
+ function getTakeStateKey(partitionKey, rowOrConstraint) {
9042
+ const partitionValues = [];
9043
+ if (partitionKey && rowOrConstraint) {
9044
+ for (const key of partitionKey) {
9045
+ partitionValues.push(rowOrConstraint[key]);
9046
+ }
9047
+ }
9048
+ return JSON.stringify(["take", ...partitionValues]);
9049
+ }
9050
+ function constraintMatchesPartitionKey(constraint, partitionKey) {
9051
+ if (constraint === void 0 || partitionKey === void 0) {
9052
+ return constraint === partitionKey;
9053
+ }
9054
+ if (partitionKey.length !== Object.keys(constraint).length) {
9055
+ return false;
9056
+ }
9057
+ for (const key of partitionKey) {
9058
+ if (!hasOwn(constraint, key)) {
9059
+ return false;
9060
+ }
9061
+ }
9062
+ return true;
9063
+ }
9064
+ function makePartitionKeyComparator(partitionKey) {
9065
+ return (a, b) => {
9066
+ for (const key of partitionKey) {
9067
+ const cmp2 = compareValues(a[key], b[key]);
9068
+ if (cmp2 !== 0) {
9069
+ return cmp2;
9070
+ }
9071
+ }
9072
+ return 0;
9073
+ };
9074
+ }
9075
+
9076
+ // ../zql/src/ivm/union-fan-in.ts
9077
+ var UnionFanIn = class {
9078
+ #inputs;
9079
+ #schema;
9080
+ #fanOutPushStarted = false;
9081
+ #output = throwOutput;
9082
+ #accumulatedPushes = [];
9083
+ constructor(fanOut, inputs) {
9084
+ this.#inputs = inputs;
9085
+ const fanOutSchema = fanOut.getSchema();
9086
+ fanOut.setFanIn(this);
9087
+ const schema = {
9088
+ tableName: fanOutSchema.tableName,
9089
+ columns: fanOutSchema.columns,
9090
+ primaryKey: fanOutSchema.primaryKey,
9091
+ relationships: {
9092
+ ...fanOutSchema.relationships
9093
+ },
9094
+ isHidden: fanOutSchema.isHidden,
9095
+ system: fanOutSchema.system,
9096
+ compareRows: fanOutSchema.compareRows,
9097
+ sort: fanOutSchema.sort
9098
+ };
9099
+ const relationshipsFromBranches = /* @__PURE__ */ new Set();
9100
+ for (const input of inputs) {
9101
+ const inputSchema = input.getSchema();
9102
+ assert(
9103
+ schema.tableName === inputSchema.tableName,
9104
+ `Table name mismatch in union fan-in: ${schema.tableName} !== ${inputSchema.tableName}`
9105
+ );
9106
+ assert(
9107
+ schema.primaryKey === inputSchema.primaryKey,
9108
+ `Primary key mismatch in union fan-in`
9109
+ );
9110
+ assert(
9111
+ schema.system === inputSchema.system,
9112
+ `System mismatch in union fan-in: ${schema.system} !== ${inputSchema.system}`
9113
+ );
9114
+ assert(
9115
+ schema.compareRows === inputSchema.compareRows,
9116
+ `compareRows mismatch in union fan-in`
9117
+ );
9118
+ assert(schema.sort === inputSchema.sort, `Sort mismatch in union fan-in`);
9119
+ for (const [relName, relSchema] of Object.entries(
9120
+ inputSchema.relationships
9121
+ )) {
9122
+ if (relName in fanOutSchema.relationships) {
9123
+ continue;
9124
+ }
9125
+ assert(
9126
+ !relationshipsFromBranches.has(relName),
9127
+ `Relationship ${relName} exists in multiple upstream inputs to union fan-in`
9128
+ );
9129
+ schema.relationships[relName] = relSchema;
9130
+ relationshipsFromBranches.add(relName);
9131
+ }
9132
+ input.setOutput(this);
9133
+ }
9134
+ this.#schema = schema;
9135
+ this.#inputs = inputs;
9136
+ }
9137
+ cleanup(_req) {
9138
+ return [];
9139
+ }
9140
+ destroy() {
9141
+ for (const input of this.#inputs) {
9142
+ input.destroy();
9143
+ }
9144
+ }
9145
+ fetch(req) {
9146
+ const iterables = this.#inputs.map((input) => input.fetch(req));
9147
+ return mergeIterables(
9148
+ iterables,
9149
+ (l, r) => this.#schema.compareRows(l.row, r.row),
9150
+ true
9151
+ );
9152
+ }
9153
+ getSchema() {
9154
+ return this.#schema;
9155
+ }
9156
+ push(change, pusher) {
9157
+ if (!this.#fanOutPushStarted) {
9158
+ this.#pushInternalChange(change, pusher);
9159
+ } else {
9160
+ this.#accumulatedPushes.push(change);
9161
+ }
9162
+ }
9163
+ /**
9164
+ * An internal change means that a change was received inside the fan-out/fan-in sub-graph.
9165
+ *
9166
+ * These changes always come from children of a flip-join as no other push generating operators
9167
+ * currently exist between union-fan-in and union-fan-out. All other pushes
9168
+ * enter into union-fan-out before reaching union-fan-in.
9169
+ *
9170
+ * - normal joins for `exists` come before `union-fan-out`
9171
+ * - joins for `related` come after `union-fan-out`
9172
+ * - take comes after `union-fan-out`
9173
+ *
9174
+ * The algorithm for deciding whether or not to forward a push that came from inside the ufo/ufi sub-graph:
9175
+ * 1. If the change is a `child` change we can forward it. This is because all child branches in the ufo/ufi sub-graph are unique.
9176
+ * 2. If the change is `add` we can forward it iff no `fetches` for the row return any results.
9177
+ * If another branch has it, the add was already emitted in the past.
9178
+ * 3. If the change is `remove` we can forward it iff no `fetches` for the row return any results.
9179
+ * If no other branches have the change, the remove can be sent as the value is no longer present.
9180
+ * If other branches have it, the last branch the processes the remove will send the remove.
9181
+ * 4. Edits will always come through as child changes as flip join will flip them into children.
9182
+ * An edit that would result in a remove or add will have been split into an add/remove pair rather than being an edit.
9183
+ */
9184
+ #pushInternalChange(change, pusher) {
9185
+ if (change.type === "child") {
9186
+ this.#output.push(change, this);
9187
+ return;
9188
+ }
9189
+ assert(change.type === "add" || change.type === "remove");
9190
+ let hadMatch = false;
9191
+ for (const input of this.#inputs) {
9192
+ if (input === pusher) {
9193
+ hadMatch = true;
9194
+ continue;
9195
+ }
9196
+ const constraint = {};
9197
+ for (const key of this.#schema.primaryKey) {
9198
+ constraint[key] = change.node.row[key];
9199
+ }
9200
+ const fetchResult = input.fetch({
9201
+ constraint
9202
+ });
9203
+ if (first(fetchResult) !== void 0) {
9204
+ return;
9205
+ }
9206
+ }
9207
+ assert(hadMatch, "Pusher was not one of the inputs to union-fan-in!");
9208
+ this.#output.push(change, this);
9209
+ }
9210
+ fanOutStartedPushing() {
9211
+ assert(this.#fanOutPushStarted === false);
9212
+ this.#fanOutPushStarted = true;
9213
+ }
9214
+ fanOutDonePushing(fanOutChangeType) {
9215
+ assert(this.#fanOutPushStarted);
9216
+ this.#fanOutPushStarted = false;
9217
+ if (this.#inputs.length === 0) {
9218
+ return;
9219
+ }
9220
+ if (this.#accumulatedPushes.length === 0) {
9221
+ return;
9222
+ }
9223
+ pushAccumulatedChanges(
9224
+ this.#accumulatedPushes,
9225
+ this.#output,
9226
+ this,
9227
+ fanOutChangeType,
9228
+ mergeRelationships,
9229
+ makeAddEmptyRelationships(this.#schema)
9230
+ );
9231
+ }
9232
+ setOutput(output) {
9233
+ this.#output = output;
9234
+ }
9235
+ };
9236
+
9237
+ // ../zql/src/ivm/union-fan-out.ts
9238
+ var UnionFanOut = class {
9239
+ #destroyCount = 0;
9240
+ #unionFanIn;
9241
+ #input;
9242
+ #outputs = [];
9243
+ constructor(input) {
9244
+ this.#input = input;
9245
+ input.setOutput(this);
9246
+ }
9247
+ setFanIn(fanIn) {
9248
+ assert(!this.#unionFanIn, "FanIn already set for this FanOut");
9249
+ this.#unionFanIn = fanIn;
9250
+ }
9251
+ push(change) {
9252
+ must(this.#unionFanIn).fanOutStartedPushing();
9253
+ for (const output of this.#outputs) {
9254
+ output.push(change, this);
9255
+ }
9256
+ must(this.#unionFanIn).fanOutDonePushing(change.type);
9257
+ }
9258
+ setOutput(output) {
9259
+ this.#outputs.push(output);
9260
+ }
9261
+ getSchema() {
9262
+ return this.#input.getSchema();
9263
+ }
9264
+ fetch(req) {
9265
+ return this.#input.fetch(req);
9266
+ }
9267
+ cleanup(_req) {
9268
+ return [];
9269
+ }
9270
+ destroy() {
9271
+ if (this.#destroyCount < this.#outputs.length) {
9272
+ ++this.#destroyCount;
9273
+ if (this.#destroyCount === this.#outputs.length) {
9274
+ this.#input.destroy();
9275
+ }
9276
+ } else {
9277
+ throw new Error("FanOut already destroyed once for each output");
9278
+ }
9279
+ }
9280
+ };
9281
+
9282
+ // ../zql/src/query/expression.ts
9283
+ var ExpressionBuilder = class {
9284
+ #exists;
9285
+ constructor(exists) {
9286
+ this.#exists = exists;
9287
+ this.exists = this.exists.bind(this);
9288
+ }
9289
+ get eb() {
9290
+ return this;
9291
+ }
9292
+ cmp(field, opOrValue, value) {
9293
+ return cmp(field, opOrValue, value);
9294
+ }
9295
+ cmpLit(left, op, right) {
9296
+ return {
9297
+ type: "simple",
9298
+ left: isParameterReference(left) ? left[toStaticParam]() : { type: "literal", value: left },
9299
+ right: isParameterReference(right) ? right[toStaticParam]() : { type: "literal", value: right },
9300
+ op
9301
+ };
9302
+ }
9303
+ and = and;
9304
+ or = or;
9305
+ not = not;
9306
+ exists = (relationship, cb, options) => this.#exists(relationship, cb, options);
9307
+ };
9308
+ function and(...conditions) {
9309
+ const expressions = filterTrue(filterUndefined(conditions));
9310
+ if (expressions.length === 1) {
9311
+ return expressions[0];
9312
+ }
9313
+ if (expressions.some(isAlwaysFalse)) {
9314
+ return FALSE;
9315
+ }
9316
+ return { type: "and", conditions: expressions };
9317
+ }
9318
+ function or(...conditions) {
9319
+ const expressions = filterFalse(filterUndefined(conditions));
9320
+ if (expressions.length === 1) {
9321
+ return expressions[0];
9322
+ }
9323
+ if (expressions.some(isAlwaysTrue)) {
9324
+ return TRUE;
9325
+ }
9326
+ return { type: "or", conditions: expressions };
9327
+ }
9328
+ function not(expression) {
9329
+ switch (expression.type) {
9330
+ case "and":
9331
+ return {
9332
+ type: "or",
9333
+ conditions: expression.conditions.map(not)
9334
+ };
9335
+ case "or":
9336
+ return {
9337
+ type: "and",
9338
+ conditions: expression.conditions.map(not)
9339
+ };
9340
+ case "correlatedSubquery":
9341
+ return {
9342
+ type: "correlatedSubquery",
9343
+ related: expression.related,
9344
+ op: negateOperator(expression.op)
9345
+ };
9346
+ case "simple":
9347
+ return {
9348
+ type: "simple",
9349
+ op: negateOperator(expression.op),
9350
+ left: expression.left,
9351
+ right: expression.right
9352
+ };
9353
+ }
9354
+ }
9355
+ function cmp(field, opOrValue, value) {
9356
+ let op;
9357
+ if (value === void 0) {
9358
+ value = opOrValue;
9359
+ op = "=";
9360
+ } else {
9361
+ op = opOrValue;
9362
+ }
9363
+ return {
9364
+ type: "simple",
9365
+ left: { type: "column", name: field },
9366
+ right: isParameterReference(value) ? value[toStaticParam]() : { type: "literal", value },
9367
+ op
9368
+ };
9369
+ }
9370
+ function isParameterReference(value) {
9371
+ return value !== null && typeof value === "object" && value[toStaticParam];
9372
+ }
9373
+ var TRUE = {
9374
+ type: "and",
9375
+ conditions: []
9376
+ };
9377
+ var FALSE = {
9378
+ type: "or",
9379
+ conditions: []
9380
+ };
9381
+ function isAlwaysTrue(condition) {
9382
+ return condition.type === "and" && condition.conditions.length === 0;
9383
+ }
9384
+ function isAlwaysFalse(condition) {
9385
+ return condition.type === "or" && condition.conditions.length === 0;
9386
+ }
9387
+ function simplifyCondition(c) {
9388
+ if (c.type === "simple" || c.type === "correlatedSubquery") {
9389
+ return c;
9390
+ }
9391
+ if (c.conditions.length === 1) {
9392
+ return simplifyCondition(c.conditions[0]);
9393
+ }
9394
+ const conditions = flatten(c.type, c.conditions.map(simplifyCondition));
9395
+ if (c.type === "and" && conditions.some(isAlwaysFalse)) {
9396
+ return FALSE;
9397
+ }
9398
+ if (c.type === "or" && conditions.some(isAlwaysTrue)) {
9399
+ return TRUE;
9400
+ }
9401
+ return {
9402
+ type: c.type,
9403
+ conditions
9404
+ };
9405
+ }
9406
+ function flatten(type, conditions) {
9407
+ const flattened = [];
9408
+ for (const c of conditions) {
9409
+ if (c.type === type) {
9410
+ flattened.push(...c.conditions);
9411
+ } else {
9412
+ flattened.push(c);
9413
+ }
9414
+ }
9415
+ return flattened;
9416
+ }
9417
+ var negateSimpleOperatorMap = {
9418
+ ["="]: "!=",
9419
+ ["!="]: "=",
9420
+ ["<"]: ">=",
9421
+ [">"]: "<=",
9422
+ [">="]: "<",
9423
+ ["<="]: ">",
9424
+ ["IN"]: "NOT IN",
9425
+ ["NOT IN"]: "IN",
9426
+ ["LIKE"]: "NOT LIKE",
9427
+ ["NOT LIKE"]: "LIKE",
9428
+ ["ILIKE"]: "NOT ILIKE",
9429
+ ["NOT ILIKE"]: "ILIKE",
9430
+ ["IS"]: "IS NOT",
9431
+ ["IS NOT"]: "IS"
9432
+ };
9433
+ var negateOperatorMap = {
9434
+ ...negateSimpleOperatorMap,
9435
+ ["EXISTS"]: "NOT EXISTS",
9436
+ ["NOT EXISTS"]: "EXISTS"
9437
+ };
9438
+ function negateOperator(op) {
9439
+ return must(negateOperatorMap[op]);
9440
+ }
9441
+ function filterUndefined(array9) {
9442
+ return array9.filter((e) => e !== void 0);
9443
+ }
9444
+ function filterTrue(conditions) {
9445
+ return conditions.filter((c) => !isAlwaysTrue(c));
9446
+ }
9447
+ function filterFalse(conditions) {
9448
+ return conditions.filter((c) => !isAlwaysFalse(c));
9449
+ }
9450
+
9451
+ // ../zql/src/builder/like.ts
9452
+ function getLikePredicate(pattern, flags) {
9453
+ const op = getLikeOp(String(pattern), flags);
9454
+ return (lhs) => {
9455
+ assertString(lhs);
9456
+ return op(String(lhs));
9457
+ };
9458
+ }
9459
+ function getLikeOp(pattern, flags) {
9460
+ if (!/_|%|\\/.test(pattern)) {
9461
+ if (flags === "i") {
9462
+ const rhsLower = pattern.toLowerCase();
9463
+ return (lhs) => lhs.toLowerCase() === rhsLower;
9464
+ }
9465
+ return (lhs) => lhs === pattern;
9466
+ }
9467
+ const re = patternToRegExp(pattern, flags);
9468
+ return (lhs) => re.test(lhs);
9469
+ }
9470
+ var specialCharsRe = /[$()*+.?[\]\\^{|}]/;
9471
+ function patternToRegExp(source, flags = "") {
9472
+ let pattern = "^";
9473
+ for (let i = 0; i < source.length; i++) {
9474
+ let c = source[i];
9475
+ switch (c) {
9476
+ case "%":
9477
+ pattern += ".*";
9478
+ break;
9479
+ case "_":
9480
+ pattern += ".";
9481
+ break;
9482
+ // @ts-expect-error fallthrough
9483
+ case "\\":
9484
+ if (i === source.length - 1) {
9485
+ throw new Error("LIKE pattern must not end with escape character");
9486
+ }
9487
+ i++;
9488
+ c = source[i];
9489
+ // fall through
9490
+ default:
9491
+ if (specialCharsRe.test(c)) {
9492
+ pattern += "\\";
9493
+ }
9494
+ pattern += c;
9495
+ break;
9496
+ }
9497
+ }
9498
+ return new RegExp(pattern + "$", flags + "m");
9499
+ }
9500
+
9501
+ // ../zql/src/builder/filter.ts
9502
+ function createPredicate(condition) {
9503
+ if (condition.type !== "simple") {
9504
+ const predicates = condition.conditions.map((c) => createPredicate(c));
9505
+ return condition.type === "and" ? (row) => {
9506
+ for (const predicate of predicates) {
9507
+ if (!predicate(row)) {
9508
+ return false;
9509
+ }
9510
+ }
9511
+ return true;
9512
+ } : (row) => {
9513
+ for (const predicate of predicates) {
9514
+ if (predicate(row)) {
9515
+ return true;
9516
+ }
9517
+ }
9518
+ return false;
9519
+ };
9520
+ }
9521
+ const { left } = condition;
9522
+ const { right } = condition;
9523
+ assert(
9524
+ right.type !== "static",
9525
+ "static values should be resolved before creating predicates"
9526
+ );
9527
+ assert(
9528
+ left.type !== "static",
9529
+ "static values should be resolved before creating predicates"
9530
+ );
9531
+ switch (condition.op) {
9532
+ case "IS":
9533
+ case "IS NOT": {
9534
+ const impl2 = createIsPredicate(right.value, condition.op);
9535
+ if (left.type === "literal") {
9536
+ const result = impl2(left.value);
9537
+ return () => result;
9538
+ }
9539
+ return (row) => impl2(row[left.name]);
9540
+ }
9541
+ }
9542
+ if (right.value === null || right.value === void 0) {
9543
+ return (_row) => false;
9544
+ }
9545
+ const impl = createPredicateImpl(right.value, condition.op);
9546
+ if (left.type === "literal") {
9547
+ if (left.value === null || left.value === void 0) {
9548
+ return (_row) => false;
9549
+ }
9550
+ const result = impl(left.value);
9551
+ return () => result;
9552
+ }
9553
+ return (row) => {
9554
+ const lhs = row[left.name];
9555
+ if (lhs === null || lhs === void 0) {
9556
+ return false;
9557
+ }
9558
+ return impl(lhs);
9559
+ };
9560
+ }
9561
+ function createIsPredicate(rhs, operator) {
9562
+ switch (operator) {
9563
+ case "IS":
9564
+ return (lhs) => lhs === rhs;
9565
+ case "IS NOT":
9566
+ return (lhs) => lhs !== rhs;
9567
+ }
9568
+ }
9569
+ function createPredicateImpl(rhs, operator) {
9570
+ switch (operator) {
9571
+ case "=":
9572
+ return (lhs) => lhs === rhs;
9573
+ case "!=":
9574
+ return (lhs) => lhs !== rhs;
9575
+ case "<":
9576
+ return (lhs) => lhs < rhs;
9577
+ case "<=":
9578
+ return (lhs) => lhs <= rhs;
9579
+ case ">":
9580
+ return (lhs) => lhs > rhs;
9581
+ case ">=":
9582
+ return (lhs) => lhs >= rhs;
9583
+ case "LIKE":
9584
+ return getLikePredicate(rhs, "");
9585
+ case "NOT LIKE":
9586
+ return not2(getLikePredicate(rhs, ""));
9587
+ case "ILIKE":
9588
+ return getLikePredicate(rhs, "i");
9589
+ case "NOT ILIKE":
9590
+ return not2(getLikePredicate(rhs, "i"));
9591
+ case "IN": {
9592
+ assert(Array.isArray(rhs));
9593
+ const set = new Set(rhs);
9594
+ return (lhs) => set.has(lhs);
9595
+ }
9596
+ case "NOT IN": {
9597
+ assert(Array.isArray(rhs));
9598
+ const set = new Set(rhs);
9599
+ return (lhs) => !set.has(lhs);
9600
+ }
9601
+ default:
9602
+ operator;
9603
+ throw new Error(`Unexpected operator: ${operator}`);
9604
+ }
9605
+ }
9606
+ function not2(f) {
9607
+ return (lhs) => !f(lhs);
9608
+ }
9609
+ function transformFilters(filters) {
9610
+ if (!filters) {
9611
+ return { filters: void 0, conditionsRemoved: false };
9612
+ }
9613
+ switch (filters.type) {
9614
+ case "simple":
9615
+ return { filters, conditionsRemoved: false };
9616
+ case "correlatedSubquery":
9617
+ return { filters: void 0, conditionsRemoved: true };
9618
+ case "and":
9619
+ case "or": {
9620
+ const transformedConditions = [];
9621
+ let conditionsRemoved = false;
9622
+ for (const cond of filters.conditions) {
9623
+ const transformed = transformFilters(cond);
9624
+ if (transformed.filters === void 0 && filters.type === "or") {
9625
+ return { filters: void 0, conditionsRemoved: true };
9626
+ }
9627
+ conditionsRemoved = conditionsRemoved || transformed.conditionsRemoved;
9628
+ if (transformed.filters) {
9629
+ transformedConditions.push(transformed.filters);
9630
+ }
9631
+ }
9632
+ return {
9633
+ filters: simplifyCondition({
9634
+ type: filters.type,
9635
+ conditions: transformedConditions
9636
+ }),
9637
+ conditionsRemoved
9638
+ };
9639
+ }
9640
+ default:
9641
+ unreachable(filters);
9642
+ }
9643
+ }
9644
+
9645
+ // ../zql/src/builder/builder.ts
9646
+ function buildPipeline(ast, delegate, queryID) {
9647
+ ast = delegate.mapAst ? delegate.mapAst(ast) : ast;
9648
+ return buildPipelineInternal(ast, delegate, queryID, "");
9649
+ }
9650
+ var EXISTS_LIMIT = 3;
9651
+ var PERMISSIONS_EXISTS_LIMIT = 1;
9652
+ function buildPipelineInternal(ast, delegate, queryID, name, partitionKey) {
9653
+ const source = delegate.getSource(ast.table);
9654
+ if (!source) {
9655
+ throw new Error(`Source not found: ${ast.table}`);
9656
+ }
9657
+ ast = uniquifyCorrelatedSubqueryConditionAliases(ast);
9658
+ const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);
9659
+ const splitEditKeys = partitionKey ? new Set(partitionKey) : /* @__PURE__ */ new Set();
9660
+ const aliases = /* @__PURE__ */ new Set();
9661
+ for (const csq of csqConditions) {
9662
+ aliases.add(csq.related.subquery.alias || "");
9663
+ for (const key of csq.related.correlation.parentField) {
9664
+ splitEditKeys.add(key);
9665
+ }
9666
+ }
9667
+ if (ast.related) {
9668
+ for (const csq of ast.related) {
9669
+ for (const key of csq.correlation.parentField) {
9670
+ splitEditKeys.add(key);
9671
+ }
9672
+ }
9673
+ }
9674
+ const conn = source.connect(
9675
+ must(ast.orderBy),
9676
+ ast.where,
9677
+ splitEditKeys,
9678
+ delegate.debug
9679
+ );
9680
+ let end = delegate.decorateSourceInput(conn, queryID);
9681
+ end = delegate.decorateInput(end, `${name}:source(${ast.table})`);
9682
+ const { fullyAppliedFilters } = conn;
9683
+ if (ast.start) {
9684
+ const skip = new Skip(end, ast.start);
9685
+ delegate.addEdge(end, skip);
9686
+ end = delegate.decorateInput(skip, `${name}:skip)`);
9687
+ }
9688
+ for (const csqCondition of csqConditions) {
9689
+ if (!csqCondition.flip) {
9690
+ end = applyCorrelatedSubQuery(
9691
+ {
9692
+ ...csqCondition.related,
9693
+ subquery: {
9694
+ ...csqCondition.related.subquery,
9695
+ limit: csqCondition.related.system === "permissions" ? PERMISSIONS_EXISTS_LIMIT : EXISTS_LIMIT
9696
+ }
9697
+ },
9698
+ delegate,
9699
+ queryID,
9700
+ end,
9701
+ name,
9702
+ true
9703
+ );
9704
+ }
9705
+ }
9706
+ if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) {
9707
+ end = applyWhere(end, ast.where, delegate, name);
9708
+ }
9709
+ if (ast.limit !== void 0) {
9710
+ const takeName = `${name}:take`;
9711
+ const take2 = new Take(
9712
+ end,
9713
+ delegate.createStorage(takeName),
9714
+ ast.limit,
9715
+ partitionKey
9716
+ );
9717
+ delegate.addEdge(end, take2);
9718
+ end = delegate.decorateInput(take2, takeName);
9719
+ }
9720
+ if (ast.related) {
9721
+ for (const csq of ast.related) {
9722
+ end = applyCorrelatedSubQuery(csq, delegate, queryID, end, name, false);
9723
+ }
9724
+ }
9725
+ return end;
9726
+ }
9727
+ function applyWhere(input, condition, delegate, name) {
9728
+ if (!conditionIncludesFlippedSubqueryAtAnyLevel(condition)) {
9729
+ return buildFilterPipeline(
9730
+ input,
9731
+ delegate,
9732
+ (filterInput) => applyFilter(filterInput, condition, delegate, name)
9733
+ );
9734
+ }
9735
+ return applyFilterWithFlips(input, condition, delegate, name);
9736
+ }
9737
+ function applyFilterWithFlips(input, condition, delegate, name) {
9738
+ let end = input;
9739
+ assert(condition.type !== "simple", "Simple conditions cannot have flips");
9740
+ switch (condition.type) {
9741
+ case "and": {
9742
+ const [withFlipped, withoutFlipped] = partitionBranches(
9743
+ condition.conditions,
9744
+ conditionIncludesFlippedSubqueryAtAnyLevel
9745
+ );
9746
+ if (withoutFlipped.length > 0) {
9747
+ end = buildFilterPipeline(
9748
+ input,
9749
+ delegate,
9750
+ (filterInput) => applyAnd(
9751
+ filterInput,
9752
+ {
9753
+ type: "and",
9754
+ conditions: withoutFlipped
9755
+ },
9756
+ delegate,
9757
+ name
9758
+ )
9759
+ );
9760
+ }
9761
+ assert(withFlipped.length > 0, "Impossible to have no flips here");
9762
+ for (const cond of withFlipped) {
9763
+ end = applyFilterWithFlips(end, cond, delegate, name);
9764
+ }
9765
+ break;
9766
+ }
9767
+ case "or": {
9768
+ const [withFlipped, withoutFlipped] = partitionBranches(
9769
+ condition.conditions,
9770
+ conditionIncludesFlippedSubqueryAtAnyLevel
9771
+ );
9772
+ assert(withFlipped.length > 0, "Impossible to have no flips here");
9773
+ const ufo = new UnionFanOut(end);
9774
+ delegate.addEdge(end, ufo);
9775
+ end = delegate.decorateInput(ufo, `${name}:ufo`);
9776
+ const branches = [];
9777
+ if (withoutFlipped.length > 0) {
9778
+ branches.push(
9779
+ buildFilterPipeline(
9780
+ end,
9781
+ delegate,
9782
+ (filterInput) => applyOr(
9783
+ filterInput,
9784
+ {
9785
+ type: "or",
9786
+ conditions: withoutFlipped
9787
+ },
9788
+ delegate,
9789
+ name
9790
+ )
9791
+ )
9792
+ );
9793
+ }
9794
+ for (const cond of withFlipped) {
9795
+ branches.push(applyFilterWithFlips(end, cond, delegate, name));
9796
+ }
9797
+ const ufi = new UnionFanIn(ufo, branches);
9798
+ for (const branch of branches) {
9799
+ delegate.addEdge(branch, ufi);
9800
+ }
9801
+ end = delegate.decorateInput(ufi, `${name}:ufi`);
9802
+ break;
9803
+ }
9804
+ case "correlatedSubquery": {
9805
+ const sq = condition.related;
9806
+ const child = buildPipelineInternal(
9807
+ sq.subquery,
9808
+ delegate,
9809
+ "",
9810
+ `${name}.${sq.subquery.alias}`,
9811
+ sq.correlation.childField
9812
+ );
9813
+ const flippedJoin = new FlippedJoin({
9814
+ parent: end,
9815
+ child,
9816
+ parentKey: sq.correlation.parentField,
9817
+ childKey: sq.correlation.childField,
9818
+ relationshipName: must(
9819
+ sq.subquery.alias,
9820
+ "Subquery must have an alias"
9821
+ ),
9822
+ hidden: sq.hidden ?? false,
9823
+ system: sq.system ?? "client"
9824
+ });
9825
+ delegate.addEdge(end, flippedJoin);
9826
+ delegate.addEdge(child, flippedJoin);
9827
+ end = delegate.decorateInput(
9828
+ flippedJoin,
9829
+ `${name}:flipped-join(${sq.subquery.alias})`
9830
+ );
9831
+ break;
9832
+ }
9833
+ }
9834
+ return end;
9835
+ }
9836
+ function applyFilter(input, condition, delegate, name) {
9837
+ switch (condition.type) {
9838
+ case "and":
9839
+ return applyAnd(input, condition, delegate, name);
9840
+ case "or":
9841
+ return applyOr(input, condition, delegate, name);
9842
+ case "correlatedSubquery":
9843
+ return applyCorrelatedSubqueryCondition(input, condition, delegate, name);
9844
+ case "simple":
9845
+ return applySimpleCondition(input, delegate, condition);
9846
+ }
9847
+ }
9848
+ function applyAnd(input, condition, delegate, name) {
9849
+ for (const subCondition of condition.conditions) {
9850
+ input = applyFilter(input, subCondition, delegate, name);
9851
+ }
9852
+ return input;
9853
+ }
9854
+ function applyOr(input, condition, delegate, name) {
9855
+ const [subqueryConditions, otherConditions] = groupSubqueryConditions(condition);
9856
+ if (subqueryConditions.length === 0) {
9857
+ const filter = new Filter(
9858
+ input,
9859
+ createPredicate({
9860
+ type: "or",
9861
+ conditions: otherConditions
9862
+ })
9863
+ );
9864
+ delegate.addEdge(input, filter);
9865
+ return filter;
9866
+ }
9867
+ const fanOut = new FanOut(input);
9868
+ delegate.addEdge(input, fanOut);
9869
+ const branches = subqueryConditions.map(
9870
+ (subCondition) => applyFilter(fanOut, subCondition, delegate, name)
9871
+ );
9872
+ if (otherConditions.length > 0) {
9873
+ const filter = new Filter(
9874
+ fanOut,
9875
+ createPredicate({
9876
+ type: "or",
9877
+ conditions: otherConditions
9878
+ })
9879
+ );
9880
+ delegate.addEdge(fanOut, filter);
9881
+ branches.push(filter);
9882
+ }
9883
+ const ret = new FanIn(fanOut, branches);
9884
+ for (const branch of branches) {
9885
+ delegate.addEdge(branch, ret);
9886
+ }
9887
+ fanOut.setFanIn(ret);
9888
+ return ret;
9889
+ }
9890
+ function groupSubqueryConditions(condition) {
9891
+ const partitioned = [[], []];
9892
+ for (const subCondition of condition.conditions) {
9893
+ if (isNotAndDoesNotContainSubquery(subCondition)) {
9894
+ partitioned[1].push(subCondition);
9895
+ } else {
9896
+ partitioned[0].push(subCondition);
9897
+ }
9898
+ }
9899
+ return partitioned;
9900
+ }
9901
+ function isNotAndDoesNotContainSubquery(condition) {
9902
+ if (condition.type === "correlatedSubquery") {
9903
+ return false;
9904
+ }
9905
+ if (condition.type === "simple") {
9906
+ return true;
9907
+ }
9908
+ return condition.conditions.every(isNotAndDoesNotContainSubquery);
9909
+ }
9910
+ function applySimpleCondition(input, delegate, condition) {
9911
+ const filter = new Filter(input, createPredicate(condition));
9912
+ delegate.decorateFilterInput(
9913
+ filter,
9914
+ `${valuePosName(condition.left)}:${condition.op}:${valuePosName(condition.right)}`
9915
+ );
9916
+ delegate.addEdge(input, filter);
9917
+ return filter;
9918
+ }
9919
+ function valuePosName(left) {
9920
+ switch (left.type) {
9921
+ case "static":
9922
+ return left.field;
9923
+ case "literal":
9924
+ return left.value;
9925
+ case "column":
9926
+ return left.name;
9927
+ }
9928
+ }
9929
+ function applyCorrelatedSubQuery(sq, delegate, queryID, end, name, fromCondition) {
9930
+ if (sq.subquery.limit === 0 && fromCondition) {
9931
+ return end;
9932
+ }
9933
+ assert(sq.subquery.alias, "Subquery must have an alias");
9934
+ const child = buildPipelineInternal(
9935
+ sq.subquery,
9936
+ delegate,
9937
+ queryID,
9938
+ `${name}.${sq.subquery.alias}`,
9939
+ sq.correlation.childField
9940
+ );
9941
+ const joinName = `${name}:join(${sq.subquery.alias})`;
9942
+ const join = new Join({
9943
+ parent: end,
9944
+ child,
9945
+ storage: delegate.createStorage(joinName),
9946
+ parentKey: sq.correlation.parentField,
9947
+ childKey: sq.correlation.childField,
9948
+ relationshipName: sq.subquery.alias,
9949
+ hidden: sq.hidden ?? false,
9950
+ system: sq.system ?? "client"
9951
+ });
9952
+ delegate.addEdge(end, join);
9953
+ delegate.addEdge(child, join);
9954
+ return delegate.decorateInput(join, joinName);
9955
+ }
9956
+ function applyCorrelatedSubqueryCondition(input, condition, delegate, name) {
9957
+ assert(condition.op === "EXISTS" || condition.op === "NOT EXISTS");
9958
+ if (condition.related.subquery.limit === 0) {
9959
+ if (condition.op === "EXISTS") {
9960
+ const filter2 = new Filter(input, () => false);
9961
+ delegate.addEdge(input, filter2);
9962
+ return filter2;
9963
+ }
9964
+ const filter = new Filter(input, () => true);
9965
+ delegate.addEdge(input, filter);
9966
+ return filter;
9967
+ }
9968
+ const existsName = `${name}:exists(${condition.related.subquery.alias})`;
9969
+ const exists = new Exists(
9970
+ input,
9971
+ delegate.createStorage(existsName),
9972
+ must(condition.related.subquery.alias),
9973
+ condition.related.correlation.parentField,
9974
+ condition.op
9975
+ );
9976
+ delegate.addEdge(input, exists);
9977
+ return delegate.decorateFilterInput(exists, existsName);
9978
+ }
9979
+ function gatherCorrelatedSubqueryQueryConditions(condition) {
9980
+ const csqs = [];
9981
+ const gather = (condition2) => {
9982
+ if (condition2.type === "correlatedSubquery") {
9983
+ csqs.push(condition2);
9984
+ return;
9985
+ }
9986
+ if (condition2.type === "and" || condition2.type === "or") {
9987
+ for (const c of condition2.conditions) {
9988
+ gather(c);
9989
+ }
9990
+ return;
9991
+ }
9992
+ };
9993
+ if (condition) {
9994
+ gather(condition);
9995
+ }
9996
+ return csqs;
9997
+ }
9998
+ function assertOrderingIncludesPK(ordering, pk) {
9999
+ const orderingFields = ordering.map(([field]) => field);
10000
+ const missingFields = pk.filter((pkField) => !orderingFields.includes(pkField));
10001
+ if (missingFields.length > 0) {
10002
+ throw new Error(
10003
+ `Ordering must include all primary key fields. Missing: ${missingFields.join(
10004
+ ", "
10005
+ )}. ZQL automatically appends primary key fields to the ordering if they are missing
10006
+ so a common cause of this error is a casing mismatch between Postgres and ZQL.
10007
+ E.g., "userid" vs "userID".
10008
+ You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:
10009
+ https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`
10010
+ );
10011
+ }
10012
+ }
10013
+ function uniquifyCorrelatedSubqueryConditionAliases(ast) {
10014
+ if (!ast.where) {
10015
+ return ast;
10016
+ }
10017
+ const { where } = ast;
10018
+ if (where.type !== "and" && where.type !== "or") {
10019
+ return ast;
10020
+ }
10021
+ let count = 0;
10022
+ const uniquifyCorrelatedSubquery = (csqc) => ({
10023
+ ...csqc,
10024
+ related: {
10025
+ ...csqc.related,
10026
+ subquery: {
10027
+ ...csqc.related.subquery,
10028
+ alias: (csqc.related.subquery.alias ?? "") + "_" + count++
10029
+ }
10030
+ }
10031
+ });
10032
+ const uniquify = (cond) => {
10033
+ if (cond.type === "simple") {
10034
+ return cond;
10035
+ } else if (cond.type === "correlatedSubquery") {
10036
+ return uniquifyCorrelatedSubquery(cond);
10037
+ }
10038
+ const conditions = [];
10039
+ for (const c of cond.conditions) {
10040
+ conditions.push(uniquify(c));
10041
+ }
10042
+ return {
10043
+ type: cond.type,
10044
+ conditions
10045
+ };
10046
+ };
10047
+ const result = {
10048
+ ...ast,
10049
+ where: uniquify(where)
10050
+ };
10051
+ return result;
10052
+ }
10053
+ function conditionIncludesFlippedSubqueryAtAnyLevel(cond) {
10054
+ if (cond.type === "correlatedSubquery") {
10055
+ return !!cond.flip;
10056
+ }
10057
+ if (cond.type === "and" || cond.type === "or") {
10058
+ return cond.conditions.some(
10059
+ (c) => conditionIncludesFlippedSubqueryAtAnyLevel(c)
10060
+ );
10061
+ }
10062
+ return false;
10063
+ }
10064
+ function partitionBranches(conditions, predicate) {
10065
+ const matched = [];
10066
+ const notMatched = [];
10067
+ for (const c of conditions) {
10068
+ if (predicate(c)) {
10069
+ matched.push(c);
10070
+ } else {
10071
+ notMatched.push(c);
10072
+ }
10073
+ }
10074
+ return [matched, notMatched];
10075
+ }
10076
+
10077
+ // ../zql/src/error.ts
10078
+ var NotImplementedError = class extends Error {
10079
+ constructor(message) {
10080
+ super(message);
10081
+ this.name = "NotImplementedError";
10082
+ }
10083
+ };
10084
+
10085
+ // ../zql/src/ivm/array-view.ts
10086
+ var ArrayView = class {
10087
+ #input;
10088
+ #listeners = /* @__PURE__ */ new Set();
10089
+ #schema;
10090
+ #format;
10091
+ // Synthetic "root" entry that has a single "" relationship, so that we can
10092
+ // treat all changes, including the root change, generically.
10093
+ #root;
10094
+ onDestroy;
10095
+ #dirty = false;
10096
+ #resultType = "unknown";
10097
+ #error;
10098
+ #updateTTL;
10099
+ constructor(input, format, queryComplete, updateTTL) {
10100
+ this.#input = input;
10101
+ this.#schema = input.getSchema();
10102
+ this.#format = format;
10103
+ this.#updateTTL = updateTTL;
10104
+ this.#root = { "": format.singular ? void 0 : [] };
10105
+ input.setOutput(this);
10106
+ if (queryComplete === true) {
10107
+ this.#resultType = "complete";
10108
+ } else if ("error" in queryComplete) {
10109
+ this.#resultType = "error";
10110
+ this.#error = queryComplete;
10111
+ } else {
10112
+ void queryComplete.then(() => {
10113
+ this.#resultType = "complete";
10114
+ this.#fireListeners();
10115
+ }).catch((e) => {
10116
+ this.#resultType = "error";
10117
+ this.#error = e;
10118
+ this.#fireListeners();
10119
+ });
10120
+ }
10121
+ this.#hydrate();
10122
+ }
10123
+ get data() {
10124
+ return this.#root[""];
10125
+ }
10126
+ addListener(listener) {
10127
+ assert(!this.#listeners.has(listener), "Listener already registered");
10128
+ this.#listeners.add(listener);
10129
+ this.#fireListener(listener);
10130
+ return () => {
10131
+ this.#listeners.delete(listener);
10132
+ };
10133
+ }
10134
+ #fireListeners() {
10135
+ for (const listener of this.#listeners) {
10136
+ this.#fireListener(listener);
10137
+ }
10138
+ }
10139
+ #fireListener(listener) {
10140
+ listener(this.data, this.#resultType, this.#error);
10141
+ }
10142
+ destroy() {
10143
+ this.onDestroy?.();
10144
+ }
10145
+ #hydrate() {
10146
+ this.#dirty = true;
10147
+ for (const node of this.#input.fetch({})) {
10148
+ applyChange(
10149
+ this.#root,
10150
+ { type: "add", node },
10151
+ this.#schema,
10152
+ "",
10153
+ this.#format
10154
+ );
10155
+ }
10156
+ this.flush();
10157
+ }
10158
+ push(change) {
10159
+ this.#dirty = true;
10160
+ applyChange(this.#root, change, this.#schema, "", this.#format);
10161
+ }
10162
+ flush() {
10163
+ if (!this.#dirty) {
10164
+ return;
10165
+ }
10166
+ this.#dirty = false;
10167
+ this.#fireListeners();
10168
+ }
10169
+ updateTTL(ttl) {
10170
+ this.#updateTTL(ttl);
10171
+ }
10172
+ };
10173
+
10174
+ // ../zero-types/src/format.ts
10175
+ var defaultFormat = {
10176
+ singular: false,
10177
+ relationships: {}
10178
+ };
10179
+
10180
+ // ../zql/src/query/assert-no-not-exists.ts
10181
+ function assertNoNotExists(condition) {
10182
+ switch (condition.type) {
10183
+ case "simple":
10184
+ return;
10185
+ case "correlatedSubquery":
10186
+ if (condition.op === "NOT EXISTS") {
10187
+ throw new Error(
10188
+ "not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438"
10189
+ );
10190
+ }
10191
+ if (condition.related.subquery.where) {
10192
+ assertNoNotExists(condition.related.subquery.where);
10193
+ }
10194
+ return;
10195
+ case "and":
10196
+ case "or":
10197
+ for (const c of condition.conditions) {
10198
+ assertNoNotExists(c);
10199
+ }
10200
+ return;
10201
+ default:
10202
+ unreachable(condition);
10203
+ }
10204
+ }
10205
+
10206
+ // ../zql/src/query/query.ts
10207
+ var delegateSymbol = Symbol("delegate");
10208
+
10209
+ // ../zql/src/query/query-impl.ts
10210
+ function materialize(query, delegate, factoryOrOptions, maybeOptions) {
10211
+ if (typeof factoryOrOptions === "function") {
10212
+ return query[delegateSymbol](delegate).materialize(factoryOrOptions, maybeOptions?.ttl);
10213
+ }
10214
+ return query[delegateSymbol](delegate).materialize(factoryOrOptions?.ttl);
10215
+ }
10216
+ var astSymbol = Symbol();
10217
+ function newQuery(delegate, schema, table2) {
10218
+ return new QueryImpl(
10219
+ delegate,
10220
+ schema,
10221
+ table2,
10222
+ { table: table2 },
10223
+ defaultFormat,
10224
+ void 0
10225
+ );
10226
+ }
10227
+ var newQuerySymbol = Symbol();
10228
+ var AbstractQuery = class {
10229
+ #schema;
10230
+ _delegate;
10231
+ #tableName;
10232
+ _ast;
10233
+ format;
10234
+ #hash = "";
10235
+ #system;
10236
+ #currentJunction;
10237
+ customQueryID;
10238
+ constructor(delegate, schema, tableName, ast, format, system, customQueryID, currentJunction) {
10239
+ this.#schema = schema;
10240
+ this._delegate = delegate;
10241
+ this.#tableName = tableName;
10242
+ this._ast = ast;
10243
+ this.format = format;
10244
+ this.#system = system;
10245
+ this.#currentJunction = currentJunction;
10246
+ this.customQueryID = customQueryID;
10247
+ }
10248
+ [delegateSymbol](delegate) {
10249
+ return this[newQuerySymbol](
10250
+ delegate,
10251
+ this.#schema,
10252
+ this.#tableName,
10253
+ this._ast,
10254
+ this.format,
10255
+ this.customQueryID,
10256
+ this.#currentJunction
10257
+ );
10258
+ }
10259
+ nameAndArgs(name, args) {
10260
+ return this[newQuerySymbol](
10261
+ this._delegate,
10262
+ this.#schema,
10263
+ this.#tableName,
10264
+ this._ast,
10265
+ this.format,
10266
+ {
10267
+ name,
10268
+ args
10269
+ },
10270
+ this.#currentJunction
10271
+ );
10272
+ }
10273
+ get [astSymbol]() {
10274
+ return this._ast;
10275
+ }
10276
+ get ast() {
10277
+ return this._completeAst();
10278
+ }
10279
+ hash() {
10280
+ if (!this.#hash) {
10281
+ this.#hash = hashOfAST(this._completeAst());
10282
+ }
10283
+ return this.#hash;
10284
+ }
10285
+ one = () => this[newQuerySymbol](
10286
+ this._delegate,
10287
+ this.#schema,
10288
+ this.#tableName,
10289
+ {
10290
+ ...this._ast,
10291
+ limit: 1
10292
+ },
10293
+ {
10294
+ ...this.format,
10295
+ singular: true
10296
+ },
10297
+ this.customQueryID,
10298
+ this.#currentJunction
10299
+ );
10300
+ whereExists = (relationship, cbOrOptions, options) => {
10301
+ const cb = typeof cbOrOptions === "function" ? cbOrOptions : void 0;
10302
+ const opts = typeof cbOrOptions === "function" ? options : cbOrOptions;
10303
+ const flipped = opts?.flip ?? false;
10304
+ return this.where(({ exists }) => exists(relationship, cb, { flip: flipped }));
10305
+ };
10306
+ related = (relationship, cb) => {
10307
+ if (relationship.startsWith(SUBQ_PREFIX)) {
10308
+ throw new Error(
10309
+ `Relationship names may not start with "${SUBQ_PREFIX}". That is a reserved prefix.`
10310
+ );
10311
+ }
10312
+ cb = cb ?? ((q) => q);
10313
+ const related = this.#schema.relationships[this.#tableName][relationship];
10314
+ assert(related, "Invalid relationship");
10315
+ if (isOneHop(related)) {
10316
+ const { destSchema, destField, sourceField, cardinality } = related[0];
10317
+ const q = this[newQuerySymbol](
10318
+ this._delegate,
10319
+ this.#schema,
10320
+ destSchema,
10321
+ {
10322
+ table: destSchema,
10323
+ alias: relationship
10324
+ },
10325
+ {
10326
+ relationships: {},
10327
+ singular: cardinality === "one"
10328
+ },
10329
+ this.customQueryID,
10330
+ void 0
10331
+ );
10332
+ const sq = cb(q);
10333
+ assert(
10334
+ isCompoundKey(sourceField),
10335
+ "The source of a relationship must specify at last 1 field"
10336
+ );
10337
+ assert(
10338
+ isCompoundKey(destField),
10339
+ "The destination of a relationship must specify at last 1 field"
10340
+ );
10341
+ assert(
10342
+ sourceField.length === destField.length,
10343
+ "The source and destination of a relationship must have the same number of fields"
10344
+ );
10345
+ return this[newQuerySymbol](
10346
+ this._delegate,
10347
+ this.#schema,
10348
+ this.#tableName,
10349
+ {
10350
+ ...this._ast,
10351
+ related: [
10352
+ ...this._ast.related ?? [],
10353
+ {
10354
+ system: this.#system,
10355
+ correlation: {
10356
+ parentField: sourceField,
10357
+ childField: destField
10358
+ },
10359
+ subquery: addPrimaryKeysToAst(
10360
+ this.#schema.tables[destSchema],
10361
+ sq._ast
10362
+ )
10363
+ }
10364
+ ]
10365
+ },
10366
+ {
10367
+ ...this.format,
10368
+ relationships: {
10369
+ ...this.format.relationships,
10370
+ [relationship]: sq.format
10371
+ }
10372
+ },
10373
+ this.customQueryID,
10374
+ this.#currentJunction
10375
+ );
10376
+ }
10377
+ if (isTwoHop(related)) {
10378
+ const [firstRelation, secondRelation] = related;
10379
+ const { destSchema } = secondRelation;
10380
+ const junctionSchema = firstRelation.destSchema;
10381
+ const sq = cb(
10382
+ this[newQuerySymbol](
10383
+ this._delegate,
10384
+ this.#schema,
10385
+ destSchema,
10386
+ {
10387
+ table: destSchema,
10388
+ alias: relationship
10389
+ },
10390
+ {
10391
+ relationships: {},
10392
+ singular: secondRelation.cardinality === "one"
10393
+ },
10394
+ this.customQueryID,
10395
+ relationship
10396
+ )
10397
+ );
10398
+ assert(isCompoundKey(firstRelation.sourceField), "Invalid relationship");
10399
+ assert(isCompoundKey(firstRelation.destField), "Invalid relationship");
10400
+ assert(isCompoundKey(secondRelation.sourceField), "Invalid relationship");
10401
+ assert(isCompoundKey(secondRelation.destField), "Invalid relationship");
10402
+ return this[newQuerySymbol](
10403
+ this._delegate,
10404
+ this.#schema,
10405
+ this.#tableName,
10406
+ {
10407
+ ...this._ast,
10408
+ related: [
10409
+ ...this._ast.related ?? [],
10410
+ {
10411
+ system: this.#system,
10412
+ correlation: {
10413
+ parentField: firstRelation.sourceField,
10414
+ childField: firstRelation.destField
10415
+ },
10416
+ hidden: true,
10417
+ subquery: {
10418
+ table: junctionSchema,
10419
+ alias: relationship,
10420
+ orderBy: addPrimaryKeys(
10421
+ this.#schema.tables[junctionSchema],
10422
+ void 0
10423
+ ),
10424
+ related: [
10425
+ {
10426
+ system: this.#system,
10427
+ correlation: {
10428
+ parentField: secondRelation.sourceField,
10429
+ childField: secondRelation.destField
10430
+ },
10431
+ subquery: addPrimaryKeysToAst(
10432
+ this.#schema.tables[destSchema],
10433
+ sq._ast
10434
+ )
10435
+ }
10436
+ ]
10437
+ }
10438
+ }
10439
+ ]
10440
+ },
10441
+ {
10442
+ ...this.format,
10443
+ relationships: {
10444
+ ...this.format.relationships,
10445
+ [relationship]: sq.format
10446
+ }
10447
+ },
10448
+ this.customQueryID,
10449
+ this.#currentJunction
10450
+ );
10451
+ }
10452
+ throw new Error(`Invalid relationship ${relationship}`);
10453
+ };
10454
+ where = (fieldOrExpressionFactory, opOrValue, value) => {
10455
+ let cond;
10456
+ if (typeof fieldOrExpressionFactory === "function") {
10457
+ cond = fieldOrExpressionFactory(
10458
+ new ExpressionBuilder(this._exists)
10459
+ );
10460
+ } else {
10461
+ assert(opOrValue !== void 0, "Invalid condition");
10462
+ cond = cmp(fieldOrExpressionFactory, opOrValue, value);
10463
+ }
10464
+ const existingWhere = this._ast.where;
10465
+ if (existingWhere) {
10466
+ cond = and(existingWhere, cond);
10467
+ }
10468
+ const where = simplifyCondition(cond);
10469
+ if (this.#system === "client") {
10470
+ assertNoNotExists(where);
10471
+ }
10472
+ return this[newQuerySymbol](
10473
+ this._delegate,
10474
+ this.#schema,
10475
+ this.#tableName,
10476
+ {
10477
+ ...this._ast,
10478
+ where
10479
+ },
10480
+ this.format,
10481
+ this.customQueryID,
10482
+ this.#currentJunction
10483
+ );
10484
+ };
10485
+ start = (row, opts) => this[newQuerySymbol](
10486
+ this._delegate,
10487
+ this.#schema,
10488
+ this.#tableName,
10489
+ {
10490
+ ...this._ast,
10491
+ start: {
10492
+ row,
10493
+ exclusive: !opts?.inclusive
10494
+ }
10495
+ },
10496
+ this.format,
10497
+ this.customQueryID,
10498
+ this.#currentJunction
10499
+ );
10500
+ limit = (limit) => {
10501
+ if (limit < 0) {
10502
+ throw new Error("Limit must be non-negative");
10503
+ }
10504
+ if ((limit | 0) !== limit) {
10505
+ throw new Error("Limit must be an integer");
10506
+ }
10507
+ if (this.#currentJunction) {
10508
+ throw new NotImplementedError(
10509
+ "Limit is not supported in junction relationships yet. Junction relationship being limited: " + this.#currentJunction
10510
+ );
10511
+ }
10512
+ return this[newQuerySymbol](
10513
+ this._delegate,
10514
+ this.#schema,
10515
+ this.#tableName,
10516
+ {
10517
+ ...this._ast,
10518
+ limit
10519
+ },
10520
+ this.format,
10521
+ this.customQueryID,
10522
+ this.#currentJunction
10523
+ );
10524
+ };
10525
+ orderBy = (field, direction) => {
10526
+ if (this.#currentJunction) {
10527
+ throw new NotImplementedError(
10528
+ "Order by is not supported in junction relationships yet. Junction relationship being ordered: " + this.#currentJunction
10529
+ );
10530
+ }
10531
+ return this[newQuerySymbol](
10532
+ this._delegate,
10533
+ this.#schema,
10534
+ this.#tableName,
10535
+ {
10536
+ ...this._ast,
10537
+ orderBy: [...this._ast.orderBy ?? [], [field, direction]]
10538
+ },
10539
+ this.format,
10540
+ this.customQueryID,
10541
+ this.#currentJunction
10542
+ );
10543
+ };
10544
+ _exists = (relationship, cb, options) => {
10545
+ cb = cb ?? ((q) => q);
10546
+ const flip = options?.flip ?? false;
10547
+ const related = this.#schema.relationships[this.#tableName][relationship];
10548
+ assert(related, "Invalid relationship");
10549
+ if (isOneHop(related)) {
10550
+ const { destSchema, sourceField, destField } = related[0];
10551
+ assert(isCompoundKey(sourceField), "Invalid relationship");
10552
+ assert(isCompoundKey(destField), "Invalid relationship");
10553
+ const sq = cb(
10554
+ this[newQuerySymbol](
10555
+ this._delegate,
10556
+ this.#schema,
10557
+ destSchema,
10558
+ {
10559
+ table: destSchema,
10560
+ alias: `${SUBQ_PREFIX}${relationship}`
10561
+ },
10562
+ defaultFormat,
10563
+ this.customQueryID,
10564
+ void 0
10565
+ )
10566
+ );
10567
+ return {
10568
+ type: "correlatedSubquery",
10569
+ related: {
10570
+ system: this.#system,
10571
+ correlation: {
10572
+ parentField: sourceField,
10573
+ childField: destField
10574
+ },
10575
+ subquery: addPrimaryKeysToAst(
10576
+ this.#schema.tables[destSchema],
10577
+ sq._ast
10578
+ )
10579
+ },
10580
+ op: "EXISTS",
10581
+ flip
10582
+ };
10583
+ }
10584
+ if (isTwoHop(related)) {
10585
+ const [firstRelation, secondRelation] = related;
10586
+ assert(isCompoundKey(firstRelation.sourceField), "Invalid relationship");
10587
+ assert(isCompoundKey(firstRelation.destField), "Invalid relationship");
10588
+ assert(isCompoundKey(secondRelation.sourceField), "Invalid relationship");
10589
+ assert(isCompoundKey(secondRelation.destField), "Invalid relationship");
10590
+ const { destSchema } = secondRelation;
10591
+ const junctionSchema = firstRelation.destSchema;
10592
+ const queryToDest = cb(
10593
+ this[newQuerySymbol](
10594
+ this._delegate,
10595
+ this.#schema,
10596
+ destSchema,
10597
+ {
10598
+ table: destSchema,
10599
+ alias: `${SUBQ_PREFIX}zhidden_${relationship}`
10600
+ },
10601
+ defaultFormat,
10602
+ this.customQueryID,
10603
+ relationship
10604
+ )
10605
+ );
10606
+ return {
10607
+ type: "correlatedSubquery",
10608
+ related: {
10609
+ system: this.#system,
10610
+ correlation: {
10611
+ parentField: firstRelation.sourceField,
10612
+ childField: firstRelation.destField
10613
+ },
10614
+ subquery: {
10615
+ table: junctionSchema,
10616
+ alias: `${SUBQ_PREFIX}${relationship}`,
10617
+ orderBy: addPrimaryKeys(
10618
+ this.#schema.tables[junctionSchema],
10619
+ void 0
10620
+ ),
10621
+ where: {
10622
+ type: "correlatedSubquery",
10623
+ related: {
10624
+ system: this.#system,
10625
+ correlation: {
10626
+ parentField: secondRelation.sourceField,
10627
+ childField: secondRelation.destField
10628
+ },
10629
+ subquery: addPrimaryKeysToAst(
10630
+ this.#schema.tables[destSchema],
10631
+ queryToDest._ast
10632
+ )
10633
+ },
10634
+ op: "EXISTS",
10635
+ flip
10636
+ }
10637
+ }
10638
+ },
10639
+ op: "EXISTS",
10640
+ flip
10641
+ };
10642
+ }
10643
+ throw new Error(`Invalid relationship ${relationship}`);
10644
+ };
10645
+ #completedAST;
10646
+ _completeAst() {
10647
+ if (!this.#completedAST) {
10648
+ const finalOrderBy = addPrimaryKeys(
10649
+ this.#schema.tables[this.#tableName],
10650
+ this._ast.orderBy
10651
+ );
10652
+ if (this._ast.start) {
10653
+ const { row } = this._ast.start;
10654
+ const narrowedRow = {};
10655
+ for (const [field] of finalOrderBy) {
10656
+ narrowedRow[field] = row[field];
10657
+ }
10658
+ this.#completedAST = {
10659
+ ...this._ast,
10660
+ start: {
10661
+ ...this._ast.start,
10662
+ row: narrowedRow
10663
+ },
10664
+ orderBy: finalOrderBy
10665
+ };
10666
+ } else {
10667
+ this.#completedAST = {
10668
+ ...this._ast,
10669
+ orderBy: addPrimaryKeys(
10670
+ this.#schema.tables[this.#tableName],
10671
+ this._ast.orderBy
10672
+ )
10673
+ };
10674
+ }
10675
+ }
10676
+ return this.#completedAST;
10677
+ }
10678
+ };
10679
+ var completedAstSymbol = Symbol();
10680
+ var QueryImpl = class _QueryImpl extends AbstractQuery {
10681
+ #system;
10682
+ constructor(delegate, schema, tableName, ast = { table: tableName }, format = defaultFormat, system = "client", customQueryID, currentJunction) {
10683
+ super(
10684
+ delegate,
10685
+ schema,
10686
+ tableName,
10687
+ ast,
10688
+ format,
10689
+ system,
10690
+ customQueryID,
10691
+ currentJunction
10692
+ );
10693
+ this.#system = system;
10694
+ }
10695
+ get [completedAstSymbol]() {
10696
+ return this._completeAst();
10697
+ }
10698
+ [newQuerySymbol](delegate, schema, tableName, ast, format, customQueryID, currentJunction) {
10699
+ return new _QueryImpl(
10700
+ delegate,
10701
+ schema,
10702
+ tableName,
10703
+ ast,
10704
+ format,
10705
+ this.#system,
10706
+ customQueryID,
10707
+ currentJunction
10708
+ );
10709
+ }
10710
+ materialize(factoryOrTTL, ttl = DEFAULT_TTL_MS) {
10711
+ const delegate = must(
10712
+ this._delegate,
10713
+ "materialize requires a query delegate to be set"
10714
+ );
10715
+ let factory;
10716
+ if (typeof factoryOrTTL === "function") {
10717
+ factory = factoryOrTTL;
10718
+ } else {
10719
+ ttl = factoryOrTTL ?? DEFAULT_TTL_MS;
10720
+ }
10721
+ const ast = this._completeAst();
10722
+ const queryID = this.customQueryID ? hashOfNameAndArgs(this.customQueryID.name, this.customQueryID.args) : this.hash();
10723
+ const queryCompleteResolver = resolver7();
10724
+ let queryComplete = delegate.defaultQueryComplete;
10725
+ const updateTTL = (newTTL) => {
10726
+ this.customQueryID ? delegate.updateCustomQuery(this.customQueryID, newTTL) : delegate.updateServerQuery(ast, newTTL);
10727
+ };
10728
+ const gotCallback = (got, error) => {
10729
+ if (error) {
10730
+ queryCompleteResolver.reject(error);
10731
+ queryComplete = error;
10732
+ return;
10733
+ }
10734
+ if (got) {
10735
+ delegate.addMetric(
10736
+ "query-materialization-end-to-end",
10737
+ performance.now() - t0,
10738
+ queryID,
10739
+ ast
10740
+ );
10741
+ queryComplete = true;
10742
+ queryCompleteResolver.resolve(true);
10743
+ }
10744
+ };
10745
+ let removeCommitObserver;
10746
+ const onDestroy = () => {
10747
+ input.destroy();
10748
+ removeCommitObserver?.();
10749
+ removeAddedQuery();
10750
+ };
10751
+ const t0 = performance.now();
10752
+ const removeAddedQuery = this.customQueryID ? delegate.addCustomQuery(ast, this.customQueryID, ttl, gotCallback) : delegate.addServerQuery(ast, ttl, gotCallback);
10753
+ const input = buildPipeline(ast, delegate, queryID);
10754
+ const view = delegate.batchViewUpdates(
10755
+ () => (factory ?? arrayViewFactory)(
10756
+ this,
10757
+ input,
10758
+ this.format,
10759
+ onDestroy,
10760
+ (cb) => {
10761
+ removeCommitObserver = delegate.onTransactionCommit(cb);
10762
+ },
10763
+ queryComplete || queryCompleteResolver.promise,
10764
+ updateTTL
10765
+ )
10766
+ );
10767
+ delegate.addMetric(
10768
+ "query-materialization-client",
10769
+ performance.now() - t0,
10770
+ queryID
10771
+ );
10772
+ return view;
10773
+ }
10774
+ run(options) {
10775
+ const delegate = must(
10776
+ this._delegate,
10777
+ "run requires a query delegate to be set"
10778
+ );
10779
+ delegate.assertValidRunOptions(options);
10780
+ const v = this.materialize(options?.ttl);
10781
+ if (options?.type === "complete") {
10782
+ return new Promise((resolve) => {
10783
+ v.addListener((data, type) => {
10784
+ if (type === "complete") {
10785
+ v.destroy();
10786
+ resolve(data);
10787
+ } else if (type === "error") {
10788
+ v.destroy();
10789
+ resolve(Promise.reject(data));
10790
+ }
10791
+ });
10792
+ });
10793
+ }
10794
+ options?.type;
10795
+ const ret = v.data;
10796
+ v.destroy();
10797
+ return Promise.resolve(ret);
10798
+ }
10799
+ preload(options) {
10800
+ const delegate = must(
10801
+ this._delegate,
10802
+ "preload requires a query delegate to be set"
10803
+ );
10804
+ const ttl = options?.ttl ?? DEFAULT_PRELOAD_TTL_MS;
10805
+ const ast = this._completeAst();
10806
+ const { resolve, promise: complete } = resolver7();
10807
+ if (this.customQueryID) {
10808
+ const cleanup2 = delegate.addCustomQuery(
10809
+ ast,
10810
+ this.customQueryID,
10811
+ ttl,
10812
+ (got) => {
10813
+ if (got) {
10814
+ resolve();
10815
+ }
10816
+ }
10817
+ );
10818
+ return {
10819
+ cleanup: cleanup2,
10820
+ complete
10821
+ };
10822
+ }
10823
+ const cleanup = delegate.addServerQuery(ast, ttl, (got) => {
10824
+ if (got) {
10825
+ resolve();
10826
+ }
10827
+ });
10828
+ return {
10829
+ cleanup,
10830
+ complete
10831
+ };
10832
+ }
10833
+ };
10834
+ function addPrimaryKeys(schema, orderBy) {
10835
+ orderBy = orderBy ?? [];
10836
+ const { primaryKey } = schema;
10837
+ const primaryKeysToAdd = new Set(primaryKey);
10838
+ for (const [field] of orderBy) {
10839
+ primaryKeysToAdd.delete(field);
10840
+ }
10841
+ if (primaryKeysToAdd.size === 0) {
10842
+ return orderBy;
10843
+ }
10844
+ return [
10845
+ ...orderBy,
10846
+ ...[...primaryKeysToAdd].map((key) => [key, "asc"])
10847
+ ];
10848
+ }
10849
+ function addPrimaryKeysToAst(schema, ast) {
10850
+ return {
10851
+ ...ast,
10852
+ orderBy: addPrimaryKeys(schema, ast.orderBy)
10853
+ };
10854
+ }
10855
+ function arrayViewFactory(_query, input, format, onDestroy, onTransactionCommit, queryComplete, updateTTL) {
10856
+ const v = new ArrayView(
10857
+ input,
10858
+ format,
10859
+ queryComplete,
10860
+ updateTTL
10861
+ );
10862
+ v.onDestroy = onDestroy;
10863
+ onTransactionCommit(() => {
10864
+ v.flush();
10865
+ });
10866
+ return v;
10867
+ }
10868
+ function isCompoundKey(field) {
10869
+ return Array.isArray(field) && field.length >= 1;
10870
+ }
10871
+ function isOneHop(r) {
10872
+ return r.length === 1;
10873
+ }
10874
+ function isTwoHop(r) {
10875
+ return r.length === 2;
10876
+ }
10877
+
10878
+ // ../zero-client/src/util/socket.ts
10879
+ function send(ws, data) {
10880
+ ws.send(JSON.stringify(data));
10881
+ }
10882
+
10883
+ // ../zero-client/src/client/active-clients-manager.ts
10884
+ import { resolver as resolver8 } from "@rocicorp/resolver";
10885
+ var keyPrefix = "zero-active";
10886
+ function toLockName(clientGroupID, clientID) {
10887
+ return `${keyPrefix}/${clientGroupID}/${clientID}`;
10888
+ }
10889
+ function toBroadcastChannelName(clientGroupID) {
10890
+ return `${keyPrefix}/${clientGroupID}`;
10891
+ }
10892
+ function fromLockName(lockKey) {
10893
+ if (!lockKey || !lockKey.startsWith(keyPrefix)) {
10894
+ return void 0;
10895
+ }
10896
+ const parts = lockKey.slice(keyPrefix.length).split("/");
10897
+ if (parts.length !== 3) {
10898
+ return void 0;
10899
+ }
10900
+ return {
10901
+ clientGroupID: parts[1],
10902
+ clientID: parts[2]
10903
+ };
10904
+ }
10905
+ function ignoreAbortError(e) {
10906
+ if (e instanceof Error && e.name === "AbortError") {
10907
+ return;
10908
+ }
10909
+ throw e;
10910
+ }
10911
+ var ActiveClientsManager = class _ActiveClientsManager {
10912
+ clientGroupID;
10913
+ clientID;
10914
+ #resolver = resolver8();
10915
+ #lockManager;
10916
+ #activeClients = /* @__PURE__ */ new Set();
10917
+ /**
10918
+ * A callback that is called when a client is added to the client group.
10919
+ * It receives the client ID of the added client.
10920
+ */
10921
+ onAdd;
10922
+ /**
10923
+ * A callback that is called when a client is deleted from the client group.
10924
+ * It receives the client ID of the deleted client.
10925
+ */
10926
+ onDelete;
10927
+ /**
10928
+ * Creates an instance of `ActiveClientsManager` for the specified client
10929
+ * group and client ID. It will return a promise that resolves when the
10930
+ * instance is ready to use, which means that it has successfully acquired the
10931
+ * exclusive lock for the client and has retrieved the list of active clients.
10932
+ */
10933
+ static async create(clientGroupID, clientID, signal) {
10934
+ const instance = new _ActiveClientsManager(clientGroupID, clientID, signal);
10935
+ await instance.#init(signal);
10936
+ return instance;
10937
+ }
10938
+ constructor(clientGroupID, clientID, signal) {
10939
+ this.clientGroupID = clientGroupID;
10940
+ this.clientID = clientID;
10941
+ this.#lockManager = getClientLockManager(signal);
10942
+ this.#activeClients.add(clientID);
10943
+ }
10944
+ async #init(signal) {
10945
+ const { clientGroupID, clientID } = this;
10946
+ const name = toLockName(clientGroupID, clientID);
10947
+ const channel = new bc(toBroadcastChannelName(clientGroupID));
10948
+ channel.addEventListener(
6599
10949
  "message",
6600
10950
  (e) => {
6601
10951
  const client = fromLockName(e.data);
@@ -6732,7 +11082,7 @@ var Connecting = 1;
6732
11082
  var Connected = 2;
6733
11083
 
6734
11084
  // ../zql/src/ivm/memory-storage.ts
6735
- import { compareUTF8 as compareUTF82 } from "compare-utf8";
11085
+ import { compareUTF8 as compareUTF83 } from "compare-utf8";
6736
11086
 
6737
11087
  // ../shared/src/btree-set.ts
6738
11088
  var MAX_NODE_SIZE = 32;
@@ -7000,8 +11350,8 @@ var BNode = class _BNode {
7000
11350
  return new _BNode(keys);
7001
11351
  }
7002
11352
  delete(key, tree) {
7003
- const cmp = tree.comparator;
7004
- const iLow = indexOf(key, this.keys, -1, cmp);
11353
+ const cmp2 = tree.comparator;
11354
+ const iLow = indexOf(key, this.keys, -1, cmp2);
7005
11355
  const iHigh = iLow + 1;
7006
11356
  if (iLow < 0) {
7007
11357
  return false;
@@ -7066,21 +11416,21 @@ var BNodeInternal = class _BNodeInternal extends BNode {
7066
11416
  }
7067
11417
  set(key, tree) {
7068
11418
  const c = this.children;
7069
- const cmp = tree.comparator;
7070
- let i = Math.min(indexOf(key, this.keys, 0, cmp), c.length - 1);
11419
+ const cmp2 = tree.comparator;
11420
+ let i = Math.min(indexOf(key, this.keys, 0, cmp2), c.length - 1);
7071
11421
  let child = c[i];
7072
11422
  if (child.isShared) {
7073
11423
  c[i] = child = child.clone();
7074
11424
  }
7075
11425
  if (child.keys.length >= MAX_NODE_SIZE) {
7076
11426
  let other;
7077
- if (i > 0 && (other = c[i - 1]).keys.length < MAX_NODE_SIZE && cmp(child.keys[0], key) < 0) {
11427
+ if (i > 0 && (other = c[i - 1]).keys.length < MAX_NODE_SIZE && cmp2(child.keys[0], key) < 0) {
7078
11428
  if (other.isShared) {
7079
11429
  c[i - 1] = other = other.clone();
7080
11430
  }
7081
11431
  other.takeFromRight(child);
7082
11432
  this.keys[i - 1] = other.maxKey();
7083
- } else if ((other = c[i + 1]) !== void 0 && other.keys.length < MAX_NODE_SIZE && cmp(child.maxKey(), key) < 0) {
11433
+ } else if ((other = c[i + 1]) !== void 0 && other.keys.length < MAX_NODE_SIZE && cmp2(child.maxKey(), key) < 0) {
7084
11434
  if (other.isShared) c[i + 1] = other = other.clone();
7085
11435
  other.takeFromLeft(child);
7086
11436
  this.keys[i] = c[i].maxKey();
@@ -7095,7 +11445,7 @@ var BNodeInternal = class _BNodeInternal extends BNode {
7095
11445
  }
7096
11446
  const newRightSibling = this.splitOffRightSide();
7097
11447
  let target = this;
7098
- if (cmp(result.maxKey(), this.maxKey()) > 0) {
11448
+ if (cmp2(result.maxKey(), this.maxKey()) > 0) {
7099
11449
  target = newRightSibling;
7100
11450
  i -= this.keys.length;
7101
11451
  }
@@ -7131,10 +11481,10 @@ var BNodeInternal = class _BNodeInternal extends BNode {
7131
11481
  this.children.unshift(lhs.children.pop());
7132
11482
  }
7133
11483
  delete(key, tree) {
7134
- const cmp = tree.comparator;
11484
+ const cmp2 = tree.comparator;
7135
11485
  const { keys } = this;
7136
11486
  const { children } = this;
7137
- let iLow = indexOf(key, this.keys, 0, cmp);
11487
+ let iLow = indexOf(key, this.keys, 0, cmp2);
7138
11488
  let i = iLow;
7139
11489
  const iHigh = Math.min(iLow, keys.length - 1);
7140
11490
  if (i <= iHigh) {
@@ -7223,7 +11573,7 @@ emptyLeaf.isShared = true;
7223
11573
 
7224
11574
  // ../zql/src/ivm/memory-storage.ts
7225
11575
  function comparator(a, b) {
7226
- return compareUTF82(a[0], b[0]);
11576
+ return compareUTF83(a[0], b[0]);
7227
11577
  }
7228
11578
  var MemoryStorage = class {
7229
11579
  #data = new BTreeSet(comparator);
@@ -7451,7 +11801,7 @@ var MemorySource = class _MemorySource {
7451
11801
  scanStart = startAt;
7452
11802
  }
7453
11803
  const rowsIterable = generateRows(data, scanStart, req.reverse);
7454
- const withOverlay = generateWithOverlay(
11804
+ const withOverlay = generateWithOverlay2(
7455
11805
  startAt,
7456
11806
  pkConstraint ? once(rowsIterable) : rowsIterable,
7457
11807
  // use `req.constraint` here and not `fetchOrPkConstraint` since `fetchOrPkConstraint` could be the
@@ -7673,7 +12023,7 @@ function* generateWithStart(nodes, start, compare2) {
7673
12023
  }
7674
12024
  }
7675
12025
  }
7676
- function* generateWithOverlay(startAt, rows, constraint, overlay, connectionIndex, compare2, filterPredicate) {
12026
+ function* generateWithOverlay2(startAt, rows, constraint, overlay, connectionIndex, compare2, filterPredicate) {
7677
12027
  let overlayToApply = void 0;
7678
12028
  if (overlay && connectionIndex <= overlay.outputIndex) {
7679
12029
  overlayToApply = overlay;
@@ -7723,24 +12073,24 @@ function computeOverlays(startAt, constraint, overlay, compare2, filterPredicate
7723
12073
  }
7724
12074
  return overlays;
7725
12075
  }
7726
- function overlaysForStartAt({ add, remove }, startAt, compare2) {
12076
+ function overlaysForStartAt({ add: add2, remove }, startAt, compare2) {
7727
12077
  const undefinedIfBeforeStartAt = (row) => row === void 0 || compare2(row, startAt) < 0 ? void 0 : row;
7728
12078
  return {
7729
- add: undefinedIfBeforeStartAt(add),
12079
+ add: undefinedIfBeforeStartAt(add2),
7730
12080
  remove: undefinedIfBeforeStartAt(remove)
7731
12081
  };
7732
12082
  }
7733
- function overlaysForConstraint({ add, remove }, constraint) {
12083
+ function overlaysForConstraint({ add: add2, remove }, constraint) {
7734
12084
  const undefinedIfDoesntMatchConstraint = (row) => row === void 0 || !constraintMatchesRow(constraint, row) ? void 0 : row;
7735
12085
  return {
7736
- add: undefinedIfDoesntMatchConstraint(add),
12086
+ add: undefinedIfDoesntMatchConstraint(add2),
7737
12087
  remove: undefinedIfDoesntMatchConstraint(remove)
7738
12088
  };
7739
12089
  }
7740
- function overlaysForFilterPredicate({ add, remove }, filterPredicate) {
12090
+ function overlaysForFilterPredicate({ add: add2, remove }, filterPredicate) {
7741
12091
  const undefinedIfDoesntMatchFilter = (row) => row === void 0 || !filterPredicate(row) ? void 0 : row;
7742
12092
  return {
7743
- add: undefinedIfDoesntMatchFilter(add),
12093
+ add: undefinedIfDoesntMatchFilter(add2),
7744
12094
  remove: undefinedIfDoesntMatchFilter(remove)
7745
12095
  };
7746
12096
  }
@@ -7749,15 +12099,15 @@ function* generateWithOverlayInner(rowIterator, overlays, compare2) {
7749
12099
  let removeOverlaySkipped = false;
7750
12100
  for (const row of rowIterator) {
7751
12101
  if (!addOverlayYielded && overlays.add) {
7752
- const cmp = compare2(overlays.add, row);
7753
- if (cmp < 0) {
12102
+ const cmp2 = compare2(overlays.add, row);
12103
+ if (cmp2 < 0) {
7754
12104
  addOverlayYielded = true;
7755
12105
  yield { row: overlays.add, relationships: {} };
7756
12106
  }
7757
12107
  }
7758
12108
  if (!removeOverlaySkipped && overlays.remove) {
7759
- const cmp = compare2(overlays.remove, row);
7760
- if (cmp === 0) {
12109
+ const cmp2 = compare2(overlays.remove, row);
12110
+ if (cmp2 === 0) {
7761
12111
  removeOverlaySkipped = true;
7762
12112
  continue;
7763
12113
  }
@@ -7774,9 +12124,9 @@ function makeBoundComparator(sort) {
7774
12124
  return (a, b) => {
7775
12125
  for (const entry of sort) {
7776
12126
  const key = entry[0];
7777
- const cmp = compareBounds(a[key], b[key]);
7778
- if (cmp !== 0) {
7779
- return entry[1] === "asc" ? cmp : -cmp;
12127
+ const cmp2 = compareBounds(a[key], b[key]);
12128
+ if (cmp2 !== 0) {
12129
+ return entry[1] === "asc" ? cmp2 : -cmp2;
7780
12130
  }
7781
12131
  }
7782
12132
  return 0;
@@ -8692,7 +13042,7 @@ function makeMessage(message, context, logLevel) {
8692
13042
  }
8693
13043
 
8694
13044
  // ../zero-client/src/client/version.ts
8695
- var version2 = "0.24.2025100802";
13045
+ var version2 = "0.24.2025101200";
8696
13046
 
8697
13047
  // ../zero-client/src/client/log-options.ts
8698
13048
  var LevelFilterLogSink = class {
@@ -8987,7 +13337,7 @@ var State = class {
8987
13337
  };
8988
13338
 
8989
13339
  // ../zero-client/src/client/mutation-tracker.ts
8990
- import { resolver as resolver8 } from "@rocicorp/resolver";
13340
+ import { resolver as resolver9 } from "@rocicorp/resolver";
8991
13341
  var currentEphemeralID = 0;
8992
13342
  function nextEphemeralID() {
8993
13343
  return ++currentEphemeralID;
@@ -9025,7 +13375,7 @@ var MutationTracker = class {
9025
13375
  }
9026
13376
  trackMutation() {
9027
13377
  const id = nextEphemeralID();
9028
- const mutationResolver = resolver8();
13378
+ const mutationResolver = resolver9();
9029
13379
  this.#outstandingMutations.set(id, {
9030
13380
  resolver: mutationResolver
9031
13381
  });
@@ -10229,12 +14579,12 @@ var Zero = class _Zero {
10229
14579
  };
10230
14580
  #zeroContext;
10231
14581
  queryDelegate;
10232
- #connectResolver = resolver9();
14582
+ #connectResolver = resolver10();
10233
14583
  #pendingPullsByRequestID = /* @__PURE__ */ new Map();
10234
14584
  #lastMutationIDReceived = 0;
10235
14585
  #socket = void 0;
10236
- #socketResolver = resolver9();
10237
- #connectionStateChangeResolver = resolver9();
14586
+ #socketResolver = resolver10();
14587
+ #connectionStateChangeResolver = resolver10();
10238
14588
  /**
10239
14589
  * This resolver is only used for rejections. It is awaited in the connected
10240
14590
  * state (including when waiting for a pong). It is rejected when we get an
@@ -10253,7 +14603,7 @@ var Zero = class _Zero {
10253
14603
  }
10254
14604
  this.#connectionState = state;
10255
14605
  this.#connectionStateChangeResolver.resolve(state);
10256
- this.#connectionStateChangeResolver = resolver9();
14606
+ this.#connectionStateChangeResolver = resolver10();
10257
14607
  if (false) {
10258
14608
  asTestZero(this)[onSetConnectionStateSymbol]?.(state);
10259
14609
  }
@@ -11081,9 +15431,9 @@ ${error.errorBody.message}`, error);
11081
15431
  lc.error?.("disconnect() called while disconnected");
11082
15432
  break;
11083
15433
  }
11084
- this.#socketResolver = resolver9();
15434
+ this.#socketResolver = resolver10();
11085
15435
  lc.debug?.("Creating new connect resolver");
11086
- this.#connectResolver = resolver9();
15436
+ this.#connectResolver = resolver10();
11087
15437
  this.#setConnectionState(Disconnected);
11088
15438
  this.#messageCount = 0;
11089
15439
  this.#connectStart = void 0;
@@ -11130,12 +15480,12 @@ ${error.errorBody.message}`, error);
11130
15480
  const body = pullResponseMessage[1];
11131
15481
  lc = lc.withContext("requestID", body.requestID);
11132
15482
  lc.debug?.("Handling pull response", body);
11133
- const resolver10 = this.#pendingPullsByRequestID.get(body.requestID);
11134
- if (!resolver10) {
15483
+ const resolver11 = this.#pendingPullsByRequestID.get(body.requestID);
15484
+ if (!resolver11) {
11135
15485
  lc.debug?.("No resolver found");
11136
15486
  return;
11137
15487
  }
11138
- resolver10.resolve(pullResponseMessage[1]);
15488
+ resolver11.resolve(pullResponseMessage[1]);
11139
15489
  }
11140
15490
  async #pusher(req, requestID) {
11141
15491
  assert(req.pushVersion === 1);
@@ -11221,6 +15571,7 @@ ${error.errorBody.message}`, error);
11221
15571
  };
11222
15572
  await this.#updateAuthToken(bareLogContext);
11223
15573
  let needsReauth = false;
15574
+ let lastReauthAttemptAt;
11224
15575
  let gotError = false;
11225
15576
  let backoffMs = RUN_LOOP_INTERVAL_MS;
11226
15577
  let additionalConnectParams;
@@ -11237,6 +15588,7 @@ ${error.errorBody.message}`, error);
11237
15588
  }
11238
15589
  await this.#visibilityWatcher.waitForVisible();
11239
15590
  if (needsReauth) {
15591
+ lastReauthAttemptAt = Date.now();
11240
15592
  await this.#updateAuthToken(lc, "invalid-token");
11241
15593
  }
11242
15594
  if (reloadScheduled()) {
@@ -11266,7 +15618,7 @@ ${error.errorBody.message}`, error);
11266
15618
  PING_INTERVAL_MS,
11267
15619
  controller.signal
11268
15620
  );
11269
- this.#rejectMessageError = resolver9();
15621
+ this.#rejectMessageError = resolver10();
11270
15622
  const PING = 0;
11271
15623
  const HIDDEN = 2;
11272
15624
  const raceResult = await promiseRace([
@@ -11318,11 +15670,12 @@ ${error.errorBody.message}`, error);
11318
15670
  ex
11319
15671
  );
11320
15672
  if (isAuthError(ex)) {
11321
- if (!needsReauth) {
11322
- needsReauth = true;
15673
+ const now = Date.now();
15674
+ const msSinceLastReauthAttempt = lastReauthAttemptAt === void 0 ? Number.POSITIVE_INFINITY : now - lastReauthAttemptAt;
15675
+ needsReauth = true;
15676
+ if (msSinceLastReauthAttempt > RUN_LOOP_INTERVAL_MS) {
11323
15677
  continue;
11324
15678
  }
11325
- needsReauth = true;
11326
15679
  }
11327
15680
  if (isServerError(ex) || ex instanceof TimedOutError || ex instanceof CloseError) {
11328
15681
  gotError = true;
@@ -11380,7 +15733,7 @@ ${error.errorBody.message}`, error);
11380
15733
  }
11381
15734
  ];
11382
15735
  send(socket, pullRequestMessage);
11383
- const pullResponseResolver = resolver9();
15736
+ const pullResponseResolver = resolver10();
11384
15737
  this.#pendingPullsByRequestID.set(requestID, pullResponseResolver);
11385
15738
  try {
11386
15739
  const TIMEOUT = 0;
@@ -11443,7 +15796,7 @@ ${error.errorBody.message}`, error);
11443
15796
  */
11444
15797
  async #ping(lc, messageErrorRejectionPromise) {
11445
15798
  lc.debug?.("pinging");
11446
- const { promise, resolve } = resolver9();
15799
+ const { promise, resolve } = resolver10();
11447
15800
  this.#onPong = resolve;
11448
15801
  const pingMessage = ["ping", {}];
11449
15802
  const t0 = performance.now();
@@ -11661,8 +16014,15 @@ export {
11661
16014
  json,
11662
16015
  enumeration,
11663
16016
  createSchema,
16017
+ defaultFormat,
16018
+ ExpressionBuilder,
16019
+ idSymbol,
16020
+ applyChange,
16021
+ newQuery,
16022
+ newQuerySymbol,
16023
+ AbstractQuery,
11664
16024
  clientToServer,
11665
16025
  update_needed_reason_type_enum_exports,
11666
16026
  Zero
11667
16027
  };
11668
- //# sourceMappingURL=chunk-UEUKOYBK.js.map
16028
+ //# sourceMappingURL=chunk-5J6ROZSO.js.map