@rocicorp/zero 0.26.1 → 0.26.2-canary.1

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 (1086) hide show
  1. package/out/_virtual/_@oxc-project_runtime@0.115.0/helpers/usingCtx.js +57 -0
  2. package/out/_virtual/_rolldown/runtime.js +27 -0
  3. package/out/analyze-query/src/bin-analyze.js +195 -283
  4. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  5. package/out/analyze-query/src/bin-transform.js +35 -40
  6. package/out/analyze-query/src/bin-transform.js.map +1 -1
  7. package/out/analyze-query/src/explain-queries.js +11 -13
  8. package/out/analyze-query/src/explain-queries.js.map +1 -1
  9. package/out/analyze-query/src/run-ast.js +68 -103
  10. package/out/analyze-query/src/run-ast.js.map +1 -1
  11. package/out/ast-to-zql/src/ast-to-zql.js +105 -153
  12. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  13. package/out/ast-to-zql/src/bin.js +57 -62
  14. package/out/ast-to-zql/src/bin.js.map +1 -1
  15. package/out/ast-to-zql/src/format.js +14 -13
  16. package/out/ast-to-zql/src/format.js.map +1 -1
  17. package/out/datadog/src/datadog-log-sink.js +148 -213
  18. package/out/datadog/src/datadog-log-sink.js.map +1 -1
  19. package/out/otel/src/enabled.js +9 -11
  20. package/out/otel/src/enabled.js.map +1 -1
  21. package/out/otel/src/log-options.js +25 -35
  22. package/out/otel/src/log-options.js.map +1 -1
  23. package/out/otel/src/maybe-time.js +13 -14
  24. package/out/otel/src/maybe-time.js.map +1 -1
  25. package/out/otel/src/span.js +23 -26
  26. package/out/otel/src/span.js.map +1 -1
  27. package/out/otel/src/test-log-config.js +11 -10
  28. package/out/otel/src/test-log-config.js.map +1 -1
  29. package/out/otel/src/version.js +6 -5
  30. package/out/otel/src/version.js.map +1 -1
  31. package/out/replicache/src/async-iterable-to-array.js +8 -9
  32. package/out/replicache/src/async-iterable-to-array.js.map +1 -1
  33. package/out/replicache/src/bg-interval.js +28 -35
  34. package/out/replicache/src/bg-interval.js.map +1 -1
  35. package/out/replicache/src/btree/diff.js +6 -5
  36. package/out/replicache/src/btree/diff.js.map +1 -1
  37. package/out/replicache/src/btree/node.js +281 -372
  38. package/out/replicache/src/btree/node.js.map +1 -1
  39. package/out/replicache/src/btree/read.js +155 -256
  40. package/out/replicache/src/btree/read.js.map +1 -1
  41. package/out/replicache/src/btree/splice.js +60 -80
  42. package/out/replicache/src/btree/splice.js.map +1 -1
  43. package/out/replicache/src/btree/write.js +134 -158
  44. package/out/replicache/src/btree/write.js.map +1 -1
  45. package/out/replicache/src/call-default-fetch.js +28 -32
  46. package/out/replicache/src/call-default-fetch.js.map +1 -1
  47. package/out/replicache/src/config.js +2 -0
  48. package/out/replicache/src/connection-loop-delegates.js +31 -33
  49. package/out/replicache/src/connection-loop-delegates.js.map +1 -1
  50. package/out/replicache/src/connection-loop.js +174 -240
  51. package/out/replicache/src/connection-loop.js.map +1 -1
  52. package/out/replicache/src/cookies.js +22 -32
  53. package/out/replicache/src/cookies.js.map +1 -1
  54. package/out/replicache/src/dag/chunk.js +44 -50
  55. package/out/replicache/src/dag/chunk.js.map +1 -1
  56. package/out/replicache/src/dag/gc.js +94 -114
  57. package/out/replicache/src/dag/gc.js.map +1 -1
  58. package/out/replicache/src/dag/key.js +9 -11
  59. package/out/replicache/src/dag/key.js.map +1 -1
  60. package/out/replicache/src/dag/lazy-store.js +458 -510
  61. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  62. package/out/replicache/src/dag/store-impl.js +147 -178
  63. package/out/replicache/src/dag/store-impl.js.map +1 -1
  64. package/out/replicache/src/dag/store.js +19 -22
  65. package/out/replicache/src/dag/store.js.map +1 -1
  66. package/out/replicache/src/dag/visitor.js +23 -21
  67. package/out/replicache/src/dag/visitor.js.map +1 -1
  68. package/out/replicache/src/db/commit.js +209 -283
  69. package/out/replicache/src/db/commit.js.map +1 -1
  70. package/out/replicache/src/db/index.js +79 -122
  71. package/out/replicache/src/db/index.js.map +1 -1
  72. package/out/replicache/src/db/read.js +44 -60
  73. package/out/replicache/src/db/read.js.map +1 -1
  74. package/out/replicache/src/db/rebase.js +22 -77
  75. package/out/replicache/src/db/rebase.js.map +1 -1
  76. package/out/replicache/src/db/write.js +162 -296
  77. package/out/replicache/src/db/write.js.map +1 -1
  78. package/out/replicache/src/deleted-clients.js +59 -87
  79. package/out/replicache/src/deleted-clients.js.map +1 -1
  80. package/out/replicache/src/error-responses.js +18 -26
  81. package/out/replicache/src/error-responses.js.map +1 -1
  82. package/out/replicache/src/expo-sqlite.js +2 -0
  83. package/out/replicache/src/frozen-json.js +74 -108
  84. package/out/replicache/src/frozen-json.js.map +1 -1
  85. package/out/replicache/src/get-default-puller.js +34 -46
  86. package/out/replicache/src/get-default-puller.js.map +1 -1
  87. package/out/replicache/src/get-default-pusher.js +25 -33
  88. package/out/replicache/src/get-default-pusher.js.map +1 -1
  89. package/out/replicache/src/get-kv-store-provider.js +18 -20
  90. package/out/replicache/src/get-kv-store-provider.js.map +1 -1
  91. package/out/replicache/src/hash.js +29 -29
  92. package/out/replicache/src/hash.js.map +1 -1
  93. package/out/replicache/src/http-request-info.js +9 -8
  94. package/out/replicache/src/http-request-info.js.map +1 -1
  95. package/out/replicache/src/impl.js +2 -0
  96. package/out/replicache/src/index-defs.js +17 -28
  97. package/out/replicache/src/index-defs.js.map +1 -1
  98. package/out/replicache/src/kv/expo-sqlite/store.js +52 -50
  99. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  100. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +71 -68
  101. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  102. package/out/replicache/src/kv/idb-store.js +144 -168
  103. package/out/replicache/src/kv/idb-store.js.map +1 -1
  104. package/out/replicache/src/kv/mem-store.js +57 -45
  105. package/out/replicache/src/kv/mem-store.js.map +1 -1
  106. package/out/replicache/src/kv/op-sqlite/store.js +56 -62
  107. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  108. package/out/replicache/src/kv/op-sqlite/types.d.ts.map +1 -1
  109. package/out/replicache/src/kv/op-sqlite/types.js +7 -6
  110. package/out/replicache/src/kv/op-sqlite/types.js.map +1 -1
  111. package/out/replicache/src/kv/read-impl.js +26 -25
  112. package/out/replicache/src/kv/read-impl.js.map +1 -1
  113. package/out/replicache/src/kv/sqlite-store.js +194 -207
  114. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  115. package/out/replicache/src/kv/throw-if-closed.js +12 -19
  116. package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
  117. package/out/replicache/src/kv/write-impl-base.js +44 -56
  118. package/out/replicache/src/kv/write-impl-base.js.map +1 -1
  119. package/out/replicache/src/kv/write-impl.js +22 -26
  120. package/out/replicache/src/kv/write-impl.js.map +1 -1
  121. package/out/replicache/src/lazy.js +10 -11
  122. package/out/replicache/src/lazy.js.map +1 -1
  123. package/out/replicache/src/log-options.js +14 -7
  124. package/out/replicache/src/log-options.js.map +1 -1
  125. package/out/replicache/src/make-idb-name.js +14 -9
  126. package/out/replicache/src/make-idb-name.js.map +1 -1
  127. package/out/replicache/src/mutation-recovery.js +12 -0
  128. package/out/replicache/src/mutation-recovery.js.map +1 -0
  129. package/out/replicache/src/new-client-channel.js +34 -42
  130. package/out/replicache/src/new-client-channel.js.map +1 -1
  131. package/out/replicache/src/on-persist-channel.js +26 -29
  132. package/out/replicache/src/on-persist-channel.js.map +1 -1
  133. package/out/replicache/src/op-sqlite.js +2 -0
  134. package/out/replicache/src/patch-operation.js +27 -36
  135. package/out/replicache/src/patch-operation.js.map +1 -1
  136. package/out/replicache/src/pending-mutations.js +14 -12
  137. package/out/replicache/src/pending-mutations.js.map +1 -1
  138. package/out/replicache/src/persist/client-gc.js +36 -51
  139. package/out/replicache/src/persist/client-gc.js.map +1 -1
  140. package/out/replicache/src/persist/client-group-gc.js +29 -36
  141. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  142. package/out/replicache/src/persist/client-groups.js +80 -154
  143. package/out/replicache/src/persist/client-groups.js.map +1 -1
  144. package/out/replicache/src/persist/clients.js +212 -307
  145. package/out/replicache/src/persist/clients.js.map +1 -1
  146. package/out/replicache/src/persist/collect-idb-databases.js +109 -171
  147. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  148. package/out/replicache/src/persist/gather-mem-only-visitor.js +23 -24
  149. package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
  150. package/out/replicache/src/persist/gather-not-cached-visitor.js +35 -33
  151. package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
  152. package/out/replicache/src/persist/heartbeat.js +31 -41
  153. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  154. package/out/replicache/src/persist/idb-databases-store-db-name.js +9 -12
  155. package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
  156. package/out/replicache/src/persist/idb-databases-store.js +78 -97
  157. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  158. package/out/replicache/src/persist/make-client-id.js +13 -9
  159. package/out/replicache/src/persist/make-client-id.js.map +1 -1
  160. package/out/replicache/src/persist/persist.js +113 -174
  161. package/out/replicache/src/persist/persist.js.map +1 -1
  162. package/out/replicache/src/persist/refresh.js +94 -183
  163. package/out/replicache/src/persist/refresh.js.map +1 -1
  164. package/out/replicache/src/process-scheduler.js +122 -143
  165. package/out/replicache/src/process-scheduler.js.map +1 -1
  166. package/out/replicache/src/pusher.js +21 -26
  167. package/out/replicache/src/pusher.js.map +1 -1
  168. package/out/replicache/src/replicache-impl.js +844 -1184
  169. package/out/replicache/src/replicache-impl.js.map +1 -1
  170. package/out/replicache/src/report-error.js +9 -6
  171. package/out/replicache/src/report-error.js.map +1 -1
  172. package/out/replicache/src/request-idle.js +13 -11
  173. package/out/replicache/src/request-idle.js.map +1 -1
  174. package/out/replicache/src/scan-iterator.d.ts.map +1 -1
  175. package/out/replicache/src/scan-iterator.js +108 -135
  176. package/out/replicache/src/scan-iterator.js.map +1 -1
  177. package/out/replicache/src/scan-options.js +33 -39
  178. package/out/replicache/src/scan-options.js.map +1 -1
  179. package/out/replicache/src/set-interval-with-signal.js +11 -10
  180. package/out/replicache/src/set-interval-with-signal.js.map +1 -1
  181. package/out/replicache/src/sqlite.js +2 -0
  182. package/out/replicache/src/subscriptions.js +222 -338
  183. package/out/replicache/src/subscriptions.js.map +1 -1
  184. package/out/replicache/src/sync/diff.js +52 -65
  185. package/out/replicache/src/sync/diff.js.map +1 -1
  186. package/out/replicache/src/sync/ids.js +8 -9
  187. package/out/replicache/src/sync/ids.js.map +1 -1
  188. package/out/replicache/src/sync/patch.js +34 -45
  189. package/out/replicache/src/sync/patch.js.map +1 -1
  190. package/out/replicache/src/sync/pull-error.js +15 -15
  191. package/out/replicache/src/sync/pull-error.js.map +1 -1
  192. package/out/replicache/src/sync/pull.js +145 -283
  193. package/out/replicache/src/sync/pull.js.map +1 -1
  194. package/out/replicache/src/sync/push.js +64 -79
  195. package/out/replicache/src/sync/push.js.map +1 -1
  196. package/out/replicache/src/sync/request-id.js +23 -15
  197. package/out/replicache/src/sync/request-id.js.map +1 -1
  198. package/out/replicache/src/sync/sync-head-name.js +6 -5
  199. package/out/replicache/src/sync/sync-head-name.js.map +1 -1
  200. package/out/replicache/src/to-error.js +7 -8
  201. package/out/replicache/src/to-error.js.map +1 -1
  202. package/out/replicache/src/transaction-closed-error.js +15 -15
  203. package/out/replicache/src/transaction-closed-error.js.map +1 -1
  204. package/out/replicache/src/transactions.js +120 -140
  205. package/out/replicache/src/transactions.js.map +1 -1
  206. package/out/replicache/src/version.js +9 -5
  207. package/out/replicache/src/version.js.map +1 -1
  208. package/out/replicache/src/with-transactions.js +23 -20
  209. package/out/replicache/src/with-transactions.js.map +1 -1
  210. package/out/shared/src/abort-error.js +7 -6
  211. package/out/shared/src/abort-error.js.map +1 -1
  212. package/out/shared/src/arrays.js +35 -42
  213. package/out/shared/src/arrays.js.map +1 -1
  214. package/out/shared/src/asserts.js +21 -45
  215. package/out/shared/src/asserts.js.map +1 -1
  216. package/out/shared/src/bigint-json.js +42 -38
  217. package/out/shared/src/bigint-json.js.map +1 -1
  218. package/out/shared/src/binary-search.js +27 -18
  219. package/out/shared/src/binary-search.js.map +1 -1
  220. package/out/shared/src/broadcast-channel.js +20 -23
  221. package/out/shared/src/broadcast-channel.js.map +1 -1
  222. package/out/shared/src/browser-env.js +11 -17
  223. package/out/shared/src/browser-env.js.map +1 -1
  224. package/out/shared/src/btree-set.js +419 -481
  225. package/out/shared/src/btree-set.js.map +1 -1
  226. package/out/shared/src/cache.js +43 -36
  227. package/out/shared/src/cache.js.map +1 -1
  228. package/out/shared/src/centroid.js +24 -26
  229. package/out/shared/src/centroid.js.map +1 -1
  230. package/out/shared/src/config.js +6 -6
  231. package/out/shared/src/config.js.map +1 -1
  232. package/out/shared/src/custom-key-map.js +54 -58
  233. package/out/shared/src/custom-key-map.js.map +1 -1
  234. package/out/shared/src/custom-key-set.js +53 -51
  235. package/out/shared/src/custom-key-set.js.map +1 -1
  236. package/out/shared/src/deep-clone.js +30 -41
  237. package/out/shared/src/deep-clone.js.map +1 -1
  238. package/out/shared/src/deep-merge.js +25 -24
  239. package/out/shared/src/deep-merge.js.map +1 -1
  240. package/out/shared/src/document-visible.js +63 -70
  241. package/out/shared/src/document-visible.js.map +1 -1
  242. package/out/shared/src/dotenv.js +7 -3
  243. package/out/shared/src/dotenv.js.map +1 -1
  244. package/out/shared/src/error.js +43 -64
  245. package/out/shared/src/error.js.map +1 -1
  246. package/out/shared/src/has-own.js +6 -5
  247. package/out/shared/src/has-own.js.map +1 -1
  248. package/out/shared/src/hash.js +15 -14
  249. package/out/shared/src/hash.js.map +1 -1
  250. package/out/shared/src/iterables.js +34 -47
  251. package/out/shared/src/iterables.js.map +1 -1
  252. package/out/shared/src/json-schema.js +25 -30
  253. package/out/shared/src/json-schema.js.map +1 -1
  254. package/out/shared/src/json.js +90 -129
  255. package/out/shared/src/json.js.map +1 -1
  256. package/out/shared/src/logging-test-utils.js +9 -11
  257. package/out/shared/src/logging-test-utils.js.map +1 -1
  258. package/out/shared/src/logging.js +75 -95
  259. package/out/shared/src/logging.js.map +1 -1
  260. package/out/shared/src/must.js +7 -8
  261. package/out/shared/src/must.js.map +1 -1
  262. package/out/shared/src/navigator.js +6 -5
  263. package/out/shared/src/navigator.js.map +1 -1
  264. package/out/shared/src/object-traversal.js +23 -23
  265. package/out/shared/src/object-traversal.js.map +1 -1
  266. package/out/shared/src/objects.js +15 -18
  267. package/out/shared/src/objects.js.map +1 -1
  268. package/out/shared/src/options.js +225 -302
  269. package/out/shared/src/options.js.map +1 -1
  270. package/out/shared/src/parse-big-int.js +12 -11
  271. package/out/shared/src/parse-big-int.js.map +1 -1
  272. package/out/shared/src/promise-race.js +21 -17
  273. package/out/shared/src/promise-race.js.map +1 -1
  274. package/out/shared/src/queue.js +124 -124
  275. package/out/shared/src/queue.js.map +1 -1
  276. package/out/shared/src/rand.js +13 -7
  277. package/out/shared/src/rand.js.map +1 -1
  278. package/out/shared/src/random-uint64.js +8 -7
  279. package/out/shared/src/random-uint64.js.map +1 -1
  280. package/out/shared/src/random-values.js +8 -11
  281. package/out/shared/src/random-values.js.map +1 -1
  282. package/out/shared/src/record-proxy.js +68 -57
  283. package/out/shared/src/record-proxy.js.map +1 -1
  284. package/out/shared/src/resolved-promises.js +9 -11
  285. package/out/shared/src/resolved-promises.js.map +1 -1
  286. package/out/shared/src/sentinels.js +9 -12
  287. package/out/shared/src/sentinels.js.map +1 -1
  288. package/out/shared/src/set-utils.js +41 -63
  289. package/out/shared/src/set-utils.js.map +1 -1
  290. package/out/shared/src/size-of-value.js +55 -51
  291. package/out/shared/src/size-of-value.js.map +1 -1
  292. package/out/shared/src/sleep.js +50 -45
  293. package/out/shared/src/sleep.js.map +1 -1
  294. package/out/shared/src/string-compare.js +8 -11
  295. package/out/shared/src/string-compare.js.map +1 -1
  296. package/out/shared/src/subscribable.js +34 -33
  297. package/out/shared/src/subscribable.js.map +1 -1
  298. package/out/shared/src/tdigest-schema.js +11 -7
  299. package/out/shared/src/tdigest-schema.js.map +1 -1
  300. package/out/shared/src/tdigest.js +197 -270
  301. package/out/shared/src/tdigest.js.map +1 -1
  302. package/out/shared/src/valita.js +145 -174
  303. package/out/shared/src/valita.js.map +1 -1
  304. package/out/z2s/src/compiler.d.ts.map +1 -1
  305. package/out/z2s/src/compiler.js +238 -468
  306. package/out/z2s/src/compiler.js.map +1 -1
  307. package/out/z2s/src/sql.d.ts +0 -1
  308. package/out/z2s/src/sql.d.ts.map +1 -1
  309. package/out/z2s/src/sql.js +149 -194
  310. package/out/z2s/src/sql.js.map +1 -1
  311. package/out/zero/package.js +193 -0
  312. package/out/zero/package.js.map +1 -0
  313. package/out/zero/src/adapters/drizzle.js +1 -6
  314. package/out/zero/src/adapters/pg.js +1 -6
  315. package/out/zero/src/adapters/postgresjs.js +1 -6
  316. package/out/zero/src/adapters/prisma.js +1 -5
  317. package/out/zero/src/analyze-query.js +1 -1
  318. package/out/zero/src/ast-to-zql.js +1 -1
  319. package/out/zero/src/bindings.js +6 -21
  320. package/out/zero/src/build-schema.js +5 -1
  321. package/out/zero/src/build-schema.js.map +1 -1
  322. package/out/zero/src/change-protocol/v0.js +3 -5
  323. package/out/zero/src/cli.js +2 -2
  324. package/out/zero/src/deploy-permissions.js +1 -1
  325. package/out/zero/src/expo-sqlite.js +2 -4
  326. package/out/zero/src/op-sqlite.js +2 -4
  327. package/out/zero/src/pg.js +2 -20
  328. package/out/zero/src/react-native.js +16 -12
  329. package/out/zero/src/react-native.js.map +1 -1
  330. package/out/zero/src/react.js +3 -12
  331. package/out/zero/src/server/runner/main.js +2 -0
  332. package/out/zero/src/server.js +2 -17
  333. package/out/zero/src/solid.js +3 -12
  334. package/out/zero/src/sqlite.js +2 -6
  335. package/out/zero/src/transform-query.js +1 -1
  336. package/out/zero/src/zero-cache-dev.js +124 -151
  337. package/out/zero/src/zero-cache-dev.js.map +1 -1
  338. package/out/zero/src/zero-out.js +9 -6
  339. package/out/zero/src/zero-out.js.map +1 -1
  340. package/out/zero/src/zero.js +6 -55
  341. package/out/zero/src/zqlite.js +2 -7
  342. package/out/zero-cache/src/auth/auth.js +138 -172
  343. package/out/zero-cache/src/auth/auth.js.map +1 -1
  344. package/out/zero-cache/src/auth/jwt.js +25 -33
  345. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  346. package/out/zero-cache/src/auth/load-permissions.js +54 -62
  347. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  348. package/out/zero-cache/src/auth/read-authorizer.js +70 -80
  349. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  350. package/out/zero-cache/src/auth/write-authorizer.js +284 -432
  351. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  352. package/out/zero-cache/src/config/network.js +31 -45
  353. package/out/zero-cache/src/config/network.js.map +1 -1
  354. package/out/zero-cache/src/config/normalize.js +81 -83
  355. package/out/zero-cache/src/config/normalize.js.map +1 -1
  356. package/out/zero-cache/src/config/server-context.js +32 -29
  357. package/out/zero-cache/src/config/server-context.js.map +1 -1
  358. package/out/zero-cache/src/config/zero-config.js +753 -833
  359. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  360. package/out/zero-cache/src/custom/fetch.js +183 -230
  361. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  362. package/out/zero-cache/src/custom-queries/transform-query.js +93 -99
  363. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  364. package/out/zero-cache/src/db/create.js +27 -29
  365. package/out/zero-cache/src/db/create.js.map +1 -1
  366. package/out/zero-cache/src/db/delete-lite-db.js +11 -7
  367. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  368. package/out/zero-cache/src/db/lite-tables.js +118 -158
  369. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  370. package/out/zero-cache/src/db/migration-lite.js +110 -178
  371. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  372. package/out/zero-cache/src/db/migration.js +82 -151
  373. package/out/zero-cache/src/db/migration.js.map +1 -1
  374. package/out/zero-cache/src/db/mode-enum.js +8 -9
  375. package/out/zero-cache/src/db/mode-enum.js.map +1 -1
  376. package/out/zero-cache/src/db/pg-copy.js +56 -54
  377. package/out/zero-cache/src/db/pg-copy.js.map +1 -1
  378. package/out/zero-cache/src/db/pg-to-lite.js +74 -110
  379. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  380. package/out/zero-cache/src/db/pg-type-parser.js +19 -36
  381. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  382. package/out/zero-cache/src/db/run-transaction.js +19 -20
  383. package/out/zero-cache/src/db/run-transaction.js.map +1 -1
  384. package/out/zero-cache/src/db/specs.js +42 -78
  385. package/out/zero-cache/src/db/specs.js.map +1 -1
  386. package/out/zero-cache/src/db/statements.js +52 -59
  387. package/out/zero-cache/src/db/statements.js.map +1 -1
  388. package/out/zero-cache/src/db/transaction-pool.js +376 -400
  389. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  390. package/out/zero-cache/src/db/warmup.js +13 -24
  391. package/out/zero-cache/src/db/warmup.js.map +1 -1
  392. package/out/zero-cache/src/observability/events.js +89 -99
  393. package/out/zero-cache/src/observability/events.js.map +1 -1
  394. package/out/zero-cache/src/observability/metrics.js +30 -54
  395. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  396. package/out/zero-cache/src/scripts/decommission.js +42 -47
  397. package/out/zero-cache/src/scripts/decommission.js.map +1 -1
  398. package/out/zero-cache/src/scripts/deploy-permissions.js +106 -144
  399. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  400. package/out/zero-cache/src/scripts/permissions.js +86 -107
  401. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  402. package/out/zero-cache/src/server/anonymous-otel-start.js +306 -440
  403. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  404. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  405. package/out/zero-cache/src/server/change-streamer.js +57 -130
  406. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  407. package/out/zero-cache/src/server/inspector-delegate.js +89 -100
  408. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  409. package/out/zero-cache/src/server/logging.js +18 -26
  410. package/out/zero-cache/src/server/logging.js.map +1 -1
  411. package/out/zero-cache/src/server/main.js +85 -142
  412. package/out/zero-cache/src/server/main.js.map +1 -1
  413. package/out/zero-cache/src/server/mutator.js +16 -13
  414. package/out/zero-cache/src/server/mutator.js.map +1 -1
  415. package/out/zero-cache/src/server/otel-diag-logger.js +42 -49
  416. package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
  417. package/out/zero-cache/src/server/otel-log-sink.js +34 -44
  418. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  419. package/out/zero-cache/src/server/otel-start.js +43 -51
  420. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  421. package/out/zero-cache/src/server/priority-op.js +27 -25
  422. package/out/zero-cache/src/server/priority-op.js.map +1 -1
  423. package/out/zero-cache/src/server/reaper.js +32 -43
  424. package/out/zero-cache/src/server/reaper.js.map +1 -1
  425. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  426. package/out/zero-cache/src/server/replicator.js +41 -57
  427. package/out/zero-cache/src/server/replicator.js.map +1 -1
  428. package/out/zero-cache/src/server/runner/main.js +7 -8
  429. package/out/zero-cache/src/server/runner/main.js.map +1 -1
  430. package/out/zero-cache/src/server/runner/run-worker.js +56 -52
  431. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  432. package/out/zero-cache/src/server/runner/runtime.js +26 -32
  433. package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
  434. package/out/zero-cache/src/server/runner/zero-dispatcher.js +22 -27
  435. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  436. package/out/zero-cache/src/server/syncer.js +79 -148
  437. package/out/zero-cache/src/server/syncer.js.map +1 -1
  438. package/out/zero-cache/src/server/worker-dispatcher.js +84 -113
  439. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  440. package/out/zero-cache/src/server/worker-urls.d.ts +2 -1
  441. package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
  442. package/out/zero-cache/src/server/worker-urls.js +14 -18
  443. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  444. package/out/zero-cache/src/server/write-worker.js +2 -0
  445. package/out/zero-cache/src/services/analyze.js +61 -130
  446. package/out/zero-cache/src/services/analyze.js.map +1 -1
  447. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +420 -419
  448. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  449. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +111 -114
  450. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  451. package/out/zero-cache/src/services/change-source/common/replica-schema.js +80 -148
  452. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  453. package/out/zero-cache/src/services/change-source/custom/change-source.js +154 -216
  454. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  455. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js +11 -14
  456. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
  457. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +168 -212
  458. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  459. package/out/zero-cache/src/services/change-source/pg/change-source.js +672 -892
  460. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  461. package/out/zero-cache/src/services/change-source/pg/decommission.js +19 -23
  462. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  463. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +258 -411
  464. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  465. package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js +59 -65
  466. package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
  467. package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js +218 -247
  468. package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
  469. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +100 -142
  470. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  471. package/out/zero-cache/src/services/change-source/pg/lsn.js +17 -19
  472. package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
  473. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +88 -98
  474. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  475. package/out/zero-cache/src/services/change-source/pg/schema/init.js +96 -177
  476. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  477. package/out/zero-cache/src/services/change-source/pg/schema/published.js +69 -107
  478. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  479. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +151 -212
  480. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  481. package/out/zero-cache/src/services/change-source/pg/schema/validation.js +22 -53
  482. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  483. package/out/zero-cache/src/services/change-source/protocol/current/control.js +24 -12
  484. package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
  485. package/out/zero-cache/src/services/change-source/protocol/current/data.js +180 -290
  486. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  487. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js +21 -33
  488. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
  489. package/out/zero-cache/src/services/change-source/protocol/current/json.js +7 -18
  490. package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -1
  491. package/out/zero-cache/src/services/change-source/protocol/current/path.js +24 -5
  492. package/out/zero-cache/src/services/change-source/protocol/current/path.js.map +1 -1
  493. package/out/zero-cache/src/services/change-source/protocol/current/status.js +25 -19
  494. package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
  495. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +24 -16
  496. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  497. package/out/zero-cache/src/services/change-source/protocol/current.js +51 -46
  498. package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
  499. package/out/zero-cache/src/services/change-source/protocol/mod.js +2 -0
  500. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +165 -171
  501. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  502. package/out/zero-cache/src/services/change-streamer/broadcast.js +163 -169
  503. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  504. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +154 -221
  505. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  506. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  507. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +340 -299
  508. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  509. package/out/zero-cache/src/services/change-streamer/change-streamer.js +17 -24
  510. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  511. package/out/zero-cache/src/services/change-streamer/forwarder.js +84 -103
  512. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  513. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +49 -43
  514. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -1
  515. package/out/zero-cache/src/services/change-streamer/schema/init.js +61 -89
  516. package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
  517. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +20 -1
  518. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  519. package/out/zero-cache/src/services/change-streamer/schema/tables.js +131 -109
  520. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  521. package/out/zero-cache/src/services/change-streamer/snapshot.js +26 -28
  522. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  523. package/out/zero-cache/src/services/change-streamer/storer.js +434 -513
  524. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  525. package/out/zero-cache/src/services/change-streamer/subscriber.js +142 -155
  526. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  527. package/out/zero-cache/src/services/heapz.js +18 -20
  528. package/out/zero-cache/src/services/heapz.js.map +1 -1
  529. package/out/zero-cache/src/services/http-service.js +59 -57
  530. package/out/zero-cache/src/services/http-service.js.map +1 -1
  531. package/out/zero-cache/src/services/life-cycle.js +182 -214
  532. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  533. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +102 -81
  534. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
  535. package/out/zero-cache/src/services/litestream/commands.js +144 -205
  536. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  537. package/out/zero-cache/src/services/mutagen/error.js +10 -14
  538. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  539. package/out/zero-cache/src/services/mutagen/mutagen.js +166 -264
  540. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  541. package/out/zero-cache/src/services/mutagen/pusher.js +372 -487
  542. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  543. package/out/zero-cache/src/services/replicator/change-processor.js +483 -592
  544. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  545. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +4 -2
  546. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  547. package/out/zero-cache/src/services/replicator/incremental-sync.js +118 -143
  548. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  549. package/out/zero-cache/src/services/replicator/notifier.js +52 -28
  550. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  551. package/out/zero-cache/src/services/replicator/replication-status.js +105 -128
  552. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  553. package/out/zero-cache/src/services/replicator/replicator.d.ts +2 -1
  554. package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
  555. package/out/zero-cache/src/services/replicator/replicator.js +32 -34
  556. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  557. package/out/zero-cache/src/services/replicator/schema/change-log.js +101 -133
  558. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  559. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +145 -174
  560. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  561. package/out/zero-cache/src/services/replicator/schema/constants.js +11 -5
  562. package/out/zero-cache/src/services/replicator/schema/constants.js.map +1 -1
  563. package/out/zero-cache/src/services/replicator/schema/replication-state.js +56 -107
  564. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  565. package/out/zero-cache/src/services/replicator/schema/table-metadata.js +81 -66
  566. package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
  567. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +69 -0
  568. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -0
  569. package/out/zero-cache/src/services/replicator/write-worker-client.js +96 -0
  570. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -0
  571. package/out/zero-cache/src/services/replicator/write-worker.js +68 -0
  572. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -0
  573. package/out/zero-cache/src/services/run-ast.js +79 -120
  574. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  575. package/out/zero-cache/src/services/runner.js +39 -41
  576. package/out/zero-cache/src/services/runner.js.map +1 -1
  577. package/out/zero-cache/src/services/running-state.js +129 -134
  578. package/out/zero-cache/src/services/running-state.js.map +1 -1
  579. package/out/zero-cache/src/services/statz.js +139 -200
  580. package/out/zero-cache/src/services/statz.js.map +1 -1
  581. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +46 -49
  582. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
  583. package/out/zero-cache/src/services/view-syncer/client-handler.js +257 -299
  584. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  585. package/out/zero-cache/src/services/view-syncer/client-schema.js +52 -82
  586. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
  587. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +85 -107
  588. package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
  589. package/out/zero-cache/src/services/view-syncer/cvr-store.js +604 -757
  590. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  591. package/out/zero-cache/src/services/view-syncer/cvr.js +631 -739
  592. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  593. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +60 -40
  594. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  595. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +95 -178
  596. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  597. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  598. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +572 -722
  599. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  600. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  601. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +246 -257
  602. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  603. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +59 -45
  604. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  605. package/out/zero-cache/src/services/view-syncer/schema/init.js +121 -189
  606. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  607. package/out/zero-cache/src/services/view-syncer/schema/types.js +138 -263
  608. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  609. package/out/zero-cache/src/services/view-syncer/snapshotter.js +322 -335
  610. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  611. package/out/zero-cache/src/services/view-syncer/tracer.js +7 -6
  612. package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -1
  613. package/out/zero-cache/src/services/view-syncer/ttl-clock.js +9 -11
  614. package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
  615. package/out/zero-cache/src/services/view-syncer/view-syncer.js +1067 -1603
  616. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  617. package/out/zero-cache/src/types/error-with-level.js +19 -25
  618. package/out/zero-cache/src/types/error-with-level.js.map +1 -1
  619. package/out/zero-cache/src/types/http.js +17 -26
  620. package/out/zero-cache/src/types/http.js.map +1 -1
  621. package/out/zero-cache/src/types/lexi-version.js +28 -42
  622. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  623. package/out/zero-cache/src/types/lite.js +101 -121
  624. package/out/zero-cache/src/types/lite.js.map +1 -1
  625. package/out/zero-cache/src/types/names.js +6 -5
  626. package/out/zero-cache/src/types/names.js.map +1 -1
  627. package/out/zero-cache/src/types/pg-data-type.d.ts +1 -0
  628. package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
  629. package/out/zero-cache/src/types/pg-data-type.js +58 -73
  630. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  631. package/out/zero-cache/src/types/pg-types.js +12 -19
  632. package/out/zero-cache/src/types/pg-types.js.map +1 -1
  633. package/out/zero-cache/src/types/pg.js +144 -218
  634. package/out/zero-cache/src/types/pg.js.map +1 -1
  635. package/out/zero-cache/src/types/processes.js +95 -90
  636. package/out/zero-cache/src/types/processes.js.map +1 -1
  637. package/out/zero-cache/src/types/profiler.js +32 -27
  638. package/out/zero-cache/src/types/profiler.js.map +1 -1
  639. package/out/zero-cache/src/types/row-key.js +42 -30
  640. package/out/zero-cache/src/types/row-key.js.map +1 -1
  641. package/out/zero-cache/src/types/shards.js +36 -45
  642. package/out/zero-cache/src/types/shards.js.map +1 -1
  643. package/out/zero-cache/src/types/sql.js +20 -9
  644. package/out/zero-cache/src/types/sql.js.map +1 -1
  645. package/out/zero-cache/src/types/state-version.js +17 -23
  646. package/out/zero-cache/src/types/state-version.js.map +1 -1
  647. package/out/zero-cache/src/types/streams.js +234 -270
  648. package/out/zero-cache/src/types/streams.js.map +1 -1
  649. package/out/zero-cache/src/types/strings.js +10 -13
  650. package/out/zero-cache/src/types/strings.js.map +1 -1
  651. package/out/zero-cache/src/types/subscription.js +266 -226
  652. package/out/zero-cache/src/types/subscription.js.map +1 -1
  653. package/out/zero-cache/src/types/url-params.js +30 -39
  654. package/out/zero-cache/src/types/url-params.js.map +1 -1
  655. package/out/zero-cache/src/types/websocket-handoff.js +62 -75
  656. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  657. package/out/zero-cache/src/types/ws.js +43 -53
  658. package/out/zero-cache/src/types/ws.js.map +1 -1
  659. package/out/zero-cache/src/workers/connect-params.js +42 -43
  660. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  661. package/out/zero-cache/src/workers/connection.js +213 -282
  662. package/out/zero-cache/src/workers/connection.js.map +1 -1
  663. package/out/zero-cache/src/workers/mutator.js +22 -21
  664. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  665. package/out/zero-cache/src/workers/replicator.d.ts +7 -0
  666. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  667. package/out/zero-cache/src/workers/replicator.js +92 -97
  668. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  669. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +121 -203
  670. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  671. package/out/zero-cache/src/workers/syncer.js +147 -201
  672. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  673. package/out/zero-client/src/client/active-clients-manager.js +178 -187
  674. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  675. package/out/zero-client/src/client/bindings.js +11 -0
  676. package/out/zero-client/src/client/client-error-kind-enum.js +18 -29
  677. package/out/zero-client/src/client/client-error-kind-enum.js.map +1 -1
  678. package/out/zero-client/src/client/connection-manager.js +291 -346
  679. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  680. package/out/zero-client/src/client/connection-status-enum.js +20 -15
  681. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  682. package/out/zero-client/src/client/connection.js +92 -110
  683. package/out/zero-client/src/client/connection.js.map +1 -1
  684. package/out/zero-client/src/client/context.js +84 -100
  685. package/out/zero-client/src/client/context.js.map +1 -1
  686. package/out/zero-client/src/client/crud-impl.js +56 -88
  687. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  688. package/out/zero-client/src/client/crud.js +127 -129
  689. package/out/zero-client/src/client/crud.js.map +1 -1
  690. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  691. package/out/zero-client/src/client/custom.js +50 -74
  692. package/out/zero-client/src/client/custom.js.map +1 -1
  693. package/out/zero-client/src/client/delete-clients-manager.js +72 -93
  694. package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
  695. package/out/zero-client/src/client/enable-analytics.js +8 -16
  696. package/out/zero-client/src/client/enable-analytics.js.map +1 -1
  697. package/out/zero-client/src/client/error.js +118 -133
  698. package/out/zero-client/src/client/error.js.map +1 -1
  699. package/out/zero-client/src/client/http-string.js +7 -7
  700. package/out/zero-client/src/client/http-string.js.map +1 -1
  701. package/out/zero-client/src/client/inspector/client-group.js +21 -26
  702. package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
  703. package/out/zero-client/src/client/inspector/client.js +23 -26
  704. package/out/zero-client/src/client/inspector/client.js.map +1 -1
  705. package/out/zero-client/src/client/inspector/html-dialog-prompt.js +72 -73
  706. package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
  707. package/out/zero-client/src/client/inspector/inspector.js +46 -51
  708. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  709. package/out/zero-client/src/client/inspector/lazy-inspector.js +132 -192
  710. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  711. package/out/zero-client/src/client/inspector/query.js +72 -77
  712. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  713. package/out/zero-client/src/client/ivm-branch.js +118 -145
  714. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  715. package/out/zero-client/src/client/keys.js +15 -31
  716. package/out/zero-client/src/client/keys.js.map +1 -1
  717. package/out/zero-client/src/client/log-options.js +43 -57
  718. package/out/zero-client/src/client/log-options.js.map +1 -1
  719. package/out/zero-client/src/client/make-mutate-property.js +46 -29
  720. package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
  721. package/out/zero-client/src/client/make-replicache-mutators.js +80 -96
  722. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  723. package/out/zero-client/src/client/metric-name-enum.js +11 -15
  724. package/out/zero-client/src/client/metric-name-enum.js.map +1 -1
  725. package/out/zero-client/src/client/metrics.js +210 -237
  726. package/out/zero-client/src/client/metrics.js.map +1 -1
  727. package/out/zero-client/src/client/mutation-tracker.js +264 -354
  728. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  729. package/out/zero-client/src/client/mutator-proxy.js +122 -151
  730. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  731. package/out/zero-client/src/client/options.js +7 -10
  732. package/out/zero-client/src/client/options.js.map +1 -1
  733. package/out/zero-client/src/client/query-manager.js +305 -373
  734. package/out/zero-client/src/client/query-manager.js.map +1 -1
  735. package/out/zero-client/src/client/reload-error-handler.js +80 -101
  736. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  737. package/out/zero-client/src/client/server-option.js +30 -59
  738. package/out/zero-client/src/client/server-option.js.map +1 -1
  739. package/out/zero-client/src/client/update-needed-reason-type-enum.js +27 -9
  740. package/out/zero-client/src/client/update-needed-reason-type-enum.js.map +1 -1
  741. package/out/zero-client/src/client/version.js +9 -5
  742. package/out/zero-client/src/client/version.js.map +1 -1
  743. package/out/zero-client/src/client/zero-poke-handler.d.ts +1 -1
  744. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  745. package/out/zero-client/src/client/zero-poke-handler.js +205 -293
  746. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  747. package/out/zero-client/src/client/zero-rep.js +61 -68
  748. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  749. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  750. package/out/zero-client/src/client/zero.js +1367 -1834
  751. package/out/zero-client/src/client/zero.js.map +1 -1
  752. package/out/zero-client/src/mod.js +21 -0
  753. package/out/zero-client/src/util/nanoid.js +13 -18
  754. package/out/zero-client/src/util/nanoid.js.map +1 -1
  755. package/out/zero-client/src/util/socket.js +6 -5
  756. package/out/zero-client/src/util/socket.js.map +1 -1
  757. package/out/zero-pg/src/mod.js +10 -0
  758. package/out/zero-protocol/src/analyze-query-result.js +108 -148
  759. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  760. package/out/zero-protocol/src/application-error.js +36 -34
  761. package/out/zero-protocol/src/application-error.js.map +1 -1
  762. package/out/zero-protocol/src/ast.js +236 -309
  763. package/out/zero-protocol/src/ast.js.map +1 -1
  764. package/out/zero-protocol/src/change-desired-queries.js +8 -13
  765. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  766. package/out/zero-protocol/src/client-schema.js +21 -42
  767. package/out/zero-protocol/src/client-schema.js.map +1 -1
  768. package/out/zero-protocol/src/close-connection.js +20 -12
  769. package/out/zero-protocol/src/close-connection.js.map +1 -1
  770. package/out/zero-protocol/src/connect.js +37 -52
  771. package/out/zero-protocol/src/connect.js.map +1 -1
  772. package/out/zero-protocol/src/custom-queries.js +34 -65
  773. package/out/zero-protocol/src/custom-queries.js.map +1 -1
  774. package/out/zero-protocol/src/data.js +6 -9
  775. package/out/zero-protocol/src/data.js.map +1 -1
  776. package/out/zero-protocol/src/delete-clients.js +11 -17
  777. package/out/zero-protocol/src/delete-clients.js.map +1 -1
  778. package/out/zero-protocol/src/down.js +11 -23
  779. package/out/zero-protocol/src/down.js.map +1 -1
  780. package/out/zero-protocol/src/error-kind-enum.js +24 -41
  781. package/out/zero-protocol/src/error-kind-enum.js.map +1 -1
  782. package/out/zero-protocol/src/error-origin-enum.js +8 -9
  783. package/out/zero-protocol/src/error-origin-enum.js.map +1 -1
  784. package/out/zero-protocol/src/error-reason-enum.js +12 -17
  785. package/out/zero-protocol/src/error-reason-enum.js.map +1 -1
  786. package/out/zero-protocol/src/error.js +76 -152
  787. package/out/zero-protocol/src/error.js.map +1 -1
  788. package/out/zero-protocol/src/inspect-down.js +51 -74
  789. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  790. package/out/zero-protocol/src/inspect-up.js +28 -46
  791. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  792. package/out/zero-protocol/src/mutation-id.js +9 -9
  793. package/out/zero-protocol/src/mutation-id.js.map +1 -1
  794. package/out/zero-protocol/src/mutation-type-enum.js +7 -7
  795. package/out/zero-protocol/src/mutation-type-enum.js.map +1 -1
  796. package/out/zero-protocol/src/mutations-patch.js +21 -16
  797. package/out/zero-protocol/src/mutations-patch.js.map +1 -1
  798. package/out/zero-protocol/src/ping.js +8 -9
  799. package/out/zero-protocol/src/ping.js.map +1 -1
  800. package/out/zero-protocol/src/poke.js +53 -59
  801. package/out/zero-protocol/src/poke.js.map +1 -1
  802. package/out/zero-protocol/src/pong.js +8 -9
  803. package/out/zero-protocol/src/pong.js.map +1 -1
  804. package/out/zero-protocol/src/primary-key.js +9 -19
  805. package/out/zero-protocol/src/primary-key.js.map +1 -1
  806. package/out/zero-protocol/src/protocol-version.js +5 -11
  807. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  808. package/out/zero-protocol/src/pull.js +16 -28
  809. package/out/zero-protocol/src/pull.js.map +1 -1
  810. package/out/zero-protocol/src/push.js +162 -209
  811. package/out/zero-protocol/src/push.js.map +1 -1
  812. package/out/zero-protocol/src/queries-patch.js +22 -30
  813. package/out/zero-protocol/src/queries-patch.js.map +1 -1
  814. package/out/zero-protocol/src/query-hash.js +14 -17
  815. package/out/zero-protocol/src/query-hash.js.map +1 -1
  816. package/out/zero-protocol/src/row-patch.js +23 -30
  817. package/out/zero-protocol/src/row-patch.js.map +1 -1
  818. package/out/zero-protocol/src/up.js +11 -22
  819. package/out/zero-protocol/src/up.js.map +1 -1
  820. package/out/zero-protocol/src/update-auth.js +8 -13
  821. package/out/zero-protocol/src/update-auth.js.map +1 -1
  822. package/out/zero-protocol/src/version.js +8 -9
  823. package/out/zero-protocol/src/version.js.map +1 -1
  824. package/out/zero-react/src/bindings.js +12 -0
  825. package/out/zero-react/src/mod.js +5 -0
  826. package/out/zero-react/src/use-connection-state.js +14 -11
  827. package/out/zero-react/src/use-connection-state.js.map +1 -1
  828. package/out/zero-react/src/use-query.js +283 -281
  829. package/out/zero-react/src/use-query.js.map +1 -1
  830. package/out/zero-react/src/use-zero-online.js +17 -11
  831. package/out/zero-react/src/use-zero-online.js.map +1 -1
  832. package/out/zero-react/src/zero-provider.js +53 -69
  833. package/out/zero-react/src/zero-provider.js.map +1 -1
  834. package/out/zero-react/src/zero.js +22 -0
  835. package/out/zero-schema/src/builder/relationship-builder.js +25 -21
  836. package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
  837. package/out/zero-schema/src/builder/schema-builder.js +51 -79
  838. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  839. package/out/zero-schema/src/builder/table-builder.js +99 -116
  840. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  841. package/out/zero-schema/src/compiled-permissions.js +21 -25
  842. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  843. package/out/zero-schema/src/name-mapper.js +31 -47
  844. package/out/zero-schema/src/name-mapper.js.map +1 -1
  845. package/out/zero-schema/src/permissions.js +94 -181
  846. package/out/zero-schema/src/permissions.js.map +1 -1
  847. package/out/zero-schema/src/schema-config.js +26 -32
  848. package/out/zero-schema/src/schema-config.js.map +1 -1
  849. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  850. package/out/zero-server/src/adapters/drizzle.js +79 -76
  851. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  852. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  853. package/out/zero-server/src/adapters/pg.js +79 -55
  854. package/out/zero-server/src/adapters/pg.js.map +1 -1
  855. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  856. package/out/zero-server/src/adapters/postgresjs.js +66 -40
  857. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  858. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
  859. package/out/zero-server/src/adapters/prisma.js +75 -55
  860. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  861. package/out/zero-server/src/custom.d.ts.map +1 -1
  862. package/out/zero-server/src/custom.js +188 -265
  863. package/out/zero-server/src/custom.js.map +1 -1
  864. package/out/zero-server/src/logging.js +6 -5
  865. package/out/zero-server/src/logging.js.map +1 -1
  866. package/out/zero-server/src/mod.js +8 -0
  867. package/out/zero-server/src/pg-query-executor.js +14 -17
  868. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  869. package/out/zero-server/src/process-mutations.js +293 -365
  870. package/out/zero-server/src/process-mutations.js.map +1 -1
  871. package/out/zero-server/src/push-processor.js +33 -49
  872. package/out/zero-server/src/push-processor.js.map +1 -1
  873. package/out/zero-server/src/queries/process-queries.js +106 -96
  874. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  875. package/out/zero-server/src/schema.js +98 -144
  876. package/out/zero-server/src/schema.js.map +1 -1
  877. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  878. package/out/zero-server/src/zql-database.js +54 -69
  879. package/out/zero-server/src/zql-database.js.map +1 -1
  880. package/out/zero-solid/src/bindings.js +12 -0
  881. package/out/zero-solid/src/mod.js +5 -0
  882. package/out/zero-solid/src/solid-view.js +135 -227
  883. package/out/zero-solid/src/solid-view.js.map +1 -1
  884. package/out/zero-solid/src/use-connection-state.js +18 -14
  885. package/out/zero-solid/src/use-connection-state.js.map +1 -1
  886. package/out/zero-solid/src/use-query.js +55 -100
  887. package/out/zero-solid/src/use-query.js.map +1 -1
  888. package/out/zero-solid/src/use-zero-online.js +18 -12
  889. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  890. package/out/zero-solid/src/use-zero.js +65 -77
  891. package/out/zero-solid/src/use-zero.js.map +1 -1
  892. package/out/zero-solid/src/zero.js +22 -0
  893. package/out/zero-types/src/format.js +8 -7
  894. package/out/zero-types/src/format.js.map +1 -1
  895. package/out/zero-types/src/name-mapper.js +34 -47
  896. package/out/zero-types/src/name-mapper.js.map +1 -1
  897. package/out/zql/src/builder/builder.d.ts.map +1 -1
  898. package/out/zql/src/builder/builder.js +315 -476
  899. package/out/zql/src/builder/builder.js.map +1 -1
  900. package/out/zql/src/builder/debug-delegate.js +69 -74
  901. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  902. package/out/zql/src/builder/filter.js +116 -140
  903. package/out/zql/src/builder/filter.js.map +1 -1
  904. package/out/zql/src/builder/like.js +41 -46
  905. package/out/zql/src/builder/like.js.map +1 -1
  906. package/out/zql/src/error.js +10 -9
  907. package/out/zql/src/error.js.map +1 -1
  908. package/out/zql/src/ivm/array-view.js +89 -91
  909. package/out/zql/src/ivm/array-view.js.map +1 -1
  910. package/out/zql/src/ivm/constraint.js +65 -74
  911. package/out/zql/src/ivm/constraint.js.map +1 -1
  912. package/out/zql/src/ivm/data.js +61 -48
  913. package/out/zql/src/ivm/data.js.map +1 -1
  914. package/out/zql/src/ivm/exists.js +164 -213
  915. package/out/zql/src/ivm/exists.js.map +1 -1
  916. package/out/zql/src/ivm/fan-in.js +62 -59
  917. package/out/zql/src/ivm/fan-in.js.map +1 -1
  918. package/out/zql/src/ivm/fan-out.js +52 -61
  919. package/out/zql/src/ivm/fan-out.js.map +1 -1
  920. package/out/zql/src/ivm/filter-operators.js +91 -96
  921. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  922. package/out/zql/src/ivm/filter-push.js +22 -26
  923. package/out/zql/src/ivm/filter-push.js.map +1 -1
  924. package/out/zql/src/ivm/filter.js +41 -35
  925. package/out/zql/src/ivm/filter.js.map +1 -1
  926. package/out/zql/src/ivm/flipped-join.js +282 -391
  927. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  928. package/out/zql/src/ivm/join-utils.js +85 -115
  929. package/out/zql/src/ivm/join-utils.js.map +1 -1
  930. package/out/zql/src/ivm/join.js +162 -231
  931. package/out/zql/src/ivm/join.js.map +1 -1
  932. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +21 -25
  933. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  934. package/out/zql/src/ivm/memory-source.js +364 -503
  935. package/out/zql/src/ivm/memory-source.js.map +1 -1
  936. package/out/zql/src/ivm/memory-storage.js +33 -34
  937. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  938. package/out/zql/src/ivm/operator.js +13 -15
  939. package/out/zql/src/ivm/operator.js.map +1 -1
  940. package/out/zql/src/ivm/push-accumulated.js +267 -270
  941. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  942. package/out/zql/src/ivm/skip.js +91 -104
  943. package/out/zql/src/ivm/skip.js.map +1 -1
  944. package/out/zql/src/ivm/stream.js +10 -10
  945. package/out/zql/src/ivm/stream.js.map +1 -1
  946. package/out/zql/src/ivm/take.js +422 -569
  947. package/out/zql/src/ivm/take.js.map +1 -1
  948. package/out/zql/src/ivm/union-fan-in.js +157 -231
  949. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  950. package/out/zql/src/ivm/union-fan-out.js +38 -43
  951. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  952. package/out/zql/src/ivm/view-apply-change.js +166 -255
  953. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  954. package/out/zql/src/mutate/crud.js +35 -34
  955. package/out/zql/src/mutate/crud.js.map +1 -1
  956. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  957. package/out/zql/src/mutate/custom.js +7 -11
  958. package/out/zql/src/mutate/custom.js.map +1 -1
  959. package/out/zql/src/mutate/mutator-registry.js +67 -71
  960. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  961. package/out/zql/src/mutate/mutator.js +26 -25
  962. package/out/zql/src/mutate/mutator.js.map +1 -1
  963. package/out/zql/src/planner/planner-builder.js +134 -239
  964. package/out/zql/src/planner/planner-builder.js.map +1 -1
  965. package/out/zql/src/planner/planner-connection.js +222 -212
  966. package/out/zql/src/planner/planner-connection.js.map +1 -1
  967. package/out/zql/src/planner/planner-constraint.js +15 -7
  968. package/out/zql/src/planner/planner-constraint.js.map +1 -1
  969. package/out/zql/src/planner/planner-debug.js +199 -224
  970. package/out/zql/src/planner/planner-debug.js.map +1 -1
  971. package/out/zql/src/planner/planner-fan-in.js +146 -162
  972. package/out/zql/src/planner/planner-fan-in.js.map +1 -1
  973. package/out/zql/src/planner/planner-fan-out.js +62 -74
  974. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  975. package/out/zql/src/planner/planner-graph.js +302 -334
  976. package/out/zql/src/planner/planner-graph.js.map +1 -1
  977. package/out/zql/src/planner/planner-join.js +255 -240
  978. package/out/zql/src/planner/planner-join.js.map +1 -1
  979. package/out/zql/src/planner/planner-node.js +10 -6
  980. package/out/zql/src/planner/planner-node.js.map +1 -1
  981. package/out/zql/src/planner/planner-source.js +15 -22
  982. package/out/zql/src/planner/planner-source.js.map +1 -1
  983. package/out/zql/src/planner/planner-terminus.js +28 -28
  984. package/out/zql/src/planner/planner-terminus.js.map +1 -1
  985. package/out/zql/src/query/complete-ordering.js +37 -61
  986. package/out/zql/src/query/complete-ordering.js.map +1 -1
  987. package/out/zql/src/query/create-builder.js +14 -22
  988. package/out/zql/src/query/create-builder.js.map +1 -1
  989. package/out/zql/src/query/error.js +10 -12
  990. package/out/zql/src/query/error.js.map +1 -1
  991. package/out/zql/src/query/escape-like.js +6 -5
  992. package/out/zql/src/query/escape-like.js.map +1 -1
  993. package/out/zql/src/query/expression.js +138 -157
  994. package/out/zql/src/query/expression.js.map +1 -1
  995. package/out/zql/src/query/measure-push-operator.js +35 -38
  996. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  997. package/out/zql/src/query/metrics-delegate.js +7 -7
  998. package/out/zql/src/query/metrics-delegate.js.map +1 -1
  999. package/out/zql/src/query/named.js +52 -51
  1000. package/out/zql/src/query/named.js.map +1 -1
  1001. package/out/zql/src/query/query-delegate-base.js +190 -238
  1002. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  1003. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  1004. package/out/zql/src/query/query-impl.js +271 -405
  1005. package/out/zql/src/query/query-impl.js.map +1 -1
  1006. package/out/zql/src/query/query-internals.js +16 -8
  1007. package/out/zql/src/query/query-internals.js.map +1 -1
  1008. package/out/zql/src/query/query-registry.js +83 -98
  1009. package/out/zql/src/query/query-registry.js.map +1 -1
  1010. package/out/zql/src/query/query.d.ts.map +1 -1
  1011. package/out/zql/src/query/query.js +2 -0
  1012. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  1013. package/out/zql/src/query/runnable-query-impl.js +30 -55
  1014. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  1015. package/out/zql/src/query/static-query.js +7 -14
  1016. package/out/zql/src/query/static-query.js.map +1 -1
  1017. package/out/zql/src/query/ttl.js +45 -67
  1018. package/out/zql/src/query/ttl.js.map +1 -1
  1019. package/out/zql/src/query/validate-input.js +23 -20
  1020. package/out/zql/src/query/validate-input.js.map +1 -1
  1021. package/out/zqlite/src/database-storage.js +99 -103
  1022. package/out/zqlite/src/database-storage.js.map +1 -1
  1023. package/out/zqlite/src/db.js +206 -249
  1024. package/out/zqlite/src/db.js.map +1 -1
  1025. package/out/zqlite/src/explain-queries.js +11 -13
  1026. package/out/zqlite/src/explain-queries.js.map +1 -1
  1027. package/out/zqlite/src/internal/sql-inline.js +54 -37
  1028. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  1029. package/out/zqlite/src/internal/sql.js +17 -15
  1030. package/out/zqlite/src/internal/sql.js.map +1 -1
  1031. package/out/zqlite/src/internal/statement-cache.js +117 -92
  1032. package/out/zqlite/src/internal/statement-cache.js.map +1 -1
  1033. package/out/zqlite/src/mod.js +5 -0
  1034. package/out/zqlite/src/query-builder.js +81 -172
  1035. package/out/zqlite/src/query-builder.js.map +1 -1
  1036. package/out/zqlite/src/query-delegate.js +45 -55
  1037. package/out/zqlite/src/query-delegate.js.map +1 -1
  1038. package/out/zqlite/src/resolve-scalar-subqueries.js +134 -124
  1039. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  1040. package/out/zqlite/src/sqlite-cost-model.js +92 -97
  1041. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  1042. package/out/zqlite/src/sqlite-stat-fanout.js +304 -286
  1043. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  1044. package/out/zqlite/src/table-source.js +281 -455
  1045. package/out/zqlite/src/table-source.js.map +1 -1
  1046. package/package.json +7 -7
  1047. package/out/replicache/src/db/index-operation-enum.js +0 -7
  1048. package/out/replicache/src/db/index-operation-enum.js.map +0 -1
  1049. package/out/replicache/src/db/meta-type-enum.js +0 -7
  1050. package/out/replicache/src/db/meta-type-enum.js.map +0 -1
  1051. package/out/replicache/src/format-version-enum.js +0 -11
  1052. package/out/replicache/src/format-version-enum.js.map +0 -1
  1053. package/out/replicache/src/http-status-unauthorized.js +0 -5
  1054. package/out/replicache/src/http-status-unauthorized.js.map +0 -1
  1055. package/out/replicache/src/invoke-kind-enum.js +0 -7
  1056. package/out/replicache/src/invoke-kind-enum.js.map +0 -1
  1057. package/out/replicache/src/sync/handle-pull-response-result-type-enum.js +0 -9
  1058. package/out/replicache/src/sync/handle-pull-response-result-type-enum.js.map +0 -1
  1059. package/out/zero/package.json.js +0 -9
  1060. package/out/zero/package.json.js.map +0 -1
  1061. package/out/zero/src/adapters/drizzle.js.map +0 -1
  1062. package/out/zero/src/adapters/pg.js.map +0 -1
  1063. package/out/zero/src/adapters/postgresjs.js.map +0 -1
  1064. package/out/zero/src/adapters/prisma.js.map +0 -1
  1065. package/out/zero/src/analyze-query.js.map +0 -1
  1066. package/out/zero/src/ast-to-zql.js.map +0 -1
  1067. package/out/zero/src/bindings.js.map +0 -1
  1068. package/out/zero/src/change-protocol/v0.js.map +0 -1
  1069. package/out/zero/src/cli.js.map +0 -1
  1070. package/out/zero/src/deploy-permissions.js.map +0 -1
  1071. package/out/zero/src/expo-sqlite.js.map +0 -1
  1072. package/out/zero/src/op-sqlite.js.map +0 -1
  1073. package/out/zero/src/pg.js.map +0 -1
  1074. package/out/zero/src/react.js.map +0 -1
  1075. package/out/zero/src/server.js.map +0 -1
  1076. package/out/zero/src/solid.js.map +0 -1
  1077. package/out/zero/src/sqlite.js.map +0 -1
  1078. package/out/zero/src/transform-query.js.map +0 -1
  1079. package/out/zero/src/zero.js.map +0 -1
  1080. package/out/zero/src/zqlite.js.map +0 -1
  1081. package/out/zero-cache/src/db/postgres-replica-identity-enum.js +0 -11
  1082. package/out/zero-cache/src/db/postgres-replica-identity-enum.js.map +0 -1
  1083. package/out/zero-cache/src/db/postgres-type-class-enum.js +0 -17
  1084. package/out/zero-cache/src/db/postgres-type-class-enum.js.map +0 -1
  1085. package/out/zero-cache/src/services/change-streamer/error-type-enum.js +0 -9
  1086. package/out/zero-cache/src/services/change-streamer/error-type-enum.js.map +0 -1
