jazz-tools 2.0.0-alpha.50 → 2.0.0-alpha.52

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 (414) hide show
  1. package/bin/docs-index.txt +5 -6
  2. package/bin/native/jazz-tools-darwin-arm64 +0 -0
  3. package/bin/native/jazz-tools-darwin-x64 +0 -0
  4. package/bin/native/jazz-tools-linux-arm64 +0 -0
  5. package/bin/native/jazz-tools-linux-x64 +0 -0
  6. package/dist/backend/index.d.ts +1 -0
  7. package/dist/backend/index.d.ts.map +1 -1
  8. package/dist/backend/index.js +1 -0
  9. package/dist/backend/index.js.map +1 -1
  10. package/dist/better-auth-adapter/index.test.js +11 -11
  11. package/dist/better-auth-adapter/index.test.js.map +1 -1
  12. package/dist/better-auth-adapter/utils.d.ts.map +1 -1
  13. package/dist/better-auth-adapter/utils.js +3 -37
  14. package/dist/better-auth-adapter/utils.js.map +1 -1
  15. package/dist/better-auth-adapter/utils.test.js +44 -0
  16. package/dist/better-auth-adapter/utils.test.js.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +125 -1055
  19. package/dist/cli.js.map +1 -1
  20. package/dist/codegen/schema-reader.d.ts.map +1 -1
  21. package/dist/codegen/schema-reader.js +6 -0
  22. package/dist/codegen/schema-reader.js.map +1 -1
  23. package/dist/dev/catalogue.d.ts +212 -0
  24. package/dist/dev/catalogue.d.ts.map +1 -0
  25. package/dist/dev/catalogue.js +879 -0
  26. package/dist/dev/catalogue.js.map +1 -0
  27. package/dist/dev/catalogue.test.d.ts +2 -0
  28. package/dist/dev/catalogue.test.d.ts.map +1 -0
  29. package/dist/dev/catalogue.test.js +607 -0
  30. package/dist/dev/catalogue.test.js.map +1 -0
  31. package/dist/dev/dev-server.d.ts +16 -15
  32. package/dist/dev/dev-server.d.ts.map +1 -1
  33. package/dist/dev/dev-server.js +23 -34
  34. package/dist/dev/dev-server.js.map +1 -1
  35. package/dist/dev/dev-server.test.js +12 -7
  36. package/dist/dev/dev-server.test.js.map +1 -1
  37. package/dist/dev/expo.test.js +3 -3
  38. package/dist/dev/expo.test.js.map +1 -1
  39. package/dist/dev/index.d.ts +2 -1
  40. package/dist/dev/index.d.ts.map +1 -1
  41. package/dist/dev/index.js +2 -1
  42. package/dist/dev/index.js.map +1 -1
  43. package/dist/dev/managed-runtime.d.ts.map +1 -1
  44. package/dist/dev/managed-runtime.js +5 -4
  45. package/dist/dev/managed-runtime.js.map +1 -1
  46. package/dist/dev/managed-runtime.test.js +11 -4
  47. package/dist/dev/managed-runtime.test.js.map +1 -1
  48. package/dist/dev/migrations.d.ts +8 -0
  49. package/dist/dev/migrations.d.ts.map +1 -0
  50. package/dist/dev/migrations.js +300 -0
  51. package/dist/dev/migrations.js.map +1 -0
  52. package/dist/dev/next.js +1 -1
  53. package/dist/dev/next.js.map +1 -1
  54. package/dist/dev/next.test.js +21 -10
  55. package/dist/dev/next.test.js.map +1 -1
  56. package/dist/dev/schema-utils.d.ts +7 -0
  57. package/dist/dev/schema-utils.d.ts.map +1 -0
  58. package/dist/dev/schema-utils.js +60 -0
  59. package/dist/dev/schema-utils.js.map +1 -0
  60. package/dist/dev/schema-watcher.js +3 -3
  61. package/dist/dev/schema-watcher.js.map +1 -1
  62. package/dist/dev/sveltekit.test.js +33 -22
  63. package/dist/dev/sveltekit.test.js.map +1 -1
  64. package/dist/dev/vite.test.js +13 -3
  65. package/dist/dev/vite.test.js.map +1 -1
  66. package/dist/dev-tools/dev-tools.js +1 -1
  67. package/dist/dev-tools/dev-tools.test.js +5 -5
  68. package/dist/dev-tools/extension-panel.js +0 -3
  69. package/dist/dev-tools/extension-panel.js.map +1 -1
  70. package/dist/drivers/types.d.ts +1 -1
  71. package/dist/drivers/types.d.ts.map +1 -1
  72. package/dist/dsl.d.ts +9 -1
  73. package/dist/dsl.d.ts.map +1 -1
  74. package/dist/dsl.js +8 -2
  75. package/dist/dsl.js.map +1 -1
  76. package/dist/dsl.test.js +34 -0
  77. package/dist/dsl.test.js.map +1 -1
  78. package/dist/index.d.ts +2 -0
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +1 -0
  81. package/dist/index.js.map +1 -1
  82. package/dist/permissions/index.d.ts +3 -3
  83. package/dist/permissions/index.d.ts.map +1 -1
  84. package/dist/react-core/provider.d.ts.map +1 -1
  85. package/dist/react-core/provider.js +43 -43
  86. package/dist/react-core/provider.js.map +1 -1
  87. package/dist/react-core/provider.onjwtexpired.test.js +49 -1
  88. package/dist/react-core/provider.onjwtexpired.test.js.map +1 -1
  89. package/dist/react-core/use-all.d.ts +13 -1
  90. package/dist/react-core/use-all.d.ts.map +1 -1
  91. package/dist/react-core/use-all.js +67 -37
  92. package/dist/react-core/use-all.js.map +1 -1
  93. package/dist/react-core/use-all.test.d.ts +2 -0
  94. package/dist/react-core/use-all.test.d.ts.map +1 -0
  95. package/dist/react-core/use-all.test.js +130 -0
  96. package/dist/react-core/use-all.test.js.map +1 -0
  97. package/dist/react-native/db.test.js +6 -6
  98. package/dist/react-native/jazz-rn-handoff.test.js +0 -7
  99. package/dist/react-native/jazz-rn-handoff.test.js.map +1 -1
  100. package/dist/react-native/jazz-rn-runtime-adapter.d.ts +19 -37
  101. package/dist/react-native/jazz-rn-runtime-adapter.d.ts.map +1 -1
  102. package/dist/react-native/jazz-rn-runtime-adapter.js +24 -78
  103. package/dist/react-native/jazz-rn-runtime-adapter.js.map +1 -1
  104. package/dist/react-native/jazz-rn-runtime-adapter.test.js +55 -80
  105. package/dist/react-native/jazz-rn-runtime-adapter.test.js.map +1 -1
  106. package/dist/runtime/browser-broker-client.d.ts +101 -0
  107. package/dist/runtime/browser-broker-client.d.ts.map +1 -0
  108. package/dist/runtime/browser-broker-client.js +598 -0
  109. package/dist/runtime/browser-broker-client.js.map +1 -0
  110. package/dist/runtime/browser-broker-client.test.d.ts +2 -0
  111. package/dist/runtime/browser-broker-client.test.d.ts.map +1 -0
  112. package/dist/runtime/browser-broker-client.test.js +798 -0
  113. package/dist/runtime/browser-broker-client.test.js.map +1 -0
  114. package/dist/runtime/browser-broker-errors.d.ts +10 -0
  115. package/dist/runtime/browser-broker-errors.d.ts.map +1 -0
  116. package/dist/runtime/browser-broker-errors.js +22 -0
  117. package/dist/runtime/browser-broker-errors.js.map +1 -0
  118. package/dist/runtime/browser-broker-protocol.d.ts +196 -0
  119. package/dist/runtime/browser-broker-protocol.d.ts.map +1 -0
  120. package/dist/runtime/browser-broker-protocol.js +159 -0
  121. package/dist/runtime/browser-broker-protocol.js.map +1 -0
  122. package/dist/runtime/browser-broker-protocol.test.d.ts +2 -0
  123. package/dist/runtime/browser-broker-protocol.test.d.ts.map +1 -0
  124. package/dist/runtime/browser-broker-protocol.test.js +67 -0
  125. package/dist/runtime/browser-broker-protocol.test.js.map +1 -0
  126. package/dist/runtime/client-registry.d.ts +20 -0
  127. package/dist/runtime/client-registry.d.ts.map +1 -0
  128. package/dist/runtime/client-registry.js +80 -0
  129. package/dist/runtime/client-registry.js.map +1 -0
  130. package/dist/runtime/client-registry.test.d.ts +2 -0
  131. package/dist/runtime/client-registry.test.d.ts.map +1 -0
  132. package/dist/runtime/client-registry.test.js +59 -0
  133. package/dist/runtime/client-registry.test.js.map +1 -0
  134. package/dist/runtime/client-tests/for-request.test.js +12 -17
  135. package/dist/runtime/client-tests/for-request.test.js.map +1 -1
  136. package/dist/runtime/client-tests/support.d.ts +8 -2
  137. package/dist/runtime/client-tests/support.d.ts.map +1 -1
  138. package/dist/runtime/client-tests/support.js +18 -12
  139. package/dist/runtime/client-tests/support.js.map +1 -1
  140. package/dist/runtime/client.d.ts +55 -179
  141. package/dist/runtime/client.d.ts.map +1 -1
  142. package/dist/runtime/client.js +75 -548
  143. package/dist/runtime/client.js.map +1 -1
  144. package/dist/runtime/client.mutations.test.js +41 -230
  145. package/dist/runtime/client.mutations.test.js.map +1 -1
  146. package/dist/runtime/client.test.js +46 -195
  147. package/dist/runtime/client.test.js.map +1 -1
  148. package/dist/runtime/context.d.ts +3 -0
  149. package/dist/runtime/context.d.ts.map +1 -1
  150. package/dist/runtime/db-runtime-module.d.ts +1 -0
  151. package/dist/runtime/db-runtime-module.d.ts.map +1 -1
  152. package/dist/runtime/db-runtime-module.js.map +1 -1
  153. package/dist/runtime/db.d.ts +122 -54
  154. package/dist/runtime/db.d.ts.map +1 -1
  155. package/dist/runtime/db.driver-mode.test.js +51 -1
  156. package/dist/runtime/db.driver-mode.test.js.map +1 -1
  157. package/dist/runtime/db.js +890 -357
  158. package/dist/runtime/db.js.map +1 -1
  159. package/dist/runtime/db.one.test.d.ts +2 -0
  160. package/dist/runtime/db.one.test.d.ts.map +1 -0
  161. package/dist/runtime/db.one.test.js +69 -0
  162. package/dist/runtime/db.one.test.js.map +1 -0
  163. package/dist/runtime/db.persisted.test.js +17 -17
  164. package/dist/runtime/db.persisted.test.js.map +1 -1
  165. package/dist/runtime/db.schema-order.test.js +32 -89
  166. package/dist/runtime/db.schema-order.test.js.map +1 -1
  167. package/dist/runtime/db.transaction.test.js +81 -1184
  168. package/dist/runtime/db.transaction.test.js.map +1 -1
  169. package/dist/runtime/db.transport.test.js +26 -1
  170. package/dist/runtime/db.transport.test.js.map +1 -1
  171. package/dist/runtime/db.worker-bootstrap.test.js +339 -19
  172. package/dist/runtime/db.worker-bootstrap.test.js.map +1 -1
  173. package/dist/runtime/index.d.ts +6 -5
  174. package/dist/runtime/index.d.ts.map +1 -1
  175. package/dist/runtime/index.js +4 -3
  176. package/dist/runtime/index.js.map +1 -1
  177. package/dist/runtime/leader-lock.d.ts +21 -3
  178. package/dist/runtime/leader-lock.d.ts.map +1 -1
  179. package/dist/runtime/leader-lock.js +131 -33
  180. package/dist/runtime/leader-lock.js.map +1 -1
  181. package/dist/runtime/napi.auth-failure.test.js +1 -1
  182. package/dist/runtime/napi.auth-failure.test.js.map +1 -1
  183. package/dist/runtime/napi.for-request.test.js +1 -1
  184. package/dist/runtime/napi.for-request.test.js.map +1 -1
  185. package/dist/runtime/napi.integration.test.js +4 -8
  186. package/dist/runtime/napi.integration.test.js.map +1 -1
  187. package/dist/runtime/permissions.repro.test.js +1 -1
  188. package/dist/runtime/permissions.repro.test.js.map +1 -1
  189. package/dist/runtime/query-adapter-tests/condition-translation.test.js +20 -0
  190. package/dist/runtime/query-adapter-tests/condition-translation.test.js.map +1 -1
  191. package/dist/runtime/query-adapter.d.ts.map +1 -1
  192. package/dist/runtime/query-adapter.js +14 -12
  193. package/dist/runtime/query-adapter.js.map +1 -1
  194. package/dist/runtime/query-builder-shape.d.ts +1 -0
  195. package/dist/runtime/query-builder-shape.d.ts.map +1 -1
  196. package/dist/runtime/query-builder-shape.js +1 -0
  197. package/dist/runtime/query-builder-shape.js.map +1 -1
  198. package/dist/runtime/runtime-config.d.ts +1 -0
  199. package/dist/runtime/runtime-config.d.ts.map +1 -1
  200. package/dist/runtime/runtime-config.js +11 -5
  201. package/dist/runtime/runtime-config.js.map +1 -1
  202. package/dist/runtime/runtime-config.test.d.ts +2 -0
  203. package/dist/runtime/runtime-config.test.d.ts.map +1 -0
  204. package/dist/runtime/runtime-config.test.js +21 -0
  205. package/dist/runtime/runtime-config.test.js.map +1 -0
  206. package/dist/runtime/schema-fetch.d.ts +5 -0
  207. package/dist/runtime/schema-fetch.d.ts.map +1 -1
  208. package/dist/runtime/schema-fetch.js +33 -2
  209. package/dist/runtime/schema-fetch.js.map +1 -1
  210. package/dist/runtime/schema-fetch.test.js +31 -0
  211. package/dist/runtime/schema-fetch.test.js.map +1 -1
  212. package/dist/runtime/select-projection.d.ts +0 -1
  213. package/dist/runtime/select-projection.d.ts.map +1 -1
  214. package/dist/runtime/select-projection.js +0 -3
  215. package/dist/runtime/select-projection.js.map +1 -1
  216. package/dist/runtime/subscription-manager.d.ts +8 -3
  217. package/dist/runtime/subscription-manager.d.ts.map +1 -1
  218. package/dist/runtime/subscription-manager.js +1 -1
  219. package/dist/runtime/subscription-manager.js.map +1 -1
  220. package/dist/runtime/value-converter.d.ts +6 -17
  221. package/dist/runtime/value-converter.d.ts.map +1 -1
  222. package/dist/runtime/value-converter.js +6 -36
  223. package/dist/runtime/value-converter.js.map +1 -1
  224. package/dist/runtime/value-converter.test.js +13 -74
  225. package/dist/runtime/value-converter.test.js.map +1 -1
  226. package/dist/runtime/wasm-runtime-module.d.ts +1 -1
  227. package/dist/runtime/wasm-runtime-module.d.ts.map +1 -1
  228. package/dist/runtime/wasm-runtime-module.js +6 -2
  229. package/dist/runtime/wasm-runtime-module.js.map +1 -1
  230. package/dist/runtime/wasm-teardown-trap-suppressor.d.ts +27 -0
  231. package/dist/runtime/wasm-teardown-trap-suppressor.d.ts.map +1 -0
  232. package/dist/runtime/wasm-teardown-trap-suppressor.js +73 -0
  233. package/dist/runtime/wasm-teardown-trap-suppressor.js.map +1 -0
  234. package/dist/runtime/wasm-teardown-trap-suppressor.test.d.ts +2 -0
  235. package/dist/runtime/wasm-teardown-trap-suppressor.test.d.ts.map +1 -0
  236. package/dist/runtime/wasm-teardown-trap-suppressor.test.js +60 -0
  237. package/dist/runtime/wasm-teardown-trap-suppressor.test.js.map +1 -0
  238. package/dist/runtime/worker-bridge.d.ts +25 -2
  239. package/dist/runtime/worker-bridge.d.ts.map +1 -1
  240. package/dist/runtime/worker-bridge.js +48 -2
  241. package/dist/runtime/worker-bridge.js.map +1 -1
  242. package/dist/runtime/worker-bridge.test.d.ts +2 -0
  243. package/dist/runtime/worker-bridge.test.d.ts.map +1 -0
  244. package/dist/runtime/worker-bridge.test.js +53 -0
  245. package/dist/runtime/worker-bridge.test.js.map +1 -0
  246. package/dist/schema-loader.d.ts.map +1 -1
  247. package/dist/schema-loader.js +2 -0
  248. package/dist/schema-loader.js.map +1 -1
  249. package/dist/schema.d.ts +1 -1
  250. package/dist/schema.d.ts.map +1 -1
  251. package/dist/shared/index.d.ts +25 -0
  252. package/dist/shared/index.d.ts.map +1 -0
  253. package/dist/shared/index.js +22 -0
  254. package/dist/shared/index.js.map +1 -0
  255. package/dist/shared/index.test.d.ts +2 -0
  256. package/dist/shared/index.test.d.ts.map +1 -0
  257. package/dist/shared/index.test.js +79 -0
  258. package/dist/shared/index.test.js.map +1 -0
  259. package/dist/solid/create-solid-jazz-client-internal.d.ts +13 -0
  260. package/dist/solid/create-solid-jazz-client-internal.d.ts.map +1 -0
  261. package/dist/solid/create-solid-jazz-client-internal.js +47 -0
  262. package/dist/solid/create-solid-jazz-client-internal.js.map +1 -0
  263. package/dist/solid/create-solid-jazz-client-internal.ssr.js +64 -0
  264. package/dist/solid/create-solid-jazz-client-internal.ssr.js.map +1 -0
  265. package/dist/solid/create-solid-jazz-client-internal.test.d.ts +2 -0
  266. package/dist/solid/create-solid-jazz-client-internal.test.d.ts.map +1 -0
  267. package/dist/solid/create-solid-jazz-client.d.ts +34 -0
  268. package/dist/solid/create-solid-jazz-client.d.ts.map +1 -0
  269. package/dist/solid/create-solid-jazz-client.integration.test.d.ts +2 -0
  270. package/dist/solid/create-solid-jazz-client.integration.test.d.ts.map +1 -0
  271. package/dist/solid/create-solid-jazz-client.js +38 -0
  272. package/dist/solid/create-solid-jazz-client.js.map +1 -0
  273. package/dist/solid/create-solid-jazz-client.ssr.js +41 -0
  274. package/dist/solid/create-solid-jazz-client.ssr.js.map +1 -0
  275. package/dist/solid/index.d.ts +8 -0
  276. package/dist/solid/index.d.ts.map +1 -0
  277. package/dist/solid/index.js +7 -0
  278. package/dist/solid/index.ssr.js +7 -0
  279. package/dist/solid/provider.d.ts +27 -0
  280. package/dist/solid/provider.d.ts.map +1 -0
  281. package/dist/solid/provider.js +44 -0
  282. package/dist/solid/provider.js.map +1 -0
  283. package/dist/solid/provider.ssr.js +44 -0
  284. package/dist/solid/provider.ssr.js.map +1 -0
  285. package/dist/solid/solid-jazz-client-store.d.ts +11 -0
  286. package/dist/solid/solid-jazz-client-store.d.ts.map +1 -0
  287. package/dist/solid/solid-jazz-client-store.js +35 -0
  288. package/dist/solid/solid-jazz-client-store.js.map +1 -0
  289. package/dist/solid/solid-jazz-client-store.ssr.js +37 -0
  290. package/dist/solid/solid-jazz-client-store.ssr.js.map +1 -0
  291. package/dist/solid/solid-jazz-client-store.test.d.ts +2 -0
  292. package/dist/solid/solid-jazz-client-store.test.d.ts.map +1 -0
  293. package/dist/solid/use-all.d.ts +16 -0
  294. package/dist/solid/use-all.d.ts.map +1 -0
  295. package/dist/solid/use-all.js +60 -0
  296. package/dist/solid/use-all.js.map +1 -0
  297. package/dist/solid/use-all.ssr.js +68 -0
  298. package/dist/solid/use-all.ssr.js.map +1 -0
  299. package/dist/solid/use-all.test.d.ts +2 -0
  300. package/dist/solid/use-all.test.d.ts.map +1 -0
  301. package/dist/solid/use-local-first-auth.d.ts +11 -0
  302. package/dist/solid/use-local-first-auth.d.ts.map +1 -0
  303. package/dist/solid/use-local-first-auth.js +65 -0
  304. package/dist/solid/use-local-first-auth.js.map +1 -0
  305. package/dist/solid/use-local-first-auth.ssr.js +83 -0
  306. package/dist/solid/use-local-first-auth.ssr.js.map +1 -0
  307. package/dist/solid/use-local-first-auth.test.d.ts +2 -0
  308. package/dist/solid/use-local-first-auth.test.d.ts.map +1 -0
  309. package/dist/subscriptions-orchestrator.d.ts +33 -1
  310. package/dist/subscriptions-orchestrator.d.ts.map +1 -1
  311. package/dist/subscriptions-orchestrator.js +97 -7
  312. package/dist/subscriptions-orchestrator.js.map +1 -1
  313. package/dist/subscriptions-orchestrator.test.js +96 -0
  314. package/dist/subscriptions-orchestrator.test.js.map +1 -1
  315. package/dist/svelte/context.svelte.d.ts +6 -2
  316. package/dist/svelte/context.svelte.d.ts.map +1 -1
  317. package/dist/svelte/context.svelte.js +9 -2
  318. package/dist/svelte/context.svelte.test.js +14 -3
  319. package/dist/svelte/create-jazz-client.d.ts.map +1 -1
  320. package/dist/svelte/create-jazz-client.dedup.test.d.ts +2 -0
  321. package/dist/svelte/create-jazz-client.dedup.test.d.ts.map +1 -0
  322. package/dist/svelte/create-jazz-client.dedup.test.js +69 -0
  323. package/dist/svelte/create-jazz-client.js +14 -1
  324. package/dist/svelte/create-jazz-client.test.js +3 -3
  325. package/dist/svelte/use-all.svelte.d.ts +1 -2
  326. package/dist/svelte/use-all.svelte.d.ts.map +1 -1
  327. package/dist/svelte/use-all.svelte.js +14 -15
  328. package/dist/svelte/use-all.svelte.test.js +11 -0
  329. package/dist/testing/index.d.ts +2 -2
  330. package/dist/testing/index.d.ts.map +1 -1
  331. package/dist/testing/index.js +2 -2
  332. package/dist/testing/index.js.map +1 -1
  333. package/dist/testing/index.test.js +11 -69
  334. package/dist/testing/index.test.js.map +1 -1
  335. package/dist/testing/policy-test-app.d.ts +3 -3
  336. package/dist/testing/policy-test-app.d.ts.map +1 -1
  337. package/dist/testing/policy-test-app.js +1 -1
  338. package/dist/testing/policy-test-app.js.map +1 -1
  339. package/dist/testing/test-jwt-issuer.d.ts +16 -0
  340. package/dist/testing/test-jwt-issuer.d.ts.map +1 -0
  341. package/dist/testing/test-jwt-issuer.js +23 -0
  342. package/dist/testing/test-jwt-issuer.js.map +1 -0
  343. package/dist/typed-app.d.ts +24 -32
  344. package/dist/typed-app.d.ts.map +1 -1
  345. package/dist/typed-app.js +12 -1
  346. package/dist/typed-app.js.map +1 -1
  347. package/dist/vue/create-jazz-client.d.ts.map +1 -1
  348. package/dist/vue/create-jazz-client.dedup.test.d.ts +2 -0
  349. package/dist/vue/create-jazz-client.dedup.test.d.ts.map +1 -0
  350. package/dist/vue/create-jazz-client.dedup.test.js +70 -0
  351. package/dist/vue/create-jazz-client.dedup.test.js.map +1 -0
  352. package/dist/vue/create-jazz-client.js +14 -1
  353. package/dist/vue/create-jazz-client.js.map +1 -1
  354. package/dist/vue/provider.d.ts +5 -3
  355. package/dist/vue/provider.d.ts.map +1 -1
  356. package/dist/vue/provider.js +9 -3
  357. package/dist/vue/provider.js.map +1 -1
  358. package/dist/vue/provider.test.d.ts +2 -0
  359. package/dist/vue/provider.test.d.ts.map +1 -0
  360. package/dist/vue/provider.test.js +71 -0
  361. package/dist/vue/provider.test.js.map +1 -0
  362. package/dist/vue/use-all.d.ts +44 -3
  363. package/dist/vue/use-all.d.ts.map +1 -1
  364. package/dist/vue/use-all.js +56 -8
  365. package/dist/vue/use-all.js.map +1 -1
  366. package/dist/vue/use-all.test.js +73 -40
  367. package/dist/vue/use-all.test.js.map +1 -1
  368. package/dist/web/create-jazz-client.d.ts +20 -0
  369. package/dist/web/create-jazz-client.d.ts.map +1 -0
  370. package/dist/web/create-jazz-client.js +61 -0
  371. package/dist/web/create-jazz-client.js.map +1 -0
  372. package/dist/web/create-jazz-client.test.d.ts +2 -0
  373. package/dist/web/create-jazz-client.test.d.ts.map +1 -0
  374. package/dist/web/create-jazz-client.test.js +159 -0
  375. package/dist/web/create-jazz-client.test.js.map +1 -0
  376. package/dist/where-operators.d.ts +12 -0
  377. package/dist/where-operators.d.ts.map +1 -0
  378. package/dist/where-operators.js +46 -0
  379. package/dist/where-operators.js.map +1 -0
  380. package/dist/worker/broker-worker-bundle.test.d.ts +2 -0
  381. package/dist/worker/broker-worker-bundle.test.d.ts.map +1 -0
  382. package/dist/worker/broker-worker-bundle.test.js +40 -0
  383. package/dist/worker/broker-worker-bundle.test.js.map +1 -0
  384. package/dist/worker/jazz-broker-worker.d.ts +2 -0
  385. package/dist/worker/jazz-broker-worker.d.ts.map +1 -0
  386. package/dist/worker/jazz-broker-worker.js +1090 -0
  387. package/dist/worker/jazz-worker.js +80 -2
  388. package/dist/worker/jazz-worker.js.map +1 -1
  389. package/dist/worker/jazz-worker.ts +104 -2
  390. package/package.json +27 -8
  391. package/dist/runtime/client-tests/schema-order.test.d.ts +0 -2
  392. package/dist/runtime/client-tests/schema-order.test.d.ts.map +0 -1
  393. package/dist/runtime/client-tests/schema-order.test.js +0 -700
  394. package/dist/runtime/client-tests/schema-order.test.js.map +0 -1
  395. package/dist/runtime/storage-reset-coordinator.d.ts +0 -58
  396. package/dist/runtime/storage-reset-coordinator.d.ts.map +0 -1
  397. package/dist/runtime/storage-reset-coordinator.js +0 -402
  398. package/dist/runtime/storage-reset-coordinator.js.map +0 -1
  399. package/dist/runtime/tab-leader-election.d.ts +0 -97
  400. package/dist/runtime/tab-leader-election.d.ts.map +0 -1
  401. package/dist/runtime/tab-leader-election.js +0 -339
  402. package/dist/runtime/tab-leader-election.js.map +0 -1
  403. package/dist/runtime/tab-leader-election.test.d.ts +0 -2
  404. package/dist/runtime/tab-leader-election.test.d.ts.map +0 -1
  405. package/dist/runtime/tab-leader-election.test.js +0 -278
  406. package/dist/runtime/tab-leader-election.test.js.map +0 -1
  407. package/dist/runtime/tab-sync-protocol.d.ts +0 -55
  408. package/dist/runtime/tab-sync-protocol.d.ts.map +0 -1
  409. package/dist/runtime/tab-sync-protocol.js +0 -54
  410. package/dist/runtime/tab-sync-protocol.js.map +0 -1
  411. package/dist/testing/local-jazz-server.d.ts +0 -2
  412. package/dist/testing/local-jazz-server.d.ts.map +0 -1
  413. package/dist/testing/local-jazz-server.js +0 -2
  414. package/dist/testing/local-jazz-server.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,15 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  // CLI for jazz-tools schema tooling
