@rocicorp/zero 1.2.0-canary.12 → 1.2.0-canary.14

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 (122) hide show
  1. package/out/shared/src/sorted-entries.d.ts +2 -0
  2. package/out/shared/src/sorted-entries.d.ts.map +1 -0
  3. package/out/shared/src/sorted-entries.js +9 -0
  4. package/out/shared/src/sorted-entries.js.map +1 -0
  5. package/out/zero/package.js +1 -1
  6. package/out/zero/package.js.map +1 -1
  7. package/out/zero-cache/src/auth/auth.d.ts +8 -26
  8. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  9. package/out/zero-cache/src/auth/auth.js +57 -82
  10. package/out/zero-cache/src/auth/auth.js.map +1 -1
  11. package/out/zero-cache/src/auth/jwt.d.ts +3 -3
  12. package/out/zero-cache/src/auth/jwt.d.ts.map +1 -1
  13. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  14. package/out/zero-cache/src/config/zero-config.d.ts +22 -2
  15. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  16. package/out/zero-cache/src/config/zero-config.js +21 -0
  17. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  18. package/out/zero-cache/src/custom/fetch.d.ts +2 -9
  19. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  20. package/out/zero-cache/src/custom/fetch.js +9 -4
  21. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  22. package/out/zero-cache/src/custom-queries/transform-query.d.ts +20 -9
  23. package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
  24. package/out/zero-cache/src/custom-queries/transform-query.js +71 -37
  25. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  26. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  27. package/out/zero-cache/src/db/transaction-pool.js +3 -0
  28. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  29. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  30. package/out/zero-cache/src/server/change-streamer.js +4 -1
  31. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  32. package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -2
  33. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  34. package/out/zero-cache/src/server/inspector-delegate.js +4 -4
  35. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  36. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  37. package/out/zero-cache/src/server/reaper.js +4 -1
  38. package/out/zero-cache/src/server/reaper.js.map +1 -1
  39. package/out/zero-cache/src/server/runner/run-worker.js +1 -1
  40. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  41. package/out/zero-cache/src/server/syncer.js +34 -11
  42. package/out/zero-cache/src/server/syncer.js.map +1 -1
  43. package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
  44. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  45. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/change-source/pg/change-source.js +4 -3
  47. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  48. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +2 -1
  49. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  50. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +7 -5
  51. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  52. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +3 -3
  53. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  54. package/out/zero-cache/src/services/mutagen/pusher.d.ts +20 -20
  55. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  56. package/out/zero-cache/src/services/mutagen/pusher.js +91 -104
  57. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  58. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +168 -0
  59. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -0
  60. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js +385 -0
  61. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -0
  62. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -3
  63. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  64. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +3 -3
  65. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  66. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +20 -26
  67. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  68. package/out/zero-cache/src/services/view-syncer/view-syncer.js +203 -114
  69. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  70. package/out/zero-cache/src/types/pg-versions.d.ts +3 -0
  71. package/out/zero-cache/src/types/pg-versions.d.ts.map +1 -0
  72. package/out/zero-cache/src/types/pg-versions.js +7 -0
  73. package/out/zero-cache/src/types/pg-versions.js.map +1 -0
  74. package/out/zero-cache/src/workers/connect-params.d.ts +1 -1
  75. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  76. package/out/zero-cache/src/workers/connect-params.js +1 -1
  77. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  78. package/out/zero-cache/src/workers/connection.js +4 -4
  79. package/out/zero-cache/src/workers/connection.js.map +1 -1
  80. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts +2 -1
  81. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  82. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +46 -36
  83. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  84. package/out/zero-cache/src/workers/syncer.d.ts +2 -1
  85. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  86. package/out/zero-cache/src/workers/syncer.js +53 -26
  87. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  88. package/out/zero-client/src/client/connection.d.ts +4 -4
  89. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  90. package/out/zero-client/src/client/connection.js.map +1 -1
  91. package/out/zero-client/src/client/options.d.ts +34 -5
  92. package/out/zero-client/src/client/options.d.ts.map +1 -1
  93. package/out/zero-client/src/client/options.js.map +1 -1
  94. package/out/zero-client/src/client/version.js +1 -1
  95. package/out/zero-client/src/client/zero.d.ts +4 -3
  96. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  97. package/out/zero-client/src/client/zero.js +33 -11
  98. package/out/zero-client/src/client/zero.js.map +1 -1
  99. package/out/zero-protocol/src/change-desired-queries.d.ts +4 -0
  100. package/out/zero-protocol/src/change-desired-queries.d.ts.map +1 -1
  101. package/out/zero-protocol/src/change-desired-queries.js +4 -1
  102. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  103. package/out/zero-protocol/src/connect.d.ts +4 -0
  104. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  105. package/out/zero-protocol/src/connect.js +2 -1
  106. package/out/zero-protocol/src/connect.js.map +1 -1
  107. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  108. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  109. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  110. package/out/zero-protocol/src/push.d.ts +4 -0
  111. package/out/zero-protocol/src/push.d.ts.map +1 -1
  112. package/out/zero-protocol/src/push.js +2 -1
  113. package/out/zero-protocol/src/push.js.map +1 -1
  114. package/out/zero-protocol/src/up.d.ts +3 -0
  115. package/out/zero-protocol/src/up.d.ts.map +1 -1
  116. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  117. package/out/zero-react/src/zero-provider.js +11 -5
  118. package/out/zero-react/src/zero-provider.js.map +1 -1
  119. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  120. package/out/zero-solid/src/use-zero.js +8 -9
  121. package/out/zero-solid/src/use-zero.js.map +1 -1
  122. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export declare function sortedEntries<T extends Record<string, any>>(object: T): [keyof T & string, T[keyof T]][];