@@ -1,1886 +1,1419 @@
1
- import { LogContext } from "@rocicorp/logger";
2
- import { resolver } from "@rocicorp/resolver";
1
+ import { assert, unreachable } from "../../../shared/src/asserts.js";
2
+ import { getBrowserGlobal, mustGetBrowserGlobal } from "../../../shared/src/browser-env.js";
3
+ import { AbortError } from "../../../shared/src/abort-error.js";
4
+ import { sleep, sleepWithAbort } from "../../../shared/src/sleep.js";
5
+ import { parse } from "../../../shared/src/valita.js";
3
6
  import "../../../replicache/src/deleted-clients.js";
7
+ import { localNavigator } from "../../../shared/src/navigator.js";
4
8
  import { getKVStoreProvider } from "../../../replicache/src/get-kv-store-provider.js";
5
- import { ReplicacheImpl } from "../../../replicache/src/replicache-impl.js";
6
- import { dropDatabase } from "../../../replicache/src/persist/collect-idb-databases.js";
7
9
  import { IDBDatabasesStore } from "../../../replicache/src/persist/idb-databases-store.js";
8
- import { AbortError } from "../../../shared/src/abort-error.js";
9
- import { assert, unreachable } from "../../../shared/src/asserts.js";
10
- import { getBrowserGlobal, mustGetBrowserGlobal } from "../../../shared/src/browser-env.js";
11
- import { getDocumentVisibilityWatcher } from "../../../shared/src/document-visible.js";
10
+ import { dropDatabase } from "../../../replicache/src/persist/collect-idb-databases.js";
12
11
  import { getErrorMessage } from "../../../shared/src/error.js";