3
3
  import { existsSync, readFileSync, realpathSync } from "fs";
4
- import { access, mkdir, readFile, readdir, rm, writeFile } from "fs/promises";
5
- import { basename, dirname, join, resolve } from "path";
6
- import { fileURLToPath, pathToFileURL } from "url";
7
- import { build } from "esbuild";
8
- import { schemaDefinitionToAst } from "./migrations.js";
9
- import { loadCompiledSchema } from "./schema-loader.js";
10
- import { collectMissingExplicitPolicyDiagnostics } from "./schema-permissions.js";
11
- import { encodePublishedMigrationValue, fetchPermissionsHead, fetchSchemaConnectivity, fetchSchemaHashes, fetchStoredWasmSchema, publishStoredSchema, publishStoredPermissions, publishStoredMigration, } from "./runtime/schema-fetch.js";
12
- import { toValue } from "./runtime/value-converter.js";
4
+ import { readFile } from "fs/promises";
5
+ import { basename, join, resolve } from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { createMigration as createCatalogueMigration, deploy as deployCatalogue, exportSchema as exportCatalogueSchema, getCurrentSchemaHash, getPermissionsStatus, pushMigration as pushCatalogueMigration, shortSchemaHash, validateProject, } from "./dev/catalogue.js";
13
8
  const PERMISSIONS_LIFECYCLE_NOTE = "Permission-only changes do not create schema hashes or require migrations.";
