@rocicorp/zero 1.6.0-canary.12 → 1.6.0-canary.13

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 (551) hide show
  1. package/README.md +3 -28
  2. package/out/_virtual/{_@oxc-project_runtime@0.130.0 → _@oxc-project_runtime@0.122.0}/helpers/usingCtx.js +1 -1
  3. package/out/analyze-query/src/analyze-cli.js +3 -3
  4. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  5. package/out/analyze-query/src/bin-analyze.js +1 -6
  6. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  7. package/out/analyze-query/src/bin-transform.js.map +1 -1
  8. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  9. package/out/ast-to-zql/src/bin.js.map +1 -1
  10. package/out/ast-to-zql/src/format.js.map +1 -1
  11. package/out/datadog/src/datadog-log-sink.js.map +1 -1
  12. package/out/otel/src/enabled.js.map +1 -1
  13. package/out/otel/src/log-options.js.map +1 -1
  14. package/out/otel/src/maybe-time.js.map +1 -1
  15. package/out/otel/src/span.js.map +1 -1
  16. package/out/replicache/src/async-iterable-to-array.js.map +1 -1
  17. package/out/replicache/src/bg-interval.js.map +1 -1
  18. package/out/replicache/src/btree/diff.js.map +1 -1
  19. package/out/replicache/src/btree/node.js.map +1 -1
  20. package/out/replicache/src/btree/read.js.map +1 -1
  21. package/out/replicache/src/btree/splice.js.map +1 -1
  22. package/out/replicache/src/btree/write.js +3 -6
  23. package/out/replicache/src/btree/write.js.map +1 -1
  24. package/out/replicache/src/call-default-fetch.js.map +1 -1
  25. package/out/replicache/src/connection-loop-delegates.js.map +1 -1
  26. package/out/replicache/src/connection-loop.js.map +1 -1
  27. package/out/replicache/src/cookies.js.map +1 -1
  28. package/out/replicache/src/dag/chunk.js.map +1 -1
  29. package/out/replicache/src/dag/gc.js.map +1 -1
  30. package/out/replicache/src/dag/key.js.map +1 -1
  31. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  32. package/out/replicache/src/dag/store-impl.js.map +1 -1
  33. package/out/replicache/src/dag/store.js.map +1 -1
  34. package/out/replicache/src/dag/visitor.js.map +1 -1
  35. package/out/replicache/src/db/commit.js.map +1 -1
  36. package/out/replicache/src/db/index.js.map +1 -1
  37. package/out/replicache/src/db/read.js.map +1 -1
  38. package/out/replicache/src/db/rebase.js.map +1 -1
  39. package/out/replicache/src/db/write.js.map +1 -1
  40. package/out/replicache/src/deleted-clients.js.map +1 -1
  41. package/out/replicache/src/error-responses.js.map +1 -1
  42. package/out/replicache/src/frozen-json.js.map +1 -1
  43. package/out/replicache/src/get-default-puller.js.map +1 -1
  44. package/out/replicache/src/get-default-pusher.js.map +1 -1
  45. package/out/replicache/src/get-kv-store-provider.js.map +1 -1
  46. package/out/replicache/src/hash.js.map +1 -1
  47. package/out/replicache/src/http-request-info.js.map +1 -1
  48. package/out/replicache/src/index-defs.js.map +1 -1
  49. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  50. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  51. package/out/replicache/src/kv/idb-store.js.map +1 -1
  52. package/out/replicache/src/kv/mem-store.js.map +1 -1
  53. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  54. package/out/replicache/src/kv/read-impl.js.map +1 -1
  55. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  56. package/out/replicache/src/kv/sqlite-store.js +1 -4
  57. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  58. package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
  59. package/out/replicache/src/kv/write-impl-base.js.map +1 -1
  60. package/out/replicache/src/kv/write-impl.js.map +1 -1
  61. package/out/replicache/src/lazy.js.map +1 -1
  62. package/out/replicache/src/log-options.js.map +1 -1
  63. package/out/replicache/src/make-idb-name.js.map +1 -1
  64. package/out/replicache/src/new-client-channel.js.map +1 -1
  65. package/out/replicache/src/on-persist-channel.js.map +1 -1
  66. package/out/replicache/src/patch-operation.js.map +1 -1
  67. package/out/replicache/src/pending-mutations.js.map +1 -1
  68. package/out/replicache/src/persist/client-gc.js.map +1 -1
  69. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  70. package/out/replicache/src/persist/client-groups.js +0 -40
  71. package/out/replicache/src/persist/client-groups.js.map +1 -1
  72. package/out/replicache/src/persist/clients.js +0 -28
  73. package/out/replicache/src/persist/clients.js.map +1 -1
  74. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  75. package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
  76. package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
  77. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  78. package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
  79. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  80. package/out/replicache/src/persist/make-client-id.js.map +1 -1
  81. package/out/replicache/src/persist/persist.js.map +1 -1
  82. package/out/replicache/src/persist/refresh.js.map +1 -1
  83. package/out/replicache/src/process-scheduler.js.map +1 -1
  84. package/out/replicache/src/pusher.js.map +1 -1
  85. package/out/replicache/src/replicache-impl.js.map +1 -1
  86. package/out/replicache/src/report-error.js.map +1 -1
  87. package/out/replicache/src/request-idle.js.map +1 -1
  88. package/out/replicache/src/scan-iterator.js.map +1 -1
  89. package/out/replicache/src/scan-options.js.map +1 -1
  90. package/out/replicache/src/set-interval-with-signal.js.map +1 -1
  91. package/out/replicache/src/subscriptions.js.map +1 -1
  92. package/out/replicache/src/sync/diff.js.map +1 -1
  93. package/out/replicache/src/sync/ids.js.map +1 -1
  94. package/out/replicache/src/sync/patch.js.map +1 -1
  95. package/out/replicache/src/sync/pull-error.js.map +1 -1
  96. package/out/replicache/src/sync/pull.js.map +1 -1
  97. package/out/replicache/src/sync/push.js.map +1 -1
  98. package/out/replicache/src/sync/request-id.js.map +1 -1
  99. package/out/replicache/src/to-error.js.map +1 -1
  100. package/out/replicache/src/transaction-closed-error.js.map +1 -1
  101. package/out/replicache/src/transactions.js.map +1 -1
  102. package/out/replicache/src/with-transactions.js.map +1 -1
  103. package/out/shared/src/abort-error.js.map +1 -1
  104. package/out/shared/src/arrays.js.map +1 -1
  105. package/out/shared/src/asserts.js.map +1 -1
  106. package/out/shared/src/bigint-json.js.map +1 -1
  107. package/out/shared/src/binary-search.js.map +1 -1
  108. package/out/shared/src/broadcast-channel.js.map +1 -1
  109. package/out/shared/src/browser-env.js.map +1 -1
  110. package/out/shared/src/btree-set.js.map +1 -1
  111. package/out/shared/src/cache.js.map +1 -1
  112. package/out/shared/src/centroid.js.map +1 -1
  113. package/out/shared/src/custom-key-map.js.map +1 -1
  114. package/out/shared/src/custom-key-set.js.map +1 -1
  115. package/out/shared/src/deep-clone.js.map +1 -1
  116. package/out/shared/src/deep-merge.js.map +1 -1
  117. package/out/shared/src/document-visible.js.map +1 -1
  118. package/out/shared/src/dotenv.js.map +1 -1
  119. package/out/shared/src/error.js.map +1 -1
  120. package/out/shared/src/hash.js.map +1 -1
  121. package/out/shared/src/iterables.d.ts +0 -2
  122. package/out/shared/src/iterables.d.ts.map +1 -1
  123. package/out/shared/src/iterables.js +1 -9
  124. package/out/shared/src/iterables.js.map +1 -1
  125. package/out/shared/src/json-schema.js.map +1 -1
  126. package/out/shared/src/json.js.map +1 -1
  127. package/out/shared/src/logging-test-utils.js.map +1 -1
  128. package/out/shared/src/logging.js.map +1 -1
  129. package/out/shared/src/map.js.map +1 -1
  130. package/out/shared/src/must.js.map +1 -1
  131. package/out/shared/src/object-traversal.js.map +1 -1
  132. package/out/shared/src/objects.js.map +1 -1
  133. package/out/shared/src/options.js.map +1 -1
  134. package/out/shared/src/parse-big-int.js.map +1 -1
  135. package/out/shared/src/promise-race.js.map +1 -1
  136. package/out/shared/src/queue.d.ts.map +1 -1
  137. package/out/shared/src/queue.js +21 -15
  138. package/out/shared/src/queue.js.map +1 -1
  139. package/out/shared/src/rand.js.map +1 -1
  140. package/out/shared/src/random-uint64.js.map +1 -1
  141. package/out/shared/src/random-values.js.map +1 -1
  142. package/out/shared/src/record-proxy.js.map +1 -1
  143. package/out/shared/src/resolved-promises.js.map +1 -1
  144. package/out/shared/src/sentinels.js.map +1 -1
  145. package/out/shared/src/set-utils.js.map +1 -1
  146. package/out/shared/src/size-of-value.js.map +1 -1
  147. package/out/shared/src/sleep.js.map +1 -1
  148. package/out/shared/src/sorted-entries.js.map +1 -1
  149. package/out/shared/src/string-compare.js.map +1 -1
  150. package/out/shared/src/subscribable.js.map +1 -1
  151. package/out/shared/src/tdigest-schema.js.map +1 -1
  152. package/out/shared/src/tdigest.js.map +1 -1
  153. package/out/shared/src/valita.js.map +1 -1
  154. package/out/z2s/src/compiler.js.map +1 -1
  155. package/out/z2s/src/sql.js.map +1 -1
  156. package/out/zero/package.js +26 -34
  157. package/out/zero/package.js.map +1 -1
  158. package/out/zero/src/build-schema.js.map +1 -1
  159. package/out/zero/src/zero-cache-dev.js.map +1 -1
  160. package/out/zero/src/zero-out.js.map +1 -1
  161. package/out/zero-cache/src/auth/auth.js.map +1 -1
  162. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  163. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  164. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  165. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  166. package/out/zero-cache/src/config/network.js.map +1 -1
  167. package/out/zero-cache/src/config/normalize.js.map +1 -1
  168. package/out/zero-cache/src/config/server-context.js.map +1 -1
  169. package/out/zero-cache/src/config/zero-config.js +0 -5
  170. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  171. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  172. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  173. package/out/zero-cache/src/db/create.js.map +1 -1
  174. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  175. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  176. package/out/zero-cache/src/db/migration-lite.js +0 -19
  177. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  178. package/out/zero-cache/src/db/migration.js +0 -19
  179. package/out/zero-cache/src/db/migration.js.map +1 -1
  180. package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -1
  181. package/out/zero-cache/src/db/pg-copy.js.map +1 -1
  182. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  183. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  184. package/out/zero-cache/src/db/run-transaction.js.map +1 -1
  185. package/out/zero-cache/src/db/specs.js.map +1 -1
  186. package/out/zero-cache/src/db/statements.js.map +1 -1
  187. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  188. package/out/zero-cache/src/db/warmup.js.map +1 -1
  189. package/out/zero-cache/src/observability/events.js.map +1 -1
  190. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  191. package/out/zero-cache/src/scripts/decommission.js.map +1 -1
  192. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  193. package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
  194. package/out/zero-cache/src/scripts/permissions.js +2 -1
  195. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  196. package/out/zero-cache/src/server/anonymous-otel-start.js +7 -8
  197. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  198. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  199. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  200. package/out/zero-cache/src/server/logging.js.map +1 -1
  201. package/out/zero-cache/src/server/main.js.map +1 -1
  202. package/out/zero-cache/src/server/mutator.js.map +1 -1
  203. package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
  204. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  205. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  206. package/out/zero-cache/src/server/priority-op.js.map +1 -1
  207. package/out/zero-cache/src/server/reaper.js.map +1 -1
  208. package/out/zero-cache/src/server/replicator.js.map +1 -1
  209. package/out/zero-cache/src/server/runner/main.js.map +1 -1
  210. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  211. package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
  212. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  213. package/out/zero-cache/src/server/shadow-syncer.js.map +1 -1
  214. package/out/zero-cache/src/server/syncer.js.map +1 -1
  215. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  216. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  217. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  218. package/out/zero-cache/src/services/analyze.js +2 -5
  219. package/out/zero-cache/src/services/analyze.js.map +1 -1
  220. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  221. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  222. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  223. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  224. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
  225. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  226. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  227. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  228. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  229. package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
  230. package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
  231. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  232. package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
  233. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  234. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  235. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  236. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  237. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  238. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  239. package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
  240. package/out/zero-cache/src/services/change-source/protocol/current/data.js +0 -2
  241. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  242. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
  243. package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -1
  244. package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
  245. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  246. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  247. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  248. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  249. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  250. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  251. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  252. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -1
  253. package/out/zero-cache/src/services/change-streamer/schema/init.js +25 -21
  254. package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
  255. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  256. package/out/zero-cache/src/services/change-streamer/snapshot.js +0 -15
  257. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  258. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  259. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  260. package/out/zero-cache/src/services/heapz.js.map +1 -1
  261. package/out/zero-cache/src/services/http-service.js.map +1 -1
  262. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  263. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
  264. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  265. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  266. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  267. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  268. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  269. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  270. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  271. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  272. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  273. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  274. package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -1
  275. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  276. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  277. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  278. package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
  279. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  280. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  281. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  282. package/out/zero-cache/src/services/run-ast.js +0 -1
  283. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  284. package/out/zero-cache/src/services/runner.js.map +1 -1
  285. package/out/zero-cache/src/services/running-state.js.map +1 -1
  286. package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js.map +1 -1
  287. package/out/zero-cache/src/services/statz.js.map +1 -1
  288. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
  289. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  290. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
  291. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  292. package/out/zero-cache/src/services/view-syncer/cvr-purger.d.ts.map +1 -1
  293. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +1 -2
  294. package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
  295. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  296. package/out/zero-cache/src/services/view-syncer/cvr-store.js +1 -2
  297. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  298. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  299. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  300. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +14 -0
  301. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  302. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +25 -2
  303. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  304. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  305. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  306. package/out/zero-cache/src/services/view-syncer/row-set-signature.js.map +1 -1
  307. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  308. package/out/zero-cache/src/services/view-syncer/schema/init.js +113 -97
  309. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  310. package/out/zero-cache/src/services/view-syncer/schema/types.js +1 -103
  311. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  312. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  313. package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -1
  314. package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
  315. package/out/zero-cache/src/services/view-syncer/view-syncer.js +1 -4
  316. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  317. package/out/zero-cache/src/types/configuration-error.js.map +1 -1
  318. package/out/zero-cache/src/types/error-with-level.js.map +1 -1
  319. package/out/zero-cache/src/types/http.js.map +1 -1
  320. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  321. package/out/zero-cache/src/types/lite.js.map +1 -1
  322. package/out/zero-cache/src/types/names.js.map +1 -1
  323. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  324. package/out/zero-cache/src/types/pg.js.map +1 -1
  325. package/out/zero-cache/src/types/processes.js.map +1 -1
  326. package/out/zero-cache/src/types/profiler.js.map +1 -1
  327. package/out/zero-cache/src/types/row-key.js.map +1 -1
  328. package/out/zero-cache/src/types/shards.js.map +1 -1
  329. package/out/zero-cache/src/types/sql.js.map +1 -1
  330. package/out/zero-cache/src/types/state-version.js.map +1 -1
  331. package/out/zero-cache/src/types/streams.js.map +1 -1
  332. package/out/zero-cache/src/types/strings.js.map +1 -1
  333. package/out/zero-cache/src/types/subscription.js.map +1 -1
  334. package/out/zero-cache/src/types/timeout.js.map +1 -1
  335. package/out/zero-cache/src/types/url-params.js.map +1 -1
  336. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  337. package/out/zero-cache/src/types/ws.js.map +1 -1
  338. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  339. package/out/zero-cache/src/workers/connection.js.map +1 -1
  340. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  341. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  342. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  343. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  344. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  345. package/out/zero-client/src/client/connection-manager.js +1 -2
  346. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  347. package/out/zero-client/src/client/connection.js.map +1 -1
  348. package/out/zero-client/src/client/context.js.map +1 -1
  349. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  350. package/out/zero-client/src/client/crud.js.map +1 -1
  351. package/out/zero-client/src/client/custom.js +1 -2
  352. package/out/zero-client/src/client/custom.js.map +1 -1
  353. package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
  354. package/out/zero-client/src/client/enable-analytics.js.map +1 -1
  355. package/out/zero-client/src/client/error.js.map +1 -1
  356. package/out/zero-client/src/client/http-string.js.map +1 -1
  357. package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
  358. package/out/zero-client/src/client/inspector/client.js.map +1 -1
  359. package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
  360. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  361. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  362. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  363. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  364. package/out/zero-client/src/client/keys.js.map +1 -1
  365. package/out/zero-client/src/client/log-options.js.map +1 -1
  366. package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
  367. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  368. package/out/zero-client/src/client/metrics.js.map +1 -1
  369. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  370. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  371. package/out/zero-client/src/client/options.js.map +1 -1
  372. package/out/zero-client/src/client/query-manager.js.map +1 -1
  373. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  374. package/out/zero-client/src/client/server-option.js.map +1 -1
  375. package/out/zero-client/src/client/version.js +1 -1
  376. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  377. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  378. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  379. package/out/zero-client/src/client/zero.js +32 -58
  380. package/out/zero-client/src/client/zero.js.map +1 -1
  381. package/out/zero-client/src/util/nanoid.js.map +1 -1
  382. package/out/zero-client/src/util/socket.d.ts +3 -0
  383. package/out/zero-client/src/util/socket.d.ts.map +1 -0
  384. package/out/zero-client/src/util/socket.js +8 -0
  385. package/out/zero-client/src/util/socket.js.map +1 -0
  386. package/out/zero-protocol/src/analyze-query-result.js +0 -3
  387. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  388. package/out/zero-protocol/src/application-error.js.map +1 -1
  389. package/out/zero-protocol/src/ast.js.map +1 -1
  390. package/out/zero-protocol/src/change-desired-queries.js +0 -1
  391. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  392. package/out/zero-protocol/src/client-schema.js.map +1 -1
  393. package/out/zero-protocol/src/close-connection.js.map +1 -1
  394. package/out/zero-protocol/src/connect.js +0 -7
  395. package/out/zero-protocol/src/connect.js.map +1 -1
  396. package/out/zero-protocol/src/custom-queries.js.map +1 -1
  397. package/out/zero-protocol/src/data.js.map +1 -1
  398. package/out/zero-protocol/src/delete-clients.js.map +1 -1
  399. package/out/zero-protocol/src/down.js.map +1 -1
  400. package/out/zero-protocol/src/error.js +0 -7
  401. package/out/zero-protocol/src/error.js.map +1 -1
  402. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  403. package/out/zero-protocol/src/inspect-up.js +0 -1
  404. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  405. package/out/zero-protocol/src/mutate-server.js.map +1 -1
  406. package/out/zero-protocol/src/mutation-id.js.map +1 -1
  407. package/out/zero-protocol/src/mutation.js.map +1 -1
  408. package/out/zero-protocol/src/mutations-patch.js.map +1 -1
  409. package/out/zero-protocol/src/ping.js.map +1 -1
  410. package/out/zero-protocol/src/poke.js +0 -4
  411. package/out/zero-protocol/src/poke.js.map +1 -1
  412. package/out/zero-protocol/src/pong.js.map +1 -1
  413. package/out/zero-protocol/src/primary-key.js.map +1 -1
  414. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  415. package/out/zero-protocol/src/pull.js.map +1 -1
  416. package/out/zero-protocol/src/push.js +0 -16
  417. package/out/zero-protocol/src/push.js.map +1 -1
  418. package/out/zero-protocol/src/queries-patch.js.map +1 -1
  419. package/out/zero-protocol/src/query-hash.js.map +1 -1
  420. package/out/zero-protocol/src/query-server.js.map +1 -1
  421. package/out/zero-protocol/src/row-patch.js.map +1 -1
  422. package/out/zero-protocol/src/up.js.map +1 -1
  423. package/out/zero-protocol/src/update-auth.js.map +1 -1
  424. package/out/zero-protocol/src/version.js.map +1 -1
  425. package/out/zero-react/src/use-connection-state.js.map +1 -1
  426. package/out/zero-react/src/use-query.js.map +1 -1
  427. package/out/zero-react/src/use-zero-online.js.map +1 -1
  428. package/out/zero-react/src/zero-provider.js.map +1 -1
  429. package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
  430. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  431. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  432. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  433. package/out/zero-schema/src/name-mapper.js.map +1 -1
  434. package/out/zero-schema/src/permissions.js.map +1 -1
  435. package/out/zero-schema/src/schema-config.js.map +1 -1
  436. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  437. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  438. package/out/zero-server/src/adapters/pg.js.map +1 -1
  439. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  440. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  441. package/out/zero-server/src/custom.js +1 -2
  442. package/out/zero-server/src/custom.js.map +1 -1
  443. package/out/zero-server/src/logging.js.map +1 -1
  444. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  445. package/out/zero-server/src/process-mutations.js.map +1 -1
  446. package/out/zero-server/src/push-processor.js.map +1 -1
  447. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  448. package/out/zero-server/src/schema.js.map +1 -1
  449. package/out/zero-server/src/zql-database.js.map +1 -1
  450. package/out/zero-solid/src/solid-view.js.map +1 -1
  451. package/out/zero-solid/src/use-connection-state.js.map +1 -1
  452. package/out/zero-solid/src/use-query.js.map +1 -1
  453. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  454. package/out/zero-solid/src/use-zero.js.map +1 -1
  455. package/out/zero-types/src/format.js.map +1 -1
  456. package/out/zero-types/src/name-mapper.js.map +1 -1
  457. package/out/zql/src/builder/builder.js.map +1 -1
  458. package/out/zql/src/builder/debug-delegate.d.ts +0 -5
  459. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  460. package/out/zql/src/builder/debug-delegate.js +1 -10
  461. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  462. package/out/zql/src/builder/filter.js.map +1 -1
  463. package/out/zql/src/builder/like.js.map +1 -1
  464. package/out/zql/src/error.js.map +1 -1
  465. package/out/zql/src/ivm/array-view.js.map +1 -1
  466. package/out/zql/src/ivm/cap.js.map +1 -1
  467. package/out/zql/src/ivm/change.js.map +1 -1
  468. package/out/zql/src/ivm/constraint.js +1 -1
  469. package/out/zql/src/ivm/constraint.js.map +1 -1
  470. package/out/zql/src/ivm/data.js.map +1 -1
  471. package/out/zql/src/ivm/exists.js.map +1 -1
  472. package/out/zql/src/ivm/fan-in.js.map +1 -1
  473. package/out/zql/src/ivm/fan-out.js.map +1 -1
  474. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  475. package/out/zql/src/ivm/filter-push.js.map +1 -1
  476. package/out/zql/src/ivm/filter.js.map +1 -1
  477. package/out/zql/src/ivm/flipped-join.d.ts +8 -4
  478. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  479. package/out/zql/src/ivm/flipped-join.js +63 -59
  480. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  481. package/out/zql/src/ivm/join-utils.js.map +1 -1
  482. package/out/zql/src/ivm/join.js.map +1 -1
  483. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  484. package/out/zql/src/ivm/memory-source.js.map +1 -1
  485. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  486. package/out/zql/src/ivm/operator.d.ts +1 -1
  487. package/out/zql/src/ivm/operator.js.map +1 -1
  488. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  489. package/out/zql/src/ivm/schema.d.ts +8 -0
  490. package/out/zql/src/ivm/schema.d.ts.map +1 -1
  491. package/out/zql/src/ivm/skip-yields.js.map +1 -1
  492. package/out/zql/src/ivm/skip.js.map +1 -1
  493. package/out/zql/src/ivm/source.js.map +1 -1
  494. package/out/zql/src/ivm/stream.js.map +1 -1
  495. package/out/zql/src/ivm/take.js.map +1 -1
  496. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  497. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  498. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  499. package/out/zql/src/mutate/crud.js.map +1 -1
  500. package/out/zql/src/mutate/custom.js.map +1 -1
  501. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  502. package/out/zql/src/mutate/mutator.js.map +1 -1
  503. package/out/zql/src/planner/planner-builder.js.map +1 -1
  504. package/out/zql/src/planner/planner-connection.js.map +1 -1
  505. package/out/zql/src/planner/planner-constraint.js.map +1 -1
  506. package/out/zql/src/planner/planner-debug.js.map +1 -1
  507. package/out/zql/src/planner/planner-fan-in.js.map +1 -1
  508. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  509. package/out/zql/src/planner/planner-graph.js.map +1 -1
  510. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  511. package/out/zql/src/planner/planner-join.js +1 -2
  512. package/out/zql/src/planner/planner-join.js.map +1 -1
  513. package/out/zql/src/planner/planner-node.js.map +1 -1
  514. package/out/zql/src/planner/planner-source.js.map +1 -1
  515. package/out/zql/src/planner/planner-terminus.js.map +1 -1
  516. package/out/zql/src/query/complete-ordering.js.map +1 -1
  517. package/out/zql/src/query/create-builder.js.map +1 -1
  518. package/out/zql/src/query/error.js.map +1 -1
  519. package/out/zql/src/query/escape-like.js.map +1 -1
  520. package/out/zql/src/query/expression.js.map +1 -1
  521. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  522. package/out/zql/src/query/metrics-delegate.js.map +1 -1
  523. package/out/zql/src/query/named.js.map +1 -1
  524. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  525. package/out/zql/src/query/query-impl.js +1 -1
  526. package/out/zql/src/query/query-impl.js.map +1 -1
  527. package/out/zql/src/query/query-internals.js.map +1 -1
  528. package/out/zql/src/query/query-registry.js.map +1 -1
  529. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  530. package/out/zql/src/query/static-query.js.map +1 -1
  531. package/out/zql/src/query/ttl.js.map +1 -1
  532. package/out/zql/src/query/validate-input.js.map +1 -1
  533. package/out/zqlite/src/database-storage.js.map +1 -1
  534. package/out/zqlite/src/db.js.map +1 -1
  535. package/out/zqlite/src/explain-queries.js.map +1 -1
  536. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  537. package/out/zqlite/src/internal/sql.js.map +1 -1
  538. package/out/zqlite/src/internal/statement-cache.js.map +1 -1
  539. package/out/zqlite/src/query-builder.js.map +1 -1
  540. package/out/zqlite/src/query-delegate.js.map +1 -1
  541. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  542. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  543. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  544. package/out/zqlite/src/table-source.d.ts.map +1 -1
  545. package/out/zqlite/src/table-source.js +6 -6
  546. package/out/zqlite/src/table-source.js.map +1 -1
  547. package/package.json +26 -42
  548. package/out/shared/src/ring-buffer.d.ts +0 -32
  549. package/out/shared/src/ring-buffer.d.ts.map +0 -1
  550. package/out/shared/src/ring-buffer.js +0 -109
  551. package/out/shared/src/ring-buffer.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"connection-manager.js","names":["#disconnectTimeout","#timeoutCheckIntervalMs","#state","#connectingStartedAt","#maybeStartTimeoutInterval","#nextStatePromise","#connectRequestResolver","#consumeConnectRequest","#publishStateAndGetPromise","#maybeStopTimeoutInterval","#publishState","#resolveNextStateWaiters","#stateChangeResolver","#timeoutInterval","#checkTimeout"],"sources":["../../../../../zero-client/src/client/connection-manager.ts"],"sourcesContent":["import {resolver, type Resolver} from '@rocicorp/resolver';\nimport {Subscribable} from '../../../shared/src/subscribable.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {ConnectionStatus} from './connection-status.ts';\nimport {\n ClientError,\n isClientError,\n type AuthError,\n type ClosedError,\n type DisconnectedReason,\n type ZeroError,\n} from './error.ts';\n\nconst DEFAULT_TIMEOUT_CHECK_INTERVAL_MS = 1_000;\n\nexport type ConnectionManagerState =\n | {\n name: ConnectionStatus.Disconnected;\n reason: DisconnectedReason;\n }\n | {\n name: ConnectionStatus.Connecting;\n attempt: number;\n disconnectAt: number;\n reason?: ZeroError | undefined;\n }\n | {\n name: ConnectionStatus.Connected;\n }\n | {\n name: ConnectionStatus.NeedsAuth;\n reason: AuthError;\n }\n | {\n name: ConnectionStatus.Error;\n reason: ZeroError;\n }\n | {\n name: ConnectionStatus.Closed;\n reason: ClosedError;\n };\n\nexport type ConnectionManagerOptions = {\n /**\n * The amount of milliseconds we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n */\n disconnectTimeout: number;\n /**\n * How frequently we check whether the connecting timeout has elapsed.\n * Defaults to 1 second.\n */\n timeoutCheckIntervalMs?: number | undefined;\n};\n\nconst TERMINAL_STATES = [\n ConnectionStatus.NeedsAuth,\n ConnectionStatus.Error,\n] as const satisfies ConnectionStatus[];\n\ntype TerminalConnectionStatus = (typeof TERMINAL_STATES)[number];\ntype TerminalConnectionManagerState = Extract<\n ConnectionManagerState,\n {name: TerminalConnectionStatus}\n>;\n\nexport class ConnectionManager extends Subscribable<ConnectionManagerState> {\n #state: ConnectionManagerState;\n #connectRequestResolver: Resolver<void> | undefined = resolver();\n\n /**\n * The timestamp when we first started trying to connect.\n * This is used to track the retry window.\n * Reset to undefined when we successfully connect or when we transition to disconnected.\n */\n #connectingStartedAt: number | undefined;\n\n /**\n * The amount of milliseconds we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n */\n #disconnectTimeout: number;\n\n /**\n * Handle for the timeout interval that periodically checks whether we've\n * exceeded the allowed connecting window.\n */\n #timeoutInterval: ReturnType<typeof setInterval> | undefined;\n\n /**\n * Interval duration for checking whether the connecting timeout has elapsed.\n */\n #timeoutCheckIntervalMs: number;\n\n /**\n * Resolver used to signal waiting callers when the state changes.\n */\n #stateChangeResolver: Resolver<ConnectionManagerState> = resolver();\n\n constructor(options: ConnectionManagerOptions) {\n super();\n\n const now = Date.now();\n\n this.#disconnectTimeout = options.disconnectTimeout;\n this.#timeoutCheckIntervalMs =\n options.timeoutCheckIntervalMs ?? DEFAULT_TIMEOUT_CHECK_INTERVAL_MS;\n this.#state = {\n name: ConnectionStatus.Connecting,\n attempt: 0,\n disconnectAt: now + this.#disconnectTimeout,\n };\n this.#connectingStartedAt = now;\n this.#maybeStartTimeoutInterval();\n }\n\n get state(): ConnectionManagerState {\n return this.#state;\n }\n\n /**\n * Returns true if the current state is equal to the given status.\n */\n is(status: ConnectionStatus): boolean {\n return this.#state.name === status;\n }\n\n /**\n * Returns true if the current state is a terminal state\n * that can be recovered from by calling connect().\n */\n isInTerminalState(): boolean {\n return ConnectionManager.isTerminalState(this.#state);\n }\n\n /**\n * Returns true if the given status is a terminal state\n * that can be recovered from by calling connect().\n */\n static isTerminalState(\n state: ConnectionManagerState,\n ): state is TerminalConnectionManagerState {\n return (TERMINAL_STATES as readonly ConnectionStatus[]).includes(\n state.name,\n );\n }\n\n /**\n * Returns true if the run loop should continue.\n * The run loop continues in all states except closed.\n * In needs-auth and error states, the run loop pauses and waits for connect() to be called.\n */\n shouldContinueRunLoop(): boolean {\n return this.#state.name !== ConnectionStatus.Closed;\n }\n\n /**\n * Waits for the next state change.\n * @returns A promise that resolves when the next state change occurs.\n */\n waitForStateChange(): Promise<ConnectionManagerState> {\n return this.#nextStatePromise();\n }\n\n requestConnect(): void {\n if (this.#connectRequestResolver === undefined) {\n return;\n }\n this.#connectRequestResolver.resolve();\n this.#connectRequestResolver = undefined;\n }\n\n waitForConnectRequest(): Promise<void> {\n return this.#connectRequestResolver === undefined\n ? Promise.resolve()\n : this.#connectRequestResolver.promise;\n }\n\n #consumeConnectRequest(): boolean {\n if (this.#connectRequestResolver !== undefined) {\n return false;\n }\n this.#connectRequestResolver = resolver();\n return true;\n }\n\n /**\n * Consume a pending connect request and resume connecting.\n *\n * @returns true if a pending request was handled.\n */\n resumeFromConnectRequest(): boolean {\n if (!this.isInTerminalState()) {\n return false;\n }\n if (!this.#consumeConnectRequest()) {\n return false;\n }\n this.connecting();\n return true;\n }\n\n /**\n * Transition to connecting state.\n *\n * This starts the timeout timer, but if we've entered disconnected state,\n * we stay there and continue retrying.\n *\n * If we're disconnected due to a hidden tab, allow a transition back to\n * connecting when visibility returns.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n connecting(reason?: ZeroError): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n const isHiddenDisconnect =\n this.#state.name === ConnectionStatus.Disconnected &&\n this.#state.reason.kind === ClientErrorKind.Hidden;\n\n // we cannot intentionally transition from disconnected to connecting\n // unless the disconnection was due to a hidden tab\n if (\n this.#state.name === ConnectionStatus.Disconnected &&\n !isHiddenDisconnect\n ) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n const now = Date.now();\n\n if (isHiddenDisconnect) {\n // Reset the retry window after a hidden-tab disconnect.\n this.#connectingStartedAt = undefined;\n }\n\n // If we're already connecting, increment the attempt counter\n if (this.#state.name === ConnectionStatus.Connecting) {\n this.#state = {\n ...this.#state,\n attempt: this.#state.attempt + 1,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n this.#maybeStartTimeoutInterval();\n return {nextStatePromise};\n }\n\n // Starting a new connecting session\n // If #connectingStartedAt is undefined, this is a fresh start - set it to now\n // If it's already set, we're retrying within the same retry window, so keep it\n if (this.#connectingStartedAt === undefined) {\n this.#connectingStartedAt = now;\n }\n\n const disconnectAt = this.#connectingStartedAt + this.#disconnectTimeout;\n\n this.#state = {\n name: ConnectionStatus.Connecting,\n attempt: 1,\n disconnectAt,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n this.#maybeStartTimeoutInterval();\n return {nextStatePromise};\n }\n\n /**\n * Transition to connected state.\n * This resets the connecting timeout timer.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n connected(): {nextStatePromise: Promise<ConnectionManagerState>} {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already connected, no-op\n if (this.#state.name === ConnectionStatus.Connected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer on successful connection\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Connected,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to disconnected state.\n * This is called when the timeout expires.\n * The run loop will continue trying to reconnect.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n disconnected(reason: DisconnectedReason): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already disconnected, no-op\n if (this.#state.name === ConnectionStatus.Disconnected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // When transitioning from connected to disconnected, we've lost a connection\n // we previously had. Clear the timeout timer so we can start a fresh timeout window.\n if (this.#state.name === ConnectionStatus.Connected) {\n this.#connectingStartedAt = undefined;\n }\n // When transitioning from connecting to disconnected (e.g., due to timeout),\n // we keep the start time to maintain the context that we've been trying for a while.\n\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Disconnected,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to needs-auth state.\n * This pauses the run loop until connect() is called with new credentials.\n * Resets the retry window and attempt counter.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n needsAuth(reason: AuthError): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already in needs-auth state, no-op\n if (this.#state.name === ConnectionStatus.NeedsAuth) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer and connecting start time\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.NeedsAuth,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to error state.\n * This pauses the run loop until connect() is called.\n * Resets the retry window and attempt counter.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n error(reason: ZeroError): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already in error state, no-op\n if (this.#state.name === ConnectionStatus.Error) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer and connecting start time\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Error,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to closed state.\n * This is terminal - no further transitions are allowed.\n */\n closed() {\n // Already closed, no-op\n if (this.#state.name === ConnectionStatus.Closed) {\n return;\n }\n\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Closed,\n reason: new ClientError({\n kind: ClientErrorKind.ClientClosed,\n message: 'Zero was explicitly closed by calling zero.close()',\n }),\n };\n this.#publishState();\n this.cleanup();\n return;\n }\n\n override cleanup = (): void => {\n this._listeners.clear();\n this.#resolveNextStateWaiters();\n };\n\n #resolveNextStateWaiters(): void {\n this.#stateChangeResolver.resolve(this.#state);\n this.#stateChangeResolver = resolver();\n }\n\n #publishState(): void {\n this.notify(this.#state);\n this.#resolveNextStateWaiters();\n }\n\n #nextStatePromise(): Promise<ConnectionManagerState> {\n return this.#stateChangeResolver.promise;\n }\n\n #publishStateAndGetPromise(): Promise<ConnectionManagerState> {\n this.#publishState();\n return this.#nextStatePromise();\n }\n\n /**\n * Check if we should transition from connecting to disconnected due to timeout.\n * Returns true if the transition happened.\n */\n #checkTimeout(): boolean {\n if (this.#state.name !== ConnectionStatus.Connecting) {\n return false;\n }\n\n const now = Date.now();\n if (now >= this.#state.disconnectAt) {\n this.disconnected(\n new ClientError({\n kind: ClientErrorKind.Offline,\n message: `Zero was unable to connect for ${Math.floor(this.#disconnectTimeout / 1_000)} seconds and was disconnected`,\n }),\n );\n return true;\n }\n\n return false;\n }\n\n #maybeStartTimeoutInterval(): void {\n if (this.#timeoutInterval !== undefined) {\n return;\n }\n this.#timeoutInterval = setInterval(() => {\n this.#checkTimeout();\n }, this.#timeoutCheckIntervalMs);\n }\n\n #maybeStopTimeoutInterval(): void {\n if (this.#timeoutInterval === undefined) {\n return;\n }\n clearInterval(this.#timeoutInterval);\n this.#timeoutInterval = undefined;\n }\n}\n\n/**\n * Used to trigger the catch block when a terminal state is reached.\n *\n * @param state - The current connection state.\n */\nexport const throwIfConnectionError = (state: ConnectionManagerState) => {\n if (\n ConnectionManager.isTerminalState(state) ||\n state.name === ConnectionStatus.Closed ||\n ((state.name === ConnectionStatus.Connecting ||\n state.name === ConnectionStatus.Disconnected) &&\n state.reason)\n ) {\n if (\n isClientError(state.reason) &&\n (state.reason.kind === ClientErrorKind.ConnectTimeout ||\n state.reason.kind === ClientErrorKind.AbruptClose ||\n state.reason.kind === ClientErrorKind.CleanClose ||\n state.reason.kind === ClientErrorKind.Hidden)\n ) {\n return;\n }\n throw state.reason;\n }\n};\n"],"mappings":";;;;;;AAaA,IAAM,oCAAoC;AA0C1C,IAAM,kBAAkB,CACtB,WACA,KACF;AAQA,IAAa,oBAAb,MAAa,0BAA0B,aAAqC;CAC1E;CACA,0BAAsD,SAAS;;;;;;CAO/D;;;;;CAMA;;;;;CAMA;;;;CAKA;;;;CAKA,uBAAyD,SAAS;CAElE,YAAY,SAAmC;EAC7C,MAAM;EAEN,MAAM,MAAM,KAAK,IAAI;EAErB,KAAKA,qBAAqB,QAAQ;EAClC,KAAKC,0BACH,QAAQ,0BAA0B;EACpC,KAAKC,SAAS;GACZ,MAAM;GACN,SAAS;GACT,cAAc,MAAM,KAAKF;EAC3B;EACA,KAAKG,uBAAuB;EAC5B,KAAKC,2BAA2B;CAClC;CAEA,IAAI,QAAgC;EAClC,OAAO,KAAKF;CACd;;;;CAKA,GAAG,QAAmC;EACpC,OAAO,KAAKA,OAAO,SAAS;CAC9B;;;;;CAMA,oBAA6B;EAC3B,OAAO,kBAAkB,gBAAgB,KAAKA,MAAM;CACtD;;;;;CAMA,OAAO,gBACL,OACyC;EACzC,OAAQ,gBAAgD,SACtD,MAAM,IACR;CACF;;;;;;CAOA,wBAAiC;EAC/B,OAAO,KAAKA,OAAO,SAAS;CAC9B;;;;;CAMA,qBAAsD;EACpD,OAAO,KAAKG,kBAAkB;CAChC;CAEA,iBAAuB;EACrB,IAAI,KAAKC,4BAA4B,KAAA,GACnC;EAEF,KAAKA,wBAAwB,QAAQ;EACrC,KAAKA,0BAA0B,KAAA;CACjC;CAEA,wBAAuC;EACrC,OAAO,KAAKA,4BAA4B,KAAA,IACpC,QAAQ,QAAQ,IAChB,KAAKA,wBAAwB;CACnC;CAEA,yBAAkC;EAChC,IAAI,KAAKA,4BAA4B,KAAA,GACnC,OAAO;EAET,KAAKA,0BAA0B,SAAS;EACxC,OAAO;CACT;;;;;;CAOA,2BAAoC;EAClC,IAAI,CAAC,KAAK,kBAAkB,GAC1B,OAAO;EAET,IAAI,CAAC,KAAKC,uBAAuB,GAC/B,OAAO;EAET,KAAK,WAAW;EAChB,OAAO;CACT;;;;;;;;;;;;CAaA,WAAW,QAET;EAEA,IAAI,KAAKL,OAAO,SAAS,UACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAGpD,MAAM,qBACJ,KAAKH,OAAO,SAAS,kBACrB,KAAKA,OAAO,OAAO,SAAS;EAI9B,IACE,KAAKA,OAAO,SAAS,kBACrB,CAAC,oBAED,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAGpD,MAAM,MAAM,KAAK,IAAI;EAErB,IAAI,oBAEF,KAAKF,uBAAuB,KAAA;EAI9B,IAAI,KAAKD,OAAO,SAAS,cAA6B;GACpD,KAAKA,SAAS;IACZ,GAAG,KAAKA;IACR,SAAS,KAAKA,OAAO,UAAU;IAC/B;GACF;GACA,MAAM,mBAAmB,KAAKM,2BAA2B;GACzD,KAAKJ,2BAA2B;GAChC,OAAO,EAAC,iBAAgB;EAC1B;EAKA,IAAI,KAAKD,yBAAyB,KAAA,GAChC,KAAKA,uBAAuB;EAG9B,MAAM,eAAe,KAAKA,uBAAuB,KAAKH;EAEtD,KAAKE,SAAS;GACZ,MAAM;GACN,SAAS;GACT;GACA;EACF;EACA,MAAM,mBAAmB,KAAKM,2BAA2B;EACzD,KAAKJ,2BAA2B;EAChC,OAAO,EAAC,iBAAgB;CAC1B;;;;;;;CAQA,YAAiE;EAE/D,IAAI,KAAKF,OAAO,SAAS,UACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,IAAI,KAAKH,OAAO,SAAS,aACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,KAAKF,uBAAuB,KAAA;EAC5B,KAAKM,0BAA0B;EAE/B,KAAKP,SAAS,EACZ,MAAM,UACR;EAEA,OAAO,EAAC,kBADiB,KAAKM,2BACtB,EAAgB;CAC1B;;;;;;;;CASA,aAAa,QAEX;EAEA,IAAI,KAAKN,OAAO,SAAS,UACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,IAAI,KAAKH,OAAO,SAAS,gBACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAKpD,IAAI,KAAKH,OAAO,SAAS,aACvB,KAAKC,uBAAuB,KAAA;EAK9B,KAAKM,0BAA0B;EAE/B,KAAKP,SAAS;GACZ,MAAM;GACN;EACF;EAEA,OAAO,EAAC,kBADiB,KAAKM,2BACtB,EAAgB;CAC1B;;;;;;;;CASA,UAAU,QAER;EAEA,IAAI,KAAKN,OAAO,SAAS,UACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,IAAI,KAAKH,OAAO,SAAS,cACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,KAAKF,uBAAuB,KAAA;EAC5B,KAAKM,0BAA0B;EAE/B,KAAKP,SAAS;GACZ,MAAM;GACN;EACF;EAEA,OAAO,EAAC,kBADiB,KAAKM,2BACtB,EAAgB;CAC1B;;;;;;;;CASA,MAAM,QAEJ;EAEA,IAAI,KAAKN,OAAO,SAAS,UACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,IAAI,KAAKH,OAAO,SAAS,SACvB,OAAO,EAAC,kBAAkB,KAAKG,kBAAkB,EAAC;EAIpD,KAAKF,uBAAuB,KAAA;EAC5B,KAAKM,0BAA0B;EAE/B,KAAKP,SAAS;GACZ,MAAM;GACN;EACF;EAEA,OAAO,EAAC,kBADiB,KAAKM,2BACtB,EAAgB;CAC1B;;;;;CAMA,SAAS;EAEP,IAAI,KAAKN,OAAO,SAAS,UACvB;EAGF,KAAKC,uBAAuB,KAAA;EAC5B,KAAKM,0BAA0B;EAE/B,KAAKP,SAAS;GACZ,MAAM;GACN,QAAQ,IAAI,YAAY;IACtB,MAAM;IACN,SAAS;GACX,CAAC;EACH;EACA,KAAKQ,cAAc;EACnB,KAAK,QAAQ;CAEf;CAEA,gBAA+B;EAC7B,KAAK,WAAW,MAAM;EACtB,KAAKC,yBAAyB;CAChC;CAEA,2BAAiC;EAC/B,KAAKC,qBAAqB,QAAQ,KAAKV,MAAM;EAC7C,KAAKU,uBAAuB,SAAS;CACvC;CAEA,gBAAsB;EACpB,KAAK,OAAO,KAAKV,MAAM;EACvB,KAAKS,yBAAyB;CAChC;CAEA,oBAAqD;EACnD,OAAO,KAAKC,qBAAqB;CACnC;CAEA,6BAA8D;EAC5D,KAAKF,cAAc;EACnB,OAAO,KAAKL,kBAAkB;CAChC;;;;;CAMA,gBAAyB;EACvB,IAAI,KAAKH,OAAO,SAAS,cACvB,OAAO;EAIT,IADY,KAAK,IACb,KAAO,KAAKA,OAAO,cAAc;GACnC,KAAK,aACH,IAAI,YAAY;IACd,MAAM;IACN,SAAS,kCAAkC,KAAK,MAAM,KAAKF,qBAAqB,GAAK,EAAE;GACzF,CAAC,CACH;GACA,OAAO;EACT;EAEA,OAAO;CACT;CAEA,6BAAmC;EACjC,IAAI,KAAKa,qBAAqB,KAAA,GAC5B;EAEF,KAAKA,mBAAmB,kBAAkB;GACxC,KAAKC,cAAc;EACrB,GAAG,KAAKb,uBAAuB;CACjC;CAEA,4BAAkC;EAChC,IAAI,KAAKY,qBAAqB,KAAA,GAC5B;EAEF,cAAc,KAAKA,gBAAgB;EACnC,KAAKA,mBAAmB,KAAA;CAC1B;AACF;;;;;;AAOA,IAAa,0BAA0B,UAAkC;CACvE,IACE,kBAAkB,gBAAgB,KAAK,KACvC,MAAM,SAAS,aACb,MAAM,SAAS,gBACf,MAAM,SAAS,mBACf,MAAM,QACR;EACA,IACE,cAAc,MAAM,MAAM,MACzB,MAAM,OAAO,SAAS,oBACrB,MAAM,OAAO,SAAS,iBACtB,MAAM,OAAO,SAAS,gBACtB,MAAM,OAAO,SAAS,WAExB;EAEF,MAAM,MAAM;CACd;AACF"}