13
- import { h64 } from "../../../shared/src/hash.js";
14
12
  import { must } from "../../../shared/src/must.js";
15
- import { navigator as localNavigator } from "../../../shared/src/navigator.js";
13
+ import "../../../zero-protocol/src/error-kind-enum.js";
14
+ import { ProtocolError } from "../../../zero-protocol/src/error.js";
15
+ import { h64 } from "../../../shared/src/hash.js";
16
+ import "../../../zero-protocol/src/client-schema.js";
17
+ import { clientSchemaFrom } from "../../../zero-schema/src/builder/schema-builder.js";
18
+ import { clientToServer } from "../../../zero-schema/src/name-mapper.js";
19
+ import { isMutatorRegistry, iterateMutators } from "../../../zql/src/mutate/mutator-registry.js";
20
+ import { createRunnableBuilder } from "../../../zql/src/query/create-builder.js";
21
+ import "../../../zql/src/query/query.js";
22
+ import { addContextToQuery } from "../../../zql/src/query/query-registry.js";
23
+ import { Closed, Connected, Connecting, Disconnected, Error as Error$1, NeedsAuth } from "./connection-status-enum.js";
24
+ import { getDocumentVisibilityWatcher } from "../../../shared/src/document-visible.js";
25
+ import { ReplicacheImpl } from "../../../replicache/src/replicache-impl.js";
26
+ import "../../../replicache/src/impl.js";
16
27
  import { promiseRace } from "../../../shared/src/promise-race.js";
17
28
  import { emptyFunction } from "../../../shared/src/sentinels.js";
18
- import { sleepWithAbort, sleep } from "../../../shared/src/sleep.js";
19
29
  import { Subscribable } from "../../../shared/src/subscribable.js";
20
- import { parse } from "../../../shared/src/valita.js";
21
- import "../../../zero-protocol/src/client-schema.js";
22
30
  import { encodeSecProtocols } from "../../../zero-protocol/src/connect.js";
23
- import { downstreamSchema } from "../../../zero-protocol/src/down.js";
24
- import { MutationRateLimited, VersionNotSupported, SchemaVersionNotSupported, ClientNotFound, InvalidConnectionRequestLastMutationID, InvalidConnectionRequestBaseCookie } from "../../../zero-protocol/src/error-kind-enum.js";
25
- import { ProtocolError } from "../../../zero-protocol/src/error.js";
26
31
  import { CRUD, Custom } from "../../../zero-protocol/src/mutation-type-enum.js";
27
- import { PROTOCOL_VERSION } from "../../../zero-protocol/src/protocol-version.js";
28
- import { CRUD_MUTATION_NAME, mapCRUD } from "../../../zero-protocol/src/push.js";
32
+ import { mapCRUD } from "../../../zero-protocol/src/push.js";
29
33
  import { nullableVersionSchema } from "../../../zero-protocol/src/version.js";
30
- import { clientSchemaFrom } from "../../../zero-schema/src/builder/schema-builder.js";
31
- import { clientToServer } from "../../../zero-schema/src/name-mapper.js";
32
- import { iterateMutators, isMutatorRegistry } from "../../../zql/src/mutate/mutator-registry.js";
33
- import { createRunnableBuilder } from "../../../zql/src/query/create-builder.js";
34
+ import { downstreamSchema } from "../../../zero-protocol/src/down.js";
35
+ import "../../../zero-protocol/src/protocol-version.js";
34
36
  import { isClientMetric } from "../../../zql/src/query/metrics-delegate.js";
35
- import { addContextToQuery } from "../../../zql/src/query/query-registry.js";
36
- import "../../../zero-protocol/src/ast.js";
37
37
  import { nanoid } from "../util/nanoid.js";
38
38
  import { send } from "../util/socket.js";
39
39
  import { ActiveClientsManager } from "./active-clients-manager.js";
40
- import { Internal, ClientClosed, InvalidMessage, CleanClose, AbruptClose, ConnectTimeout, UnexpectedBaseCookie, NoSocketOrigin, Hidden, PullTimeout, PingTimeout } from "./client-error-kind-enum.js";
40
+ import { AbruptClose, CleanClose, ClientClosed, ConnectTimeout, Hidden, Internal, InvalidMessage, NoSocketOrigin, PingTimeout, PullTimeout, UnexpectedBaseCookie } from "./client-error-kind-enum.js";
41
+ import { ClientError, NO_STATUS_TRANSITION, getBackoffParams, getErrorConnectionTransition, isAuthError, isClientError, isServerError } from "./error.js";
41
42
  import { ConnectionManager, throwIfConnectionError } from "./connection-manager.js";
42
- import { Connected, Connecting, Closed, Disconnected, Error as Error$1, NeedsAuth } from "./connection-status-enum.js";
43
43
  import { ConnectionImpl } from "./connection.js";
44
+ import { IVMSourceBranch } from "./ivm-branch.js";
44
45
  import { ZeroContext } from "./context.js";
45
- import { makeCRUDMutateBatch, addTableCRUDProperties } from "./crud.js";
46
+ import { addTableCRUDProperties, makeCRUDMutateBatch } from "./crud.js";
46
47
  import { DeleteClientsManager } from "./delete-clients-manager.js";
47
48
  import { shouldEnableAnalytics } from "./enable-analytics.js";
48
- import { ClientError, getErrorConnectionTransition, NO_STATUS_TRANSITION, isClientError, isAuthError, isServerError, getBackoffParams } from "./error.js";
49
- import { toWSString, appendPath } from "./http-string.js";
49
+ import { appendPath, toWSString } from "./http-string.js";
50
50
  import { Inspector } from "./inspector/inspector.js";
51
- import { IVMSourceBranch } from "./ivm-branch.js";
51
+ import { version } from "./version.js";
52
52
  import { createLogOptions } from "./log-options.js";
53
53
  import { addCustomMutatorsProperties } from "./make-mutate-property.js";
54
54
  import { makeReplicacheMutators } from "./make-replicache-mutators.js";
55
- import { MetricManager, REPORT_INTERVAL_MS, shouldReportConnectError, getLastConnectErrorValue, DID_NOT_CONNECT_VALUE } from "./metrics.js";
55
+ import { DID_NOT_CONNECT_VALUE, MetricManager, REPORT_INTERVAL_MS, getLastConnectErrorValue, shouldReportConnectError } from "./metrics.js";
56
56
  import { MutationTracker } from "./mutation-tracker.js";
57
57
  import { MutatorProxy } from "./mutator-proxy.js";
58
58
  import { QueryManager } from "./query-manager.js";
59
- import { reportReloadReason, resetBackoff, reloadWithReason, reloadScheduled } from "./reload-error-handler.js";
59
+ import { reloadScheduled, reloadWithReason, reportReloadReason, resetBackoff } from "./reload-error-handler.js";
60
60
  import { getServer } from "./server-option.js";
61
- import { version } from "./version.js";
62
61
  import { PokeHandler } from "./zero-poke-handler.js";
63
62
  import { ZeroRep, fromReplicacheAuthToken, toReplicacheAuthToken } from "./zero-rep.js";
64
- const RUN_LOOP_INTERVAL_MS = 5e3;
65
- const DEFAULT_PING_TIMEOUT_MS = 5e3;
66
- const PULL_TIMEOUT_MS = 5e3;
67
- const DEFAULT_DISCONNECT_HIDDEN_DELAY_MS = 5 * 60 * 1e3;
68
- const DEFAULT_DISCONNECT_TIMEOUT_MS = 60 * 1e3;
69
- const CONNECT_TIMEOUT_MS = 1e4;
70
- const CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY = 6;
71
- const NULL_LAST_MUTATION_ID_SENT = { clientID: "", id: -1 };
72
- const DEFAULT_QUERY_CHANGE_THROTTLE_MS = 10;
63
+ import { resolver } from "@rocicorp/resolver";
64
+ import { LogContext } from "@rocicorp/logger";
65
+ //#region ../zero-client/src/client/zero.ts
66
+ var RUN_LOOP_INTERVAL_MS = 5e3;
67
+ /**
68
+ * Default timeout for ping operations. Controls both:
69
+ * - How long to wait in idle before sending a ping
70
+ * - How long to wait for a pong response
71
+ */
72
+ var DEFAULT_PING_TIMEOUT_MS = 5e3;
73
+ /**
74
+ * The amount of time we wait for a pull response before we consider a pull
75
+ * request timed out.
76
+ */
77
+ var PULL_TIMEOUT_MS = 5e3;
78
+ var DEFAULT_DISCONNECT_HIDDEN_DELAY_MS = 300 * 1e3;
79
+ /**
80
+ * The amount of time we allow for continuous connecting attempts before
81
+ * transitioning to disconnected state.
82
+ */
83
+ var DEFAULT_DISCONNECT_TIMEOUT_MS = 60 * 1e3;
84
+ /**
85
+ * The amount of time we wait for a connection to be established before we
86
+ * consider it timed out.
87
+ */
88
+ var CONNECT_TIMEOUT_MS = 1e4;
89
+ var CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY = 6;
90
+ var NULL_LAST_MUTATION_ID_SENT = {
91
+ clientID: "",
92
+ id: -1
93
+ };
94
+ var DEFAULT_QUERY_CHANGE_THROTTLE_MS = 10;
73
95
  function convertOnUpdateNeededReason(reason) {
74
- return { type: reason.type };
96
+ return { type: reason.type };
75
97
  }
76
98
  function updateNeededReloadReasonMessage(reason) {
77
- const { type } = reason;
78
- let reasonMsg = "";
79
- switch (type) {
80
- case "NewClientGroup":
81
- reasonMsg = "This client could not sync with a newer client. This is probably due to another tab loading a newer incompatible version of the app's code.";
82
- break;
83
- case "VersionNotSupported":
84
- reasonMsg = "The server no longer supports this client's protocol version.";
85
- break;
86
- case "SchemaVersionNotSupported":
87
- reasonMsg = "Client and server schemas incompatible.";
88
- break;
89
- default:
90
- unreachable();
91
- }
92
- if (reason.message) {
93
- reasonMsg += " " + reason.message;
94
- }
95
- return reasonMsg;
99
+ const { type } = reason;
100
+ let reasonMsg = "";
101
+ switch (type) {
102
+ case "NewClientGroup":
103
+ reasonMsg = "This client could not sync with a newer client. This is probably due to another tab loading a newer incompatible version of the app's code.";
104
+ break;
105
+ case "VersionNotSupported":
106
+ reasonMsg = "The server no longer supports this client's protocol version.";
107
+ break;
108
+ case "SchemaVersionNotSupported":
109
+ reasonMsg = "Client and server schemas incompatible.";
110
+ break;
111
+ default: unreachable(type);
112
+ }
113
+ if (reason.message) reasonMsg += " " + reason.message;
114
+ return reasonMsg;
96
115
  }