14
9
  function parseArgs() {
15
10
  const args = process.argv.slice(2);
@@ -30,60 +25,28 @@ function parseArgs() {
30
25
  }
31
26
  return { command, options: { jazzBin, schemaDir } };
32
27
  }
33
- let importCounter = 0;
34
- async function bundleToTempFile(filePath) {
35
- const sourceDir = dirname(resolve(filePath));
36
- const outFile = join(sourceDir, `.jazz-bundle-${++importCounter}.mjs`);
37
- await build({
38
- entryPoints: [resolve(filePath)],
39
- bundle: true,
40
- format: "esm",
41
- platform: "node",
42
- outfile: outFile,
43
- packages: "external",
44
- });
45
- return outFile;
46
- }
47
- async function pathExists(path) {
48
- try {
49
- await access(path);
50
- return true;
51
- }
52
- catch {
53
- return false;
54
- }
55
- }
56
28
  export async function validate(options) {
57
- const compiled = await loadCompiledSchema(options.schemaDir);
58
- const tableCount = compiled.schema.tables.length;
59
- console.log(`Loaded structural schema from ${compiled.schemaFile}.`);
60
- if (compiled.permissionsFile) {
61
- console.log(`Loaded current permissions from ${compiled.permissionsFile}.`);
29
+ const result = await validateProject(options);
30
+ console.log(`Loaded structural schema from ${result.schemaFile}.`);
31
+ if (result.permissionsFile) {
32
+ console.log(`Loaded current permissions from ${result.permissionsFile}.`);
62
33
  console.log(PERMISSIONS_LIFECYCLE_NOTE);
63
34
  console.log("Use `jazz-tools permissions status <appId>` or `jazz-tools deploy <appId>` for auth publication.");
64
35
  }
65
- for (const diagnostic of collectMissingExplicitPolicyDiagnostics(compiled.schema.tables.map((table) => table.name), compiled.permissions)) {
66
- console.warn(`\x1b[33m${diagnostic.message}\x1b[0m`);
36
+ for (const warning of result.warnings) {
37
+ console.warn(`\x1b[33m${warning}\x1b[0m`);
67
38
  }
68
- console.log(`Validated ${tableCount} table${tableCount === 1 ? "" : "s"} in schema.ts.`);
39
+ console.log(`Validated ${result.tableCount} table${result.tableCount === 1 ? "" : "s"} in schema.ts.`);
69
40
  }
70
41
  export async function exportSchema(options) {
71
- if (options.schemaHash) {
72
- const schema = await resolveExportedSchemaByHash(options);
73
- process.stdout.write(`${JSON.stringify(schema, null, 2)}\n`);
74
- return;
75
- }
76
- const currentSchema = await loadCurrentSchema(options.schemaDir);
77
- await ensureLocalSnapshot(options.schemaDir, options.migrationsDir, currentSchema);
78
- process.stdout.write(`${JSON.stringify(currentSchema.schema, null, 2)}\n`);
42
+ const result = await exportCatalogueSchema(options);
43
+ process.stdout.write(`${JSON.stringify(result.schema, null, 2)}\n`);
79
44
  }
80
45
  export async function schemaHash(options) {
81
- const compiled = await loadCompiledSchema(options.schemaDir);
82
- console.log(`Loaded structural schema from ${compiled.schemaFile}.`);
83
- const hash = await computeSchemaHash(compiled.wasmSchema);
84
- console.log(`Current schema hash: ${shortSchemaHash(hash)}`);
46
+ const result = await getCurrentSchemaHash(options);
47
+ console.log(`Loaded structural schema from ${result.schemaFile}.`);
48
+ console.log(`Current schema hash: ${shortSchemaHash(result.hash)}`);
85
49
  }
86
- const SHORT_SCHEMA_HASH_LENGTH = 12;
87
50
  // Framework bundlers (Vite, SvelteKit, Next.js, Expo) expose public env vars
88
51
  // under their own prefix so the client bundle can read them. The CLI often
89
52
  // runs in the same project, so accept those prefixed names as fallbacks for
@@ -221,131 +184,6 @@ function resolvePermissionsOptions(args) {
221
184
  schemaDir,
222
185
  };
223
186
  }
224
- function normalizeSchemaHashInput(hash, label) {
225
- const normalized = hash.trim().toLowerCase();
226
- if (!/^[0-9a-f]{12,64}$/.test(normalized)) {
227
- throw new Error(`${label} must be a 12-64 character lowercase hex schema hash.`);
228
- }
229
- return normalized;
230
- }
231
- function shortSchemaHash(hash) {
232
- return normalizeSchemaHashInput(hash, "schema hash").slice(0, SHORT_SCHEMA_HASH_LENGTH);
233
- }
234
- function hashMatchesFullSchema(hash, fullHash) {
235
- return fullHash.startsWith(normalizeSchemaHashInput(hash, "schema hash"));
236
- }
237
- function resolveKnownSchemaHash(hash, label, knownHashes) {
238
- const normalized = normalizeSchemaHashInput(hash, label);
239
- if (normalized.length === 64) {
240
- if (!knownHashes.includes(normalized)) {
241
- throw new Error(`No stored schema found for ${label} ${normalized}.`);
242
- }
243
- return normalized;
244
- }
245
- const matches = knownHashes.filter((candidate) => candidate.startsWith(normalized));
246
- if (matches.length === 0) {
247
- throw new Error(`No stored schema found for ${label} prefix ${normalized}.`);
248
- }
249
- if (matches.length > 1) {
250
- throw new Error(`${label} prefix ${normalized} is ambiguous: ${matches
251
- .map((candidate) => shortSchemaHash(candidate))
252
- .join(", ")}`);
253
- }
254
- return matches[0];
255
- }
256
- function defaultMigrationsDir(schemaDir) {
257
- return join(schemaDir, "migrations");
258
- }
259
- function resolvedMigrationsDir(schemaDir, migrationsDir) {
260
- return migrationsDir ?? defaultMigrationsDir(schemaDir);
261
- }
262
- function snapshotsDirForMigrations(migrationsDir) {
263
- return join(migrationsDir, "snapshots");
264
- }
265
- function snapshotsDir(schemaDir, migrationsDir) {
266
- return snapshotsDirForMigrations(resolvedMigrationsDir(schemaDir, migrationsDir));
267
- }
268
- // Supports both millisecond and microsecond-precision timestamps
269
- function looksLikeSnapshotFileName(fileName) {
270
- return /^(?:\d{8,17}T\d{6}-)?[0-9a-f]{12}\.json$/i.test(fileName);
271
- }
272
- async function readSnapshotEntry(dir, fileName) {
273
- if (!looksLikeSnapshotFileName(fileName)) {
274
- return null;
275
- }
276
- const filePath = join(dir, fileName);
277
- const schema = JSON.parse(await readFile(filePath, "utf8"));
278
- return {
279
- hash: await computeSchemaHash(schema),
280
- fileName,
281
- filePath,
282
- schema,
283
- };
284
- }
285
- async function listSnapshotEntries(dir) {
286
- if (!(await pathExists(dir))) {
287
- return [];
288
- }
289
- const files = await readdir(dir);
290
- return (await Promise.all(files.map((fileName) => readSnapshotEntry(dir, fileName)))).filter((entry) => entry !== null);
291
- }
292
- async function listLocalSnapshotEntries(schemaDir, migrationsDir) {
293
- return listSnapshotEntries(snapshotsDir(schemaDir, migrationsDir));
294
- }
295
- async function listSnapshotEntriesForMigrations(migrationsDir) {
296
- return listSnapshotEntries(snapshotsDirForMigrations(migrationsDir));
297
- }
298
- async function resolveLocalSnapshotEntry(schemaDir, migrationsDir, hash, label) {
299
- const entries = await listLocalSnapshotEntries(schemaDir, migrationsDir);
300
- if (entries.length === 0) {
301
- return null;
302
- }
303
- const fullHash = normalizeSchemaHashInput(hash, label);
304
- if (fullHash.length === 64) {
305
- return entries.find((entry) => entry.hash === fullHash) ?? null;
306
- }
307
- const matches = entries.filter((entry) => hashMatchesFullSchema(fullHash, entry.hash));
308
- if (matches.length === 0) {
309
- return null;
310
- }
311
- if (matches.length > 1) {
312
- throw new Error(`${label} prefix ${fullHash} is ambiguous: ${matches
313
- .map((entry) => shortSchemaHash(entry.hash))
314
- .join(", ")}`);
315
- }
316
- return matches[0];
317
- }
318
- async function loadLocalSnapshotSchema(schemaDir, migrationsDir, hash, label) {
319
- const entry = await resolveLocalSnapshotEntry(schemaDir, migrationsDir, hash, label);
320
- if (!entry) {
321
- return null;
322
- }
323
- return {
324
- hash: entry.hash,
325
- schema: entry.schema,
326
- };
327
- }
328
- async function writeSnapshotSchema(schemaDir, migrationsDir, hash, schema, timestamp = createTimestamp()) {
329
- const dir = snapshotsDir(schemaDir, migrationsDir);
330
- await mkdir(dir, { recursive: true });
331
- const filePath = join(dir, snapshotFilename(hash, timestamp));
332
- await writeFile(filePath, `${JSON.stringify(schema, null, 2)}\n`);
333
- return filePath;
334
- }
335
- async function ensureLocalSnapshot(schemaDir, migrationsDir, schema) {
336
- const entries = await listLocalSnapshotEntries(schemaDir, migrationsDir);
337
- if (entries.some((entry) => entry.hash === schema.hash)) {
338
- return null;
339
- }
340
- return writeSnapshotSchema(schemaDir, migrationsDir, schema.hash, schema.schema);
341
- }
342
- async function writeSnapshotSchemaForMigrations(migrationsDir, fileName, schema) {
343
- const dir = snapshotsDirForMigrations(migrationsDir);
344
- await mkdir(dir, { recursive: true });
345
- const filePath = join(dir, fileName);
346
- await writeFile(filePath, `${JSON.stringify(schema, null, 2)}\n`);
347
- return filePath;
348
- }
349
187
  function requireSchemaExportServerValue(value, kind) {
350
188
  if (value) {
351
189
  return value;
@@ -368,921 +206,153 @@ function requireMigrationServerOptions(options) {
368
206
  adminSecret: requireSchemaExportServerValue(options.adminSecret, "adminSecret"),
369
207
  };
370
208
  }
371
- async function resolveExportedSchemaByHash(options) {
372
- const schemaHash = normalizeSchemaHashInput(options.schemaHash, "schema hash");
373
- const local = await loadLocalSnapshotSchema(options.schemaDir, options.migrationsDir, schemaHash, "schema hash");
374
- if (local) {
375
- return local.schema;
376
- }
377
- const serverUrl = requireSchemaExportServerValue(options.serverUrl ?? resolveEnvVar(SERVER_URL_ENV_VARS), "serverUrl");
378
- const adminSecret = requireSchemaExportServerValue(options.adminSecret ?? process.env.JAZZ_ADMIN_SECRET, "adminSecret");
379
- const appId = requireAppId(options.appId);
380
- const resolvedHash = schemaHash.length === 64
381
- ? schemaHash
382
- : resolveKnownSchemaHash(schemaHash, "schema hash", (await fetchSchemaHashes(serverUrl, { appId, adminSecret })).hashes);
383
- const storedSchema = await fetchStoredWasmSchema(serverUrl, {
384
- appId,
385
- adminSecret,
386
- schemaHash: resolvedHash,
387
- });
388
- await writeSnapshotSchema(options.schemaDir, options.migrationsDir, resolvedHash, storedSchema.schema, createSnapshotTimestampFromPublishedAt(storedSchema.publishedAt));
389
- return storedSchema.schema;
390
- }
391
- let wasmModulePromise = null;
392
- async function loadCliWasmModule() {
393
- if (!wasmModulePromise) {
394
- wasmModulePromise = import("./runtime/client.js").then(({ loadWasmModule }) => loadWasmModule());
395
- }
396
- return wasmModulePromise;
397
- }
398
- async function computeSchemaHash(schema) {
399
- const wasmModule = await loadCliWasmModule();
400
- const runtime = new wasmModule.WasmRuntime(JSON.stringify(schema), "jazz-tools-cli", "dev", "main", null, null);
401
- try {
402
- return runtime.getSchemaHash();
403
- }
404
- finally {
405
- if (typeof runtime.free === "function") {
406
- runtime.free();
407
- }
408
- }
409
- }
410
- function columnTypeSignature(columnType) {
411
- return JSON.stringify(columnType);
412
- }
413
- function columnsEqual(left, right) {
414
- return (left.name === right.name &&
415
- left.nullable === right.nullable &&
416
- left.references === right.references &&
417
- left.merge_strategy === right.merge_strategy &&
418
- columnTypeSignature(left.column_type) === columnTypeSignature(right.column_type));
419
- }
420
- function indexedColumnsEqual(left, right) {
421
- if (!left && !right) {
422
- return true;
423
- }
424
- if (!left || !right || left.length !== right.length) {
425
- return false;
426
- }
427
- const leftColumns = [...left].sort();
428
- const rightColumns = [...right].sort();
429
- return leftColumns.every((column, index) => column === rightColumns[index]);
430
- }
431
- function tableSchemasEqual(left, right) {
432
- if (!left || !right) {
433
- return false;
434
- }
435
- if (left.columns.length !== right.columns.length) {
436
- return false;
437
- }
438
- if (!indexedColumnsEqual(left.indexed_columns, right.indexed_columns)) {
439
- return false;
440
- }
441
- const leftColumns = [...left.columns].sort((a, b) => a.name.localeCompare(b.name));
442
- const rightColumns = [...right.columns].sort((a, b) => a.name.localeCompare(b.name));
443
- return leftColumns.every((column, index) => columnsEqual(column, rightColumns[index]));
444
- }
445
- function tableSchemasRequireRowTransform(left, right) {
446
- if (!left || !right) {
447
- return true;
448
- }
449
- const leftColumnNames = left.columns.map((column) => column.name).sort();
450
- const rightColumnNames = right.columns.map((column) => column.name).sort();
451
- if (leftColumnNames.length !== rightColumnNames.length) {
452
- return true;
453
- }
454
- for (const [index, columnName] of leftColumnNames.entries()) {
455
- if (columnName !== rightColumnNames[index]) {
456
- return true;
457
- }
458
- }
459
- const leftColumns = new Map(left.columns.map((column) => [column.name, column]));
460
- const rightColumns = new Map(right.columns.map((column) => [column.name, column]));
461
- return leftColumnNames.some((columnName) => {
462
- const leftColumn = leftColumns.get(columnName);
463
- const rightColumn = rightColumns.get(columnName);
464
- return (leftColumn.nullable !== rightColumn.nullable ||
465
- leftColumn.references !== rightColumn.references ||
466
- columnTypeSignature(leftColumn.column_type) !== columnTypeSignature(rightColumn.column_type));
467
- });
468
- }
469
- function wasmSchemasEqual(left, right) {
470
- const leftTableNames = Object.keys(left).sort();
471
- const rightTableNames = Object.keys(right).sort();
472
- if (leftTableNames.length !== rightTableNames.length) {
473
- return false;
474
- }
475
- return leftTableNames.every((tableName, index) => {
476
- if (tableName !== rightTableNames[index]) {
477
- return false;
478
- }
479
- return tableSchemasEqual(left[tableName], right[tableName]);
480
- });
481
- }
482
- function schemaTransitionRequiresRowTransform(fromSchema, toSchema) {
483
- const fromTableNames = Object.keys(fromSchema).sort();
484
- const toTableNames = Object.keys(toSchema).sort();
485
- if (fromTableNames.length !== toTableNames.length) {
486
- return true;
487
- }
488
- for (const [index, tableName] of fromTableNames.entries()) {
489
- if (tableName !== toTableNames[index]) {
490
- return true;
491
- }
492
- }
493
- return fromTableNames.some((tableName) => tableSchemasRequireRowTransform(fromSchema[tableName], toSchema[tableName]));
494
- }
495
- function changedTableNames(fromSchema, toSchema) {
496
- const names = new Set([...Object.keys(fromSchema), ...Object.keys(toSchema)]);
497
- return [...names].filter((tableName) => !tableSchemasEqual(fromSchema[tableName], toSchema[tableName]));
498
- }
499
- function detectPossibleTableRenames(fromSchema, toSchema) {
500
- const removedTables = Object.keys(fromSchema)
501
- .filter((tableName) => !toSchema[tableName])
502
- .sort();
503
- const addedTables = Object.keys(toSchema)
504
- .filter((tableName) => !fromSchema[tableName])
505
- .sort();
506
- const matches = removedTables
507
- .map((oldTableName) => {
508
- const candidateAddedTables = addedTables.filter((newTableName) => tableSchemasEqual(fromSchema[oldTableName], toSchema[newTableName]));
509
- return candidateAddedTables.length === 1
510
- ? [oldTableName, candidateAddedTables[0]]
511
- : undefined;
512
- })
513
- .filter((match) => match !== undefined);
514
- return matches.flatMap(([oldTableName, newTableName], i) => {
515
- const isDuplicateNewTableMatch = matches.some(([_, otherNewTableName], j) => {
516
- return i !== j && newTableName === otherNewTableName;
517
- });
518
- return !isDuplicateNewTableMatch ? [{ oldTableName, newTableName }] : [];
519
- });
520
- }
521
- function ensurePermissionsProject(compiled) {
522
- if (!compiled.permissions || !compiled.permissionsFile) {
523
- throw new Error("No permissions found for this app. Create a permissions.ts file before using permissions commands.");
524
- }
525
- return compiled;
526
- }
527
- /**
528
- * If the provided schema exists in the server, returns its hash. Otherwise, throws an error.
529
- */
530
- async function resolveStoredStructuralSchemaHashOrThrow(appId, serverUrl, adminSecret, wasmSchema) {
531
- const hash = await resolveStoredStructuralSchemaHash(appId, serverUrl, adminSecret, wasmSchema);
532
- if (!hash) {
533
- throw new Error("No stored structural schema matches the local schema.ts. Publish the structural schema before pushing permissions.");
534
- }
535
- return hash;
536
- }
537
- async function resolveStoredStructuralSchemaHash(appId, serverUrl, adminSecret, wasmSchema) {
538
- const { hashes } = await fetchSchemaHashes(serverUrl, { appId, adminSecret });
539
- const storedSchemas = await Promise.all(hashes.map(async (hash) => ({
540
- hash,
541
- schema: (await fetchStoredWasmSchema(serverUrl, { appId, adminSecret, schemaHash: hash }))
542
- .schema,
543
- })));
544
- const match = storedSchemas.find(({ schema }) => wasmSchemasEqual(schema, wasmSchema));
545
- return match?.hash ?? null;
546
- }
547
- function pickWitnessSchema(schema, tableNames) {
548
- const uniqueTableNames = [...new Set(tableNames)];
549
- return Object.fromEntries(uniqueTableNames
550
- .filter((tableName) => schema[tableName])
551
- .map((tableName) => [tableName, schema[tableName]]));
552
- }
553
- function indentBlock(text, indent) {
554
- const prefix = " ".repeat(indent);
555
- return text
556
- .split("\n")
557
- .map((line) => (line.length === 0 ? line : `${prefix}${line}`))
558
- .join("\n");
559
- }
560
- function baseBuilderExpression(columnType, references) {
561
- switch (columnType.type) {
562
- case "Text":
563
- return "s.string()";
564
- case "Boolean":
565
- return "s.boolean()";
566
- case "Integer":
567
- return "s.int()";
568
- case "Double":
569
- return "s.float()";
570
- case "Timestamp":
571
- return "s.timestamp()";
572
- case "Bytea":
573
- return "s.bytes()";
574
- case "Json":
575
- return columnType.schema ? `s.json(${JSON.stringify(columnType.schema)})` : "s.json()";
576
- case "Enum":
577
- return `s.enum(${columnType.variants.map((variant) => JSON.stringify(variant)).join(", ")})`;
578
- case "Uuid":
579
- if (!references) {
580
- throw new Error("Migration stub generation does not yet support bare UUID columns.");
581
- }
582
- return `s.ref(${JSON.stringify(references)})`;
583
- case "Array":
584
- return `s.array(${baseBuilderExpression(columnType.element, references)})`;
585
- case "BigInt":
586
- throw new Error("Migration stub generation does not yet support BIGINT columns.");
587
- case "Row":
588
- throw new Error("Migration stub generation does not yet support row-valued columns.");
589
- }
590
- }
591
- function builderExpressionForColumn(column) {
592
- const base = baseBuilderExpression(column.column_type, column.references);
593
- const withOptional = column.nullable ? `${base}.optional()` : base;
594
- if (column.merge_strategy === "Counter") {
595
- return `${withOptional}.merge("counter")`;
596
- }
597
- return withOptional;
598
- }
599
- function sqlTypeToWasmColumnType(sqlType) {
600
- if (typeof sqlType === "string") {
601
- switch (sqlType) {
602
- case "TEXT":
603
- return { type: "Text" };
604
- case "BOOLEAN":
605
- return { type: "Boolean" };
606
- case "INTEGER":
607
- return { type: "Integer" };
608
- case "REAL":
609
- return { type: "Double" };
610
- case "TIMESTAMP":
611
- return { type: "Timestamp" };
612
- case "UUID":
613
- return { type: "Uuid" };
614
- case "BYTEA":
615
- return { type: "Bytea" };
616
- }
617
- }
618
- if (sqlType.kind === "ENUM") {
619
- return {
620
- type: "Enum",
621
- variants: [...sqlType.variants],
622
- };
623
- }
624
- if (sqlType.kind === "JSON") {
625
- return {
626
- type: "Json",
627
- schema: sqlType.schema,
628
- };
629
- }
630
- return {
631
- type: "Array",
632
- element: sqlTypeToWasmColumnType(sqlType.element),
633
- };
634
- }
635
- function serializeForwardLenses(forward) {
636
- return forward.map((tableLens) => ({
637
- table: tableLens.table,
638
- added: tableLens.added,
639
- removed: tableLens.removed,
640
- renamedFrom: tableLens.renamedFrom,
641
- operations: tableLens.operations.map((op) => {
642
- if (op.type === "rename") {
643
- return op;
644
- }
645
- const columnType = sqlTypeToWasmColumnType(op.sqlType);
646
- const value = encodePublishedMigrationValue(toValue(op.value, columnType));
647
- return {
648
- type: op.type,
649
- column: op.column,
650
- column_type: columnType,
651
- value,
652
- };
653
- }),
654
- }));
655
- }
656
- function renderSchemaWitness(schema) {
657
- const tableEntries = Object.entries(schema)
658
- .sort(([left], [right]) => left.localeCompare(right))
659
- .map(([tableName, tableSchema]) => {
660
- const columnLines = tableSchema.columns.map((column) => `${JSON.stringify(column.name)}: ${builderExpressionForColumn(column)},`);
661
- return `${JSON.stringify(tableName)}: s.table({\n${indentBlock(columnLines.join("\n"), 2)}\n})`;
662
- });
663
- if (tableEntries.length === 0) {
664
- return "{}";
665
- }
666
- return `{\n${indentBlock(tableEntries.join(",\n"), 2)}\n}`;
667
- }
668
- function renderArrayElementExpression(columnType, references) {
669
- return baseBuilderExpression(columnType, references);
670
- }
671
- function renderAddOperationExpression(column, defaultExpression) {
672
- switch (column.column_type.type) {
673
- case "Text":
674
- return `s.add.string({ default: ${defaultExpression} })`;
675
- case "Boolean":
676
- return `s.add.boolean({ default: ${defaultExpression} })`;
677
- case "Integer":
678
- return `s.add.int({ default: ${defaultExpression} })`;
679
- case "Double":
680
- return `s.add.float({ default: ${defaultExpression} })`;
681
- case "Timestamp":
682
- return `s.add.timestamp({ default: ${defaultExpression} })`;
683
- case "Bytea":
684
- return `s.add.bytes({ default: ${defaultExpression} })`;
685
- case "Json":
686
- return column.column_type.schema
687
- ? `s.add.json({ default: ${defaultExpression}, schema: ${JSON.stringify(column.column_type.schema)} })`
688
- : `s.add.json({ default: ${defaultExpression} })`;
689
- case "Enum":
690
- return `s.add.enum(${column.column_type.variants
691
- .map((variant) => JSON.stringify(variant))
692
- .join(", ")}, { default: ${defaultExpression} })`;
693
- case "Uuid":
694
- if (column.references) {
695
- return `s.add.ref(${JSON.stringify(column.references)}, { default: ${defaultExpression} })`;
696
- }
697
- return `s.add.ref("TODO_TABLE", { default: ${defaultExpression} })`;
698
- case "Array":
699
- return `s.add.array({ of: ${renderArrayElementExpression(column.column_type.element, column.references)}, default: ${defaultExpression} })`;
700
- case "BigInt":
701
- throw new Error("Migration stub generation does not yet support BIGINT columns.");
702
- case "Row":
703
- throw new Error("Migration stub generation does not yet support row-valued columns.");
704
- }
705
- }
706
- function renderDropOperationExpression(column, defaultExpression) {
707
- switch (column.column_type.type) {
708
- case "Text":
709
- return `s.drop.string({ backwardsDefault: ${defaultExpression} })`;
710
- case "Boolean":
711
- return `s.drop.boolean({ backwardsDefault: ${defaultExpression} })`;
712
- case "Integer":
713
- return `s.drop.int({ backwardsDefault: ${defaultExpression} })`;
714
- case "Double":
715
- return `s.drop.float({ backwardsDefault: ${defaultExpression} })`;
716
- case "Timestamp":
717
- return `s.drop.timestamp({ backwardsDefault: ${defaultExpression} })`;
718
- case "Bytea":
719
- return `s.drop.bytes({ backwardsDefault: ${defaultExpression} })`;
720
- case "Json":
721
- return column.column_type.schema
722
- ? `s.drop.json({ backwardsDefault: ${defaultExpression}, schema: ${JSON.stringify(column.column_type.schema)} })`
723
- : `s.drop.json({ backwardsDefault: ${defaultExpression} })`;
724
- case "Enum":
725
- return `s.drop.enum(${column.column_type.variants
726
- .map((variant) => JSON.stringify(variant))
727
- .join(", ")}, { backwardsDefault: ${defaultExpression} })`;
728
- case "Uuid":
729
- if (column.references) {
730
- return `s.drop.ref(${JSON.stringify(column.references)}, { backwardsDefault: ${defaultExpression} })`;
731
- }
732
- return `s.drop.ref("TODO_TABLE", { backwardsDefault: ${defaultExpression} })`;
733
- case "Array":
734
- return `s.drop.array({ of: ${renderArrayElementExpression(column.column_type.element, column.references)}, backwardsDefault: ${defaultExpression} })`;
735
- case "BigInt":
736
- throw new Error("Migration stub generation does not yet support BIGINT columns.");
737
- case "Row":
738
- throw new Error("Migration stub generation does not yet support row-valued columns.");
739
- }
740
- }
741
- function inferTableSuggestions(tableName, fromTable, toTable) {
742
- const fromColumns = new Map(fromTable.columns.map((column) => [column.name, column]));
743
- const toColumns = new Map(toTable.columns.map((column) => [column.name, column]));
744
- const comments = [];
745
- const properties = [];
746
- const removedColumns = [...fromColumns.keys()].filter((name) => !toColumns.has(name));
747
- const addedColumns = [...toColumns.keys()].filter((name) => !fromColumns.has(name));
748
- if (removedColumns.length === 1 && addedColumns.length === 1) {
749
- const removed = fromColumns.get(removedColumns[0]);
750
- const added = toColumns.get(addedColumns[0]);
751
- if (removed.nullable === added.nullable &&
752
- removed.references === added.references &&
753
- columnTypeSignature(removed.column_type) === columnTypeSignature(added.column_type)) {
754
- comments.push(`Possible rename detected: ${JSON.stringify(removed.name)} -> ${JSON.stringify(added.name)}.`);
755
- }
756
- }
757
- for (const columnName of addedColumns) {
758
- const column = toColumns.get(columnName);
759
- if (column.nullable) {
760
- properties.push(`${JSON.stringify(columnName)}: ${renderAddOperationExpression(column, "null")},`);
761
- }
762
- else {
763
- comments.push(`Added required column ${JSON.stringify(columnName)} needs an explicit default.`);
764
- }
765
- }
766
- for (const columnName of removedColumns) {
767
- const column = fromColumns.get(columnName);
768
- if (column.nullable) {
769
- properties.push(`${JSON.stringify(columnName)}: ${renderDropOperationExpression(column, "null")},`);
770
- }
771
- else {
772
- comments.push(`Removed required column ${JSON.stringify(columnName)} needs an explicit backwardsDefault.`);
773
- }
774
- }
775
- return {
776
- tableName,
777
- comments,
778
- properties,
779
- };
780
- }
781
- function renderMigrationBody(fromSchema, toSchema) {
782
- const renameSuggestions = detectPossibleTableRenames(fromSchema, toSchema);
783
- const renamedOldTables = new Set(renameSuggestions.map((suggestion) => suggestion.oldTableName));
784
- const renamedNewTables = new Set(renameSuggestions.map((suggestion) => suggestion.newTableName));
785
- const addedTables = Object.keys(toSchema)
786
- .filter((tableName) => !fromSchema[tableName])
787
- .sort();
788
- const removedTables = Object.keys(fromSchema)
789
- .filter((tableName) => !toSchema[tableName])
790
- .sort();
791
- const explicitAddedTables = addedTables.filter((tableName) => !renamedNewTables.has(tableName));
792
- const explicitRemovedTables = removedTables.filter((tableName) => !renamedOldTables.has(tableName));
793
- const changedTables = changedTableNames(fromSchema, toSchema);
794
- const migratableTables = changedTables.filter((tableName) => fromSchema[tableName] !== undefined && toSchema[tableName] !== undefined);
795
- const witnessFromTables = [...migratableTables, ...explicitRemovedTables];
796
- const witnessToTables = [...migratableTables, ...explicitAddedTables];
797
- for (const renameSuggestion of renameSuggestions) {
798
- witnessFromTables.push(renameSuggestion.oldTableName);
799
- witnessToTables.push(renameSuggestion.newTableName);
800
- }
801
- const witnessFrom = pickWitnessSchema(fromSchema, witnessFromTables);
802
- const witnessTo = pickWitnessSchema(toSchema, witnessToTables);
803
- const lines = [];
804
- for (const tableName of migratableTables) {
805
- const fromTable = fromSchema[tableName];
806
- const toTable = toSchema[tableName];
807
- const suggestion = inferTableSuggestions(tableName, fromTable, toTable);
808
- lines.push(`${JSON.stringify(tableName)}: {`);
809
- for (const comment of suggestion.comments) {
810
- lines.push(` // TODO: ${comment}`);
811
- }
812
- for (const property of suggestion.properties) {
813
- lines.push(` ${property}`);
814
- }
815
- if (suggestion.comments.length === 0 && suggestion.properties.length === 0) {
816
- lines.push(" // TODO: No safe migration steps were inferred automatically.");
817
- }
818
- lines.push("},");
819
- lines.push("");
820
- }
821
- if (lines.length === 0) {
822
- if (renameSuggestions.length === 0 &&
823
- explicitAddedTables.length === 0 &&
824
- explicitRemovedTables.length === 0) {
825
- lines.push(changedTables.length === 0
826
- ? "// TODO: No schema differences were detected."
827
- : "// TODO: No column-level migration steps were required for the detected schema changes.");
828
- }
829
- }
830
- return {
831
- migrateBody: lines.length > 0 ? lines.join("\n").trimEnd() : undefined,
832
- createTablesBody: explicitAddedTables.length > 0
833
- ? explicitAddedTables.map((tableName) => `${JSON.stringify(tableName)}: true,`).join("\n")
834
- : undefined,
835
- dropTablesBody: explicitRemovedTables.length > 0
836
- ? explicitRemovedTables.map((tableName) => `${JSON.stringify(tableName)}: true,`).join("\n")
837
- : undefined,
838
- renameTablesBody: renameSuggestions.length > 0
839
- ? renameSuggestions
840
- .map((renameSuggestion) => `${renameSuggestion.newTableName}: s.renameTableFrom(${JSON.stringify(renameSuggestion.oldTableName)}),`)
841
- .join("\n")
842
- : undefined,
843
- witnessFrom,
844
- witnessTo,
845
- };
846
- }
847
209
  async function packageVersion() {
848
210
  const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
849
211
  return packageJson.version ?? "unknown";
850
212
  }
851
- function createTimestamp(now = new Date()) {
852
- const year = now.getUTCFullYear();
853
- const month = String(now.getUTCMonth() + 1).padStart(2, "0");
854
- const day = String(now.getUTCDate()).padStart(2, "0");
855
- const hours = String(now.getUTCHours()).padStart(2, "0");
856
- const minutes = String(now.getUTCMinutes()).padStart(2, "0");
857
- const seconds = String(now.getUTCSeconds()).padStart(2, "0");
858
- return `${year}${month}${day}T${hours}${minutes}${seconds}`;
859
- }
860
- function createSnapshotTimestampFromPublishedAt(publishedAt, fallbackNow = new Date()) {
861
- if (typeof publishedAt !== "number" || !Number.isFinite(publishedAt) || publishedAt < 0) {
862
- return createTimestamp(fallbackNow);
863
- }
864
- return createTimestamp(new Date(publishedAt));
865
- }
866
- function normalizeMigrationName(name) {
867
- const normalized = name
868
- .trim()
869
- .toLowerCase()
870
- .replace(/[^a-z0-9]+/g, "-")
871
- .replace(/^-+|-+$/g, "");
872
- if (normalized.length === 0) {
873
- throw new Error("Migration name must contain at least one ASCII letter or digit after normalization.");
874
- }
875
- return normalized;
876
- }
877
- function migrationFilename(migrationsDir, fromHash, toHash, name = "unnamed", timestamp = createTimestamp()) {
878
- return join(migrationsDir, `${timestamp}-${name}-${shortSchemaHash(fromHash)}-${shortSchemaHash(toHash)}.ts`);
879
- }
880
- function snapshotFilename(hash, timestamp = createTimestamp()) {
881
- return `${timestamp}-${shortSchemaHash(hash)}.json`;
882
- }
883
- function renderMigrationStub(input) {
884
- const rendered = renderMigrationBody(input.fromSchema, input.toSchema);
885
- const sections = [];
886
- if (rendered.renameTablesBody) {
887
- sections.push(` renameTables: {\n${indentBlock(rendered.renameTablesBody, 4)}\n },`);
888
- }
889
- if (rendered.createTablesBody) {
890
- sections.push(` createTables: {\n${indentBlock(rendered.createTablesBody, 4)}\n },`);
891
- }
892
- if (rendered.dropTablesBody) {
893
- sections.push(` dropTables: {\n${indentBlock(rendered.dropTablesBody, 4)}\n },`);
894
- }
895
- if (rendered.migrateBody) {
896
- sections.push(` migrate: {\n${indentBlock(rendered.migrateBody, 4)}\n },`);
897
- }
898
- sections.push(` fromHash: ${JSON.stringify(shortSchemaHash(input.fromHash))},`);
899
- sections.push(` toHash: ${JSON.stringify(shortSchemaHash(input.toHash))},`);
900
- sections.push(` from: ${renderSchemaWitness(rendered.witnessFrom)},`);
901
- sections.push(` to: ${renderSchemaWitness(rendered.witnessTo)},`);
902
- return `import { schema as s } from "jazz-tools";
903
-
904
- export default s.defineMigration({
905
- ${sections.join("\n")}
906
- });
907
- `;
908
- }
909
- function isDefinedMigration(value) {
910
- if (typeof value !== "object" || value === null) {
911
- return false;
912
- }
913
- const candidate = value;
914
- return (typeof candidate.fromHash === "string" &&
915
- typeof candidate.toHash === "string" &&
916
- typeof candidate.from === "object" &&
917
- candidate.from !== null &&
918
- typeof candidate.to === "object" &&
919
- candidate.to !== null &&
920
- Array.isArray(candidate.forward));
921
- }
922
- async function loadDefinedMigration(filePath) {
923
- const outFile = await bundleToTempFile(filePath);
924
- try {
925
- const loaded = (await import(pathToFileURL(outFile).href));
926
- const migration = unwrapMigrationExport(loaded.default ?? loaded.migration);
927
- if (!isDefinedMigration(migration)) {
928
- throw new Error(`Invalid migration export in ${basename(filePath)}. Export default defineMigration(...).`);
929
- }
930
- return migration;
931
- }
932
- finally {
933
- await rm(outFile, { force: true }).catch(() => undefined);
934
- }
935
- }
936
- function unwrapMigrationExport(value) {
937
- let current = value;
938
- while (typeof current === "object" &&
939
- current !== null &&
940
- "default" in current &&
941
- Object.keys(current).length === 1) {
942
- current = current.default;
943
- }
944
- return current;
945
- }
946
- async function findMigrationFile(migrationsDir, fromHash, toHash) {
947
- if (!(await pathExists(migrationsDir))) {
948
- throw new Error(`No migration file found in ${migrationsDir} for ${fromHash} -> ${toHash}.`);
949
- }
950
- const fromShortHash = shortSchemaHash(fromHash);
951
- const toShortHash = shortSchemaHash(toHash);
952
- const files = await readdir(migrationsDir);
953
- const matches = files
954
- .filter((file) => file.endsWith(".ts"))
955
- .filter((file) => file.includes(`-${fromShortHash}-${toShortHash}.ts`) ||
956
- file.includes(`-${fromHash}-${toHash}.ts`));
957
- if (matches.length === 0) {
958
- throw new Error(`No migration file found in ${migrationsDir} for ${fromHash} -> ${toHash}.`);
959
- }
960
- if (matches.length > 1) {
961
- throw new Error(`Multiple migration files found for ${fromHash} -> ${toHash}: ${matches.join(", ")}`);
962
- }
963
- return join(migrationsDir, matches[0]);
964
- }
965
- function isCommittedSnapshotFileName(fileName) {
966
- return /^\d{8}T\d{6}-[0-9a-f]{12}\.json$/i.test(fileName);
967
- }
968
- async function loadLatestCommittedSnapshot(migrationsDir) {
969
- const entries = await listSnapshotEntriesForMigrations(migrationsDir);
970
- const latest = entries
971
- .filter((entry) => isCommittedSnapshotFileName(entry.fileName))
972
- .sort((left, right) => left.fileName.localeCompare(right.fileName))
973
- .at(-1);
974
- if (!latest) {
975
- return null;
976
- }
977
- return {
978
- hash: latest.hash,
979
- schema: latest.schema,
980
- };
981
- }
982
- async function ensureCommittedSnapshot(migrationsDir, schema, timestamp) {
983
- const entries = await listSnapshotEntriesForMigrations(migrationsDir);
984
- if (entries.some((entry) => entry.hash === schema.hash && isCommittedSnapshotFileName(entry.fileName))) {
985
- return null;
986
- }
987
- return writeSnapshotSchemaForMigrations(migrationsDir, snapshotFilename(schema.hash, timestamp), schema.schema);
988
- }
989
- async function loadCurrentSchema(schemaDir) {
990
- const compiled = await loadCompiledSchema(schemaDir);
991
- return {
992
- hash: await computeSchemaHash(compiled.wasmSchema),
993
- schema: compiled.wasmSchema,
994
- };
995
- }
996
- async function resolveHistoricalSchema(migrationsDir, hash, label, appId, serverUrl, adminSecret) {
997
- const localEntries = await listSnapshotEntriesForMigrations(migrationsDir);
998
- const normalized = normalizeSchemaHashInput(hash, label);
999
- const localFullHash = normalized.length === 64
1000
- ? localEntries.find((entry) => entry.hash === normalized)?.hash
1001
- : (() => {
1002
- const matches = localEntries.filter((entry) => entry.hash.startsWith(normalized));
1003
- if (matches.length === 0) {
1004
- return null;
1005
- }
1006
- if (matches.length > 1) {
1007
- throw new Error(`${label} prefix ${normalized} is ambiguous: ${matches
1008
- .map((entry) => shortSchemaHash(entry.hash))
1009
- .join(", ")}`);
1010
- }
1011
- return matches[0].hash;
1012
- })();
1013
- if (localFullHash) {
1014
- return {
1015
- hash: localFullHash,
1016
- schema: localEntries.find((entry) => entry.hash === localFullHash).schema,
1017
- };
1018
- }
1019
- const resolvedHash = normalized.length === 64
1020
- ? normalized
1021
- : resolveKnownSchemaHash(normalized, label, (await fetchSchemaHashes(requireSchemaExportServerValue(serverUrl, "serverUrl"), {
1022
- appId: requireAppId(appId),
1023
- adminSecret: requireSchemaExportServerValue(adminSecret, "adminSecret"),
1024
- })).hashes);
1025
- const resolvedAppId = requireAppId(appId);
1026
- const resolvedServerUrl = requireSchemaExportServerValue(serverUrl, "serverUrl");
1027
- const resolvedAdminSecret = requireSchemaExportServerValue(adminSecret, "adminSecret");
1028
- try {
1029
- const storedSchema = await fetchStoredWasmSchema(resolvedServerUrl, {
1030
- appId: resolvedAppId,
1031
- adminSecret: resolvedAdminSecret,
1032
- schemaHash: resolvedHash,
1033
- });
1034
- await writeSnapshotSchemaForMigrations(migrationsDir, snapshotFilename(resolvedHash, createSnapshotTimestampFromPublishedAt(storedSchema.publishedAt)), storedSchema.schema);
1035
- return { hash: resolvedHash, schema: storedSchema.schema };
1036
- }
1037
- catch (error) {
1038
- if (error instanceof Error && /Schema fetch failed: 404/i.test(error.message)) {
1039
- throw new Error(`No stored schema found for ${label} ${resolvedHash}.`);
1040
- }
1041
- throw error;
1042
- }
1043
- }
1044
213
  export async function createMigration(options) {
1045
- const explicitHashFlow = Boolean(options.fromHash || options.toHash);
1046
- await mkdir(options.migrationsDir, { recursive: true });
1047
- const currentSchema = !explicitHashFlow || !options.toHash ? await loadCurrentSchema(options.schemaDir) : null;
1048
- let fromSchema;
1049
- let toSchema;
1050
- let shouldWriteCommittedSnapshot = false;
1051
- const timestamp = createTimestamp();
1052
- if (explicitHashFlow) {
1053
- if (options.fromHash) {
1054
- fromSchema = await resolveHistoricalSchema(options.migrationsDir, options.fromHash, "fromHash", options.appId, options.serverUrl, options.adminSecret);
1055
- }
1056
- else {
1057
- const latest = await loadLatestCommittedSnapshot(options.migrationsDir);
1058
- if (!latest) {
1059
- throw new Error("No committed snapshot found. Provide --fromHash or run `jazz-tools migrations create` once to create an initial snapshot.");
1060
- }
1061
- fromSchema = latest;
1062
- }
1063
- toSchema = options.toHash
1064
- ? await resolveHistoricalSchema(options.migrationsDir, options.toHash, "toHash", options.appId, options.serverUrl, options.adminSecret)
1065
- : currentSchema;
1066
- shouldWriteCommittedSnapshot = !options.toHash;
1067
- }
1068
- else {
1069
- const latest = await loadLatestCommittedSnapshot(options.migrationsDir);
1070
- if (!latest) {
1071
- const snapshotPath = await ensureCommittedSnapshot(options.migrationsDir, currentSchema, timestamp);
1072
- console.log(`Wrote initial schema snapshot: ${snapshotPath}`);
214
+ const result = await createCatalogueMigration(options);
215
+ switch (result.status) {
216
+ case "initial-snapshot":
217
+ console.log("Wrote initial schema snapshot: " + result.snapshotPath);
1073
218
  console.log("No migration created because there was no previous local schema baseline.");
1074
219
  return null;
1075
- }
1076
- if (latest.hash === currentSchema.hash) {
220
+ case "unchanged":
1077
221
  console.log("No structural schema changes detected.");
1078
222
  return null;
223
+ case "migration-not-required": {
224
+ const version = await packageVersion();
225
+ console.log("No reviewed migration file needed because this schema change does not require row transformations.");
226
+ console.log("Next step: Run npx jazz-tools@" +
227
+ version +
228
+ " migrations push " +
229
+ (options.appId ?? "<appId>") +
230
+ " " +
231
+ shortSchemaHash(result.fromHash) +
232
+ " " +
233
+ shortSchemaHash(result.toHash));
234
+ return null;
1079
235
  }
1080
- fromSchema = latest;
1081
- toSchema = currentSchema;
1082
- shouldWriteCommittedSnapshot = true;
1083
- }
1084
- if (fromSchema.hash === toSchema.hash) {
1085
- console.log("No structural schema changes detected.");
1086
- return null;
1087
- }
1088
- if (!schemaTransitionRequiresRowTransform(fromSchema.schema, toSchema.schema)) {
1089
- if (shouldWriteCommittedSnapshot) {
1090
- await ensureCommittedSnapshot(options.migrationsDir, toSchema, timestamp);
236
+ case "generated": {
237
+ const version = await packageVersion();
238
+ console.log("Generated: " + result.filePath);
239
+ console.log("");
240
+ console.log("Migration stubs are only for structural schema changes.");
241
+ console.log(PERMISSIONS_LIFECYCLE_NOTE);
242
+ console.log("");
243
+ console.log("Next steps:");
244
+ console.log("1. Fill in migrate.");
245
+ if (result.needsRename) {
246
+ console.log("2. Rename the file by replacing 'unnamed'.");
247
+ }
248
+ console.log((result.needsRename ? "3" : "2") +
249
+ ". Run npx jazz-tools@" +
250
+ version +
251
+ " migrations push " +
252
+ (options.appId ?? "<appId>") +
253
+ " " +
254
+ shortSchemaHash(result.fromHash) +
255
+ " " +
256
+ shortSchemaHash(result.toHash));
257
+ return result.filePath;
1091
258
  }
1092
- const version = await packageVersion();
1093
- console.log("No reviewed migration file needed because this schema change does not require row transformations.");
1094
- console.log(`Next step: Run npx jazz-tools@${version} migrations push ${options.appId ?? "<appId>"} ${shortSchemaHash(fromSchema.hash)} ${shortSchemaHash(toSchema.hash)}`);
1095
- return null;
1096
259
  }
1097
- const filePath = migrationFilename(options.migrationsDir, fromSchema.hash, toSchema.hash, options.name ? normalizeMigrationName(options.name) : undefined, timestamp);
1098
- if (await pathExists(filePath)) {
1099
- throw new Error(`Migration stub already exists: ${filePath}`);
1100
- }
1101
- const stub = renderMigrationStub({
1102
- fromHash: fromSchema.hash,
1103
- toHash: toSchema.hash,
1104
- fromSchema: fromSchema.schema,
1105
- toSchema: toSchema.schema,
1106
- });
1107
- await writeFile(filePath, stub);
1108
- if (shouldWriteCommittedSnapshot) {
1109
- await ensureCommittedSnapshot(options.migrationsDir, toSchema, timestamp);
1110
- }
1111
- const version = await packageVersion();
1112
- console.log(`Generated: ${filePath}`);
1113
- console.log("");
1114
- console.log("Migration stubs are only for structural schema changes.");
1115
- console.log(PERMISSIONS_LIFECYCLE_NOTE);
1116
- console.log("");
1117
- console.log("Next steps:");
1118
- console.log("1. Fill in migrate.");
1119
- if (!options.name) {
1120
- console.log("2. Rename the file by replacing 'unnamed'.");
1121
- }
1122
- console.log(`${options.name ? "2" : "3"}. Run npx jazz-tools@${version} migrations push ${options.appId ?? "<appId>"} ${shortSchemaHash(fromSchema.hash)} ${shortSchemaHash(toSchema.hash)}`);
1123
- return filePath;
1124
260
  }
1125
261
  export async function pushMigration(options) {
1126
262
  const { appId, serverUrl, adminSecret } = requireMigrationServerOptions(options);
1127
- const { hashes } = await fetchSchemaHashes(serverUrl, {
263
+ const result = await pushCatalogueMigration({
1128
264
  appId,
265
+ serverUrl,
1129
266
  adminSecret,
267
+ migrationsDir: options.migrationsDir,
268
+ fromHash: options.fromHash,
269
+ toHash: options.toHash,
1130
270
  });
1131
- const fromHash = resolveKnownSchemaHash(options.fromHash, "fromHash", hashes);
1132
- const toHash = resolveKnownSchemaHash(options.toHash, "toHash", hashes);
1133
- let filePath = null;
1134
- try {
1135
- filePath = await findMigrationFile(options.migrationsDir, fromHash, toHash);
1136
- }
1137
- catch (error) {
1138
- if (!(error instanceof Error) ||
1139
- !error.message.startsWith(`No migration file found in ${options.migrationsDir}`)) {
1140
- throw error;
1141
- }
1142
- }
1143
- if (!filePath) {
1144
- const fromSchema = await resolveHistoricalSchema(options.migrationsDir, fromHash, "fromHash", appId, serverUrl, adminSecret);
1145
- const toSchema = await resolveHistoricalSchema(options.migrationsDir, toHash, "toHash", appId, serverUrl, adminSecret);
1146
- if (schemaTransitionRequiresRowTransform(fromSchema.schema, toSchema.schema)) {
1147
- throw new Error(`No migration file found in ${options.migrationsDir} for ${fromHash} -> ${toHash}. Run \`jazz-tools migrations create ${appId} --fromHash ${shortSchemaHash(fromHash)} --toHash ${shortSchemaHash(toHash)}\` first.`);
1148
- }
1149
- await publishStoredMigration(serverUrl, {
1150
- appId,
1151
- adminSecret,
1152
- fromHash,
1153
- toHash,
1154
- forward: [],
1155
- });
1156
- console.log(`Pushed migration ${shortSchemaHash(fromHash)} -> ${shortSchemaHash(toHash)} without a reviewed migration file because no row transformations are required.`);
271
+ if (result.filePath) {
272
+ console.log(`Pushed migration ${shortSchemaHash(result.fromHash)} -> ${shortSchemaHash(result.toHash)} from ${basename(result.filePath)}.`);
1157
273
  return;
1158
274
  }
1159
- const migration = await loadDefinedMigration(filePath);
1160
- if (!hashMatchesFullSchema(migration.fromHash, fromHash) ||
1161
- !hashMatchesFullSchema(migration.toHash, toHash)) {
1162
- throw new Error(`Migration ${basename(filePath)} exports ${migration.fromHash} -> ${migration.toHash}, expected ${shortSchemaHash(fromHash)} -> ${shortSchemaHash(toHash)}.`);
1163
- }
1164
- schemaDefinitionToAst(migration.from);
1165
- schemaDefinitionToAst(migration.to);
1166
- if (migration.forward.length === 0) {
1167
- const fromSchema = await resolveHistoricalSchema(options.migrationsDir, fromHash, "fromHash", appId, serverUrl, adminSecret);
1168
- const toSchema = await resolveHistoricalSchema(options.migrationsDir, toHash, "toHash", appId, serverUrl, adminSecret);
1169
- if (schemaTransitionRequiresRowTransform(fromSchema.schema, toSchema.schema)) {
1170
- throw new Error(`Migration ${basename(filePath)} has no steps. Fill in migrate before push.`);
1171
- }
1172
- }
1173
- const forward = migration.forward.length === 0 ? [] : serializeForwardLenses(migration.forward);
1174
- await publishStoredMigration(serverUrl, {
1175
- appId,
1176
- adminSecret,
1177
- fromHash,
1178
- toHash,
1179
- forward,
1180
- });
1181
- console.log(`Pushed migration ${shortSchemaHash(fromHash)} -> ${shortSchemaHash(toHash)} from ${basename(filePath)}.`);
275
+ console.log(`Pushed migration ${shortSchemaHash(result.fromHash)} -> ${shortSchemaHash(result.toHash)} without a reviewed migration file because no row transformations are required.`);
1182
276
  }
1183
277
  function describePermissionsHead(head) {
1184
278
  return `v${head.version} on ${shortSchemaHash(head.schemaHash)}`;
1185
279
  }
280
+ function logDeployWarning(message) {
281
+ if (message.startsWith("Warning: table ")) {
282
+ console.warn(`\x1b[33m${message}\x1b[0m`);
283
+ return;
284
+ }
285
+ if (message.startsWith("Warning: ")) {
286
+ console.warn(message);
287
+ return;
288
+ }
289
+ console.warn(`Warning: ${message}`);
290
+ }
1186
291
  export async function permissionsStatus(options) {
1187
- const compiled = ensurePermissionsProject(await loadCompiledSchema(options.schemaDir));
1188
- const localSchemaHash = await resolveStoredStructuralSchemaHashOrThrow(options.appId, options.serverUrl, options.adminSecret, compiled.wasmSchema);
1189
- const { head } = await fetchPermissionsHead(options.serverUrl, {
1190
- appId: options.appId,
1191
- adminSecret: options.adminSecret,
1192
- });
1193
- console.log(`Loaded structural schema from ${compiled.schemaFile}.`);
1194
- console.log(`Loaded current permissions from ${compiled.permissionsFile}.`);
1195
- console.log(`Local structural schema matches stored hash ${shortSchemaHash(localSchemaHash)}.`);
292
+ const result = await getPermissionsStatus(options);
293
+ console.log(`Loaded structural schema from ${result.schemaFile}.`);
294
+ console.log(`Loaded current permissions from ${result.permissionsFile}.`);
295
+ console.log(`Local structural schema matches stored hash ${shortSchemaHash(result.localSchemaHash)}.`);
1196
296
  console.log(PERMISSIONS_LIFECYCLE_NOTE);
1197
- if (!head) {
297
+ if (!result.head) {
1198
298
  console.log("Server has no published permissions head yet.");
1199
299
  console.log("Next push will publish version 1.");
1200
300
  return;
1201
301
  }
1202
- console.log(`Server permissions head is ${describePermissionsHead(head)}.`);
1203
- if (head.schemaHash === localSchemaHash) {
302
+ console.log(`Server permissions head is ${describePermissionsHead(result.head)}.`);
303
+ if (result.head.schemaHash === result.localSchemaHash) {
1204
304
  console.log("Current server permissions already target this structural schema.");
1205
305
  }
1206
306
  else {
1207
- console.log(`Current server permissions target ${shortSchemaHash(head.schemaHash)}; pushing will retarget the head to ${shortSchemaHash(localSchemaHash)}.`);
307
+ console.log(`Current server permissions target ${shortSchemaHash(result.head.schemaHash)}; pushing will retarget the head to ${shortSchemaHash(result.localSchemaHash)}.`);
1208
308
  }
1209
- console.log(`Next push will require parent bundle ${head.bundleObjectId}.`);
309
+ console.log(`Next push will require parent bundle ${result.head.bundleObjectId}.`);
1210
310
  }
1211
311
  export async function deploy(options) {
1212
- const compiled = await loadCompiledSchema(options.schemaDir);
1213
- console.log(`Loaded current schema from ${compiled.schemaFile}.`);
1214
- for (const diagnostic of collectMissingExplicitPolicyDiagnostics(compiled.schema.tables.map((table) => table.name), compiled.permissions)) {
1215
- console.warn(`\x1b[33m${diagnostic.message}\x1b[0m`);
1216
- }
1217
- let localSchemaHash = await resolveStoredStructuralSchemaHash(options.appId, options.serverUrl, options.adminSecret, compiled.wasmSchema);
1218
- if (!localSchemaHash) {
1219
- const publishedSchema = await publishStoredSchema(options.serverUrl, {
1220
- appId: options.appId,
1221
- adminSecret: options.adminSecret,
1222
- schema: compiled.wasmSchema,
1223
- });
1224
- localSchemaHash = publishedSchema.hash;
1225
- console.log(`Published the current schema as ${shortSchemaHash(localSchemaHash)}.`);
1226
- }
1227
- else {
1228
- console.log(`The current schema is already stored in the server as ${shortSchemaHash(localSchemaHash)}; skipping publish.`);
1229
- }
1230
- if (!compiled.permissions || !compiled.permissionsFile) {
1231
- console.log("No permissions.ts found; skipping permissions publish.");
1232
- return;
1233
- }
1234
- console.log(`Loaded current permissions from ${compiled.permissionsFile}.`);
1235
- const { head: currentHead } = await fetchPermissionsHead(options.serverUrl, {
1236
- appId: options.appId,
1237
- adminSecret: options.adminSecret,
1238
- });
1239
- if (currentHead && currentHead.schemaHash !== localSchemaHash) {
1240
- const fromShortHash = shortSchemaHash(currentHead.schemaHash);
1241
- const toShortHash = shortSchemaHash(localSchemaHash);
1242
- try {
1243
- const { connected } = await fetchSchemaConnectivity(options.serverUrl, {
1244
- appId: options.appId,
1245
- adminSecret: options.adminSecret,
1246
- fromHash: currentHead.schemaHash,
1247
- toHash: localSchemaHash,
1248
- });
1249
- if (!connected) {
1250
- await pushMigration({
1251
- appId: options.appId,
1252
- serverUrl: options.serverUrl,
1253
- adminSecret: options.adminSecret,
1254
- migrationsDir: options.migrationsDir,
1255
- fromHash: currentHead.schemaHash,
1256
- toHash: localSchemaHash,
1257
- });
312
+ const result = await deployCatalogue({
313
+ ...options,
314
+ onEvent: (event) => {
315
+ switch (event.type) {
316
+ case "schema-loaded":
317
+ console.log(`Loaded current schema from ${event.schemaFile}.`);
318
+ break;
319
+ case "warning":
320
+ logDeployWarning(event.message);
321
+ break;
322
+ case "schema-published":
323
+ console.log(`Published the current schema as ${shortSchemaHash(event.hash)}.`);
324
+ break;
325
+ case "schema-skipped":
326
+ console.log(`The current schema is already stored in the server as ${shortSchemaHash(event.hash)}; skipping publish.`);
327
+ break;
328
+ case "permissions-skipped":
329
+ console.log("No permissions.ts found; skipping permissions publish.");
330
+ break;
331
+ case "permissions-loaded":
332
+ console.log(`Loaded current permissions from ${event.permissionsFile}.`);
333
+ break;
334
+ case "migration-published":
335
+ if (event.filePath) {
336
+ console.log(`Pushed migration ${shortSchemaHash(event.fromHash)} -> ${shortSchemaHash(event.toHash)} from ${basename(event.filePath)}.`);
337
+ }
338
+ else {
339
+ console.log(`Pushed migration ${shortSchemaHash(event.fromHash)} -> ${shortSchemaHash(event.toHash)} without a reviewed migration file because no row transformations are required.`);
340
+ }
341
+ break;
342
+ case "permissions-published":
343
+ break;
1258
344
  }
1259
- }
1260
- catch (error) {
1261
- const migrationMissingPrefix = `No migration file found in ${options.migrationsDir}`;
1262
- if (!(error instanceof Error) || !error.message.startsWith(migrationMissingPrefix)) {
1263
- throw error;
1264
- }
1265
- const message = `The new permissions schema ${toShortHash} is not connected to the previous permissions schema ${fromShortHash} on the server. Reads and writes may fail until you push a migration. Run \`jazz-tools migrations create ${options.appId} --fromHash ${fromShortHash} --toHash ${toShortHash}\` to create a migration and then re-run this command.`;
1266
- if (options.noVerify) {
1267
- console.warn(`Warning: ${message}`);
1268
- }
1269
- else {
1270
- throw Error(message);
1271
- }
1272
- }
1273
- }
1274
- const { head: publishedHead } = await publishStoredPermissions(options.serverUrl, {
1275
- appId: options.appId,
1276
- adminSecret: options.adminSecret,
1277
- schemaHash: localSchemaHash,
1278
- permissions: compiled.permissions,
1279
- expectedParentBundleObjectId: currentHead?.bundleObjectId ?? null,
345
+ },
1280
346
  });
1281
- const nextHead = publishedHead ?? {
1282
- schemaHash: localSchemaHash,
1283
- version: currentHead ? currentHead.version + 1 : 1,
1284
- parentBundleObjectId: currentHead?.bundleObjectId ?? null,
1285
- bundleObjectId: currentHead?.bundleObjectId ?? "",
347
+ if (!result.permissions) {
348
+ return;
349
+ }
350
+ const previousHead = result.permissions.previousHead;
351
+ const nextHead = result.permissions.head ?? {
352
+ schemaHash: result.permissions.schemaHash,
353
+ version: previousHead ? previousHead.version + 1 : 1,
354
+ parentBundleObjectId: previousHead?.bundleObjectId ?? null,
355
+ bundleObjectId: previousHead?.bundleObjectId ?? "",
1286
356
  };
1287
357
  console.log(`Published permissions as ${describePermissionsHead(nextHead)}.`);
1288
358
  }