@rocicorp/zero 1.2.0 → 1.3.0-canary.0

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 (303) hide show
  1. package/out/analyze-query/src/bin-analyze.js +25 -25
  2. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  3. package/out/ast-to-zql/src/ast-to-zql.d.ts.map +1 -1
  4. package/out/ast-to-zql/src/ast-to-zql.js +2 -1
  5. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  6. package/out/replicache/src/btree/node.d.ts.map +1 -1
  7. package/out/replicache/src/btree/node.js +2 -2
  8. package/out/replicache/src/btree/node.js.map +1 -1
  9. package/out/replicache/src/connection-loop.js +3 -3
  10. package/out/replicache/src/connection-loop.js.map +1 -1
  11. package/out/replicache/src/deleted-clients.d.ts +0 -4
  12. package/out/replicache/src/deleted-clients.d.ts.map +1 -1
  13. package/out/replicache/src/deleted-clients.js +1 -1
  14. package/out/replicache/src/deleted-clients.js.map +1 -1
  15. package/out/replicache/src/hash.d.ts.map +1 -1
  16. package/out/replicache/src/hash.js.map +1 -1
  17. package/out/replicache/src/process-scheduler.d.ts.map +1 -1
  18. package/out/replicache/src/process-scheduler.js.map +1 -1
  19. package/out/replicache/src/request-idle.js +1 -1
  20. package/out/replicache/src/request-idle.js.map +1 -1
  21. package/out/replicache/src/sync/patch.d.ts +1 -1
  22. package/out/replicache/src/sync/patch.d.ts.map +1 -1
  23. package/out/replicache/src/sync/patch.js +1 -1
  24. package/out/replicache/src/sync/patch.js.map +1 -1
  25. package/out/shared/src/arrays.d.ts.map +1 -1
  26. package/out/shared/src/arrays.js +1 -2
  27. package/out/shared/src/arrays.js.map +1 -1
  28. package/out/shared/src/bigint-json.js +1 -1
  29. package/out/shared/src/bigint-json.js.map +1 -1
  30. package/out/shared/src/btree-set.js +1 -1
  31. package/out/shared/src/btree-set.js.map +1 -1
  32. package/out/shared/src/iterables.d.ts +7 -0
  33. package/out/shared/src/iterables.d.ts.map +1 -1
  34. package/out/shared/src/iterables.js +10 -1
  35. package/out/shared/src/iterables.js.map +1 -1
  36. package/out/shared/src/logging.d.ts.map +1 -1
  37. package/out/shared/src/logging.js +10 -9
  38. package/out/shared/src/logging.js.map +1 -1
  39. package/out/shared/src/options.js +1 -1
  40. package/out/shared/src/options.js.map +1 -1
  41. package/out/shared/src/sorted-entries.d.ts +2 -0
  42. package/out/shared/src/sorted-entries.d.ts.map +1 -0
  43. package/out/shared/src/sorted-entries.js +9 -0
  44. package/out/shared/src/sorted-entries.js.map +1 -0
  45. package/out/shared/src/tdigest-schema.d.ts.map +1 -1
  46. package/out/shared/src/tdigest-schema.js.map +1 -1
  47. package/out/shared/src/tdigest.d.ts.map +1 -1
  48. package/out/shared/src/tdigest.js +7 -7
  49. package/out/shared/src/tdigest.js.map +1 -1
  50. package/out/shared/src/valita.d.ts.map +1 -1
  51. package/out/shared/src/valita.js +1 -1
  52. package/out/shared/src/valita.js.map +1 -1
  53. package/out/z2s/src/sql.d.ts +2 -2
  54. package/out/z2s/src/sql.d.ts.map +1 -1
  55. package/out/z2s/src/sql.js +3 -3
  56. package/out/z2s/src/sql.js.map +1 -1
  57. package/out/zero/package.js +6 -7
  58. package/out/zero/package.js.map +1 -1
  59. package/out/zero/src/pg.js +1 -1
  60. package/out/zero/src/server.js +1 -1
  61. package/out/zero-cache/src/auth/auth.d.ts +8 -26
  62. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  63. package/out/zero-cache/src/auth/auth.js +57 -82
  64. package/out/zero-cache/src/auth/auth.js.map +1 -1
  65. package/out/zero-cache/src/auth/jwt.d.ts +3 -3
  66. package/out/zero-cache/src/auth/jwt.d.ts.map +1 -1
  67. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  68. package/out/zero-cache/src/auth/load-permissions.js +1 -1
  69. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  70. package/out/zero-cache/src/config/zero-config.d.ts +38 -2
  71. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  72. package/out/zero-cache/src/config/zero-config.js +56 -1
  73. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  74. package/out/zero-cache/src/custom/fetch.d.ts +2 -9
  75. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  76. package/out/zero-cache/src/custom/fetch.js +11 -4
  77. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  78. package/out/zero-cache/src/custom-queries/transform-query.d.ts +20 -9
  79. package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
  80. package/out/zero-cache/src/custom-queries/transform-query.js +74 -37
  81. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  82. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  83. package/out/zero-cache/src/db/migration-lite.js +1 -1
  84. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  85. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  86. package/out/zero-cache/src/db/migration.js +1 -1
  87. package/out/zero-cache/src/db/migration.js.map +1 -1
  88. package/out/zero-cache/src/db/pg-copy-binary.d.ts +101 -0
  89. package/out/zero-cache/src/db/pg-copy-binary.d.ts.map +1 -0
  90. package/out/zero-cache/src/db/pg-copy-binary.js +381 -0
  91. package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -0
  92. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  93. package/out/zero-cache/src/db/transaction-pool.js +3 -0
  94. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  95. package/out/zero-cache/src/db/warmup.d.ts.map +1 -1
  96. package/out/zero-cache/src/db/warmup.js +3 -1
  97. package/out/zero-cache/src/db/warmup.js.map +1 -1
  98. package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
  99. package/out/zero-cache/src/server/anonymous-otel-start.js +2 -1
  100. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  101. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  102. package/out/zero-cache/src/server/change-streamer.js +5 -2
  103. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  104. package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -2
  105. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  106. package/out/zero-cache/src/server/inspector-delegate.js +4 -4
  107. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  108. package/out/zero-cache/src/server/main.js +1 -1
  109. package/out/zero-cache/src/server/main.js.map +1 -1
  110. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  111. package/out/zero-cache/src/server/reaper.js +4 -1
  112. package/out/zero-cache/src/server/reaper.js.map +1 -1
  113. package/out/zero-cache/src/server/runner/run-worker.js +1 -1
  114. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  115. package/out/zero-cache/src/server/syncer.js +41 -20
  116. package/out/zero-cache/src/server/syncer.js.map +1 -1
  117. package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
  118. package/out/zero-cache/src/server/worker-urls.js +2 -1
  119. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  120. package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -0
  121. package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
  122. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  123. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +3 -2
  124. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  125. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  126. package/out/zero-cache/src/services/change-source/custom/change-source.js +5 -2
  127. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  128. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  129. package/out/zero-cache/src/services/change-source/pg/change-source.js +13 -4
  130. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  131. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +3 -1
  132. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  133. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +91 -9
  134. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  135. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +2 -2
  136. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  137. package/out/zero-cache/src/services/change-streamer/broadcast.js +1 -1
  138. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  139. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +3 -0
  140. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  141. package/out/zero-cache/src/services/life-cycle.d.ts +5 -4
  142. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  143. package/out/zero-cache/src/services/life-cycle.js +11 -11
  144. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  145. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  146. package/out/zero-cache/src/services/litestream/commands.js +5 -5
  147. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  148. package/out/zero-cache/src/services/mutagen/pusher.d.ts +20 -20
  149. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  150. package/out/zero-cache/src/services/mutagen/pusher.js +91 -104
  151. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  152. package/out/zero-cache/src/services/replicator/change-processor.js +1 -1
  153. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  154. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  155. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
  156. package/out/zero-cache/src/services/view-syncer/client-schema.js +4 -3
  157. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
  158. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +168 -0
  159. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -0
  160. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +385 -0
  161. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -0
  162. package/out/zero-cache/src/services/view-syncer/cvr-store.js +2 -2
  163. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  164. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/view-syncer/cvr.js +5 -4
  166. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  167. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -3
  168. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +3 -3
  170. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  171. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  172. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +5 -3
  173. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  174. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  175. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +13 -7
  176. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  177. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +3 -1
  178. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  179. package/out/zero-cache/src/services/view-syncer/snapshotter.js +6 -9
  180. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  181. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +24 -26
  182. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  183. package/out/zero-cache/src/services/view-syncer/view-syncer.js +236 -124
  184. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  185. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  186. package/out/zero-cache/src/types/lite.js +3 -2
  187. package/out/zero-cache/src/types/lite.js.map +1 -1
  188. package/out/zero-cache/src/types/pg-types.js +4 -1
  189. package/out/zero-cache/src/types/pg-types.js.map +1 -1
  190. package/out/zero-cache/src/types/pg-versions.d.ts +3 -0
  191. package/out/zero-cache/src/types/pg-versions.d.ts.map +1 -0
  192. package/out/zero-cache/src/types/pg-versions.js +7 -0
  193. package/out/zero-cache/src/types/pg-versions.js.map +1 -0
  194. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  195. package/out/zero-cache/src/types/pg.js +6 -1
  196. package/out/zero-cache/src/types/pg.js.map +1 -1
  197. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  198. package/out/zero-cache/src/types/subscription.js +2 -2
  199. package/out/zero-cache/src/types/subscription.js.map +1 -1
  200. package/out/zero-cache/src/workers/connect-params.d.ts +1 -1
  201. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  202. package/out/zero-cache/src/workers/connect-params.js +1 -1
  203. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  204. package/out/zero-cache/src/workers/connection.js +2 -2
  205. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts +2 -1
  206. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  207. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +64 -38
  208. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  209. package/out/zero-cache/src/workers/syncer.d.ts +2 -1
  210. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  211. package/out/zero-cache/src/workers/syncer.js +70 -31
  212. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  213. package/out/zero-client/src/client/connection.d.ts +4 -4
  214. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  215. package/out/zero-client/src/client/connection.js.map +1 -1
  216. package/out/zero-client/src/client/http-string.d.ts.map +1 -1
  217. package/out/zero-client/src/client/http-string.js.map +1 -1
  218. package/out/zero-client/src/client/metrics.d.ts.map +1 -1
  219. package/out/zero-client/src/client/metrics.js +2 -1
  220. package/out/zero-client/src/client/metrics.js.map +1 -1
  221. package/out/zero-client/src/client/options.d.ts +34 -5
  222. package/out/zero-client/src/client/options.d.ts.map +1 -1
  223. package/out/zero-client/src/client/options.js.map +1 -1
  224. package/out/zero-client/src/client/server-option.js +1 -1
  225. package/out/zero-client/src/client/server-option.js.map +1 -1
  226. package/out/zero-client/src/client/version.js +1 -1
  227. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  228. package/out/zero-client/src/client/zero-poke-handler.js +1 -1
  229. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  230. package/out/zero-client/src/client/zero.d.ts +4 -3
  231. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  232. package/out/zero-client/src/client/zero.js +33 -11
  233. package/out/zero-client/src/client/zero.js.map +1 -1
  234. package/out/zero-pg/src/mod.js +1 -1
  235. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  236. package/out/zero-protocol/src/ast.js.map +1 -1
  237. package/out/zero-protocol/src/change-desired-queries.d.ts +4 -0
  238. package/out/zero-protocol/src/change-desired-queries.d.ts.map +1 -1
  239. package/out/zero-protocol/src/change-desired-queries.js +4 -1
  240. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  241. package/out/zero-protocol/src/connect.d.ts +4 -0
  242. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  243. package/out/zero-protocol/src/connect.js +2 -1
  244. package/out/zero-protocol/src/connect.js.map +1 -1
  245. package/out/zero-protocol/src/primary-key.d.ts.map +1 -1
  246. package/out/zero-protocol/src/primary-key.js.map +1 -1
  247. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  248. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  249. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  250. package/out/zero-protocol/src/push.d.ts +4 -0
  251. package/out/zero-protocol/src/push.d.ts.map +1 -1
  252. package/out/zero-protocol/src/push.js +2 -1
  253. package/out/zero-protocol/src/push.js.map +1 -1
  254. package/out/zero-protocol/src/up.d.ts +3 -0
  255. package/out/zero-protocol/src/up.d.ts.map +1 -1
  256. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  257. package/out/zero-react/src/zero-provider.js +11 -5
  258. package/out/zero-react/src/zero-provider.js.map +1 -1
  259. package/out/zero-schema/src/name-mapper.js +1 -1
  260. package/out/zero-schema/src/name-mapper.js.map +1 -1
  261. package/out/zero-server/src/mod.js +1 -1
  262. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  263. package/out/zero-server/src/process-mutations.js +2 -1
  264. package/out/zero-server/src/process-mutations.js.map +1 -1
  265. package/out/zero-server/src/push-processor.d.ts +1 -0
  266. package/out/zero-server/src/push-processor.d.ts.map +1 -1
  267. package/out/zero-server/src/push-processor.js +3 -2
  268. package/out/zero-server/src/push-processor.js.map +1 -1
  269. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  270. package/out/zero-solid/src/use-zero.js +8 -9
  271. package/out/zero-solid/src/use-zero.js.map +1 -1
  272. package/out/zql/src/builder/like.js +2 -1
  273. package/out/zql/src/builder/like.js.map +1 -1
  274. package/out/zql/src/ivm/data.d.ts.map +1 -1
  275. package/out/zql/src/ivm/data.js +6 -15
  276. package/out/zql/src/ivm/data.js.map +1 -1
  277. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  278. package/out/zql/src/ivm/memory-source.js +14 -8
  279. package/out/zql/src/ivm/memory-source.js.map +1 -1
  280. package/out/zql/src/query/complete-ordering.js +1 -1
  281. package/out/zql/src/query/complete-ordering.js.map +1 -1
  282. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  283. package/out/zql/src/query/query-impl.js +2 -2
  284. package/out/zql/src/query/query-impl.js.map +1 -1
  285. package/out/zql/src/query/query-registry.d.ts.map +1 -1
  286. package/out/zql/src/query/query-registry.js +2 -1
  287. package/out/zql/src/query/query-registry.js.map +1 -1
  288. package/out/zql/src/query/ttl.js +1 -1
  289. package/out/zql/src/query/ttl.js.map +1 -1
  290. package/out/zqlite/src/internal/sql.d.ts +2 -2
  291. package/out/zqlite/src/internal/sql.d.ts.map +1 -1
  292. package/out/zqlite/src/internal/sql.js +1 -2
  293. package/out/zqlite/src/internal/sql.js.map +1 -1
  294. package/out/zqlite/src/sqlite-cost-model.d.ts +1 -1
  295. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  296. package/out/zqlite/src/sqlite-cost-model.js +1 -1
  297. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  298. package/out/zqlite/src/sqlite-stat-fanout.js +1 -1
  299. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  300. package/out/zqlite/src/table-source.d.ts.map +1 -1
  301. package/out/zqlite/src/table-source.js +8 -12
  302. package/out/zqlite/src/table-source.js.map +1 -1
  303. package/package.json +6 -7