2
+ //# sourceMappingURL=sorted-entries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sorted-entries.d.ts","sourceRoot":"","sources":["../../../../shared/src/sorted-entries.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzD,MAAM,EAAE,CAAC,GACR,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAElC"}
@@ -0,0 +1,9 @@
1
+ import { stringCompare } from "./string-compare.js";
2
+ //#region ../shared/src/sorted-entries.ts
3
+ function sortedEntries(object) {
4
+ return Object.entries(object).sort((a, b) => stringCompare(a[0], b[0]));
5
+ }
6
+ //#endregion
7
+ export { sortedEntries };
8
+
9
+ //# sourceMappingURL=sorted-entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sorted-entries.js","names":[],"sources":["../../../../shared/src/sorted-entries.ts"],"sourcesContent":["import {stringCompare} from './string-compare.ts';\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport function sortedEntries<T extends Record<string, any>>(\n object: T,\n): [keyof T & string, T[keyof T]][] {\n return Object.entries(object).sort((a, b) => stringCompare(a[0], b[0]));\n}\n"],"mappings":";;AAGA,SAAgB,cACd,QACkC;AAClC,QAAO,OAAO,QAAQ,OAAO,CAAC,MAAM,GAAG,MAAM,cAAc,EAAE,IAAI,EAAE,GAAG,CAAC"}
@@ -1,6 +1,6 @@
1
1
  var package_default = {
2
2
  name: "@rocicorp/zero",
3
- version: "1.2.0-canary.12",
3
+ version: "1.2.0-canary.14",
4
4
  description: "Zero is a web framework for serverless web development.",
5
5
  author: "Rocicorp, Inc.",
6
6
  repository: {
@@ -1 +1 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.2.0-canary.12\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"license\": \"Apache-2.0\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --type-aware src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.203.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.62.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.203.0\",\n \"@opentelemetry/resources\": \"^2.0.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.0.1\",\n \"@opentelemetry/sdk-node\": \"^0.203.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.0.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^5.4.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.0.15\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.0\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"js-xxhash\": \"^4.0.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.44.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"tsx\": \"^4.21.0\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"4.1.3\",\n \"analyze-query\": \"0.0.0\",\n \"ast-to-zql\": \"0.0.0\",\n \"expo-sqlite\": \">=15\",\n \"replicache\": \"15.2.1\",\n \"shared\": \"0.0.0\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"8.0.3\",\n \"vitest\": \"4.1.3\",\n \"zero-cache\": \"0.0.0\",\n \"zero-client\": \"0.0.0\",\n \"zero-pg\": \"0.0.0\",\n \"zero-protocol\": \"0.0.0\",\n \"zero-react\": \"0.0.0\",\n \"zero-server\": \"0.0.0\",\n \"zero-solid\": \"0.0.0\",\n \"zqlite\": \"0.0.0\"\n },\n \"peerDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"expo-sqlite\": \">=15\"\n },\n \"peerDependenciesMeta\": {\n \"expo-sqlite\": {\n \"optional\": true\n },\n \"@op-engineering/op-sqlite\": {\n \"optional\": true\n }\n },\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"bin\": {\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ]\n}"],"mappings":""}
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.2.0-canary.14\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"license\": \"Apache-2.0\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --type-aware src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.203.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.62.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.203.0\",\n \"@opentelemetry/resources\": \"^2.0.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.0.1\",\n \"@opentelemetry/sdk-node\": \"^0.203.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.0.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^5.4.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.0.15\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.0\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"js-xxhash\": \"^4.0.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.44.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"tsx\": \"^4.21.0\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"4.1.3\",\n \"analyze-query\": \"0.0.0\",\n \"ast-to-zql\": \"0.0.0\",\n \"expo-sqlite\": \">=15\",\n \"replicache\": \"15.2.1\",\n \"shared\": \"0.0.0\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"8.0.3\",\n \"vitest\": \"4.1.3\",\n \"zero-cache\": \"0.0.0\",\n \"zero-client\": \"0.0.0\",\n \"zero-pg\": \"0.0.0\",\n \"zero-protocol\": \"0.0.0\",\n \"zero-react\": \"0.0.0\",\n \"zero-server\": \"0.0.0\",\n \"zero-solid\": \"0.0.0\",\n \"zqlite\": \"0.0.0\"\n },\n \"peerDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"expo-sqlite\": \">=15\"\n },\n \"peerDependenciesMeta\": {\n \"expo-sqlite\": {\n \"optional\": true\n },\n \"@op-engineering/op-sqlite\": {\n \"optional\": true\n }\n },\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"bin\": {\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ]\n}"],"mappings":""}
@@ -1,6 +1,7 @@
1
1
  import type { LogContext } from '@rocicorp/logger';
2
2
  import type { JWTPayload } from 'jose';
3
3
  import { type ErrorBody } from '../../../zero-protocol/src/error.ts';
4
+ import type { PushError } from '../../../zero-protocol/src/push.ts';
4
5
  /** @deprecated JWT auth is deprecated */