97
- const serverAheadReloadReason = `Server reported that client is ahead of server. This probably happened because the server is in development mode and restarted. Currently when this happens, the dev server loses its state and on reconnect sees the client as ahead. If you see this in other cases, it may be a bug in Zero.`;
116
+ var serverAheadReloadReason = `Server reported that client is ahead of server. This probably happened because the server is in development mode and restarted. Currently when this happens, the dev server loses its state and on reconnect sees the client as ahead. If you see this in other cases, it may be a bug in Zero.`;
98
117
  function onClientStateNotFoundServerReason(serverErrMsg) {
99
- return `Server could not find state needed to synchronize this client. ${serverErrMsg}`;
100
- }
101
- const ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT = "The local persistent state needed to synchronize this client has been garbage collected.";
102
- const CLOSE_CODE_NORMAL = 1e3;
103
- class Zero {
104
- version = version;
105
- #rep;
106
- #server;
107
- userID;
108
- storageKey;
109
- #lc;
110
- #logOptions;
111
- #enableAnalytics;
112
- #clientSchema;
113
- #pokeHandler;
114
- #queryManager;
115
- #ivmMain;
116
- #clientToServer;
117
- #deleteClientsManager;
118
- #mutationTracker;
119
- /**
120
- * The queries we sent when inside the sec-protocol header when establishing a connection.
121
- * More queries could be registered while we're waiting for the 'connected' message
122
- * to come back from the server. To understand what queries we need to send
123
- * to the server, we diff the `initConnectionQueries` with the current set of desired queries.
124
- *
125
- * If this is set to `undefined` that means no queries were sent inside the `sec-protocol` header
126
- * and an `initConnection` message must be sent to the server after receiving the `connected` message.
127
- */
128
- #initConnectionQueries;
129
- /**
130
- * We try to send the deleted clients and (client groups) as part of the
131
- * sec-protocol header. If we can't because the header would get too large we
132
- * keep track of the deleted clients and send them after the connection is
133
- * established.
134
- */
135
- #deletedClients;
136
- #lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
137
- #onPong = () => void 0;
138
- #onlineManager;
139
- #onUpdateNeeded;
140
- #onClientStateNotFound;
141
- // Last cookie used to initiate a connection
142
- #connectCookie = null;
143
- // Total number of sockets successfully connected by this client
144
- #connectedCount = 0;
145
- // Number of messages received over currently connected socket. Reset
146
- // on disconnect.
147
- #messageCount = 0;
148
- #connectedAt = 0;
149
- // Reset on successful connection.
150
- #connectErrorCount = 0;
151
- #abortPingTimeout = () => {
152
- };
153
- #forceEnableRefresh = false;
154
- /**
155
- * The timeout in milliseconds for ping operations. Controls both:
156
- * - How long to wait in idle before sending a ping
157
- * - How long to wait for a pong response
158
- *
159
- * Total time to detect a dead connection is 2 × pingTimeoutMs.
160
- *
161
- * The new value will take effect on the next ping cycle.
162
- */
163
- pingTimeoutMs;
164
- #zeroContext;
165
- #pendingPullsByRequestID = /* @__PURE__ */ new Map();
166
- #lastMutationIDReceived = 0;
167
- #socket = void 0;
168
- #socketResolver = resolver();
169
- /**
170
- * Utility promise that resolves when the socket transitions to connected.
171
- * It rejects if we hit an error or timeout before the connected message.
172
- * Used by push/pull helpers to queue work until the connection is usable.
173
- */
174
- #connectResolver = resolver();
175
- #closeAbortController = new AbortController();
176
- #visibilityWatcher;
177
- #connectionManager;
178
- #connection;
179
- #activeClientsManager;
180
- #inspector;
181
- #connectStart = void 0;
182
- // Set on connect attempt if currently undefined.
183
- // Reset to undefined when
184
- // 1. client stops trying to connect because it is hidden
185
- // 2. client encounters a connect error and canary request indicates
186
- // the client is offline
187
- // 2. client successfully connects
188
- #totalToConnectStart = void 0;
189
- #options;
190
- #kvStore;
191
- /**
192
- * Query builders for each table in the schema.
193
- *
194
- * @deprecated Use {@linkcode createBuilder} to create query builders instead.
195
- */
196
- query;
197
- // TODO: Metrics needs to be rethought entirely as we're not going to
198
- // send metrics to customer server.
199
- #metrics;
200
- // Store as field to allow test subclass to override. Web API doesn't allow
201
- // overwriting location fields for security reasons.
202
- #reload = () => getBrowserGlobal("location")?.reload();
203
- /**
204
- * Constructs a new Zero client.
205
- */
206
- constructor(options) {
207
- const {
208
- userID,
209
- storageKey,
210
- onOnlineChange,
211
- onUpdateNeeded,
212
- onClientStateNotFound,
213
- hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS,
214
- pingTimeoutMs = DEFAULT_PING_TIMEOUT_MS,
215
- disconnectTimeoutMs = DEFAULT_DISCONNECT_TIMEOUT_MS,
216
- schema,
217
- batchViewUpdates = (applyViewUpdates) => applyViewUpdates(),
218
- maxRecentQueries = 0,
219
- slowMaterializeThreshold = 5e3
220
- } = options;
221
- if (!userID) {
222
- throw new ClientError({
223
- kind: Internal,
224
- message: "ZeroOptions.userID must not be empty."
225
- });
226
- }
227
- const cacheURL = options.cacheURL ?? options.server;
228
- const server = getServer(cacheURL);
229
- this.#enableAnalytics = shouldEnableAnalytics(
230
- server,
231
- false
232
- // Reenable analytics
233
- );
234
- let { kvStore = "idb" } = options;
235
- if (kvStore === "idb") {
236
- if (!getBrowserGlobal("indexedDB")) {
237
- console.warn(
238
- "IndexedDB is not supported in this environment. Falling back to memory storage."
239
- );
240
- kvStore = "mem";
241
- }
242
- }
243
- if (hiddenTabDisconnectDelay < 0) {
244
- throw new ClientError({
245
- kind: Internal,
246
- message: "ZeroOptions.hiddenTabDisconnectDelay must not be negative."
247
- });
248
- }
249
- this.#kvStore = kvStore;
250
- this.pingTimeoutMs = pingTimeoutMs;
251
- this.#onlineManager = new OnlineManager();
252
- if (onOnlineChange) {
253
- this.#onlineManager.subscribe(onOnlineChange);
254
- }
255
- this.#options = options;
256
- this.#logOptions = this.#createLogOptions({
257
- consoleLogLevel: options.logLevel ?? "warn",
258
- server: null,
259
- //server, // Reenable remote logging
260
- enableAnalytics: this.#enableAnalytics
261
- });
262
- const logOptions = this.#logOptions;
263
- this.#connectionManager = new ConnectionManager({
264
- disconnectTimeout: disconnectTimeoutMs
265
- });
266
- const syncConnectionState = (state) => {
267
- this.#onlineManager.setOnline(state.name === Connected);
268
- if (state.name === Closed) {
269
- this.#queryManager.handleClosed(state.reason);
270
- }
271
- };
272
- syncConnectionState(this.#connectionManager.state);
273
- this.#connectionManager.subscribe(syncConnectionState);
274
- const sink = logOptions.logSink;
275
- const lc = new LogContext(logOptions.logLevel, {}, sink);
276
- this.#mutationTracker = new MutationTracker(
277
- lc,
278
- (upTo) => this.#send(["ackMutationResponses", upTo]),
279
- (error) => this.#disconnect(lc, error)
280
- );
281
- this.#ivmMain = new IVMSourceBranch(schema.tables);
282
- const { enableLegacyQueries = false } = schema;
283
- const replicacheMutators = makeReplicacheMutators(
284
- schema,
285
- options.mutators,
286
- this.context,
287
- lc
288
- );
289
- this.storageKey = storageKey ?? "";
290
- const { clientSchema, hash } = clientSchemaFrom(schema);
291
- this.#clientSchema = clientSchema;
292
- const nameKey = JSON.stringify({
293
- storageKey: this.storageKey,
294
- mutateUrl: options.mutateURL ?? "",
295
- queryUrl: options.queryURL ?? options.getQueriesURL ?? ""
296
- });
297
- const hashedKey = h64(nameKey).toString(36);
298
- const replicacheOptions = {
299
- // The schema stored in IDB is dependent upon both the ClientSchema
300
- // and the AST schema (i.e. PROTOCOL_VERSION).
301
- schemaVersion: `${PROTOCOL_VERSION}.${hash}`,
302
- logLevel: logOptions.logLevel,
303
- logSinks: [logOptions.logSink],
304
- mutators: replicacheMutators,
305
- name: `zero-${userID}-${hashedKey}`,
306
- pusher: (req, reqID) => this.#pusher(req, reqID),
307
- puller: (req, reqID) => this.#puller(req, reqID),
308
- pushDelay: 0,
309
- requestOptions: {
310
- maxDelayMs: 0,
311
- minDelayMs: 0
312
- },
313
- licenseKey: "zero-client-static-key",
314
- kvStore
315
- };
316
- this.#zeroContext = new ZeroContext(
317
- lc,
318
- this.#ivmMain,
319
- (ast, ttl, gotCallback) => {
320
- if (enableLegacyQueries) {
321
- return this.#queryManager.addLegacy(ast, ttl, gotCallback);
322
- }
323
- return emptyFunction;
324
- },
325
- (ast, customQueryID, ttl, gotCallback) => this.#queryManager.addCustom(ast, customQueryID, ttl, gotCallback),
326
- (ast, ttl) => {
327
- if (enableLegacyQueries) {
328
- this.#queryManager.updateLegacy(ast, ttl);
329
- }
330
- },
331
- (customQueryID, ttl) => this.#queryManager.updateCustom(customQueryID, ttl),
332
- () => this.#queryManager.flushBatch(),
333
- batchViewUpdates,
334
- this.#addMetric,
335
- assertValidRunOptions
336
- );
337
- this.query = createRunnableBuilder(this.#zeroContext, schema);
338
- const replicacheImplOptions = {
339
- enableClientGroupForking: false,
340
- enableMutationRecovery: false,
341
- enablePullAndPushInOpen: false,
342
- // Zero calls push in its connection management code
343
- enableRefresh: () => this.#enableRefresh(),
344
- onClientsDeleted: (deletedClients) => this.#deleteClientsManager.onClientsDeleted(deletedClients),
345
- zero: new ZeroRep(
346
- this.#zeroContext,
347
- this.#ivmMain,
348
- options.mutators !== void 0,
349
- this.#mutationTracker
350
- )
351
- };
352
- const rep = new ReplicacheImpl(replicacheOptions, replicacheImplOptions);
353
- this.#rep = rep;
354
- this.#server = server;
355
- this.userID = userID;
356
- this.#lc = lc.withContext("clientID", rep.clientID);
357
- this.#connection = new ConnectionImpl(
358
- this.#connectionManager,
359
- this.#lc,
360
- (auth) => this.#setAuth(auth)
361
- );
362
- this.#mutationTracker.setClientIDAndWatch(
363
- rep.clientID,
364
- rep.experimentalWatch.bind(rep)
365
- );
366
- this.#activeClientsManager = makeActiveClientsManager(
367
- rep.clientGroupID,
368
- this.clientID,
369
- this.#closeAbortController.signal,
370
- (clientID, clientGroupID) => this.#deleteClientsManager.onClientsDeleted([
371
- { clientGroupID, clientID }
372
- ])
373
- );
374
- const onUpdateNeededCallback = (reason) => {
375
- if (onUpdateNeeded) {
376
- onUpdateNeeded(reason);
377
- } else {
378
- reloadWithReason(
379
- this.#lc,
380
- this.#reload,
381
- reason.type,
382
- updateNeededReloadReasonMessage(reason)
383
- );
384
- }
385
- };
386
- this.#onUpdateNeeded = onUpdateNeededCallback;
387
- this.#rep.onUpdateNeeded = (reason) => {
388
- onUpdateNeededCallback(convertOnUpdateNeededReason(reason));
389
- };
390
- const onClientStateNotFoundCallback = onClientStateNotFound ?? ((reason) => {
391
- reloadWithReason(
392
- this.#lc,
393
- this.#reload,
394
- ClientNotFound,
395
- reason ?? ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT
396
- );
397
- });
398
- this.#onClientStateNotFound = onClientStateNotFoundCallback;
399
- this.#rep.onClientStateNotFound = onClientStateNotFoundCallback;
400
- const mutatorProxy = new MutatorProxy(
401
- this.#lc,
402
- this.#connectionManager,
403
- this.#mutationTracker
404
- );
405
- const { mutators } = options;
406
- const registeredMutators = new Set(
407
- isMutatorRegistry(mutators) ? iterateMutators(mutators) : void 0
408
- );
409
- const callableMutate = (mr) => {
410
- if (!registeredMutators.has(mr.mutator)) {
411
- throw new Error(
412
- `Mutator "${mr.mutator.mutatorName}" is not registered. Mutators must be registered with the Zero constructor before use.`
413
- );
414
- }
415
- const repMutator = rep.mutate[mr.mutator.mutatorName];
416
- return mutatorProxy.wrapCustomMutator(
417
- mr.mutator.mutatorName,
418
- repMutator
419
- )(mr.args);
420
- };
421
- const mutateBatch = makeCRUDMutateBatch(schema, rep.mutate);
422
- if (schema.enableLegacyMutators) {
423
- addTableCRUDProperties(schema, callableMutate, rep.mutate);
424
- }
425
- if (mutators && !isMutatorRegistry(mutators)) {
426
- addCustomMutatorsProperties(
427
- mutators,
428
- mutatorProxy,
429
- callableMutate,
430
- rep.mutate
431
- );
432
- }
433
- this.mutate = callableMutate;
434
- this.mutateBatch = mutateBatch;
435
- this.#queryManager = new QueryManager(
436
- this.#lc,
437
- this.#mutationTracker,
438
- rep.clientID,
439
- schema.tables,
440
- (msg) => this.#send(msg),
441
- rep.experimentalWatch.bind(rep),
442
- maxRecentQueries,
443
- options.queryChangeThrottleMs ?? DEFAULT_QUERY_CHANGE_THROTTLE_MS,
444
- slowMaterializeThreshold,
445
- (error) => {
446
- this.#disconnect(lc, error);
447
- }
448
- );
449
- this.#clientToServer = clientToServer(schema.tables);
450
- this.#deleteClientsManager = new DeleteClientsManager(
451
- (msg) => this.#send(msg),
452
- rep.perdag,
453
- this.#lc,
454
- this.#rep.clientGroupID,
455
- rep.clientID
456
- );
457
- reportReloadReason(this.#lc);
458
- this.#metrics = new MetricManager({
459
- reportIntervalMs: REPORT_INTERVAL_MS,
460
- host: getBrowserGlobal("location")?.host ?? "",
461
- source: "client",
462
- reporter: this.#enableAnalytics ? (allSeries) => this.#reportMetrics(allSeries) : () => Promise.resolve(),
463
- lc: this.#lc
464
- });
465
- this.#metrics.tags.push(`version:${this.version}`);
466
- this.#pokeHandler = new PokeHandler(
467
- (poke) => this.#rep.poke(poke),
468
- () => this.#onPokeError(),
469
- rep.clientID,
470
- schema,
471
- this.#lc,
472
- this.#mutationTracker
473
- );
474
- this.#visibilityWatcher = getDocumentVisibilityWatcher(
475
- getBrowserGlobal("document"),
476
- hiddenTabDisconnectDelay,
477
- this.#closeAbortController.signal
478
- );
479
- void this.#runLoop();
480
- this.#expose();
481
- }
482
- #enableRefresh() {
483
- return this.#forceEnableRefresh || !this.#connectionManager.is(Connected) && !this.#connectionManager.is(Connecting);
484
- }
485
- #expose() {
486
- const g = globalThis;
487
- if (g.__zero === void 0) {
488
- g.__zero = this;
489
- } else if (g.__zero instanceof Zero) {
490
- const prev = g.__zero;
491
- g.__zero = {
492
- [prev.clientID]: prev,
493
- [this.clientID]: this
494
- };
495
- } else {
496
- g.__zero[this.clientID] = this;
497
- }
498
- }
499
- #unexpose() {
500
- const g = globalThis;
501
- assert(g.__zero !== void 0, "No global zero instance found");
502
- if (g.__zero instanceof Zero) {
503
- assert(
504
- g.__zero === this,
505
- "Global zero instance does not match this instance"
506
- );
507
- delete g.__zero;
508
- } else {
509
- delete g.__zero[this.clientID];
510
- if (Object.entries(g.__zero).length === 1) {
511
- g.__zero = Object.values(g.__zero)[0];
512
- }
513
- }
514
- }
515
- #send(msg) {
516
- if (this.#socket && this.#connectionManager.is(Connected)) {
517
- send(this.#socket, msg);
518
- }
519
- }
520
- #createLogOptions(options) {
521
- return createLogOptions(options);
522
- }
523
- /**
524
- * Preloads data for a query into the cache, without keeping it in memory.
525
- *
526
- * This function is useful when you want to populate the cache ahead of time,
527
- * for example after login, to avoid a flash of loading screen on the next page.
528
- *
529
- * Returns an object with two properties:
530
- * - `complete`: a Promise that resolves when the data is loaded
531
- * - `cleanup`: a function that can be called to cancel the preload
532
- *
533
- * @example
534
- * ```ts
535
- * const {complete, cleanup} = zero.preload(userQuery);
536
- * await complete;
537
- * // Now the data is cached and can be used immediately
538
- * ```
539
- */
540
- preload(query, options) {
541
- return this.#zeroContext.preload(
542
- addContextToQuery(query, this.context),
543
- options
544
- );
545
- }
546
- /**
547
- * Executes a query once and returns the results.
548
- *
549
- * By default, waits for any pending data to sync before running the query.
550
- * This ensures fresh results from the server. Use `{type: 'unknown'}` to
551
- * run immediately with whatever data is available locally.
552
- *
553
- * @param query - The query to execute
554
- * @param runOptions - Options controlling query execution
555
- * @returns A Promise resolving to the query results
556
- *
557
- * @example
558
- * ```ts
559
- * // Wait for server sync
560
- * const users = await zero.run(userQuery);
561
- *
562
- * // Run with local data only
563
- * const cachedUsers = await zero.run(userQuery, {type: 'unknown'});
564
- * ```
565
- */
566
- run(query, runOptions) {
567
- return this.#zeroContext.run(
568
- addContextToQuery(query, this.context),
569
- runOptions
570
- );
571
- }
572
- get context() {
573
- return this.#options.context;
574
- }
575
- materialize(query, factoryOrOptions, maybeOptions) {
576
- const q = addContextToQuery(query, this.context);
577
- let factory;
578
- let options;
579
- if (typeof factoryOrOptions === "function") {
580
- factory = factoryOrOptions;
581
- options = maybeOptions;
582
- } else {
583
- options = factoryOrOptions;
584
- }
585
- return this.#zeroContext.materialize(q, factory, options);
586
- }
587
- /**
588
- * The server URL that this Zero instance is configured with.
589
- */
590
- get server() {
591
- return this.#server;
592
- }
593
- /**
594
- * The name of the IndexedDB database in which the data of this
595
- * instance of Zero is stored.
596
- */
597
- get idbName() {
598
- return this.#rep.idbName;
599
- }
600
- /**
601
- * The schema version of the data understood by this application.
602
- * See [[ZeroOptions.schemaVersion]].
603
- */
604
- get schemaVersion() {
605
- return this.#rep.schemaVersion;
606
- }
607
- /**
608
- * The schema passed into Zero when it was constructed.
609
- *
610
- * This can be paired with the inspector API to explore the client cache for
611
- * debugging or tooling. The inspector exposes the raw key/value map as well
612
- * as the per-table rows that back `zero.query[tableName].run()`.
613
- *
614
- * ```ts
615
- * const inspector = __zero.inspector;
616
- * const client = inspector.client;
617
- *
618
- * console.log('client map:', await client.map());
619
- *
620
- * for (const tableName of Object.keys(__zero.schema.tables)) {
621
- * console.table(await client.rows(tableName));
622
- * }
623
- * ```
624
- */
625
- get schema() {
626
- return this.#options.schema;
627
- }
628
- /**
629
- * The client ID for this instance of Zero. Each instance
630
- * gets a unique client ID.
631
- */
632
- get clientID() {
633
- return this.#rep.clientID;
634
- }
635
- get clientGroupID() {
636
- return this.#rep.clientGroupID;
637
- }
638
- /**
639
- * Use to execute mutations. The primary flow is to call
640
- * `zero.mutate(mutationRequest)` with your registered custom mutators:
641
- *
642
- * ```ts
643
- * await zero.mutate(
644
- * mutators.myMutator({id: '1', title: 'First issue'}),
645
- * );
646
- * ```
647
- *
648
- * When `schema.enableLegacyMutators` is true, legacy conveniences are added:
649
- * - Table-scoped CRUD helpers, e.g. `zero.mutate.issue.create` / `set` / `update` / `delete`
650
- * - Your custom mutators exposed directly on `zero.mutate`
651
- *
652
- * ```ts
653
- * await zero.mutate.issue.create({id: '1', title: 'First issue', priority: 'high'});
654
- * await zero.mutate.comment.create({id: '1', text: 'First comment', issueID: '1'});
655
- * await zero.mutate.myMutator({id: '1', title: 'First issue'});
656
- * ```
657
- *
658
- * The `update` methods support partials. Unspecified or `undefined` fields
659
- * are left unchanged:
660
- *
661
- * ```ts
662
- * // Priority left unchanged.
663
- * await zero.mutate.issue.update({id: '1', title: 'Updated title'});
664
- * ```
665
- */
666
- mutate;
667
- /**
668
- * Provides a way to batch multiple CRUD mutations together:
669
- *
670
- * ```ts
671
- * await zero.mutateBatch(m => {
672
- * await m.issue.create({id: '1', title: 'First issue'});
673
- * await m.comment.create({id: '1', text: 'First comment', issueID: '1'});
674
- * });
675
- * ```
676
- *
677
- * Batch sends all mutations in a single transaction. If one fails, all are
678
- * rolled back together. Batch can also be more efficient than making many
679
- * individual mutations.
680
- *
681
- * `mutateBatch` is not allowed inside another `mutateBatch` call. Doing so
682
- * will throw an error.
683
- *
684
- * @deprecated Use `zero.mutate(mutationRequest)`
685
- */
686
- mutateBatch;
687
- /**
688
- * The connection API for managing Zero's connection lifecycle.
689
- *
690
- * Use this to monitor connection state and manually control connections.
691
- *
692
- * @example
693
- * ```ts
694
- * // Subscribe to connection state changes
695
- * z.connection.state.subscribe(state => {
696
- * console.log('Connection state:', state.name);
697
- * });
698
- *
699
- * // Manually resume connection from error state
700
- * await z.connection.connect();
701
- * ```
702
- */
703
- get connection() {
704
- return this.#connection;
705
- }
706
- /**
707
- * Whether this Zero instance has been closed.
708
- *
709
- * Once a Zero instance has been closed it no longer syncs, you can no
710
- * longer query or mutate data with it, and its query views stop updating.
711
- */
712
- get closed() {
713
- return this.#connectionManager.is(Closed);
714
- }
715
- /**
716
- * Closes this Zero instance.
717
- *
718
- * Once a Zero instance has been closed it no longer syncs, you can no
719
- * longer query or mutate data with it, and its query views stop updating.
720
- */
721
- async close() {
722
- const lc = this.#lc.withContext("close");
723
- try {
724
- if (this.closed) {
725
- lc.debug?.("close() called on already closed instance");
726
- return;
727
- }
728
- lc.debug?.("Closing Zero instance. Stack:", new Error().stack);
729
- this.#onlineManager.cleanup();
730
- if (!this.#connectionManager.is(Disconnected)) {
731
- this.#disconnect(
732
- lc,
733
- new ClientError({
734
- kind: ClientClosed,
735
- message: "Zero instance closed by user"
736
- }),
737
- CLOSE_CODE_NORMAL
738
- );
739
- }
740
- lc.debug?.("Aborting closeAbortController due to close()");
741
- this.#closeAbortController.abort();
742
- this.#metrics.stop();
743
- const ret = await this.#rep.close();
744
- this.#unexpose();
745
- return ret;
746
- } catch (e) {
747
- lc.error?.("Error closing Zero instance", e);
748
- throw e;
749
- } finally {
750
- this.#connectionManager.closed();
751
- }
752
- }
753
- #onMessage = (e) => {
754
- const lc = this.#lc;
755
- lc.debug?.("received message", e.data);
756
- if (this.closed) {
757
- lc.debug?.("ignoring message because already closed");
758
- return;
759
- }
760
- let downMessage;
761
- const { data } = e;
762
- try {
763
- downMessage = parse(
764
- JSON.parse(data),
765
- downstreamSchema,
766
- "passthrough"
767
- );
768
- } catch (e2) {
769
- const invalidMessageError = new ClientError(
770
- {
771
- kind: InvalidMessage,
772
- message: `Invalid message received from server: ${getErrorMessage(e2)}${data}`
773
- },
774
- { cause: e2 }
775
- );
776
- this.#disconnect(lc, invalidMessageError);
777
- return;
778
- }
779
- this.#messageCount++;
780
- const msgType = downMessage[0];
781
- try {
782
- switch (msgType) {
783
- case "connected":
784
- return this.#handleConnectedMessage(lc, downMessage);
785
- case "error":
786
- return this.#handleErrorMessage(lc, downMessage);
787
- case "pong":
788
- resetBackoff();
789
- return this.#onPong();
790
- case "pokeStart":
791
- return this.#handlePokeStart(lc, downMessage);
792
- case "pokePart":
793
- if (downMessage[1].rowsPatch) {
794
- resetBackoff();
795
- }
796
- return this.#handlePokePart(lc, downMessage);
797
- case "pokeEnd":
798
- return this.#handlePokeEnd(lc, downMessage);
799
- case "pull":
800
- return this.#handlePullResponse(lc, downMessage);
801
- case "deleteClients":
802
- return this.#deleteClientsManager.clientsDeletedOnServer(
803
- downMessage[1]
804
- );
805
- case "pushResponse":
806
- return this.#mutationTracker.processPushResponse(downMessage[1]);
807
- case "transformError":
808
- this.#queryManager.handleTransformErrors(downMessage[1]);
809
- break;
810
- case "inspect":
811
- break;
812
- default:
813
- unreachable(msgType);
814
- }
815
- } catch (e2) {
816
- lc.error?.("Unhandled error in onOpen", e2);
817
- this.#disconnect(
818
- lc,
819
- new ClientError(
820
- {
821
- kind: Internal,
822
- message: getErrorMessage(e2)
823
- },
824
- { cause: e2 }
825
- )
826
- );
827
- return;
828
- }
829
- };
830
- #onOpen = () => {
831
- let lc = this.#lc;
832
- try {
833
- assert(this.#socket, "Socket is not set before onOpen");
834
- lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);
835
- if (this.#connectStart === void 0) {
836
- throw new Error("Got open event but connect start time is undefined.");
837
- } else {
838
- const now = Date.now();
839
- const timeToOpenMs = now - this.#connectStart;
840
- lc.info?.("Got socket open event", {
841
- navigatorOnline: localNavigator?.onLine,
842
- timeToOpenMs
843
- });
844
- }
845
- } catch (e) {
846
- lc.error?.("Unhandled error in onOpen", e);
847
- this.#disconnect(
848
- lc,
849
- new ClientError(
850
- {
851
- kind: Internal,
852
- message: getErrorMessage(e)
853
- },
854
- { cause: e }
855
- )
856
- );
857
- }
858
- };
859
- #onClose = (e) => {
860
- let lc = this.#lc;
861
- try {
862
- assert(this.#socket, "Socket is not set before onClose");
863
- lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);
864
- const { code, reason, wasClean } = e;
865
- if (code <= 1001 || code === 1006) {
866
- lc.info?.("Got socket close event", { code, reason, wasClean });
867
- } else {
868
- lc.error?.("Got unexpected socket close event", {
869
- code,
870
- reason,
871
- wasClean
872
- });
873
- }
874
- const closeError = new ClientError(
875
- wasClean ? {
876
- kind: CleanClose,
877
- message: "WebSocket connection closed cleanly"
878
- } : {
879
- kind: AbruptClose,
880
- message: "WebSocket connection closed abruptly"
881
- }
882
- );
883
- this.#connectResolver.reject(closeError);
884
- this.#disconnect(lc, closeError);
885
- } catch (e2) {
886
- lc.error?.("Unhandled error in onClose", e2);
887
- const internalError = new ClientError(
888
- {
889
- kind: Internal,
890
- message: getErrorMessage(e2)
891
- },
892
- { cause: e2 }
893
- );
894
- this.#connectResolver.reject(internalError);
895
- this.#disconnect(lc, internalError);
896
- }
897
- };
898
- // An error on the connection is fatal for the connection.
899
- async #handleErrorMessage(lc, downMessage) {
900
- const [, { kind, message }] = downMessage;
901
- if (kind === MutationRateLimited) {
902
- this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
903
- lc.error?.(kind, "Mutation rate limited", { message });
904
- return;
905
- }
906
- lc.info?.(`${kind}: ${message}}`);
907
- const error = new ProtocolError(downMessage[1]);
908
- lc.error?.(`${error.kind}:
909
-
910
- ${error.errorBody.message}`, error);
911
- lc.debug?.("Rejecting connect resolver due to error", error);
912
- this.#connectResolver.reject(error);
913
- this.#disconnect(lc, error);
914
- if (kind === VersionNotSupported) {
915
- this.#onUpdateNeeded({ type: kind, message });
916
- } else if (kind === SchemaVersionNotSupported) {
917
- await this.#rep.disableClientGroup();
918
- this.#onUpdateNeeded({
919
- type: "SchemaVersionNotSupported",
920
- message
921
- });
922
- } else if (kind === ClientNotFound) {
923
- await this.#rep.disableClientGroup();
924
- this.#onClientStateNotFound?.(onClientStateNotFoundServerReason(message));
925
- } else if (kind === InvalidConnectionRequestLastMutationID || kind === InvalidConnectionRequestBaseCookie) {
926
- await dropDatabase(this.#rep.idbName, {
927
- kvStore: this.#kvStore
928
- });
929
- reloadWithReason(lc, this.#reload, kind, serverAheadReloadReason);
930
- }
931
- }
932
- async #handleConnectedMessage(lc, connectedMessage) {
933
- const now = Date.now();
934
- const [, connectBody] = connectedMessage;
935
- lc = addWebSocketIDToLogContext(connectBody.wsid, lc);
936
- if (this.#connectedCount === 0) {
937
- this.#checkConnectivity("firstConnect");
938
- } else if (this.#connectErrorCount > 0) {
939
- this.#checkConnectivity("connectAfterError");
940
- }
941
- this.#connectedCount++;
942
- this.#connectedAt = now;
943
- this.#metrics.lastConnectError.clear();
944
- const proceedingConnectErrorCount = this.#connectErrorCount;
945
- this.#connectErrorCount = 0;
946
- let timeToConnectMs;
947
- let connectMsgLatencyMs;
948
- if (this.#connectStart === void 0) {
949
- lc.error?.("Got connected message but connect start time is undefined.");
950
- } else {
951
- timeToConnectMs = now - this.#connectStart;
952
- this.#metrics.timeToConnectMs.set(timeToConnectMs);
953
- connectMsgLatencyMs = connectBody.timestamp !== void 0 ? now - connectBody.timestamp : void 0;
954
- this.#connectStart = void 0;
955
- }
956
- let totalTimeToConnectMs;
957
- if (this.#totalToConnectStart === void 0) {
958
- lc.error?.(
959
- "Got connected message but total to connect start time is undefined."
960
- );
961
- } else {
962
- totalTimeToConnectMs = now - this.#totalToConnectStart;
963
- this.#totalToConnectStart = void 0;
964
- }
965
- this.#metrics.setConnected(timeToConnectMs ?? 0, totalTimeToConnectMs ?? 0);
966
- lc.info?.("Connected", {
967
- navigatorOnline: localNavigator?.onLine,
968
- timeToConnectMs,
969
- totalTimeToConnectMs,
970
- connectMsgLatencyMs,
971
- connectedCount: this.#connectedCount,
972
- proceedingConnectErrorCount
973
- });
974
- this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
975
- lc.debug?.("Resolving connect resolver");
976
- const socket = must(this.#socket);
977
- const queriesPatch = await this.#rep.query(
978
- (tx) => this.#queryManager.getQueriesPatch(tx, this.#initConnectionQueries)
979
- );
980
- const hasDeletedClients = () => skipEmptyArray(this.#deletedClients?.clientIDs) || skipEmptyArray(this.#deletedClients?.clientGroupIDs);
981
- const maybeSendDeletedClients = () => {
982
- if (hasDeletedClients()) {
983
- send(socket, ["deleteClients", this.#deletedClients]);
984
- this.#deletedClients = void 0;
985
- }
986
- };
987
- if (queriesPatch.size > 0 && this.#initConnectionQueries !== void 0) {
988
- maybeSendDeletedClients();
989
- send(socket, [
990
- "changeDesiredQueries",
991
- {
992
- desiredQueriesPatch: [...queriesPatch.values()]
993
- }
994
- ]);
995
- } else if (this.#initConnectionQueries === void 0) {
996
- const clientSchema = this.#clientSchema;
997
- send(socket, [
998
- "initConnection",
999
- {
1000
- desiredQueriesPatch: [...queriesPatch.values()],
1001
- deleted: skipEmptyDeletedClients(this.#deletedClients),
1002
- // The clientSchema only needs to be sent for the very first request.
1003
- // Henceforth it is stored with the CVR and verified automatically.
1004
- ...this.#connectCookie === null ? { clientSchema } : {},
1005
- userPushURL: this.#options.mutateURL,
1006
- userPushHeaders: this.#options.mutateHeaders,
1007
- userQueryURL: this.#options.queryURL ?? this.#options.getQueriesURL,
1008
- userQueryHeaders: this.#options.queryHeaders
1009
- }
1010
- ]);
1011
- this.#deletedClients = void 0;
1012
- }
1013
- this.#initConnectionQueries = void 0;
1014
- maybeSendDeletedClients();
1015
- this.#connectionManager.connected();
1016
- this.#connectResolver.resolve();
1017
- }
1018
- /**
1019
- * Starts a new connection. This will create the WebSocket that does the HTTP
1020
- * request to the server.
1021
- *
1022
- * {@link #connect} will throw an assertion error if the
1023
- * {@link #connectionManager} status is not {@link ConnectionManagerState.Disconnected}
1024
- * or {@link ConnectionManagerState.Connecting}.
1025
- * Callers MUST check the connection status before calling this method and log
1026
- * an error as needed.
1027
- *
1028
- * The function will resolve once the socket is connected. If you need to know
1029
- * when a connection has been established, as in we have received the
1030
- * {@link ConnectedMessage}, you should await the {@link #connectResolver}
1031
- * promise. The {@link #connectResolver} promise rejects if an error message
1032
- * is received before the connected message is received or if the connection
1033
- * attempt times out.
1034
- */
1035
- async #connect(lc, additionalConnectParams) {
1036
- if (this.closed) {
1037
- return;
1038
- }
1039
- assert(this.#server, "No server provided");
1040
- assert(
1041
- this.#connectionManager.is(Disconnected) || this.#connectionManager.is(Connecting),
1042
- "connect() called from invalid state: " + this.#connectionManager.state.name
1043
- );
1044
- const wsid = nanoid();
1045
- lc = addWebSocketIDToLogContext(wsid, lc);
1046
- lc.info?.("Connecting...", { navigatorOnline: localNavigator?.onLine });
1047
- this.#connectionManager.connecting();
1048
- assert(this.#connectStart === void 0, "connect start time is defined");
1049
- const now = Date.now();
1050
- this.#connectStart = now;
1051
- if (this.#totalToConnectStart === void 0) {
1052
- this.#totalToConnectStart = now;
1053
- }
1054
- if (this.closed) {
1055
- return;
1056
- }
1057
- this.#connectCookie = parse(
1058
- await this.#rep.cookie,
1059
- nullableVersionSchema,
1060
- "passthrough"
1061
- );
1062
- if (this.closed) {
1063
- return;
1064
- }
1065
- const timeoutID = setTimeout(() => {
1066
- lc.debug?.("Rejecting connect resolver due to timeout");
1067
- const timeoutError = new ClientError({
1068
- kind: ConnectTimeout,
1069
- message: `Connection attempt timed out after ${CONNECT_TIMEOUT_MS / 1e3} seconds`
1070
- });
1071
- this.#connectResolver.reject(timeoutError);
1072
- this.#disconnect(lc, timeoutError);
1073
- }, CONNECT_TIMEOUT_MS);
1074
- const abortHandler = () => {
1075
- clearTimeout(timeoutID);
1076
- };
1077
- this.#closeAbortController.signal.addEventListener("abort", abortHandler);
1078
- const [ws, initConnectionQueries, deletedClients] = await createSocket(
1079
- this.#rep,
1080
- this.#queryManager,
1081
- this.#deleteClientsManager,
1082
- toWSString(this.#server),
1083
- this.#connectCookie,
1084
- this.clientID,
1085
- await this.clientGroupID,
1086
- this.#clientSchema,
1087
- this.userID,
1088
- fromReplicacheAuthToken(this.#rep.auth),
1089
- this.#lastMutationIDReceived,
1090
- wsid,
1091
- this.#options.logLevel === "debug",
1092
- lc,
1093
- this.#options.mutateURL,
1094
- this.#options.mutateHeaders,
1095
- this.#options.queryURL ?? this.#options.getQueriesURL,
1096
- this.#options.queryHeaders,
1097
- additionalConnectParams,
1098
- await this.#activeClientsManager,
1099
- this.#options.maxHeaderLength
1100
- );
1101
- if (this.closed) {
1102
- return;
1103
- }
1104
- this.#initConnectionQueries = initConnectionQueries;
1105
- this.#deletedClients = deletedClients;
1106
- ws.addEventListener("message", this.#onMessage);
1107
- ws.addEventListener("open", this.#onOpen);
1108
- ws.addEventListener("close", this.#onClose);
1109
- this.#socket = ws;
1110
- this.#socketResolver.resolve(ws);
1111
- try {
1112
- lc.debug?.("Waiting for connection to be acknowledged");
1113
- await this.#connectResolver.promise;
1114
- this.#mutationTracker.onConnected(this.#lastMutationIDReceived);
1115
- this.#rep.push().catch(() => {
1116
- });
1117
- } finally {
1118
- clearTimeout(timeoutID);
1119
- this.#closeAbortController.signal.removeEventListener(
1120
- "abort",
1121
- abortHandler
1122
- );
1123
- }
1124
- }
1125
- #disconnect(lc, reason, closeCode) {
1126
- if (shouldReportConnectError(reason)) {
1127
- this.#connectErrorCount++;
1128
- this.#metrics.lastConnectError.set(getLastConnectErrorValue(reason));
1129
- this.#metrics.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);
1130
- this.#metrics.setConnectError(reason);
1131
- if (this.#connectErrorCount % CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY === 1) {
1132
- this.#checkConnectivity(`connectErrorCount=${this.#connectErrorCount}`);
1133
- }
1134
- }
1135
- lc.info?.("disconnecting", {
1136
- navigatorOnline: localNavigator?.onLine,
1137
- reason: reason.kind,
1138
- connectStart: this.#connectStart,
1139
- totalToConnectStart: this.#totalToConnectStart,
1140
- connectedAt: this.#connectedAt,
1141
- connectionDuration: this.#connectedAt ? Date.now() - this.#connectedAt : 0,
1142
- messageCount: this.#messageCount,
1143
- connectionState: this.#connectionManager.state,
1144
- connectErrorCount: this.#connectErrorCount
1145
- });
1146
- const connectionStatus = this.#connectionManager.state.name;
1147
- switch (connectionStatus) {
1148
- case Connected: {
1149
- if (this.#connectStart !== void 0) {
1150
- lc.error?.(
1151
- "disconnect() called while connected but connect start time is defined."
1152
- );
1153
- }
1154
- break;
1155
- }
1156
- case Closed:
1157
- lc.debug?.("disconnect() called while closed");
1158
- return;
1159
- case Disconnected:
1160
- case Connecting:
1161
- case NeedsAuth:
1162
- case Error$1:
1163
- break;
1164
- default:
1165
- unreachable();
1166
- }
1167
- this.#socketResolver = resolver();
1168
- lc.debug?.("Creating new connect resolver");
1169
- this.#connectResolver = resolver();
1170
- this.#messageCount = 0;
1171
- this.#connectStart = void 0;
1172
- this.#connectedAt = 0;
1173
- this.#socket?.removeEventListener("message", this.#onMessage);
1174
- this.#socket?.removeEventListener("open", this.#onOpen);
1175
- this.#socket?.removeEventListener("close", this.#onClose);
1176
- this.#socket?.close(closeCode);
1177
- this.#socket = void 0;
1178
- this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
1179
- this.#pokeHandler.handleDisconnect();
1180
- const transition = getErrorConnectionTransition(reason);
1181
- switch (transition.status) {
1182
- case NeedsAuth:
1183
- this.#connectionManager.needsAuth(transition.reason);
1184
- break;
1185
- case Error$1:
1186
- this.#connectionManager.error(transition.reason);
1187
- break;
1188
- case Disconnected:
1189
- this.#connectionManager.disconnected(transition.reason);
1190
- break;
1191
- case Closed:
1192
- this.#connectionManager.closed();
1193
- break;
1194
- case NO_STATUS_TRANSITION:
1195
- if (!this.#connectionManager.isInTerminalState()) {
1196
- this.#connectionManager.connecting(transition.reason);
1197
- }
1198
- break;
1199
- default:
1200
- unreachable();
1201
- }
1202
- }
1203
- #handlePokeStart(_lc, pokeMessage) {
1204
- this.#abortPingTimeout();
1205
- this.#pokeHandler.handlePokeStart(pokeMessage[1]);
1206
- }
1207
- #handlePokePart(_lc, pokeMessage) {
1208
- this.#abortPingTimeout();
1209
- const lastMutationIDChangeForSelf = this.#pokeHandler.handlePokePart(
1210
- pokeMessage[1]
1211
- );
1212
- if (lastMutationIDChangeForSelf !== void 0) {
1213
- this.#lastMutationIDReceived = lastMutationIDChangeForSelf;
1214
- }
1215
- }
1216
- #handlePokeEnd(_lc, pokeMessage) {
1217
- this.#abortPingTimeout();
1218
- this.#pokeHandler.handlePokeEnd(pokeMessage[1]);
1219
- }
1220
- #onPokeError() {
1221
- const lc = this.#lc;
1222
- lc.info?.(
1223
- "poke error, disconnecting?",
1224
- !this.#connectionManager.is(Disconnected)
1225
- );
1226
- if (!this.#connectionManager.is(Disconnected)) {
1227
- this.#disconnect(
1228
- lc,
1229
- new ClientError({
1230
- kind: UnexpectedBaseCookie,
1231
- message: "Server returned unexpected base cookie during sync"
1232
- })
1233
- );
1234
- }
1235
- }
1236
- #handlePullResponse(lc, pullResponseMessage) {
1237
- this.#abortPingTimeout();
1238
- const body = pullResponseMessage[1];
1239
- lc = lc.withContext("requestID", body.requestID);
1240
- lc.debug?.("Handling pull response", body);
1241
- const resolver2 = this.#pendingPullsByRequestID.get(body.requestID);
1242
- if (!resolver2) {
1243
- lc.debug?.("No resolver found");
1244
- return;
1245
- }
1246
- resolver2.resolve(pullResponseMessage[1]);
1247
- }
1248
- async #pusher(req, requestID) {
1249
- assert(req.pushVersion === 1, "Expected pushVersion 1");
1250
- await this.#connectResolver.promise;
1251
- const lc = this.#lc.withContext("requestID", requestID);
1252
- lc.debug?.(`pushing ${req.mutations.length} mutations`);
1253
- const socket = this.#socket;
1254
- assert(socket, "Expected socket to be connected for push");
1255
- const isMutationRecoveryPush = req.clientGroupID !== await this.clientGroupID;
1256
- const start = isMutationRecoveryPush ? 0 : req.mutations.findIndex(
1257
- (m) => m.clientID === this.#lastMutationIDSent.clientID && m.id === this.#lastMutationIDSent.id
1258
- ) + 1;
1259
- lc.debug?.(
1260
- isMutationRecoveryPush ? "pushing for recovery" : "pushing",
1261
- req.mutations.length - start,
1262
- "mutations of",
1263
- req.mutations.length,
1264
- "mutations."
1265
- );
1266
- const now = Date.now();
1267
- for (let i = start; i < req.mutations.length; i++) {
1268
- const m = req.mutations[i];
1269
- const timestamp = now - Math.round(performance.now() - m.timestamp);
1270
- const zeroM = m.name === CRUD_MUTATION_NAME ? {
1271
- type: CRUD,
1272
- timestamp,
1273
- id: m.id,
1274
- clientID: m.clientID,
1275
- name: m.name,
1276
- args: [mapCRUD(m.args, this.#clientToServer)]
1277
- } : {
1278
- type: Custom,
1279
- timestamp,
1280
- id: m.id,
1281
- clientID: m.clientID,
1282
- name: m.name,
1283
- args: [m.args]
1284
- };
1285
- const msg = [
1286
- "push",
1287
- {
1288
- timestamp: now,
1289
- clientGroupID: req.clientGroupID,
1290
- mutations: [zeroM],
1291
- pushVersion: req.pushVersion,
1292
- requestID
1293
- }
1294
- ];
1295
- send(socket, msg);
1296
- if (!isMutationRecoveryPush) {
1297
- this.#lastMutationIDSent = { clientID: m.clientID, id: m.id };
1298
- }
1299
- }
1300
- return {
1301
- httpRequestInfo: {
1302
- errorMessage: "",
1303
- httpStatusCode: 200
1304
- }
1305
- };
1306
- }
1307
- async #runLoop() {
1308
- this.#lc.info?.(`Starting Zero version: ${this.version}`);
1309
- if (this.#server === null) {
1310
- this.#lc.info?.("No socket origin provided, not starting connect loop.");
1311
- this.#connectionManager.disconnected(
1312
- new ClientError({
1313
- kind: NoSocketOrigin,
1314
- message: "No server socket origin provided"
1315
- })
1316
- );
1317
- return;
1318
- }
1319
- let runLoopCounter = 0;
1320
- const bareLogContext = this.#lc;
1321
- const getLogContext = () => {
1322
- let lc = bareLogContext;
1323
- if (this.#socket) {
1324
- lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);
1325
- }
1326
- return lc.withContext("runLoopCounter", runLoopCounter);
1327
- };
1328
- const { auth } = this.#options;
1329
- this.#setAuth(auth);
1330
- let backoffMs;
1331
- let additionalConnectParams;
1332
- while (this.#connectionManager.shouldContinueRunLoop()) {
1333
- runLoopCounter++;
1334
- let lc = getLogContext();
1335
- backoffMs = RUN_LOOP_INTERVAL_MS;
1336
- try {
1337
- const currentState = this.#connectionManager.state;
1338
- switch (currentState.name) {
1339
- case Connecting:
1340
- case Disconnected: {
1341
- if (this.#visibilityWatcher.visibilityState === "hidden") {
1342
- this.#metrics.setDisconnectedWaitingForVisible();
1343
- this.#totalToConnectStart = void 0;
1344
- }
1345
- const visibilityResult = await promiseRace({
1346
- visible: this.#visibilityWatcher.waitForVisible(),
1347
- stateChange: this.#connectionManager.waitForStateChange()
1348
- });
1349
- if (visibilityResult.key === "stateChange") {
1350
- throwIfConnectionError(visibilityResult.result);
1351
- break;
1352
- }
1353
- if (reloadScheduled()) {
1354
- break;
1355
- }
1356
- await this.#connect(lc, additionalConnectParams);
1357
- additionalConnectParams = void 0;
1358
- throwIfConnectionError(this.#connectionManager.state);
1359
- assert(this.#socket, "Expected socket after reconnection");
1360
- lc = getLogContext();
1361
- lc.debug?.("Connected successfully");
1362
- break;
1363
- }
1364
- case Connected: {
1365
- const controller = new AbortController();
1366
- this.#abortPingTimeout = () => controller.abort();
1367
- const [pingTimeoutPromise, pingTimeoutAborted] = sleepWithAbort(
1368
- this.pingTimeoutMs,
1369
- controller.signal
1370
- );
1371
- const raceResult = await promiseRace({
1372
- waitForPing: pingTimeoutPromise,
1373
- waitForPingAborted: pingTimeoutAborted,
1374
- tabHidden: this.#visibilityWatcher.waitForHidden(),
1375
- stateChange: this.#connectionManager.waitForStateChange()
1376
- });
1377
- switch (raceResult.key) {
1378
- case "waitForPing": {
1379
- await this.#ping(lc);
1380
- break;
1381
- }
1382
- case "waitForPingAborted":
1383
- break;
1384
- case "tabHidden": {
1385
- const hiddenError = new ClientError({
1386
- kind: Hidden,
1387
- message: "Connection closed because tab was hidden"
1388
- });
1389
- this.#disconnect(lc, hiddenError);
1390
- break;
1391
- }
1392
- case "stateChange": {
1393
- throwIfConnectionError(raceResult.result);
1394
- break;
1395
- }
1396
- default:
1397
- unreachable(raceResult);
1398
- }
1399
- break;
1400
- }
1401
- case NeedsAuth: {
1402
- lc.info?.(
1403
- `Run loop paused in needs-auth state. Call zero.connection.connect({auth}) to resume.`,
1404
- currentState.reason
1405
- );
1406
- const resumeResult = await promiseRace({
1407
- connectRequest: this.#connectionManager.waitForConnectRequest(),
1408
- stateChange: this.#connectionManager.waitForStateChange()
1409
- });
1410
- if (resumeResult.key === "connectRequest") {
1411
- this.#connectionManager.resumeFromConnectRequest();
1412
- }
1413
- break;
1414
- }
1415
- case Error$1: {
1416
- lc.info?.(
1417
- `Run loop paused in error state. Call zero.connection.connect() to resume.`,
1418
- currentState.reason
1419
- );
1420
- const resumeResult = await promiseRace({
1421
- connectRequest: this.#connectionManager.waitForConnectRequest(),
1422
- stateChange: this.#connectionManager.waitForStateChange()
1423
- });
1424
- if (resumeResult.key === "connectRequest") {
1425
- this.#connectionManager.resumeFromConnectRequest();
1426
- }
1427
- break;
1428
- }
1429
- case Closed:
1430
- break;
1431
- default:
1432
- unreachable(currentState);
1433
- }
1434
- } catch (ex) {
1435
- const isClientClosedError = isClientError(ex) && ex.kind === ClientClosed;
1436
- if (!this.#connectionManager.is(Connected) && !isClientClosedError) {
1437
- const level = isAuthError(ex) ? "warn" : "error";
1438
- const kind = isServerError(ex) ? ex.kind : "Unknown Error";
1439
- lc[level]?.("Failed to connect", ex, kind, {
1440
- lmid: this.#lastMutationIDReceived,
1441
- baseCookie: this.#connectCookie
1442
- });
1443
- }
1444
- lc.debug?.(
1445
- "Got an exception in the run loop",
1446
- "state:",
1447
- this.#connectionManager.state,
1448
- "exception:",
1449
- ex
1450
- );
1451
- const transition = getErrorConnectionTransition(ex);
1452
- let sleepMs = void 0;
1453
- switch (transition.status) {
1454
- case NO_STATUS_TRANSITION: {
1455
- const backoffParams = getBackoffParams(transition.reason);
1456
- if (backoffParams) {
1457
- if (backoffParams.minBackoffMs !== void 0) {
1458
- backoffMs = Math.max(backoffMs, backoffParams.minBackoffMs);
1459
- }
1460
- if (backoffParams.maxBackoffMs !== void 0) {
1461
- backoffMs = Math.min(backoffMs, backoffParams.maxBackoffMs);
1462
- }
1463
- additionalConnectParams = backoffParams.reconnectParams;
1464
- }
1465
- lc.debug?.(
1466
- "Sleeping",
1467
- backoffMs,
1468
- "ms before reconnecting due to error, state:",
1469
- this.#connectionManager.state
1470
- );
1471
- sleepMs = backoffMs;
1472
- break;
1473
- }
1474
- case NeedsAuth: {
1475
- lc.debug?.(
1476
- "Auth error encountered, transitioning to needs-auth state"
1477
- );
1478
- this.#connectionManager.needsAuth(transition.reason);
1479
- break;
1480
- }
1481
- case Error$1: {
1482
- lc.debug?.("Fatal error encountered, transitioning to error state");
1483
- this.#connectionManager.error(transition.reason);
1484
- break;
1485
- }
1486
- case Disconnected: {
1487
- this.#connectionManager.disconnected(transition.reason);
1488
- break;
1489
- }
1490
- case Closed: {
1491
- break;
1492
- }
1493
- default:
1494
- unreachable();
1495
- }
1496
- if (transition.status !== Closed) {
1497
- try {
1498
- this.#forceEnableRefresh = true;
1499
- await this.#rep.runRefresh();
1500
- } catch (ex2) {
1501
- if (ex2 instanceof AbortError) {
1502
- this.#lc.debug?.(
1503
- `Refresh from storage did not complete before close.`
1504
- );
1505
- } else {
1506
- this.#lc.error?.(`Error during refresh from storage`, ex2);
1507
- }
1508
- } finally {
1509
- this.#forceEnableRefresh = false;
1510
- }
1511
- }
1512
- if (sleepMs) {
1513
- await sleep(sleepMs);
1514
- }
1515
- }
1516
- }
1517
- }
1518
- async #puller(req, requestID) {
1519
- assert(req.pullVersion === 1, "Expected pullVersion 1");
1520
- const lc = this.#lc.withContext("requestID", requestID);
1521
- lc.debug?.("Pull", req);
1522
- if (req.clientGroupID === await this.clientGroupID) {
1523
- return {
1524
- httpRequestInfo: {
1525
- errorMessage: "",
1526
- httpStatusCode: 200
1527
- }
1528
- };
1529
- }
1530
- await this.#connectResolver.promise;
1531
- const socket = this.#socket;
1532
- assert(
1533
- socket,
1534
- "Expected socket to be connected for mutation recovery pull"
1535
- );
1536
- lc.debug?.("Pull is for mutation recovery");
1537
- const cookie = parse(
1538
- req.cookie,
1539
- nullableVersionSchema,
1540
- "passthrough"
1541
- );
1542
- const pullRequestMessage = [
1543
- "pull",
1544
- {
1545
- clientGroupID: req.clientGroupID,
1546
- cookie,
1547
- requestID
1548
- }
1549
- ];
1550
- send(socket, pullRequestMessage);
1551
- const pullResponseResolver = resolver();
1552
- this.#pendingPullsByRequestID.set(requestID, pullResponseResolver);
1553
- try {
1554
- const raceResult = await promiseRace({
1555
- timeout: sleep(PULL_TIMEOUT_MS),
1556
- success: pullResponseResolver.promise
1557
- });
1558
- switch (raceResult.key) {
1559
- case "timeout":
1560
- lc.debug?.("Mutation recovery pull timed out");
1561
- throw new ClientError({
1562
- kind: PullTimeout,
1563
- message: "Pull timed out"
1564
- });
1565
- case "success": {
1566
- lc.debug?.("Returning mutation recovery pull response");
1567
- const response = await pullResponseResolver.promise;
1568
- return {
1569
- response: {
1570
- cookie: response.cookie,
1571
- lastMutationIDChanges: response.lastMutationIDChanges,
1572
- patch: []
1573
- },
1574
- httpRequestInfo: {
1575
- errorMessage: "",
1576
- httpStatusCode: 200
1577
- }
1578
- };
1579
- }
1580
- default:
1581
- unreachable(raceResult);
1582
- }
1583
- } finally {
1584
- pullResponseResolver.reject(
1585
- new ClientError({
1586
- kind: PullTimeout,
1587
- message: "Pull timed out"
1588
- })
1589
- );
1590
- this.#pendingPullsByRequestID.delete(requestID);
1591
- }
1592
- }
1593
- /**
1594
- * Sets the authentication token on the replicache instance.
1595
- *
1596
- * @param auth - The authentication token to set.
1597
- */
1598
- #setAuth(auth) {
1599
- this.#rep.auth = toReplicacheAuthToken(auth);
1600
- if (auth) {
1601
- this.#send(["updateAuth", { auth }]);
1602
- }
1603
- }
1604
- /**
1605
- * A rough heuristic for whether the client is currently online and
1606
- * authenticated.
1607
- *
1608
- * @deprecated Use `connection` instead, which provides more detailed connection state.
1609
- */
1610
- get online() {
1611
- return this.#onlineManager.online;
1612
- }
1613
- /**
1614
- * Subscribe to online status changes.
1615
- *
1616
- * This is useful when you want to update state based on the online status.
1617
- *
1618
- * @param listener - The listener to subscribe to.
1619
- * @returns A function to unsubscribe the listener.
1620
- *
1621
- * @deprecated Use `connection` instead, which provides more detailed connection state.
1622
- */
1623
- onOnline = (listener) => this.#onlineManager.subscribe(listener);
1624
- /**
1625
- * Starts a ping and waits for a pong.
1626
- */
1627
- async #ping(lc) {
1628
- lc.debug?.("pinging");
1629
- const { promise, resolve } = resolver();
1630
- this.#onPong = resolve;
1631
- const pingMessage = ["ping", {}];
1632
- const t0 = performance.now();
1633
- assert(this.#socket, "Expected socket to be connected for ping");
1634
- send(this.#socket, pingMessage);
1635
- const raceResult = await promiseRace({
1636
- waitForPong: promise,
1637
- pingTimeout: sleep(this.pingTimeoutMs),
1638
- stateChange: this.#connectionManager.waitForStateChange()
1639
- });
1640
- const delta = performance.now() - t0;
1641
- switch (raceResult.key) {
1642
- case "waitForPong": {
1643
- lc.debug?.("ping succeeded in", delta, "ms");
1644
- return;
1645
- }
1646
- case "pingTimeout": {
1647
- lc.info?.("ping failed in", delta, "ms - disconnecting");
1648
- const pingTimeoutError = new ClientError({
1649
- kind: PingTimeout,
1650
- message: "Server ping request failed"
1651
- });
1652
- this.#disconnect(lc, pingTimeoutError);
1653
- throw pingTimeoutError;
1654
- }
1655
- case "stateChange": {
1656
- lc.debug?.(
1657
- "ping aborted due to connection state change",
1658
- raceResult.result
1659
- );
1660
- throwIfConnectionError(raceResult.result);
1661
- break;
1662
- }
1663
- default:
1664
- unreachable();
1665
- }
1666
- }
1667
- // Sends a set of metrics to the server. Throws unless the server
1668
- // returns 200.
1669
- // TODO: Reenable metrics reporting
1670
- async #reportMetrics(_allSeries) {
1671
- }
1672
- #checkConnectivity(reason) {
1673
- this.#checkConnectivityAsync(reason);
1674
- }
1675
- #checkConnectivityAsync(_reason) {
1676
- }
1677
- /**
1678
- * `inspector` is an object that can be used to inspect the state of the
1679
- * queries a Zero instance uses. It is intended for debugging purposes.
1680
- */
1681
- get inspector() {
1682
- {
1683
- return this.#inspector ??= new Inspector(
1684
- this.#rep,
1685
- this.#queryManager,
1686
- this.#zeroContext,
1687
- async () => {
1688
- await this.#connectResolver.promise;
1689
- return must(this.#socket);
1690
- }
1691
- );
1692
- }
1693
- }
1694
- async delete() {
1695
- await this.close();
1696
- const kvStoreProvider = getKVStoreProvider(this.#lc, this.#kvStore);
1697
- const idbDatabasesStore = new IDBDatabasesStore(kvStoreProvider.create);
1698
- try {
1699
- const databases = await idbDatabasesStore.getDatabases();
1700
- const dbNamesToDelete = Object.values(databases).filter((database) => database.replicacheName === this.#rep.name).map((database) => database.name);
1701
- const deleteResults = await Promise.allSettled(
1702
- dbNamesToDelete.map(async (dbName) => {
1703
- await dropDatabase(dbName, { kvStore: this.#kvStore });
1704
- return dbName;
1705
- })
1706
- );
1707
- const deleted = [];
1708
- const errors = [];
1709
- for (const result of deleteResults) {
1710
- if (result.status === "fulfilled") {
1711
- deleted.push(result.value);
1712
- } else {
1713
- errors.push(result.reason);
1714
- }
1715
- }
1716
- return { deleted, errors };
1717
- } finally {
1718
- await idbDatabasesStore.close();
1719
- }
1720
- }
1721
- #addMetric = (metric, value, ...args) => {
1722
- assert(isClientMetric(metric), `Invalid metric: ${metric}`);
1723
- this.#queryManager.addMetric(
1724
- metric,
1725
- value,
1726
- ...args
1727
- );
1728
- };
1729
- }
1730
- class OnlineManager extends Subscribable {
1731
- #online = false;
1732
- setOnline(online) {
1733
- if (this.#online === online) {
1734
- return;
1735
- }
1736
- this.#online = online;
1737
- this.notify(online);
1738
- }
1739
- get online() {
1740
- return this.#online;
1741
- }
118
+ return `Server could not find state needed to synchronize this client. ${serverErrMsg}`;
1742
119
  }
120
+ var ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT = "The local persistent state needed to synchronize this client has been garbage collected.";
121
+ var CLOSE_CODE_NORMAL = 1e3;
122
+ var Zero = class Zero {
123
+ version = version;
124
+ #rep;
125
+ #server;
126
+ userID;
127
+ storageKey;
128
+ #lc;
129
+ #logOptions;
130
+ #enableAnalytics;
131
+ #clientSchema;
132
+ #pokeHandler;
133
+ #queryManager;
134
+ #ivmMain;
135
+ #clientToServer;
136
+ #deleteClientsManager;
137
+ #mutationTracker;
138
+ /**
139
+ * The queries we sent when inside the sec-protocol header when establishing a connection.
140
+ * More queries could be registered while we're waiting for the 'connected' message
141
+ * to come back from the server. To understand what queries we need to send
142
+ * to the server, we diff the `initConnectionQueries` with the current set of desired queries.
143
+ *
144
+ * If this is set to `undefined` that means no queries were sent inside the `sec-protocol` header
145
+ * and an `initConnection` message must be sent to the server after receiving the `connected` message.
146
+ */
147
+ #initConnectionQueries;
148
+ /**
149
+ * We try to send the deleted clients and (client groups) as part of the
150
+ * sec-protocol header. If we can't because the header would get too large we
151
+ * keep track of the deleted clients and send them after the connection is
152
+ * established.
153
+ */
154
+ #deletedClients;
155
+ #lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
156
+ #onPong = () => void 0;
157
+ #onlineManager;
158
+ #onUpdateNeeded;
159
+ #onClientStateNotFound;
160
+ #connectCookie = null;
161
+ #connectedCount = 0;
162
+ #messageCount = 0;
163
+ #connectedAt = 0;
164
+ #connectErrorCount = 0;
165
+ #abortPingTimeout = () => {};
166
+ #forceEnableRefresh = false;
167
+ /**
168
+ * The timeout in milliseconds for ping operations. Controls both:
169
+ * - How long to wait in idle before sending a ping
170
+ * - How long to wait for a pong response
171
+ *
172
+ * Total time to detect a dead connection is 2 × pingTimeoutMs.
173
+ *
174
+ * The new value will take effect on the next ping cycle.
175
+ */
176
+ pingTimeoutMs;
177
+ #zeroContext;
178
+ #pendingPullsByRequestID = /* @__PURE__ */ new Map();
179
+ #lastMutationIDReceived = 0;
180
+ #socket = void 0;
181
+ #socketResolver = resolver();
182
+ /**
183
+ * Utility promise that resolves when the socket transitions to connected.
184
+ * It rejects if we hit an error or timeout before the connected message.
185
+ * Used by push/pull helpers to queue work until the connection is usable.
186
+ */
187
+ #connectResolver = resolver();
188
+ #closeAbortController = new AbortController();
189
+ #visibilityWatcher;
190
+ #connectionManager;
191
+ #connection;
192
+ #activeClientsManager;
193
+ #inspector;
194
+ #connectStart = void 0;
195
+ #totalToConnectStart = void 0;
196
+ #options;
197
+ #kvStore;
198
+ /**
199
+ * Query builders for each table in the schema.
200
+ *
201
+ * @deprecated Use {@linkcode createBuilder} to create query builders instead.
202
+ */
203
+ query;
204
+ #metrics;
205
+ #reload = () => getBrowserGlobal("location")?.reload();
206
+ /**
207
+ * Constructs a new Zero client.
208
+ */
209
+ constructor(options) {
210
+ const { userID, storageKey, onOnlineChange, onUpdateNeeded, onClientStateNotFound, hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS, pingTimeoutMs = DEFAULT_PING_TIMEOUT_MS, disconnectTimeoutMs = DEFAULT_DISCONNECT_TIMEOUT_MS, schema, batchViewUpdates = (applyViewUpdates) => applyViewUpdates(), maxRecentQueries = 0, slowMaterializeThreshold = 5e3 } = options;
211
+ if (!userID) throw new ClientError({
212
+ kind: Internal,
213
+ message: "ZeroOptions.userID must not be empty."
214
+ });
215
+ const server = getServer(options.cacheURL ?? options.server);
216
+ this.#enableAnalytics = shouldEnableAnalytics(server, false);
217
+ let { kvStore = "idb" } = options;
218
+ if (kvStore === "idb") {
219
+ if (!getBrowserGlobal("indexedDB")) {
220
+ console.warn("IndexedDB is not supported in this environment. Falling back to memory storage.");
221
+ kvStore = "mem";
222
+ }
223
+ }
224
+ if (hiddenTabDisconnectDelay < 0) throw new ClientError({
225
+ kind: Internal,
226
+ message: "ZeroOptions.hiddenTabDisconnectDelay must not be negative."
227
+ });
228
+ this.#kvStore = kvStore;
229
+ this.pingTimeoutMs = pingTimeoutMs;
230
+ this.#onlineManager = new OnlineManager();
231
+ if (onOnlineChange) this.#onlineManager.subscribe(onOnlineChange);
232
+ this.#options = options;
233
+ this.#logOptions = this.#createLogOptions({
234
+ consoleLogLevel: options.logLevel ?? "warn",
235
+ server: null,
236
+ enableAnalytics: this.#enableAnalytics
237
+ });
238
+ const logOptions = this.#logOptions;
239
+ this.#connectionManager = new ConnectionManager({ disconnectTimeout: disconnectTimeoutMs });
240
+ const syncConnectionState = (state) => {
241
+ this.#onlineManager.setOnline(state.name === Connected);
242
+ if (state.name === "closed") this.#queryManager.handleClosed(state.reason);
243
+ };
244
+ syncConnectionState(this.#connectionManager.state);
245
+ this.#connectionManager.subscribe(syncConnectionState);
246
+ const sink = logOptions.logSink;
247
+ const lc = new LogContext(logOptions.logLevel, {}, sink);
248
+ this.#mutationTracker = new MutationTracker(lc, (upTo) => this.#send(["ackMutationResponses", upTo]), (error) => this.#disconnect(lc, error));
249
+ this.#ivmMain = new IVMSourceBranch(schema.tables);
250
+ const { enableLegacyQueries = false } = schema;
251
+ const replicacheMutators = makeReplicacheMutators(schema, options.mutators, this.context, lc);
252
+ this.storageKey = storageKey ?? "";
253
+ const { clientSchema, hash } = clientSchemaFrom(schema);
254
+ this.#clientSchema = clientSchema;
255
+ const hashedKey = h64(JSON.stringify({
256
+ storageKey: this.storageKey,
257
+ mutateUrl: options.mutateURL ?? "",
258
+ queryUrl: options.queryURL ?? options.getQueriesURL ?? ""
259
+ })).toString(36);
260
+ const replicacheOptions = {
261
+ schemaVersion: `49.${hash}`,
262
+ logLevel: logOptions.logLevel,
263
+ logSinks: [logOptions.logSink],
264
+ mutators: replicacheMutators,
265
+ name: `zero-${userID}-${hashedKey}`,
266
+ pusher: (req, reqID) => this.#pusher(req, reqID),
267
+ puller: (req, reqID) => this.#puller(req, reqID),
268
+ pushDelay: 0,
269
+ requestOptions: {
270
+ maxDelayMs: 0,
271
+ minDelayMs: 0
272
+ },
273
+ licenseKey: "zero-client-static-key",
274
+ kvStore
275
+ };
276
+ this.#zeroContext = new ZeroContext(lc, this.#ivmMain, (ast, ttl, gotCallback) => {
277
+ if (enableLegacyQueries) return this.#queryManager.addLegacy(ast, ttl, gotCallback);
278
+ return emptyFunction;
279
+ }, (ast, customQueryID, ttl, gotCallback) => this.#queryManager.addCustom(ast, customQueryID, ttl, gotCallback), (ast, ttl) => {
280
+ if (enableLegacyQueries) this.#queryManager.updateLegacy(ast, ttl);
281
+ }, (customQueryID, ttl) => this.#queryManager.updateCustom(customQueryID, ttl), () => this.#queryManager.flushBatch(), batchViewUpdates, this.#addMetric, assertValidRunOptions);
282
+ this.query = createRunnableBuilder(this.#zeroContext, schema);
283
+ const rep = new ReplicacheImpl(replicacheOptions, {
284
+ enableClientGroupForking: false,
285
+ enableMutationRecovery: false,
286
+ enablePullAndPushInOpen: false,
287
+ enableRefresh: () => this.#enableRefresh(),
288
+ onClientsDeleted: (deletedClients) => this.#deleteClientsManager.onClientsDeleted(deletedClients),
289
+ zero: new ZeroRep(this.#zeroContext, this.#ivmMain, options.mutators !== void 0, this.#mutationTracker)
290
+ });
291
+ this.#rep = rep;
292
+ this.#server = server;
293
+ this.userID = userID;
294
+ this.#lc = lc.withContext("clientID", rep.clientID);
295
+ this.#connection = new ConnectionImpl(this.#connectionManager, this.#lc, (auth) => this.#setAuth(auth));
296
+ this.#mutationTracker.setClientIDAndWatch(rep.clientID, rep.experimentalWatch.bind(rep));
297
+ this.#activeClientsManager = makeActiveClientsManager(rep.clientGroupID, this.clientID, this.#closeAbortController.signal, (clientID, clientGroupID) => this.#deleteClientsManager.onClientsDeleted([{
298
+ clientGroupID,
299
+ clientID
300
+ }]));
301
+ const onUpdateNeededCallback = (reason) => {
302
+ if (onUpdateNeeded) onUpdateNeeded(reason);
303
+ else reloadWithReason(this.#lc, this.#reload, reason.type, updateNeededReloadReasonMessage(reason));
304
+ };
305
+ this.#onUpdateNeeded = onUpdateNeededCallback;
306
+ this.#rep.onUpdateNeeded = (reason) => {
307
+ onUpdateNeededCallback(convertOnUpdateNeededReason(reason));
308
+ };
309
+ const onClientStateNotFoundCallback = onClientStateNotFound ?? ((reason) => {
310
+ reloadWithReason(this.#lc, this.#reload, "ClientNotFound", reason ?? ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT);
311
+ });
312
+ this.#onClientStateNotFound = onClientStateNotFoundCallback;
313
+ this.#rep.onClientStateNotFound = onClientStateNotFoundCallback;
314
+ const mutatorProxy = new MutatorProxy(this.#lc, this.#connectionManager, this.#mutationTracker);
315
+ const { mutators } = options;
316
+ const registeredMutators = new Set(isMutatorRegistry(mutators) ? iterateMutators(mutators) : void 0);
317
+ const callableMutate = (mr) => {
318
+ if (!registeredMutators.has(mr.mutator)) throw new Error(`Mutator "${mr.mutator.mutatorName}" is not registered. Mutators must be registered with the Zero constructor before use.`);
319
+ const repMutator = rep.mutate[mr.mutator.mutatorName];
320
+ return mutatorProxy.wrapCustomMutator(mr.mutator.mutatorName, repMutator)(mr.args);
321
+ };
322
+ const mutateBatch = makeCRUDMutateBatch(schema, rep.mutate);
323
+ if (schema.enableLegacyMutators) addTableCRUDProperties(schema, callableMutate, rep.mutate);
324
+ if (mutators && !isMutatorRegistry(mutators)) addCustomMutatorsProperties(mutators, mutatorProxy, callableMutate, rep.mutate);
325
+ this.mutate = callableMutate;
326
+ this.mutateBatch = mutateBatch;
327
+ this.#queryManager = new QueryManager(this.#lc, this.#mutationTracker, rep.clientID, schema.tables, (msg) => this.#send(msg), rep.experimentalWatch.bind(rep), maxRecentQueries, options.queryChangeThrottleMs ?? DEFAULT_QUERY_CHANGE_THROTTLE_MS, slowMaterializeThreshold, (error) => {
328
+ this.#disconnect(lc, error);
329
+ });
330
+ this.#clientToServer = clientToServer(schema.tables);
331
+ this.#deleteClientsManager = new DeleteClientsManager((msg) => this.#send(msg), rep.perdag, this.#lc, this.#rep.clientGroupID, rep.clientID);
332
+ reportReloadReason(this.#lc);
333
+ this.#metrics = new MetricManager({
334
+ reportIntervalMs: REPORT_INTERVAL_MS,
335
+ host: getBrowserGlobal("location")?.host ?? "",
336
+ source: "client",
337
+ reporter: this.#enableAnalytics ? (allSeries) => this.#reportMetrics(allSeries) : () => Promise.resolve(),
338
+ lc: this.#lc
339
+ });
340
+ this.#metrics.tags.push(`version:${this.version}`);
341
+ this.#pokeHandler = new PokeHandler((poke) => this.#rep.poke(poke), (e) => this.#onPokeError(e), rep.clientID, schema, this.#lc, this.#mutationTracker);
342
+ this.#visibilityWatcher = getDocumentVisibilityWatcher(getBrowserGlobal("document"), hiddenTabDisconnectDelay, this.#closeAbortController.signal);
343
+ this.#runLoop();
344
+ this.#expose();
345
+ }
346
+ #enableRefresh() {
347
+ return this.#forceEnableRefresh || !this.#connectionManager.is("connected") && !this.#connectionManager.is("connecting");
348
+ }
349
+ #expose() {
350
+ const g = globalThis;
351
+ if (g.__zero === void 0) g.__zero = this;
352
+ else if (g.__zero instanceof Zero) {
353
+ const prev = g.__zero;
354
+ g.__zero = {
355
+ [prev.clientID]: prev,
356
+ [this.clientID]: this
357
+ };
358
+ } else g.__zero[this.clientID] = this;
359
+ }
360
+ #unexpose() {
361
+ const g = globalThis;
362
+ assert(g.__zero !== void 0, "No global zero instance found");
363
+ if (g.__zero instanceof Zero) {
364
+ assert(g.__zero === this, "Global zero instance does not match this instance");
365
+ delete g.__zero;
366
+ } else {
367
+ delete g.__zero[this.clientID];
368
+ if (Object.entries(g.__zero).length === 1) g.__zero = Object.values(g.__zero)[0];
369
+ }
370
+ }
371
+ #send(msg) {
372
+ if (this.#socket && this.#connectionManager.is("connected")) send(this.#socket, msg);
373
+ }
374
+ #createLogOptions(options) {
375
+ return createLogOptions(options);
376
+ }
377
+ /**
378
+ * Preloads data for a query into the cache, without keeping it in memory.
379
+ *
380
+ * This function is useful when you want to populate the cache ahead of time,
381
+ * for example after login, to avoid a flash of loading screen on the next page.
382
+ *
383
+ * Returns an object with two properties:
384
+ * - `complete`: a Promise that resolves when the data is loaded
385
+ * - `cleanup`: a function that can be called to cancel the preload
386
+ *
387
+ * @example
388
+ * ```ts
389
+ * const {complete, cleanup} = zero.preload(userQuery);
390
+ * await complete;
391
+ * // Now the data is cached and can be used immediately
392
+ * ```
393
+ */
394
+ preload(query, options) {
395
+ return this.#zeroContext.preload(addContextToQuery(query, this.context), options);
396
+ }
397
+ /**
398
+ * Executes a query once and returns the results.
399
+ *
400
+ * By default, waits for any pending data to sync before running the query.
401
+ * This ensures fresh results from the server. Use `{type: 'unknown'}` to
402
+ * run immediately with whatever data is available locally.
403
+ *
404
+ * @param query - The query to execute
405
+ * @param runOptions - Options controlling query execution
406
+ * @returns A Promise resolving to the query results
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * // Wait for server sync
411
+ * const users = await zero.run(userQuery);
412
+ *
413
+ * // Run with local data only
414
+ * const cachedUsers = await zero.run(userQuery, {type: 'unknown'});
415
+ * ```
416
+ */
417
+ run(query, runOptions) {
418
+ return this.#zeroContext.run(addContextToQuery(query, this.context), runOptions);
419
+ }
420
+ get context() {
421
+ return this.#options.context;
422
+ }
423
+ materialize(query, factoryOrOptions, maybeOptions) {
424
+ const q = addContextToQuery(query, this.context);
425
+ let factory;
426
+ let options;
427
+ if (typeof factoryOrOptions === "function") {
428
+ factory = factoryOrOptions;
429
+ options = maybeOptions;
430
+ } else options = factoryOrOptions;
431
+ return this.#zeroContext.materialize(q, factory, options);
432
+ }
433
+ /**
434
+ * The server URL that this Zero instance is configured with.
435
+ */
436
+ get server() {
437
+ return this.#server;
438
+ }
439
+ /**
440
+ * The name of the IndexedDB database in which the data of this
441
+ * instance of Zero is stored.
442
+ */
443
+ get idbName() {
444
+ return this.#rep.idbName;
445
+ }
446
+ /**
447
+ * The schema version of the data understood by this application.
448
+ * See [[ZeroOptions.schemaVersion]].
449
+ */
450
+ get schemaVersion() {
451
+ return this.#rep.schemaVersion;
452
+ }
453
+ /**
454
+ * The schema passed into Zero when it was constructed.
455
+ *
456
+ * This can be paired with the inspector API to explore the client cache for
457
+ * debugging or tooling. The inspector exposes the raw key/value map as well
458
+ * as the per-table rows that back `zero.query[tableName].run()`.
459
+ *
460
+ * ```ts
461
+ * const inspector = __zero.inspector;
462
+ * const client = inspector.client;
463
+ *
464
+ * console.log('client map:', await client.map());
465
+ *
466
+ * for (const tableName of Object.keys(__zero.schema.tables)) {
467
+ * console.table(await client.rows(tableName));
468
+ * }
469
+ * ```
470
+ */
471
+ get schema() {
472
+ return this.#options.schema;
473
+ }
474
+ /**
475
+ * The client ID for this instance of Zero. Each instance
476
+ * gets a unique client ID.
477
+ */
478
+ get clientID() {
479
+ return this.#rep.clientID;
480
+ }
481
+ get clientGroupID() {
482
+ return this.#rep.clientGroupID;
483
+ }
484
+ /**
485
+ * Use to execute mutations. The primary flow is to call
486
+ * `zero.mutate(mutationRequest)` with your registered custom mutators:
487
+ *
488
+ * ```ts
489
+ * await zero.mutate(
490
+ * mutators.myMutator({id: '1', title: 'First issue'}),
491
+ * );
492
+ * ```
493
+ *
494
+ * When `schema.enableLegacyMutators` is true, legacy conveniences are added:
495
+ * - Table-scoped CRUD helpers, e.g. `zero.mutate.issue.create` / `set` / `update` / `delete`
496
+ * - Your custom mutators exposed directly on `zero.mutate`
497
+ *
498
+ * ```ts
499
+ * await zero.mutate.issue.create({id: '1', title: 'First issue', priority: 'high'});
500
+ * await zero.mutate.comment.create({id: '1', text: 'First comment', issueID: '1'});
501
+ * await zero.mutate.myMutator({id: '1', title: 'First issue'});
502
+ * ```
503
+ *
504
+ * The `update` methods support partials. Unspecified or `undefined` fields
505
+ * are left unchanged:
506
+ *
507
+ * ```ts
508
+ * // Priority left unchanged.
509
+ * await zero.mutate.issue.update({id: '1', title: 'Updated title'});
510
+ * ```
511
+ */
512
+ mutate;
513
+ /**
514
+ * Provides a way to batch multiple CRUD mutations together:
515
+ *
516
+ * ```ts
517
+ * await zero.mutateBatch(m => {
518
+ * await m.issue.create({id: '1', title: 'First issue'});
519
+ * await m.comment.create({id: '1', text: 'First comment', issueID: '1'});
520
+ * });
521
+ * ```
522
+ *
523
+ * Batch sends all mutations in a single transaction. If one fails, all are
524
+ * rolled back together. Batch can also be more efficient than making many
525
+ * individual mutations.
526
+ *
527
+ * `mutateBatch` is not allowed inside another `mutateBatch` call. Doing so
528
+ * will throw an error.
529
+ *
530
+ * @deprecated Use `zero.mutate(mutationRequest)`
531
+ */
532
+ mutateBatch;
533
+ /**
534
+ * The connection API for managing Zero's connection lifecycle.
535
+ *
536
+ * Use this to monitor connection state and manually control connections.
537
+ *
538
+ * @example
539
+ * ```ts
540
+ * // Subscribe to connection state changes
541
+ * z.connection.state.subscribe(state => {
542
+ * console.log('Connection state:', state.name);
543
+ * });
544
+ *
545
+ * // Manually resume connection from error state
546
+ * await z.connection.connect();
547
+ * ```
548
+ */
549
+ get connection() {
550
+ return this.#connection;
551
+ }
552
+ /**
553
+ * Whether this Zero instance has been closed.
554
+ *
555
+ * Once a Zero instance has been closed it no longer syncs, you can no
556
+ * longer query or mutate data with it, and its query views stop updating.
557
+ */
558
+ get closed() {
559
+ return this.#connectionManager.is(Closed);
560
+ }
561
+ /**
562
+ * Closes this Zero instance.
563
+ *
564
+ * Once a Zero instance has been closed it no longer syncs, you can no
565
+ * longer query or mutate data with it, and its query views stop updating.
566
+ */
567
+ async close() {
568
+ const lc = this.#lc.withContext("close");
569
+ try {
570
+ if (this.closed) {
571
+ lc.debug?.("close() called on already closed instance");
572
+ return;
573
+ }
574
+ lc.debug?.("Closing Zero instance. Stack:", (/* @__PURE__ */ new Error()).stack);
575
+ this.#onlineManager.cleanup();
576
+ if (!this.#connectionManager.is("disconnected")) this.#disconnect(lc, new ClientError({
577
+ kind: ClientClosed,
578
+ message: "Zero instance closed by user"
579
+ }), CLOSE_CODE_NORMAL);
580
+ lc.debug?.("Aborting closeAbortController due to close()");
581
+ this.#closeAbortController.abort();
582
+ this.#metrics.stop();
583
+ const ret = await this.#rep.close();
584
+ this.#unexpose();
585
+ return ret;
586
+ } catch (e) {
587
+ lc.error?.("Error closing Zero instance", e);
588
+ throw e;
589
+ } finally {
590
+ this.#connectionManager.closed();
591
+ }
592
+ }
593
+ #onMessage = (e) => {
594
+ const lc = this.#lc;
595
+ lc.debug?.("received message", e.data);
596
+ if (this.closed) {
597
+ lc.debug?.("ignoring message because already closed");
598
+ return;
599
+ }
600
+ let downMessage;
601
+ const { data } = e;
602
+ try {
603
+ downMessage = parse(JSON.parse(data), downstreamSchema, "passthrough");
604
+ } catch (e) {
605
+ const invalidMessageError = new ClientError({
606
+ kind: InvalidMessage,
607
+ message: `Invalid message received from server: ${getErrorMessage(e)}${data}`
608
+ }, { cause: e });
609
+ this.#disconnect(lc, invalidMessageError);
610
+ return;
611
+ }
612
+ this.#messageCount++;
613
+ const msgType = downMessage[0];
614
+ try {
615
+ switch (msgType) {
616
+ case "connected": return this.#handleConnectedMessage(lc, downMessage);
617
+ case "error": return this.#handleErrorMessage(lc, downMessage);
618
+ case "pong":
619
+ resetBackoff();
620
+ return this.#onPong();
621
+ case "pokeStart": return this.#handlePokeStart(lc, downMessage);
622
+ case "pokePart":
623
+ if (downMessage[1].rowsPatch) resetBackoff();
624
+ return this.#handlePokePart(lc, downMessage);
625
+ case "pokeEnd": return this.#handlePokeEnd(lc, downMessage);
626
+ case "pull": return this.#handlePullResponse(lc, downMessage);
627
+ case "deleteClients": return this.#deleteClientsManager.clientsDeletedOnServer(downMessage[1]);
628
+ case "pushResponse": return this.#mutationTracker.processPushResponse(downMessage[1]);
629
+ case "transformError":
630
+ this.#queryManager.handleTransformErrors(downMessage[1]);
631
+ break;
632
+ case "inspect": break;
633
+ default: unreachable(msgType);
634
+ }
635
+ } catch (e) {
636
+ lc.error?.("Unhandled error in onOpen", e);
637
+ this.#disconnect(lc, new ClientError({
638
+ kind: Internal,
639
+ message: getErrorMessage(e)
640
+ }, { cause: e }));
641
+ return;
642
+ }
643
+ };
644
+ #onOpen = () => {
645
+ let lc = this.#lc;
646
+ try {
647
+ assert(this.#socket, "Socket is not set before onOpen");
648
+ lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);
649
+ if (this.#connectStart === void 0) throw new Error("Got open event but connect start time is undefined.");
650
+ else {
651
+ const timeToOpenMs = Date.now() - this.#connectStart;
652
+ lc.info?.("Got socket open event", {
653
+ navigatorOnline: localNavigator?.onLine,
654
+ timeToOpenMs
655
+ });
656
+ }
657
+ } catch (e) {
658
+ lc.error?.("Unhandled error in onOpen", e);
659
+ this.#disconnect(lc, new ClientError({
660
+ kind: Internal,
661
+ message: getErrorMessage(e)
662
+ }, { cause: e }));
663
+ }
664
+ };
665
+ #onClose = (e) => {
666
+ let lc = this.#lc;
667
+ try {
668
+ assert(this.#socket, "Socket is not set before onClose");
669
+ lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);
670
+ const { code, reason, wasClean } = e;
671
+ if (code <= 1001 || code === 1006) lc.info?.("Got socket close event", {
672
+ code,
673
+ reason,
674
+ wasClean
675
+ });
676
+ else lc.error?.("Got unexpected socket close event", {
677
+ code,
678
+ reason,
679
+ wasClean
680
+ });
681
+ const closeError = new ClientError(wasClean ? {
682
+ kind: CleanClose,
683
+ message: "WebSocket connection closed cleanly"
684
+ } : {
685
+ kind: AbruptClose,
686
+ message: "WebSocket connection closed abruptly"
687
+ });
688
+ this.#connectResolver.reject(closeError);
689
+ this.#disconnect(lc, closeError);
690
+ } catch (e) {
691
+ lc.error?.("Unhandled error in onClose", e);
692
+ const internalError = new ClientError({
693
+ kind: Internal,
694
+ message: getErrorMessage(e)
695
+ }, { cause: e });
696
+ this.#connectResolver.reject(internalError);
697
+ this.#disconnect(lc, internalError);
698
+ }
699
+ };
700
+ async #handleErrorMessage(lc, downMessage) {
701
+ const [, { kind, message }] = downMessage;
702
+ if (kind === "MutationRateLimited") {
703
+ this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
704
+ lc.error?.(kind, "Mutation rate limited", { message });
705
+ return;
706
+ }
707
+ lc.info?.(`${kind}: ${message}}`);
708
+ const error = new ProtocolError(downMessage[1]);
709
+ lc.error?.(`${error.kind}:\n\n${error.errorBody.message}`, error);
710
+ lc.debug?.("Rejecting connect resolver due to error", error);
711
+ this.#connectResolver.reject(error);
712
+ this.#disconnect(lc, error);
713
+ if (kind === "VersionNotSupported") this.#onUpdateNeeded({
714
+ type: kind,
715
+ message
716
+ });
717
+ else if (kind === "SchemaVersionNotSupported") {
718
+ await this.#rep.disableClientGroup();
719
+ this.#onUpdateNeeded({
720
+ type: "SchemaVersionNotSupported",
721
+ message
722
+ });
723
+ } else if (kind === "ClientNotFound") {
724
+ await this.#rep.disableClientGroup();
725
+ this.#onClientStateNotFound?.(onClientStateNotFoundServerReason(message));
726
+ } else if (kind === "InvalidConnectionRequestLastMutationID" || kind === "InvalidConnectionRequestBaseCookie") {
727
+ await dropDatabase(this.#rep.idbName, { kvStore: this.#kvStore });
728
+ reloadWithReason(lc, this.#reload, kind, serverAheadReloadReason);
729
+ }
730
+ }
731
+ async #handleConnectedMessage(lc, connectedMessage) {
732
+ const now = Date.now();
733
+ const [, connectBody] = connectedMessage;
734
+ lc = addWebSocketIDToLogContext(connectBody.wsid, lc);
735
+ if (this.#connectedCount === 0) this.#checkConnectivity("firstConnect");
736
+ else if (this.#connectErrorCount > 0) this.#checkConnectivity("connectAfterError");
737
+ this.#connectedCount++;
738
+ this.#connectedAt = now;
739
+ this.#metrics.lastConnectError.clear();
740
+ const proceedingConnectErrorCount = this.#connectErrorCount;
741
+ this.#connectErrorCount = 0;
742
+ let timeToConnectMs;
743
+ let connectMsgLatencyMs;
744
+ if (this.#connectStart === void 0) lc.error?.("Got connected message but connect start time is undefined.");
745
+ else {
746
+ timeToConnectMs = now - this.#connectStart;
747
+ this.#metrics.timeToConnectMs.set(timeToConnectMs);
748
+ connectMsgLatencyMs = connectBody.timestamp !== void 0 ? now - connectBody.timestamp : void 0;
749
+ this.#connectStart = void 0;
750
+ }
751
+ let totalTimeToConnectMs;
752
+ if (this.#totalToConnectStart === void 0) lc.error?.("Got connected message but total to connect start time is undefined.");
753
+ else {
754
+ totalTimeToConnectMs = now - this.#totalToConnectStart;
755
+ this.#totalToConnectStart = void 0;
756
+ }
757
+ this.#metrics.setConnected(timeToConnectMs ?? 0, totalTimeToConnectMs ?? 0);
758
+ lc.info?.("Connected", {
759
+ navigatorOnline: localNavigator?.onLine,
760
+ timeToConnectMs,
761
+ totalTimeToConnectMs,
762
+ connectMsgLatencyMs,
763
+ connectedCount: this.#connectedCount,
764
+ proceedingConnectErrorCount
765
+ });
766
+ this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
767
+ lc.debug?.("Resolving connect resolver");
768
+ const socket = must(this.#socket);
769
+ const queriesPatch = await this.#rep.query((tx) => this.#queryManager.getQueriesPatch(tx, this.#initConnectionQueries));
770
+ const hasDeletedClients = () => skipEmptyArray(this.#deletedClients?.clientIDs) || skipEmptyArray(this.#deletedClients?.clientGroupIDs);
771
+ const maybeSendDeletedClients = () => {
772
+ if (hasDeletedClients()) {
773
+ send(socket, ["deleteClients", this.#deletedClients]);
774
+ this.#deletedClients = void 0;
775
+ }
776
+ };
777
+ if (queriesPatch.size > 0 && this.#initConnectionQueries !== void 0) {
778
+ maybeSendDeletedClients();
779
+ send(socket, ["changeDesiredQueries", { desiredQueriesPatch: [...queriesPatch.values()] }]);
780
+ } else if (this.#initConnectionQueries === void 0) {
781
+ const clientSchema = this.#clientSchema;
782
+ send(socket, ["initConnection", {
783
+ desiredQueriesPatch: [...queriesPatch.values()],
784
+ deleted: skipEmptyDeletedClients(this.#deletedClients),
785
+ ...this.#connectCookie === null ? { clientSchema } : {},
786
+ userPushURL: this.#options.mutateURL,
787
+ userPushHeaders: this.#options.mutateHeaders,
788
+ userQueryURL: this.#options.queryURL ?? this.#options.getQueriesURL,
789
+ userQueryHeaders: this.#options.queryHeaders
790
+ }]);
791
+ this.#deletedClients = void 0;
792
+ }
793
+ this.#initConnectionQueries = void 0;
794
+ maybeSendDeletedClients();
795
+ this.#connectionManager.connected();
796
+ this.#connectResolver.resolve();
797
+ }
798
+ /**
799
+ * Starts a new connection. This will create the WebSocket that does the HTTP
800
+ * request to the server.
801
+ *
802
+ * {@link #connect} will throw an assertion error if the
803
+ * {@link #connectionManager} status is not {@link ConnectionManagerState.Disconnected}
804
+ * or {@link ConnectionManagerState.Connecting}.
805
+ * Callers MUST check the connection status before calling this method and log
806
+ * an error as needed.
807
+ *
808
+ * The function will resolve once the socket is connected. If you need to know
809
+ * when a connection has been established, as in we have received the
810
+ * {@link ConnectedMessage}, you should await the {@link #connectResolver}
811
+ * promise. The {@link #connectResolver} promise rejects if an error message
812
+ * is received before the connected message is received or if the connection
813
+ * attempt times out.
814
+ */
815
+ async #connect(lc, additionalConnectParams) {
816
+ if (this.closed) return;
817
+ assert(this.#server, "No server provided");
818
+ assert(this.#connectionManager.is("disconnected") || this.#connectionManager.is("connecting"), "connect() called from invalid state: " + this.#connectionManager.state.name);
819
+ const wsid = nanoid();
820
+ lc = addWebSocketIDToLogContext(wsid, lc);
821
+ lc.info?.("Connecting...", { navigatorOnline: localNavigator?.onLine });
822
+ this.#connectionManager.connecting();
823
+ assert(this.#connectStart === void 0, "connect start time is defined");
824
+ const now = Date.now();
825
+ this.#connectStart = now;
826
+ if (this.#totalToConnectStart === void 0) this.#totalToConnectStart = now;
827
+ if (this.closed) return;
828
+ this.#connectCookie = parse(await this.#rep.cookie, nullableVersionSchema, "passthrough");
829
+ if (this.closed) return;
830
+ const timeoutID = setTimeout(() => {
831
+ lc.debug?.("Rejecting connect resolver due to timeout");
832
+ const timeoutError = new ClientError({
833
+ kind: ConnectTimeout,
834
+ message: `Connection attempt timed out after ${CONNECT_TIMEOUT_MS / 1e3} seconds`
835
+ });
836
+ this.#connectResolver.reject(timeoutError);
837
+ this.#disconnect(lc, timeoutError);
838
+ }, CONNECT_TIMEOUT_MS);
839
+ const abortHandler = () => {
840
+ clearTimeout(timeoutID);
841
+ };
842
+ this.#closeAbortController.signal.addEventListener("abort", abortHandler);
843
+ const [ws, initConnectionQueries, deletedClients] = await createSocket(this.#rep, this.#queryManager, this.#deleteClientsManager, toWSString(this.#server), this.#connectCookie, this.clientID, await this.clientGroupID, this.#clientSchema, this.userID, fromReplicacheAuthToken(this.#rep.auth), this.#lastMutationIDReceived, wsid, this.#options.logLevel === "debug", lc, this.#options.mutateURL, this.#options.mutateHeaders, this.#options.queryURL ?? this.#options.getQueriesURL, this.#options.queryHeaders, additionalConnectParams, await this.#activeClientsManager, this.#options.maxHeaderLength);
844
+ if (this.closed) return;
845
+ this.#initConnectionQueries = initConnectionQueries;
846
+ this.#deletedClients = deletedClients;
847
+ ws.addEventListener("message", this.#onMessage);
848
+ ws.addEventListener("open", this.#onOpen);
849
+ ws.addEventListener("close", this.#onClose);
850
+ this.#socket = ws;
851
+ this.#socketResolver.resolve(ws);
852
+ try {
853
+ lc.debug?.("Waiting for connection to be acknowledged");
854
+ await this.#connectResolver.promise;
855
+ this.#mutationTracker.onConnected(this.#lastMutationIDReceived);
856
+ this.#rep.push().catch(() => {});
857
+ } finally {
858
+ clearTimeout(timeoutID);
859
+ this.#closeAbortController.signal.removeEventListener("abort", abortHandler);
860
+ }
861
+ }
862
+ #disconnect(lc, reason, closeCode) {
863
+ if (shouldReportConnectError(reason)) {
864
+ this.#connectErrorCount++;
865
+ this.#metrics.lastConnectError.set(getLastConnectErrorValue(reason));
866
+ this.#metrics.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);
867
+ this.#metrics.setConnectError(reason);
868
+ if (this.#connectErrorCount % CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY === 1) this.#checkConnectivity(`connectErrorCount=${this.#connectErrorCount}`);
869
+ }
870
+ lc.info?.("disconnecting", {
871
+ navigatorOnline: localNavigator?.onLine,
872
+ reason: reason.kind,
873
+ connectStart: this.#connectStart,
874
+ totalToConnectStart: this.#totalToConnectStart,
875
+ connectedAt: this.#connectedAt,
876
+ connectionDuration: this.#connectedAt ? Date.now() - this.#connectedAt : 0,
877
+ messageCount: this.#messageCount,
878
+ connectionState: this.#connectionManager.state,
879
+ connectErrorCount: this.#connectErrorCount
880
+ });
881
+ const connectionStatus = this.#connectionManager.state.name;
882
+ switch (connectionStatus) {
883
+ case Connected:
884
+ if (this.#connectStart !== void 0) lc.error?.("disconnect() called while connected but connect start time is defined.");
885
+ break;
886
+ case Closed:
887
+ lc.debug?.("disconnect() called while closed");
888
+ return;
889
+ case Disconnected:
890
+ case Connecting:
891
+ case NeedsAuth:
892
+ case Error$1: break;
893
+ default: unreachable(connectionStatus);
894
+ }
895
+ this.#socketResolver = resolver();
896
+ lc.debug?.("Creating new connect resolver");
897
+ this.#connectResolver = resolver();
898
+ this.#messageCount = 0;
899
+ this.#connectStart = void 0;
900
+ this.#connectedAt = 0;
901
+ this.#socket?.removeEventListener("message", this.#onMessage);
902
+ this.#socket?.removeEventListener("open", this.#onOpen);
903
+ this.#socket?.removeEventListener("close", this.#onClose);
904
+ this.#socket?.close(closeCode);
905
+ this.#socket = void 0;
906
+ this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
907
+ this.#pokeHandler.handleDisconnect();
908
+ const transition = getErrorConnectionTransition(reason);
909
+ switch (transition.status) {
910
+ case NeedsAuth:
911
+ this.#connectionManager.needsAuth(transition.reason);
912
+ break;
913
+ case Error$1:
914
+ this.#connectionManager.error(transition.reason);
915
+ break;
916
+ case Disconnected:
917
+ this.#connectionManager.disconnected(transition.reason);
918
+ break;
919
+ case Closed:
920
+ this.#connectionManager.closed();
921
+ break;
922
+ case NO_STATUS_TRANSITION:
923
+ if (!this.#connectionManager.isInTerminalState()) this.#connectionManager.connecting(transition.reason);
924
+ break;
925
+ default: unreachable(transition);
926
+ }
927
+ }
928
+ #handlePokeStart(_lc, pokeMessage) {
929
+ this.#abortPingTimeout();
930
+ this.#pokeHandler.handlePokeStart(pokeMessage[1]);
931
+ }
932
+ #handlePokePart(_lc, pokeMessage) {
933
+ this.#abortPingTimeout();
934
+ const lastMutationIDChangeForSelf = this.#pokeHandler.handlePokePart(pokeMessage[1]);
935
+ if (lastMutationIDChangeForSelf !== void 0) this.#lastMutationIDReceived = lastMutationIDChangeForSelf;
936
+ }
937
+ #handlePokeEnd(_lc, pokeMessage) {
938
+ this.#abortPingTimeout();
939
+ this.#pokeHandler.handlePokeEnd(pokeMessage[1]);
940
+ }
941
+ #onPokeError(error) {
942
+ const lc = this.#lc;
943
+ lc.info?.("poke error, disconnecting?", !this.#connectionManager.is(Disconnected));
944
+ if (!this.#connectionManager.is("disconnected")) {
945
+ const errorStr = String(error);
946
+ const isBaseCookieError = errorStr.includes("unexpected base cookie");
947
+ this.#disconnect(lc, new ClientError({
948
+ kind: isBaseCookieError ? UnexpectedBaseCookie : Internal,
949
+ message: isBaseCookieError ? "Server returned unexpected base cookie during sync" : `Poke processing error: ${errorStr}`
950
+ }));
951
+ }
952
+ }
953
+ #handlePullResponse(lc, pullResponseMessage) {
954
+ this.#abortPingTimeout();
955
+ const body = pullResponseMessage[1];
956
+ lc = lc.withContext("requestID", body.requestID);
957
+ lc.debug?.("Handling pull response", body);
958
+ const resolver = this.#pendingPullsByRequestID.get(body.requestID);
959
+ if (!resolver) {
960
+ lc.debug?.("No resolver found");
961
+ return;
962
+ }
963
+ resolver.resolve(pullResponseMessage[1]);
964
+ }
965
+ async #pusher(req, requestID) {
966
+ assert(req.pushVersion === 1, "Expected pushVersion 1");
967
+ await this.#connectResolver.promise;
968
+ const lc = this.#lc.withContext("requestID", requestID);
969
+ lc.debug?.(`pushing ${req.mutations.length} mutations`);
970
+ const socket = this.#socket;
971
+ assert(socket, "Expected socket to be connected for push");
972
+ const isMutationRecoveryPush = req.clientGroupID !== await this.clientGroupID;
973
+ const start = isMutationRecoveryPush ? 0 : req.mutations.findIndex((m) => m.clientID === this.#lastMutationIDSent.clientID && m.id === this.#lastMutationIDSent.id) + 1;
974
+ lc.debug?.(isMutationRecoveryPush ? "pushing for recovery" : "pushing", req.mutations.length - start, "mutations of", req.mutations.length, "mutations.");
975
+ const now = Date.now();
976
+ for (let i = start; i < req.mutations.length; i++) {
977
+ const m = req.mutations[i];
978
+ const timestamp = now - Math.round(performance.now() - m.timestamp);
979
+ const zeroM = m.name === "_zero_crud" ? {
980
+ type: CRUD,
981
+ timestamp,
982
+ id: m.id,
983
+ clientID: m.clientID,
984
+ name: m.name,
985
+ args: [mapCRUD(m.args, this.#clientToServer)]
986
+ } : {
987
+ type: Custom,
988
+ timestamp,
989
+ id: m.id,
990
+ clientID: m.clientID,
991
+ name: m.name,
992
+ args: [m.args]
993
+ };
994
+ send(socket, ["push", {
995
+ timestamp: now,
996
+ clientGroupID: req.clientGroupID,
997
+ mutations: [zeroM],
998
+ pushVersion: req.pushVersion,
999
+ requestID
1000
+ }]);
1001
+ if (!isMutationRecoveryPush) this.#lastMutationIDSent = {
1002
+ clientID: m.clientID,
1003
+ id: m.id
1004
+ };
1005
+ }
1006
+ return { httpRequestInfo: {
1007
+ errorMessage: "",
1008
+ httpStatusCode: 200
1009
+ } };
1010
+ }
1011
+ async #runLoop() {
1012
+ this.#lc.info?.(`Starting Zero version: ${this.version}`);
1013
+ if (this.#server === null) {
1014
+ this.#lc.info?.("No socket origin provided, not starting connect loop.");
1015
+ this.#connectionManager.disconnected(new ClientError({
1016
+ kind: NoSocketOrigin,
1017
+ message: "No server socket origin provided"
1018
+ }));
1019
+ return;
1020
+ }
1021
+ let runLoopCounter = 0;
1022
+ const bareLogContext = this.#lc;
1023
+ const getLogContext = () => {
1024
+ let lc = bareLogContext;
1025
+ if (this.#socket) lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);
1026
+ return lc.withContext("runLoopCounter", runLoopCounter);
1027
+ };
1028
+ const { auth } = this.#options;
1029
+ this.#setAuth(auth);
1030
+ let backoffMs;
1031
+ let additionalConnectParams;
1032
+ while (this.#connectionManager.shouldContinueRunLoop()) {
1033
+ runLoopCounter++;
1034
+ let lc = getLogContext();
1035
+ backoffMs = RUN_LOOP_INTERVAL_MS;
1036
+ try {
1037
+ const currentState = this.#connectionManager.state;
1038
+ switch (currentState.name) {
1039
+ case Connecting:
1040
+ case Disconnected: {
1041
+ if (this.#visibilityWatcher.visibilityState === "hidden") {
1042
+ this.#metrics.setDisconnectedWaitingForVisible();
1043
+ this.#totalToConnectStart = void 0;
1044
+ }
1045
+ const visibilityResult = await promiseRace({
1046
+ visible: this.#visibilityWatcher.waitForVisible(),
1047
+ stateChange: this.#connectionManager.waitForStateChange()
1048
+ });
1049
+ if (visibilityResult.key === "stateChange") {
1050
+ throwIfConnectionError(visibilityResult.result);
1051
+ break;
1052
+ }
1053
+ if (reloadScheduled()) break;
1054
+ await this.#connect(lc, additionalConnectParams);
1055
+ additionalConnectParams = void 0;
1056
+ throwIfConnectionError(this.#connectionManager.state);
1057
+ assert(this.#socket, "Expected socket after reconnection");
1058
+ lc = getLogContext();
1059
+ lc.debug?.("Connected successfully");
1060
+ break;
1061
+ }
1062
+ case Connected: {
1063
+ const controller = new AbortController();
1064
+ this.#abortPingTimeout = () => controller.abort();
1065
+ const [pingTimeoutPromise, pingTimeoutAborted] = sleepWithAbort(this.pingTimeoutMs, controller.signal);
1066
+ const raceResult = await promiseRace({
1067
+ waitForPing: pingTimeoutPromise,
1068
+ waitForPingAborted: pingTimeoutAborted,
1069
+ tabHidden: this.#visibilityWatcher.waitForHidden(),
1070
+ stateChange: this.#connectionManager.waitForStateChange()
1071
+ });
1072
+ switch (raceResult.key) {
1073
+ case "waitForPing":
1074
+ await this.#ping(lc);
1075
+ break;
1076
+ case "waitForPingAborted": break;
1077
+ case "tabHidden": {
1078
+ const hiddenError = new ClientError({
1079
+ kind: Hidden,
1080
+ message: "Connection closed because tab was hidden"
1081
+ });
1082
+ this.#disconnect(lc, hiddenError);
1083
+ break;
1084
+ }
1085
+ case "stateChange":
1086
+ throwIfConnectionError(raceResult.result);
1087
+ break;
1088
+ default: unreachable(raceResult);
1089
+ }
1090
+ break;
1091
+ }
1092
+ case NeedsAuth:
1093
+ lc.info?.(`Run loop paused in needs-auth state. Call zero.connection.connect({auth}) to resume.`, currentState.reason);
1094
+ if ((await promiseRace({
1095
+ connectRequest: this.#connectionManager.waitForConnectRequest(),
1096
+ stateChange: this.#connectionManager.waitForStateChange()
1097
+ })).key === "connectRequest") this.#connectionManager.resumeFromConnectRequest();
1098
+ break;
1099
+ case Error$1:
1100
+ lc.info?.(`Run loop paused in error state. Call zero.connection.connect() to resume.`, currentState.reason);
1101
+ if ((await promiseRace({
1102
+ connectRequest: this.#connectionManager.waitForConnectRequest(),
1103
+ stateChange: this.#connectionManager.waitForStateChange()
1104
+ })).key === "connectRequest") this.#connectionManager.resumeFromConnectRequest();
1105
+ break;
1106
+ case Closed: break;
1107
+ default: unreachable(currentState);
1108
+ }
1109
+ } catch (ex) {
1110
+ const isClientClosedError = isClientError(ex) && ex.kind === "ClientClosed";
1111
+ if (!this.#connectionManager.is("connected") && !isClientClosedError) {
1112
+ const level = isAuthError(ex) ? "warn" : "error";
1113
+ const kind = isServerError(ex) ? ex.kind : "Unknown Error";
1114
+ lc[level]?.("Failed to connect", ex, kind, {
1115
+ lmid: this.#lastMutationIDReceived,
1116
+ baseCookie: this.#connectCookie
1117
+ });
1118
+ }
1119
+ lc.debug?.("Got an exception in the run loop", "state:", this.#connectionManager.state, "exception:", ex);
1120
+ const transition = getErrorConnectionTransition(ex);
1121
+ let sleepMs = void 0;
1122
+ switch (transition.status) {
1123
+ case NO_STATUS_TRANSITION: {
1124
+ const backoffParams = getBackoffParams(transition.reason);
1125
+ if (backoffParams) {
1126
+ if (backoffParams.minBackoffMs !== void 0) backoffMs = Math.max(backoffMs, backoffParams.minBackoffMs);
1127
+ if (backoffParams.maxBackoffMs !== void 0) backoffMs = Math.min(backoffMs, backoffParams.maxBackoffMs);
1128
+ additionalConnectParams = backoffParams.reconnectParams;
1129
+ }
1130
+ lc.debug?.("Sleeping", backoffMs, "ms before reconnecting due to error, state:", this.#connectionManager.state);
1131
+ sleepMs = backoffMs;
1132
+ break;
1133
+ }
1134
+ case NeedsAuth:
1135
+ lc.debug?.("Auth error encountered, transitioning to needs-auth state");
1136
+ this.#connectionManager.needsAuth(transition.reason);
1137
+ break;
1138
+ case Error$1:
1139
+ lc.debug?.("Fatal error encountered, transitioning to error state");
1140
+ this.#connectionManager.error(transition.reason);
1141
+ break;
1142
+ case Disconnected:
1143
+ this.#connectionManager.disconnected(transition.reason);
1144
+ break;
1145
+ case Closed: break;
1146
+ default: unreachable(transition);
1147
+ }
1148
+ if (transition.status !== "closed") try {
1149
+ this.#forceEnableRefresh = true;
1150
+ await this.#rep.runRefresh();
1151
+ } catch (ex) {
1152
+ if (ex instanceof AbortError) this.#lc.debug?.(`Refresh from storage did not complete before close.`);
1153
+ else this.#lc.error?.(`Error during refresh from storage`, ex);
1154
+ } finally {
1155
+ this.#forceEnableRefresh = false;
1156
+ }
1157
+ if (sleepMs) await sleep(sleepMs);
1158
+ }
1159
+ }
1160
+ }
1161
+ async #puller(req, requestID) {
1162
+ assert(req.pullVersion === 1, "Expected pullVersion 1");
1163
+ const lc = this.#lc.withContext("requestID", requestID);
1164
+ lc.debug?.("Pull", req);
1165
+ if (req.clientGroupID === await this.clientGroupID) return { httpRequestInfo: {
1166
+ errorMessage: "",
1167
+ httpStatusCode: 200
1168
+ } };
1169
+ await this.#connectResolver.promise;
1170
+ const socket = this.#socket;
1171
+ assert(socket, "Expected socket to be connected for mutation recovery pull");
1172
+ lc.debug?.("Pull is for mutation recovery");
1173
+ const cookie = parse(req.cookie, nullableVersionSchema, "passthrough");
1174
+ send(socket, ["pull", {
1175
+ clientGroupID: req.clientGroupID,
1176
+ cookie,
1177
+ requestID
1178
+ }]);
1179
+ const pullResponseResolver = resolver();
1180
+ this.#pendingPullsByRequestID.set(requestID, pullResponseResolver);
1181
+ try {
1182
+ const raceResult = await promiseRace({
1183
+ timeout: sleep(PULL_TIMEOUT_MS),
1184
+ success: pullResponseResolver.promise
1185
+ });
1186
+ switch (raceResult.key) {
1187
+ case "timeout":
1188
+ lc.debug?.("Mutation recovery pull timed out");
1189
+ throw new ClientError({
1190
+ kind: PullTimeout,
1191
+ message: "Pull timed out"
1192
+ });
1193
+ case "success": {
1194
+ lc.debug?.("Returning mutation recovery pull response");
1195
+ const response = await pullResponseResolver.promise;
1196
+ return {
1197
+ response: {
1198
+ cookie: response.cookie,
1199
+ lastMutationIDChanges: response.lastMutationIDChanges,
1200
+ patch: []
1201
+ },
1202
+ httpRequestInfo: {
1203
+ errorMessage: "",
1204
+ httpStatusCode: 200
1205
+ }
1206
+ };
1207
+ }
1208
+ default: unreachable(raceResult);
1209
+ }
1210
+ } finally {
1211
+ pullResponseResolver.reject(new ClientError({
1212
+ kind: PullTimeout,
1213
+ message: "Pull timed out"
1214
+ }));
1215
+ this.#pendingPullsByRequestID.delete(requestID);
1216
+ }
1217
+ }
1218
+ /**
1219
+ * Sets the authentication token on the replicache instance.
1220
+ *
1221
+ * @param auth - The authentication token to set.
1222
+ */
1223
+ #setAuth(auth) {
1224
+ this.#rep.auth = toReplicacheAuthToken(auth);
1225
+ if (auth) this.#send(["updateAuth", { auth }]);
1226
+ }
1227
+ /**
1228
+ * A rough heuristic for whether the client is currently online and
1229
+ * authenticated.
1230
+ *
1231
+ * @deprecated Use `connection` instead, which provides more detailed connection state.
1232
+ */
1233
+ get online() {
1234
+ return this.#onlineManager.online;
1235
+ }
1236
+ /**
1237
+ * Subscribe to online status changes.
1238
+ *
1239
+ * This is useful when you want to update state based on the online status.
1240
+ *
1241
+ * @param listener - The listener to subscribe to.
1242
+ * @returns A function to unsubscribe the listener.
1243
+ *
1244
+ * @deprecated Use `connection` instead, which provides more detailed connection state.
1245
+ */
1246
+ onOnline = (listener) => this.#onlineManager.subscribe(listener);
1247
+ /**
1248
+ * Starts a ping and waits for a pong.
1249
+ */
1250
+ async #ping(lc) {
1251
+ lc.debug?.("pinging");
1252
+ const { promise, resolve } = resolver();
1253
+ this.#onPong = resolve;
1254
+ const pingMessage = ["ping", {}];
1255
+ const t0 = performance.now();
1256
+ assert(this.#socket, "Expected socket to be connected for ping");
1257
+ send(this.#socket, pingMessage);
1258
+ const raceResult = await promiseRace({
1259
+ waitForPong: promise,
1260
+ pingTimeout: sleep(this.pingTimeoutMs),
1261
+ stateChange: this.#connectionManager.waitForStateChange()
1262
+ });
1263
+ const delta = performance.now() - t0;
1264
+ switch (raceResult.key) {
1265
+ case "waitForPong":
1266
+ lc.debug?.("ping succeeded in", delta, "ms");
1267
+ return;
1268
+ case "pingTimeout": {
1269
+ lc.info?.("ping failed in", delta, "ms - disconnecting");
1270
+ const pingTimeoutError = new ClientError({
1271
+ kind: PingTimeout,
1272
+ message: "Server ping request failed"
1273
+ });
1274
+ this.#disconnect(lc, pingTimeoutError);
1275
+ throw pingTimeoutError;
1276
+ }
1277
+ case "stateChange":
1278
+ lc.debug?.("ping aborted due to connection state change", raceResult.result);
1279
+ throwIfConnectionError(raceResult.result);
1280
+ break;
1281
+ default: unreachable(raceResult);
1282
+ }
1283
+ }
1284
+ async #reportMetrics(_allSeries) {}
1285
+ #checkConnectivity(reason) {
1286
+ this.#checkConnectivityAsync(reason);
1287
+ }
1288
+ #checkConnectivityAsync(_reason) {}
1289
+ /**
1290
+ * `inspector` is an object that can be used to inspect the state of the
1291
+ * queries a Zero instance uses. It is intended for debugging purposes.
1292
+ */
1293
+ get inspector() {
1294
+ BUNDLE_SIZE: return this.#inspector ??= new Inspector(this.#rep, this.#queryManager, this.#zeroContext, async () => {
1295
+ await this.#connectResolver.promise;
1296
+ return must(this.#socket);
1297
+ });
1298
+ }
1299
+ async delete() {
1300
+ await this.close();
1301
+ const idbDatabasesStore = new IDBDatabasesStore(getKVStoreProvider(this.#lc, this.#kvStore).create);
1302
+ try {
1303
+ const databases = await idbDatabasesStore.getDatabases();
1304
+ const dbNamesToDelete = Object.values(databases).filter((database) => database.replicacheName === this.#rep.name).map((database) => database.name);
1305
+ const deleteResults = await Promise.allSettled(dbNamesToDelete.map(async (dbName) => {
1306
+ await dropDatabase(dbName, { kvStore: this.#kvStore });
1307
+ return dbName;
1308
+ }));
1309
+ const deleted = [];
1310
+ const errors = [];
1311
+ for (const result of deleteResults) if (result.status === "fulfilled") deleted.push(result.value);
1312
+ else errors.push(result.reason);
1313
+ return {
1314
+ deleted,
1315
+ errors
1316
+ };
1317
+ } finally {
1318
+ await idbDatabasesStore.close();
1319
+ }
1320
+ }
1321
+ #addMetric = (metric, value, ...args) => {
1322
+ assert(isClientMetric(metric), `Invalid metric: ${metric}`);
1323
+ this.#queryManager.addMetric(metric, value, ...args);
1324
+ };
1325
+ };
1326
+ var OnlineManager = class extends Subscribable {
1327
+ #online = false;
1328
+ setOnline(online) {
1329
+ if (this.#online === online) return;
1330
+ this.#online = online;
1331
+ this.notify(online);
1332
+ }
1333
+ get online() {
1334
+ return this.#online;
1335
+ }
1336
+ };
1743
1337
  async function createSocket(rep, queryManager, deleteClientsManager, socketOrigin, baseCookie, clientID, clientGroupID, clientSchema, userID, auth, lmid, wsid, debugPerf, lc, userPushURL, userPushHeaders, userQueryURL, userQueryHeaders, additionalConnectParams, activeClientsManager, maxHeaderLength = 1024 * 8) {
1744
- const url = await createConnectionURL(
1745
- socketOrigin,
1746
- clientID,
1747
- clientGroupID,
1748
- userID,
1749
- baseCookie,
1750
- lmid,
1751
- wsid,
1752
- rep,
1753
- debugPerf,
1754
- additionalConnectParams,
1755
- lc
1756
- );
1757
- const WS = mustGetBrowserGlobal("WebSocket");
1758
- const queriesPatchP = rep.query((tx) => queryManager.getQueriesPatch(tx));
1759
- const deletedClientsArray = await deleteClientsManager.getDeletedClients();
1760
- let deletedClients = convertDeletedClientsToBody(deletedClientsArray, clientGroupID);
1761
- let queriesPatch = await queriesPatchP;
1762
- const { activeClients } = activeClientsManager;
1763
- let secProtocol = encodeSecProtocols(
1764
- [
1765
- "initConnection",
1766
- {
1767
- desiredQueriesPatch: [...queriesPatch.values()],
1768
- deleted: skipEmptyDeletedClients(deletedClients),
1769
- // The clientSchema only needs to be sent for the very first request.
1770
- // Henceforth it is stored with the CVR and verified automatically.
1771
- ...baseCookie === null ? { clientSchema } : {},
1772
- userPushURL,
1773
- userPushHeaders,
1774
- userQueryURL,
1775
- userQueryHeaders,
1776
- activeClients: [...activeClients]
1777
- }
1778
- ],
1779
- auth
1780
- );
1781
- if (secProtocol.length > maxHeaderLength) {
1782
- secProtocol = encodeSecProtocols(void 0, auth);
1783
- if (secProtocol.length > maxHeaderLength) {
1784
- lc.warn?.(
1785
- `Encoded auth token length (${secProtocol.length}) exceeds ZeroOptions.maxHeaderLength (${maxHeaderLength}). This may cause connection failures.`
1786
- );
1787
- }
1788
- queriesPatch = void 0;
1789
- } else {
1790
- deletedClients = void 0;
1791
- }
1792
- return [
1793
- new WS(
1794
- // toString() required for RN URL polyfill.
1795
- url.toString(),
1796
- secProtocol
1797
- ),
1798
- queriesPatch,
1799
- skipEmptyDeletedClients(deletedClients)
1800
- ];
1338
+ const url = await createConnectionURL(socketOrigin, clientID, clientGroupID, userID, baseCookie, lmid, wsid, rep, debugPerf, additionalConnectParams, lc);
1339
+ const WS = mustGetBrowserGlobal("WebSocket");
1340
+ const queriesPatchP = rep.query((tx) => queryManager.getQueriesPatch(tx));
1341
+ let deletedClients = convertDeletedClientsToBody(await deleteClientsManager.getDeletedClients(), clientGroupID);
1342
+ let queriesPatch = await queriesPatchP;
1343
+ const { activeClients } = activeClientsManager;
1344
+ let secProtocol = encodeSecProtocols(["initConnection", {
1345
+ desiredQueriesPatch: [...queriesPatch.values()],
1346
+ deleted: skipEmptyDeletedClients(deletedClients),
1347
+ ...baseCookie === null ? { clientSchema } : {},
1348
+ userPushURL,
1349
+ userPushHeaders,
1350
+ userQueryURL,
1351
+ userQueryHeaders,
1352
+ activeClients: [...activeClients]
1353
+ }], auth);
1354
+ if (secProtocol.length > maxHeaderLength) {
1355
+ secProtocol = encodeSecProtocols(void 0, auth);
1356
+ if (secProtocol.length > maxHeaderLength) lc.warn?.(`Encoded auth token length (${secProtocol.length}) exceeds ZeroOptions.maxHeaderLength (${maxHeaderLength}). This may cause connection failures.`);
1357
+ queriesPatch = void 0;
1358
+ } else deletedClients = void 0;
1359
+ return [
1360
+ new WS(url.toString(), secProtocol),
1361
+ queriesPatch,
1362
+ skipEmptyDeletedClients(deletedClients)
1363
+ ];
1801
1364
  }
1802
1365
  async function createConnectionURL(socketOrigin, clientID, clientGroupID, userID, baseCookie, lmid, wsid, rep, debugPerf, additionalConnectParams, lc) {
1803
- const url = new URL(
1804
- appendPath(socketOrigin, `/sync/v${PROTOCOL_VERSION}/connect`)
1805
- );
1806
- const { searchParams } = url;
1807
- searchParams.set("clientID", clientID);
1808
- searchParams.set("clientGroupID", clientGroupID);
1809
- searchParams.set("userID", userID);
1810
- searchParams.set("baseCookie", baseCookie === null ? "" : String(baseCookie));
1811
- searchParams.set("ts", String(performance.now()));
1812
- searchParams.set("lmid", String(lmid));
1813
- searchParams.set("wsid", wsid);
1814
- searchParams.set("profileID", await rep.profileID);
1815
- if (debugPerf) {
1816
- searchParams.set("debugPerf", true.toString());
1817
- }
1818
- if (additionalConnectParams) {
1819
- for (const k in additionalConnectParams) {
1820
- if (searchParams.has(k)) {
1821
- lc.warn?.(`skipping conflicting parameter ${k}`);
1822
- } else {
1823
- searchParams.set(k, additionalConnectParams[k]);
1824
- }
1825
- }
1826
- }
1827
- lc.info?.("Connecting to", url.toString());
1828
- return url;
1366
+ const url = new URL(appendPath(socketOrigin, `/sync/v49/connect`));
1367
+ const { searchParams } = url;
1368
+ searchParams.set("clientID", clientID);
1369
+ searchParams.set("clientGroupID", clientGroupID);
1370
+ searchParams.set("userID", userID);
1371
+ searchParams.set("baseCookie", baseCookie === null ? "" : String(baseCookie));
1372
+ searchParams.set("ts", String(performance.now()));
1373
+ searchParams.set("lmid", String(lmid));
1374
+ searchParams.set("wsid", wsid);
1375
+ searchParams.set("profileID", await rep.profileID);
1376
+ if (debugPerf) searchParams.set("debugPerf", true.toString());
1377
+ if (additionalConnectParams) for (const k in additionalConnectParams) if (searchParams.has(k)) lc.warn?.(`skipping conflicting parameter ${k}`);
1378
+ else searchParams.set(k, additionalConnectParams[k]);
1379
+ lc.info?.("Connecting to", url.toString());
1380
+ return url;
1829
1381
  }
1830
1382
  function skipEmptyArray(arr) {
1831
- return arr && arr.length > 0 ? arr : void 0;
1383
+ return arr && arr.length > 0 ? arr : void 0;
1832
1384
  }
1833
1385
  function skipEmptyDeletedClients(deletedClients) {
1834
- if (!deletedClients) {
1835
- return void 0;
1836
- }
1837
- const { clientIDs, clientGroupIDs } = deletedClients;
1838
- if ((!clientIDs || clientIDs.length === 0) && (!clientGroupIDs || clientGroupIDs.length === 0)) {
1839
- return void 0;
1840
- }
1841
- const data = {};
1842
- data.clientIDs = skipEmptyArray(clientIDs);
1843
- data.clientGroupIDs = skipEmptyArray(clientGroupIDs);
1844
- return data;
1386
+ if (!deletedClients) return;
1387
+ const { clientIDs, clientGroupIDs } = deletedClients;
1388
+ if ((!clientIDs || clientIDs.length === 0) && (!clientGroupIDs || clientGroupIDs.length === 0)) return;
1389
+ const data = {};
1390
+ data.clientIDs = skipEmptyArray(clientIDs);
1391
+ data.clientGroupIDs = skipEmptyArray(clientGroupIDs);
1392
+ return data;
1845
1393
  }
1846
1394
  function convertDeletedClientsToBody(deletedClients, clientGroupID) {
1847
- if (deletedClients.length === 0) {
1848
- return void 0;
1849
- }
1850
- const clientIDs = deletedClients.filter((pair) => pair.clientID && pair.clientGroupID === clientGroupID).map((pair) => pair.clientID);
1851
- if (clientIDs.length === 0) {
1852
- return void 0;
1853
- }
1854
- return { clientIDs };
1395
+ if (deletedClients.length === 0) return;
1396
+ const clientIDs = deletedClients.filter((pair) => pair.clientID && pair.clientGroupID === clientGroupID).map((pair) => pair.clientID);
1397
+ if (clientIDs.length === 0) return;
1398
+ return { clientIDs };
1855
1399
  }
1400
+ /**
1401
+ * Adds the wsid query parameter to the log context. If the URL does not
1402
+ * have a wsid we use a randomID instead.
1403
+ */
1856
1404
  function addWebSocketIDFromSocketToLogContext({ url }, lc) {
1857
- const wsid = new URL(url).searchParams.get("wsid") ?? nanoid();
1858
- return addWebSocketIDToLogContext(wsid, lc);
1405
+ return addWebSocketIDToLogContext(new URL(url).searchParams.get("wsid") ?? nanoid(), lc);
1859
1406
  }
1860
1407
  function addWebSocketIDToLogContext(wsid, lc) {
1861
- return lc.withContext("wsid", wsid);
1862
- }
1863
- function assertValidRunOptions(_options) {
1408
+ return lc.withContext("wsid", wsid);
1864
1409
  }
1410
+ function assertValidRunOptions(_options) {}
1865
1411
  async function makeActiveClientsManager(clientGroupID, clientID, signal, onDelete) {
1866
- const manager = await ActiveClientsManager.create(
1867
- await clientGroupID,
1868
- clientID,
1869
- signal
1870
- );
1871
- manager.onDelete = onDelete;
1872
- return manager;
1412
+ const manager = await ActiveClientsManager.create(await clientGroupID, clientID, signal);
1413
+ manager.onDelete = onDelete;
1414
+ return manager;
1873
1415
  }
1874
- export {
1875
- CONNECT_TIMEOUT_MS,
1876
- DEFAULT_DISCONNECT_HIDDEN_DELAY_MS,
1877
- DEFAULT_DISCONNECT_TIMEOUT_MS,
1878
- DEFAULT_PING_TIMEOUT_MS,
1879
- OnlineManager,
1880
- PULL_TIMEOUT_MS,
1881
- RUN_LOOP_INTERVAL_MS,
1882
- Zero,
1883
- createConnectionURL,
1884
- createSocket
1885
- };
1886
- //# sourceMappingURL=zero.js.map
1416
+ //#endregion
1417
+ export { Zero };
1418
+
1419
+ //# sourceMappingURL=zero.js.map