@@ -7,8 +7,9 @@ var REPORT_INTERVAL_MS = 5e3;
7
7
  function getLastConnectErrorValue(reason) {
8
8
  return `${isServerError(reason) ? "server_" : "client_"}${camelToSnake(reason.kind)}`;
9
9
  }
10
+ var upperCasesRegExp = /\.?(?=[A-Z])/;
10
11
  function camelToSnake(kind) {
11
- return kind.split(/\.?(?=[A-Z])/).join("_").toLowerCase();
12
+ return kind.split(upperCasesRegExp).join("_").toLowerCase();
12
13
  }
13
14
  /**
14
15
  * Returns whether an error should be reported in metrics and
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","names":["#reportIntervalMs","#host","#reporter","#lc","#setNotConnectedReason","#timerID","#register","#notConnected","#timeToConnectMsV2","#lastConnectErrorV2","#totalTimeToConnectMs","#metrics","#name","#value","#prefix","#clearOnFlush","#current"],"sources":["../../../../../zero-client/src/client/metrics.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {\n isClientError,\n isServerError,\n type ZeroError,\n type ZeroErrorKind,\n} from './error.ts';\nimport {MetricName} from './metric-name.ts';\n\n// This value is used to indicate that the client's last connection attempt\n// failed. We don't make this -1 because we want to stack this never connected\n// state in a graph on top of actual connection times, so it should be greater\n// than any other value.\nexport const DID_NOT_CONNECT_VALUE = 100 * 1000;\n\nexport const REPORT_INTERVAL_MS = 5_000;\n\ntype NotConnectedReason =\n | 'init'\n | 'error'\n | 'hidden'\n | 'hidden_was_init'\n | 'hidden_was_error';\n\nexport function getLastConnectErrorValue(reason: ZeroError) {\n return `${isServerError(reason) ? 'server_' : 'client_'}${camelToSnake(reason.kind)}` as const;\n}\n\n// camelToSnake is used to convert a ZeroErrorKind into a suitable\n// metric name, eg AuthInvalidated => auth_invalidated. It converts\n// both PascalCase and camelCase to snake_case.\nfunction camelToSnake(kind: ZeroErrorKind): string {\n return kind\n .split(/\\.?(?=[A-Z])/)\n .join('_')\n .toLowerCase();\n}\n\n/**\n * Returns whether an error should be reported in metrics and\n * increment the connect error count.\n *\n * Returns `true` for all server errors and client errors that represent actual\n * connection problems. Returns `false` for expected client-side disconnections\n * (user disconnect, client closed, hidden tab, clean/abrupt close).\n */\nexport function shouldReportConnectError(reason: ZeroError): boolean {\n if (!isClientError(reason)) {\n return true;\n }\n switch (reason.kind) {\n case ClientErrorKind.Hidden:\n case ClientErrorKind.ClientClosed:\n case ClientErrorKind.UserDisconnect:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.AbruptClose:\n return false;\n default:\n return true;\n }\n}\n\ntype MetricsReporter = (metrics: Series[]) => MaybePromise<void>;\n\nexport type MetricManagerOptions = {\n reportIntervalMs: number;\n host: string;\n source: string;\n reporter: MetricsReporter;\n lc: LogContext;\n};\n\n/**\n * MetricManager keeps track of the set of metrics in use and flushes them\n * to a format suitable for reporting.\n */\nexport class MetricManager {\n #reportIntervalMs: number;\n #host: string;\n #reporter: MetricsReporter;\n #lc: LogContext;\n #timerID: ReturnType<typeof setInterval> | null;\n\n constructor(opts: MetricManagerOptions) {\n this.#reportIntervalMs = opts.reportIntervalMs;\n this.#host = opts.host;\n this.#reporter = opts.reporter;\n this.#lc = opts.lc;\n\n this.tags.push(`source:${opts.source}`);\n\n this.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);\n this.#setNotConnectedReason('init');\n\n this.#timerID = setInterval(() => {\n void this.flush();\n }, this.#reportIntervalMs);\n }\n\n #metrics: Flushable[] = [];\n\n // timeToConnectMs measures the time from the call to connect() to receiving\n // the 'connected' ws message. We record the DID_NOT_CONNECT_VALUE if the previous\n // connection attempt failed for any reason.\n //\n // We set the gauge using #connectStart as follows:\n // - #connectStart is undefined if we are disconnected or connected; it is\n // defined only in the Connecting state, as a number representing the timestamp\n // at which we started connecting.\n // - #connectStart is set to the current time when connect() is called.\n // - When we receive the 'connected' message we record the time to connect and\n // set #connectStart to undefined.\n // - If disconnect() is called with a defined #connectStart then we record\n // DID_NOT_CONNECT_VALUE and set #connectStart to undefined.\n //\n // TODO: this should be folded into the ConnectionManager.\n readonly timeToConnectMs = this.#register(\n new Gauge(MetricName.TimeToConnectMs),\n );\n\n // lastConnectError records the last error that occurred when connecting,\n // if any. It is cleared when connecting successfully or when reported, so this\n // state only gets reported if there was a failure during the reporting period and\n // we are still not connected.\n readonly lastConnectError = this.#register(\n new State(\n MetricName.LastConnectError,\n true, // clearOnFlush\n ),\n );\n\n // notConnected records the reason why the client is not currently connected.\n // It is cleared when the client successfully connects.\n readonly #notConnected = this.#register(new State(MetricName.NotConnected));\n\n // The time from the call to connect() to receiving the 'connected' ws message\n // for the current connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect untill there is a\n // connect error, or client reports disconnected and waiting for visible.\n // Should have a value iff _notConnected has no value.\n readonly #timeToConnectMsV2 = this.#register(\n new Gauge(MetricName.TimeToConnectMsV2),\n );\n\n // lastConnectErrorV2 records the last error that occurred when connecting,\n // if any. It is cleared when the client successfully connects or\n // stops trying to connect due to being hidden.\n // Should have a value iff notConnected state is NotConnectedReason.Error.\n readonly #lastConnectErrorV2 = this.#register(\n new State(MetricName.LastConnectErrorV2),\n );\n\n // The total time it took to connect across retries for the current\n // connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect until there is a\n // connect error, or client reports disconnected and waiting for visible.\n // See Zero.#totalToConnectStart for details of how this total is computed.\n // Should have a value iff _notConnected has no value.\n readonly #totalTimeToConnectMs = this.#register(\n new Gauge(MetricName.TotalTimeToConnectMs),\n );\n\n #setNotConnectedReason(reason: NotConnectedReason) {\n this.#notConnected.set(reason);\n }\n\n setConnected(timeToConnectMs: number, totalTimeToConnectMs: number) {\n this.#notConnected.clear();\n this.#lastConnectErrorV2.clear();\n this.#timeToConnectMsV2.set(timeToConnectMs);\n this.#totalTimeToConnectMs.set(totalTimeToConnectMs);\n }\n\n setDisconnectedWaitingForVisible() {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#lastConnectErrorV2.clear();\n let notConnectedReason: NotConnectedReason;\n switch (this.#notConnected.get()) {\n case 'init':\n notConnectedReason = 'hidden_was_init';\n break;\n case 'error':\n notConnectedReason = 'hidden_was_error';\n break;\n default:\n notConnectedReason = 'hidden';\n break;\n }\n this.#setNotConnectedReason(notConnectedReason);\n }\n\n setConnectError(reason: ZeroError) {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#setNotConnectedReason('error');\n this.#lastConnectErrorV2.set(getLastConnectErrorValue(reason));\n }\n\n /**\n * Tags to include in all metrics.\n */\n readonly tags: string[] = [];\n\n // Flushes all metrics to an array of time series (plural), one Series\n // per metric.\n async flush() {\n const lc = this.#lc;\n if (this.#timerID === null) {\n lc.error?.('MetricManager.flush() called but already stopped');\n return;\n }\n const allSeries: Series[] = [];\n for (const metric of this.#metrics) {\n const series = metric.flush();\n if (series !== undefined) {\n allSeries.push({\n ...series,\n host: this.#host,\n tags: this.tags,\n });\n }\n }\n if (allSeries.length === 0) {\n lc?.debug?.('No metrics to report');\n return;\n }\n try {\n await this.#reporter(allSeries);\n } catch (e) {\n lc?.error?.('Error reporting metrics', e);\n }\n }\n\n stop() {\n if (this.#timerID === null) {\n this.#lc.error?.('MetricManager.stop() called but already stopped');\n return;\n }\n clearInterval(this.#timerID);\n this.#timerID = null;\n }\n\n #register<M extends Flushable>(metric: M) {\n this.#metrics.push(metric);\n return metric;\n }\n}\n\n// These two types are influenced by Datadog's API's needs. We could change what\n// we use internally if necessary, but we'd just have to convert to/from before\n// sending to DD. So for convenience we go with their format.\n\n/** Series is a time series of points for a single metric. */\nexport type Series = {\n host: string;\n metric: string; // We call this 'name' bc 'metric' is overloaded in code.\n points: Point[];\n tags?: string[];\n};\n/**\n * A point is a second-resolution timestamp and a set of values for that\n * timestamp. A point represents exactly one second in time and the values\n * are those recorded for that second. The first element of this array\n * is the timestamp and the second element is an array of values.\n */\nexport type Point = [number, number[]];\n\nfunction makePoint(ts: number, value: number): Point {\n return [ts, [value]];\n}\n\ntype Flushable = {\n flush(): Pick<Series, 'metric' | 'points'> | undefined;\n};\n\n/**\n * Gauge is a metric type that represents a single value that can go up and\n * down. It's typically used to track discrete values or counts eg the number\n * of active users, number of connections, cpu load, etc. A gauge retains\n * its value when flushed.\n *\n * We use a Gauge to sample at the client. If we are interested in tracking\n * a metric value *per client*, the client can note the latest value in\n * a Gauge metric. The metric is periodically reported via Reporter. On the\n * server, we graph the value of the metric rolled up over the periodic\n * reporting period, that is, counted over a span of time equal to the\n * reporting period. The result is ~one point per client per reporting\n * period.\n */\nexport class Gauge implements Flushable {\n readonly #name: string;\n #value: number | undefined = undefined;\n\n constructor(name: string) {\n this.#name = name;\n }\n\n set(value: number) {\n this.#value = value;\n }\n\n get() {\n return this.#value;\n }\n\n clear() {\n this.#value = undefined;\n }\n\n flush() {\n if (this.#value === undefined) {\n return undefined;\n }\n // Gauge reports the timestamp at flush time, not at the point the value was\n // recorded.\n const points = [makePoint(t(), this.#value)];\n return {metric: this.#name, points};\n }\n}\n\nfunction t() {\n return Math.round(Date.now() / 1000);\n}\n\n/**\n * State is a metric type that represents a specific state that the system is\n * in, for example the state of a connection which may be 'open' or 'closed'.\n * The state is given a name/prefix at construction time (eg 'connection') and\n * then can be set to a specific state (eg 'open'). The prefix is prepended to\n * the set state (eg, 'connection_open') and a value of 1 is reported.\n * Unset/cleared states are not reported.\n *\n * Example:\n * const s = new State('connection');\n * s.set('open');\n * s.flush(); // returns {metric: 'connection_open', points: [[now(), [1]]]}\n */\nexport class State implements Flushable {\n readonly #prefix: string;\n readonly #clearOnFlush: boolean;\n #current: string | undefined = undefined;\n\n constructor(prefix: string, clearOnFlush = false) {\n this.#prefix = prefix;\n this.#clearOnFlush = clearOnFlush;\n }\n\n set(state: string) {\n this.#current = state;\n }\n\n get() {\n return this.#current;\n }\n\n clear() {\n this.#current = undefined;\n }\n\n flush() {\n if (this.#current === undefined) {\n return undefined;\n }\n const gauge = new Gauge([this.#prefix, this.#current].join('_'));\n gauge.set(1);\n const series = gauge.flush();\n if (this.#clearOnFlush) {\n this.clear();\n }\n return series;\n }\n}\n"],"mappings":";;;;AAeA,IAAa,wBAAwB,MAAM;AAE3C,IAAa,qBAAqB;AASlC,SAAgB,yBAAyB,QAAmB;AAC1D,QAAO,GAAG,cAAc,OAAO,GAAG,YAAY,YAAY,aAAa,OAAO,KAAK;;AAMrF,SAAS,aAAa,MAA6B;AACjD,QAAO,KACJ,MAAM,eAAe,CACrB,KAAK,IAAI,CACT,aAAa;;;;;;;;;;AAWlB,SAAgB,yBAAyB,QAA4B;AACnE,KAAI,CAAC,cAAc,OAAO,CACxB,QAAO;AAET,SAAQ,OAAO,MAAf;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,YACH,QAAO;EACT,QACE,QAAO;;;;;;;AAkBb,IAAa,gBAAb,MAA2B;CACzB;CACA;CACA;CACA;CACA;CAEA,YAAY,MAA4B;AACtC,QAAA,mBAAyB,KAAK;AAC9B,QAAA,OAAa,KAAK;AAClB,QAAA,WAAiB,KAAK;AACtB,QAAA,KAAW,KAAK;AAEhB,OAAK,KAAK,KAAK,UAAU,KAAK,SAAS;AAEvC,OAAK,gBAAgB,IAAI,sBAAsB;AAC/C,QAAA,sBAA4B,OAAO;AAEnC,QAAA,UAAgB,kBAAkB;AAC3B,QAAK,OAAO;KAChB,MAAA,iBAAuB;;CAG5B,WAAwB,EAAE;CAiB1B,kBAA2B,MAAA,SACzB,IAAI,MAAM,gBAA2B,CACtC;CAMD,mBAA4B,MAAA,SAC1B,IAAI,MACF,kBACA,KACD,CACF;CAID,gBAAyB,MAAA,SAAe,IAAI,MAAM,aAAwB,CAAC;CAO3E,qBAA8B,MAAA,SAC5B,IAAI,MAAM,kBAA6B,CACxC;CAMD,sBAA+B,MAAA,SAC7B,IAAI,MAAM,mBAA8B,CACzC;CAQD,wBAAiC,MAAA,SAC/B,IAAI,MAAM,qBAAgC,CAC3C;CAED,uBAAuB,QAA4B;AACjD,QAAA,aAAmB,IAAI,OAAO;;CAGhC,aAAa,iBAAyB,sBAA8B;AAClE,QAAA,aAAmB,OAAO;AAC1B,QAAA,mBAAyB,OAAO;AAChC,QAAA,kBAAwB,IAAI,gBAAgB;AAC5C,QAAA,qBAA2B,IAAI,qBAAqB;;CAGtD,mCAAmC;AACjC,QAAA,kBAAwB,OAAO;AAC/B,QAAA,qBAA2B,OAAO;AAClC,QAAA,mBAAyB,OAAO;EAChC,IAAI;AACJ,UAAQ,MAAA,aAAmB,KAAK,EAAhC;GACE,KAAK;AACH,yBAAqB;AACrB;GACF,KAAK;AACH,yBAAqB;AACrB;GACF;AACE,yBAAqB;AACrB;;AAEJ,QAAA,sBAA4B,mBAAmB;;CAGjD,gBAAgB,QAAmB;AACjC,QAAA,kBAAwB,OAAO;AAC/B,QAAA,qBAA2B,OAAO;AAClC,QAAA,sBAA4B,QAAQ;AACpC,QAAA,mBAAyB,IAAI,yBAAyB,OAAO,CAAC;;;;;CAMhE,OAA0B,EAAE;CAI5B,MAAM,QAAQ;EACZ,MAAM,KAAK,MAAA;AACX,MAAI,MAAA,YAAkB,MAAM;AAC1B,MAAG,QAAQ,mDAAmD;AAC9D;;EAEF,MAAM,YAAsB,EAAE;AAC9B,OAAK,MAAM,UAAU,MAAA,SAAe;GAClC,MAAM,SAAS,OAAO,OAAO;AAC7B,OAAI,WAAW,KAAA,EACb,WAAU,KAAK;IACb,GAAG;IACH,MAAM,MAAA;IACN,MAAM,KAAK;IACZ,CAAC;;AAGN,MAAI,UAAU,WAAW,GAAG;AAC1B,OAAI,QAAQ,uBAAuB;AACnC;;AAEF,MAAI;AACF,SAAM,MAAA,SAAe,UAAU;WACxB,GAAG;AACV,OAAI,QAAQ,2BAA2B,EAAE;;;CAI7C,OAAO;AACL,MAAI,MAAA,YAAkB,MAAM;AAC1B,SAAA,GAAS,QAAQ,kDAAkD;AACnE;;AAEF,gBAAc,MAAA,QAAc;AAC5B,QAAA,UAAgB;;CAGlB,UAA+B,QAAW;AACxC,QAAA,QAAc,KAAK,OAAO;AAC1B,SAAO;;;AAuBX,SAAS,UAAU,IAAY,OAAsB;AACnD,QAAO,CAAC,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;AAqBtB,IAAa,QAAb,MAAwC;CACtC;CACA,SAA6B,KAAA;CAE7B,YAAY,MAAc;AACxB,QAAA,OAAa;;CAGf,IAAI,OAAe;AACjB,QAAA,QAAc;;CAGhB,MAAM;AACJ,SAAO,MAAA;;CAGT,QAAQ;AACN,QAAA,QAAc,KAAA;;CAGhB,QAAQ;AACN,MAAI,MAAA,UAAgB,KAAA,EAClB;EAIF,MAAM,SAAS,CAAC,UAAU,GAAG,EAAE,MAAA,MAAY,CAAC;AAC5C,SAAO;GAAC,QAAQ,MAAA;GAAY;GAAO;;;AAIvC,SAAS,IAAI;AACX,QAAO,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;;;;;;;;;;;;;;;AAgBtC,IAAa,QAAb,MAAwC;CACtC;CACA;CACA,WAA+B,KAAA;CAE/B,YAAY,QAAgB,eAAe,OAAO;AAChD,QAAA,SAAe;AACf,QAAA,eAAqB;;CAGvB,IAAI,OAAe;AACjB,QAAA,UAAgB;;CAGlB,MAAM;AACJ,SAAO,MAAA;;CAGT,QAAQ;AACN,QAAA,UAAgB,KAAA;;CAGlB,QAAQ;AACN,MAAI,MAAA,YAAkB,KAAA,EACpB;EAEF,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAA,QAAc,MAAA,QAAc,CAAC,KAAK,IAAI,CAAC;AAChE,QAAM,IAAI,EAAE;EACZ,MAAM,SAAS,MAAM,OAAO;AAC5B,MAAI,MAAA,aACF,MAAK,OAAO;AAEd,SAAO"}
1
+ {"version":3,"file":"metrics.js","names":["#reportIntervalMs","#host","#reporter","#lc","#setNotConnectedReason","#timerID","#register","#notConnected","#timeToConnectMsV2","#lastConnectErrorV2","#totalTimeToConnectMs","#metrics","#name","#value","#prefix","#clearOnFlush","#current"],"sources":["../../../../../zero-client/src/client/metrics.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {\n isClientError,\n isServerError,\n type ZeroError,\n type ZeroErrorKind,\n} from './error.ts';\nimport {MetricName} from './metric-name.ts';\n\n// This value is used to indicate that the client's last connection attempt\n// failed. We don't make this -1 because we want to stack this never connected\n// state in a graph on top of actual connection times, so it should be greater\n// than any other value.\nexport const DID_NOT_CONNECT_VALUE = 100 * 1000;\n\nexport const REPORT_INTERVAL_MS = 5_000;\n\ntype NotConnectedReason =\n | 'init'\n | 'error'\n | 'hidden'\n | 'hidden_was_init'\n | 'hidden_was_error';\n\nexport function getLastConnectErrorValue(reason: ZeroError) {\n return `${isServerError(reason) ? 'server_' : 'client_'}${camelToSnake(reason.kind)}` as const;\n}\n\nconst upperCasesRegExp = /\\.?(?=[A-Z])/;\n\n// camelToSnake is used to convert a ZeroErrorKind into a suitable\n// metric name, eg AuthInvalidated => auth_invalidated. It converts\n// both PascalCase and camelCase to snake_case.\nfunction camelToSnake(kind: ZeroErrorKind): string {\n return kind.split(upperCasesRegExp).join('_').toLowerCase();\n}\n\n/**\n * Returns whether an error should be reported in metrics and\n * increment the connect error count.\n *\n * Returns `true` for all server errors and client errors that represent actual\n * connection problems. Returns `false` for expected client-side disconnections\n * (user disconnect, client closed, hidden tab, clean/abrupt close).\n */\nexport function shouldReportConnectError(reason: ZeroError): boolean {\n if (!isClientError(reason)) {\n return true;\n }\n switch (reason.kind) {\n case ClientErrorKind.Hidden:\n case ClientErrorKind.ClientClosed:\n case ClientErrorKind.UserDisconnect:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.AbruptClose:\n return false;\n default:\n return true;\n }\n}\n\ntype MetricsReporter = (metrics: Series[]) => MaybePromise<void>;\n\nexport type MetricManagerOptions = {\n reportIntervalMs: number;\n host: string;\n source: string;\n reporter: MetricsReporter;\n lc: LogContext;\n};\n\n/**\n * MetricManager keeps track of the set of metrics in use and flushes them\n * to a format suitable for reporting.\n */\nexport class MetricManager {\n #reportIntervalMs: number;\n #host: string;\n #reporter: MetricsReporter;\n #lc: LogContext;\n #timerID: ReturnType<typeof setInterval> | null;\n\n constructor(opts: MetricManagerOptions) {\n this.#reportIntervalMs = opts.reportIntervalMs;\n this.#host = opts.host;\n this.#reporter = opts.reporter;\n this.#lc = opts.lc;\n\n this.tags.push(`source:${opts.source}`);\n\n this.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);\n this.#setNotConnectedReason('init');\n\n this.#timerID = setInterval(() => {\n void this.flush();\n }, this.#reportIntervalMs);\n }\n\n #metrics: Flushable[] = [];\n\n // timeToConnectMs measures the time from the call to connect() to receiving\n // the 'connected' ws message. We record the DID_NOT_CONNECT_VALUE if the previous\n // connection attempt failed for any reason.\n //\n // We set the gauge using #connectStart as follows:\n // - #connectStart is undefined if we are disconnected or connected; it is\n // defined only in the Connecting state, as a number representing the timestamp\n // at which we started connecting.\n // - #connectStart is set to the current time when connect() is called.\n // - When we receive the 'connected' message we record the time to connect and\n // set #connectStart to undefined.\n // - If disconnect() is called with a defined #connectStart then we record\n // DID_NOT_CONNECT_VALUE and set #connectStart to undefined.\n //\n // TODO: this should be folded into the ConnectionManager.\n readonly timeToConnectMs = this.#register(\n new Gauge(MetricName.TimeToConnectMs),\n );\n\n // lastConnectError records the last error that occurred when connecting,\n // if any. It is cleared when connecting successfully or when reported, so this\n // state only gets reported if there was a failure during the reporting period and\n // we are still not connected.\n readonly lastConnectError = this.#register(\n new State(\n MetricName.LastConnectError,\n true, // clearOnFlush\n ),\n );\n\n // notConnected records the reason why the client is not currently connected.\n // It is cleared when the client successfully connects.\n readonly #notConnected = this.#register(new State(MetricName.NotConnected));\n\n // The time from the call to connect() to receiving the 'connected' ws message\n // for the current connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect untill there is a\n // connect error, or client reports disconnected and waiting for visible.\n // Should have a value iff _notConnected has no value.\n readonly #timeToConnectMsV2 = this.#register(\n new Gauge(MetricName.TimeToConnectMsV2),\n );\n\n // lastConnectErrorV2 records the last error that occurred when connecting,\n // if any. It is cleared when the client successfully connects or\n // stops trying to connect due to being hidden.\n // Should have a value iff notConnected state is NotConnectedReason.Error.\n readonly #lastConnectErrorV2 = this.#register(\n new State(MetricName.LastConnectErrorV2),\n );\n\n // The total time it took to connect across retries for the current\n // connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect until there is a\n // connect error, or client reports disconnected and waiting for visible.\n // See Zero.#totalToConnectStart for details of how this total is computed.\n // Should have a value iff _notConnected has no value.\n readonly #totalTimeToConnectMs = this.#register(\n new Gauge(MetricName.TotalTimeToConnectMs),\n );\n\n #setNotConnectedReason(reason: NotConnectedReason) {\n this.#notConnected.set(reason);\n }\n\n setConnected(timeToConnectMs: number, totalTimeToConnectMs: number) {\n this.#notConnected.clear();\n this.#lastConnectErrorV2.clear();\n this.#timeToConnectMsV2.set(timeToConnectMs);\n this.#totalTimeToConnectMs.set(totalTimeToConnectMs);\n }\n\n setDisconnectedWaitingForVisible() {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#lastConnectErrorV2.clear();\n let notConnectedReason: NotConnectedReason;\n switch (this.#notConnected.get()) {\n case 'init':\n notConnectedReason = 'hidden_was_init';\n break;\n case 'error':\n notConnectedReason = 'hidden_was_error';\n break;\n default:\n notConnectedReason = 'hidden';\n break;\n }\n this.#setNotConnectedReason(notConnectedReason);\n }\n\n setConnectError(reason: ZeroError) {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#setNotConnectedReason('error');\n this.#lastConnectErrorV2.set(getLastConnectErrorValue(reason));\n }\n\n /**\n * Tags to include in all metrics.\n */\n readonly tags: string[] = [];\n\n // Flushes all metrics to an array of time series (plural), one Series\n // per metric.\n async flush() {\n const lc = this.#lc;\n if (this.#timerID === null) {\n lc.error?.('MetricManager.flush() called but already stopped');\n return;\n }\n const allSeries: Series[] = [];\n for (const metric of this.#metrics) {\n const series = metric.flush();\n if (series !== undefined) {\n allSeries.push({\n ...series,\n host: this.#host,\n tags: this.tags,\n });\n }\n }\n if (allSeries.length === 0) {\n lc?.debug?.('No metrics to report');\n return;\n }\n try {\n await this.#reporter(allSeries);\n } catch (e) {\n lc?.error?.('Error reporting metrics', e);\n }\n }\n\n stop() {\n if (this.#timerID === null) {\n this.#lc.error?.('MetricManager.stop() called but already stopped');\n return;\n }\n clearInterval(this.#timerID);\n this.#timerID = null;\n }\n\n #register<M extends Flushable>(metric: M) {\n this.#metrics.push(metric);\n return metric;\n }\n}\n\n// These two types are influenced by Datadog's API's needs. We could change what\n// we use internally if necessary, but we'd just have to convert to/from before\n// sending to DD. So for convenience we go with their format.\n\n/** Series is a time series of points for a single metric. */\nexport type Series = {\n host: string;\n metric: string; // We call this 'name' bc 'metric' is overloaded in code.\n points: Point[];\n tags?: string[];\n};\n/**\n * A point is a second-resolution timestamp and a set of values for that\n * timestamp. A point represents exactly one second in time and the values\n * are those recorded for that second. The first element of this array\n * is the timestamp and the second element is an array of values.\n */\nexport type Point = [number, number[]];\n\nfunction makePoint(ts: number, value: number): Point {\n return [ts, [value]];\n}\n\ntype Flushable = {\n flush(): Pick<Series, 'metric' | 'points'> | undefined;\n};\n\n/**\n * Gauge is a metric type that represents a single value that can go up and\n * down. It's typically used to track discrete values or counts eg the number\n * of active users, number of connections, cpu load, etc. A gauge retains\n * its value when flushed.\n *\n * We use a Gauge to sample at the client. If we are interested in tracking\n * a metric value *per client*, the client can note the latest value in\n * a Gauge metric. The metric is periodically reported via Reporter. On the\n * server, we graph the value of the metric rolled up over the periodic\n * reporting period, that is, counted over a span of time equal to the\n * reporting period. The result is ~one point per client per reporting\n * period.\n */\nexport class Gauge implements Flushable {\n readonly #name: string;\n #value: number | undefined = undefined;\n\n constructor(name: string) {\n this.#name = name;\n }\n\n set(value: number) {\n this.#value = value;\n }\n\n get() {\n return this.#value;\n }\n\n clear() {\n this.#value = undefined;\n }\n\n flush() {\n if (this.#value === undefined) {\n return undefined;\n }\n // Gauge reports the timestamp at flush time, not at the point the value was\n // recorded.\n const points = [makePoint(t(), this.#value)];\n return {metric: this.#name, points};\n }\n}\n\nfunction t() {\n return Math.round(Date.now() / 1000);\n}\n\n/**\n * State is a metric type that represents a specific state that the system is\n * in, for example the state of a connection which may be 'open' or 'closed'.\n * The state is given a name/prefix at construction time (eg 'connection') and\n * then can be set to a specific state (eg 'open'). The prefix is prepended to\n * the set state (eg, 'connection_open') and a value of 1 is reported.\n * Unset/cleared states are not reported.\n *\n * Example:\n * const s = new State('connection');\n * s.set('open');\n * s.flush(); // returns {metric: 'connection_open', points: [[now(), [1]]]}\n */\nexport class State implements Flushable {\n readonly #prefix: string;\n readonly #clearOnFlush: boolean;\n #current: string | undefined = undefined;\n\n constructor(prefix: string, clearOnFlush = false) {\n this.#prefix = prefix;\n this.#clearOnFlush = clearOnFlush;\n }\n\n set(state: string) {\n this.#current = state;\n }\n\n get() {\n return this.#current;\n }\n\n clear() {\n this.#current = undefined;\n }\n\n flush() {\n if (this.#current === undefined) {\n return undefined;\n }\n const gauge = new Gauge([this.#prefix, this.#current].join('_'));\n gauge.set(1);\n const series = gauge.flush();\n if (this.#clearOnFlush) {\n this.clear();\n }\n return series;\n }\n}\n"],"mappings":"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"}
@@ -33,6 +33,9 @@ export type ZeroOptions<S extends BaseDefaultSchema = DefaultSchema, MD extends
33
33
  * The call to `connect` is handled automatically by the ZeroProvider component
34
34
  * for React and SolidJS when the `auth` prop changes.
35
35
  *
36
+ * Transitions between authenticated and logged-out states recreate the Zero
37
+ * instance instead.
38
+ *
36
39
  * When `auth` changes while connected, Zero refreshes server-side auth context
37
40
  * and re-transforms queries without reconnecting.
38
41
  *
@@ -42,15 +45,18 @@ export type ZeroOptions<S extends BaseDefaultSchema = DefaultSchema, MD extends
42
45
  */
43
46
  auth?: string | null | undefined;
44
47
  /**
45
- * A unique identifier for the user. Must be non-empty.
48
+ * A unique identifier for the user.
49
+ *
50
+ * Omit this, or set to `null`, for logged-out clients.
51
+ *
52
+ * This is passed to the query/mutate endpoints via an `X-User-ID` header and
53
+ * must be used to validate claimed user identity against the provided auth
54
+ * on the server (either token or cookie auth).
46
55
  *
47
56
  * Each userID gets its own client-side storage so that the app can switch
48
57
  * between users without losing state.
49
- *
50
- * This must match the `sub` claim of the `auth` token if
51
- * `auth` is provided.
52
58
  */
53
- userID: string;
59
+ userID?: string | null | undefined;
54
60
  /**
55
61
  * Distinguishes the storage used by this Zero instance from that of other
56
62
  * instances with the same userID. Useful in the case where the app wants to
@@ -143,6 +149,29 @@ export type ZeroOptions<S extends BaseDefaultSchema = DefaultSchema, MD extends
143
149
  * These headers are passed through zero-cache to the query endpoint.
144
150
  */
145
151
  queryHeaders?: Record<string, string> | undefined;
152
+ /**
153
+ * Optional callback that returns a W3C `traceparent` header value for
154
+ * distributed tracing. Called before sending WebSocket messages that
155
+ * trigger API server calls (`push`, `changeDesiredQueries`,
156
+ * `initConnection`).
157
+ *
158
+ * This enables end-to-end trace correlation from your frontend through
159
+ * zero-cache to your API server.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * import {propagation, context} from '@opentelemetry/api';
164
+ *
165
+ * new Zero({
166
+ * getTraceparent: () => {
167
+ * const carrier: Record<string, string> = {};
168
+ * propagation.inject(context.active(), carrier);
169
+ * return carrier.traceparent;
170
+ * },
171
+ * });
172
+ * ```
173
+ */
174
+ getTraceparent?: (() => string | undefined) | undefined;
146
175
  /**
147
176
  * `onOnlineChange` is called when the Zero instance's online status changes.
148
177
  *
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/options.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/options.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","names":[],"sources":["../../../../../zero-client/src/client/options.ts"],"sourcesContent":["import type {LogLevel} from '@rocicorp/logger';\nimport type {StoreProvider} from '../../../replicache/src/kv/store.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {\n BaseDefaultContext,\n BaseDefaultSchema,\n DefaultContext,\n DefaultSchema,\n} from '../../../zero-types/src/default-types.ts';\nimport type {AnyMutatorRegistry} from '../../../zql/src/mutate/mutator-registry.ts';\nimport type {CustomMutatorDefs} from './custom.ts';\nimport {UpdateNeededReasonType} from './update-needed-reason-type.ts';\n\n/**\n * Configuration for {@linkcode Zero}.\n */\nexport type ZeroOptions<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n C extends BaseDefaultContext = DefaultContext,\n> = {\n /**\n * URL to the zero-cache. This can be a simple hostname, e.g.\n * - \"https://myapp-myteam.zero.ms\"\n * or a prefix with a single path component, e.g.\n * - \"https://myapp-myteam.zero.ms/zero\"\n * - \"https://myapp-myteam.zero.ms/db\"\n *\n * The latter is useful for configuring routing rules (e.g. \"/zero/\\*\") when\n * the zero-cache is hosted on the same domain as the application. **Note that\n * only a single path segment is allowed (e.g. it cannot be \"/proxy/zero/\\*\")**.\n */\n cacheURL?: string | null | undefined;\n\n /**\n * @deprecated Use {@linkcode cacheURL} instead.\n */\n server?: string | null | undefined;\n\n /**\n * A token to identify and authenticate the user.\n *\n * Set `auth` to `null` or `undefined` if there is no logged in user.\n *\n * The call to `connect` is handled automatically by the ZeroProvider component\n * for React and SolidJS when the `auth` prop changes.\n *\n * When `auth` changes while connected, Zero refreshes server-side auth context\n * and re-transforms queries without reconnecting.\n *\n * When a 401 or 403 HTTP status code is received from your server, Zero will\n * transition to the `needs-auth` connection state. The app should call\n * `zero.connection.connect({auth: newToken})` with a new token to reconnect.\n */\n auth?: string | null | undefined;\n\n /**\n * A unique identifier for the user. Must be non-empty.\n *\n * Each userID gets its own client-side storage so that the app can switch\n * between users without losing state.\n *\n * This must match the `sub` claim of the `auth` token if\n * `auth` is provided.\n */\n userID: string;\n\n /**\n * Distinguishes the storage used by this Zero instance from that of other\n * instances with the same userID. Useful in the case where the app wants to\n * have multiple Zero instances for the same user for different parts of the\n * app.\n */\n storageKey?: string | undefined;\n\n /**\n * Determines the level of detail at which Zero logs messages about\n * its operation. Messages are logged to the `console`.\n *\n * When this is set to `'debug'`, `'info'` and `'error'` messages are also\n * logged. When set to `'info'`, `'info'` and `'error'` but not\n * `'debug'` messages are logged. When set to `'error'` only `'error'`\n * messages are logged.\n *\n * Default is `'error'`.\n */\n logLevel?: LogLevel | undefined;\n\n /**\n * This defines the schema of the tables used in Zero and their relationships\n * to one another.\n */\n schema: S;\n\n /**\n * `mutators` is a map of custom mutator definitions. The keys are\n * namespaces or names of the mutators. The values are the mutator\n * implementations. Client side mutators must be idempotent as a\n * mutation can be rebased multiple times when folding in authoritative\n * changes from the server to the client.\n *\n * Define mutators using the `defineMutator` function to create type-safe,\n * parameterized mutations. Mutators can be top-level or grouped in namespaces.\n *\n * @example\n * ```ts\n * import {defineMutator} from '@rocicorp/zero';\n *\n * const z = new Zero({\n * schema,\n * userID,\n * mutators: {\n * // Top-level mutator\n * increment: defineMutator(({tx, args}: {tx: Transaction<Schema>, args: {id: string}}) =>\n * tx.mutate.counter.update({id: args.id, value: tx.query.counter.where('id', '=', args.id).value + 1})\n * ),\n * // Namespace with multiple mutators\n * issues: {\n * create: defineMutator(({tx, args}: {tx: Transaction<Schema>, args: {title: string}}) =>\n * tx.mutate.issues.insert({id: nanoid(), title: args.title, status: 'open'})\n * ),\n * close: defineMutator(({tx, args}: {tx: Transaction<Schema>, args: {id: string}}) =>\n * tx.mutate.issues.update({id: args.id, status: 'closed'})\n * ),\n * },\n * },\n * });\n *\n * // Usage\n * await z.mutate.increment({id: 'counter-1'}).client;\n * await z.mutate.issues.create({title: 'New issue'}).client;\n * await z.mutate.issues.close({id: 'issue-123'}).client;\n * ```\n */\n mutators?: MD extends CustomMutatorDefs ? MD : AnyMutatorRegistry | undefined;\n\n /**\n * Custom URL for mutation requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n */\n mutateURL?: string | undefined;\n\n /**\n * Custom headers to include in mutation requests sent to your API server.\n * These headers are passed through zero-cache to the mutate endpoint.\n */\n mutateHeaders?: Record<string, string> | undefined;\n\n /**\n * Custom URL for query requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n *\n * @deprecated Use {@linkcode queryURL} instead.\n */\n getQueriesURL?: string | undefined;\n\n /**\n * Custom URL for query requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n */\n queryURL?: string | undefined;\n\n /**\n * Custom headers to include in query requests sent to your API server.\n * These headers are passed through zero-cache to the query endpoint.\n */\n queryHeaders?: Record<string, string> | undefined;\n\n /**\n * `onOnlineChange` is called when the Zero instance's online status changes.\n *\n * @deprecated Use {@linkcode Connection.state.subscribe} on the Zero instance instead. e.g.\n * ```ts\n * const zero = new Zero({...});\n * zero.connection.state.subscribe((state) => {\n * console.log('Connection state:', state.name);\n * });\n * ```\n *\n * Or use a hook like {@linkcode useConnectionState} to subscribe to state changes.\n */\n onOnlineChange?: ((online: boolean) => void) | undefined;\n\n /**\n * `onUpdateNeeded` is called when a client code update is needed.\n *\n * See {@link UpdateNeededReason} for why updates can be needed.\n *\n * The default behavior is to reload the page (using `location.reload()`).\n * Provide your own function to prevent the page from\n * reloading automatically. You may want to display a toast to inform the end\n * user there is a new version of your app available and prompt them to\n * refresh.\n */\n onUpdateNeeded?: ((reason: UpdateNeededReason) => void) | undefined;\n\n /**\n * `onClientStateNotFound` is called when this client is no longer able\n * to sync with the zero-cache due to missing synchronization state. This\n * can be because:\n * - the local persistent synchronization state has been garbage collected.\n * This can happen if the client has no pending mutations and has not been\n * used for a while (e.g. the client's tab has been hidden for a long time).\n * - the zero-cache fails to find the server side synchronization state for\n * this client.\n *\n * The default behavior is to reload the page (using `location.reload()`).\n * Provide your own function to prevent the page from reloading automatically.\n */\n onClientStateNotFound?: (() => void) | undefined;\n\n /**\n * The number of milliseconds to wait before disconnecting a Zero\n * instance whose tab has become hidden.\n *\n * Instances in hidden tabs are disconnected to save resources.\n *\n * Default is 5 minutes.\n */\n hiddenTabDisconnectDelay?: number | undefined;\n\n /**\n * The number of milliseconds to wait before disconnecting a Zero\n * instance when the connection to the server has timed out.\n *\n * Default is 1 minute.\n */\n disconnectTimeoutMs?: number | undefined;\n\n /**\n * The timeout in milliseconds for ping operations. This value is used for:\n * - How long to wait in idle before sending a ping to the server\n * - How long to wait for a pong response after sending a ping\n *\n * Total time to detect a dead connection is 2 × pingTimeoutMs.\n *\n * Default is 5_000.\n */\n pingTimeoutMs?: number | undefined;\n\n /**\n * Determines what kind of storage implementation to use on the client.\n *\n * Defaults to `'idb'` which means that Zero uses an IndexedDB storage\n * implementation. This allows the data to be persisted on the client and\n * enables faster syncs between application restarts.\n *\n * By setting this to `'mem'`, Zero uses an in memory storage and\n * the data is not persisted on the client.\n *\n * You can also set this to a function that is used to create new KV stores,\n * allowing a custom implementation of the underlying storage layer.\n */\n kvStore?: 'mem' | 'idb' | StoreProvider | undefined;\n\n /**\n * The maximum number of bytes to allow in a single header.\n *\n * Zero adds some extra information to headers on initialization if possible.\n * This speeds up data synchronization. This number should be kept less than\n * or equal to the maximum header size allowed by the zero-cache and any load\n * balancers.\n *\n * Default value: 8kb.\n */\n maxHeaderLength?: number | undefined;\n\n /**\n * The maximum amount of milliseconds to wait for a materialization to\n * complete (including network/server time) before printing a warning to the\n * console.\n *\n * Default value: 5_000.\n */\n slowMaterializeThreshold?: number | undefined;\n\n /**\n * UI rendering libraries will often provide a utility for batching multiple\n * state updates into a single render. Some examples are React's\n * `unstable_batchedUpdates`, and solid-js's `batch`.\n *\n * This option enables integrating these batch utilities with Zero.\n *\n * When `batchViewUpdates` is provided, Zero will call it whenever\n * it updates query view state with an `applyViewUpdates` function\n * that performs the actual state updates.\n *\n * Zero updates query view state when:\n * 1. creating a new view\n * 2. updating all existing queries' views to a new consistent state\n *\n * When creating a new view, that single view's creation will be wrapped\n * in a `batchViewUpdates` call.\n *\n * When updating existing queries, all queries will be updated in a single\n * `batchViewUpdates` call, so that the transition to the new consistent\n * state can be done in a single render.\n *\n * Implementations must always call `applyViewUpdates` synchronously.\n */\n batchViewUpdates?: ((applyViewUpdates: () => void) => void) | undefined;\n\n /**\n * The maximum number of recent queries, no longer subscribed to by a preload\n * or view, to continue syncing.\n *\n * Defaults is 0.\n *\n * @deprecated Use ttl instead\n */\n maxRecentQueries?: number | undefined;\n\n /**\n * Changes to queries are sent to server in batches. This option controls\n * the number of milliseconds to wait before sending the next batch.\n *\n * Defaults is 10.\n */\n queryChangeThrottleMs?: number | undefined;\n\n /**\n * Context is passed to queries when they are executed.\n */\n context?: C | undefined;\n} & (unknown extends DefaultContext\n ? {}\n : {\n context: C;\n });\n\n/**\n * @deprecated Use {@link ZeroOptions} instead.\n */\nexport type ZeroAdvancedOptions<\n S extends BaseDefaultSchema,\n MD extends CustomMutatorDefs | undefined,\n Context extends BaseDefaultContext,\n> = ZeroOptions<S, MD, Context>;\n\ntype UpdateNeededReasonBase = {\n message?: string;\n};\n\nexport type UpdateNeededReason =\n | ({type: UpdateNeededReasonType.NewClientGroup} & UpdateNeededReasonBase)\n | ({\n type: UpdateNeededReasonType.VersionNotSupported;\n } & UpdateNeededReasonBase)\n | ({\n type: UpdateNeededReasonType.SchemaVersionNotSupported;\n } & UpdateNeededReasonBase);\n\nexport const updateNeededReasonTypeSchema: v.Type<UpdateNeededReason['type']> =\n v.literalUnion(\n UpdateNeededReasonType.NewClientGroup,\n UpdateNeededReasonType.VersionNotSupported,\n UpdateNeededReasonType.SchemaVersionNotSupported,\n );\n"],"mappings":";;;AAgWA,IAAa,+BACX,aACE,gBACA,qBACA,0BACD"}
1
+ {"version":3,"file":"options.js","names":[],"sources":["../../../../../zero-client/src/client/options.ts"],"sourcesContent":["import type {LogLevel} from '@rocicorp/logger';\nimport type {StoreProvider} from '../../../replicache/src/kv/store.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {\n BaseDefaultContext,\n BaseDefaultSchema,\n DefaultContext,\n DefaultSchema,\n} from '../../../zero-types/src/default-types.ts';\nimport type {AnyMutatorRegistry} from '../../../zql/src/mutate/mutator-registry.ts';\nimport type {CustomMutatorDefs} from './custom.ts';\nimport {UpdateNeededReasonType} from './update-needed-reason-type.ts';\n\n/**\n * Configuration for {@linkcode Zero}.\n */\nexport type ZeroOptions<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n C extends BaseDefaultContext = DefaultContext,\n> = {\n /**\n * URL to the zero-cache. This can be a simple hostname, e.g.\n * - \"https://myapp-myteam.zero.ms\"\n * or a prefix with a single path component, e.g.\n * - \"https://myapp-myteam.zero.ms/zero\"\n * - \"https://myapp-myteam.zero.ms/db\"\n *\n * The latter is useful for configuring routing rules (e.g. \"/zero/\\*\") when\n * the zero-cache is hosted on the same domain as the application. **Note that\n * only a single path segment is allowed (e.g. it cannot be \"/proxy/zero/\\*\")**.\n */\n cacheURL?: string | null | undefined;\n\n /**\n * @deprecated Use {@linkcode cacheURL} instead.\n */\n server?: string | null | undefined;\n\n /**\n * A token to identify and authenticate the user.\n *\n * Set `auth` to `null` or `undefined` if there is no logged in user.\n *\n * The call to `connect` is handled automatically by the ZeroProvider component\n * for React and SolidJS when the `auth` prop changes.\n *\n * Transitions between authenticated and logged-out states recreate the Zero\n * instance instead.\n *\n * When `auth` changes while connected, Zero refreshes server-side auth context\n * and re-transforms queries without reconnecting.\n *\n * When a 401 or 403 HTTP status code is received from your server, Zero will\n * transition to the `needs-auth` connection state. The app should call\n * `zero.connection.connect({auth: newToken})` with a new token to reconnect.\n */\n auth?: string | null | undefined;\n\n /**\n * A unique identifier for the user.\n *\n * Omit this, or set to `null`, for logged-out clients.\n *\n * This is passed to the query/mutate endpoints via an `X-User-ID` header and\n * must be used to validate claimed user identity against the provided auth\n * on the server (either token or cookie auth).\n *\n * Each userID gets its own client-side storage so that the app can switch\n * between users without losing state.\n */\n userID?: string | null | undefined;\n\n /**\n * Distinguishes the storage used by this Zero instance from that of other\n * instances with the same userID. Useful in the case where the app wants to\n * have multiple Zero instances for the same user for different parts of the\n * app.\n */\n storageKey?: string | undefined;\n\n /**\n * Determines the level of detail at which Zero logs messages about\n * its operation. Messages are logged to the `console`.\n *\n * When this is set to `'debug'`, `'info'` and `'error'` messages are also\n * logged. When set to `'info'`, `'info'` and `'error'` but not\n * `'debug'` messages are logged. When set to `'error'` only `'error'`\n * messages are logged.\n *\n * Default is `'error'`.\n */\n logLevel?: LogLevel | undefined;\n\n /**\n * This defines the schema of the tables used in Zero and their relationships\n * to one another.\n */\n schema: S;\n\n /**\n * `mutators` is a map of custom mutator definitions. The keys are\n * namespaces or names of the mutators. The values are the mutator\n * implementations. Client side mutators must be idempotent as a\n * mutation can be rebased multiple times when folding in authoritative\n * changes from the server to the client.\n *\n * Define mutators using the `defineMutator` function to create type-safe,\n * parameterized mutations. Mutators can be top-level or grouped in namespaces.\n *\n * @example\n * ```ts\n * import {defineMutator} from '@rocicorp/zero';\n *\n * const z = new Zero({\n * schema,\n * userID,\n * mutators: {\n * // Top-level mutator\n * increment: defineMutator(({tx, args}: {tx: Transaction<Schema>, args: {id: string}}) =>\n * tx.mutate.counter.update({id: args.id, value: tx.query.counter.where('id', '=', args.id).value + 1})\n * ),\n * // Namespace with multiple mutators\n * issues: {\n * create: defineMutator(({tx, args}: {tx: Transaction<Schema>, args: {title: string}}) =>\n * tx.mutate.issues.insert({id: nanoid(), title: args.title, status: 'open'})\n * ),\n * close: defineMutator(({tx, args}: {tx: Transaction<Schema>, args: {id: string}}) =>\n * tx.mutate.issues.update({id: args.id, status: 'closed'})\n * ),\n * },\n * },\n * });\n *\n * // Usage\n * await z.mutate.increment({id: 'counter-1'}).client;\n * await z.mutate.issues.create({title: 'New issue'}).client;\n * await z.mutate.issues.close({id: 'issue-123'}).client;\n * ```\n */\n mutators?: MD extends CustomMutatorDefs ? MD : AnyMutatorRegistry | undefined;\n\n /**\n * Custom URL for mutation requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n */\n mutateURL?: string | undefined;\n\n /**\n * Custom headers to include in mutation requests sent to your API server.\n * These headers are passed through zero-cache to the mutate endpoint.\n */\n mutateHeaders?: Record<string, string> | undefined;\n\n /**\n * Custom URL for query requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n *\n * @deprecated Use {@linkcode queryURL} instead.\n */\n getQueriesURL?: string | undefined;\n\n /**\n * Custom URL for query requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n */\n queryURL?: string | undefined;\n\n /**\n * Custom headers to include in query requests sent to your API server.\n * These headers are passed through zero-cache to the query endpoint.\n */\n queryHeaders?: Record<string, string> | undefined;\n\n /**\n * Optional callback that returns a W3C `traceparent` header value for\n * distributed tracing. Called before sending WebSocket messages that\n * trigger API server calls (`push`, `changeDesiredQueries`,\n * `initConnection`).\n *\n * This enables end-to-end trace correlation from your frontend through\n * zero-cache to your API server.\n *\n * @example\n * ```ts\n * import {propagation, context} from '@opentelemetry/api';\n *\n * new Zero({\n * getTraceparent: () => {\n * const carrier: Record<string, string> = {};\n * propagation.inject(context.active(), carrier);\n * return carrier.traceparent;\n * },\n * });\n * ```\n */\n getTraceparent?: (() => string | undefined) | undefined;\n\n /**\n * `onOnlineChange` is called when the Zero instance's online status changes.\n *\n * @deprecated Use {@linkcode Connection.state.subscribe} on the Zero instance instead. e.g.\n * ```ts\n * const zero = new Zero({...});\n * zero.connection.state.subscribe((state) => {\n * console.log('Connection state:', state.name);\n * });\n * ```\n *\n * Or use a hook like {@linkcode useConnectionState} to subscribe to state changes.\n */\n onOnlineChange?: ((online: boolean) => void) | undefined;\n\n /**\n * `onUpdateNeeded` is called when a client code update is needed.\n *\n * See {@link UpdateNeededReason} for why updates can be needed.\n *\n * The default behavior is to reload the page (using `location.reload()`).\n * Provide your own function to prevent the page from\n * reloading automatically. You may want to display a toast to inform the end\n * user there is a new version of your app available and prompt them to\n * refresh.\n */\n onUpdateNeeded?: ((reason: UpdateNeededReason) => void) | undefined;\n\n /**\n * `onClientStateNotFound` is called when this client is no longer able\n * to sync with the zero-cache due to missing synchronization state. This\n * can be because:\n * - the local persistent synchronization state has been garbage collected.\n * This can happen if the client has no pending mutations and has not been\n * used for a while (e.g. the client's tab has been hidden for a long time).\n * - the zero-cache fails to find the server side synchronization state for\n * this client.\n *\n * The default behavior is to reload the page (using `location.reload()`).\n * Provide your own function to prevent the page from reloading automatically.\n */\n onClientStateNotFound?: (() => void) | undefined;\n\n /**\n * The number of milliseconds to wait before disconnecting a Zero\n * instance whose tab has become hidden.\n *\n * Instances in hidden tabs are disconnected to save resources.\n *\n * Default is 5 minutes.\n */\n hiddenTabDisconnectDelay?: number | undefined;\n\n /**\n * The number of milliseconds to wait before disconnecting a Zero\n * instance when the connection to the server has timed out.\n *\n * Default is 1 minute.\n */\n disconnectTimeoutMs?: number | undefined;\n\n /**\n * The timeout in milliseconds for ping operations. This value is used for:\n * - How long to wait in idle before sending a ping to the server\n * - How long to wait for a pong response after sending a ping\n *\n * Total time to detect a dead connection is 2 × pingTimeoutMs.\n *\n * Default is 5_000.\n */\n pingTimeoutMs?: number | undefined;\n\n /**\n * Determines what kind of storage implementation to use on the client.\n *\n * Defaults to `'idb'` which means that Zero uses an IndexedDB storage\n * implementation. This allows the data to be persisted on the client and\n * enables faster syncs between application restarts.\n *\n * By setting this to `'mem'`, Zero uses an in memory storage and\n * the data is not persisted on the client.\n *\n * You can also set this to a function that is used to create new KV stores,\n * allowing a custom implementation of the underlying storage layer.\n */\n kvStore?: 'mem' | 'idb' | StoreProvider | undefined;\n\n /**\n * The maximum number of bytes to allow in a single header.\n *\n * Zero adds some extra information to headers on initialization if possible.\n * This speeds up data synchronization. This number should be kept less than\n * or equal to the maximum header size allowed by the zero-cache and any load\n * balancers.\n *\n * Default value: 8kb.\n */\n maxHeaderLength?: number | undefined;\n\n /**\n * The maximum amount of milliseconds to wait for a materialization to\n * complete (including network/server time) before printing a warning to the\n * console.\n *\n * Default value: 5_000.\n */\n slowMaterializeThreshold?: number | undefined;\n\n /**\n * UI rendering libraries will often provide a utility for batching multiple\n * state updates into a single render. Some examples are React's\n * `unstable_batchedUpdates`, and solid-js's `batch`.\n *\n * This option enables integrating these batch utilities with Zero.\n *\n * When `batchViewUpdates` is provided, Zero will call it whenever\n * it updates query view state with an `applyViewUpdates` function\n * that performs the actual state updates.\n *\n * Zero updates query view state when:\n * 1. creating a new view\n * 2. updating all existing queries' views to a new consistent state\n *\n * When creating a new view, that single view's creation will be wrapped\n * in a `batchViewUpdates` call.\n *\n * When updating existing queries, all queries will be updated in a single\n * `batchViewUpdates` call, so that the transition to the new consistent\n * state can be done in a single render.\n *\n * Implementations must always call `applyViewUpdates` synchronously.\n */\n batchViewUpdates?: ((applyViewUpdates: () => void) => void) | undefined;\n\n /**\n * The maximum number of recent queries, no longer subscribed to by a preload\n * or view, to continue syncing.\n *\n * Defaults is 0.\n *\n * @deprecated Use ttl instead\n */\n maxRecentQueries?: number | undefined;\n\n /**\n * Changes to queries are sent to server in batches. This option controls\n * the number of milliseconds to wait before sending the next batch.\n *\n * Defaults is 10.\n */\n queryChangeThrottleMs?: number | undefined;\n\n /**\n * Context is passed to queries when they are executed.\n */\n context?: C | undefined;\n} & (unknown extends DefaultContext\n ? {}\n : {\n context: C;\n });\n\n/**\n * @deprecated Use {@link ZeroOptions} instead.\n */\nexport type ZeroAdvancedOptions<\n S extends BaseDefaultSchema,\n MD extends CustomMutatorDefs | undefined,\n Context extends BaseDefaultContext,\n> = ZeroOptions<S, MD, Context>;\n\ntype UpdateNeededReasonBase = {\n message?: string;\n};\n\nexport type UpdateNeededReason =\n | ({type: UpdateNeededReasonType.NewClientGroup} & UpdateNeededReasonBase)\n | ({\n type: UpdateNeededReasonType.VersionNotSupported;\n } & UpdateNeededReasonBase)\n | ({\n type: UpdateNeededReasonType.SchemaVersionNotSupported;\n } & UpdateNeededReasonBase);\n\nexport const updateNeededReasonTypeSchema: v.Type<UpdateNeededReason['type']> =\n v.literalUnion(\n UpdateNeededReasonType.NewClientGroup,\n UpdateNeededReasonType.VersionNotSupported,\n UpdateNeededReasonType.SchemaVersionNotSupported,\n );\n"],"mappings":";;;AA8XA,IAAa,+BACX,aACE,gBACA,qBACA,0BACD"}
@@ -13,7 +13,7 @@ function validateServerParam(paramName, server) {
13
13
  const urlString = url.toString();
14
14
  const pathComponents = url.pathname.split("/");
15
15
  if (pathComponents[0] === "") pathComponents.shift();
16
- if (pathComponents[pathComponents.length - 1] === "") pathComponents.pop();
16
+ if (pathComponents.at(-1) === "") pathComponents.pop();
17
17
  if (pathComponents.length > 1) throw new Error(`ZeroOptions.${paramName} may have at most one path component.${forExample("zero")}`);
18
18
  for (const [property, invalidEndsWith] of [["search", "?"], ["hash", "#"]]) if (url[property] || urlString.endsWith(invalidEndsWith)) throw new Error(`ZeroOptions.${paramName} must not contain a ${property} component.${forExample()}`);
19
19
  return urlString;
@@ -1 +1 @@
1
- {"version":3,"file":"server-option.js","names":[],"sources":["../../../../../zero-client/src/client/server-option.ts"],"sourcesContent":["import {getBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport type {HTTPString} from './http-string.ts';\n\nfunction validateServerParam(paramName: string, server: string): HTTPString {\n const expectedProtocol = 'http';\n const forExample = (path: string = '') =>\n ` For example: \"${expectedProtocol}s://myapp-myteam.zero.ms/${path}\".`;\n\n if (\n !server.startsWith(`${expectedProtocol}://`) &&\n !server.startsWith(`${expectedProtocol}s://`)\n ) {\n throw new Error(\n `ZeroOptions.${paramName} must use the \"${expectedProtocol}\" or \"${expectedProtocol}s\" scheme.`,\n );\n }\n let url;\n try {\n url = new URL(server);\n } catch {\n throw new Error(\n `ZeroOptions.${paramName} must be a valid URL.${forExample()}`,\n );\n }\n\n const urlString = url.toString();\n\n const pathComponents = url.pathname.split('/');\n if (pathComponents[0] === '') {\n pathComponents.shift();\n }\n if (pathComponents[pathComponents.length - 1] === '') {\n pathComponents.pop();\n }\n if (pathComponents.length > 1) {\n throw new Error(\n `ZeroOptions.${paramName} may have at most one path component.${forExample(\n 'zero',\n )}`,\n );\n }\n\n for (const [property, invalidEndsWith] of [\n ['search', '?'],\n ['hash', '#'],\n ] as const) {\n if (url[property] || urlString.endsWith(invalidEndsWith)) {\n throw new Error(\n `ZeroOptions.${paramName} must not contain a ${property} component.${forExample()}`,\n );\n }\n }\n\n return urlString as HTTPString;\n}\n\nexport function getServer(\n server: string | undefined | null,\n): HTTPString | null {\n const WS = getBrowserGlobal('WebSocket');\n if (!WS) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'Zero started in an unsupported environment, no data will be synced.',\n );\n return null;\n }\n if (server === undefined || server === null) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'Zero starting up with no server URL. No data will be synced.',\n );\n return null;\n }\n return validateServerParam('server', server);\n}\n"],"mappings":";;AAGA,SAAS,oBAAoB,WAAmB,QAA4B;CAC1E,MAAM,mBAAmB;CACzB,MAAM,cAAc,OAAe,OACjC,kBAAkB,iBAAiB,2BAA2B,KAAK;AAErE,KACE,CAAC,OAAO,WAAW,GAAG,iBAAiB,KAAK,IAC5C,CAAC,OAAO,WAAW,GAAG,iBAAiB,MAAM,CAE7C,OAAM,IAAI,MACR,eAAe,UAAU,iBAAiB,iBAAiB,QAAQ,iBAAiB,YACrF;CAEH,IAAI;AACJ,KAAI;AACF,QAAM,IAAI,IAAI,OAAO;SACf;AACN,QAAM,IAAI,MACR,eAAe,UAAU,uBAAuB,YAAY,GAC7D;;CAGH,MAAM,YAAY,IAAI,UAAU;CAEhC,MAAM,iBAAiB,IAAI,SAAS,MAAM,IAAI;AAC9C,KAAI,eAAe,OAAO,GACxB,gBAAe,OAAO;AAExB,KAAI,eAAe,eAAe,SAAS,OAAO,GAChD,gBAAe,KAAK;AAEtB,KAAI,eAAe,SAAS,EAC1B,OAAM,IAAI,MACR,eAAe,UAAU,uCAAuC,WAC9D,OACD,GACF;AAGH,MAAK,MAAM,CAAC,UAAU,oBAAoB,CACxC,CAAC,UAAU,IAAI,EACf,CAAC,QAAQ,IAAI,CACd,CACC,KAAI,IAAI,aAAa,UAAU,SAAS,gBAAgB,CACtD,OAAM,IAAI,MACR,eAAe,UAAU,sBAAsB,SAAS,aAAa,YAAY,GAClF;AAIL,QAAO;;AAGT,SAAgB,UACd,QACmB;AAEnB,KAAI,CADO,iBAAiB,YAAY,EAC/B;AAEP,UAAQ,KACN,sEACD;AACD,SAAO;;AAET,KAAI,WAAW,KAAA,KAAa,WAAW,MAAM;AAE3C,UAAQ,KACN,+DACD;AACD,SAAO;;AAET,QAAO,oBAAoB,UAAU,OAAO"}
1
+ {"version":3,"file":"server-option.js","names":[],"sources":["../../../../../zero-client/src/client/server-option.ts"],"sourcesContent":["import {getBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport type {HTTPString} from './http-string.ts';\n\nfunction validateServerParam(paramName: string, server: string): HTTPString {\n const expectedProtocol = 'http';\n const forExample = (path: string = '') =>\n ` For example: \"${expectedProtocol}s://myapp-myteam.zero.ms/${path}\".`;\n\n if (\n !server.startsWith(`${expectedProtocol}://`) &&\n !server.startsWith(`${expectedProtocol}s://`)\n ) {\n throw new Error(\n `ZeroOptions.${paramName} must use the \"${expectedProtocol}\" or \"${expectedProtocol}s\" scheme.`,\n );\n }\n let url;\n try {\n url = new URL(server);\n } catch {\n throw new Error(\n `ZeroOptions.${paramName} must be a valid URL.${forExample()}`,\n );\n }\n\n const urlString = url.toString();\n\n const pathComponents = url.pathname.split('/');\n if (pathComponents[0] === '') {\n pathComponents.shift();\n }\n if (pathComponents.at(-1) === '') {\n pathComponents.pop();\n }\n if (pathComponents.length > 1) {\n throw new Error(\n `ZeroOptions.${paramName} may have at most one path component.${forExample(\n 'zero',\n )}`,\n );\n }\n\n for (const [property, invalidEndsWith] of [\n ['search', '?'],\n ['hash', '#'],\n ] as const) {\n if (url[property] || urlString.endsWith(invalidEndsWith)) {\n throw new Error(\n `ZeroOptions.${paramName} must not contain a ${property} component.${forExample()}`,\n );\n }\n }\n\n return urlString as HTTPString;\n}\n\nexport function getServer(\n server: string | undefined | null,\n): HTTPString | null {\n const WS = getBrowserGlobal('WebSocket');\n if (!WS) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'Zero started in an unsupported environment, no data will be synced.',\n );\n return null;\n }\n if (server === undefined || server === null) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'Zero starting up with no server URL. No data will be synced.',\n );\n return null;\n }\n return validateServerParam('server', server);\n}\n"],"mappings":";;AAGA,SAAS,oBAAoB,WAAmB,QAA4B;CAC1E,MAAM,mBAAmB;CACzB,MAAM,cAAc,OAAe,OACjC,kBAAkB,iBAAiB,2BAA2B,KAAK;AAErE,KACE,CAAC,OAAO,WAAW,GAAG,iBAAiB,KAAK,IAC5C,CAAC,OAAO,WAAW,GAAG,iBAAiB,MAAM,CAE7C,OAAM,IAAI,MACR,eAAe,UAAU,iBAAiB,iBAAiB,QAAQ,iBAAiB,YACrF;CAEH,IAAI;AACJ,KAAI;AACF,QAAM,IAAI,IAAI,OAAO;SACf;AACN,QAAM,IAAI,MACR,eAAe,UAAU,uBAAuB,YAAY,GAC7D;;CAGH,MAAM,YAAY,IAAI,UAAU;CAEhC,MAAM,iBAAiB,IAAI,SAAS,MAAM,IAAI;AAC9C,KAAI,eAAe,OAAO,GACxB,gBAAe,OAAO;AAExB,KAAI,eAAe,GAAG,GAAG,KAAK,GAC5B,gBAAe,KAAK;AAEtB,KAAI,eAAe,SAAS,EAC1B,OAAM,IAAI,MACR,eAAe,UAAU,uCAAuC,WAC9D,OACD,GACF;AAGH,MAAK,MAAM,CAAC,UAAU,oBAAoB,CACxC,CAAC,UAAU,IAAI,EACf,CAAC,QAAQ,IAAI,CACd,CACC,KAAI,IAAI,aAAa,UAAU,SAAS,gBAAgB,CACtD,OAAM,IAAI,MACR,eAAe,UAAU,sBAAsB,SAAS,aAAa,YAAY,GAClF;AAIL,QAAO;;AAGT,SAAgB,UACd,QACmB;AAEnB,KAAI,CADO,iBAAiB,YAAY,EAC/B;AAEP,UAAQ,KACN,sEACD;AACD,SAAO;;AAET,KAAI,WAAW,KAAA,KAAa,WAAW,MAAM;AAE3C,UAAQ,KACN,+DACD;AACD,SAAO;;AAET,QAAO,oBAAoB,UAAU,OAAO"}
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * The current version of Zero.
4
4
  */
5
- var version = "1.2.0";
5
+ var version = "1.3.0-canary.0";
6
6
  //#endregion
7
7
  export { version };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"zero-poke-handler.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero-poke-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACb,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,qCAAqC,CAAC;AAElE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,+CAA+C,CAAC;AACjF,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACd,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAO9D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAE3D,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,WAAW;;gBAiBpB,cAAc,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,EACrD,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACrC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,UAAU,EACd,eAAe,EAAE,eAAe;IAWlC,eAAe,CAAC,SAAS,EAAE,aAAa;IAiBxC,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS;IAa1D,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAoBzC,gBAAgB,IAAI,IAAI;CAmFzB;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,eAAe,EAAE,EAC7B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,UAAU,GAExB,CAAC,YAAY,GAAG;IAAC,eAAe,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,CAAA;CAAC,CAAC,GAChE,SAAS,CAwFZ;AAyBD,wBAAgB,kCAAkC,CAChD,EAAE,EAAE,aAAa,GAChB,sBAAsB,CAcxB"}
1
+ {"version":3,"file":"zero-poke-handler.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero-poke-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACb,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,qCAAqC,CAAC;AAElE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,+CAA+C,CAAC;AACjF,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACd,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAO9D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAE3D,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,WAAW;;gBAiBpB,cAAc,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,EACrD,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACrC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,UAAU,EACd,eAAe,EAAE,eAAe;IAWlC,eAAe,CAAC,SAAS,EAAE,aAAa;IAiBxC,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS;IAa1D,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAoBzC,gBAAgB,IAAI,IAAI;CAmFzB;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,eAAe,EAAE,EAC7B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,UAAU,GAExB,CAAC,YAAY,GAAG;IAAC,eAAe,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,CAAA;CAAC,CAAC,GAChE,SAAS,CAyFZ;AAyBD,wBAAgB,kCAAkC,CAChD,EAAE,EAAE,aAAa,GAChB,sBAAsB,CAcxB"}
@@ -130,7 +130,7 @@ var PokeHandler = class {
130
130
  function mergePokes(pokeBuffer, schema, serverToClient) {
131
131
  if (pokeBuffer.length === 0) return;
132
132
  const { baseCookie } = pokeBuffer[0].pokeStart;
133
- const { cookie } = pokeBuffer[pokeBuffer.length - 1].pokeEnd;
133
+ const { cookie } = pokeBuffer.at(-1).pokeEnd;
134
134
  const mergedPatch = [];
135
135
  const mergedLastMutationIDChanges = {};
136
136
  const mutationResults = [];
@@ -1 +1 @@
1
- {"version":3,"file":"zero-poke-handler.js","names":["#replicachePoke","#onPokeError","#clientID","#lc","#pokeBuffer","#pokeLock","#schema","#serverToClient","#mutationTracker","#receivingPoke","#handlePokeError","#pokePlaybackLoopRunning","#startPlaybackLoop","#clear","#scheduledCallback","#lastScheduledTimestamp","#processPokesForFrame"],"sources":["../../../../../zero-client/src/client/zero-poke-handler.ts"],"sourcesContent":["import {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {\n PatchOperationInternal,\n PokeInternal,\n} from '../../../replicache/src/impl.ts';\nimport type {PatchOperation} from '../../../replicache/src/patch-operation.ts';\nimport type {ClientID} from '../../../replicache/src/sync/ids.ts';\nimport {unreachable} from '../../../shared/src/asserts.ts';\nimport type {MutationPatch} from '../../../zero-protocol/src/mutations-patch.ts';\nimport type {\n PokeEndBody,\n PokePartBody,\n PokeStartBody,\n} from '../../../zero-protocol/src/poke.ts';\nimport type {QueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport type {RowPatchOp} from '../../../zero-protocol/src/row-patch.ts';\nimport {\n serverToClient,\n type NameMapper,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {\n toDesiredQueriesKey,\n toGotQueriesKey,\n toMutationResponseKey,\n toPrimaryKeyString,\n} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\n\ntype PokeAccumulator = {\n readonly pokeStart: PokeStartBody;\n readonly parts: PokePartBody[];\n readonly pokeEnd: PokeEndBody;\n};\n\n/**\n * Handles the multi-part format of zero pokes.\n * As an optimization it also debounces pokes, only poking Replicache with a\n * merged poke at most once per scheduled callback (using setTimeout).\n * This debouncing avoids wastefully computing separate diffs and IVM updates\n * for intermediate states. setTimeout is used instead of requestAnimationFrame\n * to ensure pokes are delivered even when the tab is in the background,\n * enabling notifications (sounds, favicon badges) to work correctly.\n */\nexport class PokeHandler {\n readonly #replicachePoke: (poke: PokeInternal) => Promise<void>;\n readonly #onPokeError: (error: unknown) => void;\n readonly #clientID: ClientID;\n readonly #lc: LogContext;\n #receivingPoke: Omit<PokeAccumulator, 'pokeEnd'> | undefined = undefined;\n readonly #pokeBuffer: PokeAccumulator[] = [];\n #pokePlaybackLoopRunning = false;\n #lastScheduledTimestamp = 0;\n // Serializes calls to this.#replicachePoke otherwise we can cause out of\n // order poke errors.\n readonly #pokeLock = new Lock();\n readonly #schema: Schema;\n readonly #serverToClient: NameMapper;\n readonly #mutationTracker: MutationTracker;\n\n constructor(\n replicachePoke: (poke: PokeInternal) => Promise<void>,\n onPokeError: (error: unknown) => void,\n clientID: ClientID,\n schema: Schema,\n lc: LogContext,\n mutationTracker: MutationTracker,\n ) {\n this.#replicachePoke = replicachePoke;\n this.#onPokeError = onPokeError;\n this.#clientID = clientID;\n this.#schema = schema;\n this.#serverToClient = serverToClient(schema.tables);\n this.#lc = lc.withContext('PokeHandler');\n this.#mutationTracker = mutationTracker;\n }\n\n handlePokeStart(pokeStart: PokeStartBody) {\n if (this.#receivingPoke) {\n this.#handlePokeError(\n `pokeStart ${JSON.stringify(\n pokeStart,\n )} while still receiving ${JSON.stringify(\n this.#receivingPoke.pokeStart,\n )} `,\n );\n return;\n }\n this.#receivingPoke = {\n pokeStart,\n parts: [],\n };\n }\n\n handlePokePart(pokePart: PokePartBody): number | undefined {\n if (pokePart.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokePart for ${pokePart.pokeID}, when receiving ${\n this.#receivingPoke?.pokeStart.pokeID\n }`,\n );\n return;\n }\n this.#receivingPoke.parts.push(pokePart);\n return pokePart.lastMutationIDChanges?.[this.#clientID];\n }\n\n handlePokeEnd(pokeEnd: PokeEndBody): void {\n if (pokeEnd.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokeEnd for ${pokeEnd.pokeID}, when receiving ${\n this.#receivingPoke?.pokeStart.pokeID\n }`,\n );\n return;\n }\n if (pokeEnd.cancel) {\n this.#receivingPoke = undefined;\n return;\n }\n this.#pokeBuffer.push({...this.#receivingPoke, pokeEnd});\n this.#receivingPoke = undefined;\n if (!this.#pokePlaybackLoopRunning) {\n this.#startPlaybackLoop();\n }\n }\n\n handleDisconnect(): void {\n this.#lc.debug?.('clearing due to disconnect');\n this.#clear();\n }\n\n #startPlaybackLoop() {\n this.#lc.debug?.('starting playback loop');\n this.#pokePlaybackLoopRunning = true;\n setTimeout(this.#scheduledCallback, 0);\n }\n\n #scheduledCallback = async () => {\n const lc = this.#lc.withContext(\n 'scheduledAt',\n Math.floor(performance.now()),\n );\n if (this.#pokeBuffer.length === 0) {\n lc.debug?.('stopping playback loop');\n this.#pokePlaybackLoopRunning = false;\n return;\n }\n setTimeout(this.#scheduledCallback, 0);\n const start = performance.now();\n lc.debug?.(\n 'scheduled callback fired, processing pokes. Since last callback',\n start - this.#lastScheduledTimestamp,\n );\n this.#lastScheduledTimestamp = start;\n await this.#processPokesForFrame(lc);\n lc.debug?.('processing pokes took', performance.now() - start);\n };\n\n #processPokesForFrame(lc: LogContext): Promise<void> {\n return this.#pokeLock.withLock(async () => {\n const now = Date.now();\n lc.debug?.('got poke lock at', now);\n lc.debug?.('merging', this.#pokeBuffer.length);\n try {\n const merged = mergePokes(\n this.#pokeBuffer,\n this.#schema,\n this.#serverToClient,\n );\n this.#pokeBuffer.length = 0;\n if (merged === undefined) {\n lc.debug?.('frame is empty');\n return;\n }\n const start = performance.now();\n lc.debug?.('poking replicache');\n await this.#replicachePoke(merged);\n lc.debug?.('poking replicache took', performance.now() - start);\n\n if (!('error' in merged.pullResponse)) {\n const lmid =\n merged.pullResponse.lastMutationIDChanges[this.#clientID];\n if (lmid !== undefined) {\n this.#mutationTracker.lmidAdvanced(lmid);\n }\n }\n } catch (e) {\n this.#handlePokeError(e);\n }\n });\n }\n\n #handlePokeError(e: unknown) {\n if (String(e).includes('unexpected base cookie for poke')) {\n // This can happen if cookie changes due to refresh from idb due\n // to an update arriving to different tabs in the same\n // client group at very different times. Unusual but possible.\n this.#lc.debug?.('clearing due to', e);\n } else {\n this.#lc.error?.('clearing due to unexpected poke error', e);\n }\n this.#clear();\n this.#onPokeError(e);\n }\n\n #clear() {\n this.#receivingPoke = undefined;\n this.#pokeBuffer.length = 0;\n }\n}\n\nexport function mergePokes(\n pokeBuffer: PokeAccumulator[],\n schema: Schema,\n serverToClient: NameMapper,\n):\n | (PokeInternal & {mutationResults?: MutationPatch[] | undefined})\n | undefined {\n if (pokeBuffer.length === 0) {\n return undefined;\n }\n const {baseCookie} = pokeBuffer[0].pokeStart;\n const lastPoke = pokeBuffer[pokeBuffer.length - 1];\n const {cookie} = lastPoke.pokeEnd;\n const mergedPatch: PatchOperationInternal[] = [];\n const mergedLastMutationIDChanges: Record<string, number> = {};\n const mutationResults: MutationPatch[] = [];\n\n let prevPokeEnd = undefined;\n for (const pokeAccumulator of pokeBuffer) {\n if (\n prevPokeEnd &&\n pokeAccumulator.pokeStart.baseCookie &&\n pokeAccumulator.pokeStart.baseCookie > prevPokeEnd.cookie\n ) {\n throw Error(\n `unexpected cookie gap ${JSON.stringify(prevPokeEnd)} ${JSON.stringify(\n pokeAccumulator.pokeStart,\n )}`,\n );\n }\n prevPokeEnd = pokeAccumulator.pokeEnd;\n for (const pokePart of pokeAccumulator.parts) {\n if (pokePart.lastMutationIDChanges) {\n for (const [clientID, lastMutationID] of Object.entries(\n pokePart.lastMutationIDChanges,\n )) {\n mergedLastMutationIDChanges[clientID] = lastMutationID;\n }\n }\n if (pokePart.desiredQueriesPatches) {\n for (const [clientID, queriesPatch] of Object.entries(\n pokePart.desiredQueriesPatches,\n )) {\n for (const op of queriesPatch) {\n mergedPatch.push(\n queryPatchOpToReplicachePatchOp(op, hash =>\n toDesiredQueriesKey(clientID, hash),\n ),\n );\n }\n }\n }\n if (pokePart.gotQueriesPatch) {\n for (const op of pokePart.gotQueriesPatch) {\n mergedPatch.push(\n queryPatchOpToReplicachePatchOp(op, toGotQueriesKey),\n );\n }\n }\n if (pokePart.rowsPatch) {\n for (const p of pokePart.rowsPatch) {\n const patchOp = rowsPatchOpToReplicachePatchOp(\n p,\n schema,\n serverToClient,\n );\n if (patchOp) {\n mergedPatch.push(patchOp);\n }\n }\n }\n if (pokePart.mutationsPatch) {\n for (const op of pokePart.mutationsPatch) {\n mergedPatch.push(mutationPatchOpToReplicachePatchOp(op));\n }\n }\n }\n }\n const ret: PokeInternal & {mutationResults?: MutationPatch[] | undefined} = {\n baseCookie,\n pullResponse: {\n lastMutationIDChanges: mergedLastMutationIDChanges,\n patch: mergedPatch,\n cookie,\n },\n };\n\n // For backwards compatibility. Because we're strict on our validation,\n // zero-client must be able to parse pokes with this field before we introduce it.\n // So users can update their clients and then start using custom mutators that write responses to the db.\n if (mutationResults.length > 0) {\n ret.mutationResults = mutationResults;\n }\n return ret;\n}\n\nfunction queryPatchOpToReplicachePatchOp(\n op: QueriesPatchOp,\n toKey: (hash: string) => string,\n): PatchOperation {\n switch (op.op) {\n case 'clear':\n return op;\n case 'del':\n return {\n op: 'del',\n key: toKey(op.hash),\n };\n case 'put':\n return {\n op: 'put',\n key: toKey(op.hash),\n value: null,\n };\n default:\n unreachable(op);\n }\n}\n\nexport function mutationPatchOpToReplicachePatchOp(\n op: MutationPatch,\n): PatchOperationInternal {\n switch (op.op) {\n case 'put':\n return {\n op: 'put',\n key: toMutationResponseKey(op.mutation.id),\n value: op.mutation.result,\n };\n case 'del':\n return {\n op: 'del',\n key: toMutationResponseKey(op.id),\n };\n }\n}\n\nfunction rowsPatchOpToReplicachePatchOp(\n op: RowPatchOp,\n schema: Schema,\n serverToClient: NameMapper,\n): PatchOperationInternal | undefined {\n if (op.op === 'clear') {\n return op;\n }\n // Skip rows for tables not in the client schema. This can happen when\n // the server-side query AST references tables (e.g. issueNotifications)\n // that are not yet part of the client schema definition.\n const tableName = serverToClient.tableNameIfKnown(op.tableName);\n if (!tableName) {\n return undefined;\n }\n switch (op.op) {\n case 'del':\n return {\n op: 'del',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.id),\n ),\n };\n case 'put':\n return {\n op: 'put',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.value),\n ),\n value: serverToClient.row(op.tableName, op.value),\n };\n case 'update':\n return {\n op: 'update',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.id),\n ),\n merge: op.merge\n ? serverToClient.row(op.tableName, op.merge)\n : undefined,\n constrain: serverToClient.columns(op.tableName, op.constrain),\n };\n default:\n unreachable(op);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"zero-poke-handler.js","names":["#replicachePoke","#onPokeError","#clientID","#lc","#pokeBuffer","#pokeLock","#schema","#serverToClient","#mutationTracker","#receivingPoke","#handlePokeError","#pokePlaybackLoopRunning","#startPlaybackLoop","#clear","#scheduledCallback","#lastScheduledTimestamp","#processPokesForFrame"],"sources":["../../../../../zero-client/src/client/zero-poke-handler.ts"],"sourcesContent":["import {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {\n PatchOperationInternal,\n PokeInternal,\n} from '../../../replicache/src/impl.ts';\nimport type {PatchOperation} from '../../../replicache/src/patch-operation.ts';\nimport type {ClientID} from '../../../replicache/src/sync/ids.ts';\nimport {unreachable} from '../../../shared/src/asserts.ts';\nimport type {MutationPatch} from '../../../zero-protocol/src/mutations-patch.ts';\nimport type {\n PokeEndBody,\n PokePartBody,\n PokeStartBody,\n} from '../../../zero-protocol/src/poke.ts';\nimport type {QueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport type {RowPatchOp} from '../../../zero-protocol/src/row-patch.ts';\nimport {\n serverToClient,\n type NameMapper,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {\n toDesiredQueriesKey,\n toGotQueriesKey,\n toMutationResponseKey,\n toPrimaryKeyString,\n} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\n\ntype PokeAccumulator = {\n readonly pokeStart: PokeStartBody;\n readonly parts: PokePartBody[];\n readonly pokeEnd: PokeEndBody;\n};\n\n/**\n * Handles the multi-part format of zero pokes.\n * As an optimization it also debounces pokes, only poking Replicache with a\n * merged poke at most once per scheduled callback (using setTimeout).\n * This debouncing avoids wastefully computing separate diffs and IVM updates\n * for intermediate states. setTimeout is used instead of requestAnimationFrame\n * to ensure pokes are delivered even when the tab is in the background,\n * enabling notifications (sounds, favicon badges) to work correctly.\n */\nexport class PokeHandler {\n readonly #replicachePoke: (poke: PokeInternal) => Promise<void>;\n readonly #onPokeError: (error: unknown) => void;\n readonly #clientID: ClientID;\n readonly #lc: LogContext;\n #receivingPoke: Omit<PokeAccumulator, 'pokeEnd'> | undefined = undefined;\n readonly #pokeBuffer: PokeAccumulator[] = [];\n #pokePlaybackLoopRunning = false;\n #lastScheduledTimestamp = 0;\n // Serializes calls to this.#replicachePoke otherwise we can cause out of\n // order poke errors.\n readonly #pokeLock = new Lock();\n readonly #schema: Schema;\n readonly #serverToClient: NameMapper;\n readonly #mutationTracker: MutationTracker;\n\n constructor(\n replicachePoke: (poke: PokeInternal) => Promise<void>,\n onPokeError: (error: unknown) => void,\n clientID: ClientID,\n schema: Schema,\n lc: LogContext,\n mutationTracker: MutationTracker,\n ) {\n this.#replicachePoke = replicachePoke;\n this.#onPokeError = onPokeError;\n this.#clientID = clientID;\n this.#schema = schema;\n this.#serverToClient = serverToClient(schema.tables);\n this.#lc = lc.withContext('PokeHandler');\n this.#mutationTracker = mutationTracker;\n }\n\n handlePokeStart(pokeStart: PokeStartBody) {\n if (this.#receivingPoke) {\n this.#handlePokeError(\n `pokeStart ${JSON.stringify(\n pokeStart,\n )} while still receiving ${JSON.stringify(\n this.#receivingPoke.pokeStart,\n )} `,\n );\n return;\n }\n this.#receivingPoke = {\n pokeStart,\n parts: [],\n };\n }\n\n handlePokePart(pokePart: PokePartBody): number | undefined {\n if (pokePart.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokePart for ${pokePart.pokeID}, when receiving ${\n this.#receivingPoke?.pokeStart.pokeID\n }`,\n );\n return;\n }\n this.#receivingPoke.parts.push(pokePart);\n return pokePart.lastMutationIDChanges?.[this.#clientID];\n }\n\n handlePokeEnd(pokeEnd: PokeEndBody): void {\n if (pokeEnd.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokeEnd for ${pokeEnd.pokeID}, when receiving ${\n this.#receivingPoke?.pokeStart.pokeID\n }`,\n );\n return;\n }\n if (pokeEnd.cancel) {\n this.#receivingPoke = undefined;\n return;\n }\n this.#pokeBuffer.push({...this.#receivingPoke, pokeEnd});\n this.#receivingPoke = undefined;\n if (!this.#pokePlaybackLoopRunning) {\n this.#startPlaybackLoop();\n }\n }\n\n handleDisconnect(): void {\n this.#lc.debug?.('clearing due to disconnect');\n this.#clear();\n }\n\n #startPlaybackLoop() {\n this.#lc.debug?.('starting playback loop');\n this.#pokePlaybackLoopRunning = true;\n setTimeout(this.#scheduledCallback, 0);\n }\n\n #scheduledCallback = async () => {\n const lc = this.#lc.withContext(\n 'scheduledAt',\n Math.floor(performance.now()),\n );\n if (this.#pokeBuffer.length === 0) {\n lc.debug?.('stopping playback loop');\n this.#pokePlaybackLoopRunning = false;\n return;\n }\n setTimeout(this.#scheduledCallback, 0);\n const start = performance.now();\n lc.debug?.(\n 'scheduled callback fired, processing pokes. Since last callback',\n start - this.#lastScheduledTimestamp,\n );\n this.#lastScheduledTimestamp = start;\n await this.#processPokesForFrame(lc);\n lc.debug?.('processing pokes took', performance.now() - start);\n };\n\n #processPokesForFrame(lc: LogContext): Promise<void> {\n return this.#pokeLock.withLock(async () => {\n const now = Date.now();\n lc.debug?.('got poke lock at', now);\n lc.debug?.('merging', this.#pokeBuffer.length);\n try {\n const merged = mergePokes(\n this.#pokeBuffer,\n this.#schema,\n this.#serverToClient,\n );\n this.#pokeBuffer.length = 0;\n if (merged === undefined) {\n lc.debug?.('frame is empty');\n return;\n }\n const start = performance.now();\n lc.debug?.('poking replicache');\n await this.#replicachePoke(merged);\n lc.debug?.('poking replicache took', performance.now() - start);\n\n if (!('error' in merged.pullResponse)) {\n const lmid =\n merged.pullResponse.lastMutationIDChanges[this.#clientID];\n if (lmid !== undefined) {\n this.#mutationTracker.lmidAdvanced(lmid);\n }\n }\n } catch (e) {\n this.#handlePokeError(e);\n }\n });\n }\n\n #handlePokeError(e: unknown) {\n if (String(e).includes('unexpected base cookie for poke')) {\n // This can happen if cookie changes due to refresh from idb due\n // to an update arriving to different tabs in the same\n // client group at very different times. Unusual but possible.\n this.#lc.debug?.('clearing due to', e);\n } else {\n this.#lc.error?.('clearing due to unexpected poke error', e);\n }\n this.#clear();\n this.#onPokeError(e);\n }\n\n #clear() {\n this.#receivingPoke = undefined;\n this.#pokeBuffer.length = 0;\n }\n}\n\nexport function mergePokes(\n pokeBuffer: PokeAccumulator[],\n schema: Schema,\n serverToClient: NameMapper,\n):\n | (PokeInternal & {mutationResults?: MutationPatch[] | undefined})\n | undefined {\n if (pokeBuffer.length === 0) {\n return undefined;\n }\n const {baseCookie} = pokeBuffer[0].pokeStart;\n // oxlint-disable-next-line typescript/no-non-null-assertion\n const lastPoke = pokeBuffer.at(-1)!;\n const {cookie} = lastPoke.pokeEnd;\n const mergedPatch: PatchOperationInternal[] = [];\n const mergedLastMutationIDChanges: Record<string, number> = {};\n const mutationResults: MutationPatch[] = [];\n\n let prevPokeEnd = undefined;\n for (const pokeAccumulator of pokeBuffer) {\n if (\n prevPokeEnd &&\n pokeAccumulator.pokeStart.baseCookie &&\n pokeAccumulator.pokeStart.baseCookie > prevPokeEnd.cookie\n ) {\n throw Error(\n `unexpected cookie gap ${JSON.stringify(prevPokeEnd)} ${JSON.stringify(\n pokeAccumulator.pokeStart,\n )}`,\n );\n }\n prevPokeEnd = pokeAccumulator.pokeEnd;\n for (const pokePart of pokeAccumulator.parts) {\n if (pokePart.lastMutationIDChanges) {\n for (const [clientID, lastMutationID] of Object.entries(\n pokePart.lastMutationIDChanges,\n )) {\n mergedLastMutationIDChanges[clientID] = lastMutationID;\n }\n }\n if (pokePart.desiredQueriesPatches) {\n for (const [clientID, queriesPatch] of Object.entries(\n pokePart.desiredQueriesPatches,\n )) {\n for (const op of queriesPatch) {\n mergedPatch.push(\n queryPatchOpToReplicachePatchOp(op, hash =>\n toDesiredQueriesKey(clientID, hash),\n ),\n );\n }\n }\n }\n if (pokePart.gotQueriesPatch) {\n for (const op of pokePart.gotQueriesPatch) {\n mergedPatch.push(\n queryPatchOpToReplicachePatchOp(op, toGotQueriesKey),\n );\n }\n }\n if (pokePart.rowsPatch) {\n for (const p of pokePart.rowsPatch) {\n const patchOp = rowsPatchOpToReplicachePatchOp(\n p,\n schema,\n serverToClient,\n );\n if (patchOp) {\n mergedPatch.push(patchOp);\n }\n }\n }\n if (pokePart.mutationsPatch) {\n for (const op of pokePart.mutationsPatch) {\n mergedPatch.push(mutationPatchOpToReplicachePatchOp(op));\n }\n }\n }\n }\n const ret: PokeInternal & {mutationResults?: MutationPatch[] | undefined} = {\n baseCookie,\n pullResponse: {\n lastMutationIDChanges: mergedLastMutationIDChanges,\n patch: mergedPatch,\n cookie,\n },\n };\n\n // For backwards compatibility. Because we're strict on our validation,\n // zero-client must be able to parse pokes with this field before we introduce it.\n // So users can update their clients and then start using custom mutators that write responses to the db.\n if (mutationResults.length > 0) {\n ret.mutationResults = mutationResults;\n }\n return ret;\n}\n\nfunction queryPatchOpToReplicachePatchOp(\n op: QueriesPatchOp,\n toKey: (hash: string) => string,\n): PatchOperation {\n switch (op.op) {\n case 'clear':\n return op;\n case 'del':\n return {\n op: 'del',\n key: toKey(op.hash),\n };\n case 'put':\n return {\n op: 'put',\n key: toKey(op.hash),\n value: null,\n };\n default:\n unreachable(op);\n }\n}\n\nexport function mutationPatchOpToReplicachePatchOp(\n op: MutationPatch,\n): PatchOperationInternal {\n switch (op.op) {\n case 'put':\n return {\n op: 'put',\n key: toMutationResponseKey(op.mutation.id),\n value: op.mutation.result,\n };\n case 'del':\n return {\n op: 'del',\n key: toMutationResponseKey(op.id),\n };\n }\n}\n\nfunction rowsPatchOpToReplicachePatchOp(\n op: RowPatchOp,\n schema: Schema,\n serverToClient: NameMapper,\n): PatchOperationInternal | undefined {\n if (op.op === 'clear') {\n return op;\n }\n // Skip rows for tables not in the client schema. This can happen when\n // the server-side query AST references tables (e.g. issueNotifications)\n // that are not yet part of the client schema definition.\n const tableName = serverToClient.tableNameIfKnown(op.tableName);\n if (!tableName) {\n return undefined;\n }\n switch (op.op) {\n case 'del':\n return {\n op: 'del',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.id),\n ),\n };\n case 'put':\n return {\n op: 'put',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.value),\n ),\n value: serverToClient.row(op.tableName, op.value),\n };\n case 'update':\n return {\n op: 'update',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.id),\n ),\n merge: op.merge\n ? serverToClient.row(op.tableName, op.merge)\n : undefined,\n constrain: serverToClient.columns(op.tableName, op.constrain),\n };\n default:\n unreachable(op);\n }\n}\n"],"mappings":"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"}
@@ -70,6 +70,7 @@ export declare const DEFAULT_DISCONNECT_TIMEOUT_MS: number;
70
70
  * consider it timed out.
71
71
  */
72
72
  export declare const CONNECT_TIMEOUT_MS = 10000;
73
+ export declare const LOGGED_OUT_STORAGE_USER_ID = "__anonymous__";
73
74
  export interface ReplicacheInternalAPI {
74
75
  lastMutationID(): number;
75
76
  }
@@ -78,7 +79,7 @@ export type ZeroMutate<S extends Schema, MD extends CustomMutatorDefs | undefine
78
79
  export declare class Zero<const S extends BaseDefaultSchema = DefaultSchema, MD extends CustomMutatorDefs | undefined = undefined, C extends BaseDefaultContext = DefaultContext> {
79
80
  #private;
80
81
  readonly version: string;
81
- readonly userID: string;
82
+ readonly userID: string | undefined;
82
83
  readonly storageKey: string;
83
84
  /**
84
85
  * The timeout in milliseconds for ping operations. Controls both:
@@ -321,10 +322,10 @@ export declare class OnlineManager extends Subscribable<boolean> {
321
322
  setOnline(online: boolean): void;
322
323
  get online(): boolean;
323
324
  }
324
- export declare function createSocket(rep: ReplicacheImpl, queryManager: QueryManager, deleteClientsManager: DeleteClientsManager, socketOrigin: WSString, baseCookie: NullableVersion, clientID: string, clientGroupID: string, clientSchema: ClientSchema, userID: string, auth: string | undefined, lmid: number, wsid: string, debugPerf: boolean, lc: LogContext, userPushURL: string | undefined, userPushHeaders: Record<string, string> | undefined, userQueryURL: string | undefined, userQueryHeaders: Record<string, string> | undefined, additionalConnectParams: Record<string, string> | undefined, activeClientsManager: Pick<ActiveClientsManager, 'activeClients'>, maxHeaderLength?: number): Promise<[
325
+ export declare function createSocket(rep: ReplicacheImpl, queryManager: QueryManager, deleteClientsManager: DeleteClientsManager, socketOrigin: WSString, baseCookie: NullableVersion, clientID: string, clientGroupID: string, clientSchema: ClientSchema, userID: string | undefined, auth: string | undefined, lmid: number, wsid: string, debugPerf: boolean, lc: LogContext, userPushURL: string | undefined, userPushHeaders: Record<string, string> | undefined, userQueryURL: string | undefined, userQueryHeaders: Record<string, string> | undefined, additionalConnectParams: Record<string, string> | undefined, activeClientsManager: Pick<ActiveClientsManager, 'activeClients'>, maxHeaderLength?: number): Promise<[
325
326
  WebSocket,
326
327
  Map<string, UpQueriesPatchOp> | undefined,
327
328
  DeleteClientsBody | undefined
328
329
  ]>;
329
- export declare function createConnectionURL(socketOrigin: HTTPString | WSString, clientID: string, clientGroupID: string, userID: string, baseCookie: string | null, lmid: number, wsid: string, rep: Pick<ReplicacheImpl<{}>, 'profileID'>, debugPerf: boolean, additionalConnectParams: Record<string, string> | undefined, lc: LogContext<unknown[], unknown[], unknown[], unknown[]>): Promise<URL>;
330
+ export declare function createConnectionURL(socketOrigin: HTTPString | WSString, clientID: string, clientGroupID: string, userID: string | undefined, baseCookie: string | null, lmid: number, wsid: string, rep: Pick<ReplicacheImpl<{}>, 'profileID'>, debugPerf: boolean, additionalConnectParams: Record<string, string> | undefined, lc: LogContext<unknown[], unknown[], unknown[], unknown[]>): Promise<URL>;
330
331
  //# sourceMappingURL=zero.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"zero.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zero.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero.ts"],"names":[],"mappings":"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"}
@@ -208,10 +208,11 @@ var Zero = class Zero {
208
208
  */
209
209
  constructor(options) {
210
210
  const { userID, storageKey, onOnlineChange, onUpdateNeeded, onClientStateNotFound, hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS, pingTimeoutMs = DEFAULT_PING_TIMEOUT_MS, disconnectTimeoutMs = DEFAULT_DISCONNECT_TIMEOUT_MS, schema, batchViewUpdates = (applyViewUpdates) => applyViewUpdates(), maxRecentQueries = 0, slowMaterializeThreshold = 5e3 } = options;
211
- if (!userID) throw new ClientError({
211
+ if (userID === "") throw new ClientError({
212
212
  kind: Internal,
213
- message: "ZeroOptions.userID must not be empty."
213
+ message: "ZeroOptions.userID should not be empty. Omit it entirely for logged-out clients."
214
214
  });
215
+ this.#checkAuthValid(userID ?? void 0, options.auth);
215
216
  const server = getServer(options.cacheURL ?? options.server);
216
217
  this.#enableAnalytics = shouldEnableAnalytics(server, false);
217
218
  let { kvStore = "idb" } = options;
@@ -257,12 +258,13 @@ var Zero = class Zero {
257
258
  mutateUrl: options.mutateURL ?? "",
258
259
  queryUrl: options.queryURL ?? options.getQueriesURL ?? ""
259
260
  })).toString(36);
261
+ const storageScopedUserID = userID ?? "__anonymous__";
260
262
  const replicacheOptions = {
261
- schemaVersion: `49.${hash}`,
263
+ schemaVersion: `50.${hash}`,
262
264
  logLevel: logOptions.logLevel,
263
265
  logSinks: [logOptions.logSink],
264
266
  mutators: replicacheMutators,
265
- name: `zero-${userID}-${hashedKey}`,
267
+ name: `zero-${storageScopedUserID}-${hashedKey}`,
266
268
  pusher: (req, reqID) => this.#pusher(req, reqID),
267
269
  puller: (req, reqID) => this.#puller(req, reqID),
268
270
  pushDelay: 0,
@@ -290,8 +292,9 @@ var Zero = class Zero {
290
292
  });
291
293
  this.#rep = rep;
292
294
  this.#server = server;
293
- this.userID = userID;
295
+ this.userID = userID ?? void 0;
294
296
  this.#lc = lc.withContext("clientID", rep.clientID);
297
+ if (userID === "anon") this.#lc.warn?.("ZeroOptions.userID \"anon\" is deprecated for logged-out clients. Omit it entirely for logged-out clients.");
295
298
  this.#connection = new ConnectionImpl(this.#connectionManager, this.#lc, (auth) => this.#setAuth(auth));
296
299
  this.#mutationTracker.setClientIDAndWatch(rep.clientID, rep.experimentalWatch.bind(rep));
297
300
  this.#activeClientsManager = makeActiveClientsManager(rep.clientGroupID, this.clientID, this.#closeAbortController.signal, (clientID, clientGroupID) => this.#deleteClientsManager.onClientsDeleted([{
@@ -324,7 +327,14 @@ var Zero = class Zero {
324
327
  if (mutators && !isMutatorRegistry(mutators)) addCustomMutatorsProperties(mutators, mutatorProxy, callableMutate, rep.mutate);
325
328
  this.mutate = callableMutate;
326
329
  this.mutateBatch = mutateBatch;
327
- this.#queryManager = new QueryManager(this.#lc, this.#mutationTracker, rep.clientID, schema.tables, (msg) => this.#send(msg), rep.experimentalWatch.bind(rep), maxRecentQueries, options.queryChangeThrottleMs ?? DEFAULT_QUERY_CHANGE_THROTTLE_MS, slowMaterializeThreshold, (error) => {
330
+ this.#queryManager = new QueryManager(this.#lc, this.#mutationTracker, rep.clientID, schema.tables, (msg) => {
331
+ let body = msg[1];
332
+ if (this.#options.getTraceparent) body = {
333
+ ...msg[1],
334
+ traceparent: this.#options.getTraceparent?.()
335
+ };
336
+ this.#send([msg[0], body]);
337
+ }, rep.experimentalWatch.bind(rep), maxRecentQueries, options.queryChangeThrottleMs ?? DEFAULT_QUERY_CHANGE_THROTTLE_MS, slowMaterializeThreshold, (error) => {
328
338
  this.#disconnect(lc, error);
329
339
  });
330
340
  this.#clientToServer = clientToServer(schema.tables);
@@ -776,7 +786,10 @@ var Zero = class Zero {
776
786
  };
777
787
  if (queriesPatch.size > 0 && this.#initConnectionQueries !== void 0) {
778
788
  maybeSendDeletedClients();
779
- send(socket, ["changeDesiredQueries", { desiredQueriesPatch: [...queriesPatch.values()] }]);
789
+ send(socket, ["changeDesiredQueries", {
790
+ desiredQueriesPatch: [...queriesPatch.values()],
791
+ traceparent: this.#options.getTraceparent?.()
792
+ }]);
780
793
  } else if (this.#initConnectionQueries === void 0) {
781
794
  const clientSchema = this.#clientSchema;
782
795
  send(socket, ["initConnection", {
@@ -786,7 +799,8 @@ var Zero = class Zero {
786
799
  userPushURL: this.#options.mutateURL,
787
800
  userPushHeaders: this.#options.mutateHeaders,
788
801
  userQueryURL: this.#options.queryURL ?? this.#options.getQueriesURL,
789
- userQueryHeaders: this.#options.queryHeaders
802
+ userQueryHeaders: this.#options.queryHeaders,
803
+ traceparent: this.#options.getTraceparent?.()
790
804
  }]);
791
805
  this.#deletedClients = void 0;
792
806
  }
@@ -996,7 +1010,8 @@ var Zero = class Zero {
996
1010
  clientGroupID: req.clientGroupID,
997
1011
  mutations: [zeroM],
998
1012
  pushVersion: req.pushVersion,
999
- requestID
1013
+ requestID,
1014
+ traceparent: this.#options.getTraceparent?.()
1000
1015
  }]);
1001
1016
  if (!isMutationRecoveryPush) this.#lastMutationIDSent = {
1002
1017
  clientID: m.clientID,
@@ -1221,6 +1236,7 @@ var Zero = class Zero {
1221
1236
  * @param auth - The authentication token to set.
1222
1237
  */
1223
1238
  #setAuth(auth) {
1239
+ this.#checkAuthValid(this.userID, auth);
1224
1240
  this.#rep.auth = toReplicacheAuthToken(auth);
1225
1241
  if (auth) this.#send(["updateAuth", { auth }]);
1226
1242
  }
@@ -1322,6 +1338,12 @@ var Zero = class Zero {
1322
1338
  assert(isClientMetric(metric), `Invalid metric: ${metric}`);
1323
1339
  this.#queryManager.addMetric(metric, value, ...args);
1324
1340
  };
1341
+ #checkAuthValid(userID, auth) {
1342
+ if (userID === void 0 && auth) throw new ClientError({
1343
+ kind: Internal,
1344
+ message: "ZeroOptions.userID is required when auth is set."
1345
+ });
1346
+ }
1325
1347
  };
1326
1348
  var OnlineManager = class extends Subscribable {
1327
1349
  #online = false;
@@ -1363,11 +1385,11 @@ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigi
1363
1385
  ];
1364
1386
  }
1365
1387
  async function createConnectionURL(socketOrigin, clientID, clientGroupID, userID, baseCookie, lmid, wsid, rep, debugPerf, additionalConnectParams, lc) {
1366
- const url = new URL(appendPath(socketOrigin, `/sync/v49/connect`));
1388
+ const url = new URL(appendPath(socketOrigin, `/sync/v50/connect`));
1367
1389
  const { searchParams } = url;
1368
1390
  searchParams.set("clientID", clientID);
1369
1391
  searchParams.set("clientGroupID", clientGroupID);
1370
- searchParams.set("userID", userID);
1392
+ if (userID !== void 0) searchParams.set("userID", userID);
1371
1393
  searchParams.set("baseCookie", baseCookie === null ? "" : String(baseCookie));
1372
1394
  searchParams.set("ts", String(performance.now()));
1373
1395
  searchParams.set("lmid", String(lmid));