@rocicorp/zero 1.12.0-canary.3 → 1.12.0-canary.4

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 (785) hide show
  1. package/out/_virtual/{_@oxc-project_runtime@0.130.0/helpers → _@oxc-project_runtime@0.154.0/helpers/esm}/usingCtx.js +2 -2
  2. package/out/analyze-query/src/analyze-cli.js +4 -3
  3. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  4. package/out/analyze-query/src/bin-analyze.js +5 -3
  5. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  6. package/out/analyze-query/src/bin-transform.js +3 -2
  7. package/out/analyze-query/src/bin-transform.js.map +1 -1
  8. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  9. package/out/ast-to-zql/src/bin.js +3 -2
  10. package/out/ast-to-zql/src/bin.js.map +1 -1
  11. package/out/ast-to-zql/src/format.js.map +1 -1
  12. package/out/datadog/src/datadog-log-sink.js +5 -4
  13. package/out/datadog/src/datadog-log-sink.js.map +1 -1
  14. package/out/otel/src/log-options.js.map +1 -1
  15. package/out/replicache/src/btree/node.js +13 -11
  16. package/out/replicache/src/btree/node.js.map +1 -1
  17. package/out/replicache/src/btree/read.js +4 -2
  18. package/out/replicache/src/btree/read.js.map +1 -1
  19. package/out/replicache/src/btree/splice.js.map +1 -1
  20. package/out/replicache/src/btree/write.js +9 -5
  21. package/out/replicache/src/btree/write.js.map +1 -1
  22. package/out/replicache/src/config.js +1 -2
  23. package/out/replicache/src/connection-loop.js.map +1 -1
  24. package/out/replicache/src/dag/chunk.js +1 -1
  25. package/out/replicache/src/dag/gc.js.map +1 -1
  26. package/out/replicache/src/dag/lazy-store.js +8 -7
  27. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  28. package/out/replicache/src/dag/store-impl.js +1 -1
  29. package/out/replicache/src/dag/store-impl.js.map +1 -1
  30. package/out/replicache/src/dag/visitor.js.map +1 -1
  31. package/out/replicache/src/db/commit.js +5 -3
  32. package/out/replicache/src/db/commit.js.map +1 -1
  33. package/out/replicache/src/db/read.js +1 -1
  34. package/out/replicache/src/db/read.js.map +1 -1
  35. package/out/replicache/src/db/rebase.js.map +1 -1
  36. package/out/replicache/src/db/write.js +5 -2
  37. package/out/replicache/src/db/write.js.map +1 -1
  38. package/out/replicache/src/deleted-clients.js +3 -2
  39. package/out/replicache/src/deleted-clients.js.map +1 -1
  40. package/out/replicache/src/expo-sqlite.js +1 -2
  41. package/out/replicache/src/frozen-json.js +1 -1
  42. package/out/replicache/src/frozen-json.js.map +1 -1
  43. package/out/replicache/src/get-default-puller.js +1 -1
  44. package/out/replicache/src/hash.js +1 -1
  45. package/out/replicache/src/hash.js.map +1 -1
  46. package/out/replicache/src/impl.js +1 -2
  47. package/out/replicache/src/index-defs.js +5 -3
  48. package/out/replicache/src/index-defs.js.map +1 -1
  49. package/out/replicache/src/kv/expo-sqlite/store.js +1 -1
  50. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  51. package/out/replicache/src/kv/idb-store.js +1 -1
  52. package/out/replicache/src/kv/idb-store.js.map +1 -1
  53. package/out/replicache/src/kv/mem-fallback-store.js +1 -1
  54. package/out/replicache/src/kv/mem-fallback-store.js.map +1 -1
  55. package/out/replicache/src/kv/mem-store.js.map +1 -1
  56. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  57. package/out/replicache/src/kv/op-sqlite/types.js.map +1 -1
  58. package/out/replicache/src/kv/read-impl.js.map +1 -1
  59. package/out/replicache/src/kv/sqlite-store.js +1 -1
  60. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  61. package/out/replicache/src/kv/write-impl-base.js +4 -1
  62. package/out/replicache/src/kv/write-impl-base.js.map +1 -1
  63. package/out/replicache/src/kv/write-impl.js.map +1 -1
  64. package/out/replicache/src/log-options.js +2 -1
  65. package/out/replicache/src/log-options.js.map +1 -1
  66. package/out/replicache/src/make-idb-name.js +1 -1
  67. package/out/replicache/src/new-client-channel.js +9 -7
  68. package/out/replicache/src/new-client-channel.js.map +1 -1
  69. package/out/replicache/src/on-persist-channel.js +1 -1
  70. package/out/replicache/src/on-persist-channel.js.map +1 -1
  71. package/out/replicache/src/op-sqlite.js +1 -2
  72. package/out/replicache/src/pending-mutations.js +2 -1
  73. package/out/replicache/src/pending-mutations.js.map +1 -1
  74. package/out/replicache/src/persist/client-gc.js +2 -2
  75. package/out/replicache/src/persist/client-gc.js.map +1 -1
  76. package/out/replicache/src/persist/client-group-gc.js +2 -2
  77. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  78. package/out/replicache/src/persist/client-groups.js +1 -1
  79. package/out/replicache/src/persist/client-groups.js.map +1 -1
  80. package/out/replicache/src/persist/clients.js +1 -1
  81. package/out/replicache/src/persist/clients.js.map +1 -1
  82. package/out/replicache/src/persist/collect-idb-databases.js +5 -4
  83. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  84. package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
  85. package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
  86. package/out/replicache/src/persist/heartbeat.js +2 -2
  87. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  88. package/out/replicache/src/persist/idb-databases-store.js +1 -1
  89. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  90. package/out/replicache/src/persist/make-client-id.js +1 -1
  91. package/out/replicache/src/persist/make-client-id.js.map +1 -1
  92. package/out/replicache/src/persist/persist.js +3 -2
  93. package/out/replicache/src/persist/persist.js.map +1 -1
  94. package/out/replicache/src/persist/refresh.js +8 -5
  95. package/out/replicache/src/persist/refresh.js.map +1 -1
  96. package/out/replicache/src/process-scheduler.js.map +1 -1
  97. package/out/replicache/src/replicache-impl.js +3 -3
  98. package/out/replicache/src/replicache-impl.js.map +1 -1
  99. package/out/replicache/src/scan-iterator.js.map +1 -1
  100. package/out/replicache/src/scan-options.js +7 -6
  101. package/out/replicache/src/scan-options.js.map +1 -1
  102. package/out/replicache/src/sqlite.js +1 -2
  103. package/out/replicache/src/subscriptions.js +1 -1
  104. package/out/replicache/src/subscriptions.js.map +1 -1
  105. package/out/replicache/src/sync/diff.js +3 -1
  106. package/out/replicache/src/sync/diff.js.map +1 -1
  107. package/out/replicache/src/sync/ids.js.map +1 -1
  108. package/out/replicache/src/sync/patch.js +2 -4
  109. package/out/replicache/src/sync/patch.js.map +1 -1
  110. package/out/replicache/src/sync/pull.js +3 -1
  111. package/out/replicache/src/sync/pull.js.map +1 -1
  112. package/out/replicache/src/sync/push.js.map +1 -1
  113. package/out/replicache/src/sync/request-id.js +1 -1
  114. package/out/replicache/src/sync/request-id.js.map +1 -1
  115. package/out/replicache/src/transactions.js +1 -1
  116. package/out/replicache/src/transactions.js.map +1 -1
  117. package/out/shared/src/arrays.js +4 -1
  118. package/out/shared/src/arrays.js.map +1 -1
  119. package/out/shared/src/asserts.js +1 -1
  120. package/out/shared/src/bigint-json.d.ts +9 -0
  121. package/out/shared/src/bigint-json.d.ts.map +1 -1
  122. package/out/shared/src/bigint-json.js +27 -2
  123. package/out/shared/src/bigint-json.js.map +1 -1
  124. package/out/shared/src/broadcast-channel.js +1 -1
  125. package/out/shared/src/btree-set.js +11 -8
  126. package/out/shared/src/btree-set.js.map +1 -1
  127. package/out/shared/src/cache.js.map +1 -1
  128. package/out/shared/src/config.js +1 -1
  129. package/out/shared/src/custom-key-map.js.map +1 -1
  130. package/out/shared/src/custom-key-set.js.map +1 -1
  131. package/out/shared/src/deep-clone.js +1 -1
  132. package/out/shared/src/document-visible.js.map +1 -1
  133. package/out/shared/src/dotenv.js.map +1 -1
  134. package/out/shared/src/error.js +1 -1
  135. package/out/shared/src/error.js.map +1 -1
  136. package/out/shared/src/hash.js +2 -2
  137. package/out/shared/src/hash.js.map +1 -1
  138. package/out/shared/src/iterables.js.map +1 -1
  139. package/out/shared/src/json-schema.js.map +1 -1
  140. package/out/shared/src/json.js.map +1 -1
  141. package/out/shared/src/logging-test-utils.js +1 -1
  142. package/out/shared/src/logging.js +1 -1
  143. package/out/shared/src/logging.js.map +1 -1
  144. package/out/shared/src/navigator.js +1 -1
  145. package/out/shared/src/options.js +9 -12
  146. package/out/shared/src/options.js.map +1 -1
  147. package/out/shared/src/promise-race.js.map +1 -1
  148. package/out/shared/src/queue.js.map +1 -1
  149. package/out/shared/src/record-proxy.js.map +1 -1
  150. package/out/shared/src/ring-buffer.js.map +1 -1
  151. package/out/shared/src/size-of-value.js +7 -10
  152. package/out/shared/src/size-of-value.js.map +1 -1
  153. package/out/shared/src/sorted-entries.js.map +1 -1
  154. package/out/shared/src/tdigest-schema.js.map +1 -1
  155. package/out/shared/src/tdigest.js.map +1 -1
  156. package/out/shared/src/valita.js +1 -1
  157. package/out/shared/src/valita.js.map +1 -1
  158. package/out/z2s/src/compiler.js +2 -4
  159. package/out/z2s/src/compiler.js.map +1 -1
  160. package/out/z2s/src/sql.js +1 -1
  161. package/out/z2s/src/sql.js.map +1 -1
  162. package/out/zero/package.js +212 -189
  163. package/out/zero/package.js.map +1 -1
  164. package/out/zero/src/adapters/drizzle.js +1 -2
  165. package/out/zero/src/adapters/kysely.js +1 -2
  166. package/out/zero/src/adapters/pg.js +1 -2
  167. package/out/zero/src/adapters/postgresjs.js +1 -2
  168. package/out/zero/src/adapters/prisma.js +1 -2
  169. package/out/zero/src/analyze.js +1 -2
  170. package/out/zero/src/change-protocol/v0.js +1 -2
  171. package/out/zero/src/expo-sqlite.js +1 -2
  172. package/out/zero/src/op-sqlite.js +1 -2
  173. package/out/zero/src/react-native.js.map +1 -1
  174. package/out/zero/src/sqlite.js +1 -2
  175. package/out/zero/src/zero-cache-dev.js +10 -9
  176. package/out/zero/src/zero-cache-dev.js.map +1 -1
  177. package/out/zero/src/zero-out.js +2 -1
  178. package/out/zero/src/zero-out.js.map +1 -1
  179. package/out/zero-cache/src/auth/auth.js +1 -1
  180. package/out/zero-cache/src/auth/auth.js.map +1 -1
  181. package/out/zero-cache/src/auth/jwt.js +4 -1
  182. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  183. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  184. package/out/zero-cache/src/auth/read-authorizer.js +3 -2
  185. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  186. package/out/zero-cache/src/auth/write-authorizer.js +5 -16
  187. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  188. package/out/zero-cache/src/config/network.js +1 -1
  189. package/out/zero-cache/src/config/network.js.map +1 -1
  190. package/out/zero-cache/src/config/server-context.js.map +1 -1
  191. package/out/zero-cache/src/config/zero-config.d.ts +5 -0
  192. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  193. package/out/zero-cache/src/config/zero-config.js +13 -2
  194. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  195. package/out/zero-cache/src/custom/fetch.js +1 -1
  196. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  197. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  198. package/out/zero-cache/src/db/create.js.map +1 -1
  199. package/out/zero-cache/src/db/index-predicate.js.map +1 -1
  200. package/out/zero-cache/src/db/lite-tables.d.ts +2 -2
  201. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  202. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  203. package/out/zero-cache/src/db/migration-lite.js +1 -1
  204. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  205. package/out/zero-cache/src/db/migration.js +5 -3
  206. package/out/zero-cache/src/db/migration.js.map +1 -1
  207. package/out/zero-cache/src/db/pg-copy-binary.js +4 -3
  208. package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -1
  209. package/out/zero-cache/src/db/pg-copy.js +0 -1
  210. package/out/zero-cache/src/db/pg-copy.js.map +1 -1
  211. package/out/zero-cache/src/db/pg-to-lite.js +1 -1
  212. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  213. package/out/zero-cache/src/db/run-transaction.js.map +1 -1
  214. package/out/zero-cache/src/db/specs.js +7 -5
  215. package/out/zero-cache/src/db/specs.js.map +1 -1
  216. package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -1
  217. package/out/zero-cache/src/db/statements.d.ts.map +1 -1
  218. package/out/zero-cache/src/db/statements.js +9 -2
  219. package/out/zero-cache/src/db/statements.js.map +1 -1
  220. package/out/zero-cache/src/db/transaction-pool.js +5 -3
  221. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  222. package/out/zero-cache/src/db/warmup.js.map +1 -1
  223. package/out/zero-cache/src/observability/events.js.map +1 -1
  224. package/out/zero-cache/src/observability/log-throttle.js.map +1 -1
  225. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  226. package/out/zero-cache/src/scripts/deploy-permissions.js +4 -2
  227. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  228. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  229. package/out/zero-cache/src/server/anonymous-otel-start.js +2 -1
  230. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  231. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  232. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  233. package/out/zero-cache/src/server/logging.js +1 -1
  234. package/out/zero-cache/src/server/logging.js.map +1 -1
  235. package/out/zero-cache/src/server/main.js.map +1 -1
  236. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  237. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  238. package/out/zero-cache/src/server/reaper.js +2 -2
  239. package/out/zero-cache/src/server/reaper.js.map +1 -1
  240. package/out/zero-cache/src/server/replicator.js.map +1 -1
  241. package/out/zero-cache/src/server/runner/run-worker.js +2 -1
  242. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  243. package/out/zero-cache/src/server/runner/runtime.js +2 -1
  244. package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
  245. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  246. package/out/zero-cache/src/server/shadow-syncer.js +1 -1
  247. package/out/zero-cache/src/server/shadow-syncer.js.map +1 -1
  248. package/out/zero-cache/src/server/slot-keeper.js.map +1 -1
  249. package/out/zero-cache/src/server/syncer-assigner.js.map +1 -1
  250. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  251. package/out/zero-cache/src/server/syncer.js +6 -1
  252. package/out/zero-cache/src/server/syncer.js.map +1 -1
  253. package/out/zero-cache/src/server/worker-dispatcher.js +1 -1
  254. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  255. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  256. package/out/zero-cache/src/services/analyze.js +1 -1
  257. package/out/zero-cache/src/services/analyze.js.map +1 -1
  258. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -1
  259. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  260. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  261. package/out/zero-cache/src/services/change-source/common/init-cleanup.js.map +1 -1
  262. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
  263. package/out/zero-cache/src/services/change-source/common/replica-schema.js +3 -3
  264. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  265. package/out/zero-cache/src/services/change-source/custom/change-source.js +3 -3
  266. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  267. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
  268. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +3 -3
  269. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  270. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +1 -1
  271. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -1
  272. package/out/zero-cache/src/services/change-source/pg/change-source.js +4 -6
  273. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  274. package/out/zero-cache/src/services/change-source/pg/decommission.js +2 -1
  275. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  276. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +5 -3
  277. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  278. package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
  279. package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
  280. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +3 -2
  281. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  282. package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
  283. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +2 -2
  284. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -1
  285. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.js +1 -1
  286. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.js.map +1 -1
  287. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +3 -3
  288. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  289. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +1 -1
  290. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  291. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +13 -12
  292. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
  293. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  294. package/out/zero-cache/src/services/change-source/pg/schema/published.js +1 -1
  295. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  296. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -1
  297. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +9 -6
  298. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  299. package/out/zero-cache/src/services/change-source/pg/schema/validation.js +1 -1
  300. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  301. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js +1 -1
  302. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js.map +1 -1
  303. package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
  304. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  305. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
  306. package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
  307. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  308. package/out/zero-cache/src/services/change-source/protocol/current.js +1 -1
  309. package/out/zero-cache/src/services/change-source/protocol/mod.js +1 -2
  310. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js.map +1 -1
  311. package/out/zero-cache/src/services/change-streamer/backfill-state.js +1 -1
  312. package/out/zero-cache/src/services/change-streamer/backfill-state.js.map +1 -1
  313. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  314. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  315. package/out/zero-cache/src/services/change-streamer/broadcast.js +1 -1
  316. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  317. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +1 -1
  318. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
  319. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +2 -3
  320. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
  321. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +2 -2
  322. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -1
  323. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -1
  324. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +5 -3
  325. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  326. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +21 -21
  327. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  328. package/out/zero-cache/src/services/change-streamer/change-streamer.js +1 -1
  329. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  330. package/out/zero-cache/src/services/change-streamer/drain-tracker.js.map +1 -1
  331. package/out/zero-cache/src/services/change-streamer/forwarder.js +11 -10
  332. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  333. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js +1 -1
  334. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js.map +1 -1
  335. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js +3 -3
  336. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -1
  337. package/out/zero-cache/src/services/change-streamer/replica-poller.js +1 -1
  338. package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -1
  339. package/out/zero-cache/src/services/change-streamer/restore-admission.js +12 -1
  340. package/out/zero-cache/src/services/change-streamer/restore-admission.js.map +1 -1
  341. package/out/zero-cache/src/services/change-streamer/schema/init.js +1 -1
  342. package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
  343. package/out/zero-cache/src/services/change-streamer/schema/tables.js +1 -1
  344. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  345. package/out/zero-cache/src/services/change-streamer/snapshot-message.js +1 -1
  346. package/out/zero-cache/src/services/change-streamer/snapshot-message.js.map +1 -1
  347. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -1
  348. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +1 -1
  349. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -1
  350. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js +2 -2
  351. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js.map +1 -1
  352. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -1
  353. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js.map +1 -1
  354. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -1
  355. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +4 -6
  356. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -1
  357. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +1 -3
  358. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
  359. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  360. package/out/zero-cache/src/services/change-streamer/storer.js +2 -2
  361. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  362. package/out/zero-cache/src/services/change-streamer/subscribe.js +1 -1
  363. package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -1
  364. package/out/zero-cache/src/services/change-streamer/subscriber.js +2 -2
  365. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  366. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +0 -1
  367. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  368. package/out/zero-cache/src/services/heapz.js +2 -1
  369. package/out/zero-cache/src/services/heapz.js.map +1 -1
  370. package/out/zero-cache/src/services/http-service.js.map +1 -1
  371. package/out/zero-cache/src/services/life-cycle.js +1 -1
  372. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  373. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +4 -2
  374. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
  375. package/out/zero-cache/src/services/litestream/commands.js +1 -1
  376. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  377. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +2 -2
  378. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -1
  379. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -1
  380. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  381. package/out/zero-cache/src/services/litestream/restore-progress.js.map +1 -1
  382. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
  383. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  384. package/out/zero-cache/src/services/mutagen/pusher.js +3 -2
  385. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  386. package/out/zero-cache/src/services/plannerz.js +4 -3
  387. package/out/zero-cache/src/services/plannerz.js.map +1 -1
  388. package/out/zero-cache/src/services/profz.js +5 -3
  389. package/out/zero-cache/src/services/profz.js.map +1 -1
  390. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -1
  391. package/out/zero-cache/src/services/replicator/change-log-db.js +3 -2
  392. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
  393. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +1 -1
  394. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
  395. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  396. package/out/zero-cache/src/services/replicator/drain-handler.js.map +1 -1
  397. package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
  398. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  399. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  400. package/out/zero-cache/src/services/replicator/replication-status.js +4 -3
  401. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  402. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  403. package/out/zero-cache/src/services/replicator/reporter/recorder.js +1 -1
  404. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  405. package/out/zero-cache/src/services/replicator/reporter/report-schema.js +1 -1
  406. package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -1
  407. package/out/zero-cache/src/services/replicator/schema/backfilling.js +1 -1
  408. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -1
  409. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +19 -7
  410. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
  411. package/out/zero-cache/src/services/replicator/schema/change-log.js +31 -15
  412. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  413. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
  414. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  415. package/out/zero-cache/src/services/replicator/schema/replication-state.js +10 -7
  416. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  417. package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
  418. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +1 -1
  419. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  420. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +1 -1
  421. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -1
  422. package/out/zero-cache/src/services/replicator/write-worker-client.js +1 -1
  423. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  424. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  425. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  426. package/out/zero-cache/src/services/runner.js.map +1 -1
  427. package/out/zero-cache/src/services/running-state.js.map +1 -1
  428. package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js.map +1 -1
  429. package/out/zero-cache/src/services/statz.js +2 -1
  430. package/out/zero-cache/src/services/statz.js.map +1 -1
  431. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +2 -2
  432. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
  433. package/out/zero-cache/src/services/view-syncer/advancement-metrics.js.map +1 -1
  434. package/out/zero-cache/src/services/view-syncer/batch-pacer.js.map +1 -1
  435. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  436. package/out/zero-cache/src/services/view-syncer/client-handler.js +24 -3
  437. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  438. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts +15 -2
  439. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
  440. package/out/zero-cache/src/services/view-syncer/client-schema.js +46 -6
  441. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
  442. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  443. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +2 -2
  444. package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
  445. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  446. package/out/zero-cache/src/services/view-syncer/cvr-store.js +10 -5
  447. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  448. package/out/zero-cache/src/services/view-syncer/cvr.js +12 -4
  449. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  450. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js +1 -1
  451. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js.map +1 -1
  452. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  453. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -1
  454. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -1
  455. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +2 -2
  456. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -1
  457. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +5 -3
  458. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  459. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  460. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +8 -5
  461. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  462. package/out/zero-cache/src/services/view-syncer/plan-warnings.js.map +1 -1
  463. package/out/zero-cache/src/services/view-syncer/push-cost.js.map +1 -1
  464. package/out/zero-cache/src/services/view-syncer/push-cutoff.js.map +1 -1
  465. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
  466. package/out/zero-cache/src/services/view-syncer/query-shape.js.map +1 -1
  467. package/out/zero-cache/src/services/view-syncer/query-stats.js +1 -1
  468. package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -1
  469. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  470. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +1 -1
  471. package/out/zero-cache/src/services/view-syncer/schema/types.js +1 -1
  472. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  473. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +7 -1
  474. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +1 -1
  475. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +8 -1
  476. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  477. package/out/zero-cache/src/services/view-syncer/snapshotter.js +6 -5
  478. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  479. package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
  480. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  481. package/out/zero-cache/src/services/view-syncer/view-syncer.js +13 -9
  482. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  483. package/out/zero-cache/src/types/error-with-level.js.map +1 -1
  484. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  485. package/out/zero-cache/src/types/lite.js +1 -1
  486. package/out/zero-cache/src/types/lite.js.map +1 -1
  487. package/out/zero-cache/src/types/pg-data-type.js +1 -1
  488. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  489. package/out/zero-cache/src/types/pg.js +6 -4
  490. package/out/zero-cache/src/types/pg.js.map +1 -1
  491. package/out/zero-cache/src/types/poke-chunk.js +2 -2
  492. package/out/zero-cache/src/types/poke-chunk.js.map +1 -1
  493. package/out/zero-cache/src/types/processes.js +1 -1
  494. package/out/zero-cache/src/types/processes.js.map +1 -1
  495. package/out/zero-cache/src/types/profiler.js.map +1 -1
  496. package/out/zero-cache/src/types/row-key.js.map +1 -1
  497. package/out/zero-cache/src/types/sql.js.map +1 -1
  498. package/out/zero-cache/src/types/streams.js +10 -9
  499. package/out/zero-cache/src/types/streams.js.map +1 -1
  500. package/out/zero-cache/src/types/strings.js.map +1 -1
  501. package/out/zero-cache/src/types/subscription.js.map +1 -1
  502. package/out/zero-cache/src/types/timeout.js +1 -1
  503. package/out/zero-cache/src/types/websocket-handoff.js +1 -1
  504. package/out/zero-cache/src/types/ws.js +1 -1
  505. package/out/zero-cache/src/workers/connection.js +5 -6
  506. package/out/zero-cache/src/workers/connection.js.map +1 -1
  507. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  508. package/out/zero-cache/src/workers/replicator.js +5 -4
  509. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  510. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  511. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +9 -1
  512. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  513. package/out/zero-cache/src/workers/syncer.js +4 -4
  514. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  515. package/out/zero-client/src/client/active-clients-manager.js +1 -1
  516. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  517. package/out/zero-client/src/client/bindings.js +11 -11
  518. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  519. package/out/zero-client/src/client/connection.js +1 -1
  520. package/out/zero-client/src/client/connection.js.map +1 -1
  521. package/out/zero-client/src/client/context.js.map +1 -1
  522. package/out/zero-client/src/client/crud-impl.js +1 -1
  523. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  524. package/out/zero-client/src/client/crud.js +1 -1
  525. package/out/zero-client/src/client/crud.js.map +1 -1
  526. package/out/zero-client/src/client/custom.js +1 -1
  527. package/out/zero-client/src/client/custom.js.map +1 -1
  528. package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
  529. package/out/zero-client/src/client/enable-analytics.js +1 -1
  530. package/out/zero-client/src/client/enable-analytics.js.map +1 -1
  531. package/out/zero-client/src/client/error.js.map +1 -1
  532. package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
  533. package/out/zero-client/src/client/inspector/client.js.map +1 -1
  534. package/out/zero-client/src/client/inspector/html-dialog-prompt.js +1 -1
  535. package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
  536. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  537. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  538. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  539. package/out/zero-client/src/client/ivm-branch.js +1 -3
  540. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  541. package/out/zero-client/src/client/keys.js +2 -1
  542. package/out/zero-client/src/client/keys.js.map +1 -1
  543. package/out/zero-client/src/client/log-options.js.map +1 -1
  544. package/out/zero-client/src/client/make-replicache-mutators.js +5 -3
  545. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  546. package/out/zero-client/src/client/metrics.js +3 -5
  547. package/out/zero-client/src/client/metrics.js.map +1 -1
  548. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  549. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  550. package/out/zero-client/src/client/options.js.map +1 -1
  551. package/out/zero-client/src/client/query-manager.js +2 -2
  552. package/out/zero-client/src/client/query-manager.js.map +1 -1
  553. package/out/zero-client/src/client/reload-error-handler.js +4 -3
  554. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  555. package/out/zero-client/src/client/version.js +1 -1
  556. package/out/zero-client/src/client/zero-poke-handler.js +1 -1
  557. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  558. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  559. package/out/zero-client/src/client/zero.js +19 -11
  560. package/out/zero-client/src/client/zero.js.map +1 -1
  561. package/out/zero-client/src/mod.js +23 -23
  562. package/out/zero-client/src/util/nanoid.js.map +1 -1
  563. package/out/zero-permissions/src/permissions.js +3 -2
  564. package/out/zero-permissions/src/permissions.js.map +1 -1
  565. package/out/zero-pg/src/mod.js +9 -9
  566. package/out/zero-protocol/src/analyze-query-result.js +1 -1
  567. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  568. package/out/zero-protocol/src/application-error.js.map +1 -1
  569. package/out/zero-protocol/src/ast.js +19 -9
  570. package/out/zero-protocol/src/ast.js.map +1 -1
  571. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  572. package/out/zero-protocol/src/client-schema.js +1 -1
  573. package/out/zero-protocol/src/client-schema.js.map +1 -1
  574. package/out/zero-protocol/src/close-connection.js +1 -1
  575. package/out/zero-protocol/src/close-connection.js.map +1 -1
  576. package/out/zero-protocol/src/connect.js +1 -1
  577. package/out/zero-protocol/src/connect.js.map +1 -1
  578. package/out/zero-protocol/src/custom-queries.js +1 -1
  579. package/out/zero-protocol/src/custom-queries.js.map +1 -1
  580. package/out/zero-protocol/src/data.js +4 -2
  581. package/out/zero-protocol/src/data.js.map +1 -1
  582. package/out/zero-protocol/src/delete-clients.js.map +1 -1
  583. package/out/zero-protocol/src/down.d.ts +27 -27
  584. package/out/zero-protocol/src/down.js.map +1 -1
  585. package/out/zero-protocol/src/error.js.map +1 -1
  586. package/out/zero-protocol/src/inspect-down.d.ts +81 -81
  587. package/out/zero-protocol/src/inspect-down.js +1 -1
  588. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  589. package/out/zero-protocol/src/inspect-up.js +1 -1
  590. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  591. package/out/zero-protocol/src/mutate-server.js +1 -1
  592. package/out/zero-protocol/src/mutate-server.js.map +1 -1
  593. package/out/zero-protocol/src/mutation-id.js.map +1 -1
  594. package/out/zero-protocol/src/mutation.js +1 -1
  595. package/out/zero-protocol/src/mutation.js.map +1 -1
  596. package/out/zero-protocol/src/mutations-patch.js +1 -1
  597. package/out/zero-protocol/src/mutations-patch.js.map +1 -1
  598. package/out/zero-protocol/src/ping.js +1 -1
  599. package/out/zero-protocol/src/ping.js.map +1 -1
  600. package/out/zero-protocol/src/poke.d.ts +6 -6
  601. package/out/zero-protocol/src/poke.js +1 -1
  602. package/out/zero-protocol/src/poke.js.map +1 -1
  603. package/out/zero-protocol/src/pong.js +1 -1
  604. package/out/zero-protocol/src/pong.js.map +1 -1
  605. package/out/zero-protocol/src/primary-key.js.map +1 -1
  606. package/out/zero-protocol/src/protocol-version.js +1 -0
  607. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  608. package/out/zero-protocol/src/pull.js +1 -1
  609. package/out/zero-protocol/src/pull.js.map +1 -1
  610. package/out/zero-protocol/src/push.js +1 -1
  611. package/out/zero-protocol/src/push.js.map +1 -1
  612. package/out/zero-protocol/src/queries-patch.js +1 -1
  613. package/out/zero-protocol/src/queries-patch.js.map +1 -1
  614. package/out/zero-protocol/src/query-hash-visitor.js.map +1 -1
  615. package/out/zero-protocol/src/query-hash.js +2 -2
  616. package/out/zero-protocol/src/query-server.js +1 -1
  617. package/out/zero-protocol/src/query-server.js.map +1 -1
  618. package/out/zero-protocol/src/row-patch.js.map +1 -1
  619. package/out/zero-protocol/src/up.d.ts +60 -60
  620. package/out/zero-protocol/src/up.js.map +1 -1
  621. package/out/zero-protocol/src/update-auth.js.map +1 -1
  622. package/out/zero-protocol/src/version.js.map +1 -1
  623. package/out/zero-react/src/bindings.js +11 -11
  624. package/out/zero-react/src/mod.js +5 -5
  625. package/out/zero-react/src/use-query.js +1 -1
  626. package/out/zero-react/src/use-query.js.map +1 -1
  627. package/out/zero-react/src/zero-provider.d.ts +1 -1
  628. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  629. package/out/zero-react/src/zero-provider.js +2 -1
  630. package/out/zero-react/src/zero-provider.js.map +1 -1
  631. package/out/zero-react/src/zero.js +23 -23
  632. package/out/zero-schema/src/builder/schema-builder.js +3 -2
  633. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  634. package/out/zero-schema/src/builder/table-builder.js +1 -1
  635. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  636. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  637. package/out/zero-schema/src/name-mapper.js +7 -5
  638. package/out/zero-schema/src/name-mapper.js.map +1 -1
  639. package/out/zero-schema/src/schema-config.js +1 -1
  640. package/out/zero-schema/src/schema-config.js.map +1 -1
  641. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  642. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  643. package/out/zero-server/src/adapters/pg.js.map +1 -1
  644. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  645. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  646. package/out/zero-server/src/closable-db-transaction.js.map +1 -1
  647. package/out/zero-server/src/custom.js +1 -1
  648. package/out/zero-server/src/custom.js.map +1 -1
  649. package/out/zero-server/src/mod.js +8 -8
  650. package/out/zero-server/src/process-mutations.js.map +1 -1
  651. package/out/zero-server/src/push-processor.js.map +1 -1
  652. package/out/zero-server/src/queries/process-queries.js +2 -1
  653. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  654. package/out/zero-server/src/schema.js +7 -7
  655. package/out/zero-server/src/schema.js.map +1 -1
  656. package/out/zero-server/src/zql-database.js.map +1 -1
  657. package/out/zero-solid/src/bindings.js +11 -11
  658. package/out/zero-solid/src/mod.js +5 -5
  659. package/out/zero-solid/src/solid-view.js +1 -1
  660. package/out/zero-solid/src/solid-view.js.map +1 -1
  661. package/out/zero-solid/src/use-connection-state.js +2 -1
  662. package/out/zero-solid/src/use-connection-state.js.map +1 -1
  663. package/out/zero-solid/src/use-query.js.map +1 -1
  664. package/out/zero-solid/src/use-zero-online.js +2 -1
  665. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  666. package/out/zero-solid/src/use-zero.js +3 -2
  667. package/out/zero-solid/src/use-zero.js.map +1 -1
  668. package/out/zero-solid/src/zero.js +23 -23
  669. package/out/zero-types/src/name-mapper.js.map +1 -1
  670. package/out/zql/src/builder/builder.js +15 -13
  671. package/out/zql/src/builder/builder.js.map +1 -1
  672. package/out/zql/src/builder/correlated-predicate-pushdown.js.map +1 -1
  673. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  674. package/out/zql/src/builder/like.js +0 -1
  675. package/out/zql/src/builder/like.js.map +1 -1
  676. package/out/zql/src/ivm/array-view.js.map +1 -1
  677. package/out/zql/src/ivm/cap.js.map +1 -1
  678. package/out/zql/src/ivm/constraint.js +1 -1
  679. package/out/zql/src/ivm/constraint.js.map +1 -1
  680. package/out/zql/src/ivm/data.js.map +1 -1
  681. package/out/zql/src/ivm/deferred-input.js.map +1 -1
  682. package/out/zql/src/ivm/exists.js +20 -18
  683. package/out/zql/src/ivm/exists.js.map +1 -1
  684. package/out/zql/src/ivm/fan-in.js.map +1 -1
  685. package/out/zql/src/ivm/fan-out.js.map +1 -1
  686. package/out/zql/src/ivm/filter-operators.js +1 -1
  687. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  688. package/out/zql/src/ivm/filter-push.js.map +1 -1
  689. package/out/zql/src/ivm/filter.js.map +1 -1
  690. package/out/zql/src/ivm/flipped-join.js +1 -3
  691. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  692. package/out/zql/src/ivm/join-index-tap.js.map +1 -1
  693. package/out/zql/src/ivm/join-index.js.map +1 -1
  694. package/out/zql/src/ivm/join-utils.js +11 -13
  695. package/out/zql/src/ivm/join-utils.js.map +1 -1
  696. package/out/zql/src/ivm/join.js.map +1 -1
  697. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  698. package/out/zql/src/ivm/memory-source.js +26 -22
  699. package/out/zql/src/ivm/memory-source.js.map +1 -1
  700. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  701. package/out/zql/src/ivm/operator.js +2 -2
  702. package/out/zql/src/ivm/push-accumulated.js +0 -1
  703. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  704. package/out/zql/src/ivm/skip-yields.js.map +1 -1
  705. package/out/zql/src/ivm/skip.js.map +1 -1
  706. package/out/zql/src/ivm/take-gate.js.map +1 -1
  707. package/out/zql/src/ivm/take.js +1 -1
  708. package/out/zql/src/ivm/take.js.map +1 -1
  709. package/out/zql/src/ivm/union-fan-in.js +1 -1
  710. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  711. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  712. package/out/zql/src/ivm/view-apply-change.js +1 -1
  713. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  714. package/out/zql/src/mutate/crud.js +3 -2
  715. package/out/zql/src/mutate/crud.js.map +1 -1
  716. package/out/zql/src/planner/planner-builder.js +1 -1
  717. package/out/zql/src/planner/planner-builder.js.map +1 -1
  718. package/out/zql/src/planner/planner-connection.js.map +1 -1
  719. package/out/zql/src/planner/planner-debug.js.map +1 -1
  720. package/out/zql/src/planner/planner-fan-in.js.map +1 -1
  721. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  722. package/out/zql/src/planner/planner-filter.js.map +1 -1
  723. package/out/zql/src/planner/planner-graph.js +1 -5
  724. package/out/zql/src/planner/planner-graph.js.map +1 -1
  725. package/out/zql/src/planner/planner-join.js +1 -1
  726. package/out/zql/src/planner/planner-join.js.map +1 -1
  727. package/out/zql/src/planner/planner-source.js.map +1 -1
  728. package/out/zql/src/planner/planner-terminus.js.map +1 -1
  729. package/out/zql/src/query/create-builder.js +2 -1
  730. package/out/zql/src/query/create-builder.js.map +1 -1
  731. package/out/zql/src/query/expression.js +1 -1
  732. package/out/zql/src/query/expression.js.map +1 -1
  733. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  734. package/out/zql/src/query/named.js +2 -1
  735. package/out/zql/src/query/named.js.map +1 -1
  736. package/out/zql/src/query/query-delegate-base.js +1 -1
  737. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  738. package/out/zql/src/query/query-impl.js +3 -2
  739. package/out/zql/src/query/query-impl.js.map +1 -1
  740. package/out/zql/src/query/query-registry.js +1 -1
  741. package/out/zql/src/query/query-registry.js.map +1 -1
  742. package/out/zql/src/query/query-transitions.js +1 -1
  743. package/out/zql/src/query/query-transitions.js.map +1 -1
  744. package/out/zql/src/query/runnable-query-impl.js +3 -2
  745. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  746. package/out/zql/src/query/static-query.js.map +1 -1
  747. package/out/zql/src/query/ttl.js +8 -8
  748. package/out/zql/src/query/ttl.js.map +1 -1
  749. package/out/zql/src/query/validate-input.js.map +1 -1
  750. package/out/zqlite/src/database-storage.d.ts +27 -8
  751. package/out/zqlite/src/database-storage.d.ts.map +1 -1
  752. package/out/zqlite/src/database-storage.js +190 -53
  753. package/out/zqlite/src/database-storage.js.map +1 -1
  754. package/out/zqlite/src/db.d.ts +47 -1
  755. package/out/zqlite/src/db.d.ts.map +1 -1
  756. package/out/zqlite/src/db.js +121 -21
  757. package/out/zqlite/src/db.js.map +1 -1
  758. package/out/zqlite/src/explain-queries.js.map +1 -1
  759. package/out/zqlite/src/fetch-sql.js.map +1 -1
  760. package/out/zqlite/src/index-usage.js.map +1 -1
  761. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  762. package/out/zqlite/src/internal/sql.js.map +1 -1
  763. package/out/zqlite/src/internal/statement-cache.d.ts +7 -0
  764. package/out/zqlite/src/internal/statement-cache.d.ts.map +1 -1
  765. package/out/zqlite/src/internal/statement-cache.js +11 -4
  766. package/out/zqlite/src/internal/statement-cache.js.map +1 -1
  767. package/out/zqlite/src/mod.js +5 -5
  768. package/out/zqlite/src/pending-delta.js.map +1 -1
  769. package/out/zqlite/src/query-builder.js +1 -1
  770. package/out/zqlite/src/query-builder.js.map +1 -1
  771. package/out/zqlite/src/query-delegate.js.map +1 -1
  772. package/out/zqlite/src/resolve-scalar-subqueries.js +2 -5
  773. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  774. package/out/zqlite/src/sqlite-cost-model.js +3 -2
  775. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  776. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  777. package/out/zqlite/src/table-source.d.ts +11 -0
  778. package/out/zqlite/src/table-source.d.ts.map +1 -1
  779. package/out/zqlite/src/table-source.js +62 -25
  780. package/out/zqlite/src/table-source.js.map +1 -1
  781. package/package.json +17 -15
  782. package/out/otel/src/maybe-time.d.ts +0 -3
  783. package/out/otel/src/maybe-time.d.ts.map +0 -1
  784. package/out/otel/src/maybe-time.js +0 -15
  785. package/out/otel/src/maybe-time.js.map +0 -1