1
+ {"version":3,"file":"connection-manager.js","names":["#disconnectTimeout","#timeoutCheckIntervalMs","#state","#connectingStartedAt","#maybeStartTimeoutInterval","#nextStatePromise","#connectRequestResolver","#consumeConnectRequest","#publishStateAndGetPromise","#maybeStopTimeoutInterval","#publishState","#resolveNextStateWaiters","#stateChangeResolver","#timeoutInterval","#checkTimeout"],"sources":["../../../../../zero-client/src/client/connection-manager.ts"],"sourcesContent":["import {resolver, type Resolver} from '@rocicorp/resolver';\nimport {Subscribable} from '../../../shared/src/subscribable.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {ConnectionStatus} from './connection-status.ts';\nimport {\n ClientError,\n isClientError,\n type AuthError,\n type ClosedError,\n type DisconnectedReason,\n type ZeroError,\n} from './error.ts';\n\nconst DEFAULT_TIMEOUT_CHECK_INTERVAL_MS = 1_000;\n\nexport type ConnectionManagerState =\n | {\n name: ConnectionStatus.Disconnected;\n reason: DisconnectedReason;\n }\n | {\n name: ConnectionStatus.Connecting;\n attempt: number;\n disconnectAt: number;\n reason?: ZeroError | undefined;\n }\n | {\n name: ConnectionStatus.Connected;\n }\n | {\n name: ConnectionStatus.NeedsAuth;\n reason: AuthError;\n }\n | {\n name: ConnectionStatus.Error;\n reason: ZeroError;\n }\n | {\n name: ConnectionStatus.Closed;\n reason: ClosedError;\n };\n\nexport type ConnectionManagerOptions = {\n /**\n * The amount of milliseconds we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n */\n disconnectTimeout: number;\n /**\n * How frequently we check whether the connecting timeout has elapsed.\n * Defaults to 1 second.\n */\n timeoutCheckIntervalMs?: number | undefined;\n};\n\nconst TERMINAL_STATES = [\n ConnectionStatus.NeedsAuth,\n ConnectionStatus.Error,\n] as const satisfies ConnectionStatus[];\n\ntype TerminalConnectionStatus = (typeof TERMINAL_STATES)[number];\ntype TerminalConnectionManagerState = Extract<\n ConnectionManagerState,\n {name: TerminalConnectionStatus}\n>;\n\nexport class ConnectionManager extends Subscribable<ConnectionManagerState> {\n #state: ConnectionManagerState;\n #connectRequestResolver: Resolver<void> | undefined = resolver();\n\n /**\n * The timestamp when we first started trying to connect.\n * This is used to track the retry window.\n * Reset to undefined when we successfully connect or when we transition to disconnected.\n */\n #connectingStartedAt: number | undefined;\n\n /**\n * The amount of milliseconds we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n */\n #disconnectTimeout: number;\n\n /**\n * Handle for the timeout interval that periodically checks whether we've\n * exceeded the allowed connecting window.\n */\n #timeoutInterval: ReturnType<typeof setInterval> | undefined;\n\n /**\n * Interval duration for checking whether the connecting timeout has elapsed.\n */\n #timeoutCheckIntervalMs: number;\n\n /**\n * Resolver used to signal waiting callers when the state changes.\n */\n #stateChangeResolver: Resolver<ConnectionManagerState> = resolver();\n\n constructor(options: ConnectionManagerOptions) {\n super();\n\n const now = Date.now();\n\n this.#disconnectTimeout = options.disconnectTimeout;\n this.#timeoutCheckIntervalMs =\n options.timeoutCheckIntervalMs ?? DEFAULT_TIMEOUT_CHECK_INTERVAL_MS;\n this.#state = {\n name: ConnectionStatus.Connecting,\n attempt: 0,\n disconnectAt: now + this.#disconnectTimeout,\n };\n this.#connectingStartedAt = now;\n this.#maybeStartTimeoutInterval();\n }\n\n get state(): ConnectionManagerState {\n return this.#state;\n }\n\n /**\n * Returns true if the current state is equal to the given status.\n */\n is(status: ConnectionStatus): boolean {\n return this.#state.name === status;\n }\n\n /**\n * Returns true if the current state is a terminal state\n * that can be recovered from by calling connect().\n */\n isInTerminalState(): boolean {\n return ConnectionManager.isTerminalState(this.#state);\n }\n\n /**\n * Returns true if the given status is a terminal state\n * that can be recovered from by calling connect().\n */\n static isTerminalState(\n state: ConnectionManagerState,\n ): state is TerminalConnectionManagerState {\n return (TERMINAL_STATES as readonly ConnectionStatus[]).includes(\n state.name,\n );\n }\n\n /**\n * Returns true if the run loop should continue.\n * The run loop continues in all states except closed.\n * In needs-auth and error states, the run loop pauses and waits for connect() to be called.\n */\n shouldContinueRunLoop(): boolean {\n return this.#state.name !== ConnectionStatus.Closed;\n }\n\n /**\n * Waits for the next state change.\n * @returns A promise that resolves when the next state change occurs.\n */\n waitForStateChange(): Promise<ConnectionManagerState> {\n return this.#nextStatePromise();\n }\n\n requestConnect(): void {\n if (this.#connectRequestResolver === undefined) {\n return;\n }\n this.#connectRequestResolver.resolve();\n this.#connectRequestResolver = undefined;\n }\n\n waitForConnectRequest(): Promise<void> {\n return this.#connectRequestResolver === undefined\n ? Promise.resolve()\n : this.#connectRequestResolver.promise;\n }\n\n #consumeConnectRequest(): boolean {\n if (this.#connectRequestResolver !== undefined) {\n return false;\n }\n this.#connectRequestResolver = resolver();\n return true;\n }\n\n /**\n * Consume a pending connect request and resume connecting.\n *\n * @returns true if a pending request was handled.\n */\n resumeFromConnectRequest(): boolean {\n if (!this.isInTerminalState()) {\n return false;\n }\n if (!this.#consumeConnectRequest()) {\n return false;\n }\n this.connecting();\n return true;\n }\n\n /**\n * Transition to connecting state.\n *\n * This starts the timeout timer, but if we've entered disconnected state,\n * we stay there and continue retrying.\n *\n * If we're disconnected due to a hidden tab, allow a transition back to\n * connecting when visibility returns.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n connecting(reason?: ZeroError): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n const isHiddenDisconnect =\n this.#state.name === ConnectionStatus.Disconnected &&\n this.#state.reason.kind === ClientErrorKind.Hidden;\n\n // we cannot intentionally transition from disconnected to connecting\n // unless the disconnection was due to a hidden tab\n if (\n this.#state.name === ConnectionStatus.Disconnected &&\n !isHiddenDisconnect\n ) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n const now = Date.now();\n\n if (isHiddenDisconnect) {\n // Reset the retry window after a hidden-tab disconnect.\n this.#connectingStartedAt = undefined;\n }\n\n // If we're already connecting, increment the attempt counter\n if (this.#state.name === ConnectionStatus.Connecting) {\n this.#state = {\n ...this.#state,\n attempt: this.#state.attempt + 1,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n this.#maybeStartTimeoutInterval();\n return {nextStatePromise};\n }\n\n // Starting a new connecting session\n // If #connectingStartedAt is undefined, this is a fresh start - set it to now\n // If it's already set, we're retrying within the same retry window, so keep it\n if (this.#connectingStartedAt === undefined) {\n this.#connectingStartedAt = now;\n }\n\n const disconnectAt = this.#connectingStartedAt + this.#disconnectTimeout;\n\n this.#state = {\n name: ConnectionStatus.Connecting,\n attempt: 1,\n disconnectAt,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n this.#maybeStartTimeoutInterval();\n return {nextStatePromise};\n }\n\n /**\n * Transition to connected state.\n * This resets the connecting timeout timer.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n connected(): {nextStatePromise: Promise<ConnectionManagerState>} {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already connected, no-op\n if (this.#state.name === ConnectionStatus.Connected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer on successful connection\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Connected,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to disconnected state.\n * This is called when the timeout expires.\n * The run loop will continue trying to reconnect.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n disconnected(reason: DisconnectedReason): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already disconnected, no-op\n if (this.#state.name === ConnectionStatus.Disconnected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // When transitioning from connected to disconnected, we've lost a connection\n // we previously had. Clear the timeout timer so we can start a fresh timeout window.\n if (this.#state.name === ConnectionStatus.Connected) {\n this.#connectingStartedAt = undefined;\n }\n // When transitioning from connecting to disconnected (e.g., due to timeout),\n // we keep the start time to maintain the context that we've been trying for a while.\n\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Disconnected,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to needs-auth state.\n * This pauses the run loop until connect() is called with new credentials.\n * Resets the retry window and attempt counter.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n needsAuth(reason: AuthError): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already in needs-auth state, no-op\n if (this.#state.name === ConnectionStatus.NeedsAuth) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer and connecting start time\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.NeedsAuth,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to error state.\n * This pauses the run loop until connect() is called.\n * Resets the retry window and attempt counter.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n error(reason: ZeroError): {\n nextStatePromise: Promise<ConnectionManagerState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already in error state, no-op\n if (this.#state.name === ConnectionStatus.Error) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer and connecting start time\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Error,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to closed state.\n * This is terminal - no further transitions are allowed.\n */\n closed() {\n // Already closed, no-op\n if (this.#state.name === ConnectionStatus.Closed) {\n return;\n }\n\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Closed,\n reason: new ClientError({\n kind: ClientErrorKind.ClientClosed,\n message: 'Zero was explicitly closed by calling zero.close()',\n }),\n };\n this.#publishState();\n this.cleanup();\n return;\n }\n\n override cleanup = (): void => {\n this._listeners.clear();\n this.#resolveNextStateWaiters();\n };\n\n #resolveNextStateWaiters(): void {\n this.#stateChangeResolver.resolve(this.#state);\n this.#stateChangeResolver = resolver();\n }\n\n #publishState(): void {\n this.notify(this.#state);\n this.#resolveNextStateWaiters();\n }\n\n #nextStatePromise(): Promise<ConnectionManagerState> {\n return this.#stateChangeResolver.promise;\n }\n\n #publishStateAndGetPromise(): Promise<ConnectionManagerState> {\n this.#publishState();\n return this.#nextStatePromise();\n }\n\n /**\n * Check if we should transition from connecting to disconnected due to timeout.\n * Returns true if the transition happened.\n */\n #checkTimeout(): boolean {\n if (this.#state.name !== ConnectionStatus.Connecting) {\n return false;\n }\n\n const now = Date.now();\n if (now >= this.#state.disconnectAt) {\n this.disconnected(\n new ClientError({\n kind: ClientErrorKind.Offline,\n message: `Zero was unable to connect for ${Math.floor(this.#disconnectTimeout / 1_000)} seconds and was disconnected`,\n }),\n );\n return true;\n }\n\n return false;\n }\n\n #maybeStartTimeoutInterval(): void {\n if (this.#timeoutInterval !== undefined) {\n return;\n }\n this.#timeoutInterval = setInterval(() => {\n this.#checkTimeout();\n }, this.#timeoutCheckIntervalMs);\n }\n\n #maybeStopTimeoutInterval(): void {\n if (this.#timeoutInterval === undefined) {\n return;\n }\n clearInterval(this.#timeoutInterval);\n this.#timeoutInterval = undefined;\n }\n}\n\n/**\n * Used to trigger the catch block when a terminal state is reached.\n *\n * @param state - The current connection state.\n */\nexport const throwIfConnectionError = (state: ConnectionManagerState) => {\n if (\n ConnectionManager.isTerminalState(state) ||\n state.name === ConnectionStatus.Closed ||\n ((state.name === ConnectionStatus.Connecting ||\n state.name === ConnectionStatus.Disconnected) &&\n state.reason)\n ) {\n if (\n isClientError(state.reason) &&\n (state.reason.kind === ClientErrorKind.ConnectTimeout ||\n state.reason.kind === ClientErrorKind.AbruptClose ||\n state.reason.kind === ClientErrorKind.CleanClose ||\n state.reason.kind === ClientErrorKind.Hidden)\n ) {\n return;\n }\n throw state.reason;\n }\n};\n"],"mappings":";;;;;;AAaA,IAAM,oCAAoC;AA0C1C,IAAM,kBAAkB,CACtB,WACA,MACD;AAQD,IAAa,oBAAb,MAAa,0BAA0B,aAAqC;CAC1E;CACA,0BAAsD,UAAU;;;;;;CAOhE;;;;;CAMA;;;;;CAMA;;;;CAKA;;;;CAKA,uBAAyD,UAAU;CAEnE,YAAY,SAAmC;AAC7C,SAAO;EAEP,MAAM,MAAM,KAAK,KAAK;AAEtB,QAAA,oBAA0B,QAAQ;AAClC,QAAA,yBACE,QAAQ,0BAA0B;AACpC,QAAA,QAAc;GACZ,MAAM;GACN,SAAS;GACT,cAAc,MAAM,MAAA;GACrB;AACD,QAAA,sBAA4B;AAC5B,QAAA,2BAAiC;;CAGnC,IAAI,QAAgC;AAClC,SAAO,MAAA;;;;;CAMT,GAAG,QAAmC;AACpC,SAAO,MAAA,MAAY,SAAS;;;;;;CAO9B,oBAA6B;AAC3B,SAAO,kBAAkB,gBAAgB,MAAA,MAAY;;;;;;CAOvD,OAAO,gBACL,OACyC;AACzC,SAAQ,gBAAgD,SACtD,MAAM,KACP;;;;;;;CAQH,wBAAiC;AAC/B,SAAO,MAAA,MAAY,SAAS;;;;;;CAO9B,qBAAsD;AACpD,SAAO,MAAA,kBAAwB;;CAGjC,iBAAuB;AACrB,MAAI,MAAA,2BAAiC,KAAA,EACnC;AAEF,QAAA,uBAA6B,SAAS;AACtC,QAAA,yBAA+B,KAAA;;CAGjC,wBAAuC;AACrC,SAAO,MAAA,2BAAiC,KAAA,IACpC,QAAQ,SAAS,GACjB,MAAA,uBAA6B;;CAGnC,yBAAkC;AAChC,MAAI,MAAA,2BAAiC,KAAA,EACnC,QAAO;AAET,QAAA,yBAA+B,UAAU;AACzC,SAAO;;;;;;;CAQT,2BAAoC;AAClC,MAAI,CAAC,KAAK,mBAAmB,CAC3B,QAAO;AAET,MAAI,CAAC,MAAA,uBAA6B,CAChC,QAAO;AAET,OAAK,YAAY;AACjB,SAAO;;;;;;;;;;;;;CAcT,WAAW,QAET;AAEA,MAAI,MAAA,MAAY,SAAS,SACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;EAGrD,MAAM,qBACJ,MAAA,MAAY,SAAS,kBACrB,MAAA,MAAY,OAAO,SAAS;AAI9B,MACE,MAAA,MAAY,SAAS,kBACrB,CAAC,mBAED,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;EAGrD,MAAM,MAAM,KAAK,KAAK;AAEtB,MAAI,mBAEF,OAAA,sBAA4B,KAAA;AAI9B,MAAI,MAAA,MAAY,SAAS,cAA6B;AACpD,SAAA,QAAc;IACZ,GAAG,MAAA;IACH,SAAS,MAAA,MAAY,UAAU;IAC/B;IACD;GACD,MAAM,mBAAmB,MAAA,2BAAiC;AAC1D,SAAA,2BAAiC;AACjC,UAAO,EAAC,kBAAiB;;AAM3B,MAAI,MAAA,wBAA8B,KAAA,EAChC,OAAA,sBAA4B;AAK9B,QAAA,QAAc;GACZ,MAAM;GACN,SAAS;GACT,cALmB,MAAA,sBAA4B,MAAA;GAM/C;GACD;EACD,MAAM,mBAAmB,MAAA,2BAAiC;AAC1D,QAAA,2BAAiC;AACjC,SAAO,EAAC,kBAAiB;;;;;;;;CAS3B,YAAiE;AAE/D,MAAI,MAAA,MAAY,SAAS,SACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,MAAI,MAAA,MAAY,SAAS,YACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,QAAA,sBAA4B,KAAA;AAC5B,QAAA,0BAAgC;AAEhC,QAAA,QAAc,EACZ,MAAM,WACP;AAED,SAAO,EAAC,kBADiB,MAAA,2BAAiC,EACjC;;;;;;;;;CAU3B,aAAa,QAEX;AAEA,MAAI,MAAA,MAAY,SAAS,SACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,MAAI,MAAA,MAAY,SAAS,eACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAKrD,MAAI,MAAA,MAAY,SAAS,YACvB,OAAA,sBAA4B,KAAA;AAK9B,QAAA,0BAAgC;AAEhC,QAAA,QAAc;GACZ,MAAM;GACN;GACD;AAED,SAAO,EAAC,kBADiB,MAAA,2BAAiC,EACjC;;;;;;;;;CAU3B,UAAU,QAER;AAEA,MAAI,MAAA,MAAY,SAAS,SACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,MAAI,MAAA,MAAY,SAAS,aACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,QAAA,sBAA4B,KAAA;AAC5B,QAAA,0BAAgC;AAEhC,QAAA,QAAc;GACZ,MAAM;GACN;GACD;AAED,SAAO,EAAC,kBADiB,MAAA,2BAAiC,EACjC;;;;;;;;;CAU3B,MAAM,QAEJ;AAEA,MAAI,MAAA,MAAY,SAAS,SACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,MAAI,MAAA,MAAY,SAAS,QACvB,QAAO,EAAC,kBAAkB,MAAA,kBAAwB,EAAC;AAIrD,QAAA,sBAA4B,KAAA;AAC5B,QAAA,0BAAgC;AAEhC,QAAA,QAAc;GACZ,MAAM;GACN;GACD;AAED,SAAO,EAAC,kBADiB,MAAA,2BAAiC,EACjC;;;;;;CAO3B,SAAS;AAEP,MAAI,MAAA,MAAY,SAAS,SACvB;AAGF,QAAA,sBAA4B,KAAA;AAC5B,QAAA,0BAAgC;AAEhC,QAAA,QAAc;GACZ,MAAM;GACN,QAAQ,IAAI,YAAY;IACtB,MAAM;IACN,SAAS;IACV,CAAC;GACH;AACD,QAAA,cAAoB;AACpB,OAAK,SAAS;;CAIhB,gBAA+B;AAC7B,OAAK,WAAW,OAAO;AACvB,QAAA,yBAA+B;;CAGjC,2BAAiC;AAC/B,QAAA,oBAA0B,QAAQ,MAAA,MAAY;AAC9C,QAAA,sBAA4B,UAAU;;CAGxC,gBAAsB;AACpB,OAAK,OAAO,MAAA,MAAY;AACxB,QAAA,yBAA+B;;CAGjC,oBAAqD;AACnD,SAAO,MAAA,oBAA0B;;CAGnC,6BAA8D;AAC5D,QAAA,cAAoB;AACpB,SAAO,MAAA,kBAAwB;;;;;;CAOjC,gBAAyB;AACvB,MAAI,MAAA,MAAY,SAAS,aACvB,QAAO;AAIT,MADY,KAAK,KAAK,IACX,MAAA,MAAY,cAAc;AACnC,QAAK,aACH,IAAI,YAAY;IACd,MAAM;IACN,SAAS,kCAAkC,KAAK,MAAM,MAAA,oBAA0B,IAAM,CAAC;IACxF,CAAC,CACH;AACD,UAAO;;AAGT,SAAO;;CAGT,6BAAmC;AACjC,MAAI,MAAA,oBAA0B,KAAA,EAC5B;AAEF,QAAA,kBAAwB,kBAAkB;AACxC,SAAA,cAAoB;KACnB,MAAA,uBAA6B;;CAGlC,4BAAkC;AAChC,MAAI,MAAA,oBAA0B,KAAA,EAC5B;AAEF,gBAAc,MAAA,gBAAsB;AACpC,QAAA,kBAAwB,KAAA;;;;;;;;AAS5B,IAAa,0BAA0B,UAAkC;AACvE,KACE,kBAAkB,gBAAgB,MAAM,IACxC,MAAM,SAAS,aACb,MAAM,SAAS,gBACf,MAAM,SAAS,mBACf,MAAM,QACR;AACA,MACE,cAAc,MAAM,OAAO,KAC1B,MAAM,OAAO,SAAS,oBACrB,MAAM,OAAO,SAAS,iBACtB,MAAM,OAAO,SAAS,gBACtB,MAAM,OAAO,SAAS,UAExB;AAEF,QAAM,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","names":["#connectionManager","#lc","#source","#setAuth","#state","#mapConnectionManagerState"],"sources":["../../../../../zero-client/src/client/connection.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {unreachable} from '../../../shared/src/asserts.ts';\nimport {Subscribable} from '../../../shared/src/subscribable.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport type {\n ConnectionManager,\n ConnectionManagerState,\n} from './connection-manager.ts';\nimport {ConnectionStatus} from './connection-status.ts';\n\n/**\n * The current connection state of the Zero instance. One of the following states:\n *\n * - `connecting`: The client is actively trying to connect every 5 seconds.\n * - `disconnected`: The client is now in an \"offline\" state. It will continue\n * to try to connect every 5 seconds.\n * - `connected`: The client has opened a successful connection to the server.\n * - `needs-auth`: Authentication is invalid or expired. No connection retries will be made\n * until the host application calls `connect()`.\n * - `error`: A fatal error occurred. No connection retries will be made until the host\n * application calls `connect()` again.\n * - `closed`: The client was shut down (for example via `zero.close()`). This is\n * a terminal state, and a new Zero instance must be created to reconnect.\n */\nexport type ConnectionState =\n | {\n name: 'disconnected';\n reason: string;\n }\n | {\n name: 'connecting';\n reason?: string;\n }\n | {\n name: 'connected';\n }\n | {\n name: 'needs-auth';\n reason:\n | {\n type: 'mutate';\n status: 401 | 403;\n body?: string;\n }\n | {\n type: 'query';\n status: 401 | 403;\n body?: string;\n }\n | {\n type: 'zero-cache';\n reason: string;\n };\n }\n | {\n name: 'error';\n reason: string;\n }\n | {\n name: 'closed';\n reason: string;\n };\n\nexport interface Source<T> {\n /**\n * The current state value.\n */\n readonly current: T;\n\n /**\n * Subscribe to state changes.\n *\n * @param listener - Called when the state changes with the new state value.\n * @returns A function to unsubscribe from state changes.\n */\n subscribe(listener: (state: T) => void): () => void;\n}\n\n/**\n * Connection API for managing Zero's connection lifecycle.\n */\nexport interface Connection {\n /**\n * The current connection state as a subscribable value.\n */\n readonly state: Source<ConnectionState>;\n\n /**\n * Updates the auth token and, when Zero is paused in `needs-auth` or `error`,\n * resumes connecting.\n *\n * Calling `connect()` without `auth` preserves the current auth token.\n * If Zero is already `connected`, it sends an auth update to the server\n * _without_ reconnecting. In other states, the new token is used the next time\n * Zero connects.\n *\n * This method does not reconnect from `disconnected` or `closed`. To switch\n * to logged-out, create a new Zero instance with `auth` omitted.\n *\n * @param opts - Optional connection options.\n * @param opts.auth - Optional new auth token to store and use for auth refreshes or\n * the next connection.\n * @returns A promise that resolves immediately unless Zero is paused in\n * `needs-auth` or `error`, in which case it resolves after the next\n * connection state change.\n */\n connect(opts?: {auth: string}): Promise<void>;\n}\n\nexport class ConnectionImpl implements Connection {\n readonly #connectionManager: ConnectionManager;\n readonly #lc: LogContext;\n readonly #source: ConnectionSource;\n readonly #setAuth: (auth: string) => void;\n\n constructor(\n connectionManager: ConnectionManager,\n lc: LogContext,\n setAuth: (auth: string) => void,\n ) {\n this.#connectionManager = connectionManager;\n this.#lc = lc;\n this.#source = new ConnectionSource(connectionManager);\n this.#setAuth = setAuth;\n }\n\n get state(): Source<ConnectionState> {\n return this.#source;\n }\n\n async connect(opts?: {auth: string}): Promise<void> {\n const lc = this.#lc.withContext('connect');\n\n if (opts && 'auth' in opts) {\n lc.debug?.('Updating auth credential from connect()');\n this.#setAuth(opts.auth);\n }\n\n // if the connection is disconnected due to a missing cacheURL, we don't allow a reconnect\n if (\n this.#connectionManager.state.name === ConnectionStatus.Disconnected &&\n this.#connectionManager.state.reason.kind ===\n ClientErrorKind.NoSocketOrigin\n ) {\n lc.error?.(\n 'connect() called but the connection is disconnected due to a missing cacheURL. No reconnect will be attempted.',\n );\n return;\n }\n\n // only allow connect() to be called from a terminal state\n if (!this.#connectionManager.isInTerminalState()) {\n lc.debug?.(\n 'connect() called but not in a terminal state. Current state:',\n this.#connectionManager.state.name,\n );\n return;\n }\n\n lc.info?.(\n `Resuming connection from state: ${this.#connectionManager.state.name}`,\n );\n\n this.#connectionManager.requestConnect();\n if (this.#connectionManager.state.name === ConnectionStatus.Connecting) {\n return;\n }\n\n await this.#connectionManager.waitForStateChange();\n }\n}\n\nexport class ConnectionSource\n extends Subscribable<ConnectionState>\n implements Source<ConnectionState>\n{\n #state: ConnectionState;\n\n constructor(connectionManager: ConnectionManager) {\n super();\n this.#state = this.#mapConnectionManagerState(connectionManager.state);\n\n // Subscribe to ConnectionManager immediately to keep #state in sync.\n // This ensures `current` always returns the correct state, even if\n // external code hasn't subscribed yet (fixes race condition where\n // connection completes before React subscribes).\n connectionManager.subscribe(state => {\n this.#state = this.#mapConnectionManagerState(state);\n this.notify(this.#state);\n });\n }\n\n get current(): ConnectionState {\n return this.#state;\n }\n\n #mapConnectionManagerState(state: ConnectionManagerState): ConnectionState {\n switch (state.name) {\n case ConnectionStatus.Closed:\n return {\n name: 'closed',\n reason: state.reason.message,\n };\n case ConnectionStatus.Connected:\n return {\n name: 'connected',\n };\n case ConnectionStatus.Connecting:\n return {\n name: 'connecting',\n ...(state.reason?.message ? {reason: state.reason.message} : {}),\n };\n case ConnectionStatus.Disconnected:\n return {\n name: 'disconnected',\n reason: state.reason.message,\n };\n case ConnectionStatus.Error:\n return {\n name: 'error',\n reason: state.reason.message,\n };\n case ConnectionStatus.NeedsAuth:\n return {\n name: 'needs-auth',\n reason:\n state.reason.errorBody.kind === ErrorKind.PushFailed\n ? {\n type: 'mutate',\n status: state.reason.errorBody.status,\n ...(state.reason.errorBody.bodyPreview\n ? {body: state.reason.errorBody.bodyPreview}\n : {}),\n }\n : state.reason.errorBody.kind === ErrorKind.TransformFailed\n ? {\n type: 'query',\n status: state.reason.errorBody.status,\n ...(state.reason.errorBody.bodyPreview\n ? {body: state.reason.errorBody.bodyPreview}\n : {}),\n }\n : {\n type: 'zero-cache',\n reason: state.reason.message,\n },\n };\n\n default:\n unreachable(state);\n }\n }\n}\n"],"mappings":";;;;;;AA8GA,IAAa,iBAAb,MAAkD;CAChD;CACA;CACA;CACA;CAEA,YACE,mBACA,IACA,SACA;EACA,KAAKA,qBAAqB;EAC1B,KAAKC,MAAM;EACX,KAAKC,UAAU,IAAI,iBAAiB,iBAAiB;EACrD,KAAKC,WAAW;CAClB;CAEA,IAAI,QAAiC;EACnC,OAAO,KAAKD;CACd;CAEA,MAAM,QAAQ,MAAsC;EAClD,MAAM,KAAK,KAAKD,IAAI,YAAY,SAAS;EAEzC,IAAI,QAAQ,UAAU,MAAM;GAC1B,GAAG,QAAQ,yCAAyC;GACpD,KAAKE,SAAS,KAAK,IAAI;EACzB;EAGA,IACE,KAAKH,mBAAmB,MAAM,SAAS,kBACvC,KAAKA,mBAAmB,MAAM,OAAO,SACnC,kBACF;GACA,GAAG,QACD,gHACF;GACA;EACF;EAGA,IAAI,CAAC,KAAKA,mBAAmB,kBAAkB,GAAG;GAChD,GAAG,QACD,gEACA,KAAKA,mBAAmB,MAAM,IAChC;GACA;EACF;EAEA,GAAG,OACD,mCAAmC,KAAKA,mBAAmB,MAAM,MACnE;EAEA,KAAKA,mBAAmB,eAAe;EACvC,IAAI,KAAKA,mBAAmB,MAAM,SAAS,cACzC;EAGF,MAAM,KAAKA,mBAAmB,mBAAmB;CACnD;AACF;AAEA,IAAa,mBAAb,cACU,aAEV;CACE;CAEA,YAAY,mBAAsC;EAChD,MAAM;EACN,KAAKI,SAAS,KAAKC,2BAA2B,kBAAkB,KAAK;EAMrE,kBAAkB,WAAU,UAAS;GACnC,KAAKD,SAAS,KAAKC,2BAA2B,KAAK;GACnD,KAAK,OAAO,KAAKD,MAAM;EACzB,CAAC;CACH;CAEA,IAAI,UAA2B;EAC7B,OAAO,KAAKA;CACd;CAEA,2BAA2B,OAAgD;EACzE,QAAQ,MAAM,MAAd;GACE,KAAK,QACH,OAAO;IACL,MAAM;IACN,QAAQ,MAAM,OAAO;GACvB;GACF,KAAK,WACH,OAAO,EACL,MAAM,YACR;GACF,KAAK,YACH,OAAO;IACL,MAAM;IACN,GAAI,MAAM,QAAQ,UAAU,EAAC,QAAQ,MAAM,OAAO,QAAO,IAAI,CAAC;GAChE;GACF,KAAK,cACH,OAAO;IACL,MAAM;IACN,QAAQ,MAAM,OAAO;GACvB;GACF,KAAK,OACH,OAAO;IACL,MAAM;IACN,QAAQ,MAAM,OAAO;GACvB;GACF,KAAK,WACH,OAAO;IACL,MAAM;IACN,QACE,MAAM,OAAO,UAAU,SAAS,eAC5B;KACE,MAAM;KACN,QAAQ,MAAM,OAAO,UAAU;KAC/B,GAAI,MAAM,OAAO,UAAU,cACvB,EAAC,MAAM,MAAM,OAAO,UAAU,YAAW,IACzC,CAAC;IACP,IACA,MAAM,OAAO,UAAU,SAAS,oBAC9B;KACE,MAAM;KACN,QAAQ,MAAM,OAAO,UAAU;KAC/B,GAAI,MAAM,OAAO,UAAU,cACvB,EAAC,MAAM,MAAM,OAAO,UAAU,YAAW,IACzC,CAAC;IACP,IACA;KACE,MAAM;KACN,QAAQ,MAAM,OAAO;IACvB;GACV;GAEF,SACE,YAAY,KAAK;EACrB;CACF;AACF"}
1
+ {"version":3,"file":"connection.js","names":["#connectionManager","#lc","#source","#setAuth","#state","#mapConnectionManagerState"],"sources":["../../../../../zero-client/src/client/connection.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {unreachable} from '../../../shared/src/asserts.ts';\nimport {Subscribable} from '../../../shared/src/subscribable.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport type {\n ConnectionManager,\n ConnectionManagerState,\n} from './connection-manager.ts';\nimport {ConnectionStatus} from './connection-status.ts';\n\n/**\n * The current connection state of the Zero instance. One of the following states:\n *\n * - `connecting`: The client is actively trying to connect every 5 seconds.\n * - `disconnected`: The client is now in an \"offline\" state. It will continue\n * to try to connect every 5 seconds.\n * - `connected`: The client has opened a successful connection to the server.\n * - `needs-auth`: Authentication is invalid or expired. No connection retries will be made\n * until the host application calls `connect()`.\n * - `error`: A fatal error occurred. No connection retries will be made until the host\n * application calls `connect()` again.\n * - `closed`: The client was shut down (for example via `zero.close()`). This is\n * a terminal state, and a new Zero instance must be created to reconnect.\n */\nexport type ConnectionState =\n | {\n name: 'disconnected';\n reason: string;\n }\n | {\n name: 'connecting';\n reason?: string;\n }\n | {\n name: 'connected';\n }\n | {\n name: 'needs-auth';\n reason:\n | {\n type: 'mutate';\n status: 401 | 403;\n body?: string;\n }\n | {\n type: 'query';\n status: 401 | 403;\n body?: string;\n }\n | {\n type: 'zero-cache';\n reason: string;\n };\n }\n | {\n name: 'error';\n reason: string;\n }\n | {\n name: 'closed';\n reason: string;\n };\n\nexport interface Source<T> {\n /**\n * The current state value.\n */\n readonly current: T;\n\n /**\n * Subscribe to state changes.\n *\n * @param listener - Called when the state changes with the new state value.\n * @returns A function to unsubscribe from state changes.\n */\n subscribe(listener: (state: T) => void): () => void;\n}\n\n/**\n * Connection API for managing Zero's connection lifecycle.\n */\nexport interface Connection {\n /**\n * The current connection state as a subscribable value.\n */\n readonly state: Source<ConnectionState>;\n\n /**\n * Updates the auth token and, when Zero is paused in `needs-auth` or `error`,\n * resumes connecting.\n *\n * Calling `connect()` without `auth` preserves the current auth token.\n * If Zero is already `connected`, it sends an auth update to the server\n * _without_ reconnecting. In other states, the new token is used the next time\n * Zero connects.\n *\n * This method does not reconnect from `disconnected` or `closed`. To switch\n * to logged-out, create a new Zero instance with `auth` omitted.\n *\n * @param opts - Optional connection options.\n * @param opts.auth - Optional new auth token to store and use for auth refreshes or\n * the next connection.\n * @returns A promise that resolves immediately unless Zero is paused in\n * `needs-auth` or `error`, in which case it resolves after the next\n * connection state change.\n */\n connect(opts?: {auth: string}): Promise<void>;\n}\n\nexport class ConnectionImpl implements Connection {\n readonly #connectionManager: ConnectionManager;\n readonly #lc: LogContext;\n readonly #source: ConnectionSource;\n readonly #setAuth: (auth: string) => void;\n\n constructor(\n connectionManager: ConnectionManager,\n lc: LogContext,\n setAuth: (auth: string) => void,\n ) {\n this.#connectionManager = connectionManager;\n this.#lc = lc;\n this.#source = new ConnectionSource(connectionManager);\n this.#setAuth = setAuth;\n }\n\n get state(): Source<ConnectionState> {\n return this.#source;\n }\n\n async connect(opts?: {auth: string}): Promise<void> {\n const lc = this.#lc.withContext('connect');\n\n if (opts && 'auth' in opts) {\n lc.debug?.('Updating auth credential from connect()');\n this.#setAuth(opts.auth);\n }\n\n // if the connection is disconnected due to a missing cacheURL, we don't allow a reconnect\n if (\n this.#connectionManager.state.name === ConnectionStatus.Disconnected &&\n this.#connectionManager.state.reason.kind ===\n ClientErrorKind.NoSocketOrigin\n ) {\n lc.error?.(\n 'connect() called but the connection is disconnected due to a missing cacheURL. No reconnect will be attempted.',\n );\n return;\n }\n\n // only allow connect() to be called from a terminal state\n if (!this.#connectionManager.isInTerminalState()) {\n lc.debug?.(\n 'connect() called but not in a terminal state. Current state:',\n this.#connectionManager.state.name,\n );\n return;\n }\n\n lc.info?.(\n `Resuming connection from state: ${this.#connectionManager.state.name}`,\n );\n\n this.#connectionManager.requestConnect();\n if (this.#connectionManager.state.name === ConnectionStatus.Connecting) {\n return;\n }\n\n await this.#connectionManager.waitForStateChange();\n }\n}\n\nexport class ConnectionSource\n extends Subscribable<ConnectionState>\n implements Source<ConnectionState>\n{\n #state: ConnectionState;\n\n constructor(connectionManager: ConnectionManager) {\n super();\n this.#state = this.#mapConnectionManagerState(connectionManager.state);\n\n // Subscribe to ConnectionManager immediately to keep #state in sync.\n // This ensures `current` always returns the correct state, even if\n // external code hasn't subscribed yet (fixes race condition where\n // connection completes before React subscribes).\n connectionManager.subscribe(state => {\n this.#state = this.#mapConnectionManagerState(state);\n this.notify(this.#state);\n });\n }\n\n get current(): ConnectionState {\n return this.#state;\n }\n\n #mapConnectionManagerState(state: ConnectionManagerState): ConnectionState {\n switch (state.name) {\n case ConnectionStatus.Closed:\n return {\n name: 'closed',\n reason: state.reason.message,\n };\n case ConnectionStatus.Connected:\n return {\n name: 'connected',\n };\n case ConnectionStatus.Connecting:\n return {\n name: 'connecting',\n ...(state.reason?.message ? {reason: state.reason.message} : {}),\n };\n case ConnectionStatus.Disconnected:\n return {\n name: 'disconnected',\n reason: state.reason.message,\n };\n case ConnectionStatus.Error:\n return {\n name: 'error',\n reason: state.reason.message,\n };\n case ConnectionStatus.NeedsAuth:\n return {\n name: 'needs-auth',\n reason:\n state.reason.errorBody.kind === ErrorKind.PushFailed\n ? {\n type: 'mutate',\n status: state.reason.errorBody.status,\n ...(state.reason.errorBody.bodyPreview\n ? {body: state.reason.errorBody.bodyPreview}\n : {}),\n }\n : state.reason.errorBody.kind === ErrorKind.TransformFailed\n ? {\n type: 'query',\n status: state.reason.errorBody.status,\n ...(state.reason.errorBody.bodyPreview\n ? {body: state.reason.errorBody.bodyPreview}\n : {}),\n }\n : {\n type: 'zero-cache',\n reason: state.reason.message,\n },\n };\n\n default:\n unreachable(state);\n }\n }\n}\n"],"mappings":";;;;;;AA8GA,IAAa,iBAAb,MAAkD;CAChD;CACA;CACA;CACA;CAEA,YACE,mBACA,IACA,SACA;AACA,QAAA,oBAA0B;AAC1B,QAAA,KAAW;AACX,QAAA,SAAe,IAAI,iBAAiB,kBAAkB;AACtD,QAAA,UAAgB;;CAGlB,IAAI,QAAiC;AACnC,SAAO,MAAA;;CAGT,MAAM,QAAQ,MAAsC;EAClD,MAAM,KAAK,MAAA,GAAS,YAAY,UAAU;AAE1C,MAAI,QAAQ,UAAU,MAAM;AAC1B,MAAG,QAAQ,0CAA0C;AACrD,SAAA,QAAc,KAAK,KAAK;;AAI1B,MACE,MAAA,kBAAwB,MAAM,SAAS,kBACvC,MAAA,kBAAwB,MAAM,OAAO,SACnC,kBACF;AACA,MAAG,QACD,iHACD;AACD;;AAIF,MAAI,CAAC,MAAA,kBAAwB,mBAAmB,EAAE;AAChD,MAAG,QACD,gEACA,MAAA,kBAAwB,MAAM,KAC/B;AACD;;AAGF,KAAG,OACD,mCAAmC,MAAA,kBAAwB,MAAM,OAClE;AAED,QAAA,kBAAwB,gBAAgB;AACxC,MAAI,MAAA,kBAAwB,MAAM,SAAS,aACzC;AAGF,QAAM,MAAA,kBAAwB,oBAAoB;;;AAItD,IAAa,mBAAb,cACU,aAEV;CACE;CAEA,YAAY,mBAAsC;AAChD,SAAO;AACP,QAAA,QAAc,MAAA,0BAAgC,kBAAkB,MAAM;AAMtE,oBAAkB,WAAU,UAAS;AACnC,SAAA,QAAc,MAAA,0BAAgC,MAAM;AACpD,QAAK,OAAO,MAAA,MAAY;IACxB;;CAGJ,IAAI,UAA2B;AAC7B,SAAO,MAAA;;CAGT,2BAA2B,OAAgD;AACzE,UAAQ,MAAM,MAAd;GACE,KAAK,OACH,QAAO;IACL,MAAM;IACN,QAAQ,MAAM,OAAO;IACtB;GACH,KAAK,UACH,QAAO,EACL,MAAM,aACP;GACH,KAAK,WACH,QAAO;IACL,MAAM;IACN,GAAI,MAAM,QAAQ,UAAU,EAAC,QAAQ,MAAM,OAAO,SAAQ,GAAG,EAAE;IAChE;GACH,KAAK,aACH,QAAO;IACL,MAAM;IACN,QAAQ,MAAM,OAAO;IACtB;GACH,KAAK,MACH,QAAO;IACL,MAAM;IACN,QAAQ,MAAM,OAAO;IACtB;GACH,KAAK,UACH,QAAO;IACL,MAAM;IACN,QACE,MAAM,OAAO,UAAU,SAAS,eAC5B;KACE,MAAM;KACN,QAAQ,MAAM,OAAO,UAAU;KAC/B,GAAI,MAAM,OAAO,UAAU,cACvB,EAAC,MAAM,MAAM,OAAO,UAAU,aAAY,GAC1C,EAAE;KACP,GACD,MAAM,OAAO,UAAU,SAAS,oBAC9B;KACE,MAAM;KACN,QAAQ,MAAM,OAAO,UAAU;KAC/B,GAAI,MAAM,OAAO,UAAU,cACvB,EAAC,MAAM,MAAM,OAAO,UAAU,aAAY,GAC1C,EAAE;KACP,GACD;KACE,MAAM;KACN,QAAQ,MAAM,OAAO;KACtB;IACV;GAEH,QACE,aAAY,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","names":["#lc","#mainSources","#batchViewUpdates","#commitListeners","#endTransaction"],"sources":["../../../../../zero-client/src/client/context.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {NoIndexDiff} from '../../../replicache/src/btree/node.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport type {DebugDelegate} from '../../../zql/src/builder/debug-delegate.ts';\nimport type {Input} from '../../../zql/src/ivm/operator.ts';\nimport type {Source, SourceInput} from '../../../zql/src/ivm/source.ts';\nimport {MeasurePushOperator} from '../../../zql/src/query/measure-push-operator.ts';\nimport type {MetricsDelegate} from '../../../zql/src/query/metrics-delegate.ts';\nimport {QueryDelegateBase} from '../../../zql/src/query/query-delegate-base.ts';\nimport type {CommitListener} from '../../../zql/src/query/query-delegate.ts';\nimport type {RunOptions} from '../../../zql/src/query/query.ts';\nimport {type IVMSourceBranch} from './ivm-branch.ts';\nimport type {QueryManager} from './query-manager.ts';\n\nexport type AddQuery = QueryManager['addLegacy'];\nexport type AddCustomQuery = QueryManager['addCustom'];\n\nexport type UpdateQuery = QueryManager['updateLegacy'];\nexport type UpdateCustomQuery = QueryManager['updateCustom'];\nexport type FlushQueryChanges = QueryManager['flushBatch'];\n\n/**\n * ZeroContext glues together zql and Replicache. It listens to changes in\n * Replicache data and pushes them into IVM and on tells the server about new\n * queries.\n */\nexport class ZeroContext extends QueryDelegateBase {\n readonly #lc: LogContext;\n\n // It is a bummer to have to maintain separate MemorySources here and copy the\n // data in from the Replicache db. But we want the data to be accessible via\n // pipelines *synchronously* and the core Replicache infra is all async. So\n // that needs to be fixed.\n readonly #mainSources: IVMSourceBranch;\n\n readonly addServerQuery: AddQuery;\n readonly addCustomQuery: AddCustomQuery;\n readonly updateServerQuery: UpdateQuery;\n readonly updateCustomQuery: UpdateCustomQuery;\n readonly flushQueryChanges: () => void;\n readonly #batchViewUpdates: (applyViewUpdates: () => void) => void;\n readonly #commitListeners: Set<CommitListener> = new Set();\n\n readonly assertValidRunOptions: (options?: RunOptions) => void;\n\n /**\n * Client-side queries start out as \"unknown\" and are then updated to\n * \"complete\" once the server has sent back the query result.\n */\n readonly defaultQueryComplete = false;\n\n readonly addMetric: MetricsDelegate['addMetric'];\n\n constructor(\n lc: LogContext,\n mainSources: IVMSourceBranch,\n addQuery: AddQuery,\n addCustomQuery: AddCustomQuery,\n updateQuery: UpdateQuery,\n updateCustomQuery: UpdateCustomQuery,\n flushQueryChanges: () => void,\n batchViewUpdates: (applyViewUpdates: () => void) => void,\n addMetric: MetricsDelegate['addMetric'],\n assertValidRunOptions: (options?: RunOptions) => void,\n ) {\n super();\n this.#lc = lc;\n this.#mainSources = mainSources;\n this.addServerQuery = addQuery;\n this.updateServerQuery = updateQuery;\n this.updateCustomQuery = updateCustomQuery;\n this.#batchViewUpdates = batchViewUpdates;\n this.assertValidRunOptions = assertValidRunOptions;\n this.addCustomQuery = addCustomQuery;\n this.flushQueryChanges = flushQueryChanges;\n this.addMetric = addMetric;\n }\n\n applyFiltersAnyway?: boolean | undefined;\n\n debug?: DebugDelegate | undefined;\n\n getSource(name: string): Source | undefined {\n return this.#mainSources.getSource(name);\n }\n\n mapAst(ast: AST): AST {\n return ast;\n }\n\n override decorateSourceInput(input: SourceInput, queryID: string): Input {\n return new MeasurePushOperator(input, queryID, this, 'query-update-client');\n }\n\n onTransactionCommit(cb: CommitListener): () => void {\n this.#commitListeners.add(cb);\n return () => {\n this.#commitListeners.delete(cb);\n };\n }\n\n override batchViewUpdates<T>(applyViewUpdates: () => T) {\n let result: T | undefined;\n let viewChangesPerformed = false;\n this.#batchViewUpdates(() => {\n result = applyViewUpdates();\n viewChangesPerformed = true;\n });\n assert(\n viewChangesPerformed,\n 'batchViewUpdates must call applyViewUpdates synchronously.',\n );\n return result as T;\n }\n\n processChanges(\n expectedHead: Hash | undefined,\n newHead: Hash,\n changes: NoIndexDiff,\n ) {\n this.batchViewUpdates(() => {\n try {\n this.#mainSources.advance(expectedHead, newHead, changes);\n } finally {\n this.#endTransaction();\n }\n });\n }\n\n #endTransaction() {\n for (const listener of this.#commitListeners) {\n try {\n listener();\n } catch (e) {\n // We should not fatal the inner-workings of Zero due to the user's application\n // code throwing an error.\n // Hence we wrap notifications in a try-catch block.\n this.#lc.error?.(\n ErrorKind.Internal,\n 'Failed notifying a commit listener of IVM updates',\n e,\n );\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AA6BA,IAAa,cAAb,cAAiC,kBAAkB;CACjD;CAMA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA,mCAAiD,IAAI,IAAI;CAEzD;;;;;CAMA,uBAAgC;CAEhC;CAEA,YACE,IACA,aACA,UACA,gBACA,aACA,mBACA,mBACA,kBACA,WACA,uBACA;EACA,MAAM;EACN,KAAKA,MAAM;EACX,KAAKC,eAAe;EACpB,KAAK,iBAAiB;EACtB,KAAK,oBAAoB;EACzB,KAAK,oBAAoB;EACzB,KAAKC,oBAAoB;EACzB,KAAK,wBAAwB;EAC7B,KAAK,iBAAiB;EACtB,KAAK,oBAAoB;EACzB,KAAK,YAAY;CACnB;CAEA;CAEA;CAEA,UAAU,MAAkC;EAC1C,OAAO,KAAKD,aAAa,UAAU,IAAI;CACzC;CAEA,OAAO,KAAe;EACpB,OAAO;CACT;CAEA,oBAA6B,OAAoB,SAAwB;EACvE,OAAO,IAAI,oBAAoB,OAAO,SAAS,MAAM,qBAAqB;CAC5E;CAEA,oBAAoB,IAAgC;EAClD,KAAKE,iBAAiB,IAAI,EAAE;EAC5B,aAAa;GACX,KAAKA,iBAAiB,OAAO,EAAE;EACjC;CACF;CAEA,iBAA6B,kBAA2B;EACtD,IAAI;EACJ,IAAI,uBAAuB;EAC3B,KAAKD,wBAAwB;GAC3B,SAAS,iBAAiB;GAC1B,uBAAuB;EACzB,CAAC;EACD,OACE,sBACA,4DACF;EACA,OAAO;CACT;CAEA,eACE,cACA,SACA,SACA;EACA,KAAK,uBAAuB;GAC1B,IAAI;IACF,KAAKD,aAAa,QAAQ,cAAc,SAAS,OAAO;GAC1D,UAAU;IACR,KAAKG,gBAAgB;GACvB;EACF,CAAC;CACH;CAEA,kBAAkB;EAChB,KAAK,MAAM,YAAY,KAAKD,kBAC1B,IAAI;GACF,SAAS;EACX,SAAS,GAAG;GAIV,KAAKH,IAAI,QACP,UACA,qDACA,CACF;EACF;CAEJ;AACF"}
1
+ {"version":3,"file":"context.js","names":["#lc","#mainSources","#batchViewUpdates","#commitListeners","#endTransaction"],"sources":["../../../../../zero-client/src/client/context.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {NoIndexDiff} from '../../../replicache/src/btree/node.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport type {DebugDelegate} from '../../../zql/src/builder/debug-delegate.ts';\nimport type {Input} from '../../../zql/src/ivm/operator.ts';\nimport type {Source, SourceInput} from '../../../zql/src/ivm/source.ts';\nimport {MeasurePushOperator} from '../../../zql/src/query/measure-push-operator.ts';\nimport type {MetricsDelegate} from '../../../zql/src/query/metrics-delegate.ts';\nimport {QueryDelegateBase} from '../../../zql/src/query/query-delegate-base.ts';\nimport type {CommitListener} from '../../../zql/src/query/query-delegate.ts';\nimport type {RunOptions} from '../../../zql/src/query/query.ts';\nimport {type IVMSourceBranch} from './ivm-branch.ts';\nimport type {QueryManager} from './query-manager.ts';\n\nexport type AddQuery = QueryManager['addLegacy'];\nexport type AddCustomQuery = QueryManager['addCustom'];\n\nexport type UpdateQuery = QueryManager['updateLegacy'];\nexport type UpdateCustomQuery = QueryManager['updateCustom'];\nexport type FlushQueryChanges = QueryManager['flushBatch'];\n\n/**\n * ZeroContext glues together zql and Replicache. It listens to changes in\n * Replicache data and pushes them into IVM and on tells the server about new\n * queries.\n */\nexport class ZeroContext extends QueryDelegateBase {\n readonly #lc: LogContext;\n\n // It is a bummer to have to maintain separate MemorySources here and copy the\n // data in from the Replicache db. But we want the data to be accessible via\n // pipelines *synchronously* and the core Replicache infra is all async. So\n // that needs to be fixed.\n readonly #mainSources: IVMSourceBranch;\n\n readonly addServerQuery: AddQuery;\n readonly addCustomQuery: AddCustomQuery;\n readonly updateServerQuery: UpdateQuery;\n readonly updateCustomQuery: UpdateCustomQuery;\n readonly flushQueryChanges: () => void;\n readonly #batchViewUpdates: (applyViewUpdates: () => void) => void;\n readonly #commitListeners: Set<CommitListener> = new Set();\n\n readonly assertValidRunOptions: (options?: RunOptions) => void;\n\n /**\n * Client-side queries start out as \"unknown\" and are then updated to\n * \"complete\" once the server has sent back the query result.\n */\n readonly defaultQueryComplete = false;\n\n readonly addMetric: MetricsDelegate['addMetric'];\n\n constructor(\n lc: LogContext,\n mainSources: IVMSourceBranch,\n addQuery: AddQuery,\n addCustomQuery: AddCustomQuery,\n updateQuery: UpdateQuery,\n updateCustomQuery: UpdateCustomQuery,\n flushQueryChanges: () => void,\n batchViewUpdates: (applyViewUpdates: () => void) => void,\n addMetric: MetricsDelegate['addMetric'],\n assertValidRunOptions: (options?: RunOptions) => void,\n ) {\n super();\n this.#lc = lc;\n this.#mainSources = mainSources;\n this.addServerQuery = addQuery;\n this.updateServerQuery = updateQuery;\n this.updateCustomQuery = updateCustomQuery;\n this.#batchViewUpdates = batchViewUpdates;\n this.assertValidRunOptions = assertValidRunOptions;\n this.addCustomQuery = addCustomQuery;\n this.flushQueryChanges = flushQueryChanges;\n this.addMetric = addMetric;\n }\n\n applyFiltersAnyway?: boolean | undefined;\n\n debug?: DebugDelegate | undefined;\n\n getSource(name: string): Source | undefined {\n return this.#mainSources.getSource(name);\n }\n\n mapAst(ast: AST): AST {\n return ast;\n }\n\n override decorateSourceInput(input: SourceInput, queryID: string): Input {\n return new MeasurePushOperator(input, queryID, this, 'query-update-client');\n }\n\n onTransactionCommit(cb: CommitListener): () => void {\n this.#commitListeners.add(cb);\n return () => {\n this.#commitListeners.delete(cb);\n };\n }\n\n override batchViewUpdates<T>(applyViewUpdates: () => T) {\n let result: T | undefined;\n let viewChangesPerformed = false;\n this.#batchViewUpdates(() => {\n result = applyViewUpdates();\n viewChangesPerformed = true;\n });\n assert(\n viewChangesPerformed,\n 'batchViewUpdates must call applyViewUpdates synchronously.',\n );\n return result as T;\n }\n\n processChanges(\n expectedHead: Hash | undefined,\n newHead: Hash,\n changes: NoIndexDiff,\n ) {\n this.batchViewUpdates(() => {\n try {\n this.#mainSources.advance(expectedHead, newHead, changes);\n } finally {\n this.#endTransaction();\n }\n });\n }\n\n #endTransaction() {\n for (const listener of this.#commitListeners) {\n try {\n listener();\n } catch (e) {\n // We should not fatal the inner-workings of Zero due to the user's application\n // code throwing an error.\n // Hence we wrap notifications in a try-catch block.\n this.#lc.error?.(\n ErrorKind.Internal,\n 'Failed notifying a commit listener of IVM updates',\n e,\n );\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AA6BA,IAAa,cAAb,cAAiC,kBAAkB;CACjD;CAMA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA,mCAAiD,IAAI,KAAK;CAE1D;;;;;CAMA,uBAAgC;CAEhC;CAEA,YACE,IACA,aACA,UACA,gBACA,aACA,mBACA,mBACA,kBACA,WACA,uBACA;AACA,SAAO;AACP,QAAA,KAAW;AACX,QAAA,cAAoB;AACpB,OAAK,iBAAiB;AACtB,OAAK,oBAAoB;AACzB,OAAK,oBAAoB;AACzB,QAAA,mBAAyB;AACzB,OAAK,wBAAwB;AAC7B,OAAK,iBAAiB;AACtB,OAAK,oBAAoB;AACzB,OAAK,YAAY;;CAGnB;CAEA;CAEA,UAAU,MAAkC;AAC1C,SAAO,MAAA,YAAkB,UAAU,KAAK;;CAG1C,OAAO,KAAe;AACpB,SAAO;;CAGT,oBAA6B,OAAoB,SAAwB;AACvE,SAAO,IAAI,oBAAoB,OAAO,SAAS,MAAM,sBAAsB;;CAG7E,oBAAoB,IAAgC;AAClD,QAAA,gBAAsB,IAAI,GAAG;AAC7B,eAAa;AACX,SAAA,gBAAsB,OAAO,GAAG;;;CAIpC,iBAA6B,kBAA2B;EACtD,IAAI;EACJ,IAAI,uBAAuB;AAC3B,QAAA,uBAA6B;AAC3B,YAAS,kBAAkB;AAC3B,0BAAuB;IACvB;AACF,SACE,sBACA,6DACD;AACD,SAAO;;CAGT,eACE,cACA,SACA,SACA;AACA,OAAK,uBAAuB;AAC1B,OAAI;AACF,UAAA,YAAkB,QAAQ,cAAc,SAAS,QAAQ;aACjD;AACR,UAAA,gBAAsB;;IAExB;;CAGJ,kBAAkB;AAChB,OAAK,MAAM,YAAY,MAAA,gBACrB,KAAI;AACF,aAAU;WACH,GAAG;AAIV,SAAA,GAAS,QACP,UACA,qDACA,EACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"crud-impl.js","names":[],"sources":["../../../../../zero-client/src/client/crud-impl.ts"],"sourcesContent":["import type {ReadonlyJSONObject} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {\n type DeleteOp,\n type InsertOp,\n type UpdateOp,\n type UpsertOp,\n} from '../../../zero-protocol/src/mutation.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {\n makeSourceChangeAdd,\n makeSourceChangeEdit,\n makeSourceChangeRemove,\n} from '../../../zql/src/ivm/source.ts';\nimport {consume} from '../../../zql/src/ivm/stream.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport {toPrimaryKeyString} from './keys.ts';\nimport type {WriteTransaction} from './replicache-types.ts';\nexport type {TableMutator} from '../../../zql/src/mutate/crud.ts';\n\nfunction defaultOptionalFieldsToNull(\n schema: TableSchema,\n value: ReadonlyJSONObject,\n): ReadonlyJSONObject {\n let rv = value;\n for (const name in schema.columns) {\n if (rv[name] === undefined) {\n rv = {...rv, [name]: null};\n }\n }\n return rv;\n}\n\nexport async function insert(\n tx: WriteTransaction,\n arg: InsertOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (!(await tx.has(key))) {\n const val = defaultOptionalFieldsToNull(\n schema.tables[arg.tableName],\n arg.value,\n );\n await tx.set(key, val);\n if (ivmBranch) {\n consume(\n must(ivmBranch.getSource(arg.tableName)).push(\n makeSourceChangeAdd(arg.value),\n ),\n );\n }\n }\n}\n\nexport async function upsert(\n tx: WriteTransaction,\n arg: InsertOp | UpsertOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (await tx.has(key)) {\n await update(tx, {...arg, op: 'update'}, schema, ivmBranch);\n } else {\n await insert(tx, {...arg, op: 'insert'}, schema, ivmBranch);\n }\n}\n\nexport async function update(\n tx: WriteTransaction,\n arg: UpdateOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n const update = arg.value;\n const next = {...(prev as ReadonlyJSONObject)};\n for (const k in update) {\n if (update[k] !== undefined) {\n next[k] = update[k];\n }\n }\n await tx.set(key, next);\n if (ivmBranch) {\n consume(\n must(ivmBranch.getSource(arg.tableName)).push(\n makeSourceChangeEdit(next, prev as Row),\n ),\n );\n }\n}\n\nasync function deleteImpl(\n tx: WriteTransaction,\n arg: DeleteOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n await tx.del(key);\n if (ivmBranch) {\n consume(\n must(ivmBranch.getSource(arg.tableName)).push(\n makeSourceChangeRemove(prev as Row),\n ),\n );\n }\n}\n\nexport {deleteImpl as delete};\n"],"mappings":";;;;;;;;;;;;;AAsBA,SAAS,4BACP,QACA,OACoB;CACpB,IAAI,KAAK;CACT,KAAK,MAAM,QAAQ,OAAO,SACxB,IAAI,GAAG,UAAU,KAAA,GACf,KAAK;EAAC,GAAG;GAAK,OAAO;CAAI;CAG7B,OAAO;AACT;AAEA,eAAsB,OACpB,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,KACN;CACA,IAAI,CAAE,MAAM,GAAG,IAAI,GAAG,GAAI;EACxB,MAAM,MAAM,4BACV,OAAO,OAAO,IAAI,YAClB,IAAI,KACN;EACA,MAAM,GAAG,IAAI,KAAK,GAAG;EACrB,IAAI,WACF,QACE,KAAK,UAAU,UAAU,IAAI,SAAS,CAAC,EAAE,KACvC,oBAAoB,IAAI,KAAK,CAC/B,CACF;CAEJ;AACF;AAEA,eAAsB,OACpB,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,KACN;CACA,IAAI,MAAM,GAAG,IAAI,GAAG,GAClB,MAAM,OAAO,IAAI;EAAC,GAAG;EAAK,IAAI;CAAQ,GAAG,QAAQ,SAAS;MAE1D,MAAM,OAAO,IAAI;EAAC,GAAG;EAAK,IAAI;CAAQ,GAAG,QAAQ,SAAS;AAE9D;AAEA,eAAsB,OACpB,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,KACN;CACA,MAAM,OAAO,MAAM,GAAG,IAAI,GAAG;CAC7B,IAAI,SAAS,KAAA,GACX;CAEF,MAAM,SAAS,IAAI;CACnB,MAAM,OAAO,EAAC,GAAI,KAA2B;CAC7C,KAAK,MAAM,KAAK,QACd,IAAI,OAAO,OAAO,KAAA,GAChB,KAAK,KAAK,OAAO;CAGrB,MAAM,GAAG,IAAI,KAAK,IAAI;CACtB,IAAI,WACF,QACE,KAAK,UAAU,UAAU,IAAI,SAAS,CAAC,EAAE,KACvC,qBAAqB,MAAM,IAAW,CACxC,CACF;AAEJ;AAEA,eAAe,WACb,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,KACN;CACA,MAAM,OAAO,MAAM,GAAG,IAAI,GAAG;CAC7B,IAAI,SAAS,KAAA,GACX;CAEF,MAAM,GAAG,IAAI,GAAG;CAChB,IAAI,WACF,QACE,KAAK,UAAU,UAAU,IAAI,SAAS,CAAC,EAAE,KACvC,uBAAuB,IAAW,CACpC,CACF;AAEJ"}
1
+ {"version":3,"file":"crud-impl.js","names":[],"sources":["../../../../../zero-client/src/client/crud-impl.ts"],"sourcesContent":["import type {ReadonlyJSONObject} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {\n type DeleteOp,\n type InsertOp,\n type UpdateOp,\n type UpsertOp,\n} from '../../../zero-protocol/src/mutation.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {\n makeSourceChangeAdd,\n makeSourceChangeEdit,\n makeSourceChangeRemove,\n} from '../../../zql/src/ivm/source.ts';\nimport {consume} from '../../../zql/src/ivm/stream.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport {toPrimaryKeyString} from './keys.ts';\nimport type {WriteTransaction} from './replicache-types.ts';\nexport type {TableMutator} from '../../../zql/src/mutate/crud.ts';\n\nfunction defaultOptionalFieldsToNull(\n schema: TableSchema,\n value: ReadonlyJSONObject,\n): ReadonlyJSONObject {\n let rv = value;\n for (const name in schema.columns) {\n if (rv[name] === undefined) {\n rv = {...rv, [name]: null};\n }\n }\n return rv;\n}\n\nexport async function insert(\n tx: WriteTransaction,\n arg: InsertOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (!(await tx.has(key))) {\n const val = defaultOptionalFieldsToNull(\n schema.tables[arg.tableName],\n arg.value,\n );\n await tx.set(key, val);\n if (ivmBranch) {\n consume(\n must(ivmBranch.getSource(arg.tableName)).push(\n makeSourceChangeAdd(arg.value),\n ),\n );\n }\n }\n}\n\nexport async function upsert(\n tx: WriteTransaction,\n arg: InsertOp | UpsertOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (await tx.has(key)) {\n await update(tx, {...arg, op: 'update'}, schema, ivmBranch);\n } else {\n await insert(tx, {...arg, op: 'insert'}, schema, ivmBranch);\n }\n}\n\nexport async function update(\n tx: WriteTransaction,\n arg: UpdateOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n const update = arg.value;\n const next = {...(prev as ReadonlyJSONObject)};\n for (const k in update) {\n if (update[k] !== undefined) {\n next[k] = update[k];\n }\n }\n await tx.set(key, next);\n if (ivmBranch) {\n consume(\n must(ivmBranch.getSource(arg.tableName)).push(\n makeSourceChangeEdit(next, prev as Row),\n ),\n );\n }\n}\n\nasync function deleteImpl(\n tx: WriteTransaction,\n arg: DeleteOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n await tx.del(key);\n if (ivmBranch) {\n consume(\n must(ivmBranch.getSource(arg.tableName)).push(\n makeSourceChangeRemove(prev as Row),\n ),\n );\n }\n}\n\nexport {deleteImpl as delete};\n"],"mappings":";;;;;;;;;;;;;AAsBA,SAAS,4BACP,QACA,OACoB;CACpB,IAAI,KAAK;AACT,MAAK,MAAM,QAAQ,OAAO,QACxB,KAAI,GAAG,UAAU,KAAA,EACf,MAAK;EAAC,GAAG;GAAK,OAAO;EAAK;AAG9B,QAAO;;AAGT,eAAsB,OACpB,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,MACL;AACD,KAAI,CAAE,MAAM,GAAG,IAAI,IAAI,EAAG;EACxB,MAAM,MAAM,4BACV,OAAO,OAAO,IAAI,YAClB,IAAI,MACL;AACD,QAAM,GAAG,IAAI,KAAK,IAAI;AACtB,MAAI,UACF,SACE,KAAK,UAAU,UAAU,IAAI,UAAU,CAAC,CAAC,KACvC,oBAAoB,IAAI,MAAM,CAC/B,CACF;;;AAKP,eAAsB,OACpB,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,MACL;AACD,KAAI,MAAM,GAAG,IAAI,IAAI,CACnB,OAAM,OAAO,IAAI;EAAC,GAAG;EAAK,IAAI;EAAS,EAAE,QAAQ,UAAU;KAE3D,OAAM,OAAO,IAAI;EAAC,GAAG;EAAK,IAAI;EAAS,EAAE,QAAQ,UAAU;;AAI/D,eAAsB,OACpB,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,MACL;CACD,MAAM,OAAO,MAAM,GAAG,IAAI,IAAI;AAC9B,KAAI,SAAS,KAAA,EACX;CAEF,MAAM,SAAS,IAAI;CACnB,MAAM,OAAO,EAAC,GAAI,MAA4B;AAC9C,MAAK,MAAM,KAAK,OACd,KAAI,OAAO,OAAO,KAAA,EAChB,MAAK,KAAK,OAAO;AAGrB,OAAM,GAAG,IAAI,KAAK,KAAK;AACvB,KAAI,UACF,SACE,KAAK,UAAU,UAAU,IAAI,UAAU,CAAC,CAAC,KACvC,qBAAqB,MAAM,KAAY,CACxC,CACF;;AAIL,eAAe,WACb,IACA,KACA,QACA,WACe;CACf,MAAM,MAAM,mBACV,IAAI,WACJ,OAAO,OAAO,IAAI,WAAW,YAC7B,IAAI,MACL;CACD,MAAM,OAAO,MAAM,GAAG,IAAI,IAAI;AAC9B,KAAI,SAAS,KAAA,EACX;AAEF,OAAM,GAAG,IAAI,IAAI;AACjB,KAAI,UACF,SACE,KAAK,UAAU,UAAU,IAAI,UAAU,CAAC,CAAC,KACvC,uBAAuB,KAAY,CACpC,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"crud.js","names":[],"sources":["../../../../../zero-client/src/client/crud.ts"],"sourcesContent":["import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {\n CRUD_MUTATION_NAME,\n type CRUDMutationArg,\n type CRUDOp,\n type DeleteOp,\n type InsertOp,\n type UpdateOp,\n type UpsertOp,\n} from '../../../zero-protocol/src/mutation.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {\n CRUDExecutor,\n DeleteID,\n InsertValue,\n TableMutator,\n UpdateValue,\n UpsertValue,\n} from '../../../zql/src/mutate/crud.ts';\nimport * as crudImpl from './crud-impl.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport type {MutatorDefs, WriteTransaction} from './replicache-types.ts';\n\nexport type DBMutator<S extends Schema> = S['enableLegacyMutators'] extends true\n ? {\n [K in keyof S['tables']]: TableMutator<S['tables'][K]>;\n }\n : {}; // {} is needed here for intersection type identity\n\nexport type BatchMutator<S extends Schema> =\n S['enableLegacyMutators'] extends true\n ? <R>(body: (m: DBMutator<S>) => MaybePromise<R>) => Promise<R>\n : undefined;\n\ntype ZeroCRUDMutate = {\n [CRUD_MUTATION_NAME]: CRUDMutate;\n};\n\n/**\n * This is the zero.mutateBatch function part representing the CRUD operations. If the\n * tables are `issue` and `label`, then this object will have `issue` and\n * `label` properties.\n *\n * @param schema - The schema defining the tables\n * @param repMutate - The replicache mutate object with the CRUD mutation\n * @param mutate - The object to use as the mutate object. Properties for each\n * table will be assigned to this object.\n */\nexport function makeCRUDMutateBatch<const S extends Schema>(\n schema: S,\n repMutate: ZeroCRUDMutate,\n): BatchMutator<S> {\n if (schema.enableLegacyMutators !== true) {\n return undefined as BatchMutator<S>;\n }\n\n const {[CRUD_MUTATION_NAME]: zeroCRUD} = repMutate;\n\n const mutateBatch = async <R>(body: (m: DBMutator<S>) => R): Promise<R> => {\n const ops: CRUDOp[] = [];\n const m = {} as Record<string, unknown>;\n for (const name of Object.keys(schema.tables)) {\n m[name] = makeBatchCRUDMutate(name, schema, ops);\n }\n\n const rv = await body(m as DBMutator<S>);\n await zeroCRUD({ops});\n return rv;\n };\n\n return mutateBatch as BatchMutator<S>;\n}\n\nexport function addTableCRUDProperties<TSchema extends Schema>(\n schema: TSchema,\n mutate: object,\n repMutate: ZeroCRUDMutate,\n): void {\n const {[CRUD_MUTATION_NAME]: zeroCRUD} = repMutate;\n for (const [name, tableSchema] of Object.entries(schema.tables)) {\n (mutate as Record<string, unknown>)[name] = makeEntityCRUDMutate(\n name,\n tableSchema.primaryKey,\n zeroCRUD,\n );\n }\n}\n\n/**\n * Creates the `{insert, upsert, update, delete}` object for use outside a\n * batch.\n */\nfunction makeEntityCRUDMutate<S extends TableSchema>(\n tableName: string,\n primaryKey: S['primaryKey'],\n zeroCRUD: CRUDMutate,\n): TableMutator<S> {\n return {\n insert: (value: InsertValue<S>) => {\n const op: InsertOp = {\n op: 'insert',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n upsert: (value: UpsertValue<S>) => {\n const op: UpsertOp = {\n op: 'upsert',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n update: (value: UpdateValue<S>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n delete: (id: DeleteID<S>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n return zeroCRUD({ops: [op]});\n },\n };\n}\n\n/**\n * Creates the `{insert, upsert, update, delete}` object for use inside a\n * batch.\n */\nexport function makeBatchCRUDMutate<S extends TableSchema>(\n tableName: string,\n schema: Schema,\n ops: CRUDOp[],\n): TableMutator<S> {\n const {primaryKey} = schema.tables[tableName];\n return {\n insert: (value: InsertValue<S>) => {\n const op: InsertOp = {\n op: 'insert',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n upsert: (value: UpsertValue<S>) => {\n const op: UpsertOp = {\n op: 'upsert',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n update: (value: UpdateValue<S>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n delete: (id: DeleteID<S>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n ops.push(op);\n return promiseVoid;\n },\n };\n}\n\nexport type WithCRUD<MD extends MutatorDefs> = MD & {\n [CRUD_MUTATION_NAME]: CRUDMutator;\n};\n\nexport type CRUDMutate = (crudArg: CRUDMutationArg) => Promise<void>;\n\nexport type CRUDMutator = (\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n) => Promise<void>;\n\nexport function makeCRUDExecutor(\n tx: WriteTransaction,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): CRUDExecutor {\n return (tableName, kind, value) => {\n const {primaryKey} = schema.tables[tableName];\n return crudImpl[kind](\n tx,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n {op: kind, tableName, primaryKey, value} as any,\n schema,\n ivmBranch,\n );\n };\n}\n\n// Zero crud mutators cannot function at the same\n// time as custom mutators as the rebase of crud mutators will not\n// update the IVM branch. That's ok, we're removing crud mutators\n// in favor of custom mutators.\nexport function makeCRUDMutator(schema: Schema): CRUDMutator {\n return async (\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n ): Promise<void> => {\n const executor = makeCRUDExecutor(tx, schema, undefined);\n for (const op of crudArg.ops) {\n await executor(op.tableName, op.op, op.value);\n }\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAkDA,SAAgB,oBACd,QACA,WACiB;CACjB,IAAI,OAAO,yBAAyB,MAClC;CAGF,MAAM,GAAE,qBAAqB,aAAY;CAEzC,MAAM,cAAc,OAAU,SAA6C;EACzE,MAAM,MAAgB,CAAC;EACvB,MAAM,IAAI,CAAC;EACX,KAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,MAAM,GAC1C,EAAE,QAAQ,oBAAoB,MAAM,QAAQ,GAAG;EAGjD,MAAM,KAAK,MAAM,KAAK,CAAiB;EACvC,MAAM,SAAS,EAAC,IAAG,CAAC;EACpB,OAAO;CACT;CAEA,OAAO;AACT;AAEA,SAAgB,uBACd,QACA,QACA,WACM;CACN,MAAM,GAAE,qBAAqB,aAAY;CACzC,KAAK,MAAM,CAAC,MAAM,gBAAgB,OAAO,QAAQ,OAAO,MAAM,GAC5D,OAAoC,QAAQ,qBAC1C,MACA,YAAY,YACZ,QACF;AAEJ;;;;;AAMA,SAAS,qBACP,WACA,YACA,UACiB;CACjB,OAAO;EACL,SAAS,UAA0B;GAOjC,OAAO,SAAS,EAAC,KAAK,CAAC;IALrB,IAAI;IACJ;IACA;IACA;GAEqB,CAAE,EAAC,CAAC;EAC7B;EACA,SAAS,UAA0B;GAOjC,OAAO,SAAS,EAAC,KAAK,CAAC;IALrB,IAAI;IACJ;IACA;IACA;GAEqB,CAAE,EAAC,CAAC;EAC7B;EACA,SAAS,UAA0B;GAOjC,OAAO,SAAS,EAAC,KAAK,CAAC;IALrB,IAAI;IACJ;IACA;IACA;GAEqB,CAAE,EAAC,CAAC;EAC7B;EACA,SAAS,OAAoB;GAO3B,OAAO,SAAS,EAAC,KAAK,CAAC;IALrB,IAAI;IACJ;IACA;IACA,OAAO;GAEc,CAAE,EAAC,CAAC;EAC7B;CACF;AACF;;;;;AAMA,SAAgB,oBACd,WACA,QACA,KACiB;CACjB,MAAM,EAAC,eAAc,OAAO,OAAO;CACnC,OAAO;EACL,SAAS,UAA0B;GACjC,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA;GACF;GACA,IAAI,KAAK,EAAE;GACX,OAAO;EACT;EACA,SAAS,UAA0B;GACjC,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA;GACF;GACA,IAAI,KAAK,EAAE;GACX,OAAO;EACT;EACA,SAAS,UAA0B;GACjC,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA;GACF;GACA,IAAI,KAAK,EAAE;GACX,OAAO;EACT;EACA,SAAS,OAAoB;GAC3B,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA,OAAO;GACT;GACA,IAAI,KAAK,EAAE;GACX,OAAO;EACT;CACF;AACF;AAaA,SAAgB,iBACd,IACA,QACA,WACc;CACd,QAAQ,WAAW,MAAM,UAAU;EACjC,MAAM,EAAC,eAAc,OAAO,OAAO;EACnC,OAAO,kBAAS,MACd,IAEA;GAAC,IAAI;GAAM;GAAW;GAAY;EAAK,GACvC,QACA,SACF;CACF;AACF;AAMA,SAAgB,gBAAgB,QAA6B;CAC3D,OAAO,OACL,IACA,YACkB;EAClB,MAAM,WAAW,iBAAiB,IAAI,QAAQ,KAAA,CAAS;EACvD,KAAK,MAAM,MAAM,QAAQ,KACvB,MAAM,SAAS,GAAG,WAAW,GAAG,IAAI,GAAG,KAAK;CAEhD;AACF"}
1
+ {"version":3,"file":"crud.js","names":[],"sources":["../../../../../zero-client/src/client/crud.ts"],"sourcesContent":["import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {\n CRUD_MUTATION_NAME,\n type CRUDMutationArg,\n type CRUDOp,\n type DeleteOp,\n type InsertOp,\n type UpdateOp,\n type UpsertOp,\n} from '../../../zero-protocol/src/mutation.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {\n CRUDExecutor,\n DeleteID,\n InsertValue,\n TableMutator,\n UpdateValue,\n UpsertValue,\n} from '../../../zql/src/mutate/crud.ts';\nimport * as crudImpl from './crud-impl.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport type {MutatorDefs, WriteTransaction} from './replicache-types.ts';\n\nexport type DBMutator<S extends Schema> = S['enableLegacyMutators'] extends true\n ? {\n [K in keyof S['tables']]: TableMutator<S['tables'][K]>;\n }\n : {}; // {} is needed here for intersection type identity\n\nexport type BatchMutator<S extends Schema> =\n S['enableLegacyMutators'] extends true\n ? <R>(body: (m: DBMutator<S>) => MaybePromise<R>) => Promise<R>\n : undefined;\n\ntype ZeroCRUDMutate = {\n [CRUD_MUTATION_NAME]: CRUDMutate;\n};\n\n/**\n * This is the zero.mutateBatch function part representing the CRUD operations. If the\n * tables are `issue` and `label`, then this object will have `issue` and\n * `label` properties.\n *\n * @param schema - The schema defining the tables\n * @param repMutate - The replicache mutate object with the CRUD mutation\n * @param mutate - The object to use as the mutate object. Properties for each\n * table will be assigned to this object.\n */\nexport function makeCRUDMutateBatch<const S extends Schema>(\n schema: S,\n repMutate: ZeroCRUDMutate,\n): BatchMutator<S> {\n if (schema.enableLegacyMutators !== true) {\n return undefined as BatchMutator<S>;\n }\n\n const {[CRUD_MUTATION_NAME]: zeroCRUD} = repMutate;\n\n const mutateBatch = async <R>(body: (m: DBMutator<S>) => R): Promise<R> => {\n const ops: CRUDOp[] = [];\n const m = {} as Record<string, unknown>;\n for (const name of Object.keys(schema.tables)) {\n m[name] = makeBatchCRUDMutate(name, schema, ops);\n }\n\n const rv = await body(m as DBMutator<S>);\n await zeroCRUD({ops});\n return rv;\n };\n\n return mutateBatch as BatchMutator<S>;\n}\n\nexport function addTableCRUDProperties<TSchema extends Schema>(\n schema: TSchema,\n mutate: object,\n repMutate: ZeroCRUDMutate,\n): void {\n const {[CRUD_MUTATION_NAME]: zeroCRUD} = repMutate;\n for (const [name, tableSchema] of Object.entries(schema.tables)) {\n (mutate as Record<string, unknown>)[name] = makeEntityCRUDMutate(\n name,\n tableSchema.primaryKey,\n zeroCRUD,\n );\n }\n}\n\n/**\n * Creates the `{insert, upsert, update, delete}` object for use outside a\n * batch.\n */\nfunction makeEntityCRUDMutate<S extends TableSchema>(\n tableName: string,\n primaryKey: S['primaryKey'],\n zeroCRUD: CRUDMutate,\n): TableMutator<S> {\n return {\n insert: (value: InsertValue<S>) => {\n const op: InsertOp = {\n op: 'insert',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n upsert: (value: UpsertValue<S>) => {\n const op: UpsertOp = {\n op: 'upsert',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n update: (value: UpdateValue<S>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n delete: (id: DeleteID<S>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n return zeroCRUD({ops: [op]});\n },\n };\n}\n\n/**\n * Creates the `{insert, upsert, update, delete}` object for use inside a\n * batch.\n */\nexport function makeBatchCRUDMutate<S extends TableSchema>(\n tableName: string,\n schema: Schema,\n ops: CRUDOp[],\n): TableMutator<S> {\n const {primaryKey} = schema.tables[tableName];\n return {\n insert: (value: InsertValue<S>) => {\n const op: InsertOp = {\n op: 'insert',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n upsert: (value: UpsertValue<S>) => {\n const op: UpsertOp = {\n op: 'upsert',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n update: (value: UpdateValue<S>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n delete: (id: DeleteID<S>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n ops.push(op);\n return promiseVoid;\n },\n };\n}\n\nexport type WithCRUD<MD extends MutatorDefs> = MD & {\n [CRUD_MUTATION_NAME]: CRUDMutator;\n};\n\nexport type CRUDMutate = (crudArg: CRUDMutationArg) => Promise<void>;\n\nexport type CRUDMutator = (\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n) => Promise<void>;\n\nexport function makeCRUDExecutor(\n tx: WriteTransaction,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): CRUDExecutor {\n return (tableName, kind, value) => {\n const {primaryKey} = schema.tables[tableName];\n return crudImpl[kind](\n tx,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n {op: kind, tableName, primaryKey, value} as any,\n schema,\n ivmBranch,\n );\n };\n}\n\n// Zero crud mutators cannot function at the same\n// time as custom mutators as the rebase of crud mutators will not\n// update the IVM branch. That's ok, we're removing crud mutators\n// in favor of custom mutators.\nexport function makeCRUDMutator(schema: Schema): CRUDMutator {\n return async (\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n ): Promise<void> => {\n const executor = makeCRUDExecutor(tx, schema, undefined);\n for (const op of crudArg.ops) {\n await executor(op.tableName, op.op, op.value);\n }\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAkDA,SAAgB,oBACd,QACA,WACiB;AACjB,KAAI,OAAO,yBAAyB,KAClC;CAGF,MAAM,GAAE,qBAAqB,aAAY;CAEzC,MAAM,cAAc,OAAU,SAA6C;EACzE,MAAM,MAAgB,EAAE;EACxB,MAAM,IAAI,EAAE;AACZ,OAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,OAAO,CAC3C,GAAE,QAAQ,oBAAoB,MAAM,QAAQ,IAAI;EAGlD,MAAM,KAAK,MAAM,KAAK,EAAkB;AACxC,QAAM,SAAS,EAAC,KAAI,CAAC;AACrB,SAAO;;AAGT,QAAO;;AAGT,SAAgB,uBACd,QACA,QACA,WACM;CACN,MAAM,GAAE,qBAAqB,aAAY;AACzC,MAAK,MAAM,CAAC,MAAM,gBAAgB,OAAO,QAAQ,OAAO,OAAO,CAC5D,QAAmC,QAAQ,qBAC1C,MACA,YAAY,YACZ,SACD;;;;;;AAQL,SAAS,qBACP,WACA,YACA,UACiB;AACjB,QAAO;EACL,SAAS,UAA0B;AAOjC,UAAO,SAAS,EAAC,KAAK,CAND;IACnB,IAAI;IACJ;IACA;IACA;IACD,CACyB,EAAC,CAAC;;EAE9B,SAAS,UAA0B;AAOjC,UAAO,SAAS,EAAC,KAAK,CAND;IACnB,IAAI;IACJ;IACA;IACA;IACD,CACyB,EAAC,CAAC;;EAE9B,SAAS,UAA0B;AAOjC,UAAO,SAAS,EAAC,KAAK,CAND;IACnB,IAAI;IACJ;IACA;IACA;IACD,CACyB,EAAC,CAAC;;EAE9B,SAAS,OAAoB;AAO3B,UAAO,SAAS,EAAC,KAAK,CAND;IACnB,IAAI;IACJ;IACA;IACA,OAAO;IACR,CACyB,EAAC,CAAC;;EAE/B;;;;;;AAOH,SAAgB,oBACd,WACA,QACA,KACiB;CACjB,MAAM,EAAC,eAAc,OAAO,OAAO;AACnC,QAAO;EACL,SAAS,UAA0B;GACjC,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA;IACD;AACD,OAAI,KAAK,GAAG;AACZ,UAAO;;EAET,SAAS,UAA0B;GACjC,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA;IACD;AACD,OAAI,KAAK,GAAG;AACZ,UAAO;;EAET,SAAS,UAA0B;GACjC,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA;IACD;AACD,OAAI,KAAK,GAAG;AACZ,UAAO;;EAET,SAAS,OAAoB;GAC3B,MAAM,KAAe;IACnB,IAAI;IACJ;IACA;IACA,OAAO;IACR;AACD,OAAI,KAAK,GAAG;AACZ,UAAO;;EAEV;;AAcH,SAAgB,iBACd,IACA,QACA,WACc;AACd,SAAQ,WAAW,MAAM,UAAU;EACjC,MAAM,EAAC,eAAc,OAAO,OAAO;AACnC,SAAO,kBAAS,MACd,IAEA;GAAC,IAAI;GAAM;GAAW;GAAY;GAAM,EACxC,QACA,UACD;;;AAQL,SAAgB,gBAAgB,QAA6B;AAC3D,QAAO,OACL,IACA,YACkB;EAClB,MAAM,WAAW,iBAAiB,IAAI,QAAQ,KAAA,EAAU;AACxD,OAAK,MAAM,MAAM,QAAQ,IACvB,OAAM,SAAS,GAAG,WAAW,GAAG,IAAI,GAAG,MAAM"}
@@ -22,8 +22,7 @@ var TransactionImpl = class {
22
22
  const txData = getZeroTxData(repTx);
23
23
  const ivmBranch = txData.ivmSources;
24
24
  this.#repTx = repTx;
25
- const executor = makeCRUDExecutor(repTx, schema, ivmBranch);
26
- this.mutate = makeTransactionMutate(schema, executor);
25
+ this.mutate = makeTransactionMutate(schema, makeCRUDExecutor(repTx, schema, ivmBranch));
27
26
  const zeroContext = newZeroContext(lc, txData.ivmSources);
28
27
  this.query = createRunnableBuilder(zeroContext, schema);
29
28
  this.#zeroContext = zeroContext;
@@ -1 +1 @@
1
- {"version":3,"file":"custom.js","names":["#repTx","#zeroContext"],"sources":["../../../../../zero-client/src/client/custom.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {ZeroTxData} from '../../../replicache/src/replicache-options.ts';\nimport type {WriteTransactionImpl} from '../../../replicache/src/transactions.ts';\nimport {zeroData} from '../../../replicache/src/transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyFunction} from '../../../shared/src/sentinels.ts';\nimport type {DefaultSchema} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {\n makeTransactionMutate,\n type TransactionMutate,\n} from '../../../zql/src/mutate/crud.ts';\nimport type {\n ClientTransaction,\n Transaction,\n} from '../../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../../zql/src/query/create-builder.ts';\nimport {\n type HumanReadable,\n type Query,\n type RunOptions,\n} from '../../../zql/src/query/query.ts';\nimport type {ConditionalSchemaQuery} from '../../../zql/src/query/schema-query.ts';\nimport type {ClientID} from '../types/client-state.ts';\nimport {ZeroContext} from './context.ts';\nimport {makeCRUDExecutor} from './crud.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport type {WriteTransaction} from './replicache-types.ts';\n\n/**\n * The shape which a user's custom mutator definitions must conform to.\n * Supports arbitrary depth nesting of namespaces.\n */\nexport type CustomMutatorDefs = {\n // oxlint-disable-next-line no-explicit-any\n [namespaceOrKey: string]: CustomMutatorImpl<any> | CustomMutatorDefs;\n};\n\nexport type MutatorResultDetails =\n | {\n readonly type: 'success';\n }\n | {\n readonly type: 'error';\n readonly error:\n | {\n readonly type: 'app';\n readonly message: string;\n readonly details: ReadonlyJSONValue | undefined;\n }\n | {\n readonly type: 'zero';\n readonly message: string;\n };\n };\n\nexport type MutatorResultSuccessDetails = Extract<\n MutatorResultDetails,\n {type: 'success'}\n>;\nexport type MutatorResultErrorDetails = Extract<\n MutatorResultDetails,\n {type: 'error'}\n>;\n\nexport type MutatorResult = {\n client: Promise<MutatorResultDetails & {}>;\n server: Promise<MutatorResultDetails & {}>;\n} & {};\n\nexport type CustomMutatorImpl<\n S extends Schema,\n TWrappedTransaction = unknown,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (\n tx: Transaction<S, TWrappedTransaction>,\n // TODO: many args. See commit: 52657c2f934b4a458d628ea77e56ce92b61eb3c6 which did have many args.\n // The issue being that it will be a protocol change to support varargs.\n args: TArgs,\n ctx: Context,\n) => Promise<void>;\n\n/**\n * The shape exposed on the `Zero.mutate` instance.\n * The signature of a custom mutator takes a `transaction` as its first arg\n * but the user does not provide this arg when calling the mutator.\n *\n * This utility strips the `tx` arg from the user's custom mutator signatures.\n * Supports arbitrary depth nesting of namespaces.\n */\nexport type MakeCustomMutatorInterfaces<\n S extends Schema,\n MD extends CustomMutatorDefs,\n TContext,\n> = {\n readonly [NamespaceOrName in keyof MD]: MD[NamespaceOrName] extends (\n tx: Transaction<S>,\n ...args: infer Args\n ) => Promise<void>\n ? (...args: Args) => MutatorResult\n : MD[NamespaceOrName] extends CustomMutatorDefs\n ? MakeCustomMutatorInterfaces<S, MD[NamespaceOrName], TContext>\n : never;\n};\n\nexport type MakeCustomMutatorInterface<TSchema extends Schema, F> = F extends (\n tx: ClientTransaction<TSchema>,\n ...args: infer Args\n) => Promise<void>\n ? (...args: Args) => MutatorResult\n : never;\n\nexport class TransactionImpl<\n TSchema extends Schema = DefaultSchema,\n> implements ClientTransaction<TSchema> {\n readonly location = 'client';\n readonly mutate: TransactionMutate<TSchema>;\n /**\n * @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead.\n */\n readonly query: ConditionalSchemaQuery<TSchema>;\n\n readonly #repTx: WriteTransaction;\n readonly #zeroContext: ZeroContext;\n\n constructor(lc: LogContext, repTx: WriteTransaction, schema: TSchema) {\n must(repTx.reason === 'initial' || repTx.reason === 'rebase');\n const txData = getZeroTxData(repTx);\n const ivmBranch = txData.ivmSources as IVMSourceBranch;\n\n this.#repTx = repTx;\n\n const executor = makeCRUDExecutor(repTx, schema, ivmBranch);\n this.mutate = makeTransactionMutate(schema, executor);\n\n const zeroContext = newZeroContext(\n lc,\n txData.ivmSources as IVMSourceBranch,\n );\n\n this.query = createRunnableBuilder(zeroContext, schema);\n\n this.#zeroContext = zeroContext;\n }\n\n get clientID(): ClientID {\n return this.#repTx.clientID;\n }\n\n get mutationID(): number {\n return this.#repTx.mutationID;\n }\n\n get reason(): 'optimistic' | 'rebase' {\n return this.#repTx.reason === 'initial' ? 'optimistic' : 'rebase';\n }\n\n get token(): string | undefined {\n return (this.#repTx as WriteTransactionImpl)[zeroData]?.token;\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n return this.#zeroContext.run(query, options);\n }\n}\n\nexport function getZeroTxData(repTx: WriteTransaction): ZeroTxData {\n const txData = must(\n (repTx as WriteTransactionImpl)[zeroData],\n 'zero was not set on replicache internal options!',\n );\n return txData as ZeroTxData;\n}\n\nexport function makeReplicacheMutator<\n S extends Schema,\n TWrappedTransaction,\n Context,\n>(\n lc: LogContext,\n mutator: CustomMutatorImpl<S, TWrappedTransaction>,\n schema: S,\n context: Context,\n): (repTx: WriteTransaction, args: ReadonlyJSONValue) => Promise<void> {\n return async (\n repTx: WriteTransaction,\n args: ReadonlyJSONValue,\n ): Promise<void> => {\n const tx = new TransactionImpl(lc, repTx, schema);\n await mutator(tx, args, context);\n };\n}\n\nfunction assertValidRunOptions(options: RunOptions | undefined): void {\n // TODO(arv): We should enforce this with the type system too.\n assert(\n options?.type !== 'complete',\n 'Cannot wait for complete results in custom mutations',\n );\n}\n\nfunction newZeroContext(lc: LogContext, ivmBranch: IVMSourceBranch) {\n return new ZeroContext(\n lc,\n ivmBranch,\n () => emptyFunction,\n () => emptyFunction,\n emptyFunction,\n emptyFunction,\n emptyFunction,\n applyViewUpdates => applyViewUpdates(),\n emptyFunction,\n assertValidRunOptions,\n );\n}\n"],"mappings":";;;;;;;;;;AAoHA,IAAa,kBAAb,MAEwC;CACtC,WAAoB;CACpB;;;;CAIA;CAEA;CACA;CAEA,YAAY,IAAgB,OAAyB,QAAiB;EACpE,KAAK,MAAM,WAAW,aAAa,MAAM,WAAW,QAAQ;EAC5D,MAAM,SAAS,cAAc,KAAK;EAClC,MAAM,YAAY,OAAO;EAEzB,KAAKA,SAAS;EAEd,MAAM,WAAW,iBAAiB,OAAO,QAAQ,SAAS;EAC1D,KAAK,SAAS,sBAAsB,QAAQ,QAAQ;EAEpD,MAAM,cAAc,eAClB,IACA,OAAO,UACT;EAEA,KAAK,QAAQ,sBAAsB,aAAa,MAAM;EAEtD,KAAKC,eAAe;CACtB;CAEA,IAAI,WAAqB;EACvB,OAAO,KAAKD,OAAO;CACrB;CAEA,IAAI,aAAqB;EACvB,OAAO,KAAKA,OAAO;CACrB;CAEA,IAAI,SAAkC;EACpC,OAAO,KAAKA,OAAO,WAAW,YAAY,eAAe;CAC3D;CAEA,IAAI,QAA4B;EAC9B,OAAQ,KAAKA,OAAgC,WAAW;CAC1D;CAEA,IACE,OACA,SACiC;EACjC,OAAO,KAAKC,aAAa,IAAI,OAAO,OAAO;CAC7C;AACF;AAEA,SAAgB,cAAc,OAAqC;CAKjE,OAJe,KACZ,MAA+B,WAChC,kDAEK;AACT;AAEA,SAAgB,sBAKd,IACA,SACA,QACA,SACqE;CACrE,OAAO,OACL,OACA,SACkB;EAElB,MAAM,QAAQ,IADC,gBAAgB,IAAI,OAAO,MAC5B,GAAI,MAAM,OAAO;CACjC;AACF;AAEA,SAAS,sBAAsB,SAAuC;CAEpE,OACE,SAAS,SAAS,YAClB,sDACF;AACF;AAEA,SAAS,eAAe,IAAgB,WAA4B;CAClE,OAAO,IAAI,YACT,IACA,iBACM,qBACA,eACN,eACA,eACA,gBACA,qBAAoB,iBAAiB,GACrC,eACA,qBACF;AACF"}
1
+ {"version":3,"file":"custom.js","names":["#repTx","#zeroContext"],"sources":["../../../../../zero-client/src/client/custom.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {ZeroTxData} from '../../../replicache/src/replicache-options.ts';\nimport type {WriteTransactionImpl} from '../../../replicache/src/transactions.ts';\nimport {zeroData} from '../../../replicache/src/transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyFunction} from '../../../shared/src/sentinels.ts';\nimport type {DefaultSchema} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {\n makeTransactionMutate,\n type TransactionMutate,\n} from '../../../zql/src/mutate/crud.ts';\nimport type {\n ClientTransaction,\n Transaction,\n} from '../../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../../zql/src/query/create-builder.ts';\nimport {\n type HumanReadable,\n type Query,\n type RunOptions,\n} from '../../../zql/src/query/query.ts';\nimport type {ConditionalSchemaQuery} from '../../../zql/src/query/schema-query.ts';\nimport type {ClientID} from '../types/client-state.ts';\nimport {ZeroContext} from './context.ts';\nimport {makeCRUDExecutor} from './crud.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport type {WriteTransaction} from './replicache-types.ts';\n\n/**\n * The shape which a user's custom mutator definitions must conform to.\n * Supports arbitrary depth nesting of namespaces.\n */\nexport type CustomMutatorDefs = {\n // oxlint-disable-next-line no-explicit-any\n [namespaceOrKey: string]: CustomMutatorImpl<any> | CustomMutatorDefs;\n};\n\nexport type MutatorResultDetails =\n | {\n readonly type: 'success';\n }\n | {\n readonly type: 'error';\n readonly error:\n | {\n readonly type: 'app';\n readonly message: string;\n readonly details: ReadonlyJSONValue | undefined;\n }\n | {\n readonly type: 'zero';\n readonly message: string;\n };\n };\n\nexport type MutatorResultSuccessDetails = Extract<\n MutatorResultDetails,\n {type: 'success'}\n>;\nexport type MutatorResultErrorDetails = Extract<\n MutatorResultDetails,\n {type: 'error'}\n>;\n\nexport type MutatorResult = {\n client: Promise<MutatorResultDetails & {}>;\n server: Promise<MutatorResultDetails & {}>;\n} & {};\n\nexport type CustomMutatorImpl<\n S extends Schema,\n TWrappedTransaction = unknown,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (\n tx: Transaction<S, TWrappedTransaction>,\n // TODO: many args. See commit: 52657c2f934b4a458d628ea77e56ce92b61eb3c6 which did have many args.\n // The issue being that it will be a protocol change to support varargs.\n args: TArgs,\n ctx: Context,\n) => Promise<void>;\n\n/**\n * The shape exposed on the `Zero.mutate` instance.\n * The signature of a custom mutator takes a `transaction` as its first arg\n * but the user does not provide this arg when calling the mutator.\n *\n * This utility strips the `tx` arg from the user's custom mutator signatures.\n * Supports arbitrary depth nesting of namespaces.\n */\nexport type MakeCustomMutatorInterfaces<\n S extends Schema,\n MD extends CustomMutatorDefs,\n TContext,\n> = {\n readonly [NamespaceOrName in keyof MD]: MD[NamespaceOrName] extends (\n tx: Transaction<S>,\n ...args: infer Args\n ) => Promise<void>\n ? (...args: Args) => MutatorResult\n : MD[NamespaceOrName] extends CustomMutatorDefs\n ? MakeCustomMutatorInterfaces<S, MD[NamespaceOrName], TContext>\n : never;\n};\n\nexport type MakeCustomMutatorInterface<TSchema extends Schema, F> = F extends (\n tx: ClientTransaction<TSchema>,\n ...args: infer Args\n) => Promise<void>\n ? (...args: Args) => MutatorResult\n : never;\n\nexport class TransactionImpl<\n TSchema extends Schema = DefaultSchema,\n> implements ClientTransaction<TSchema> {\n readonly location = 'client';\n readonly mutate: TransactionMutate<TSchema>;\n /**\n * @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead.\n */\n readonly query: ConditionalSchemaQuery<TSchema>;\n\n readonly #repTx: WriteTransaction;\n readonly #zeroContext: ZeroContext;\n\n constructor(lc: LogContext, repTx: WriteTransaction, schema: TSchema) {\n must(repTx.reason === 'initial' || repTx.reason === 'rebase');\n const txData = getZeroTxData(repTx);\n const ivmBranch = txData.ivmSources as IVMSourceBranch;\n\n this.#repTx = repTx;\n\n const executor = makeCRUDExecutor(repTx, schema, ivmBranch);\n this.mutate = makeTransactionMutate(schema, executor);\n\n const zeroContext = newZeroContext(\n lc,\n txData.ivmSources as IVMSourceBranch,\n );\n\n this.query = createRunnableBuilder(zeroContext, schema);\n\n this.#zeroContext = zeroContext;\n }\n\n get clientID(): ClientID {\n return this.#repTx.clientID;\n }\n\n get mutationID(): number {\n return this.#repTx.mutationID;\n }\n\n get reason(): 'optimistic' | 'rebase' {\n return this.#repTx.reason === 'initial' ? 'optimistic' : 'rebase';\n }\n\n get token(): string | undefined {\n return (this.#repTx as WriteTransactionImpl)[zeroData]?.token;\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n return this.#zeroContext.run(query, options);\n }\n}\n\nexport function getZeroTxData(repTx: WriteTransaction): ZeroTxData {\n const txData = must(\n (repTx as WriteTransactionImpl)[zeroData],\n 'zero was not set on replicache internal options!',\n );\n return txData as ZeroTxData;\n}\n\nexport function makeReplicacheMutator<\n S extends Schema,\n TWrappedTransaction,\n Context,\n>(\n lc: LogContext,\n mutator: CustomMutatorImpl<S, TWrappedTransaction>,\n schema: S,\n context: Context,\n): (repTx: WriteTransaction, args: ReadonlyJSONValue) => Promise<void> {\n return async (\n repTx: WriteTransaction,\n args: ReadonlyJSONValue,\n ): Promise<void> => {\n const tx = new TransactionImpl(lc, repTx, schema);\n await mutator(tx, args, context);\n };\n}\n\nfunction assertValidRunOptions(options: RunOptions | undefined): void {\n // TODO(arv): We should enforce this with the type system too.\n assert(\n options?.type !== 'complete',\n 'Cannot wait for complete results in custom mutations',\n );\n}\n\nfunction newZeroContext(lc: LogContext, ivmBranch: IVMSourceBranch) {\n return new ZeroContext(\n lc,\n ivmBranch,\n () => emptyFunction,\n () => emptyFunction,\n emptyFunction,\n emptyFunction,\n emptyFunction,\n applyViewUpdates => applyViewUpdates(),\n emptyFunction,\n assertValidRunOptions,\n );\n}\n"],"mappings":";;;;;;;;;;AAoHA,IAAa,kBAAb,MAEwC;CACtC,WAAoB;CACpB;;;;CAIA;CAEA;CACA;CAEA,YAAY,IAAgB,OAAyB,QAAiB;AACpE,OAAK,MAAM,WAAW,aAAa,MAAM,WAAW,SAAS;EAC7D,MAAM,SAAS,cAAc,MAAM;EACnC,MAAM,YAAY,OAAO;AAEzB,QAAA,QAAc;AAGd,OAAK,SAAS,sBAAsB,QADnB,iBAAiB,OAAO,QAAQ,UAAU,CACN;EAErD,MAAM,cAAc,eAClB,IACA,OAAO,WACR;AAED,OAAK,QAAQ,sBAAsB,aAAa,OAAO;AAEvD,QAAA,cAAoB;;CAGtB,IAAI,WAAqB;AACvB,SAAO,MAAA,MAAY;;CAGrB,IAAI,aAAqB;AACvB,SAAO,MAAA,MAAY;;CAGrB,IAAI,SAAkC;AACpC,SAAO,MAAA,MAAY,WAAW,YAAY,eAAe;;CAG3D,IAAI,QAA4B;AAC9B,SAAQ,MAAA,MAAqC,WAAW;;CAG1D,IACE,OACA,SACiC;AACjC,SAAO,MAAA,YAAkB,IAAI,OAAO,QAAQ;;;AAIhD,SAAgB,cAAc,OAAqC;AAKjE,QAJe,KACZ,MAA+B,WAChC,mDACD;;AAIH,SAAgB,sBAKd,IACA,SACA,QACA,SACqE;AACrE,QAAO,OACL,OACA,SACkB;AAElB,QAAM,QADK,IAAI,gBAAgB,IAAI,OAAO,OAAO,EAC/B,MAAM,QAAQ;;;AAIpC,SAAS,sBAAsB,SAAuC;AAEpE,QACE,SAAS,SAAS,YAClB,uDACD;;AAGH,SAAS,eAAe,IAAgB,WAA4B;AAClE,QAAO,IAAI,YACT,IACA,iBACM,qBACA,eACN,eACA,eACA,gBACA,qBAAoB,kBAAkB,EACtC,eACA,sBACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"delete-clients-manager.js","names":["#send","#lc","#dagStore","#clientGroupID","#clientID"],"sources":["../../../../../zero-client/src/client/delete-clients-manager.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Store} from '../../../replicache/src/dag/store.ts';\nimport {\n confirmDeletedClients,\n getDeletedClients,\n type DeletedClients,\n} from '../../../replicache/src/deleted-clients.ts';\nimport type {ClientGroupID} from '../../../replicache/src/sync/ids.ts';\nimport {\n withRead,\n withWrite,\n} from '../../../replicache/src/with-transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {\n DeleteClientsBody,\n DeleteClientsMessage,\n} from '../../../zero-protocol/src/delete-clients.ts';\n\nfunction filterAndAssert(\n deletedClients: DeletedClients,\n clientGroupID: ClientGroupID,\n clientID: string,\n caller: string,\n): string[] {\n const clientIDs = deletedClients\n .filter(dc => dc.clientGroupID === clientGroupID)\n .map(dc => dc.clientID);\n for (const cid of clientIDs) {\n assert(cid !== clientID, `cannot delete self in ${caller}`);\n }\n return clientIDs;\n}\n\n/**\n * Replicache will tell us when it deletes clients from the persistent storage\n * due to GC. When this happens we tell the server about the deleted clients.\n * Replicache also store the deleted clients in IDB in case the server is\n * currently offline.\n *\n * The server will reply with the client it actually deleted. When we get that\n * we remove those IDs from our local storage.\n */\nexport class DeleteClientsManager {\n readonly #send: (msg: DeleteClientsMessage) => void;\n readonly #lc: LogContext;\n readonly #dagStore: Store;\n readonly #clientGroupID: Promise<ClientGroupID>;\n readonly #clientID: string;\n\n constructor(\n send: (msg: DeleteClientsMessage) => void,\n dagStore: Store,\n lc: LogContext,\n clientGroupID: Promise<ClientGroupID>,\n clientID: string,\n ) {\n this.#send = send;\n this.#dagStore = dagStore;\n this.#lc = lc;\n this.#clientGroupID = clientGroupID;\n this.#clientID = clientID;\n }\n\n /**\n * This gets called by Replicache when it deletes clients from the persistent\n * storage.\n */\n async onClientsDeleted(deletedClients: DeletedClients): Promise<void> {\n this.#lc.debug?.('DeletedClientsManager, send:', deletedClients);\n const clientGroupID = await this.#clientGroupID;\n const clientIDs = filterAndAssert(\n deletedClients,\n clientGroupID,\n this.#clientID,\n 'onClientsDeleted',\n );\n this.#send([\n 'deleteClients',\n {\n clientIDs,\n },\n ]);\n }\n\n /**\n * Zero calls this after it connects to ensure that the server knows about all\n * the clients that might have been deleted locally since the last connection.\n */\n async sendDeletedClientsToServer(): Promise<void> {\n const clientGroupID = await this.#clientGroupID;\n const deleted = await withRead(this.#dagStore, dagRead =>\n getDeletedClients(dagRead),\n );\n\n const clientIDs = filterAndAssert(\n deleted,\n clientGroupID,\n this.#clientID,\n 'sendDeletedClientsToServer',\n );\n\n if (clientIDs.length > 0) {\n this.#send(['deleteClients', {clientIDs}]);\n this.#lc.debug?.('DeletedClientsManager, send:', deleted);\n }\n }\n\n /**\n * This is called as a response to the server telling us which clients it\n * actually deleted.\n */\n clientsDeletedOnServer(deletedClients: DeleteClientsBody): Promise<void> {\n const {clientIDs = [], clientGroupIDs = []} = deletedClients;\n if (clientIDs.length > 0 || clientGroupIDs.length > 0) {\n // Get the deleted clients from the dag and remove the ones from the server.\n // then write them back to the dag.\n return withWrite(this.#dagStore, async dagWrite => {\n this.#lc.debug?.('clientsDeletedOnServer:', clientIDs, clientGroupIDs);\n await confirmDeletedClients(dagWrite, clientIDs, clientGroupIDs);\n });\n }\n return promiseVoid;\n }\n\n async getDeletedClients(): Promise<DeletedClients> {\n const deletedClients = await withRead(this.#dagStore, read =>\n getDeletedClients(read),\n );\n const clientGroupID = await this.#clientGroupID;\n filterAndAssert(\n deletedClients,\n clientGroupID,\n this.#clientID,\n 'getDeletedClients',\n );\n return deletedClients.filter(d => d.clientGroupID === clientGroupID);\n }\n}\n"],"mappings":";;;;;AAmBA,SAAS,gBACP,gBACA,eACA,UACA,QACU;CACV,MAAM,YAAY,eACf,QAAO,OAAM,GAAG,kBAAkB,aAAa,EAC/C,KAAI,OAAM,GAAG,QAAQ;CACxB,KAAK,MAAM,OAAO,WAChB,OAAO,QAAQ,UAAU,yBAAyB,QAAQ;CAE5D,OAAO;AACT;;;;;;;;;;AAWA,IAAa,uBAAb,MAAkC;CAChC;CACA;CACA;CACA;CACA;CAEA,YACE,MACA,UACA,IACA,eACA,UACA;EACA,KAAKA,QAAQ;EACb,KAAKE,YAAY;EACjB,KAAKD,MAAM;EACX,KAAKE,iBAAiB;EACtB,KAAKC,YAAY;CACnB;;;;;CAMA,MAAM,iBAAiB,gBAA+C;EACpE,KAAKH,IAAI,QAAQ,gCAAgC,cAAc;EAE/D,MAAM,YAAY,gBAChB,gBACA,MAH0B,KAAKE,gBAI/B,KAAKC,WACL,kBACF;EACA,KAAKJ,MAAM,CACT,iBACA,EACE,UACF,CACF,CAAC;CACH;;;;;CAMA,MAAM,6BAA4C;EAChD,MAAM,gBAAgB,MAAM,KAAKG;EACjC,MAAM,UAAU,MAAM,SAAS,KAAKD,YAAW,YAC7C,kBAAkB,OAAO,CAC3B;EAEA,MAAM,YAAY,gBAChB,SACA,eACA,KAAKE,WACL,4BACF;EAEA,IAAI,UAAU,SAAS,GAAG;GACxB,KAAKJ,MAAM,CAAC,iBAAiB,EAAC,UAAS,CAAC,CAAC;GACzC,KAAKC,IAAI,QAAQ,gCAAgC,OAAO;EAC1D;CACF;;;;;CAMA,uBAAuB,gBAAkD;EACvE,MAAM,EAAC,YAAY,CAAC,GAAG,iBAAiB,CAAC,MAAK;EAC9C,IAAI,UAAU,SAAS,KAAK,eAAe,SAAS,GAGlD,OAAO,UAAU,KAAKC,WAAW,OAAM,aAAY;GACjD,KAAKD,IAAI,QAAQ,2BAA2B,WAAW,cAAc;GACrE,MAAM,sBAAsB,UAAU,WAAW,cAAc;EACjE,CAAC;EAEH,OAAO;CACT;CAEA,MAAM,oBAA6C;EACjD,MAAM,iBAAiB,MAAM,SAAS,KAAKC,YAAW,SACpD,kBAAkB,IAAI,CACxB;EACA,MAAM,gBAAgB,MAAM,KAAKC;EACjC,gBACE,gBACA,eACA,KAAKC,WACL,mBACF;EACA,OAAO,eAAe,QAAO,MAAK,EAAE,kBAAkB,aAAa;CACrE;AACF"}
1
+ {"version":3,"file":"delete-clients-manager.js","names":["#send","#lc","#dagStore","#clientGroupID","#clientID"],"sources":["../../../../../zero-client/src/client/delete-clients-manager.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Store} from '../../../replicache/src/dag/store.ts';\nimport {\n confirmDeletedClients,\n getDeletedClients,\n type DeletedClients,\n} from '../../../replicache/src/deleted-clients.ts';\nimport type {ClientGroupID} from '../../../replicache/src/sync/ids.ts';\nimport {\n withRead,\n withWrite,\n} from '../../../replicache/src/with-transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {\n DeleteClientsBody,\n DeleteClientsMessage,\n} from '../../../zero-protocol/src/delete-clients.ts';\n\nfunction filterAndAssert(\n deletedClients: DeletedClients,\n clientGroupID: ClientGroupID,\n clientID: string,\n caller: string,\n): string[] {\n const clientIDs = deletedClients\n .filter(dc => dc.clientGroupID === clientGroupID)\n .map(dc => dc.clientID);\n for (const cid of clientIDs) {\n assert(cid !== clientID, `cannot delete self in ${caller}`);\n }\n return clientIDs;\n}\n\n/**\n * Replicache will tell us when it deletes clients from the persistent storage\n * due to GC. When this happens we tell the server about the deleted clients.\n * Replicache also store the deleted clients in IDB in case the server is\n * currently offline.\n *\n * The server will reply with the client it actually deleted. When we get that\n * we remove those IDs from our local storage.\n */\nexport class DeleteClientsManager {\n readonly #send: (msg: DeleteClientsMessage) => void;\n readonly #lc: LogContext;\n readonly #dagStore: Store;\n readonly #clientGroupID: Promise<ClientGroupID>;\n readonly #clientID: string;\n\n constructor(\n send: (msg: DeleteClientsMessage) => void,\n dagStore: Store,\n lc: LogContext,\n clientGroupID: Promise<ClientGroupID>,\n clientID: string,\n ) {\n this.#send = send;\n this.#dagStore = dagStore;\n this.#lc = lc;\n this.#clientGroupID = clientGroupID;\n this.#clientID = clientID;\n }\n\n /**\n * This gets called by Replicache when it deletes clients from the persistent\n * storage.\n */\n async onClientsDeleted(deletedClients: DeletedClients): Promise<void> {\n this.#lc.debug?.('DeletedClientsManager, send:', deletedClients);\n const clientGroupID = await this.#clientGroupID;\n const clientIDs = filterAndAssert(\n deletedClients,\n clientGroupID,\n this.#clientID,\n 'onClientsDeleted',\n );\n this.#send([\n 'deleteClients',\n {\n clientIDs,\n },\n ]);\n }\n\n /**\n * Zero calls this after it connects to ensure that the server knows about all\n * the clients that might have been deleted locally since the last connection.\n */\n async sendDeletedClientsToServer(): Promise<void> {\n const clientGroupID = await this.#clientGroupID;\n const deleted = await withRead(this.#dagStore, dagRead =>\n getDeletedClients(dagRead),\n );\n\n const clientIDs = filterAndAssert(\n deleted,\n clientGroupID,\n this.#clientID,\n 'sendDeletedClientsToServer',\n );\n\n if (clientIDs.length > 0) {\n this.#send(['deleteClients', {clientIDs}]);\n this.#lc.debug?.('DeletedClientsManager, send:', deleted);\n }\n }\n\n /**\n * This is called as a response to the server telling us which clients it\n * actually deleted.\n */\n clientsDeletedOnServer(deletedClients: DeleteClientsBody): Promise<void> {\n const {clientIDs = [], clientGroupIDs = []} = deletedClients;\n if (clientIDs.length > 0 || clientGroupIDs.length > 0) {\n // Get the deleted clients from the dag and remove the ones from the server.\n // then write them back to the dag.\n return withWrite(this.#dagStore, async dagWrite => {\n this.#lc.debug?.('clientsDeletedOnServer:', clientIDs, clientGroupIDs);\n await confirmDeletedClients(dagWrite, clientIDs, clientGroupIDs);\n });\n }\n return promiseVoid;\n }\n\n async getDeletedClients(): Promise<DeletedClients> {\n const deletedClients = await withRead(this.#dagStore, read =>\n getDeletedClients(read),\n );\n const clientGroupID = await this.#clientGroupID;\n filterAndAssert(\n deletedClients,\n clientGroupID,\n this.#clientID,\n 'getDeletedClients',\n );\n return deletedClients.filter(d => d.clientGroupID === clientGroupID);\n }\n}\n"],"mappings":";;;;;AAmBA,SAAS,gBACP,gBACA,eACA,UACA,QACU;CACV,MAAM,YAAY,eACf,QAAO,OAAM,GAAG,kBAAkB,cAAc,CAChD,KAAI,OAAM,GAAG,SAAS;AACzB,MAAK,MAAM,OAAO,UAChB,QAAO,QAAQ,UAAU,yBAAyB,SAAS;AAE7D,QAAO;;;;;;;;;;;AAYT,IAAa,uBAAb,MAAkC;CAChC;CACA;CACA;CACA;CACA;CAEA,YACE,MACA,UACA,IACA,eACA,UACA;AACA,QAAA,OAAa;AACb,QAAA,WAAiB;AACjB,QAAA,KAAW;AACX,QAAA,gBAAsB;AACtB,QAAA,WAAiB;;;;;;CAOnB,MAAM,iBAAiB,gBAA+C;AACpE,QAAA,GAAS,QAAQ,gCAAgC,eAAe;EAEhE,MAAM,YAAY,gBAChB,gBAFoB,MAAM,MAAA,eAI1B,MAAA,UACA,mBACD;AACD,QAAA,KAAW,CACT,iBACA,EACE,WACD,CACF,CAAC;;;;;;CAOJ,MAAM,6BAA4C;EAChD,MAAM,gBAAgB,MAAM,MAAA;EAC5B,MAAM,UAAU,MAAM,SAAS,MAAA,WAAgB,YAC7C,kBAAkB,QAAQ,CAC3B;EAED,MAAM,YAAY,gBAChB,SACA,eACA,MAAA,UACA,6BACD;AAED,MAAI,UAAU,SAAS,GAAG;AACxB,SAAA,KAAW,CAAC,iBAAiB,EAAC,WAAU,CAAC,CAAC;AAC1C,SAAA,GAAS,QAAQ,gCAAgC,QAAQ;;;;;;;CAQ7D,uBAAuB,gBAAkD;EACvE,MAAM,EAAC,YAAY,EAAE,EAAE,iBAAiB,EAAE,KAAI;AAC9C,MAAI,UAAU,SAAS,KAAK,eAAe,SAAS,EAGlD,QAAO,UAAU,MAAA,UAAgB,OAAM,aAAY;AACjD,SAAA,GAAS,QAAQ,2BAA2B,WAAW,eAAe;AACtE,SAAM,sBAAsB,UAAU,WAAW,eAAe;IAChE;AAEJ,SAAO;;CAGT,MAAM,oBAA6C;EACjD,MAAM,iBAAiB,MAAM,SAAS,MAAA,WAAgB,SACpD,kBAAkB,KAAK,CACxB;EACD,MAAM,gBAAgB,MAAM,MAAA;AAC5B,kBACE,gBACA,eACA,MAAA,UACA,oBACD;AACD,SAAO,eAAe,QAAO,MAAK,EAAE,kBAAkB,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"enable-analytics.js","names":[],"sources":["../../../../../zero-client/src/client/enable-analytics.ts"],"sourcesContent":["// https://www.oreilly.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html\nconst IPV4_ADDRESS_REGEX =\n /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n// This doesn't ensure a valid ipv6, but any ipv6 hostname will\n// match this regex, and no domain based hostnames will.\nconst IPV6_ADDRESS_HOSTNAME_REGEX = /^\\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\\]$/;\n\nexport const IP_ADDRESS_HOSTNAME_REGEX = new RegExp(\n `(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`,\n);\n\nexport function shouldEnableAnalytics(\n server: string | null,\n enableAnalytics = true,\n): boolean {\n if (!enableAnalytics) {\n return false;\n }\n const serverURL = server === null ? null : new URL(server);\n const socketHostname = serverURL?.hostname;\n // If the hostname is undefined, localhost, or an ip address, then\n // this is most likely a test or local development, in which case we\n // do not want to enable analytics.\n return (\n server !== null &&\n socketHostname !== undefined &&\n socketHostname !== 'localhost' &&\n !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname)\n );\n}\n"],"mappings":"AAOA,IAAa,4BAA4B,IAAI,OAC3C,IAAI,8FAAmB,OAAO,GAAG,oCAA4B,OAAO,EACtE;AAEA,SAAgB,sBACd,QACA,kBAAkB,MACT;CACT,IAAI,CAAC,iBACH,OAAO;CAGT,MAAM,kBADY,WAAW,OAAO,OAAO,IAAI,IAAI,MAAM,IACvB;CAIlC,OACE,WAAW,QACX,mBAAmB,KAAA,KACnB,mBAAmB,eACnB,CAAC,0BAA0B,KAAK,cAAc;AAElD"}
1
+ {"version":3,"file":"enable-analytics.js","names":[],"sources":["../../../../../zero-client/src/client/enable-analytics.ts"],"sourcesContent":["// https://www.oreilly.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html\nconst IPV4_ADDRESS_REGEX =\n /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n// This doesn't ensure a valid ipv6, but any ipv6 hostname will\n// match this regex, and no domain based hostnames will.\nconst IPV6_ADDRESS_HOSTNAME_REGEX = /^\\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\\]$/;\n\nexport const IP_ADDRESS_HOSTNAME_REGEX = new RegExp(\n `(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`,\n);\n\nexport function shouldEnableAnalytics(\n server: string | null,\n enableAnalytics = true,\n): boolean {\n if (!enableAnalytics) {\n return false;\n }\n const serverURL = server === null ? null : new URL(server);\n const socketHostname = serverURL?.hostname;\n // If the hostname is undefined, localhost, or an ip address, then\n // this is most likely a test or local development, in which case we\n // do not want to enable analytics.\n return (\n server !== null &&\n socketHostname !== undefined &&\n socketHostname !== 'localhost' &&\n !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname)\n );\n}\n"],"mappings":"AAOA,IAAa,4BAA4B,IAAI,OAC3C,IANA,8FAMuB,OAAO,GAHI,oCAG2B,OAAO,GACrE;AAED,SAAgB,sBACd,QACA,kBAAkB,MACT;AACT,KAAI,CAAC,gBACH,QAAO;CAGT,MAAM,kBADY,WAAW,OAAO,OAAO,IAAI,IAAI,OAAO,GACxB;AAIlC,QACE,WAAW,QACX,mBAAmB,KAAA,KACnB,mBAAmB,eACnB,CAAC,0BAA0B,KAAK,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","names":[],"sources":["../../../../../zero-client/src/client/error.ts"],"sourcesContent":["import {unreachable} from '../../../shared/src/asserts.ts';\nimport {getErrorMessage} from '../../../shared/src/error.ts';\nimport type {Expand} from '../../../shared/src/expand.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport type {ProtocolError} from '../../../zero-protocol/src/error.ts';\nimport {\n type BackoffBody,\n type ErrorBody,\n isProtocolError,\n type PushFailedBody,\n type TransformFailedBody,\n} from '../../../zero-protocol/src/error.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {ConnectionStatus} from './connection-status.ts';\n\nexport type AuthError = ProtocolError<NeedsAuthReason>;\nexport type ClientErrorBody = {\n kind: ClientErrorKind;\n origin: typeof ErrorOrigin.Client;\n message: string;\n};\nexport type ClosedError = ClientError<{\n kind: ClientErrorKind.ClientClosed;\n message: string;\n}>;\nexport type NeedsAuthReason = Expand<\n | (ErrorBody & {\n kind: ErrorKind.AuthInvalidated | ErrorKind.Unauthorized;\n })\n | (Extract<PushFailedBody, {reason: ErrorReason.HTTP}> & {status: 401 | 403})\n | (Extract<TransformFailedBody, {reason: ErrorReason.HTTP}> & {\n status: 401 | 403;\n })\n>;\nexport type OfflineError = ClientError<{\n kind: ClientErrorKind.Offline;\n message: string;\n}>;\nexport type NoSocketOriginError = ClientError<{\n kind: ClientErrorKind.NoSocketOrigin;\n message: string;\n}>;\nexport type HiddenError = ClientError<{\n kind: ClientErrorKind.Hidden;\n message: string;\n}>;\nexport type DisconnectedReason =\n | OfflineError\n | NoSocketOriginError\n | HiddenError;\nexport type ServerError = ProtocolError<ErrorBody>;\nexport type ZeroError = ServerError | ClientError;\nexport type ZeroErrorBody = Expand<ErrorBody | ClientErrorBody>;\nexport type ZeroErrorDetails = Expand<Omit<ZeroErrorBody, 'message'>>;\nexport type ZeroErrorKind = Expand<ErrorKind | ClientErrorKind>;\n\n/**\n * Represents an error encountered by the Zero client.\n */\nexport class ClientError<\n const T extends Omit<ClientErrorBody, 'origin'> = Omit<\n ClientErrorBody,\n 'origin'\n >,\n> extends Error {\n readonly errorBody: {origin: typeof ErrorOrigin.Client} & T;\n\n constructor(errorBody: T, options?: ErrorOptions) {\n super(errorBody.message, options);\n this.name = 'ClientError';\n this.errorBody = {...errorBody, origin: ErrorOrigin.Client};\n }\n\n get kind(): T['kind'] {\n return this.errorBody.kind;\n }\n}\n\nexport function isZeroError(ex: unknown): ex is ZeroError {\n return isClientError(ex) || isServerError(ex);\n}\n\nexport function isClientError(ex: unknown): ex is ClientError<ClientErrorBody> {\n return (\n ex instanceof ClientError && ex.errorBody.origin === ErrorOrigin.Client\n );\n}\n\nexport function isServerError(ex: unknown): ex is ServerError {\n return (\n isProtocolError(ex) &&\n (ex.errorBody.origin === ErrorOrigin.Server ||\n ex.errorBody.origin === ErrorOrigin.ZeroCache)\n );\n}\n\nexport function isOfflineError(ex: unknown): ex is OfflineError {\n return isClientError(ex) && ex.kind === ClientErrorKind.Offline;\n}\n\nexport function isAuthError(ex: unknown): ex is AuthError {\n if (isServerError(ex)) {\n if (\n ex.kind === ErrorKind.AuthInvalidated ||\n ex.kind === ErrorKind.Unauthorized\n ) {\n return true;\n }\n if (\n (ex.errorBody.kind === ErrorKind.PushFailed ||\n ex.errorBody.kind === ErrorKind.TransformFailed) &&\n ex.errorBody.reason === ErrorReason.HTTP &&\n (ex.errorBody.status === 401 || ex.errorBody.status === 403)\n ) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getBackoffParams(error: ZeroError): BackoffBody | undefined {\n if (isServerError(error)) {\n switch (error.errorBody.kind) {\n case ErrorKind.Rebalance:\n case ErrorKind.Rehome:\n case ErrorKind.ServerOverloaded:\n return error.errorBody;\n }\n }\n return undefined;\n}\n\nexport const NO_STATUS_TRANSITION = 'NO_STATUS_TRANSITION';\n\nexport type ErrorConnectionTransition =\n | {status: typeof NO_STATUS_TRANSITION; reason: ZeroError}\n | {status: ConnectionStatus.NeedsAuth; reason: AuthError}\n | {status: ConnectionStatus.Error; reason: ZeroError}\n | {status: ConnectionStatus.Disconnected; reason: DisconnectedReason}\n | {status: ConnectionStatus.Closed; reason: ZeroError};\n\n/**\n * Returns the status to transition to, or null if the error\n * indicates that the connection should continue in the current state.\n */\nexport function getErrorConnectionTransition(\n ex: unknown,\n): ErrorConnectionTransition {\n // Handle auth errors by transitioning to needs-auth state\n if (isAuthError(ex)) {\n return {\n status: ConnectionStatus.NeedsAuth,\n reason: ex,\n } as const;\n }\n\n if (isClientError(ex)) {\n switch (ex.kind) {\n // Connecting errors that should continue in the current state\n case ClientErrorKind.AbruptClose:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.ConnectTimeout:\n case ClientErrorKind.PingTimeout:\n case ClientErrorKind.PullTimeout:\n case ClientErrorKind.UnexpectedBaseCookie:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n // Fatal errors that should transition to error state\n case ClientErrorKind.Internal:\n case ClientErrorKind.InvalidMessage:\n case ClientErrorKind.UserDisconnect:\n return {status: ConnectionStatus.Error, reason: ex} as const;\n\n // Disconnected errors\n case ClientErrorKind.Hidden:\n case ClientErrorKind.Offline:\n case ClientErrorKind.NoSocketOrigin:\n return {\n status: ConnectionStatus.Disconnected,\n reason: ex as DisconnectedReason,\n } as const;\n\n // Closed error (this should already result in a closed state)\n case ClientErrorKind.ClientClosed:\n return {status: ConnectionStatus.Closed, reason: ex} as const;\n\n default:\n unreachable(ex.kind);\n }\n }\n\n if (isServerError(ex)) {\n switch (ex.kind) {\n // Errors that should transition to error state\n case ErrorKind.ClientNotFound:\n case ErrorKind.InvalidConnectionRequest:\n case ErrorKind.InvalidConnectionRequestBaseCookie:\n case ErrorKind.InvalidConnectionRequestLastMutationID:\n case ErrorKind.InvalidConnectionRequestClientDeleted:\n case ErrorKind.InvalidMessage:\n case ErrorKind.InvalidPush:\n case ErrorKind.VersionNotSupported:\n case ErrorKind.SchemaVersionNotSupported:\n case ErrorKind.Internal:\n // PushFailed and TransformFailed can be auth errors (401/403)\n // or other errors - handle non-auth cases here\n case ErrorKind.PushFailed:\n case ErrorKind.TransformFailed:\n return {status: ConnectionStatus.Error, reason: ex} as const;\n\n // Errors that should continue with backoff/retry\n case ErrorKind.Rebalance:\n case ErrorKind.Rehome:\n case ErrorKind.ServerOverloaded:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n // Auth errors are handled above by isAuthError check\n case ErrorKind.AuthInvalidated:\n case ErrorKind.Unauthorized:\n return {\n status: ConnectionStatus.NeedsAuth,\n reason: ex as AuthError,\n } as const;\n\n // Mutation-specific errors don't affect connection state\n case ErrorKind.MutationRateLimited:\n case ErrorKind.MutationFailed:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n default:\n unreachable(ex.kind);\n }\n }\n\n // we default to error state if we don't know what to do\n // this is a catch-all for unexpected errors\n return {\n status: ConnectionStatus.Error,\n reason: new ClientError(\n {\n kind: ClientErrorKind.Internal,\n message: 'Unexpected internal error: ' + getErrorMessage(ex),\n },\n {cause: ex},\n ),\n } as const;\n}\n"],"mappings":";;;;;;;;;;;;AA6DA,IAAa,cAAb,cAKU,MAAM;CACd;CAEA,YAAY,WAAc,SAAwB;EAChD,MAAM,UAAU,SAAS,OAAO;EAChC,KAAK,OAAO;EACZ,KAAK,YAAY;GAAC,GAAG;GAAW,QAAQ;EAAkB;CAC5D;CAEA,IAAI,OAAkB;EACpB,OAAO,KAAK,UAAU;CACxB;AACF;AAEA,SAAgB,YAAY,IAA8B;CACxD,OAAO,cAAc,EAAE,KAAK,cAAc,EAAE;AAC9C;AAEA,SAAgB,cAAc,IAAiD;CAC7E,OACE,cAAc,eAAe,GAAG,UAAU,WAAW;AAEzD;AAEA,SAAgB,cAAc,IAAgC;CAC5D,OACE,gBAAgB,EAAE,MACjB,GAAG,UAAU,WAAW,YACvB,GAAG,UAAU,WAAW;AAE9B;AAMA,SAAgB,YAAY,IAA8B;CACxD,IAAI,cAAc,EAAE,GAAG;EACrB,IACE,GAAG,SAAS,qBACZ,GAAG,SAAS,gBAEZ,OAAO;EAET,KACG,GAAG,UAAU,SAAS,gBACrB,GAAG,UAAU,SAAS,sBACxB,GAAG,UAAU,WAAW,WACvB,GAAG,UAAU,WAAW,OAAO,GAAG,UAAU,WAAW,MAExD,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAgB,iBAAiB,OAA2C;CAC1E,IAAI,cAAc,KAAK,GACrB,QAAQ,MAAM,UAAU,MAAxB;EACE,KAAK;EACL,KAAK;EACL,KAAK,kBACH,OAAO,MAAM;CACjB;AAGJ;AAEA,IAAa,uBAAuB;;;;;AAapC,SAAgB,6BACd,IAC2B;CAE3B,IAAI,YAAY,EAAE,GAChB,OAAO;EACL,QAAQ;EACR,QAAQ;CACV;CAGF,IAAI,cAAc,EAAE,GAClB,QAAQ,GAAG,MAAX;EAEE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,sBACH,OAAO;GAAC,QAAQ;GAAsB,QAAQ;EAAE;EAGlD,KAAK;EACL,KAAK;EACL,KAAK,gBACH,OAAO;GAAC,QAAQ;GAAwB,QAAQ;EAAE;EAGpD,KAAK;EACL,KAAK;EACL,KAAK,gBACH,OAAO;GACL,QAAQ;GACR,QAAQ;EACV;EAGF,KAAK,cACH,OAAO;GAAC,QAAQ;GAAyB,QAAQ;EAAE;EAErD,SACE,YAAY,GAAG,IAAI;CACvB;CAGF,IAAI,cAAc,EAAE,GAClB,QAAQ,GAAG,MAAX;EAEE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EAGL,KAAK;EACL,KAAK,iBACH,OAAO;GAAC,QAAQ;GAAwB,QAAQ;EAAE;EAGpD,KAAK;EACL,KAAK;EACL,KAAK,kBACH,OAAO;GAAC,QAAQ;GAAsB,QAAQ;EAAE;EAGlD,KAAK;EACL,KAAK,cACH,OAAO;GACL,QAAQ;GACR,QAAQ;EACV;EAGF,KAAK;EACL,KAAK,gBACH,OAAO;GAAC,QAAQ;GAAsB,QAAQ;EAAE;EAElD,SACE,YAAY,GAAG,IAAI;CACvB;CAKF,OAAO;EACL,QAAQ;EACR,QAAQ,IAAI,YACV;GACE,MAAM;GACN,SAAS,gCAAgC,gBAAgB,EAAE;EAC7D,GACA,EAAC,OAAO,GAAE,CACZ;CACF;AACF"}
1
+ {"version":3,"file":"error.js","names":[],"sources":["../../../../../zero-client/src/client/error.ts"],"sourcesContent":["import {unreachable} from '../../../shared/src/asserts.ts';\nimport {getErrorMessage} from '../../../shared/src/error.ts';\nimport type {Expand} from '../../../shared/src/expand.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport type {ProtocolError} from '../../../zero-protocol/src/error.ts';\nimport {\n type BackoffBody,\n type ErrorBody,\n isProtocolError,\n type PushFailedBody,\n type TransformFailedBody,\n} from '../../../zero-protocol/src/error.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {ConnectionStatus} from './connection-status.ts';\n\nexport type AuthError = ProtocolError<NeedsAuthReason>;\nexport type ClientErrorBody = {\n kind: ClientErrorKind;\n origin: typeof ErrorOrigin.Client;\n message: string;\n};\nexport type ClosedError = ClientError<{\n kind: ClientErrorKind.ClientClosed;\n message: string;\n}>;\nexport type NeedsAuthReason = Expand<\n | (ErrorBody & {\n kind: ErrorKind.AuthInvalidated | ErrorKind.Unauthorized;\n })\n | (Extract<PushFailedBody, {reason: ErrorReason.HTTP}> & {status: 401 | 403})\n | (Extract<TransformFailedBody, {reason: ErrorReason.HTTP}> & {\n status: 401 | 403;\n })\n>;\nexport type OfflineError = ClientError<{\n kind: ClientErrorKind.Offline;\n message: string;\n}>;\nexport type NoSocketOriginError = ClientError<{\n kind: ClientErrorKind.NoSocketOrigin;\n message: string;\n}>;\nexport type HiddenError = ClientError<{\n kind: ClientErrorKind.Hidden;\n message: string;\n}>;\nexport type DisconnectedReason =\n | OfflineError\n | NoSocketOriginError\n | HiddenError;\nexport type ServerError = ProtocolError<ErrorBody>;\nexport type ZeroError = ServerError | ClientError;\nexport type ZeroErrorBody = Expand<ErrorBody | ClientErrorBody>;\nexport type ZeroErrorDetails = Expand<Omit<ZeroErrorBody, 'message'>>;\nexport type ZeroErrorKind = Expand<ErrorKind | ClientErrorKind>;\n\n/**\n * Represents an error encountered by the Zero client.\n */\nexport class ClientError<\n const T extends Omit<ClientErrorBody, 'origin'> = Omit<\n ClientErrorBody,\n 'origin'\n >,\n> extends Error {\n readonly errorBody: {origin: typeof ErrorOrigin.Client} & T;\n\n constructor(errorBody: T, options?: ErrorOptions) {\n super(errorBody.message, options);\n this.name = 'ClientError';\n this.errorBody = {...errorBody, origin: ErrorOrigin.Client};\n }\n\n get kind(): T['kind'] {\n return this.errorBody.kind;\n }\n}\n\nexport function isZeroError(ex: unknown): ex is ZeroError {\n return isClientError(ex) || isServerError(ex);\n}\n\nexport function isClientError(ex: unknown): ex is ClientError<ClientErrorBody> {\n return (\n ex instanceof ClientError && ex.errorBody.origin === ErrorOrigin.Client\n );\n}\n\nexport function isServerError(ex: unknown): ex is ServerError {\n return (\n isProtocolError(ex) &&\n (ex.errorBody.origin === ErrorOrigin.Server ||\n ex.errorBody.origin === ErrorOrigin.ZeroCache)\n );\n}\n\nexport function isOfflineError(ex: unknown): ex is OfflineError {\n return isClientError(ex) && ex.kind === ClientErrorKind.Offline;\n}\n\nexport function isAuthError(ex: unknown): ex is AuthError {\n if (isServerError(ex)) {\n if (\n ex.kind === ErrorKind.AuthInvalidated ||\n ex.kind === ErrorKind.Unauthorized\n ) {\n return true;\n }\n if (\n (ex.errorBody.kind === ErrorKind.PushFailed ||\n ex.errorBody.kind === ErrorKind.TransformFailed) &&\n ex.errorBody.reason === ErrorReason.HTTP &&\n (ex.errorBody.status === 401 || ex.errorBody.status === 403)\n ) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getBackoffParams(error: ZeroError): BackoffBody | undefined {\n if (isServerError(error)) {\n switch (error.errorBody.kind) {\n case ErrorKind.Rebalance:\n case ErrorKind.Rehome:\n case ErrorKind.ServerOverloaded:\n return error.errorBody;\n }\n }\n return undefined;\n}\n\nexport const NO_STATUS_TRANSITION = 'NO_STATUS_TRANSITION';\n\nexport type ErrorConnectionTransition =\n | {status: typeof NO_STATUS_TRANSITION; reason: ZeroError}\n | {status: ConnectionStatus.NeedsAuth; reason: AuthError}\n | {status: ConnectionStatus.Error; reason: ZeroError}\n | {status: ConnectionStatus.Disconnected; reason: DisconnectedReason}\n | {status: ConnectionStatus.Closed; reason: ZeroError};\n\n/**\n * Returns the status to transition to, or null if the error\n * indicates that the connection should continue in the current state.\n */\nexport function getErrorConnectionTransition(\n ex: unknown,\n): ErrorConnectionTransition {\n // Handle auth errors by transitioning to needs-auth state\n if (isAuthError(ex)) {\n return {\n status: ConnectionStatus.NeedsAuth,\n reason: ex,\n } as const;\n }\n\n if (isClientError(ex)) {\n switch (ex.kind) {\n // Connecting errors that should continue in the current state\n case ClientErrorKind.AbruptClose:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.ConnectTimeout:\n case ClientErrorKind.PingTimeout:\n case ClientErrorKind.PullTimeout:\n case ClientErrorKind.UnexpectedBaseCookie:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n // Fatal errors that should transition to error state\n case ClientErrorKind.Internal:\n case ClientErrorKind.InvalidMessage:\n case ClientErrorKind.UserDisconnect:\n return {status: ConnectionStatus.Error, reason: ex} as const;\n\n // Disconnected errors\n case ClientErrorKind.Hidden:\n case ClientErrorKind.Offline:\n case ClientErrorKind.NoSocketOrigin:\n return {\n status: ConnectionStatus.Disconnected,\n reason: ex as DisconnectedReason,\n } as const;\n\n // Closed error (this should already result in a closed state)\n case ClientErrorKind.ClientClosed:\n return {status: ConnectionStatus.Closed, reason: ex} as const;\n\n default:\n unreachable(ex.kind);\n }\n }\n\n if (isServerError(ex)) {\n switch (ex.kind) {\n // Errors that should transition to error state\n case ErrorKind.ClientNotFound:\n case ErrorKind.InvalidConnectionRequest:\n case ErrorKind.InvalidConnectionRequestBaseCookie:\n case ErrorKind.InvalidConnectionRequestLastMutationID:\n case ErrorKind.InvalidConnectionRequestClientDeleted:\n case ErrorKind.InvalidMessage:\n case ErrorKind.InvalidPush:\n case ErrorKind.VersionNotSupported:\n case ErrorKind.SchemaVersionNotSupported:\n case ErrorKind.Internal:\n // PushFailed and TransformFailed can be auth errors (401/403)\n // or other errors - handle non-auth cases here\n case ErrorKind.PushFailed:\n case ErrorKind.TransformFailed:\n return {status: ConnectionStatus.Error, reason: ex} as const;\n\n // Errors that should continue with backoff/retry\n case ErrorKind.Rebalance:\n case ErrorKind.Rehome:\n case ErrorKind.ServerOverloaded:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n // Auth errors are handled above by isAuthError check\n case ErrorKind.AuthInvalidated:\n case ErrorKind.Unauthorized:\n return {\n status: ConnectionStatus.NeedsAuth,\n reason: ex as AuthError,\n } as const;\n\n // Mutation-specific errors don't affect connection state\n case ErrorKind.MutationRateLimited:\n case ErrorKind.MutationFailed:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n default:\n unreachable(ex.kind);\n }\n }\n\n // we default to error state if we don't know what to do\n // this is a catch-all for unexpected errors\n return {\n status: ConnectionStatus.Error,\n reason: new ClientError(\n {\n kind: ClientErrorKind.Internal,\n message: 'Unexpected internal error: ' + getErrorMessage(ex),\n },\n {cause: ex},\n ),\n } as const;\n}\n"],"mappings":";;;;;;;;;;;;AA6DA,IAAa,cAAb,cAKU,MAAM;CACd;CAEA,YAAY,WAAc,SAAwB;AAChD,QAAM,UAAU,SAAS,QAAQ;AACjC,OAAK,OAAO;AACZ,OAAK,YAAY;GAAC,GAAG;GAAW,QAAQ;GAAmB;;CAG7D,IAAI,OAAkB;AACpB,SAAO,KAAK,UAAU;;;AAI1B,SAAgB,YAAY,IAA8B;AACxD,QAAO,cAAc,GAAG,IAAI,cAAc,GAAG;;AAG/C,SAAgB,cAAc,IAAiD;AAC7E,QACE,cAAc,eAAe,GAAG,UAAU,WAAW;;AAIzD,SAAgB,cAAc,IAAgC;AAC5D,QACE,gBAAgB,GAAG,KAClB,GAAG,UAAU,WAAW,YACvB,GAAG,UAAU,WAAW;;AAQ9B,SAAgB,YAAY,IAA8B;AACxD,KAAI,cAAc,GAAG,EAAE;AACrB,MACE,GAAG,SAAS,qBACZ,GAAG,SAAS,eAEZ,QAAO;AAET,OACG,GAAG,UAAU,SAAS,gBACrB,GAAG,UAAU,SAAS,sBACxB,GAAG,UAAU,WAAW,WACvB,GAAG,UAAU,WAAW,OAAO,GAAG,UAAU,WAAW,KAExD,QAAO;;AAIX,QAAO;;AAGT,SAAgB,iBAAiB,OAA2C;AAC1E,KAAI,cAAc,MAAM,CACtB,SAAQ,MAAM,UAAU,MAAxB;EACE,KAAK;EACL,KAAK;EACL,KAAK,iBACH,QAAO,MAAM;;;AAMrB,IAAa,uBAAuB;;;;;AAapC,SAAgB,6BACd,IAC2B;AAE3B,KAAI,YAAY,GAAG,CACjB,QAAO;EACL,QAAQ;EACR,QAAQ;EACT;AAGH,KAAI,cAAc,GAAG,CACnB,SAAQ,GAAG,MAAX;EAEE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,qBACH,QAAO;GAAC,QAAQ;GAAsB,QAAQ;GAAG;EAGnD,KAAK;EACL,KAAK;EACL,KAAK,eACH,QAAO;GAAC,QAAQ;GAAwB,QAAQ;GAAG;EAGrD,KAAK;EACL,KAAK;EACL,KAAK,eACH,QAAO;GACL,QAAQ;GACR,QAAQ;GACT;EAGH,KAAK,aACH,QAAO;GAAC,QAAQ;GAAyB,QAAQ;GAAG;EAEtD,QACE,aAAY,GAAG,KAAK;;AAI1B,KAAI,cAAc,GAAG,CACnB,SAAQ,GAAG,MAAX;EAEE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EAGL,KAAK;EACL,KAAK,gBACH,QAAO;GAAC,QAAQ;GAAwB,QAAQ;GAAG;EAGrD,KAAK;EACL,KAAK;EACL,KAAK,iBACH,QAAO;GAAC,QAAQ;GAAsB,QAAQ;GAAG;EAGnD,KAAK;EACL,KAAK,aACH,QAAO;GACL,QAAQ;GACR,QAAQ;GACT;EAGH,KAAK;EACL,KAAK,eACH,QAAO;GAAC,QAAQ;GAAsB,QAAQ;GAAG;EAEnD,QACE,aAAY,GAAG,KAAK;;AAM1B,QAAO;EACL,QAAQ;EACR,QAAQ,IAAI,YACV;GACE,MAAM;GACN,SAAS,gCAAgC,gBAAgB,GAAG;GAC7D,EACD,EAAC,OAAO,IAAG,CACZ;EACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"http-string.js","names":[],"sources":["../../../../../zero-client/src/client/http-string.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\n\nexport type HTTPString = `http${'' | 's'}://${string}`;\n\nexport type WSString = `ws${'' | 's'}://${string}`;\n\nexport function toWSString(url: HTTPString): WSString {\n return ('ws' + url.slice(4)) as WSString;\n}\n\nexport function toHTTPString(url: WSString): HTTPString {\n return ('http' + url.slice(2)) as HTTPString;\n}\n\nconst httpsRe = /^https?:\\/\\//;\n\nexport function assertHTTPString(url: string): asserts url is HTTPString {\n assert(httpsRe.test(url), () => `Expected HTTP(S) URL, got \"${url}\"`);\n}\n\nconst wssRe = /^wss?:\\/\\//;\n\nexport function assertWSString(url: string): asserts url is WSString {\n assert(wssRe.test(url), () => `Expected WS(S) URL, got \"${url}\"`);\n}\n\nexport function appendPath<T extends HTTPString | WSString>(\n url: T,\n toAppend: `/${string}`,\n): T {\n return (url + (url.endsWith('/') ? toAppend.substring(1) : toAppend)) as T;\n}\n"],"mappings":";AAMA,SAAgB,WAAW,KAA2B;CACpD,OAAQ,OAAO,IAAI,MAAM,CAAC;AAC5B;AAkBA,SAAgB,WACd,KACA,UACG;CACH,OAAQ,OAAO,IAAI,SAAS,GAAG,IAAI,SAAS,UAAU,CAAC,IAAI;AAC7D"}
1
+ {"version":3,"file":"http-string.js","names":[],"sources":["../../../../../zero-client/src/client/http-string.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\n\nexport type HTTPString = `http${'' | 's'}://${string}`;\n\nexport type WSString = `ws${'' | 's'}://${string}`;\n\nexport function toWSString(url: HTTPString): WSString {\n return ('ws' + url.slice(4)) as WSString;\n}\n\nexport function toHTTPString(url: WSString): HTTPString {\n return ('http' + url.slice(2)) as HTTPString;\n}\n\nconst httpsRe = /^https?:\\/\\//;\n\nexport function assertHTTPString(url: string): asserts url is HTTPString {\n assert(httpsRe.test(url), () => `Expected HTTP(S) URL, got \"${url}\"`);\n}\n\nconst wssRe = /^wss?:\\/\\//;\n\nexport function assertWSString(url: string): asserts url is WSString {\n assert(wssRe.test(url), () => `Expected WS(S) URL, got \"${url}\"`);\n}\n\nexport function appendPath<T extends HTTPString | WSString>(\n url: T,\n toAppend: `/${string}`,\n): T {\n return (url + (url.endsWith('/') ? toAppend.substring(1) : toAppend)) as T;\n}\n"],"mappings":";AAMA,SAAgB,WAAW,KAA2B;AACpD,QAAQ,OAAO,IAAI,MAAM,EAAE;;AAmB7B,SAAgB,WACd,KACA,UACG;AACH,QAAQ,OAAO,IAAI,SAAS,IAAI,GAAG,SAAS,UAAU,EAAE,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"client-group.js","names":["#delegate"],"sources":["../../../../../../zero-client/src/client/inspector/client-group.ts"],"sourcesContent":["import type {Client} from './client.ts';\nimport type {ExtendedInspectorDelegate} from './lazy-inspector.ts';\nimport type {Query} from './query.ts';\n\nexport class ClientGroup {\n readonly #delegate: ExtendedInspectorDelegate;\n readonly id: Promise<string> | string;\n\n constructor(\n delegate: ExtendedInspectorDelegate,\n clientGroupID: Promise<string> | string,\n ) {\n this.#delegate = delegate;\n this.id = clientGroupID;\n }\n\n async clients(): Promise<Client[]> {\n return (await this.#delegate.lazy).clientGroupClients(\n this.#delegate,\n this.id,\n );\n }\n\n async clientsWithQueries(): Promise<Client[]> {\n return (await this.#delegate.lazy).clientGroupClientsWithQueries(\n this.#delegate,\n this.id,\n );\n }\n\n async queries(): Promise<Query[]> {\n return (await this.#delegate.lazy).clientGroupQueries(this.#delegate);\n }\n}\n"],"mappings":";AAIA,IAAa,cAAb,MAAyB;CACvB;CACA;CAEA,YACE,UACA,eACA;EACA,KAAKA,YAAY;EACjB,KAAK,KAAK;CACZ;CAEA,MAAM,UAA6B;EACjC,QAAQ,MAAM,KAAKA,UAAU,MAAM,mBACjC,KAAKA,WACL,KAAK,EACP;CACF;CAEA,MAAM,qBAAwC;EAC5C,QAAQ,MAAM,KAAKA,UAAU,MAAM,8BACjC,KAAKA,WACL,KAAK,EACP;CACF;CAEA,MAAM,UAA4B;EAChC,QAAQ,MAAM,KAAKA,UAAU,MAAM,mBAAmB,KAAKA,SAAS;CACtE;AACF"}
1
+ {"version":3,"file":"client-group.js","names":["#delegate"],"sources":["../../../../../../zero-client/src/client/inspector/client-group.ts"],"sourcesContent":["import type {Client} from './client.ts';\nimport type {ExtendedInspectorDelegate} from './lazy-inspector.ts';\nimport type {Query} from './query.ts';\n\nexport class ClientGroup {\n readonly #delegate: ExtendedInspectorDelegate;\n readonly id: Promise<string> | string;\n\n constructor(\n delegate: ExtendedInspectorDelegate,\n clientGroupID: Promise<string> | string,\n ) {\n this.#delegate = delegate;\n this.id = clientGroupID;\n }\n\n async clients(): Promise<Client[]> {\n return (await this.#delegate.lazy).clientGroupClients(\n this.#delegate,\n this.id,\n );\n }\n\n async clientsWithQueries(): Promise<Client[]> {\n return (await this.#delegate.lazy).clientGroupClientsWithQueries(\n this.#delegate,\n this.id,\n );\n }\n\n async queries(): Promise<Query[]> {\n return (await this.#delegate.lazy).clientGroupQueries(this.#delegate);\n }\n}\n"],"mappings":";AAIA,IAAa,cAAb,MAAyB;CACvB;CACA;CAEA,YACE,UACA,eACA;AACA,QAAA,WAAiB;AACjB,OAAK,KAAK;;CAGZ,MAAM,UAA6B;AACjC,UAAQ,MAAM,MAAA,SAAe,MAAM,mBACjC,MAAA,UACA,KAAK,GACN;;CAGH,MAAM,qBAAwC;AAC5C,UAAQ,MAAM,MAAA,SAAe,MAAM,8BACjC,MAAA,UACA,KAAK,GACN;;CAGH,MAAM,UAA4B;AAChC,UAAQ,MAAM,MAAA,SAAe,MAAM,mBAAmB,MAAA,SAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["#delegate"],"sources":["../../../../../../zero-client/src/client/inspector/client.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport type {Row} from '../../../../zero-protocol/src/data.ts';\nimport {ClientGroup} from './client-group.ts';\nimport type {ExtendedInspectorDelegate} from './lazy-inspector.ts';\nimport type {Query} from './query.ts';\n\nexport class Client {\n readonly #delegate: ExtendedInspectorDelegate;\n readonly id: string;\n readonly clientGroup: ClientGroup;\n\n constructor(\n delegate: ExtendedInspectorDelegate,\n clientID: string,\n clientGroupID: Promise<string> | string,\n ) {\n this.#delegate = delegate;\n this.id = clientID;\n\n this.clientGroup = new ClientGroup(this.#delegate, clientGroupID);\n }\n\n async queries(): Promise<Query[]> {\n return (await this.#delegate.lazy).clientQueries(this.#delegate, this.id);\n }\n\n async map(): Promise<Map<string, ReadonlyJSONValue>> {\n return (await this.#delegate.lazy).clientMap(this.#delegate, this.id);\n }\n\n async rows(tableName: string): Promise<Row[]> {\n return (await this.#delegate.lazy).clientRows(\n this.#delegate,\n this.id,\n tableName,\n );\n }\n}\n"],"mappings":";;AAMA,IAAa,SAAb,MAAoB;CAClB;CACA;CACA;CAEA,YACE,UACA,UACA,eACA;EACA,KAAKA,YAAY;EACjB,KAAK,KAAK;EAEV,KAAK,cAAc,IAAI,YAAY,KAAKA,WAAW,aAAa;CAClE;CAEA,MAAM,UAA4B;EAChC,QAAQ,MAAM,KAAKA,UAAU,MAAM,cAAc,KAAKA,WAAW,KAAK,EAAE;CAC1E;CAEA,MAAM,MAA+C;EACnD,QAAQ,MAAM,KAAKA,UAAU,MAAM,UAAU,KAAKA,WAAW,KAAK,EAAE;CACtE;CAEA,MAAM,KAAK,WAAmC;EAC5C,QAAQ,MAAM,KAAKA,UAAU,MAAM,WACjC,KAAKA,WACL,KAAK,IACL,SACF;CACF;AACF"}
1
+ {"version":3,"file":"client.js","names":["#delegate"],"sources":["../../../../../../zero-client/src/client/inspector/client.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport type {Row} from '../../../../zero-protocol/src/data.ts';\nimport {ClientGroup} from './client-group.ts';\nimport type {ExtendedInspectorDelegate} from './lazy-inspector.ts';\nimport type {Query} from './query.ts';\n\nexport class Client {\n readonly #delegate: ExtendedInspectorDelegate;\n readonly id: string;\n readonly clientGroup: ClientGroup;\n\n constructor(\n delegate: ExtendedInspectorDelegate,\n clientID: string,\n clientGroupID: Promise<string> | string,\n ) {\n this.#delegate = delegate;\n this.id = clientID;\n\n this.clientGroup = new ClientGroup(this.#delegate, clientGroupID);\n }\n\n async queries(): Promise<Query[]> {\n return (await this.#delegate.lazy).clientQueries(this.#delegate, this.id);\n }\n\n async map(): Promise<Map<string, ReadonlyJSONValue>> {\n return (await this.#delegate.lazy).clientMap(this.#delegate, this.id);\n }\n\n async rows(tableName: string): Promise<Row[]> {\n return (await this.#delegate.lazy).clientRows(\n this.#delegate,\n this.id,\n tableName,\n );\n }\n}\n"],"mappings":";;AAMA,IAAa,SAAb,MAAoB;CAClB;CACA;CACA;CAEA,YACE,UACA,UACA,eACA;AACA,QAAA,WAAiB;AACjB,OAAK,KAAK;AAEV,OAAK,cAAc,IAAI,YAAY,MAAA,UAAgB,cAAc;;CAGnE,MAAM,UAA4B;AAChC,UAAQ,MAAM,MAAA,SAAe,MAAM,cAAc,MAAA,UAAgB,KAAK,GAAG;;CAG3E,MAAM,MAA+C;AACnD,UAAQ,MAAM,MAAA,SAAe,MAAM,UAAU,MAAA,UAAgB,KAAK,GAAG;;CAGvE,MAAM,KAAK,WAAmC;AAC5C,UAAQ,MAAM,MAAA,SAAe,MAAM,WACjC,MAAA,UACA,KAAK,IACL,UACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"html-dialog-prompt.js","names":[],"sources":["../../../../../../zero-client/src/client/inspector/html-dialog-prompt.ts"],"sourcesContent":["/**\n * Checks if we can create HTML elements and are in a browser document context\n */\nfunction canUseHTMLDialog(): boolean {\n try {\n // Check if we're in a test environment (vitest sets this)\n if (\n typeof globalThis !== 'undefined' &&\n '__vitest_worker__' in globalThis\n ) {\n return false;\n }\n\n return (\n typeof document !== 'undefined' &&\n typeof document.createElement === 'function' &&\n typeof HTMLDialogElement !== 'undefined' &&\n document.body !== null &&\n // Make sure we can actually create a dialog element\n document.createElement('dialog') instanceof HTMLDialogElement\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Creates a password prompt using HTML <dialog> element\n */\nexport function createHTMLPasswordPrompt(\n message: string,\n): Promise<string | null> {\n if (!canUseHTMLDialog()) {\n // Fallback to browser prompt if HTML dialog is not available\n return Promise.resolve(prompt(message));\n }\n\n return new Promise<string | null>(resolve => {\n // Shared CSS constants\n const reset = 'all:revert;';\n const w = 'rgba(255,255,255,';\n const white = w + '1)';\n const whiteTransp = w + '0.4)';\n const r1 = '0.25rem';\n const font = `font-family:system-ui,sans-serif;color:${white};`;\n const btnBase = `${reset}${font}cursor:pointer;font-size:1rem;font-weight:500;border:none;padding:0.4rem 0.75rem;border-radius:${r1};background:`;\n\n const dialog = document.createElement('dialog');\n dialog.style.cssText = `${reset}${font}background:rgba(0,0,0,0.95);padding:2rem;border:1px solid ${whiteTransp};border-radius:0.5rem;`;\n\n // Prevent keydown from escaping the dialog which can be interfered by other\n // listeners (e.g. global hotkeys)\n dialog.addEventListener('keydown', e => {\n e.stopPropagation();\n });\n\n dialog.oncancel = () => {\n dialog.remove();\n resolve(null);\n };\n\n const form = document.createElement('form');\n form.method = 'dialog';\n form.style.cssText = `${reset}margin:0;`;\n\n const messagePara = document.createElement('p');\n messagePara.style.cssText = `${reset}${font}font-size:1.5rem;margin:0 0 1rem 0;`;\n messagePara.append(message);\n\n const passwordInput = document.createElement('input');\n passwordInput.type = 'password';\n passwordInput.placeholder = 'Admin password';\n passwordInput.autocomplete = 'current-password';\n passwordInput.autofocus = true;\n passwordInput.style.cssText = `${reset}${font}font-size:1rem;display:block;margin:0 0 1rem 0;padding:0.5rem;background:rgba(0,0,0,0.5);border:1px solid ${whiteTransp};border-radius:${r1};`;\n\n const buttonDiv = document.createElement('div');\n buttonDiv.style.cssText = reset;\n\n const cancelBtn = document.createElement('button');\n cancelBtn.type = 'reset';\n cancelBtn.append('Cancel');\n cancelBtn.style.cssText = btnBase + w + '0.25);';\n\n const okBtn = document.createElement('button');\n okBtn.type = 'submit';\n okBtn.value = 'ok';\n okBtn.append('OK');\n okBtn.style.cssText = btnBase + 'rgba(19,106,235,1);margin-right:0.5rem;';\n\n buttonDiv.append(okBtn, cancelBtn);\n form.append(messagePara, passwordInput, buttonDiv);\n dialog.append(form);\n\n form.onreset = () => {\n dialog.close();\n };\n\n dialog.onclose = () => {\n if (dialog.returnValue === 'ok') {\n resolve(passwordInput.value || null);\n } else {\n resolve(null);\n }\n dialog.remove();\n };\n\n document.body.append(dialog);\n dialog.showModal();\n });\n}\n"],"mappings":";;;;AAGA,SAAS,mBAA4B;CACnC,IAAI;EAEF,IACE,OAAO,eAAe,eACtB,uBAAuB,YAEvB,OAAO;EAGT,OACE,OAAO,aAAa,eACpB,OAAO,SAAS,kBAAkB,cAClC,OAAO,sBAAsB,eAC7B,SAAS,SAAS,QAElB,SAAS,cAAc,QAAQ,aAAa;CAEhD,QAAQ;EACN,OAAO;CACT;AACF;;;;AAKA,SAAgB,yBACd,SACwB;CACxB,IAAI,CAAC,iBAAiB,GAEpB,OAAO,QAAQ,QAAQ,OAAO,OAAO,CAAC;CAGxC,OAAO,IAAI,SAAuB,YAAW;EAE3C,MAAM,QAAQ;EACd,MAAM,IAAI;EACV,MAAM,QAAQ,IAAI;EAClB,MAAM,cAAc,IAAI;EACxB,MAAM,KAAK;EACX,MAAM,OAAO,0CAA0C,MAAM;EAC7D,MAAM,UAAU,GAAG,QAAQ,KAAK,iGAAiG,GAAG;EAEpI,MAAM,SAAS,SAAS,cAAc,QAAQ;EAC9C,OAAO,MAAM,UAAU,GAAG,QAAQ,KAAK,4DAA4D,YAAY;EAI/G,OAAO,iBAAiB,YAAW,MAAK;GACtC,EAAE,gBAAgB;EACpB,CAAC;EAED,OAAO,iBAAiB;GACtB,OAAO,OAAO;GACd,QAAQ,IAAI;EACd;EAEA,MAAM,OAAO,SAAS,cAAc,MAAM;EAC1C,KAAK,SAAS;EACd,KAAK,MAAM,UAAU,GAAG,MAAM;EAE9B,MAAM,cAAc,SAAS,cAAc,GAAG;EAC9C,YAAY,MAAM,UAAU,GAAG,QAAQ,KAAK;EAC5C,YAAY,OAAO,OAAO;EAE1B,MAAM,gBAAgB,SAAS,cAAc,OAAO;EACpD,cAAc,OAAO;EACrB,cAAc,cAAc;EAC5B,cAAc,eAAe;EAC7B,cAAc,YAAY;EAC1B,cAAc,MAAM,UAAU,GAAG,QAAQ,KAAK,4GAA4G,YAAY,iBAAiB,GAAG;EAE1L,MAAM,YAAY,SAAS,cAAc,KAAK;EAC9C,UAAU,MAAM,UAAU;EAE1B,MAAM,YAAY,SAAS,cAAc,QAAQ;EACjD,UAAU,OAAO;EACjB,UAAU,OAAO,QAAQ;EACzB,UAAU,MAAM,UAAU,UAAU,IAAI;EAExC,MAAM,QAAQ,SAAS,cAAc,QAAQ;EAC7C,MAAM,OAAO;EACb,MAAM,QAAQ;EACd,MAAM,OAAO,IAAI;EACjB,MAAM,MAAM,UAAU,UAAU;EAEhC,UAAU,OAAO,OAAO,SAAS;EACjC,KAAK,OAAO,aAAa,eAAe,SAAS;EACjD,OAAO,OAAO,IAAI;EAElB,KAAK,gBAAgB;GACnB,OAAO,MAAM;EACf;EAEA,OAAO,gBAAgB;GACrB,IAAI,OAAO,gBAAgB,MACzB,QAAQ,cAAc,SAAS,IAAI;QAEnC,QAAQ,IAAI;GAEd,OAAO,OAAO;EAChB;EAEA,SAAS,KAAK,OAAO,MAAM;EAC3B,OAAO,UAAU;CACnB,CAAC;AACH"}
1
+ {"version":3,"file":"html-dialog-prompt.js","names":[],"sources":["../../../../../../zero-client/src/client/inspector/html-dialog-prompt.ts"],"sourcesContent":["/**\n * Checks if we can create HTML elements and are in a browser document context\n */\nfunction canUseHTMLDialog(): boolean {\n try {\n // Check if we're in a test environment (vitest sets this)\n if (\n typeof globalThis !== 'undefined' &&\n '__vitest_worker__' in globalThis\n ) {\n return false;\n }\n\n return (\n typeof document !== 'undefined' &&\n typeof document.createElement === 'function' &&\n typeof HTMLDialogElement !== 'undefined' &&\n document.body !== null &&\n // Make sure we can actually create a dialog element\n document.createElement('dialog') instanceof HTMLDialogElement\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Creates a password prompt using HTML <dialog> element\n */\nexport function createHTMLPasswordPrompt(\n message: string,\n): Promise<string | null> {\n if (!canUseHTMLDialog()) {\n // Fallback to browser prompt if HTML dialog is not available\n return Promise.resolve(prompt(message));\n }\n\n return new Promise<string | null>(resolve => {\n // Shared CSS constants\n const reset = 'all:revert;';\n const w = 'rgba(255,255,255,';\n const white = w + '1)';\n const whiteTransp = w + '0.4)';\n const r1 = '0.25rem';\n const font = `font-family:system-ui,sans-serif;color:${white};`;\n const btnBase = `${reset}${font}cursor:pointer;font-size:1rem;font-weight:500;border:none;padding:0.4rem 0.75rem;border-radius:${r1};background:`;\n\n const dialog = document.createElement('dialog');\n dialog.style.cssText = `${reset}${font}background:rgba(0,0,0,0.95);padding:2rem;border:1px solid ${whiteTransp};border-radius:0.5rem;`;\n\n // Prevent keydown from escaping the dialog which can be interfered by other\n // listeners (e.g. global hotkeys)\n dialog.addEventListener('keydown', e => {\n e.stopPropagation();\n });\n\n dialog.oncancel = () => {\n dialog.remove();\n resolve(null);\n };\n\n const form = document.createElement('form');\n form.method = 'dialog';\n form.style.cssText = `${reset}margin:0;`;\n\n const messagePara = document.createElement('p');\n messagePara.style.cssText = `${reset}${font}font-size:1.5rem;margin:0 0 1rem 0;`;\n messagePara.append(message);\n\n const passwordInput = document.createElement('input');\n passwordInput.type = 'password';\n passwordInput.placeholder = 'Admin password';\n passwordInput.autocomplete = 'current-password';\n passwordInput.autofocus = true;\n passwordInput.style.cssText = `${reset}${font}font-size:1rem;display:block;margin:0 0 1rem 0;padding:0.5rem;background:rgba(0,0,0,0.5);border:1px solid ${whiteTransp};border-radius:${r1};`;\n\n const buttonDiv = document.createElement('div');\n buttonDiv.style.cssText = reset;\n\n const cancelBtn = document.createElement('button');\n cancelBtn.type = 'reset';\n cancelBtn.append('Cancel');\n cancelBtn.style.cssText = btnBase + w + '0.25);';\n\n const okBtn = document.createElement('button');\n okBtn.type = 'submit';\n okBtn.value = 'ok';\n okBtn.append('OK');\n okBtn.style.cssText = btnBase + 'rgba(19,106,235,1);margin-right:0.5rem;';\n\n buttonDiv.append(okBtn, cancelBtn);\n form.append(messagePara, passwordInput, buttonDiv);\n dialog.append(form);\n\n form.onreset = () => {\n dialog.close();\n };\n\n dialog.onclose = () => {\n if (dialog.returnValue === 'ok') {\n resolve(passwordInput.value || null);\n } else {\n resolve(null);\n }\n dialog.remove();\n };\n\n document.body.append(dialog);\n dialog.showModal();\n });\n}\n"],"mappings":";;;;AAGA,SAAS,mBAA4B;AACnC,KAAI;AAEF,MACE,OAAO,eAAe,eACtB,uBAAuB,WAEvB,QAAO;AAGT,SACE,OAAO,aAAa,eACpB,OAAO,SAAS,kBAAkB,cAClC,OAAO,sBAAsB,eAC7B,SAAS,SAAS,QAElB,SAAS,cAAc,SAAS,YAAY;SAExC;AACN,SAAO;;;;;;AAOX,SAAgB,yBACd,SACwB;AACxB,KAAI,CAAC,kBAAkB,CAErB,QAAO,QAAQ,QAAQ,OAAO,QAAQ,CAAC;AAGzC,QAAO,IAAI,SAAuB,YAAW;EAE3C,MAAM,QAAQ;EACd,MAAM,IAAI;EACV,MAAM,QAAQ,IAAI;EAClB,MAAM,cAAc,IAAI;EACxB,MAAM,KAAK;EACX,MAAM,OAAO,0CAA0C,MAAM;EAC7D,MAAM,UAAU,GAAG,QAAQ,KAAK,iGAAiG,GAAG;EAEpI,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,SAAO,MAAM,UAAU,GAAG,QAAQ,KAAK,4DAA4D,YAAY;AAI/G,SAAO,iBAAiB,YAAW,MAAK;AACtC,KAAE,iBAAiB;IACnB;AAEF,SAAO,iBAAiB;AACtB,UAAO,QAAQ;AACf,WAAQ,KAAK;;EAGf,MAAM,OAAO,SAAS,cAAc,OAAO;AAC3C,OAAK,SAAS;AACd,OAAK,MAAM,UAAU,GAAG,MAAM;EAE9B,MAAM,cAAc,SAAS,cAAc,IAAI;AAC/C,cAAY,MAAM,UAAU,GAAG,QAAQ,KAAK;AAC5C,cAAY,OAAO,QAAQ;EAE3B,MAAM,gBAAgB,SAAS,cAAc,QAAQ;AACrD,gBAAc,OAAO;AACrB,gBAAc,cAAc;AAC5B,gBAAc,eAAe;AAC7B,gBAAc,YAAY;AAC1B,gBAAc,MAAM,UAAU,GAAG,QAAQ,KAAK,4GAA4G,YAAY,iBAAiB,GAAG;EAE1L,MAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,YAAU,MAAM,UAAU;EAE1B,MAAM,YAAY,SAAS,cAAc,SAAS;AAClD,YAAU,OAAO;AACjB,YAAU,OAAO,SAAS;AAC1B,YAAU,MAAM,UAAU,UAAU,IAAI;EAExC,MAAM,QAAQ,SAAS,cAAc,SAAS;AAC9C,QAAM,OAAO;AACb,QAAM,QAAQ;AACd,QAAM,OAAO,KAAK;AAClB,QAAM,MAAM,UAAU,UAAU;AAEhC,YAAU,OAAO,OAAO,UAAU;AAClC,OAAK,OAAO,aAAa,eAAe,UAAU;AAClD,SAAO,OAAO,KAAK;AAEnB,OAAK,gBAAgB;AACnB,UAAO,OAAO;;AAGhB,SAAO,gBAAgB;AACrB,OAAI,OAAO,gBAAgB,KACzB,SAAQ,cAAc,SAAS,KAAK;OAEpC,SAAQ,KAAK;AAEf,UAAO,QAAQ;;AAGjB,WAAS,KAAK,OAAO,OAAO;AAC5B,SAAO,WAAW;GAClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"inspector.js","names":["#delegate","#deletedQueries"],"sources":["../../../../../../zero-client/src/client/inspector/inspector.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport type {\n AnalyzeQueryResult,\n PlanDebugEventJSON,\n} from '../../../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../../../zero-protocol/src/ast.ts';\nimport type {AnalyzeQueryOptions} from '../../../../zero-protocol/src/inspect-up.ts';\nimport {formatPlannerEvents} from '../../../../zql/src/planner/planner-debug.ts';\nimport type {QueryDelegate} from '../../../../zql/src/query/query-delegate.ts';\nimport type {AnyQuery} from '../../../../zql/src/query/query.ts';\nimport type {ClientGroup} from './client-group.ts';\nimport {Client} from './client.ts';\nimport type {\n ExtendedInspectorDelegate,\n InspectorDelegate,\n Metrics,\n QueryClientMetrics,\n Rep,\n} from './lazy-inspector.ts';\n\nexport type {InspectorDelegate};\n\n// oxlint-disable-next-line consistent-type-imports\nexport type Lazy = typeof import('./lazy-inspector.ts');\n\nexport class Inspector {\n readonly #delegate: ExtendedInspectorDelegate;\n readonly #deletedQueries = new Map<\n string,\n {readonly ast: AST; readonly metrics: QueryClientMetrics}\n >();\n readonly client: Client;\n readonly clientGroup: ClientGroup;\n\n constructor(\n rep: Rep,\n inspectorDelegate: InspectorDelegate,\n queryDelegate: QueryDelegate,\n getSocket: () => Promise<WebSocket>,\n ) {\n const deletedQueries = this.#deletedQueries;\n inspectorDelegate.setQueryEvictedCallback((hash, ast, metrics) => {\n deletedQueries.set(hash, {ast, metrics});\n });\n this.#delegate = {\n getQueryMetrics(hash) {\n return (\n inspectorDelegate.getQueryMetrics(hash) ??\n deletedQueries.get(hash)?.metrics\n );\n },\n getAST(queryID) {\n return (\n inspectorDelegate.getAST(queryID) ?? deletedQueries.get(queryID)?.ast\n );\n },\n mapClientASTToServer:\n inspectorDelegate.mapClientASTToServer.bind(inspectorDelegate),\n get metrics() {\n return inspectorDelegate.metrics;\n },\n setQueryEvictedCallback() {},\n queryDelegate,\n rep,\n getSocket,\n lazy: import('./lazy-inspector.ts'),\n };\n\n this.client = new Client(this.#delegate, rep.clientID, rep.clientGroupID);\n this.clientGroup = this.client.clientGroup;\n }\n\n async metrics(): Promise<Metrics> {\n return (await this.#delegate.lazy).inspectorMetrics(this.#delegate);\n }\n\n async clients(): Promise<Client[]> {\n return (await this.#delegate.lazy).inspectorClients(this.#delegate);\n }\n\n async clientsWithQueries(): Promise<Client[]> {\n return (await this.#delegate.lazy).inspectorClientsWithQueries(\n this.#delegate,\n );\n }\n\n async serverVersion(): Promise<string> {\n return (await this.#delegate.lazy).serverVersion(this.#delegate);\n }\n\n async analyzeQuery(\n query: AnyQuery,\n options?: AnalyzeQueryOptions,\n ): Promise<AnalyzeQueryResult> {\n return (await this.#delegate.lazy).analyzeQuery(\n this.#delegate,\n query,\n options,\n );\n }\n\n /**\n * Analyze a query specified by a server-side AST. Unlike {@link analyzeQuery}\n * the AST is sent to the server verbatim with no client-to-server name\n * mapping; callers should provide an AST already in the server shape.\n */\n async analyzeServerAST(\n ast: AST,\n options?: AnalyzeQueryOptions,\n ): Promise<AnalyzeQueryResult> {\n return (await this.#delegate.lazy).analyzeServerAST(\n this.#delegate,\n ast,\n options,\n );\n }\n\n /**\n * Analyze a server-registered named (custom) query. The server resolves\n * the name and args to an AST using its registered custom-query handler.\n */\n async analyzeNamedQuery(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n options?: AnalyzeQueryOptions,\n ): Promise<AnalyzeQueryResult> {\n return (await this.#delegate.lazy).analyzeNamedQuery(\n this.#delegate,\n name,\n args,\n options,\n );\n }\n\n /**\n * Authenticate with the server's admin password. Other inspector RPCs\n * (e.g. {@link analyzeQuery}) fall back to an interactive HTML password\n * prompt when authentication is needed, which is unavailable in non-DOM\n * environments. Call this first from Node contexts to establish the\n * session.\n *\n * Returns `true` if the password is accepted (or the server runs in a\n * development mode that bypasses the check), `false` otherwise.\n */\n async authenticate(password: string): Promise<boolean> {\n return (await this.#delegate.lazy).authenticate(this.#delegate, password);\n }\n\n /**\n * Format planner debug events as a human-readable string.\n */\n formatPlannerEvents(events: PlanDebugEventJSON[]): string {\n return formatPlannerEvents(events);\n }\n}\n"],"mappings":";;;AAyBA,IAAa,YAAb,MAAuB;CACrB;CACA,kCAA2B,IAAI,IAG7B;CACF;CACA;CAEA,YACE,KACA,mBACA,eACA,WACA;EACA,MAAM,iBAAiB,KAAKC;EAC5B,kBAAkB,yBAAyB,MAAM,KAAK,YAAY;GAChE,eAAe,IAAI,MAAM;IAAC;IAAK;GAAO,CAAC;EACzC,CAAC;EACD,KAAKD,YAAY;GACf,gBAAgB,MAAM;IACpB,OACE,kBAAkB,gBAAgB,IAAI,KACtC,eAAe,IAAI,IAAI,GAAG;GAE9B;GACA,OAAO,SAAS;IACd,OACE,kBAAkB,OAAO,OAAO,KAAK,eAAe,IAAI,OAAO,GAAG;GAEtE;GACA,sBACE,kBAAkB,qBAAqB,KAAK,iBAAiB;GAC/D,IAAI,UAAU;IACZ,OAAO,kBAAkB;GAC3B;GACA,0BAA0B,CAAC;GAC3B;GACA;GACA;GACA,MAAM,OAAO;EACf;EAEA,KAAK,SAAS,IAAI,OAAO,KAAKA,WAAW,IAAI,UAAU,IAAI,aAAa;EACxE,KAAK,cAAc,KAAK,OAAO;CACjC;CAEA,MAAM,UAA4B;EAChC,QAAQ,MAAM,KAAKA,UAAU,MAAM,iBAAiB,KAAKA,SAAS;CACpE;CAEA,MAAM,UAA6B;EACjC,QAAQ,MAAM,KAAKA,UAAU,MAAM,iBAAiB,KAAKA,SAAS;CACpE;CAEA,MAAM,qBAAwC;EAC5C,QAAQ,MAAM,KAAKA,UAAU,MAAM,4BACjC,KAAKA,SACP;CACF;CAEA,MAAM,gBAAiC;EACrC,QAAQ,MAAM,KAAKA,UAAU,MAAM,cAAc,KAAKA,SAAS;CACjE;CAEA,MAAM,aACJ,OACA,SAC6B;EAC7B,QAAQ,MAAM,KAAKA,UAAU,MAAM,aACjC,KAAKA,WACL,OACA,OACF;CACF;;;;;;CAOA,MAAM,iBACJ,KACA,SAC6B;EAC7B,QAAQ,MAAM,KAAKA,UAAU,MAAM,iBACjC,KAAKA,WACL,KACA,OACF;CACF;;;;;CAMA,MAAM,kBACJ,MACA,MACA,SAC6B;EAC7B,QAAQ,MAAM,KAAKA,UAAU,MAAM,kBACjC,KAAKA,WACL,MACA,MACA,OACF;CACF;;;;;;;;;;;CAYA,MAAM,aAAa,UAAoC;EACrD,QAAQ,MAAM,KAAKA,UAAU,MAAM,aAAa,KAAKA,WAAW,QAAQ;CAC1E;;;;CAKA,oBAAoB,QAAsC;EACxD,OAAO,oBAAoB,MAAM;CACnC;AACF"}
1
+ {"version":3,"file":"inspector.js","names":["#delegate","#deletedQueries"],"sources":["../../../../../../zero-client/src/client/inspector/inspector.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport type {\n AnalyzeQueryResult,\n PlanDebugEventJSON,\n} from '../../../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../../../zero-protocol/src/ast.ts';\nimport type {AnalyzeQueryOptions} from '../../../../zero-protocol/src/inspect-up.ts';\nimport {formatPlannerEvents} from '../../../../zql/src/planner/planner-debug.ts';\nimport type {QueryDelegate} from '../../../../zql/src/query/query-delegate.ts';\nimport type {AnyQuery} from '../../../../zql/src/query/query.ts';\nimport type {ClientGroup} from './client-group.ts';\nimport {Client} from './client.ts';\nimport type {\n ExtendedInspectorDelegate,\n InspectorDelegate,\n Metrics,\n QueryClientMetrics,\n Rep,\n} from './lazy-inspector.ts';\n\nexport type {InspectorDelegate};\n\n// oxlint-disable-next-line consistent-type-imports\nexport type Lazy = typeof import('./lazy-inspector.ts');\n\nexport class Inspector {\n readonly #delegate: ExtendedInspectorDelegate;\n readonly #deletedQueries = new Map<\n string,\n {readonly ast: AST; readonly metrics: QueryClientMetrics}\n >();\n readonly client: Client;\n readonly clientGroup: ClientGroup;\n\n constructor(\n rep: Rep,\n inspectorDelegate: InspectorDelegate,\n queryDelegate: QueryDelegate,\n getSocket: () => Promise<WebSocket>,\n ) {\n const deletedQueries = this.#deletedQueries;\n inspectorDelegate.setQueryEvictedCallback((hash, ast, metrics) => {\n deletedQueries.set(hash, {ast, metrics});\n });\n this.#delegate = {\n getQueryMetrics(hash) {\n return (\n inspectorDelegate.getQueryMetrics(hash) ??\n deletedQueries.get(hash)?.metrics\n );\n },\n getAST(queryID) {\n return (\n inspectorDelegate.getAST(queryID) ?? deletedQueries.get(queryID)?.ast\n );\n },\n mapClientASTToServer:\n inspectorDelegate.mapClientASTToServer.bind(inspectorDelegate),\n get metrics() {\n return inspectorDelegate.metrics;\n },\n setQueryEvictedCallback() {},\n queryDelegate,\n rep,\n getSocket,\n lazy: import('./lazy-inspector.ts'),\n };\n\n this.client = new Client(this.#delegate, rep.clientID, rep.clientGroupID);\n this.clientGroup = this.client.clientGroup;\n }\n\n async metrics(): Promise<Metrics> {\n return (await this.#delegate.lazy).inspectorMetrics(this.#delegate);\n }\n\n async clients(): Promise<Client[]> {\n return (await this.#delegate.lazy).inspectorClients(this.#delegate);\n }\n\n async clientsWithQueries(): Promise<Client[]> {\n return (await this.#delegate.lazy).inspectorClientsWithQueries(\n this.#delegate,\n );\n }\n\n async serverVersion(): Promise<string> {\n return (await this.#delegate.lazy).serverVersion(this.#delegate);\n }\n\n async analyzeQuery(\n query: AnyQuery,\n options?: AnalyzeQueryOptions,\n ): Promise<AnalyzeQueryResult> {\n return (await this.#delegate.lazy).analyzeQuery(\n this.#delegate,\n query,\n options,\n );\n }\n\n /**\n * Analyze a query specified by a server-side AST. Unlike {@link analyzeQuery}\n * the AST is sent to the server verbatim with no client-to-server name\n * mapping; callers should provide an AST already in the server shape.\n */\n async analyzeServerAST(\n ast: AST,\n options?: AnalyzeQueryOptions,\n ): Promise<AnalyzeQueryResult> {\n return (await this.#delegate.lazy).analyzeServerAST(\n this.#delegate,\n ast,\n options,\n );\n }\n\n /**\n * Analyze a server-registered named (custom) query. The server resolves\n * the name and args to an AST using its registered custom-query handler.\n */\n async analyzeNamedQuery(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n options?: AnalyzeQueryOptions,\n ): Promise<AnalyzeQueryResult> {\n return (await this.#delegate.lazy).analyzeNamedQuery(\n this.#delegate,\n name,\n args,\n options,\n );\n }\n\n /**\n * Authenticate with the server's admin password. Other inspector RPCs\n * (e.g. {@link analyzeQuery}) fall back to an interactive HTML password\n * prompt when authentication is needed, which is unavailable in non-DOM\n * environments. Call this first from Node contexts to establish the\n * session.\n *\n * Returns `true` if the password is accepted (or the server runs in a\n * development mode that bypasses the check), `false` otherwise.\n */\n async authenticate(password: string): Promise<boolean> {\n return (await this.#delegate.lazy).authenticate(this.#delegate, password);\n }\n\n /**\n * Format planner debug events as a human-readable string.\n */\n formatPlannerEvents(events: PlanDebugEventJSON[]): string {\n return formatPlannerEvents(events);\n }\n}\n"],"mappings":";;;AAyBA,IAAa,YAAb,MAAuB;CACrB;CACA,kCAA2B,IAAI,KAG5B;CACH;CACA;CAEA,YACE,KACA,mBACA,eACA,WACA;EACA,MAAM,iBAAiB,MAAA;AACvB,oBAAkB,yBAAyB,MAAM,KAAK,YAAY;AAChE,kBAAe,IAAI,MAAM;IAAC;IAAK;IAAQ,CAAC;IACxC;AACF,QAAA,WAAiB;GACf,gBAAgB,MAAM;AACpB,WACE,kBAAkB,gBAAgB,KAAK,IACvC,eAAe,IAAI,KAAK,EAAE;;GAG9B,OAAO,SAAS;AACd,WACE,kBAAkB,OAAO,QAAQ,IAAI,eAAe,IAAI,QAAQ,EAAE;;GAGtE,sBACE,kBAAkB,qBAAqB,KAAK,kBAAkB;GAChE,IAAI,UAAU;AACZ,WAAO,kBAAkB;;GAE3B,0BAA0B;GAC1B;GACA;GACA;GACA,MAAM,OAAO;GACd;AAED,OAAK,SAAS,IAAI,OAAO,MAAA,UAAgB,IAAI,UAAU,IAAI,cAAc;AACzE,OAAK,cAAc,KAAK,OAAO;;CAGjC,MAAM,UAA4B;AAChC,UAAQ,MAAM,MAAA,SAAe,MAAM,iBAAiB,MAAA,SAAe;;CAGrE,MAAM,UAA6B;AACjC,UAAQ,MAAM,MAAA,SAAe,MAAM,iBAAiB,MAAA,SAAe;;CAGrE,MAAM,qBAAwC;AAC5C,UAAQ,MAAM,MAAA,SAAe,MAAM,4BACjC,MAAA,SACD;;CAGH,MAAM,gBAAiC;AACrC,UAAQ,MAAM,MAAA,SAAe,MAAM,cAAc,MAAA,SAAe;;CAGlE,MAAM,aACJ,OACA,SAC6B;AAC7B,UAAQ,MAAM,MAAA,SAAe,MAAM,aACjC,MAAA,UACA,OACA,QACD;;;;;;;CAQH,MAAM,iBACJ,KACA,SAC6B;AAC7B,UAAQ,MAAM,MAAA,SAAe,MAAM,iBACjC,MAAA,UACA,KACA,QACD;;;;;;CAOH,MAAM,kBACJ,MACA,MACA,SAC6B;AAC7B,UAAQ,MAAM,MAAA,SAAe,MAAM,kBACjC,MAAA,UACA,MACA,MACA,QACD;;;;;;;;;;;;CAaH,MAAM,aAAa,UAAoC;AACrD,UAAQ,MAAM,MAAA,SAAe,MAAM,aAAa,MAAA,UAAgB,SAAS;;;;;CAM3E,oBAAoB,QAAsC;AACxD,SAAO,oBAAoB,OAAO"}