5
6
  export type JWTAuth = {
6
7
  readonly type: 'jwt';
@@ -12,34 +13,15 @@ export type OpaqueAuth = {
12
13
  readonly raw: string;
13
14
  };
14
15
  export type Auth = OpaqueAuth | JWTAuth;
15
- export interface AuthSession {
16
- /** Update the auth session with a new userID and token from the client */
17
- update(userID: string, wireAuth: string | undefined): Promise<AuthUpdateResult>;
18
- /** The revision of the auth state */
19
- get revision(): number;
20
- /** The auth state for the session */
21
- get auth(): Auth | undefined;
22
- /** Clear the auth session, removing any stored auth and allowing a new userID to be bound on the next update. */
23
- clear(): void;
24
- }
25
- export type AuthUpdateResult = {
26
- readonly ok: true;
27
- } | {
28
- readonly ok: false;
29
- readonly error: ErrorBody;
30
- };
31
16
  export type ValidateLegacyJWT = (token: string, ctx: {
32
- readonly userID: string;
17
+ readonly userID: string | undefined;
33
18
  }) => Promise<JWTAuth>;
34
- export declare class AuthSessionImpl implements AuthSession {
35
- #private;
36
- readonly id: string;
37
- constructor(lc: LogContext, clientGroupID: string, validateLegacyJWT: ValidateLegacyJWT | undefined);
38
- get auth(): Auth | undefined;
39
- get revision(): number;
40
- clear(): void;
41
- update(userID: string, wireAuth: string | undefined): Promise<AuthUpdateResult>;
42
- }
19
+ export declare function authEquals(a: Auth | undefined, b: Auth | undefined): boolean;
20
+ /**
21
+ * Resolves one auth snapshot transition without binding it to a client group.
22
+ */
23
+ export declare function resolveAuth(lc: LogContext, previousAuth: Auth | undefined, userID: string | undefined, wireAuth: string | undefined, validateLegacyJWT: ValidateLegacyJWT | undefined): Promise<Auth | undefined>;
43
24
  /** @deprecated used only in old JWT validation/rotation auth */
44
25
  export declare function pickToken(lc: LogContext, previousToken: Auth | undefined, newToken: Auth | undefined | null): Auth | undefined;
26
+ export declare function isAuthErrorBody(ex: unknown): ex is ErrorBody | PushError;
45
27
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/auth/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,MAAM,CAAC;AAGrC,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,qCAAqC,CAAC;AAE7C,yCAAyC;AACzC,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE7B,qCAAqC;IACrC,IAAI,QAAQ,IAAI,MAAM,CAAC;IAEvB,qCAAqC;IACrC,IAAI,IAAI,IAAI,IAAI,GAAG,SAAS,CAAC;IAE7B,iHAAiH;IACjH,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,MAAM,gBAAgB,GACxB;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB,GACD;IACE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B,CAAC;AAEN,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAC,KAC3B,OAAO,CAAC,OAAO,CAAC,CAAC;AAgBtB,qBAAa,eAAgB,YAAW,WAAW;;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAQlB,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,iBAAiB,GAAG,SAAS;IAOlD,IAAI,IAAI,IAAI,IAAI,GAAG,SAAS,CAE3B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,KAAK,IAAI,IAAI;IAWP,MAAM,CACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,OAAO,CAAC,gBAAgB,CAAC;CAoF7B;AAED,gEAAgE;AAChE,wBAAgB,SAAS,CACvB,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,IAAI,GAAG,SAAS,EAC/B,QAAQ,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,oBAgFlC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/auth/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,MAAM,CAAC;AAGrC,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oCAAoC,CAAC;AAElE,yCAAyC;AACzC,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC;AAExC,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAC,KACvC,OAAO,CAAC,OAAO,CAAC,CAAC;AAMtB,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,EAAE,CAAC,EAAE,IAAI,GAAG,SAAS,WAQlE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,YAAY,EAAE,IAAI,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,GAC/C,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAoE3B;AAED,gEAAgE;AAChE,wBAAgB,SAAS,CACvB,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,IAAI,GAAG,SAAS,EAC/B,QAAQ,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,oBAgFlC;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,SAAS,GAAG,SAAS,CAgCxE"}
@@ -1,5 +1,6 @@
1
1
  import { AuthInvalidated, Unauthorized } from "../../../zero-protocol/src/error-kind-enum.js";
2
2
  import { ZeroCache } from "../../../zero-protocol/src/error-origin-enum.js";
3
+ import "../../../zero-protocol/src/error-reason-enum.js";
3
4
  import { ProtocolError, isProtocolError } from "../../../zero-protocol/src/error.js";
4
5
  //#region ../zero-cache/src/auth/auth.ts
5
6
  function isProvidedAuth(wireAuth) {
@@ -10,89 +11,56 @@ function authEquals(a, b) {
10
11
  if (!a || !b) return false;
11
12
  return a.type === b.type && a.raw === b.raw;
12
13
  }
13
- var AuthSessionImpl = class {
14
- id;
15
- #lc;
16
- #validateLegacyJWT;
17
- #auth = void 0;
18
- #boundUserID;
19
- #revision = 0;
20
- constructor(lc, clientGroupID, validateLegacyJWT) {
21
- this.id = clientGroupID;
22
- this.#lc = lc;
23
- this.#validateLegacyJWT = validateLegacyJWT;
24
- }
25
- get auth() {
26
- return this.#auth;
27
- }
28
- get revision() {
29
- return this.#revision;
30
- }
31
- clear() {
32
- this.#lc.withContext("boundUserID", this.#boundUserID ?? "unknown").debug?.(`Clearing auth session`);
33
- this.#auth = void 0;
34
- this.#boundUserID = void 0;
35
- this.#revision = 0;
36
- }
37
- async update(userID, wireAuth) {
38
- try {
39
- const lc = this.#lc.withContext("newUserID", userID);
40
- if (this.#boundUserID && this.#boundUserID !== userID) return {
41
- ok: false,
42
- error: {
43
- kind: Unauthorized,
44
- message: "Client groups are pinned to a single user. Connection userID does not match existing client group userID.",
45
- origin: ZeroCache
46
- }
47
- };
48
- const previousAuth = this.#auth;
49
- const hasProvidedAuth = isProvidedAuth(wireAuth);
50
- let nextAuth = previousAuth;
51
- if (previousAuth) lc.debug?.(`Attempting to update auth from previous value`);
52
- else lc.debug?.(`Attempting to initialize auth`);
53
- if (!hasProvidedAuth && previousAuth) return {
54
- ok: false,
55
- error: {
56
- kind: Unauthorized,
57
- message: "No token provided. An unauthenticated client cannot connect to an authenticated client group.",
58
- origin: ZeroCache
59
- }
60
- };
61
- if (!hasProvidedAuth) {
62
- nextAuth = void 0;
63
- lc.debug?.(`Cleared auth`);
64
- } else if (this.#validateLegacyJWT !== void 0) {
65
- const verifiedToken = await this.#validateLegacyJWT(wireAuth, { userID });
66
- nextAuth = pickToken(this.#lc, this.#auth, verifiedToken);
67
- lc.debug?.(`Updated auth with JWT`);
68
- } else {
69
- if (this.#auth?.type === "jwt") throw new Error("Cannot change auth type from legacy to opaque token");
70
- nextAuth = {
71
- type: "opaque",
72
- raw: wireAuth
73
- };
74
- lc.debug?.(`Updated auth with opaque token`);
75
- }
76
- this.#auth = nextAuth;
77
- this.#boundUserID ??= userID;
78
- if (!authEquals(previousAuth, nextAuth)) this.#revision++;
79
- } catch (e) {
80
- if (isProtocolError(e)) return {
81
- ok: false,
82
- error: e.errorBody
83
- };
84
- return {
85
- ok: false,
86
- error: {
87
- kind: AuthInvalidated,
88
- message: `Failed to decode auth token: ${String(e)}`,
89
- origin: ZeroCache
90
- }
91
- };
14
+ /**
15
+ * Resolves one auth snapshot transition without binding it to a client group.
16
+ */
17
+ async function resolveAuth(lc, previousAuth, userID, wireAuth, validateLegacyJWT) {
18
+ try {
19
+ const hasProvidedAuth = isProvidedAuth(wireAuth);
20
+ if (previousAuth) lc.debug?.(`Attempting to update auth from previous value`);
21
+ else lc.debug?.(`Attempting to initialize auth`);
22
+ if (!hasProvidedAuth && previousAuth) throw new ProtocolError({
23
+ kind: Unauthorized,
24
+ message: "No token provided. An unauthenticated client cannot connect to an authenticated client group.",
25
+ origin: ZeroCache
26
+ });
27
+ if (!hasProvidedAuth) {
28
+ lc.debug?.(`Cleared auth`);
29
+ return;
92
30
  }
93
- return { ok: true };
31
+ if (userID === void 0) throw new ProtocolError({
32
+ kind: Unauthorized,
33
+ message: "Authenticated connections require a userID.",
34
+ origin: ZeroCache
35
+ });
36
+ if (validateLegacyJWT !== void 0) {
37
+ const nextAuth = pickToken(lc, previousAuth, await validateLegacyJWT(wireAuth, { userID }));
38
+ lc.debug?.(`Updated auth with JWT`);
39
+ return nextAuth;
40
+ }
41
+ if (previousAuth?.type === "jwt") throw new ProtocolError({
42
+ kind: Unauthorized,
43
+ message: "Token type cannot change from JWT to opaque. Connections are pinned to a single token type.",
44
+ origin: ZeroCache
45
+ });
46
+ if (previousAuth?.type === "opaque" && previousAuth.raw === wireAuth) {
47
+ lc.debug?.(`Opaque auth unchanged, reusing previous snapshot`);
48
+ return previousAuth;
49
+ }
50
+ lc.debug?.(`Updated auth with opaque token`);
51
+ return {
52
+ type: "opaque",
53
+ raw: wireAuth
54
+ };
55
+ } catch (e) {
56
+ if (isProtocolError(e)) throw e;
57
+ throw new ProtocolError({
58
+ kind: AuthInvalidated,
59
+ message: `Failed to decode auth token: ${String(e)}`,
60
+ origin: ZeroCache
61
+ });
94
62
  }
95
- };
63
+ }
96
64
  /** @deprecated used only in old JWT validation/rotation auth */
97
65
  function pickToken(lc, previousToken, newToken) {
98
66
  if (newToken === null) return;
@@ -139,7 +107,14 @@ function pickToken(lc, previousToken, newToken) {
139
107
  origin: ZeroCache
140
108
  });
141
109
  }
110
+ function isAuthErrorBody(ex) {
111
+ if (typeof ex !== "object" || ex === null) return false;
112
+ if ("error" in ex) return ex.error === "http" && "status" in ex && (ex.status === 401 || ex.status === 403);
113
+ if (!("kind" in ex)) return false;
114
+ if (ex.kind === "AuthInvalidated" || ex.kind === "Unauthorized") return true;
115
+ return (ex.kind === "PushFailed" || ex.kind === "TransformFailed") && "reason" in ex && ex.reason === "http" && "status" in ex && (ex.status === 401 || ex.status === 403);
116
+ }
142
117
  //#endregion
143
- export { AuthSessionImpl };
118
+ export { authEquals, isAuthErrorBody, resolveAuth };
144
119
 
145
120
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","names":["#lc","#validateLegacyJWT","#auth","#revision","#boundUserID"],"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 {\n isProtocolError,\n ProtocolError,\n type ErrorBody,\n} from '../../../zero-protocol/src/error.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 interface AuthSession {\n /** Update the auth session with a new userID and token from the client */\n update(\n userID: string,\n wireAuth: string | undefined,\n ): Promise<AuthUpdateResult>;\n\n /** The revision of the auth state */\n get revision(): number;\n\n /** The auth state for the session */\n get auth(): Auth | undefined;\n\n /** Clear the auth session, removing any stored auth and allowing a new userID to be bound on the next update. */\n clear(): void;\n}\n\nexport type AuthUpdateResult =\n | {\n readonly ok: true;\n }\n | {\n readonly ok: false;\n readonly error: ErrorBody;\n };\n\nexport type ValidateLegacyJWT = (\n token: string,\n ctx: {readonly userID: string},\n) => Promise<JWTAuth>;\n\nfunction isProvidedAuth(wireAuth: string | undefined): wireAuth is string {\n return wireAuth !== undefined && wireAuth !== '';\n}\n\nfunction authEquals(a: Auth | null | undefined, b: Auth | null | 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\nexport class AuthSessionImpl implements AuthSession {\n readonly id: string;\n readonly #lc: LogContext;\n readonly #validateLegacyJWT: ValidateLegacyJWT | undefined;\n #auth: Auth | undefined = undefined;\n #boundUserID: string | undefined;\n #revision = 0;\n\n constructor(\n lc: LogContext,\n clientGroupID: string,\n validateLegacyJWT: ValidateLegacyJWT | undefined,\n ) {\n this.id = clientGroupID;\n this.#lc = lc;\n this.#validateLegacyJWT = validateLegacyJWT;\n }\n\n get auth(): Auth | undefined {\n return this.#auth;\n }\n\n get revision(): number {\n return this.#revision;\n }\n\n clear(): void {\n const lc = this.#lc.withContext(\n 'boundUserID',\n this.#boundUserID ?? 'unknown',\n );\n lc.debug?.(`Clearing auth session`);\n this.#auth = undefined;\n this.#boundUserID = undefined;\n this.#revision = 0;\n }\n\n async update(\n userID: string,\n wireAuth: string | undefined,\n ): Promise<AuthUpdateResult> {\n try {\n const lc = this.#lc.withContext('newUserID', userID);\n\n // check if the auth update is trying to change the bound userID for this client group\n if (this.#boundUserID && this.#boundUserID !== userID) {\n return {\n ok: false,\n error: {\n kind: ErrorKind.Unauthorized,\n message:\n 'Client groups are pinned to a single user. Connection userID does not match existing client group userID.',\n origin: ErrorOrigin.ZeroCache,\n },\n };\n }\n\n const previousAuth = this.#auth;\n const hasProvidedAuth = isProvidedAuth(wireAuth);\n let nextAuth = previousAuth;\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 return {\n ok: false,\n error: {\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\n if (!hasProvidedAuth) {\n nextAuth = undefined;\n lc.debug?.(`Cleared auth`);\n } else if (this.#validateLegacyJWT !== undefined) {\n const verifiedToken = await this.#validateLegacyJWT(wireAuth, {userID});\n nextAuth = pickToken(this.#lc, this.#auth, verifiedToken);\n lc.debug?.(`Updated auth with JWT`);\n } else {\n if (this.#auth?.type === 'jwt') {\n throw new Error(\n 'Cannot change auth type from legacy to opaque token',\n );\n }\n nextAuth = {\n type: 'opaque',\n raw: wireAuth,\n };\n lc.debug?.(`Updated auth with opaque token`);\n }\n\n this.#auth = nextAuth;\n this.#boundUserID ??= userID;\n\n if (!authEquals(previousAuth, nextAuth)) {\n this.#revision++;\n }\n } catch (e) {\n if (isProtocolError(e)) {\n return {\n ok: false,\n error: e.errorBody,\n };\n }\n return {\n ok: false,\n error: {\n kind: ErrorKind.AuthInvalidated,\n message: `Failed to decode auth token: ${String(e)}`,\n origin: ErrorOrigin.ZeroCache,\n },\n };\n }\n\n return {ok: true};\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"],"mappings":"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"}
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 {\n isProtocolError,\n ProtocolError,\n type ErrorBody,\n} from '../../../zero-protocol/src/error.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.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 | undefined,\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 === undefined) {\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":";;;;;AA+BA,SAAS,eAAe,UAAkD;AACxE,QAAO,aAAa,KAAA,KAAa,aAAa;;AAGhD,SAAgB,WAAW,GAAqB,GAAqB;AACnE,KAAI,MAAM,EACR,QAAO;AAET,KAAI,CAAC,KAAK,CAAC,EACT,QAAO;AAET,QAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE;;;;;AAM1C,eAAsB,YACpB,IACA,cACA,QACA,UACA,mBAC2B;AAC3B,KAAI;EACF,MAAM,kBAAkB,eAAe,SAAS;AAEhD,MAAI,aACF,IAAG,QAAQ,gDAAgD;MAE3D,IAAG,QAAQ,gCAAgC;AAG7C,MAAI,CAAC,mBAAmB,aACtB,OAAM,IAAI,cAAc;GACtB,MAAM;GACN,SACE;GACF,QAAQ;GACT,CAAC;AAGJ,MAAI,CAAC,iBAAiB;AACpB,MAAG,QAAQ,eAAe;AAC1B;;AAGF,MAAI,WAAW,KAAA,EACb,OAAM,IAAI,cAAc;GACtB,MAAM;GACN,SAAS;GACT,QAAQ;GACT,CAAC;AAGJ,MAAI,sBAAsB,KAAA,GAAW;GAEnC,MAAM,WAAW,UAAU,IAAI,cADT,MAAM,kBAAkB,UAAU,EAAC,QAAO,CAAC,CACN;AAC3D,MAAG,QAAQ,wBAAwB;AACnC,UAAO;;AAGT,MAAI,cAAc,SAAS,MACzB,OAAM,IAAI,cAAc;GACtB,MAAM;GACN,SACE;GACF,QAAQ;GACT,CAAC;AAGJ,MAAI,cAAc,SAAS,YAAY,aAAa,QAAQ,UAAU;AACpE,MAAG,QAAQ,mDAAmD;AAC9D,UAAO;;AAGT,KAAG,QAAQ,iCAAiC;AAC5C,SAAO;GACL,MAAM;GACN,KAAK;GACN;UACM,GAAG;AACV,MAAI,gBAAgB,EAAE,CACpB,OAAM;AAER,QAAM,IAAI,cAAc;GACtB,MAAM;GACN,SAAS,gCAAgC,OAAO,EAAE;GAClD,QAAQ;GACT,CAAC;;;;AAKN,SAAgB,UACd,IACA,eACA,UACA;AACA,KAAI,aAAa,KACf;AAGF,KACE,eAAe,QACf,UAAU,QACV,eAAe,SAAS,UAAU,KAElC,OAAM,IAAI,cAAc;EACtB,MAAM;EACN,SACE;EACF,QAAQ;EACT,CAAC;AAGJ,KAAI,kBAAkB,KAAA,GAAW;AAC/B,KAAG,QAAQ,qCAAqC;AAChD,SAAO;;AAGT,KAAI,UAAU,SAAS,SACrB,QAAO;AAGT,KAAI,cAAc,SAAS,SACzB,OAAM,IAAI,cAAc;EACtB,MAAM;EACN,SACE;EACF,QAAQ;EACT,CAAC;AAGJ,KAAI,UAAU;AACZ,MAAI,cAAc,QAAQ,QAAQ,SAAS,QAAQ,IACjD,OAAM,IAAI,cAAc;GACtB,MAAM;GACN,SACE;GACF,QAAQ;GACT,CAAC;AAGJ,MAAI,cAAc,QAAQ,QAAQ,KAAA,GAAW;AAC3C,MAAG,QAAQ,4DAA4D;AAEvE,UAAO;;AAGT,MAAI,SAAS,QAAQ,QAAQ,KAAA,EAC3B,OAAM,IAAI,cAAc;GACtB,MAAM;GACN,SACE;GACF,QAAQ;GACT,CAAC;AAIJ,MAAI,cAAc,QAAQ,MAAM,SAAS,QAAQ,KAAK;AACpD,MAAG,QAAQ,+BAA+B;AAC1C,UAAO;;AAIT,KAAG,QAAQ,uDAAuD;AAClE,SAAO;;AAIT,OAAM,IAAI,cAAc;EACtB,MAAM;EACN,SACE;EACF,QAAQ;EACT,CAAC;;AAGJ,SAAgB,gBAAgB,IAA0C;AACxE,KAAI,OAAO,OAAO,YAAY,OAAO,KACnC,QAAO;AAGT,KAAI,WAAW,GACb,QACE,GAAG,UAAU,UACb,YAAY,OACX,GAAG,WAAW,OAAO,GAAG,WAAW;AAIxC,KAAI,EAAE,UAAU,IACd,QAAO;AAGT,KACE,GAAG,SAAS,qBACZ,GAAG,SAAS,eAEZ,QAAO;AAGT,SACG,GAAG,SAAS,gBACX,GAAG,SAAS,sBACd,YAAY,MACZ,GAAG,WAAW,UACd,YAAY,OACX,GAAG,WAAW,OAAO,GAAG,WAAW"}
@@ -1,12 +1,12 @@
1
1
  import { type JWK, type JWTClaimVerificationOptions, type JWTPayload } from 'jose';
2
- import type { AuthConfig } from '../config/zero-config.ts';
2
+ import type { LegacyJWTAuthConfig } from '../config/zero-config.ts';
3
3
  /** @deprecated */
4
4
  export declare function createJwkPair(): Promise<{
5
5
  privateJwk: JWK;
6
6
  publicJwk: JWK;
7
7
  }>;
8
8
  /** @deprecated */
9
- export declare const tokenConfigOptions: (config: AuthConfig) => ("jwk" | "jwksUrl" | "secret")[];
9
+ export declare const tokenConfigOptions: (config: LegacyJWTAuthConfig) => ("jwk" | "jwksUrl" | "secret")[];
10
10
  /** @deprecated */
11
- export declare function verifyToken(config: AuthConfig, token: string, verifyOptions: JWTClaimVerificationOptions): Promise<JWTPayload>;
11
+ export declare function verifyToken(config: LegacyJWTAuthConfig, token: string, verifyOptions: JWTClaimVerificationOptions): Promise<JWTPayload>;
12
12
  //# sourceMappingURL=jwt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/auth/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,2BAA2B,EAChC,KAAK,UAAU,EAEhB,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAEzD,kBAAkB;AAClB,wBAAsB,aAAa;;;GAelC;AAWD,kBAAkB;AAClB,eAAO,MAAM,kBAAkB,GAAI,QAAQ,UAAU,qCAMpD,CAAC;AAEF,kBAAkB;AAClB,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,2BAA2B,GACzC,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/auth/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,2BAA2B,EAChC,KAAK,UAAU,EAEhB,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,0BAA0B,CAAC;AAElE,kBAAkB;AAClB,wBAAsB,aAAa;;;GAelC;AAWD,kBAAkB;AAClB,eAAO,MAAM,kBAAkB,GAAI,QAAQ,mBAAmB,qCAM7D,CAAC;AAEF,kBAAkB;AAClB,wBAAsB,WAAW,CAC/B,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,2BAA2B,GACzC,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
@@ -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 {AuthConfig} 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: AuthConfig) => {\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: AuthConfig,\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;AACxC,KAAI,iBAAiB,KAAA,EACnB,gBAAe,mBAAmB,IAAI,IAAI,QAAQ,CAAC;AAGrD,QAAO;;;AAIT,IAAa,sBAAsB,WAAuB;AAKxD,QAJsB;EAAC;EAAO;EAAU;EAAU,CAAW,QAC3D,QAAO,OAAO,SAAS,KAAA,EACxB;;;AAMH,eAAsB,YACpB,QACA,OACA,eACqB;AACrB,KAAI,OAAO,QAAQ,KAAA,EACjB,QAAO,gBAAgB,OAAO,QAAQ,OAAO,IAAI,EAAE,cAAc;AAGnE,KAAI,OAAO,WAAW,KAAA,EACpB,QAAO,gBAAgB,OAAO,WAAW,OAAO,OAAO,EAAE,cAAc;AAGzE,KAAI,OAAO,YAAY,KAAA,EAErB,SAAQ,MAAM,UAAU,OADH,gBAAgB,OAAO,QAAQ,EACP,cAAc,EAAE;AAG/D,OAAM,IAAI,MACR,6FACD;;AAGH,SAAS,QAAQ,WAAmB;AAClC,QAAO,KAAK,MAAM,UAAU;;AAG9B,SAAS,WAAW,QAAgB;AAClC,QAAO,IAAI,aAAa,CAAC,OAAO,OAAO;;AAGzC,eAAe,gBACb,OACA,WACA,eACqB;CACrB,MAAM,EAAC,YAAW,MAAM,UAAU,OAAO,WAAW,cAAc;AAElE,QAAO"}
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;AACxC,KAAI,iBAAiB,KAAA,EACnB,gBAAe,mBAAmB,IAAI,IAAI,QAAQ,CAAC;AAGrD,QAAO;;;AAIT,IAAa,sBAAsB,WAAgC;AAKjE,QAJsB;EAAC;EAAO;EAAU;EAAU,CAAW,QAC3D,QAAO,OAAO,SAAS,KAAA,EACxB;;;AAMH,eAAsB,YACpB,QACA,OACA,eACqB;AACrB,KAAI,OAAO,QAAQ,KAAA,EACjB,QAAO,gBAAgB,OAAO,QAAQ,OAAO,IAAI,EAAE,cAAc;AAGnE,KAAI,OAAO,WAAW,KAAA,EACpB,QAAO,gBAAgB,OAAO,WAAW,OAAO,OAAO,EAAE,cAAc;AAGzE,KAAI,OAAO,YAAY,KAAA,EAErB,SAAQ,MAAM,UAAU,OADH,gBAAgB,OAAO,QAAQ,EACP,cAAc,EAAE;AAG/D,OAAM,IAAI,MACR,6FACD;;AAGH,SAAS,QAAQ,WAAmB;AAClC,QAAO,KAAK,MAAM,UAAU;;AAG9B,SAAS,WAAW,QAAgB;AAClC,QAAO,IAAI,aAAa,CAAC,OAAO,OAAO;;AAGzC,eAAe,gBACb,OACA,WACA,eACqB;CACrB,MAAM,EAAC,YAAW,MAAM,UAAU,OAAO,WAAW,cAAc;AAElE,QAAO"}
@@ -76,9 +76,18 @@ declare const authOptions: {
76
76
  desc: string[];
77
77
  deprecated: string[];
78
78
  };
79
+ revalidateIntervalSeconds: {
80
+ type: v.Optional<number>;
81
+ desc: string[];
82
+ };
83
+ retransformIntervalSeconds: {
84
+ type: v.Optional<number>;
85
+ desc: string[];
86
+ };
79
87
  };
80
- /** @deprecated */
81
88
  export type AuthConfig = Config<typeof authOptions>;
89
+ /** @deprecated used only by legacy JWT verification helpers */
90
+ export type LegacyJWTAuthConfig = Pick<AuthConfig, 'jwk' | 'jwksUrl' | 'secret' | 'issuer' | 'audience'>;
82
91
  export declare const zeroOptions: {
83
92
  upstream: {
84
93
  db: {
@@ -98,6 +107,10 @@ export declare const zeroOptions: {
98
107
  type: v.Optional<number>;
99
108
  hidden: boolean;
100
109
  };
110
+ pgReplicationSlotFailover: {
111
+ type: v.Optional<boolean>;
112
+ desc: string[];
113
+ };
101
114
  };
102
115
  /** @deprecated */
103
116
  push: {
@@ -291,7 +304,6 @@ export declare const zeroOptions: {
291
304
  hidden: boolean;
292
305
  };
293
306
  };
294
- /** @deprecated */
295
307
  auth: {
296
308
  jwk: {
297
309
  type: v.Optional<string>;
@@ -318,6 +330,14 @@ export declare const zeroOptions: {
318
330
  desc: string[];
319
331
  deprecated: string[];
320
332
  };
333
+ revalidateIntervalSeconds: {
334
+ type: v.Optional<number>;
335
+ desc: string[];
336
+ };
337
+ retransformIntervalSeconds: {
338
+ type: v.Optional<number>;
339
+ desc: string[];
340
+ };
321
341
  };
322
342
  port: {
323
343
  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":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,CAAC,MAAM,+BAA+B,CAAC;AAUnD,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAC,SAAS,EAAC,MAAM,kCAAkC,CAAC;AAEhE,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,eAAO,MAAM,UAAU;;;;;;;;;CA+CtB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;CAwBxB,CAAC;AAEF,QAAA,MAAM,cAAc;;;;;;;;;CAmBnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC;AAE3D,QAAA,MAAM,oBAAoB;;;;;;;;;CAczB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAE5D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDhB,CAAC;AAuGF,kBAAkB;AAClB,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAKpD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;IAwCtB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGlB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAgIlB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6ChB,kBAAkB;;;;;;QASlB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2WpB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAIpD,wBAAgB,aAAa,CAC3B,IAAI,GAAE,IAAI,CAAC,YAAY,EAAE,eAAe,CAAM,GAC7C,UAAU,CAaZ;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,GAAE,IAAI,CAAC,YAAY,EAAE,eAAe,CAAM,GAC7C,oBAAoB,CAItB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,GAAG,SAAS,GACpD,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,EACnD,QAAQ,EAAE,MAAM,GAAG,SAAS,WAwC7B;AAYD,wBAAgB,kBAAkB,SAEjC"}
1
+ {"version":3,"file":"zero-config.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/config/zero-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,CAAC,MAAM,+BAA+B,CAAC;AAUnD,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAC,SAAS,EAAC,MAAM,kCAAkC,CAAC;AAEhE,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,eAAO,MAAM,UAAU;;;;;;;;;CA+CtB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;CAwBxB,CAAC;AAEF,QAAA,MAAM,cAAc;;;;;;;;;CAmBnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC;AAE3D,QAAA,MAAM,oBAAoB;;;;;;;;;CAczB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAE5D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8DhB,CAAC;AAuGF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAEpD,+DAA+D;AAC/D,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,UAAU,EACV,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CACrD,CAAC;AAKF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;IAsDtB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGlB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4KhB,kBAAkB;;;;;;QASlB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2WpB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAIpD,wBAAgB,aAAa,CAC3B,IAAI,GAAE,IAAI,CAAC,YAAY,EAAE,eAAe,CAAM,GAC7C,UAAU,CAaZ;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,GAAE,IAAI,CAAC,YAAY,EAAE,eAAe,CAAM,GAC7C,oBAAoB,CAItB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,GAAG,SAAS,GACpD,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,EACnD,QAAQ,EAAE,MAAM,GAAG,SAAS,WAwC7B;AAYD,wBAAgB,kBAAkB,SAEjC"}
@@ -126,6 +126,14 @@ var authOptions = {
126
126
  type: valita_exports.string().optional(),
127
127
  desc: [`Expected audience ({bold aud} claim) for JWT validation.`, `If set, tokens with a different or missing audience will be rejected.`],
128
128
  deprecated: [`Use cookie-based authentication or an auth token instead - see https://zero.rocicorp.dev/docs/auth.`]
129
+ },
130
+ revalidateIntervalSeconds: {
131
+ type: valita_exports.number().optional(),
132
+ desc: [`The interval in seconds between periodic /query auth revalidation for validated connections.`, `If unset, periodic auth revalidation is disabled.`]
133
+ },
134
+ retransformIntervalSeconds: {
135
+ type: valita_exports.number().optional(),
136
+ desc: [`The interval in seconds between periodic shared /query retransform work for a client group.`, `If unset, periodic shared retransform is disabled.`]
129
137
  }
130
138
  };
131
139
  var makeDeprecationMessage = (flag) => `Use {bold ${flagToEnv(ZERO_ENV_VAR_PREFIX, flag)}} (or {bold --${flag}}) instead.`;
@@ -236,6 +244,19 @@ var zeroOptions = {
236
244
  maxConnsPerWorker: {
237
245
  type: valita_exports.number().optional(),
238
246
  hidden: true
247
+ },
248
+ pgReplicationSlotFailover: {
249
+ type: valita_exports.boolean().optional(),
250
+ desc: [
251
+ `For upstream Postgres versions 17+, creates replication slots with the`,
252
+ `{bold failover} parameter set to {bold true} to enable slot synchronization`,
253
+ `and failover. Note that additional Postgres-level configuration is necessary`,
254
+ `when enabling this option. For details, see:`,
255
+ ``,
256
+ `https://www.postgresql.org/docs/current/logicaldecoding-explanation.html#LOGICALDECODING-REPLICATION-SLOTS-SYNCHRONIZATION`,
257
+ ``,
258
+ `(Note that this option has no effect for Postgres versions before 17.)`
259
+ ]
239
260
  }
240
261
  },
241
262
  push: pushOptions,