@@ -115,6 +115,6 @@ function isAuthErrorBody(ex) {
115
115
  return (ex.kind === "PushFailed" || ex.kind === "TransformFailed") && "reason" in ex && ex.reason === "http" && "status" in ex && (ex.status === 401 || ex.status === 403);
116
116
  }
117
117
  //#endregion
118
- export { authEquals, isAuthErrorBody, resolveAuth };
118
+ export { authEquals, isAuthErrorBody, pickToken, resolveAuth };
119
119
 
120
120
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","names":[],"sources":["../../../../../zero-cache/src/auth/auth.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {JWTPayload} from 'jose';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {\n isProtocolError,\n ProtocolError,\n type ErrorBody,\n} from '../../../zero-protocol/src/error.ts';\nimport type {PushError} from '../../../zero-protocol/src/push.ts';\n\n/** @deprecated JWT auth is deprecated */\nexport type JWTAuth = {\n readonly type: 'jwt';\n readonly raw: string;\n readonly decoded: JWTPayload;\n};\n\nexport type OpaqueAuth = {\n readonly type: 'opaque';\n readonly raw: string;\n};\n\nexport type Auth = OpaqueAuth | JWTAuth;\n\nexport type ValidateLegacyJWT = (\n token: string,\n ctx: {readonly userID: string | undefined},\n) => Promise<JWTAuth>;\n\nfunction isProvidedAuth(wireAuth: string | undefined): wireAuth is string {\n return wireAuth !== undefined && wireAuth !== '';\n}\n\nexport function authEquals(a: Auth | undefined, b: Auth | undefined) {\n if (a === b) {\n return true;\n }\n if (!a || !b) {\n return false;\n }\n return a.type === b.type && a.raw === b.raw;\n}\n\n/**\n * Resolves one auth snapshot transition without binding it to a client group.\n */\nexport async function resolveAuth(\n lc: LogContext,\n previousAuth: Auth | undefined,\n userID: string | null,\n wireAuth: string | undefined,\n validateLegacyJWT: ValidateLegacyJWT | undefined,\n): Promise<Auth | undefined> {\n try {\n const hasProvidedAuth = isProvidedAuth(wireAuth);\n\n if (previousAuth) {\n lc.debug?.(`Attempting to update auth from previous value`);\n } else {\n lc.debug?.(`Attempting to initialize auth`);\n }\n\n if (!hasProvidedAuth && previousAuth) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'No token provided. An unauthenticated client cannot connect to an authenticated client group.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (!hasProvidedAuth) {\n lc.debug?.(`Cleared auth`);\n return undefined;\n }\n\n if (userID === null) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message: 'Authenticated connections require a userID.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (validateLegacyJWT !== undefined) {\n const verifiedToken = await validateLegacyJWT(wireAuth, {userID});\n const nextAuth = pickToken(lc, previousAuth, verifiedToken);\n lc.debug?.(`Updated auth with JWT`);\n return nextAuth;\n }\n\n if (previousAuth?.type === 'jwt') {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'Token type cannot change from JWT to opaque. Connections are pinned to a single token type.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (previousAuth?.type === 'opaque' && previousAuth.raw === wireAuth) {\n lc.debug?.(`Opaque auth unchanged, reusing previous snapshot`);\n return previousAuth;\n }\n\n lc.debug?.(`Updated auth with opaque token`);\n return {\n type: 'opaque',\n raw: wireAuth,\n };\n } catch (e) {\n if (isProtocolError(e)) {\n throw e;\n }\n throw new ProtocolError({\n kind: ErrorKind.AuthInvalidated,\n message: `Failed to decode auth token: ${String(e)}`,\n origin: ErrorOrigin.ZeroCache,\n });\n }\n}\n\n/** @deprecated used only in old JWT validation/rotation auth */\nexport function pickToken(\n lc: LogContext,\n previousToken: Auth | undefined,\n newToken: Auth | undefined | null,\n) {\n if (newToken === null) {\n return undefined;\n }\n\n if (\n previousToken?.type &&\n newToken?.type &&\n previousToken?.type !== newToken?.type\n ) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'Token type cannot change. Client groups are pinned to a single token type.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (previousToken === undefined) {\n lc.debug?.(`No previous token, using new token`);\n return newToken;\n }\n\n if (newToken?.type === 'opaque') {\n return newToken;\n }\n\n if (previousToken.type === 'opaque') {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'Token type cannot change from opaque to JWT. Client groups are pinned to a single token type.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (newToken) {\n if (previousToken.decoded.sub !== newToken.decoded.sub) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'The user id in the new token does not match the previous token. Client groups are pinned to a single user.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (previousToken.decoded.iat === undefined) {\n lc.debug?.(`No issued at time for the existing token, using new token`);\n // No issued at time for the existing token? We take the most recently received token.\n return newToken;\n }\n\n if (newToken.decoded.iat === undefined) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'The new token does not have an issued at time but the prior token does. Tokens for a client group must either all have issued at times or all not have issued at times',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n // The new token is newer, so we take it.\n if (previousToken.decoded.iat < newToken.decoded.iat) {\n lc.debug?.(`New token is newer, using it`);\n return newToken;\n }\n\n // if the new token is older or the same, we keep the existing token.\n lc.debug?.(`New token is older or the same, using existing token`);\n return previousToken;\n }\n\n // previousToken !== undefined but newToken is undefined\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'No token provided. An unauthenticated client cannot connect to an authenticated client group.',\n origin: ErrorOrigin.ZeroCache,\n });\n}\n\nexport function isAuthErrorBody(ex: unknown): ex is ErrorBody | PushError {\n if (typeof ex !== 'object' || ex === null) {\n return false;\n }\n\n if ('error' in ex) {\n return (\n ex.error === 'http' &&\n 'status' in ex &&\n (ex.status === 401 || ex.status === 403)\n );\n }\n\n if (!('kind' in ex)) {\n return false;\n }\n\n if (\n ex.kind === ErrorKind.AuthInvalidated ||\n ex.kind === ErrorKind.Unauthorized\n ) {\n return true;\n }\n\n return (\n (ex.kind === ErrorKind.PushFailed ||\n ex.kind === ErrorKind.TransformFailed) &&\n 'reason' in ex &&\n ex.reason === ErrorReason.HTTP &&\n 'status' in ex &&\n (ex.status === 401 || ex.status === 403)\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","names":["ErrorKind.Unauthorized","ErrorOrigin.ZeroCache","ErrorKind.AuthInvalidated"],"sources":["../../../../../zero-cache/src/auth/auth.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {JWTPayload} from 'jose';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {\n isProtocolError,\n ProtocolError,\n type ErrorBody,\n} from '../../../zero-protocol/src/error.ts';\nimport type {PushError} from '../../../zero-protocol/src/push.ts';\n\n/** @deprecated JWT auth is deprecated */\nexport type JWTAuth = {\n readonly type: 'jwt';\n readonly raw: string;\n readonly decoded: JWTPayload;\n};\n\nexport type OpaqueAuth = {\n readonly type: 'opaque';\n readonly raw: string;\n};\n\nexport type Auth = OpaqueAuth | JWTAuth;\n\nexport type ValidateLegacyJWT = (\n token: string,\n ctx: {readonly userID: string | undefined},\n) => Promise<JWTAuth>;\n\nfunction isProvidedAuth(wireAuth: string | undefined): wireAuth is string {\n return wireAuth !== undefined && wireAuth !== '';\n}\n\nexport function authEquals(a: Auth | undefined, b: Auth | undefined) {\n if (a === b) {\n return true;\n }\n if (!a || !b) {\n return false;\n }\n return a.type === b.type && a.raw === b.raw;\n}\n\n/**\n * Resolves one auth snapshot transition without binding it to a client group.\n */\nexport async function resolveAuth(\n lc: LogContext,\n previousAuth: Auth | undefined,\n userID: string | null,\n wireAuth: string | undefined,\n validateLegacyJWT: ValidateLegacyJWT | undefined,\n): Promise<Auth | undefined> {\n try {\n const hasProvidedAuth = isProvidedAuth(wireAuth);\n\n if (previousAuth) {\n lc.debug?.(`Attempting to update auth from previous value`);\n } else {\n lc.debug?.(`Attempting to initialize auth`);\n }\n\n if (!hasProvidedAuth && previousAuth) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'No token provided. An unauthenticated client cannot connect to an authenticated client group.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (!hasProvidedAuth) {\n lc.debug?.(`Cleared auth`);\n return undefined;\n }\n\n if (userID === null) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message: 'Authenticated connections require a userID.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (validateLegacyJWT !== undefined) {\n const verifiedToken = await validateLegacyJWT(wireAuth, {userID});\n const nextAuth = pickToken(lc, previousAuth, verifiedToken);\n lc.debug?.(`Updated auth with JWT`);\n return nextAuth;\n }\n\n if (previousAuth?.type === 'jwt') {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'Token type cannot change from JWT to opaque. Connections are pinned to a single token type.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (previousAuth?.type === 'opaque' && previousAuth.raw === wireAuth) {\n lc.debug?.(`Opaque auth unchanged, reusing previous snapshot`);\n return previousAuth;\n }\n\n lc.debug?.(`Updated auth with opaque token`);\n return {\n type: 'opaque',\n raw: wireAuth,\n };\n } catch (e) {\n if (isProtocolError(e)) {\n throw e;\n }\n throw new ProtocolError({\n kind: ErrorKind.AuthInvalidated,\n message: `Failed to decode auth token: ${String(e)}`,\n origin: ErrorOrigin.ZeroCache,\n });\n }\n}\n\n/** @deprecated used only in old JWT validation/rotation auth */\nexport function pickToken(\n lc: LogContext,\n previousToken: Auth | undefined,\n newToken: Auth | undefined | null,\n) {\n if (newToken === null) {\n return undefined;\n }\n\n if (\n previousToken?.type &&\n newToken?.type &&\n previousToken?.type !== newToken?.type\n ) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'Token type cannot change. Client groups are pinned to a single token type.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (previousToken === undefined) {\n lc.debug?.(`No previous token, using new token`);\n return newToken;\n }\n\n if (newToken?.type === 'opaque') {\n return newToken;\n }\n\n if (previousToken.type === 'opaque') {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'Token type cannot change from opaque to JWT. Client groups are pinned to a single token type.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (newToken) {\n if (previousToken.decoded.sub !== newToken.decoded.sub) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'The user id in the new token does not match the previous token. Client groups are pinned to a single user.',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n if (previousToken.decoded.iat === undefined) {\n lc.debug?.(`No issued at time for the existing token, using new token`);\n // No issued at time for the existing token? We take the most recently received token.\n return newToken;\n }\n\n if (newToken.decoded.iat === undefined) {\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'The new token does not have an issued at time but the prior token does. Tokens for a client group must either all have issued at times or all not have issued at times',\n origin: ErrorOrigin.ZeroCache,\n });\n }\n\n // The new token is newer, so we take it.\n if (previousToken.decoded.iat < newToken.decoded.iat) {\n lc.debug?.(`New token is newer, using it`);\n return newToken;\n }\n\n // if the new token is older or the same, we keep the existing token.\n lc.debug?.(`New token is older or the same, using existing token`);\n return previousToken;\n }\n\n // previousToken !== undefined but newToken is undefined\n throw new ProtocolError({\n kind: ErrorKind.Unauthorized,\n message:\n 'No token provided. An unauthenticated client cannot connect to an authenticated client group.',\n origin: ErrorOrigin.ZeroCache,\n });\n}\n\nexport function isAuthErrorBody(ex: unknown): ex is ErrorBody | PushError {\n if (typeof ex !== 'object' || ex === null) {\n return false;\n }\n\n if ('error' in ex) {\n return (\n ex.error === 'http' &&\n 'status' in ex &&\n (ex.status === 401 || ex.status === 403)\n );\n }\n\n if (!('kind' in ex)) {\n return false;\n }\n\n if (\n ex.kind === ErrorKind.AuthInvalidated ||\n ex.kind === ErrorKind.Unauthorized\n ) {\n return true;\n }\n\n return (\n (ex.kind === ErrorKind.PushFailed ||\n ex.kind === ErrorKind.TransformFailed) &&\n 'reason' in ex &&\n ex.reason === ErrorReason.HTTP &&\n 'status' in ex &&\n (ex.status === 401 || ex.status === 403)\n );\n}\n"],"mappings":"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"}
@@ -17,7 +17,10 @@ var tokenConfigOptions = (config) => {
17
17
  async function verifyToken(config, token, verifyOptions) {
18
18
  if (config.jwk !== void 0) return verifyTokenImpl(token, loadJwk(config.jwk), verifyOptions);
19
19
  if (config.secret !== void 0) return verifyTokenImpl(token, loadSecret(config.secret), verifyOptions);
20
- if (config.jwksUrl !== void 0) return (await jwtVerify(token, getRemoteKeyset(config.jwksUrl), verifyOptions)).payload;
20
+ if (config.jwksUrl !== void 0) {
21
+ const remoteKeyset = getRemoteKeyset(config.jwksUrl);
22
+ return (await jwtVerify(token, remoteKeyset, verifyOptions)).payload;
23
+ }
21
24
  throw new Error("verifyToken was called but no auth options (one of: jwk, secret, jwksUrl) were configured.");
22
25
  }
23
26
  function loadJwk(jwkString) {
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.js","names":[],"sources":["../../../../../zero-cache/src/auth/jwt.ts"],"sourcesContent":["import {\n createRemoteJWKSet,\n exportJWK,\n generateKeyPair,\n jwtVerify,\n type JWK,\n type JWTClaimVerificationOptions,\n type JWTPayload,\n type KeyLike,\n} from 'jose';\nimport type {LegacyJWTAuthConfig} from '../config/zero-config.ts';\n\n/** @deprecated */\nexport async function createJwkPair() {\n const {publicKey, privateKey} = await generateKeyPair('PS256');\n\n const privateJwk = await exportJWK(privateKey);\n const publicJwk = await exportJWK(publicKey);\n\n privateJwk.kid = 'key-2024-001';\n privateJwk.use = 'sig';\n privateJwk.alg = 'PS256';\n\n publicJwk.kid = privateJwk.kid;\n publicJwk.use = privateJwk.use;\n publicJwk.alg = privateJwk.alg;\n\n return {privateJwk, publicJwk};\n}\n\nlet remoteKeyset: ReturnType<typeof createRemoteJWKSet> | undefined;\nfunction getRemoteKeyset(jwksUrl: string) {\n if (remoteKeyset === undefined) {\n remoteKeyset = createRemoteJWKSet(new URL(jwksUrl));\n }\n\n return remoteKeyset;\n}\n\n/** @deprecated */\nexport const tokenConfigOptions = (config: LegacyJWTAuthConfig) => {\n const tokenOptions = (['jwk', 'secret', 'jwksUrl'] as const).filter(\n key => config[key] !== undefined,\n );\n\n return tokenOptions;\n};\n\n/** @deprecated */\nexport async function verifyToken(\n config: LegacyJWTAuthConfig,\n token: string,\n verifyOptions: JWTClaimVerificationOptions,\n): Promise<JWTPayload> {\n if (config.jwk !== undefined) {\n return verifyTokenImpl(token, loadJwk(config.jwk), verifyOptions);\n }\n\n if (config.secret !== undefined) {\n return verifyTokenImpl(token, loadSecret(config.secret), verifyOptions);\n }\n\n if (config.jwksUrl !== undefined) {\n const remoteKeyset = getRemoteKeyset(config.jwksUrl);\n return (await jwtVerify(token, remoteKeyset, verifyOptions)).payload;\n }\n\n throw new Error(\n 'verifyToken was called but no auth options (one of: jwk, secret, jwksUrl) were configured.',\n );\n}\n\nfunction loadJwk(jwkString: string) {\n return JSON.parse(jwkString) as JWK;\n}\n\nfunction loadSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nasync function verifyTokenImpl(\n token: string,\n verifyKey: Uint8Array | KeyLike | JWK,\n verifyOptions: JWTClaimVerificationOptions,\n): Promise<JWTPayload> {\n const {payload} = await jwtVerify(token, verifyKey, verifyOptions);\n\n return payload;\n}\n"],"mappings":";;AA8BA,IAAI;AACJ,SAAS,gBAAgB,SAAiB;CACxC,IAAI,iBAAiB,KAAA,GACnB,eAAe,mBAAmB,IAAI,IAAI,OAAO,CAAC;CAGpD,OAAO;AACT;;AAGA,IAAa,sBAAsB,WAAgC;CAKjE,OAJsB;EAAC;EAAO;EAAU;CAAS,EAAY,QAC3D,QAAO,OAAO,SAAS,KAAA,CAGlB;AACT;;AAGA,eAAsB,YACpB,QACA,OACA,eACqB;CACrB,IAAI,OAAO,QAAQ,KAAA,GACjB,OAAO,gBAAgB,OAAO,QAAQ,OAAO,GAAG,GAAG,aAAa;CAGlE,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,gBAAgB,OAAO,WAAW,OAAO,MAAM,GAAG,aAAa;CAGxE,IAAI,OAAO,YAAY,KAAA,GAErB,QAAQ,MAAM,UAAU,OADH,gBAAgB,OAAO,OACb,GAAc,aAAa,GAAG;CAG/D,MAAM,IAAI,MACR,4FACF;AACF;AAEA,SAAS,QAAQ,WAAmB;CAClC,OAAO,KAAK,MAAM,SAAS;AAC7B;AAEA,SAAS,WAAW,QAAgB;CAClC,OAAO,IAAI,YAAY,EAAE,OAAO,MAAM;AACxC;AAEA,eAAe,gBACb,OACA,WACA,eACqB;CACrB,MAAM,EAAC,YAAW,MAAM,UAAU,OAAO,WAAW,aAAa;CAEjE,OAAO;AACT"}
1
+ {"version":3,"file":"jwt.js","names":[],"sources":["../../../../../zero-cache/src/auth/jwt.ts"],"sourcesContent":["import {\n createRemoteJWKSet,\n exportJWK,\n generateKeyPair,\n jwtVerify,\n type JWK,\n type JWTClaimVerificationOptions,\n type JWTPayload,\n type KeyLike,\n} from 'jose';\nimport type {LegacyJWTAuthConfig} from '../config/zero-config.ts';\n\n/** @deprecated */\nexport async function createJwkPair() {\n const {publicKey, privateKey} = await generateKeyPair('PS256');\n\n const privateJwk = await exportJWK(privateKey);\n const publicJwk = await exportJWK(publicKey);\n\n privateJwk.kid = 'key-2024-001';\n privateJwk.use = 'sig';\n privateJwk.alg = 'PS256';\n\n publicJwk.kid = privateJwk.kid;\n publicJwk.use = privateJwk.use;\n publicJwk.alg = privateJwk.alg;\n\n return {privateJwk, publicJwk};\n}\n\nlet remoteKeyset: ReturnType<typeof createRemoteJWKSet> | undefined;\nfunction getRemoteKeyset(jwksUrl: string) {\n if (remoteKeyset === undefined) {\n remoteKeyset = createRemoteJWKSet(new URL(jwksUrl));\n }\n\n return remoteKeyset;\n}\n\n/** @deprecated */\nexport const tokenConfigOptions = (config: LegacyJWTAuthConfig) => {\n const tokenOptions = (['jwk', 'secret', 'jwksUrl'] as const).filter(\n key => config[key] !== undefined,\n );\n\n return tokenOptions;\n};\n\n/** @deprecated */\nexport async function verifyToken(\n config: LegacyJWTAuthConfig,\n token: string,\n verifyOptions: JWTClaimVerificationOptions,\n): Promise<JWTPayload> {\n if (config.jwk !== undefined) {\n return verifyTokenImpl(token, loadJwk(config.jwk), verifyOptions);\n }\n\n if (config.secret !== undefined) {\n return verifyTokenImpl(token, loadSecret(config.secret), verifyOptions);\n }\n\n if (config.jwksUrl !== undefined) {\n const remoteKeyset = getRemoteKeyset(config.jwksUrl);\n return (await jwtVerify(token, remoteKeyset, verifyOptions)).payload;\n }\n\n throw new Error(\n 'verifyToken was called but no auth options (one of: jwk, secret, jwksUrl) were configured.',\n );\n}\n\nfunction loadJwk(jwkString: string) {\n return JSON.parse(jwkString) as JWK;\n}\n\nfunction loadSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nasync function verifyTokenImpl(\n token: string,\n verifyKey: Uint8Array | KeyLike | JWK,\n verifyOptions: JWTClaimVerificationOptions,\n): Promise<JWTPayload> {\n const {payload} = await jwtVerify(token, verifyKey, verifyOptions);\n\n return payload;\n}\n"],"mappings":";;AA8BA,IAAI;AACJ,SAAS,gBAAgB,SAAiB;CACxC,IAAI,iBAAiB,KAAA,GACnB,eAAe,mBAAmB,IAAI,IAAI,OAAO,CAAC;CAGpD,OAAO;AACT;;AAGA,IAAa,sBAAsB,WAAgC;CAKjE,OAJsB;EAAC;EAAO;EAAU;CAAS,CAAC,CAAW,QAC3D,QAAO,OAAO,SAAS,KAAA,CAGlB;AACT;;AAGA,eAAsB,YACpB,QACA,OACA,eACqB;CACrB,IAAI,OAAO,QAAQ,KAAA,GACjB,OAAO,gBAAgB,OAAO,QAAQ,OAAO,GAAG,GAAG,aAAa;CAGlE,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,gBAAgB,OAAO,WAAW,OAAO,MAAM,GAAG,aAAa;CAGxE,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,MAAM,eAAe,gBAAgB,OAAO,OAAO;EACnD,QAAQ,MAAM,UAAU,OAAO,cAAc,aAAa,EAAA,CAAG;CAC/D;CAEA,MAAM,IAAI,MACR,4FACF;AACF;AAEA,SAAS,QAAQ,WAAmB;CAClC,OAAO,KAAK,MAAM,SAAS;AAC7B;AAEA,SAAS,WAAW,QAAgB;CAClC,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,MAAM;AACxC;AAEA,eAAe,gBACb,OACA,WACA,eACqB;CACrB,MAAM,EAAC,YAAW,MAAM,UAAU,OAAO,WAAW,aAAa;CAEjE,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"load-permissions.js","names":[],"sources":["../../../../../zero-cache/src/auth/load-permissions.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport * as v from '../../../shared/src/valita.ts';\nimport {\n permissionsConfigSchema,\n type PermissionsConfig,\n} from '../../../zero-schema/src/compiled-permissions.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {Database} from '../../../zqlite/src/db.ts';\nimport type {ZeroConfig} from '../config/zero-config.ts';\nimport {computeZqlSpecs} from '../db/lite-tables.ts';\nimport type {StatementRunner} from '../db/statements.ts';\nimport {elide} from '../types/strings.ts';\n\nexport type LoadedPermissions = {\n permissions: PermissionsConfig | null;\n hash: string | null;\n};\n\nexport function loadPermissions(\n lc: LogContext,\n replica: StatementRunner,\n appID: string,\n config?: ZeroConfig,\n): LoadedPermissions {\n const {permissions, hash} = replica.get(\n `SELECT permissions, hash FROM \"${appID}.permissions\"`,\n );\n if (permissions === null) {\n const hasCustomEndpoints =\n config !== undefined &&\n (config.push?.url !== undefined || config.mutate?.url !== undefined) &&\n (config.query?.url !== undefined || config.getQueries?.url !== undefined);\n\n if (!hasCustomEndpoints) {\n const appIDFlag = appID === 'zero' ? '' : ` --app-id=${appID}`;\n lc.warn?.(\n `\\n\\n\\n` +\n `No upstream permissions deployed.\\n` +\n `Run 'npx zero-deploy-permissions${appIDFlag}' to enforce permissions.` +\n `\\n\\n\\n`,\n );\n }\n return {permissions, hash: null};\n }\n let obj;\n let parsed;\n try {\n obj = JSON.parse(permissions);\n parsed = v.parse(obj, permissionsConfigSchema);\n } catch (e) {\n // TODO: Plumb the --server-version and include in error message.\n throw new Error(\n `Could not parse upstream permissions: ` +\n `'${elide(String(permissions), 100)}'.\\n` +\n `This may happen if Permissions with a new internal format are ` +\n `deployed before the supporting server has been fully rolled out.`,\n {cause: e},\n );\n }\n return {permissions: parsed, hash};\n}\n\nexport function reloadPermissionsIfChanged(\n lc: LogContext,\n replica: StatementRunner,\n appID: string,\n current: LoadedPermissions | null,\n config?: ZeroConfig,\n): {permissions: LoadedPermissions; changed: boolean} {\n if (current === null) {\n return {\n permissions: loadPermissions(lc, replica, appID, config),\n changed: true,\n };\n }\n const {hash} = replica.get(`SELECT hash FROM \"${appID}.permissions\"`);\n return hash === current.hash\n ? {permissions: current, changed: false}\n : {permissions: loadPermissions(lc, replica, appID, config), changed: true};\n}\n\nexport function getSchema(lc: LogContext, replica: Database): Schema {\n const specs = computeZqlSpecs(lc, replica, {\n includeBackfillingColumns: false,\n });\n const tables = Object.fromEntries(\n Array.from(specs.values(), table => {\n const {\n tableSpec: {name, primaryKey},\n zqlSpec: columns,\n } = table;\n return [name, {name, columns, primaryKey} satisfies TableSchema];\n }),\n );\n return {\n tables,\n relationships: {}, // relationships are already denormalized in ASTs\n };\n}\n"],"mappings":";;;;;AAmBA,SAAgB,gBACd,IACA,SACA,OACA,QACmB;CACnB,MAAM,EAAC,aAAa,SAAQ,QAAQ,IAClC,kCAAkC,MAAM,cAC1C;CACA,IAAI,gBAAgB,MAAM;EAMxB,IAAI,EAJF,WAAW,KAAA,MACV,OAAO,MAAM,QAAQ,KAAA,KAAa,OAAO,QAAQ,QAAQ,KAAA,OACzD,OAAO,OAAO,QAAQ,KAAA,KAAa,OAAO,YAAY,QAAQ,KAAA,KAExC;GACvB,MAAM,YAAY,UAAU,SAAS,KAAK,aAAa;GACvD,GAAG,OACD;;;;kCAEqC,UAAU,gCAEjD;EACF;EACA,OAAO;GAAC;GAAa,MAAM;EAAI;CACjC;CACA,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,MAAM,KAAK,MAAM,WAAW;EAC5B,SAAS,MAAQ,KAAK,uBAAuB;CAC/C,SAAS,GAAG;EAEV,MAAM,IAAI,MACR,0CACM,MAAM,OAAO,WAAW,GAAG,GAAG,EAAE,qIAGtC,EAAC,OAAO,EAAC,CACX;CACF;CACA,OAAO;EAAC,aAAa;EAAQ;CAAI;AACnC;AAEA,SAAgB,2BACd,IACA,SACA,OACA,SACA,QACoD;CACpD,IAAI,YAAY,MACd,OAAO;EACL,aAAa,gBAAgB,IAAI,SAAS,OAAO,MAAM;EACvD,SAAS;CACX;CAEF,MAAM,EAAC,SAAQ,QAAQ,IAAI,qBAAqB,MAAM,cAAc;CACpE,OAAO,SAAS,QAAQ,OACpB;EAAC,aAAa;EAAS,SAAS;CAAK,IACrC;EAAC,aAAa,gBAAgB,IAAI,SAAS,OAAO,MAAM;EAAG,SAAS;CAAI;AAC9E;AAEA,SAAgB,UAAU,IAAgB,SAA2B;CACnE,MAAM,QAAQ,gBAAgB,IAAI,SAAS,EACzC,2BAA2B,MAC7B,CAAC;CAUD,OAAO;EACL,QAVa,OAAO,YACpB,MAAM,KAAK,MAAM,OAAO,IAAG,UAAS;GAClC,MAAM,EACJ,WAAW,EAAC,MAAM,cAClB,SAAS,YACP;GACJ,OAAO,CAAC,MAAM;IAAC;IAAM;IAAS;GAAU,CAAuB;EACjE,CAAC,CAGD;EACA,eAAe,CAAC;CAClB;AACF"}
1
+ {"version":3,"file":"load-permissions.js","names":["v.parse"],"sources":["../../../../../zero-cache/src/auth/load-permissions.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport * as v from '../../../shared/src/valita.ts';\nimport {\n permissionsConfigSchema,\n type PermissionsConfig,\n} from '../../../zero-schema/src/compiled-permissions.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {Database} from '../../../zqlite/src/db.ts';\nimport type {ZeroConfig} from '../config/zero-config.ts';\nimport {computeZqlSpecs} from '../db/lite-tables.ts';\nimport type {StatementRunner} from '../db/statements.ts';\nimport {elide} from '../types/strings.ts';\n\nexport type LoadedPermissions = {\n permissions: PermissionsConfig | null;\n hash: string | null;\n};\n\nexport function loadPermissions(\n lc: LogContext,\n replica: StatementRunner,\n appID: string,\n config?: ZeroConfig,\n): LoadedPermissions {\n const {permissions, hash} = replica.get(\n `SELECT permissions, hash FROM \"${appID}.permissions\"`,\n );\n if (permissions === null) {\n const hasCustomEndpoints =\n config !== undefined &&\n (config.push?.url !== undefined || config.mutate?.url !== undefined) &&\n (config.query?.url !== undefined || config.getQueries?.url !== undefined);\n\n if (!hasCustomEndpoints) {\n const appIDFlag = appID === 'zero' ? '' : ` --app-id=${appID}`;\n lc.warn?.(\n `\\n\\n\\n` +\n `No upstream permissions deployed.\\n` +\n `Run 'npx zero-deploy-permissions${appIDFlag}' to enforce permissions.` +\n `\\n\\n\\n`,\n );\n }\n return {permissions, hash: null};\n }\n let obj;\n let parsed;\n try {\n obj = JSON.parse(permissions);\n parsed = v.parse(obj, permissionsConfigSchema);\n } catch (e) {\n // TODO: Plumb the --server-version and include in error message.\n throw new Error(\n `Could not parse upstream permissions: ` +\n `'${elide(String(permissions), 100)}'.\\n` +\n `This may happen if Permissions with a new internal format are ` +\n `deployed before the supporting server has been fully rolled out.`,\n {cause: e},\n );\n }\n return {permissions: parsed, hash};\n}\n\nexport function reloadPermissionsIfChanged(\n lc: LogContext,\n replica: StatementRunner,\n appID: string,\n current: LoadedPermissions | null,\n config?: ZeroConfig,\n): {permissions: LoadedPermissions; changed: boolean} {\n if (current === null) {\n return {\n permissions: loadPermissions(lc, replica, appID, config),\n changed: true,\n };\n }\n const {hash} = replica.get(`SELECT hash FROM \"${appID}.permissions\"`);\n return hash === current.hash\n ? {permissions: current, changed: false}\n : {permissions: loadPermissions(lc, replica, appID, config), changed: true};\n}\n\nexport function getSchema(lc: LogContext, replica: Database): Schema {\n const specs = computeZqlSpecs(lc, replica, {\n includeBackfillingColumns: false,\n });\n const tables = Object.fromEntries(\n Array.from(specs.values(), table => {\n const {\n tableSpec: {name, primaryKey},\n zqlSpec: columns,\n } = table;\n return [name, {name, columns, primaryKey} satisfies TableSchema];\n }),\n );\n return {\n tables,\n relationships: {}, // relationships are already denormalized in ASTs\n };\n}\n"],"mappings":";;;;;AAmBA,SAAgB,gBACd,IACA,SACA,OACA,QACmB;CACnB,MAAM,EAAC,aAAa,SAAQ,QAAQ,IAClC,kCAAkC,MAAM,cAC1C;CACA,IAAI,gBAAgB,MAAM;EAMxB,IAAI,EAJF,WAAW,KAAA,MACV,OAAO,MAAM,QAAQ,KAAA,KAAa,OAAO,QAAQ,QAAQ,KAAA,OACzD,OAAO,OAAO,QAAQ,KAAA,KAAa,OAAO,YAAY,QAAQ,KAAA,KAExC;GACvB,MAAM,YAAY,UAAU,SAAS,KAAK,aAAa;GACvD,GAAG,OACD;;;;kCAEqC,UAAU,gCAEjD;EACF;EACA,OAAO;GAAC;GAAa,MAAM;EAAI;CACjC;CACA,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,MAAM,KAAK,MAAM,WAAW;EAC5B,SAASA,MAAQ,KAAK,uBAAuB;CAC/C,SAAS,GAAG;EAEV,MAAM,IAAI,MACR,0CACM,MAAM,OAAO,WAAW,GAAG,GAAG,EAAE,qIAGtC,EAAC,OAAO,EAAC,CACX;CACF;CACA,OAAO;EAAC,aAAa;EAAQ;CAAI;AACnC;AAEA,SAAgB,2BACd,IACA,SACA,OACA,SACA,QACoD;CACpD,IAAI,YAAY,MACd,OAAO;EACL,aAAa,gBAAgB,IAAI,SAAS,OAAO,MAAM;EACvD,SAAS;CACX;CAEF,MAAM,EAAC,SAAQ,QAAQ,IAAI,qBAAqB,MAAM,cAAc;CACpE,OAAO,SAAS,QAAQ,OACpB;EAAC,aAAa;EAAS,SAAS;CAAK,IACrC;EAAC,aAAa,gBAAgB,IAAI,SAAS,OAAO,MAAM;EAAG,SAAS;CAAI;AAC9E;AAEA,SAAgB,UAAU,IAAgB,SAA2B;CACnE,MAAM,QAAQ,gBAAgB,IAAI,SAAS,EACzC,2BAA2B,MAC7B,CAAC;CAUD,OAAO;EACL,QAVa,OAAO,YACpB,MAAM,KAAK,MAAM,OAAO,IAAG,UAAS;GAClC,MAAM,EACJ,WAAW,EAAC,MAAM,cAClB,SAAS,YACP;GACJ,OAAO,CAAC,MAAM;IAAC;IAAM;IAAS;GAAU,CAAuB;EACjE,CAAC,CAGD;EACA,eAAe,CAAC;CAClB;AACF"}
@@ -23,7 +23,8 @@ function transformAndHashQuery(lc, id, query, permissionRules, auth, internalQue
23
23
  * For a given AST, apply the read-auth rules and bind static auth data.
24
24
  */
25
25
  function transformQuery(lc, query, permissionRules, auth) {
26
- return bindStaticParameters(transformQueryInternal(lc, query, permissionRules), { authData: auth ? auth.decoded : {} });
26
+ const queryWithPermissions = transformQueryInternal(lc, query, permissionRules);
27
+ return bindStaticParameters(queryWithPermissions, { authData: auth ? auth.decoded : {} });
27
28
  }
28
29
  function transformQueryInternal(lc, query, permissionRules) {
29
30
  let rowSelectRules = permissionRules?.tables?.[query.table]?.row?.select;
@@ -77,6 +78,6 @@ function transformCondition(lc, cond, auth) {
77
78
  }
78
79
  }
79
80
  //#endregion
80
- export { transformAndHashQuery };
81
+ export { transformAndHashQuery, transformQuery };
81
82
 
82
83
  //# sourceMappingURL=read-authorizer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-authorizer.js","names":[],"sources":["../../../../../zero-cache/src/auth/read-authorizer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport type {AST, Condition} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfAST} from '../../../zero-protocol/src/query-hash.ts';\nimport type {PermissionsConfig} from '../../../zero-schema/src/compiled-permissions.ts';\nimport {bindStaticParameters} from '../../../zql/src/builder/builder.ts';\nimport {simplifyCondition} from '../../../zql/src/query/expression.ts';\nimport type {JWTAuth} from './auth.ts';\n\nexport type TransformedAndHashed = {\n id: string;\n transformedAst: AST;\n transformationHash: string;\n};\n/**\n * Adds permission rules to the given query so it only returns rows that the\n * user is allowed to read.\n *\n * If the returned query is `undefined` that means that user cannot run\n * the query at all. This is only the case if we can infer that all rows\n * would be excluded without running the query.\n * E.g., the user is trying to query a table that is not readable.\n */\nexport function transformAndHashQuery(\n lc: LogContext,\n id: string,\n query: AST,\n permissionRules: PermissionsConfig,\n auth: JWTAuth | undefined,\n internalQuery: boolean | null | undefined,\n): TransformedAndHashed {\n const transformed = internalQuery\n ? query // application permissions do not apply to internal queries\n : transformQuery(lc, query, permissionRules, auth);\n return {\n id,\n transformedAst: transformed,\n transformationHash: hashOfAST(transformed),\n };\n}\n\n/**\n * For a given AST, apply the read-auth rules and bind static auth data.\n */\nexport function transformQuery(\n lc: LogContext,\n query: AST,\n permissionRules: PermissionsConfig,\n auth: JWTAuth | undefined,\n): AST {\n const queryWithPermissions = transformQueryInternal(\n lc,\n query,\n permissionRules,\n );\n return bindStaticParameters(queryWithPermissions, {\n authData: auth ? (auth.decoded as Record<string, JSONValue>) : {},\n });\n}\n\nfunction transformQueryInternal(\n lc: LogContext,\n query: AST,\n permissionRules: PermissionsConfig,\n): AST {\n let rowSelectRules = permissionRules?.tables?.[query.table]?.row?.select;\n\n if (!rowSelectRules || rowSelectRules.length === 0) {\n // If there are no rules, we default to not allowing any rows to be selected.\n lc.warn?.(\n \"No permission rules found for table '\" +\n query.table +\n \"'. No rows will be returned. Use ANYONE_CAN to allow all users to access all rows.\",\n );\n rowSelectRules = [\n [\n 'allow',\n {\n type: 'or',\n conditions: [],\n },\n ],\n ];\n }\n\n const updatedWhere = addRulesToWhere(\n query.where\n ? transformCondition(lc, query.where, permissionRules)\n : undefined,\n rowSelectRules,\n );\n return {\n ...query,\n where: simplifyCondition(updatedWhere),\n related: query.related?.map(sq => {\n const subquery = transformQueryInternal(lc, sq.subquery, permissionRules);\n return {\n ...sq,\n subquery,\n };\n }),\n };\n}\n\nfunction addRulesToWhere(\n where: Condition | undefined,\n rowSelectRules: ['allow', Condition][],\n): Condition {\n return {\n type: 'and',\n conditions: [\n ...(where ? [where] : []),\n {\n type: 'or',\n conditions: rowSelectRules.map(([_, condition]) => condition),\n },\n ],\n };\n}\n\n// We must augment conditions so we do not provide an oracle to users.\n// E.g.,\n// `issue.whereExists('secret', s => s.where('value', 'sdf'))`\n// Not applying read policies to subqueries in the where position\n// would allow users to infer the existence of rows, and their contents,\n// that they cannot read.\nfunction transformCondition(\n lc: LogContext,\n cond: Condition,\n auth: PermissionsConfig,\n): Condition {\n switch (cond.type) {\n case 'simple':\n return cond;\n case 'and':\n case 'or':\n return {\n ...cond,\n conditions: cond.conditions.map(c => transformCondition(lc, c, auth)),\n };\n case 'correlatedSubquery': {\n const query = transformQueryInternal(lc, cond.related.subquery, auth);\n return {\n ...cond,\n related: {\n ...cond.related,\n subquery: query,\n },\n };\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,SAAgB,sBACd,IACA,IACA,OACA,iBACA,MACA,eACsB;CACtB,MAAM,cAAc,gBAChB,QACA,eAAe,IAAI,OAAO,iBAAiB,IAAI;CACnD,OAAO;EACL;EACA,gBAAgB;EAChB,oBAAoB,UAAU,WAAW;CAC3C;AACF;;;;AAKA,SAAgB,eACd,IACA,OACA,iBACA,MACK;CAML,OAAO,qBALsB,uBAC3B,IACA,OACA,eAE0B,GAAsB,EAChD,UAAU,OAAQ,KAAK,UAAwC,CAAC,EAClE,CAAC;AACH;AAEA,SAAS,uBACP,IACA,OACA,iBACK;CACL,IAAI,iBAAiB,iBAAiB,SAAS,MAAM,QAAQ,KAAK;CAElE,IAAI,CAAC,kBAAkB,eAAe,WAAW,GAAG;EAElD,GAAG,OACD,0CACE,MAAM,QACN,oFACJ;EACA,iBAAiB,CACf,CACE,SACA;GACE,MAAM;GACN,YAAY,CAAC;EACf,CACF,CACF;CACF;CAEA,MAAM,eAAe,gBACnB,MAAM,QACF,mBAAmB,IAAI,MAAM,OAAO,eAAe,IACnD,KAAA,GACJ,cACF;CACA,OAAO;EACL,GAAG;EACH,OAAO,kBAAkB,YAAY;EACrC,SAAS,MAAM,SAAS,KAAI,OAAM;GAChC,MAAM,WAAW,uBAAuB,IAAI,GAAG,UAAU,eAAe;GACxE,OAAO;IACL,GAAG;IACH;GACF;EACF,CAAC;CACH;AACF;AAEA,SAAS,gBACP,OACA,gBACW;CACX,OAAO;EACL,MAAM;EACN,YAAY,CACV,GAAI,QAAQ,CAAC,KAAK,IAAI,CAAC,GACvB;GACE,MAAM;GACN,YAAY,eAAe,KAAK,CAAC,GAAG,eAAe,SAAS;EAC9D,CACF;CACF;AACF;AAQA,SAAS,mBACP,IACA,MACA,MACW;CACX,QAAQ,KAAK,MAAb;EACE,KAAK,UACH,OAAO;EACT,KAAK;EACL,KAAK,MACH,OAAO;GACL,GAAG;GACH,YAAY,KAAK,WAAW,KAAI,MAAK,mBAAmB,IAAI,GAAG,IAAI,CAAC;EACtE;EACF,KAAK,sBAAsB;GACzB,MAAM,QAAQ,uBAAuB,IAAI,KAAK,QAAQ,UAAU,IAAI;GACpE,OAAO;IACL,GAAG;IACH,SAAS;KACP,GAAG,KAAK;KACR,UAAU;IACZ;GACF;EACF;CACF;AACF"}
1
+ {"version":3,"file":"read-authorizer.js","names":[],"sources":["../../../../../zero-cache/src/auth/read-authorizer.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport type {AST, Condition} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfAST} from '../../../zero-protocol/src/query-hash.ts';\nimport type {PermissionsConfig} from '../../../zero-schema/src/compiled-permissions.ts';\nimport {bindStaticParameters} from '../../../zql/src/builder/builder.ts';\nimport {simplifyCondition} from '../../../zql/src/query/expression.ts';\nimport type {JWTAuth} from './auth.ts';\n\nexport type TransformedAndHashed = {\n id: string;\n transformedAst: AST;\n transformationHash: string;\n};\n/**\n * Adds permission rules to the given query so it only returns rows that the\n * user is allowed to read.\n *\n * If the returned query is `undefined` that means that user cannot run\n * the query at all. This is only the case if we can infer that all rows\n * would be excluded without running the query.\n * E.g., the user is trying to query a table that is not readable.\n */\nexport function transformAndHashQuery(\n lc: LogContext,\n id: string,\n query: AST,\n permissionRules: PermissionsConfig,\n auth: JWTAuth | undefined,\n internalQuery: boolean | null | undefined,\n): TransformedAndHashed {\n const transformed = internalQuery\n ? query // application permissions do not apply to internal queries\n : transformQuery(lc, query, permissionRules, auth);\n return {\n id,\n transformedAst: transformed,\n transformationHash: hashOfAST(transformed),\n };\n}\n\n/**\n * For a given AST, apply the read-auth rules and bind static auth data.\n */\nexport function transformQuery(\n lc: LogContext,\n query: AST,\n permissionRules: PermissionsConfig,\n auth: JWTAuth | undefined,\n): AST {\n const queryWithPermissions = transformQueryInternal(\n lc,\n query,\n permissionRules,\n );\n return bindStaticParameters(queryWithPermissions, {\n authData: auth ? (auth.decoded as Record<string, JSONValue>) : {},\n });\n}\n\nfunction transformQueryInternal(\n lc: LogContext,\n query: AST,\n permissionRules: PermissionsConfig,\n): AST {\n let rowSelectRules = permissionRules?.tables?.[query.table]?.row?.select;\n\n if (!rowSelectRules || rowSelectRules.length === 0) {\n // If there are no rules, we default to not allowing any rows to be selected.\n lc.warn?.(\n \"No permission rules found for table '\" +\n query.table +\n \"'. No rows will be returned. Use ANYONE_CAN to allow all users to access all rows.\",\n );\n rowSelectRules = [\n [\n 'allow',\n {\n type: 'or',\n conditions: [],\n },\n ],\n ];\n }\n\n const updatedWhere = addRulesToWhere(\n query.where\n ? transformCondition(lc, query.where, permissionRules)\n : undefined,\n rowSelectRules,\n );\n return {\n ...query,\n where: simplifyCondition(updatedWhere),\n related: query.related?.map(sq => {\n const subquery = transformQueryInternal(lc, sq.subquery, permissionRules);\n return {\n ...sq,\n subquery,\n };\n }),\n };\n}\n\nfunction addRulesToWhere(\n where: Condition | undefined,\n rowSelectRules: ['allow', Condition][],\n): Condition {\n return {\n type: 'and',\n conditions: [\n ...(where ? [where] : []),\n {\n type: 'or',\n conditions: rowSelectRules.map(([_, condition]) => condition),\n },\n ],\n };\n}\n\n// We must augment conditions so we do not provide an oracle to users.\n// E.g.,\n// `issue.whereExists('secret', s => s.where('value', 'sdf'))`\n// Not applying read policies to subqueries in the where position\n// would allow users to infer the existence of rows, and their contents,\n// that they cannot read.\nfunction transformCondition(\n lc: LogContext,\n cond: Condition,\n auth: PermissionsConfig,\n): Condition {\n switch (cond.type) {\n case 'simple':\n return cond;\n case 'and':\n case 'or':\n return {\n ...cond,\n conditions: cond.conditions.map(c => transformCondition(lc, c, auth)),\n };\n case 'correlatedSubquery': {\n const query = transformQueryInternal(lc, cond.related.subquery, auth);\n return {\n ...cond,\n related: {\n ...cond.related,\n subquery: query,\n },\n };\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,SAAgB,sBACd,IACA,IACA,OACA,iBACA,MACA,eACsB;CACtB,MAAM,cAAc,gBAChB,QACA,eAAe,IAAI,OAAO,iBAAiB,IAAI;CACnD,OAAO;EACL;EACA,gBAAgB;EAChB,oBAAoB,UAAU,WAAW;CAC3C;AACF;;;;AAKA,SAAgB,eACd,IACA,OACA,iBACA,MACK;CACL,MAAM,uBAAuB,uBAC3B,IACA,OACA,eACF;CACA,OAAO,qBAAqB,sBAAsB,EAChD,UAAU,OAAQ,KAAK,UAAwC,CAAC,EAClE,CAAC;AACH;AAEA,SAAS,uBACP,IACA,OACA,iBACK;CACL,IAAI,iBAAiB,iBAAiB,SAAS,MAAM,MAAM,EAAE,KAAK;CAElE,IAAI,CAAC,kBAAkB,eAAe,WAAW,GAAG;EAElD,GAAG,OACD,0CACE,MAAM,QACN,oFACJ;EACA,iBAAiB,CACf,CACE,SACA;GACE,MAAM;GACN,YAAY,CAAC;EACf,CACF,CACF;CACF;CAEA,MAAM,eAAe,gBACnB,MAAM,QACF,mBAAmB,IAAI,MAAM,OAAO,eAAe,IACnD,KAAA,GACJ,cACF;CACA,OAAO;EACL,GAAG;EACH,OAAO,kBAAkB,YAAY;EACrC,SAAS,MAAM,SAAS,KAAI,OAAM;GAChC,MAAM,WAAW,uBAAuB,IAAI,GAAG,UAAU,eAAe;GACxE,OAAO;IACL,GAAG;IACH;GACF;EACF,CAAC;CACH;AACF;AAEA,SAAS,gBACP,OACA,gBACW;CACX,OAAO;EACL,MAAM;EACN,YAAY,CACV,GAAI,QAAQ,CAAC,KAAK,IAAI,CAAC,GACvB;GACE,MAAM;GACN,YAAY,eAAe,KAAK,CAAC,GAAG,eAAe,SAAS;EAC9D,CACF;CACF;AACF;AAQA,SAAS,mBACP,IACA,MACA,MACW;CACX,QAAQ,KAAK,MAAb;EACE,KAAK,UACH,OAAO;EACT,KAAK;EACL,KAAK,MACH,OAAO;GACL,GAAG;GACH,YAAY,KAAK,WAAW,KAAI,MAAK,mBAAmB,IAAI,GAAG,IAAI,CAAC;EACtE;EACF,KAAK,sBAAsB;GACzB,MAAM,QAAQ,uBAAuB,IAAI,KAAK,QAAQ,UAAU,IAAI;GACpE,OAAO;IACL,GAAG;IACH,SAAS;KACP,GAAG,KAAK;KACR,UAAU;IACZ;GACF;EACF;CACF;AACF"}
@@ -61,9 +61,7 @@ var WriteAuthorizerImpl = class {
61
61
  case "update":
62
62
  if (!await this.#canUpdate("preMutation", authData, op)) return false;
63
63
  break;
64
- case "delete":
65
- if (!await this.#canDelete("preMutation", authData, op)) return false;
66
- break;
64
+ case "delete": if (!await this.#canDelete("preMutation", authData, op)) return false;
67
65
  }
68
66
  return true;
69
67
  }
@@ -80,19 +78,14 @@ var WriteAuthorizerImpl = class {
80
78
  case "update":
81
79
  consume(source.push(makeSourceChangeEdit(op.value, this.#requirePreMutationRow(op))));
82
80
  break;
83
- case "delete":
84
- consume(source.push(makeSourceChangeRemove(this.#requirePreMutationRow(op))));
85
- break;
81
+ case "delete": consume(source.push(makeSourceChangeRemove(this.#requirePreMutationRow(op))));
86
82
  }
87
83
  }
88
84
  for (const op of ops) switch (op.op) {
89
85
  case "insert":
90
86
  if (!await this.#canInsert("postMutation", authData, op)) return false;
91
87
  break;
92
- case "update":
93
- if (!await this.#canUpdate("postMutation", authData, op)) return false;
94
- break;
95
- case "delete": break;
88
+ case "update": if (!await this.#canUpdate("postMutation", authData, op)) return false;
96
89
  }
97
90
  } catch (e) {
98
91
  opError = e;
@@ -204,9 +197,7 @@ var WriteAuthorizerImpl = class {
204
197
  if (phase === "preMutation") applicableRowPolicy = rowPolicies?.update?.preMutation;
205
198
  else if (phase === "postMutation") applicableRowPolicy = rowPolicies?.update?.postMutation;
206
199
  break;
207
- case "delete":
208
- if (phase === "preMutation") applicableRowPolicy = rowPolicies?.delete;
209
- break;
200
+ case "delete": if (phase === "preMutation") applicableRowPolicy = rowPolicies?.delete;
210
201
  }
211
202
  const cellPolicies = rules?.cell;
212
203
  const applicableCellPolicies = [];
@@ -220,9 +211,7 @@ var WriteAuthorizerImpl = class {
220
211
  if (phase === "preMutation" && policy.update?.preMutation) applicableCellPolicies.push(policy.update.preMutation);
221
212
  if (phase === "postMutation" && policy.update?.postMutation) applicableCellPolicies.push(policy.update.postMutation);
222
213
  break;
223
- case "delete":
224
- if (policy.delete && phase === "preMutation") applicableCellPolicies.push(policy.delete);
225
- break;
214
+ case "delete": if (policy.delete && phase === "preMutation") applicableCellPolicies.push(policy.delete);
226
215
  }
227
216
  }
228
217
  if (!await this.#passesPolicyGroup(applicableRowPolicy, applicableCellPolicies, authData, rowQuery)) {
@@ -1 +1 @@
1
- {"version":3,"file":"write-authorizer.js","names":["#schema","#replica","#builderDelegate","#tableSpecs","#tables","#statementRunner","#lc","#appID","#logConfig","#cgStorage","#config","#getSource","#loadedPermissions","#canUpdate","#canDelete","#requirePreMutationRow","#canInsert","#getPreMutationRow","#timedCanDo","#canDo","#getPrimaryKey","#passesPolicyGroup","#passesPolicy"],"sources":["../../../../../zero-cache/src/auth/write-authorizer.ts"],"sourcesContent":["import type {SQLQuery} from '@databases/sql';\nimport type {MaybePromise} from '@opentelemetry/resources';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {JWTPayload} from 'jose';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {JSONValue, ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {Condition} from '../../../zero-protocol/src/ast.ts';\nimport type {\n CRUDOp,\n DeleteOp,\n InsertOp,\n UpdateOp,\n UpsertOp,\n} from '../../../zero-protocol/src/mutation.ts';\nimport {\n primaryKeyValueSchema,\n type PrimaryKeyValue,\n} from '../../../zero-protocol/src/primary-key.ts';\nimport type {Policy} from '../../../zero-schema/src/compiled-permissions.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {BuilderDelegate} from '../../../zql/src/builder/builder.ts';\nimport {\n bindStaticParameters,\n buildPipeline,\n} from '../../../zql/src/builder/builder.ts';\nimport {\n makeSourceChangeAdd,\n makeSourceChangeEdit,\n makeSourceChangeRemove,\n} from '../../../zql/src/ivm/source.ts';\nimport {consume} from '../../../zql/src/ivm/stream.ts';\nimport {simplifyCondition} from '../../../zql/src/query/expression.ts';\nimport {asQueryInternals} from '../../../zql/src/query/query-internals.ts';\nimport type {Query} from '../../../zql/src/query/query.ts';\nimport {newStaticQuery} from '../../../zql/src/query/static-query.ts';\nimport type {\n ClientGroupStorage,\n DatabaseStorage,\n} from '../../../zqlite/src/database-storage.ts';\nimport type {Database} from '../../../zqlite/src/db.ts';\nimport {compile, sql} from '../../../zqlite/src/internal/sql.ts';\nimport {\n fromSQLiteTypes,\n TableSource,\n} from '../../../zqlite/src/table-source.ts';\nimport type {LogConfig, ZeroConfig} from '../config/zero-config.ts';\nimport {computeZqlSpecs} from '../db/lite-tables.ts';\nimport type {LiteAndZqlSpec} from '../db/specs.ts';\nimport {StatementRunner} from '../db/statements.ts';\nimport {mapLiteDataTypeToZqlSchemaValue} from '../types/lite.ts';\nimport {\n getSchema,\n reloadPermissionsIfChanged,\n type LoadedPermissions,\n} from './load-permissions.ts';\n\ntype Phase = 'preMutation' | 'postMutation';\n\nexport interface WriteAuthorizer {\n canPreMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ): Promise<boolean>;\n canPostMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ): Promise<boolean>;\n reloadPermissions(): void;\n normalizeOps(ops: CRUDOp[]): Exclude<CRUDOp, UpsertOp>[];\n\n /**\n * Validates that all table names in the operations exist in the schema.\n * @throws Error if any table name is invalid\n */\n validateTableNames(ops: CRUDOp[]): void;\n}\n\nexport class WriteAuthorizerImpl implements WriteAuthorizer {\n readonly #schema: Schema;\n readonly #replica: Database;\n readonly #builderDelegate: BuilderDelegate;\n readonly #tableSpecs: Map<string, LiteAndZqlSpec>;\n readonly #tables = new Map<string, TableSource>();\n readonly #statementRunner: StatementRunner;\n readonly #lc: LogContext;\n readonly #appID: string;\n readonly #logConfig: LogConfig;\n readonly #cgStorage: ClientGroupStorage;\n readonly #config: ZeroConfig;\n\n #loadedPermissions: LoadedPermissions | null = null;\n\n constructor(\n lc: LogContext,\n config: ZeroConfig,\n replica: Database,\n appID: string,\n cgID: string,\n writeAuthzStorage: DatabaseStorage,\n ) {\n this.#appID = appID;\n this.#config = config;\n this.#lc = lc.withContext('class', 'WriteAuthorizerImpl');\n this.#logConfig = config.log;\n this.#schema = getSchema(this.#lc, replica);\n this.#replica = replica;\n this.#cgStorage = writeAuthzStorage.createClientGroupStorage(cgID);\n this.#builderDelegate = {\n disableCorrelatedPredicatePushdown:\n config.enableCorrelatedPredicatePushdown === false,\n getSource: name => this.#getSource(name),\n createStorage: () => this.#cgStorage.createStorage(),\n decorateSourceInput: input => input,\n decorateInput: input => input,\n addEdge() {},\n decorateFilterInput: input => input,\n };\n this.#tableSpecs = computeZqlSpecs(this.#lc, replica, {\n includeBackfillingColumns: false,\n });\n this.#statementRunner = new StatementRunner(replica);\n this.reloadPermissions();\n }\n\n reloadPermissions() {\n this.#loadedPermissions = reloadPermissionsIfChanged(\n this.#lc,\n this.#statementRunner,\n this.#appID,\n this.#loadedPermissions,\n this.#config,\n ).permissions;\n }\n\n destroy() {\n this.#cgStorage.destroy();\n }\n\n async canPreMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ) {\n for (const op of ops) {\n switch (op.op) {\n case 'insert':\n // insert does not run pre-mutation checks\n break;\n case 'update':\n if (!(await this.#canUpdate('preMutation', authData, op))) {\n return false;\n }\n break;\n case 'delete':\n if (!(await this.#canDelete('preMutation', authData, op))) {\n return false;\n }\n break;\n }\n }\n return true;\n }\n\n async canPostMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ) {\n this.#statementRunner.beginConcurrent();\n let opError: unknown;\n try {\n for (const op of ops) {\n const source = this.#getSource(op.tableName);\n switch (op.op) {\n case 'insert': {\n consume(source.push(makeSourceChangeAdd(op.value)));\n break;\n }\n // TODO(mlaw): what if someone updates the same thing twice?\n // TODO(aa): It seems like it will just work? source.push()\n // is going to push the row into the table source, and then the\n // next requirePreMutationRow will just return the row that was\n // pushed in.\n case 'update': {\n consume(\n source.push(\n makeSourceChangeEdit(op.value, this.#requirePreMutationRow(op)),\n ),\n );\n break;\n }\n case 'delete': {\n consume(\n source.push(\n makeSourceChangeRemove(this.#requirePreMutationRow(op)),\n ),\n );\n break;\n }\n }\n }\n\n for (const op of ops) {\n switch (op.op) {\n case 'insert':\n if (!(await this.#canInsert('postMutation', authData, op))) {\n return false;\n }\n break;\n case 'update':\n if (!(await this.#canUpdate('postMutation', authData, op))) {\n return false;\n }\n break;\n case 'delete':\n // delete does not run post-mutation checks.\n break;\n }\n }\n } catch (e) {\n opError = e;\n throw e;\n } finally {\n try {\n this.#statementRunner.rollback();\n } catch (rollbackError) {\n if (opError !== undefined) {\n const combinedError = new Error(\n `canPostMutation failed and rollback also failed: operation error = ${String(opError)}; rollback error = ${String(rollbackError)}`,\n );\n combinedError.cause = opError;\n throw combinedError;\n }\n throw rollbackError;\n }\n }\n\n return true;\n }\n\n normalizeOps(ops: CRUDOp[]): Exclude<CRUDOp, UpsertOp>[] {\n return ops.map(op => {\n if (op.op === 'upsert') {\n const preMutationRow = this.#getPreMutationRow(op);\n if (preMutationRow) {\n return {\n op: 'update',\n tableName: op.tableName,\n primaryKey: op.primaryKey,\n value: op.value,\n };\n }\n return {\n op: 'insert',\n tableName: op.tableName,\n primaryKey: op.primaryKey,\n value: op.value,\n };\n }\n return op;\n });\n }\n\n validateTableNames(ops: CRUDOp[]): void {\n for (const op of ops) {\n if (!this.#tableSpecs.has(op.tableName)) {\n throw new Error(`Table '${op.tableName}' is not a valid table.`);\n }\n }\n }\n\n #canInsert(phase: Phase, authData: JWTPayload | undefined, op: InsertOp) {\n return this.#timedCanDo(phase, 'insert', authData, op);\n }\n\n #canUpdate(phase: Phase, authData: JWTPayload | undefined, op: UpdateOp) {\n return this.#timedCanDo(phase, 'update', authData, op);\n }\n\n #canDelete(phase: Phase, authData: JWTPayload | undefined, op: DeleteOp) {\n return this.#timedCanDo(phase, 'delete', authData, op);\n }\n\n /**\n * Gets schema-defined primary key and validates that operation contains required PK values.\n *\n * @returns Record where keys are column names and values are client-provided values\n * @throws Error if operation value is missing required primary key columns\n */\n #getPrimaryKey(\n tableName: string,\n opValue: Record<string, ReadonlyJSONValue | undefined>,\n ): Record<string, ReadonlyJSONValue> {\n const tableSpec = this.#tableSpecs.get(tableName);\n if (!tableSpec) {\n throw new Error(`Table ${tableName} not found`);\n }\n const columns = tableSpec.tableSpec.primaryKey;\n\n // Extract primary key values from operation value and validate they exist\n const values: Record<string, ReadonlyJSONValue> = {};\n for (const col of columns) {\n const val = opValue[col];\n if (val === undefined) {\n throw new Error(\n `Primary key column '${col}' is missing from operation value for table ${tableName}`,\n );\n }\n values[col] = val;\n }\n\n return values;\n }\n\n #getSource(tableName: string) {\n let source = this.#tables.get(tableName);\n if (source) {\n return source;\n }\n const tableSpec = this.#tableSpecs.get(tableName);\n if (!tableSpec) {\n throw new Error(`Table ${tableName} not found`);\n }\n const {columns, primaryKey} = tableSpec.tableSpec;\n assert(\n primaryKey.length,\n () => `Table ${tableName} must have a primary key`,\n );\n source = new TableSource(\n this.#lc,\n this.#logConfig,\n this.#replica,\n tableName,\n Object.fromEntries(\n Object.entries(columns).map(([name, {dataType}]) => [\n name,\n mapLiteDataTypeToZqlSchemaValue(dataType),\n ]),\n ),\n [primaryKey[0], ...primaryKey.slice(1)],\n );\n this.#tables.set(tableName, source);\n\n return source;\n }\n\n async #timedCanDo<A extends keyof ActionOpMap>(\n phase: Phase,\n action: A,\n authData: JWTPayload | undefined,\n op: ActionOpMap[A],\n ) {\n const start = performance.now();\n try {\n const ret = await this.#canDo(phase, action, authData, op);\n return ret;\n } finally {\n this.#lc.info?.(\n 'action:',\n action,\n 'duration:',\n performance.now() - start,\n 'tableName:',\n op.tableName,\n 'primaryKey:',\n op.primaryKey,\n );\n }\n }\n\n /**\n * Evaluation order is from static to dynamic, broad to specific.\n * table -> column -> row -> cell.\n *\n * If any step fails, the entire operation is denied.\n *\n * That is, table rules supersede column rules, which supersede row rules,\n *\n * All steps must allow for the operation to be allowed.\n */\n async #canDo<A extends keyof ActionOpMap>(\n phase: Phase,\n action: A,\n authData: JWTPayload | undefined,\n op: ActionOpMap[A],\n ) {\n const rules = must(this.#loadedPermissions)?.permissions?.tables?.[\n op.tableName\n ];\n const rowPolicies = rules?.row;\n let rowQuery = newStaticQuery(this.#schema, op.tableName);\n\n const primaryKeyValues = this.#getPrimaryKey(op.tableName, op.value);\n\n for (const pk in primaryKeyValues) {\n rowQuery = rowQuery.where(pk, '=', primaryKeyValues[pk]);\n }\n\n let applicableRowPolicy: Policy | undefined;\n switch (action) {\n case 'insert':\n if (phase === 'postMutation') {\n applicableRowPolicy = rowPolicies?.insert;\n }\n break;\n case 'update':\n if (phase === 'preMutation') {\n applicableRowPolicy = rowPolicies?.update?.preMutation;\n } else if (phase === 'postMutation') {\n applicableRowPolicy = rowPolicies?.update?.postMutation;\n }\n break;\n case 'delete':\n if (phase === 'preMutation') {\n applicableRowPolicy = rowPolicies?.delete;\n }\n break;\n }\n\n const cellPolicies = rules?.cell;\n const applicableCellPolicies: Policy[] = [];\n if (cellPolicies) {\n for (const [column, policy] of Object.entries(cellPolicies)) {\n if (action === 'update' && op.value[column] === undefined) {\n // If the cell is not being updated, we do not need to check\n // the cell rules.\n continue;\n }\n switch (action) {\n case 'insert':\n if (policy.insert && phase === 'postMutation') {\n applicableCellPolicies.push(policy.insert);\n }\n break;\n case 'update':\n if (phase === 'preMutation' && policy.update?.preMutation) {\n applicableCellPolicies.push(policy.update.preMutation);\n }\n if (phase === 'postMutation' && policy.update?.postMutation) {\n applicableCellPolicies.push(policy.update.postMutation);\n }\n break;\n case 'delete':\n if (policy.delete && phase === 'preMutation') {\n applicableCellPolicies.push(policy.delete);\n }\n break;\n }\n }\n }\n\n if (\n !(await this.#passesPolicyGroup(\n applicableRowPolicy,\n applicableCellPolicies,\n authData,\n rowQuery,\n ))\n ) {\n // `op.value` is the row being written and `authData` is the decoded\n // JWT payload, so neither can go into the log. Column names and policy\n // counts are enough to debug a failed permission check.\n this.#lc.warn?.('Permission check failed', {\n action,\n phase,\n tableName: op.tableName,\n columns: Object.keys(op.value),\n rowPolicy: applicableRowPolicy !== undefined,\n cellPolicyCount: applicableCellPolicies.length,\n });\n return false;\n }\n\n return true;\n }\n\n #getPreMutationRow(op: UpsertOp | UpdateOp | DeleteOp) {\n const {value} = op;\n\n const primaryKeyValues = this.#getPrimaryKey(op.tableName, value);\n\n const spec = this.#tableSpecs.get(op.tableName);\n if (!spec) {\n throw new Error(`Table ${op.tableName} not found`);\n }\n\n const conditions: SQLQuery[] = [];\n const values: PrimaryKeyValue[] = [];\n for (const pk in primaryKeyValues) {\n conditions.push(sql`${sql.ident(pk)}=?`);\n values.push(v.parse(primaryKeyValues[pk], primaryKeyValueSchema));\n }\n\n const ret = this.#statementRunner.get(\n compile(\n sql`SELECT ${sql.join(\n Object.keys(spec.zqlSpec).map(c => sql.ident(c)),\n sql`,`,\n )} FROM ${sql.ident(op.tableName)} WHERE ${sql.join(\n conditions,\n sql` AND `,\n )}`,\n ),\n ...values,\n );\n if (ret === undefined) {\n return ret;\n }\n return fromSQLiteTypes(spec.zqlSpec, ret, op.tableName);\n }\n\n #requirePreMutationRow(op: UpdateOp | DeleteOp) {\n const ret = this.#getPreMutationRow(op);\n assert(\n ret !== undefined,\n () => `Pre-mutation row not found for ${JSON.stringify(op.value)}`,\n );\n return ret;\n }\n\n async #passesPolicyGroup(\n applicableRowPolicy: Policy | undefined,\n applicableCellPolicies: Policy[],\n authData: JWTPayload | undefined,\n rowQuery: Query<string, Schema>,\n ) {\n if (!(await this.#passesPolicy(applicableRowPolicy, authData, rowQuery))) {\n return false;\n }\n\n for (const policy of applicableCellPolicies) {\n if (!(await this.#passesPolicy(policy, authData, rowQuery))) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Defaults to *false* if the policy is empty. At least one rule has to pass\n * for the policy to pass.\n */\n #passesPolicy(\n policy: Policy | undefined,\n authData: JWTPayload | undefined,\n rowQuery: Query<string, Schema>,\n ): MaybePromise<boolean> {\n if (policy === undefined) {\n return false;\n }\n if (policy.length === 0) {\n return false;\n }\n let rowQueryAst = asQueryInternals(rowQuery).ast;\n rowQueryAst = bindStaticParameters(\n {\n ...rowQueryAst,\n where: updateWhere(rowQueryAst.where, policy),\n },\n {\n authData: authData as Record<string, JSONValue>,\n preMutationRow: undefined,\n },\n );\n\n // call the compiler directly\n // run the sql against upstream.\n // remove the collecting into json? just need to know if a row comes back.\n\n const input = buildPipeline(rowQueryAst, this.#builderDelegate, 'query-id');\n try {\n const res = input.fetch({});\n for (const _ of res) {\n // if any row is returned at all, the\n // rule passes.\n return true;\n }\n } finally {\n input.destroy();\n }\n\n // no rows returned by any rules? The policy fails.\n return false;\n }\n}\n\nfunction updateWhere(where: Condition | undefined, policy: Policy) {\n assert(where, 'A where condition must exist for RowQuery');\n\n return simplifyCondition({\n type: 'and',\n conditions: [\n where,\n {\n type: 'or',\n conditions: policy.map(([action, rule]) => {\n assert(action, 'action must be defined in policy');\n return rule;\n }),\n },\n ],\n });\n}\n\ntype ActionOpMap = {\n insert: InsertOp;\n update: UpdateOp;\n delete: DeleteOp;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"write-authorizer.js","names":["v.parse"],"sources":["../../../../../zero-cache/src/auth/write-authorizer.ts"],"sourcesContent":["import type {SQLQuery} from '@databases/sql';\nimport type {MaybePromise} from '@opentelemetry/resources';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {JWTPayload} from 'jose';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {JSONValue, ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {Condition} from '../../../zero-protocol/src/ast.ts';\nimport type {\n CRUDOp,\n DeleteOp,\n InsertOp,\n UpdateOp,\n UpsertOp,\n} from '../../../zero-protocol/src/mutation.ts';\nimport {\n primaryKeyValueSchema,\n type PrimaryKeyValue,\n} from '../../../zero-protocol/src/primary-key.ts';\nimport type {Policy} from '../../../zero-schema/src/compiled-permissions.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {BuilderDelegate} from '../../../zql/src/builder/builder.ts';\nimport {\n bindStaticParameters,\n buildPipeline,\n} from '../../../zql/src/builder/builder.ts';\nimport {\n makeSourceChangeAdd,\n makeSourceChangeEdit,\n makeSourceChangeRemove,\n} from '../../../zql/src/ivm/source.ts';\nimport {consume} from '../../../zql/src/ivm/stream.ts';\nimport {simplifyCondition} from '../../../zql/src/query/expression.ts';\nimport {asQueryInternals} from '../../../zql/src/query/query-internals.ts';\nimport type {Query} from '../../../zql/src/query/query.ts';\nimport {newStaticQuery} from '../../../zql/src/query/static-query.ts';\nimport type {\n ClientGroupStorage,\n DatabaseStorage,\n} from '../../../zqlite/src/database-storage.ts';\nimport type {Database} from '../../../zqlite/src/db.ts';\nimport {compile, sql} from '../../../zqlite/src/internal/sql.ts';\nimport {\n fromSQLiteTypes,\n TableSource,\n} from '../../../zqlite/src/table-source.ts';\nimport type {LogConfig, ZeroConfig} from '../config/zero-config.ts';\nimport {computeZqlSpecs} from '../db/lite-tables.ts';\nimport type {LiteAndZqlSpec} from '../db/specs.ts';\nimport {StatementRunner} from '../db/statements.ts';\nimport {mapLiteDataTypeToZqlSchemaValue} from '../types/lite.ts';\nimport {\n getSchema,\n reloadPermissionsIfChanged,\n type LoadedPermissions,\n} from './load-permissions.ts';\n\ntype Phase = 'preMutation' | 'postMutation';\n\nexport interface WriteAuthorizer {\n canPreMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ): Promise<boolean>;\n canPostMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ): Promise<boolean>;\n reloadPermissions(): void;\n normalizeOps(ops: CRUDOp[]): Exclude<CRUDOp, UpsertOp>[];\n\n /**\n * Validates that all table names in the operations exist in the schema.\n * @throws Error if any table name is invalid\n */\n validateTableNames(ops: CRUDOp[]): void;\n}\n\nexport class WriteAuthorizerImpl implements WriteAuthorizer {\n readonly #schema: Schema;\n readonly #replica: Database;\n readonly #builderDelegate: BuilderDelegate;\n readonly #tableSpecs: Map<string, LiteAndZqlSpec>;\n readonly #tables = new Map<string, TableSource>();\n readonly #statementRunner: StatementRunner;\n readonly #lc: LogContext;\n readonly #appID: string;\n readonly #logConfig: LogConfig;\n readonly #cgStorage: ClientGroupStorage;\n readonly #config: ZeroConfig;\n\n #loadedPermissions: LoadedPermissions | null = null;\n\n constructor(\n lc: LogContext,\n config: ZeroConfig,\n replica: Database,\n appID: string,\n cgID: string,\n writeAuthzStorage: DatabaseStorage,\n ) {\n this.#appID = appID;\n this.#config = config;\n this.#lc = lc.withContext('class', 'WriteAuthorizerImpl');\n this.#logConfig = config.log;\n this.#schema = getSchema(this.#lc, replica);\n this.#replica = replica;\n this.#cgStorage = writeAuthzStorage.createClientGroupStorage(cgID);\n this.#builderDelegate = {\n disableCorrelatedPredicatePushdown:\n config.enableCorrelatedPredicatePushdown === false,\n getSource: name => this.#getSource(name),\n createStorage: () => this.#cgStorage.createStorage(),\n decorateSourceInput: input => input,\n decorateInput: input => input,\n addEdge() {},\n decorateFilterInput: input => input,\n };\n this.#tableSpecs = computeZqlSpecs(this.#lc, replica, {\n includeBackfillingColumns: false,\n });\n this.#statementRunner = new StatementRunner(replica);\n this.reloadPermissions();\n }\n\n reloadPermissions() {\n this.#loadedPermissions = reloadPermissionsIfChanged(\n this.#lc,\n this.#statementRunner,\n this.#appID,\n this.#loadedPermissions,\n this.#config,\n ).permissions;\n }\n\n destroy() {\n this.#cgStorage.destroy();\n }\n\n async canPreMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ) {\n for (const op of ops) {\n switch (op.op) {\n case 'insert':\n // insert does not run pre-mutation checks\n break;\n case 'update':\n if (!(await this.#canUpdate('preMutation', authData, op))) {\n return false;\n }\n break;\n case 'delete':\n if (!(await this.#canDelete('preMutation', authData, op))) {\n return false;\n }\n break;\n }\n }\n return true;\n }\n\n async canPostMutation(\n authData: JWTPayload | undefined,\n ops: Exclude<CRUDOp, UpsertOp>[],\n ) {\n this.#statementRunner.beginConcurrent();\n let opError: unknown;\n try {\n for (const op of ops) {\n const source = this.#getSource(op.tableName);\n switch (op.op) {\n case 'insert': {\n consume(source.push(makeSourceChangeAdd(op.value)));\n break;\n }\n // TODO(mlaw): what if someone updates the same thing twice?\n // TODO(aa): It seems like it will just work? source.push()\n // is going to push the row into the table source, and then the\n // next requirePreMutationRow will just return the row that was\n // pushed in.\n case 'update': {\n consume(\n source.push(\n makeSourceChangeEdit(op.value, this.#requirePreMutationRow(op)),\n ),\n );\n break;\n }\n case 'delete': {\n consume(\n source.push(\n makeSourceChangeRemove(this.#requirePreMutationRow(op)),\n ),\n );\n break;\n }\n }\n }\n\n for (const op of ops) {\n switch (op.op) {\n case 'insert':\n if (!(await this.#canInsert('postMutation', authData, op))) {\n return false;\n }\n break;\n case 'update':\n if (!(await this.#canUpdate('postMutation', authData, op))) {\n return false;\n }\n break;\n case 'delete':\n // delete does not run post-mutation checks.\n break;\n }\n }\n } catch (e) {\n opError = e;\n throw e;\n } finally {\n try {\n this.#statementRunner.rollback();\n } catch (rollbackError) {\n if (opError !== undefined) {\n const combinedError = new Error(\n `canPostMutation failed and rollback also failed: operation error = ${String(opError)}; rollback error = ${String(rollbackError)}`,\n );\n combinedError.cause = opError;\n throw combinedError;\n }\n throw rollbackError;\n }\n }\n\n return true;\n }\n\n normalizeOps(ops: CRUDOp[]): Exclude<CRUDOp, UpsertOp>[] {\n return ops.map(op => {\n if (op.op === 'upsert') {\n const preMutationRow = this.#getPreMutationRow(op);\n if (preMutationRow) {\n return {\n op: 'update',\n tableName: op.tableName,\n primaryKey: op.primaryKey,\n value: op.value,\n };\n }\n return {\n op: 'insert',\n tableName: op.tableName,\n primaryKey: op.primaryKey,\n value: op.value,\n };\n }\n return op;\n });\n }\n\n validateTableNames(ops: CRUDOp[]): void {\n for (const op of ops) {\n if (!this.#tableSpecs.has(op.tableName)) {\n throw new Error(`Table '${op.tableName}' is not a valid table.`);\n }\n }\n }\n\n #canInsert(phase: Phase, authData: JWTPayload | undefined, op: InsertOp) {\n return this.#timedCanDo(phase, 'insert', authData, op);\n }\n\n #canUpdate(phase: Phase, authData: JWTPayload | undefined, op: UpdateOp) {\n return this.#timedCanDo(phase, 'update', authData, op);\n }\n\n #canDelete(phase: Phase, authData: JWTPayload | undefined, op: DeleteOp) {\n return this.#timedCanDo(phase, 'delete', authData, op);\n }\n\n /**\n * Gets schema-defined primary key and validates that operation contains required PK values.\n *\n * @returns Record where keys are column names and values are client-provided values\n * @throws Error if operation value is missing required primary key columns\n */\n #getPrimaryKey(\n tableName: string,\n opValue: Record<string, ReadonlyJSONValue | undefined>,\n ): Record<string, ReadonlyJSONValue> {\n const tableSpec = this.#tableSpecs.get(tableName);\n if (!tableSpec) {\n throw new Error(`Table ${tableName} not found`);\n }\n const columns = tableSpec.tableSpec.primaryKey;\n\n // Extract primary key values from operation value and validate they exist\n const values: Record<string, ReadonlyJSONValue> = {};\n for (const col of columns) {\n const val = opValue[col];\n if (val === undefined) {\n throw new Error(\n `Primary key column '${col}' is missing from operation value for table ${tableName}`,\n );\n }\n values[col] = val;\n }\n\n return values;\n }\n\n #getSource(tableName: string) {\n let source = this.#tables.get(tableName);\n if (source) {\n return source;\n }\n const tableSpec = this.#tableSpecs.get(tableName);\n if (!tableSpec) {\n throw new Error(`Table ${tableName} not found`);\n }\n const {columns, primaryKey} = tableSpec.tableSpec;\n assert(\n primaryKey.length,\n () => `Table ${tableName} must have a primary key`,\n );\n source = new TableSource(\n this.#lc,\n this.#logConfig,\n this.#replica,\n tableName,\n Object.fromEntries(\n Object.entries(columns).map(([name, {dataType}]) => [\n name,\n mapLiteDataTypeToZqlSchemaValue(dataType),\n ]),\n ),\n [primaryKey[0], ...primaryKey.slice(1)],\n );\n this.#tables.set(tableName, source);\n\n return source;\n }\n\n async #timedCanDo<A extends keyof ActionOpMap>(\n phase: Phase,\n action: A,\n authData: JWTPayload | undefined,\n op: ActionOpMap[A],\n ) {\n const start = performance.now();\n try {\n const ret = await this.#canDo(phase, action, authData, op);\n return ret;\n } finally {\n this.#lc.info?.(\n 'action:',\n action,\n 'duration:',\n performance.now() - start,\n 'tableName:',\n op.tableName,\n 'primaryKey:',\n op.primaryKey,\n );\n }\n }\n\n /**\n * Evaluation order is from static to dynamic, broad to specific.\n * table -> column -> row -> cell.\n *\n * If any step fails, the entire operation is denied.\n *\n * That is, table rules supersede column rules, which supersede row rules,\n *\n * All steps must allow for the operation to be allowed.\n */\n async #canDo<A extends keyof ActionOpMap>(\n phase: Phase,\n action: A,\n authData: JWTPayload | undefined,\n op: ActionOpMap[A],\n ) {\n const rules = must(this.#loadedPermissions)?.permissions?.tables?.[\n op.tableName\n ];\n const rowPolicies = rules?.row;\n let rowQuery = newStaticQuery(this.#schema, op.tableName);\n\n const primaryKeyValues = this.#getPrimaryKey(op.tableName, op.value);\n\n for (const pk in primaryKeyValues) {\n rowQuery = rowQuery.where(pk, '=', primaryKeyValues[pk]);\n }\n\n let applicableRowPolicy: Policy | undefined;\n switch (action) {\n case 'insert':\n if (phase === 'postMutation') {\n applicableRowPolicy = rowPolicies?.insert;\n }\n break;\n case 'update':\n if (phase === 'preMutation') {\n applicableRowPolicy = rowPolicies?.update?.preMutation;\n } else if (phase === 'postMutation') {\n applicableRowPolicy = rowPolicies?.update?.postMutation;\n }\n break;\n case 'delete':\n if (phase === 'preMutation') {\n applicableRowPolicy = rowPolicies?.delete;\n }\n break;\n }\n\n const cellPolicies = rules?.cell;\n const applicableCellPolicies: Policy[] = [];\n if (cellPolicies) {\n for (const [column, policy] of Object.entries(cellPolicies)) {\n if (action === 'update' && op.value[column] === undefined) {\n // If the cell is not being updated, we do not need to check\n // the cell rules.\n continue;\n }\n switch (action) {\n case 'insert':\n if (policy.insert && phase === 'postMutation') {\n applicableCellPolicies.push(policy.insert);\n }\n break;\n case 'update':\n if (phase === 'preMutation' && policy.update?.preMutation) {\n applicableCellPolicies.push(policy.update.preMutation);\n }\n if (phase === 'postMutation' && policy.update?.postMutation) {\n applicableCellPolicies.push(policy.update.postMutation);\n }\n break;\n case 'delete':\n if (policy.delete && phase === 'preMutation') {\n applicableCellPolicies.push(policy.delete);\n }\n break;\n }\n }\n }\n\n if (\n !(await this.#passesPolicyGroup(\n applicableRowPolicy,\n applicableCellPolicies,\n authData,\n rowQuery,\n ))\n ) {\n // `op.value` is the row being written and `authData` is the decoded\n // JWT payload, so neither can go into the log. Column names and policy\n // counts are enough to debug a failed permission check.\n this.#lc.warn?.('Permission check failed', {\n action,\n phase,\n tableName: op.tableName,\n columns: Object.keys(op.value),\n rowPolicy: applicableRowPolicy !== undefined,\n cellPolicyCount: applicableCellPolicies.length,\n });\n return false;\n }\n\n return true;\n }\n\n #getPreMutationRow(op: UpsertOp | UpdateOp | DeleteOp) {\n const {value} = op;\n\n const primaryKeyValues = this.#getPrimaryKey(op.tableName, value);\n\n const spec = this.#tableSpecs.get(op.tableName);\n if (!spec) {\n throw new Error(`Table ${op.tableName} not found`);\n }\n\n const conditions: SQLQuery[] = [];\n const values: PrimaryKeyValue[] = [];\n for (const pk in primaryKeyValues) {\n conditions.push(sql`${sql.ident(pk)}=?`);\n values.push(v.parse(primaryKeyValues[pk], primaryKeyValueSchema));\n }\n\n const ret = this.#statementRunner.get(\n compile(\n sql`SELECT ${sql.join(\n Object.keys(spec.zqlSpec).map(c => sql.ident(c)),\n sql`,`,\n )} FROM ${sql.ident(op.tableName)} WHERE ${sql.join(\n conditions,\n sql` AND `,\n )}`,\n ),\n ...values,\n );\n if (ret === undefined) {\n return ret;\n }\n return fromSQLiteTypes(spec.zqlSpec, ret, op.tableName);\n }\n\n #requirePreMutationRow(op: UpdateOp | DeleteOp) {\n const ret = this.#getPreMutationRow(op);\n assert(\n ret !== undefined,\n () => `Pre-mutation row not found for ${JSON.stringify(op.value)}`,\n );\n return ret;\n }\n\n async #passesPolicyGroup(\n applicableRowPolicy: Policy | undefined,\n applicableCellPolicies: Policy[],\n authData: JWTPayload | undefined,\n rowQuery: Query<string, Schema>,\n ) {\n if (!(await this.#passesPolicy(applicableRowPolicy, authData, rowQuery))) {\n return false;\n }\n\n for (const policy of applicableCellPolicies) {\n if (!(await this.#passesPolicy(policy, authData, rowQuery))) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Defaults to *false* if the policy is empty. At least one rule has to pass\n * for the policy to pass.\n */\n #passesPolicy(\n policy: Policy | undefined,\n authData: JWTPayload | undefined,\n rowQuery: Query<string, Schema>,\n ): MaybePromise<boolean> {\n if (policy === undefined) {\n return false;\n }\n if (policy.length === 0) {\n return false;\n }\n let rowQueryAst = asQueryInternals(rowQuery).ast;\n rowQueryAst = bindStaticParameters(\n {\n ...rowQueryAst,\n where: updateWhere(rowQueryAst.where, policy),\n },\n {\n authData: authData as Record<string, JSONValue>,\n preMutationRow: undefined,\n },\n );\n\n // call the compiler directly\n // run the sql against upstream.\n // remove the collecting into json? just need to know if a row comes back.\n\n const input = buildPipeline(rowQueryAst, this.#builderDelegate, 'query-id');\n try {\n const res = input.fetch({});\n for (const _ of res) {\n // if any row is returned at all, the\n // rule passes.\n return true;\n }\n } finally {\n input.destroy();\n }\n\n // no rows returned by any rules? The policy fails.\n return false;\n }\n}\n\nfunction updateWhere(where: Condition | undefined, policy: Policy) {\n assert(where, 'A where condition must exist for RowQuery');\n\n return simplifyCondition({\n type: 'and',\n conditions: [\n where,\n {\n type: 'or',\n conditions: policy.map(([action, rule]) => {\n assert(action, 'action must be defined in policy');\n return rule;\n }),\n },\n ],\n });\n}\n\ntype ActionOpMap = {\n insert: InsertOp;\n update: UpdateOp;\n delete: DeleteOp;\n};\n"],"mappings":"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"}
@@ -32,6 +32,6 @@ function getPreferredIp(interfaces, preferredPrefixes) {
32
32
  return sorted[0].family === "IPv4" ? sorted[0].address : `[${sorted[0].address}]`;
33
33
  }
34
34
  //#endregion
35
- export { DEFAULT_PREFERRED_PREFIXES, getHostIp };
35
+ export { DEFAULT_PREFERRED_PREFIXES, getHostIp, getPreferredIp };
36
36
 
37
37
  //# sourceMappingURL=network.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"network.js","names":[],"sources":["../../../../../zero-cache/src/config/network.ts"],"sourcesContent":["import {networkInterfaces, type NetworkInterfaceInfo} from 'os';\nimport type {LogContext} from '@rocicorp/logger';\nimport {isIPv6, isPrivate, isReserved} from 'is-in-subnet';\n\nexport const DEFAULT_PREFERRED_PREFIXES = [\n 'eth', // linux\n 'en', // macbooks\n] as const;\n\nexport function getHostIp(\n lc?: LogContext,\n preferredPrefixes: readonly string[] = DEFAULT_PREFERRED_PREFIXES,\n) {\n const interfaces = networkInterfaces();\n const preferred = getPreferredIp(interfaces, preferredPrefixes);\n lc?.info?.(`network interfaces`, {preferred, interfaces});\n return preferred;\n}\n\nexport function getPreferredIp(\n interfaces: NodeJS.Dict<NetworkInterfaceInfo[]>,\n preferredPrefixes: readonly string[],\n) {\n const rank = ({name}: {name: string}) => {\n for (let i = 0; i < preferredPrefixes.length; i++) {\n if (name.startsWith(preferredPrefixes[i])) {\n return i;\n }\n }\n return Number.MAX_SAFE_INTEGER;\n };\n\n const sorted = Object.entries(interfaces)\n .flatMap(([name, infos]) => (infos ?? []).map(info => ({...info, name})))\n .sort((a, b) => {\n const ap =\n (isIPv6(a.address) && isPrivate(a.address)) || isReserved(a.address);\n const bp =\n (isIPv6(b.address) && isPrivate(b.address)) || isReserved(b.address);\n if (ap !== bp) {\n // Avoid link-local, site-local, or otherwise private addresses\n return ap ? 1 : -1;\n }\n if (a.internal !== b.internal) {\n // Prefer non-internal addresses.\n return a.internal ? 1 : -1;\n }\n if (a.family !== b.family) {\n // Prefer IPv4.\n return a.family === 'IPv4' ? -1 : 1;\n }\n const rankA = rank(a);\n const rankB = rank(b);\n if (rankA !== rankB) {\n return rankA - rankB;\n }\n // arbitrary\n return a.address.localeCompare(b.address);\n });\n\n // Enclose IPv6 addresses in square brackets for use in a URL.\n const preferred =\n sorted[0].family === 'IPv4' ? sorted[0].address : `[${sorted[0].address}]`;\n return preferred;\n}\n"],"mappings":";;;AAIA,IAAa,6BAA6B,CACxC,OACA,IACF;AAEA,SAAgB,UACd,IACA,oBAAuC,4BACvC;CACA,MAAM,aAAa,kBAAkB;CACrC,MAAM,YAAY,eAAe,YAAY,iBAAiB;CAC9D,IAAI,OAAO,sBAAsB;EAAC;EAAW;CAAU,CAAC;CACxD,OAAO;AACT;AAEA,SAAgB,eACd,YACA,mBACA;CACA,MAAM,QAAQ,EAAC,WAA0B;EACvC,KAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAC5C,IAAI,KAAK,WAAW,kBAAkB,EAAE,GACtC,OAAO;EAGX,OAAO,OAAO;CAChB;CAEA,MAAM,SAAS,OAAO,QAAQ,UAAU,EACrC,SAAS,CAAC,MAAM,YAAY,SAAS,CAAC,GAAG,KAAI,UAAS;EAAC,GAAG;EAAM;CAAI,EAAE,CAAC,EACvE,MAAM,GAAG,MAAM;EACd,MAAM,KACH,OAAO,EAAE,OAAO,KAAK,UAAU,EAAE,OAAO,KAAM,WAAW,EAAE,OAAO;EAGrE,IAAI,QADD,OAAO,EAAE,OAAO,KAAK,UAAU,EAAE,OAAO,KAAM,WAAW,EAAE,OAAO,IAGnE,OAAO,KAAK,IAAI;EAElB,IAAI,EAAE,aAAa,EAAE,UAEnB,OAAO,EAAE,WAAW,IAAI;EAE1B,IAAI,EAAE,WAAW,EAAE,QAEjB,OAAO,EAAE,WAAW,SAAS,KAAK;EAEpC,MAAM,QAAQ,KAAK,CAAC;EACpB,MAAM,QAAQ,KAAK,CAAC;EACpB,IAAI,UAAU,OACZ,OAAO,QAAQ;EAGjB,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO;CAC1C,CAAC;CAKH,OADE,OAAO,GAAG,WAAW,SAAS,OAAO,GAAG,UAAU,IAAI,OAAO,GAAG,QAAQ;AAE5E"}
1
+ {"version":3,"file":"network.js","names":[],"sources":["../../../../../zero-cache/src/config/network.ts"],"sourcesContent":["import {networkInterfaces, type NetworkInterfaceInfo} from 'os';\nimport type {LogContext} from '@rocicorp/logger';\nimport {isIPv6, isPrivate, isReserved} from 'is-in-subnet';\n\nexport const DEFAULT_PREFERRED_PREFIXES = [\n 'eth', // linux\n 'en', // macbooks\n] as const;\n\nexport function getHostIp(\n lc?: LogContext,\n preferredPrefixes: readonly string[] = DEFAULT_PREFERRED_PREFIXES,\n) {\n const interfaces = networkInterfaces();\n const preferred = getPreferredIp(interfaces, preferredPrefixes);\n lc?.info?.(`network interfaces`, {preferred, interfaces});\n return preferred;\n}\n\nexport function getPreferredIp(\n interfaces: NodeJS.Dict<NetworkInterfaceInfo[]>,\n preferredPrefixes: readonly string[],\n) {\n const rank = ({name}: {name: string}) => {\n for (let i = 0; i < preferredPrefixes.length; i++) {\n if (name.startsWith(preferredPrefixes[i])) {\n return i;\n }\n }\n return Number.MAX_SAFE_INTEGER;\n };\n\n const sorted = Object.entries(interfaces)\n .flatMap(([name, infos]) => (infos ?? []).map(info => ({...info, name})))\n .sort((a, b) => {\n const ap =\n (isIPv6(a.address) && isPrivate(a.address)) || isReserved(a.address);\n const bp =\n (isIPv6(b.address) && isPrivate(b.address)) || isReserved(b.address);\n if (ap !== bp) {\n // Avoid link-local, site-local, or otherwise private addresses\n return ap ? 1 : -1;\n }\n if (a.internal !== b.internal) {\n // Prefer non-internal addresses.\n return a.internal ? 1 : -1;\n }\n if (a.family !== b.family) {\n // Prefer IPv4.\n return a.family === 'IPv4' ? -1 : 1;\n }\n const rankA = rank(a);\n const rankB = rank(b);\n if (rankA !== rankB) {\n return rankA - rankB;\n }\n // arbitrary\n return a.address.localeCompare(b.address);\n });\n\n // Enclose IPv6 addresses in square brackets for use in a URL.\n const preferred =\n sorted[0].family === 'IPv4' ? sorted[0].address : `[${sorted[0].address}]`;\n return preferred;\n}\n"],"mappings":";;;AAIA,IAAa,6BAA6B,CACxC,OACA,IACF;AAEA,SAAgB,UACd,IACA,oBAAuC,4BACvC;CACA,MAAM,aAAa,kBAAkB;CACrC,MAAM,YAAY,eAAe,YAAY,iBAAiB;CAC9D,IAAI,OAAO,sBAAsB;EAAC;EAAW;CAAU,CAAC;CACxD,OAAO;AACT;AAEA,SAAgB,eACd,YACA,mBACA;CACA,MAAM,QAAQ,EAAC,WAA0B;EACvC,KAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAC5C,IAAI,KAAK,WAAW,kBAAkB,EAAE,GACtC,OAAO;EAGX,OAAO,OAAO;CAChB;CAEA,MAAM,SAAS,OAAO,QAAQ,UAAU,CAAC,CACtC,SAAS,CAAC,MAAM,YAAY,SAAS,CAAC,EAAA,CAAG,KAAI,UAAS;EAAC,GAAG;EAAM;CAAI,EAAE,CAAC,CAAC,CACxE,MAAM,GAAG,MAAM;EACd,MAAM,KACH,OAAO,EAAE,OAAO,KAAK,UAAU,EAAE,OAAO,KAAM,WAAW,EAAE,OAAO;EAGrE,IAAI,QADD,OAAO,EAAE,OAAO,KAAK,UAAU,EAAE,OAAO,KAAM,WAAW,EAAE,OAAO,IAGnE,OAAO,KAAK,IAAI;EAElB,IAAI,EAAE,aAAa,EAAE,UAEnB,OAAO,EAAE,WAAW,IAAI;EAE1B,IAAI,EAAE,WAAW,EAAE,QAEjB,OAAO,EAAE,WAAW,SAAS,KAAK;EAEpC,MAAM,QAAQ,KAAK,CAAC;EACpB,MAAM,QAAQ,KAAK,CAAC;EACpB,IAAI,UAAU,OACZ,OAAO,QAAQ;EAGjB,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO;CAC1C,CAAC;CAKH,OADE,OAAO,EAAE,CAAC,WAAW,SAAS,OAAO,EAAE,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC,QAAQ;AAE5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"server-context.js","names":[],"sources":["../../../../../zero-cache/src/config/server-context.ts"],"sourcesContent":["import {hostname} from 'node:os';\nimport {getHostIp} from './network.ts';\nimport type {NormalizedZeroConfig} from './normalize.ts';\n\nexport type ServerContext = {\n appID: string;\n taskID: string;\n hostIP: string;\n hostname: string;\n timestamp: string;\n\n [platformVar: string]: string | undefined;\n};\n\n/**\n * Runtime and environment information useful for recording and identifying\n * the origin of certain actions such as initial sync and logical replication\n * takeovers.\n */\nexport function getServerContext(config: NormalizedZeroConfig): ServerContext {\n const context: ServerContext = {\n appID: config.app.id,\n taskID: config.taskID,\n hostIP: getHostIp(),\n hostname: hostname(),\n timestamp: new Date().toISOString(),\n\n // Platform-specific environment variables\n flyAppName: process.env.FLY_APP_NAME,\n flyMachineID: process.env.FLY_MACHINE_ID,\n\n railwayProjectID: process.env.RAILWAY_PROJECT_ID,\n railwayProjectName: process.env.RAILWAY_PROJECT_NAME,\n railwayEnvironmentID: process.env.RAILWAY_ENVIRONMENT_ID,\n railwayEnvironmentName: process.env.RAILWAY_ENVIRONMENT_NAME,\n railwayServiceID: process.env.RAILWAY_SERVICE_ID,\n railwayServiceName: process.env.RAILWAY_SERVICE_NAME,\n railwayDeploymentID: process.env.RAILWAY_DEPLOYMENT_ID,\n\n gcpProject:\n process.env.GOOGLE_CLOUD_PROJECT ??\n process.env.GCP_PROJECT ??\n process.env.GCLOUD_PROJECT,\n\n coolifyDomainName: process.env.COOLIFY_FQDN,\n coolifyContainerName: process.env.COOLIFY_CONTAINER_NAME,\n\n azureEnvName: process.env.AZURE_ENV_NAME,\n };\n\n // Remove keys with undefined values\n return Object.fromEntries(\n Object.entries(context).filter(([_, v]) => v !== undefined),\n ) as ServerContext;\n}\n"],"mappings":";;;;;;;;AAmBA,SAAgB,iBAAiB,QAA6C;CAC5E,MAAM,UAAyB;EAC7B,OAAO,OAAO,IAAI;EAClB,QAAQ,OAAO;EACf,QAAQ,UAAU;EAClB,UAAU,SAAS;EACnB,4BAAW,IAAI,KAAK,GAAE,YAAY;EAGlC,YAAY,QAAQ,IAAI;EACxB,cAAc,QAAQ,IAAI;EAE1B,kBAAkB,QAAQ,IAAI;EAC9B,oBAAoB,QAAQ,IAAI;EAChC,sBAAsB,QAAQ,IAAI;EAClC,wBAAwB,QAAQ,IAAI;EACpC,kBAAkB,QAAQ,IAAI;EAC9B,oBAAoB,QAAQ,IAAI;EAChC,qBAAqB,QAAQ,IAAI;EAEjC,YACE,QAAQ,IAAI,wBACZ,QAAQ,IAAI,eACZ,QAAQ,IAAI;EAEd,mBAAmB,QAAQ,IAAI;EAC/B,sBAAsB,QAAQ,IAAI;EAElC,cAAc,QAAQ,IAAI;CAC5B;CAGA,OAAO,OAAO,YACZ,OAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,GAAG,OAAO,MAAM,KAAA,CAAS,CAC5D;AACF"}
1
+ {"version":3,"file":"server-context.js","names":[],"sources":["../../../../../zero-cache/src/config/server-context.ts"],"sourcesContent":["import {hostname} from 'node:os';\nimport {getHostIp} from './network.ts';\nimport type {NormalizedZeroConfig} from './normalize.ts';\n\nexport type ServerContext = {\n appID: string;\n taskID: string;\n hostIP: string;\n hostname: string;\n timestamp: string;\n\n [platformVar: string]: string | undefined;\n};\n\n/**\n * Runtime and environment information useful for recording and identifying\n * the origin of certain actions such as initial sync and logical replication\n * takeovers.\n */\nexport function getServerContext(config: NormalizedZeroConfig): ServerContext {\n const context: ServerContext = {\n appID: config.app.id,\n taskID: config.taskID,\n hostIP: getHostIp(),\n hostname: hostname(),\n timestamp: new Date().toISOString(),\n\n // Platform-specific environment variables\n flyAppName: process.env.FLY_APP_NAME,\n flyMachineID: process.env.FLY_MACHINE_ID,\n\n railwayProjectID: process.env.RAILWAY_PROJECT_ID,\n railwayProjectName: process.env.RAILWAY_PROJECT_NAME,\n railwayEnvironmentID: process.env.RAILWAY_ENVIRONMENT_ID,\n railwayEnvironmentName: process.env.RAILWAY_ENVIRONMENT_NAME,\n railwayServiceID: process.env.RAILWAY_SERVICE_ID,\n railwayServiceName: process.env.RAILWAY_SERVICE_NAME,\n railwayDeploymentID: process.env.RAILWAY_DEPLOYMENT_ID,\n\n gcpProject:\n process.env.GOOGLE_CLOUD_PROJECT ??\n process.env.GCP_PROJECT ??\n process.env.GCLOUD_PROJECT,\n\n coolifyDomainName: process.env.COOLIFY_FQDN,\n coolifyContainerName: process.env.COOLIFY_CONTAINER_NAME,\n\n azureEnvName: process.env.AZURE_ENV_NAME,\n };\n\n // Remove keys with undefined values\n return Object.fromEntries(\n Object.entries(context).filter(([_, v]) => v !== undefined),\n ) as ServerContext;\n}\n"],"mappings":";;;;;;;;AAmBA,SAAgB,iBAAiB,QAA6C;CAC5E,MAAM,UAAyB;EAC7B,OAAO,OAAO,IAAI;EAClB,QAAQ,OAAO;EACf,QAAQ,UAAU;EAClB,UAAU,SAAS;EACnB,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;EAGlC,YAAY,QAAQ,IAAI;EACxB,cAAc,QAAQ,IAAI;EAE1B,kBAAkB,QAAQ,IAAI;EAC9B,oBAAoB,QAAQ,IAAI;EAChC,sBAAsB,QAAQ,IAAI;EAClC,wBAAwB,QAAQ,IAAI;EACpC,kBAAkB,QAAQ,IAAI;EAC9B,oBAAoB,QAAQ,IAAI;EAChC,qBAAqB,QAAQ,IAAI;EAEjC,YACE,QAAQ,IAAI,wBACZ,QAAQ,IAAI,eACZ,QAAQ,IAAI;EAEd,mBAAmB,QAAQ,IAAI;EAC/B,sBAAsB,QAAQ,IAAI;EAElC,cAAc,QAAQ,IAAI;CAC5B;CAGA,OAAO,OAAO,YACZ,OAAO,QAAQ,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,OAAO,MAAM,KAAA,CAAS,CAC5D;AACF"}
@@ -749,6 +749,11 @@ export declare const zeroOptions: {
749
749
  type: v.Optional<string>;
750
750
  desc: string[];
751
751
  };
752
+ operatorStorageHeapProportion: {
753
+ type: v.Type<number>;
754
+ desc: string[];
755
+ hidden: boolean;
756
+ };
752
757
  initialSync: {
753
758
  tableCopyWorkers: {
754
759
  type: v.Type<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"zero-config.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/config/zero-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zero-config.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/config/zero-config.ts"],"names":[],"mappings":"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"}
@@ -1081,7 +1081,7 @@ var zeroOptions = {
1081
1081
  ]
1082
1082
  },
1083
1083
  websocketMaxPayloadBytes: {
1084
- type: valita_exports.number().optional(() => 10 * 1024 * 1024),
1084
+ type: valita_exports.number().optional(() => 10485760),
1085
1085
  desc: [
1086
1086
  "Maximum size of incoming WebSocket messages in bytes.",
1087
1087
  "",
@@ -1336,7 +1336,7 @@ var zeroOptions = {
1336
1336
  ]
1337
1337
  },
1338
1338
  multipartSize: {
1339
- type: valita_exports.number().optional(() => 16 * 1024 * 1024),
1339
+ type: valita_exports.number().optional(() => 16777216),
1340
1340
  desc: [
1341
1341
  `The size of each part when uploading or downloading the snapshot with`,
1342
1342
  `{bold --multipart-concurrency}. Note that up to {bold concurrency * size}`,
@@ -1348,6 +1348,17 @@ var zeroOptions = {
1348
1348
  type: valita_exports.string().optional(),
1349
1349
  desc: [`tmp directory for IVM operator storage. Leave unset to use os.tmpdir()`]
1350
1350
  },
1351
+ operatorStorageHeapProportion: {
1352
+ type: valita_exports.number().assert((value) => value >= 0 && value <= 1, "must be between 0 and 1").optional(() => .1),
1353
+ desc: [
1354
+ `The proportion of {bold --max-old-space-size} that the IVM operators`,
1355
+ `of the client groups of one sync worker may keep in memory. Past it,`,
1356
+ `the least recently used operators spill their state to the SQLite`,
1357
+ `operator storage in {bold storageDBTmpDir}. 0 keeps all operator state`,
1358
+ `in SQLite.`
1359
+ ],
1360
+ hidden: true
1361
+ },
1351
1362
  initialSync: {
1352
1363
  tableCopyWorkers: {
1353
1364
  type: valita_exports.number().optional(() => 5),