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.
- package/bin/docs-index.txt +5 -6
- package/bin/native/jazz-tools-darwin-arm64 +0 -0
- package/bin/native/jazz-tools-darwin-x64 +0 -0
- package/bin/native/jazz-tools-linux-arm64 +0 -0
- package/bin/native/jazz-tools-linux-x64 +0 -0
- package/dist/backend/index.d.ts +1 -0
- package/dist/backend/index.d.ts.map +1 -1
- package/dist/backend/index.js +1 -0
- package/dist/backend/index.js.map +1 -1
- package/dist/better-auth-adapter/index.test.js +11 -11
- package/dist/better-auth-adapter/index.test.js.map +1 -1
- package/dist/better-auth-adapter/utils.d.ts.map +1 -1
- package/dist/better-auth-adapter/utils.js +3 -37
- package/dist/better-auth-adapter/utils.js.map +1 -1
- package/dist/better-auth-adapter/utils.test.js +44 -0
- package/dist/better-auth-adapter/utils.test.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +125 -1055
- package/dist/cli.js.map +1 -1
- package/dist/codegen/schema-reader.d.ts.map +1 -1
- package/dist/codegen/schema-reader.js +6 -0
- package/dist/codegen/schema-reader.js.map +1 -1
- package/dist/dev/catalogue.d.ts +212 -0
- package/dist/dev/catalogue.d.ts.map +1 -0
- package/dist/dev/catalogue.js +879 -0
- package/dist/dev/catalogue.js.map +1 -0
- package/dist/dev/catalogue.test.d.ts +2 -0
- package/dist/dev/catalogue.test.d.ts.map +1 -0
- package/dist/dev/catalogue.test.js +607 -0
- package/dist/dev/catalogue.test.js.map +1 -0
- package/dist/dev/dev-server.d.ts +16 -15
- package/dist/dev/dev-server.d.ts.map +1 -1
- package/dist/dev/dev-server.js +23 -34
- package/dist/dev/dev-server.js.map +1 -1
- package/dist/dev/dev-server.test.js +12 -7
- package/dist/dev/dev-server.test.js.map +1 -1
- package/dist/dev/expo.test.js +3 -3
- package/dist/dev/expo.test.js.map +1 -1
- package/dist/dev/index.d.ts +2 -1
- package/dist/dev/index.d.ts.map +1 -1
- package/dist/dev/index.js +2 -1
- package/dist/dev/index.js.map +1 -1
- package/dist/dev/managed-runtime.d.ts.map +1 -1
- package/dist/dev/managed-runtime.js +5 -4
- package/dist/dev/managed-runtime.js.map +1 -1
- package/dist/dev/managed-runtime.test.js +11 -4
- package/dist/dev/managed-runtime.test.js.map +1 -1
- package/dist/dev/migrations.d.ts +8 -0
- package/dist/dev/migrations.d.ts.map +1 -0
- package/dist/dev/migrations.js +300 -0
- package/dist/dev/migrations.js.map +1 -0
- package/dist/dev/next.js +1 -1
- package/dist/dev/next.js.map +1 -1
- package/dist/dev/next.test.js +21 -10
- package/dist/dev/next.test.js.map +1 -1
- package/dist/dev/schema-utils.d.ts +7 -0
- package/dist/dev/schema-utils.d.ts.map +1 -0
- package/dist/dev/schema-utils.js +60 -0
- package/dist/dev/schema-utils.js.map +1 -0
- package/dist/dev/schema-watcher.js +3 -3
- package/dist/dev/schema-watcher.js.map +1 -1
- package/dist/dev/sveltekit.test.js +33 -22
- package/dist/dev/sveltekit.test.js.map +1 -1
- package/dist/dev/vite.test.js +13 -3
- package/dist/dev/vite.test.js.map +1 -1
- package/dist/dev-tools/dev-tools.js +1 -1
- package/dist/dev-tools/dev-tools.test.js +5 -5
- package/dist/dev-tools/extension-panel.js +0 -3
- package/dist/dev-tools/extension-panel.js.map +1 -1
- package/dist/drivers/types.d.ts +1 -1
- package/dist/drivers/types.d.ts.map +1 -1
- package/dist/dsl.d.ts +9 -1
- package/dist/dsl.d.ts.map +1 -1
- package/dist/dsl.js +8 -2
- package/dist/dsl.js.map +1 -1
- package/dist/dsl.test.js +34 -0
- package/dist/dsl.test.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/permissions/index.d.ts +3 -3
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/react-core/provider.d.ts.map +1 -1
- package/dist/react-core/provider.js +43 -43
- package/dist/react-core/provider.js.map +1 -1
- package/dist/react-core/provider.onjwtexpired.test.js +49 -1
- package/dist/react-core/provider.onjwtexpired.test.js.map +1 -1
- package/dist/react-core/use-all.d.ts +13 -1
- package/dist/react-core/use-all.d.ts.map +1 -1
- package/dist/react-core/use-all.js +67 -37
- package/dist/react-core/use-all.js.map +1 -1
- package/dist/react-core/use-all.test.d.ts +2 -0
- package/dist/react-core/use-all.test.d.ts.map +1 -0
- package/dist/react-core/use-all.test.js +130 -0
- package/dist/react-core/use-all.test.js.map +1 -0
- package/dist/react-native/db.test.js +6 -6
- package/dist/react-native/jazz-rn-handoff.test.js +0 -7
- package/dist/react-native/jazz-rn-handoff.test.js.map +1 -1
- package/dist/react-native/jazz-rn-runtime-adapter.d.ts +19 -37
- package/dist/react-native/jazz-rn-runtime-adapter.d.ts.map +1 -1
- package/dist/react-native/jazz-rn-runtime-adapter.js +24 -78
- package/dist/react-native/jazz-rn-runtime-adapter.js.map +1 -1
- package/dist/react-native/jazz-rn-runtime-adapter.test.js +55 -80
- package/dist/react-native/jazz-rn-runtime-adapter.test.js.map +1 -1
- package/dist/runtime/browser-broker-client.d.ts +101 -0
- package/dist/runtime/browser-broker-client.d.ts.map +1 -0
- package/dist/runtime/browser-broker-client.js +598 -0
- package/dist/runtime/browser-broker-client.js.map +1 -0
- package/dist/runtime/browser-broker-client.test.d.ts +2 -0
- package/dist/runtime/browser-broker-client.test.d.ts.map +1 -0
- package/dist/runtime/browser-broker-client.test.js +798 -0
- package/dist/runtime/browser-broker-client.test.js.map +1 -0
- package/dist/runtime/browser-broker-errors.d.ts +10 -0
- package/dist/runtime/browser-broker-errors.d.ts.map +1 -0
- package/dist/runtime/browser-broker-errors.js +22 -0
- package/dist/runtime/browser-broker-errors.js.map +1 -0
- package/dist/runtime/browser-broker-protocol.d.ts +196 -0
- package/dist/runtime/browser-broker-protocol.d.ts.map +1 -0
- package/dist/runtime/browser-broker-protocol.js +159 -0
- package/dist/runtime/browser-broker-protocol.js.map +1 -0
- package/dist/runtime/browser-broker-protocol.test.d.ts +2 -0
- package/dist/runtime/browser-broker-protocol.test.d.ts.map +1 -0
- package/dist/runtime/browser-broker-protocol.test.js +67 -0
- package/dist/runtime/browser-broker-protocol.test.js.map +1 -0
- package/dist/runtime/client-registry.d.ts +20 -0
- package/dist/runtime/client-registry.d.ts.map +1 -0
- package/dist/runtime/client-registry.js +80 -0
- package/dist/runtime/client-registry.js.map +1 -0
- package/dist/runtime/client-registry.test.d.ts +2 -0
- package/dist/runtime/client-registry.test.d.ts.map +1 -0
- package/dist/runtime/client-registry.test.js +59 -0
- package/dist/runtime/client-registry.test.js.map +1 -0
- package/dist/runtime/client-tests/for-request.test.js +12 -17
- package/dist/runtime/client-tests/for-request.test.js.map +1 -1
- package/dist/runtime/client-tests/support.d.ts +8 -2
- package/dist/runtime/client-tests/support.d.ts.map +1 -1
- package/dist/runtime/client-tests/support.js +18 -12
- package/dist/runtime/client-tests/support.js.map +1 -1
- package/dist/runtime/client.d.ts +55 -179
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +75 -548
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/client.mutations.test.js +41 -230
- package/dist/runtime/client.mutations.test.js.map +1 -1
- package/dist/runtime/client.test.js +46 -195
- package/dist/runtime/client.test.js.map +1 -1
- package/dist/runtime/context.d.ts +3 -0
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/db-runtime-module.d.ts +1 -0
- package/dist/runtime/db-runtime-module.d.ts.map +1 -1
- package/dist/runtime/db-runtime-module.js.map +1 -1
- package/dist/runtime/db.d.ts +122 -54
- package/dist/runtime/db.d.ts.map +1 -1
- package/dist/runtime/db.driver-mode.test.js +51 -1
- package/dist/runtime/db.driver-mode.test.js.map +1 -1
- package/dist/runtime/db.js +890 -357
- package/dist/runtime/db.js.map +1 -1
- package/dist/runtime/db.one.test.d.ts +2 -0
- package/dist/runtime/db.one.test.d.ts.map +1 -0
- package/dist/runtime/db.one.test.js +69 -0
- package/dist/runtime/db.one.test.js.map +1 -0
- package/dist/runtime/db.persisted.test.js +17 -17
- package/dist/runtime/db.persisted.test.js.map +1 -1
- package/dist/runtime/db.schema-order.test.js +32 -89
- package/dist/runtime/db.schema-order.test.js.map +1 -1
- package/dist/runtime/db.transaction.test.js +81 -1184
- package/dist/runtime/db.transaction.test.js.map +1 -1
- package/dist/runtime/db.transport.test.js +26 -1
- package/dist/runtime/db.transport.test.js.map +1 -1
- package/dist/runtime/db.worker-bootstrap.test.js +339 -19
- package/dist/runtime/db.worker-bootstrap.test.js.map +1 -1
- package/dist/runtime/index.d.ts +6 -5
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/leader-lock.d.ts +21 -3
- package/dist/runtime/leader-lock.d.ts.map +1 -1
- package/dist/runtime/leader-lock.js +131 -33
- package/dist/runtime/leader-lock.js.map +1 -1
- package/dist/runtime/napi.auth-failure.test.js +1 -1
- package/dist/runtime/napi.auth-failure.test.js.map +1 -1
- package/dist/runtime/napi.for-request.test.js +1 -1
- package/dist/runtime/napi.for-request.test.js.map +1 -1
- package/dist/runtime/napi.integration.test.js +4 -8
- package/dist/runtime/napi.integration.test.js.map +1 -1
- package/dist/runtime/permissions.repro.test.js +1 -1
- package/dist/runtime/permissions.repro.test.js.map +1 -1
- package/dist/runtime/query-adapter-tests/condition-translation.test.js +20 -0
- package/dist/runtime/query-adapter-tests/condition-translation.test.js.map +1 -1
- package/dist/runtime/query-adapter.d.ts.map +1 -1
- package/dist/runtime/query-adapter.js +14 -12
- package/dist/runtime/query-adapter.js.map +1 -1
- package/dist/runtime/query-builder-shape.d.ts +1 -0
- package/dist/runtime/query-builder-shape.d.ts.map +1 -1
- package/dist/runtime/query-builder-shape.js +1 -0
- package/dist/runtime/query-builder-shape.js.map +1 -1
- package/dist/runtime/runtime-config.d.ts +1 -0
- package/dist/runtime/runtime-config.d.ts.map +1 -1
- package/dist/runtime/runtime-config.js +11 -5
- package/dist/runtime/runtime-config.js.map +1 -1
- package/dist/runtime/runtime-config.test.d.ts +2 -0
- package/dist/runtime/runtime-config.test.d.ts.map +1 -0
- package/dist/runtime/runtime-config.test.js +21 -0
- package/dist/runtime/runtime-config.test.js.map +1 -0
- package/dist/runtime/schema-fetch.d.ts +5 -0
- package/dist/runtime/schema-fetch.d.ts.map +1 -1
- package/dist/runtime/schema-fetch.js +33 -2
- package/dist/runtime/schema-fetch.js.map +1 -1
- package/dist/runtime/schema-fetch.test.js +31 -0
- package/dist/runtime/schema-fetch.test.js.map +1 -1
- package/dist/runtime/select-projection.d.ts +0 -1
- package/dist/runtime/select-projection.d.ts.map +1 -1
- package/dist/runtime/select-projection.js +0 -3
- package/dist/runtime/select-projection.js.map +1 -1
- package/dist/runtime/subscription-manager.d.ts +8 -3
- package/dist/runtime/subscription-manager.d.ts.map +1 -1
- package/dist/runtime/subscription-manager.js +1 -1
- package/dist/runtime/subscription-manager.js.map +1 -1
- package/dist/runtime/value-converter.d.ts +6 -17
- package/dist/runtime/value-converter.d.ts.map +1 -1
- package/dist/runtime/value-converter.js +6 -36
- package/dist/runtime/value-converter.js.map +1 -1
- package/dist/runtime/value-converter.test.js +13 -74
- package/dist/runtime/value-converter.test.js.map +1 -1
- package/dist/runtime/wasm-runtime-module.d.ts +1 -1
- package/dist/runtime/wasm-runtime-module.d.ts.map +1 -1
- package/dist/runtime/wasm-runtime-module.js +6 -2
- package/dist/runtime/wasm-runtime-module.js.map +1 -1
- package/dist/runtime/wasm-teardown-trap-suppressor.d.ts +27 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.d.ts.map +1 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.js +73 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.js.map +1 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.test.d.ts +2 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.test.d.ts.map +1 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.test.js +60 -0
- package/dist/runtime/wasm-teardown-trap-suppressor.test.js.map +1 -0
- package/dist/runtime/worker-bridge.d.ts +25 -2
- package/dist/runtime/worker-bridge.d.ts.map +1 -1
- package/dist/runtime/worker-bridge.js +48 -2
- package/dist/runtime/worker-bridge.js.map +1 -1
- package/dist/runtime/worker-bridge.test.d.ts +2 -0
- package/dist/runtime/worker-bridge.test.d.ts.map +1 -0
- package/dist/runtime/worker-bridge.test.js +53 -0
- package/dist/runtime/worker-bridge.test.js.map +1 -0
- package/dist/schema-loader.d.ts.map +1 -1
- package/dist/schema-loader.js +2 -0
- package/dist/schema-loader.js.map +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/shared/index.d.ts +25 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +22 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/index.test.d.ts +2 -0
- package/dist/shared/index.test.d.ts.map +1 -0
- package/dist/shared/index.test.js +79 -0
- package/dist/shared/index.test.js.map +1 -0
- package/dist/solid/create-solid-jazz-client-internal.d.ts +13 -0
- package/dist/solid/create-solid-jazz-client-internal.d.ts.map +1 -0
- package/dist/solid/create-solid-jazz-client-internal.js +47 -0
- package/dist/solid/create-solid-jazz-client-internal.js.map +1 -0
- package/dist/solid/create-solid-jazz-client-internal.ssr.js +64 -0
- package/dist/solid/create-solid-jazz-client-internal.ssr.js.map +1 -0
- package/dist/solid/create-solid-jazz-client-internal.test.d.ts +2 -0
- package/dist/solid/create-solid-jazz-client-internal.test.d.ts.map +1 -0
- package/dist/solid/create-solid-jazz-client.d.ts +34 -0
- package/dist/solid/create-solid-jazz-client.d.ts.map +1 -0
- package/dist/solid/create-solid-jazz-client.integration.test.d.ts +2 -0
- package/dist/solid/create-solid-jazz-client.integration.test.d.ts.map +1 -0
- package/dist/solid/create-solid-jazz-client.js +38 -0
- package/dist/solid/create-solid-jazz-client.js.map +1 -0
- package/dist/solid/create-solid-jazz-client.ssr.js +41 -0
- package/dist/solid/create-solid-jazz-client.ssr.js.map +1 -0
- package/dist/solid/index.d.ts +8 -0
- package/dist/solid/index.d.ts.map +1 -0
- package/dist/solid/index.js +7 -0
- package/dist/solid/index.ssr.js +7 -0
- package/dist/solid/provider.d.ts +27 -0
- package/dist/solid/provider.d.ts.map +1 -0
- package/dist/solid/provider.js +44 -0
- package/dist/solid/provider.js.map +1 -0
- package/dist/solid/provider.ssr.js +44 -0
- package/dist/solid/provider.ssr.js.map +1 -0
- package/dist/solid/solid-jazz-client-store.d.ts +11 -0
- package/dist/solid/solid-jazz-client-store.d.ts.map +1 -0
- package/dist/solid/solid-jazz-client-store.js +35 -0
- package/dist/solid/solid-jazz-client-store.js.map +1 -0
- package/dist/solid/solid-jazz-client-store.ssr.js +37 -0
- package/dist/solid/solid-jazz-client-store.ssr.js.map +1 -0
- package/dist/solid/solid-jazz-client-store.test.d.ts +2 -0
- package/dist/solid/solid-jazz-client-store.test.d.ts.map +1 -0
- package/dist/solid/use-all.d.ts +16 -0
- package/dist/solid/use-all.d.ts.map +1 -0
- package/dist/solid/use-all.js +60 -0
- package/dist/solid/use-all.js.map +1 -0
- package/dist/solid/use-all.ssr.js +68 -0
- package/dist/solid/use-all.ssr.js.map +1 -0
- package/dist/solid/use-all.test.d.ts +2 -0
- package/dist/solid/use-all.test.d.ts.map +1 -0
- package/dist/solid/use-local-first-auth.d.ts +11 -0
- package/dist/solid/use-local-first-auth.d.ts.map +1 -0
- package/dist/solid/use-local-first-auth.js +65 -0
- package/dist/solid/use-local-first-auth.js.map +1 -0
- package/dist/solid/use-local-first-auth.ssr.js +83 -0
- package/dist/solid/use-local-first-auth.ssr.js.map +1 -0
- package/dist/solid/use-local-first-auth.test.d.ts +2 -0
- package/dist/solid/use-local-first-auth.test.d.ts.map +1 -0
- package/dist/subscriptions-orchestrator.d.ts +33 -1
- package/dist/subscriptions-orchestrator.d.ts.map +1 -1
- package/dist/subscriptions-orchestrator.js +97 -7
- package/dist/subscriptions-orchestrator.js.map +1 -1
- package/dist/subscriptions-orchestrator.test.js +96 -0
- package/dist/subscriptions-orchestrator.test.js.map +1 -1
- package/dist/svelte/context.svelte.d.ts +6 -2
- package/dist/svelte/context.svelte.d.ts.map +1 -1
- package/dist/svelte/context.svelte.js +9 -2
- package/dist/svelte/context.svelte.test.js +14 -3
- package/dist/svelte/create-jazz-client.d.ts.map +1 -1
- package/dist/svelte/create-jazz-client.dedup.test.d.ts +2 -0
- package/dist/svelte/create-jazz-client.dedup.test.d.ts.map +1 -0
- package/dist/svelte/create-jazz-client.dedup.test.js +69 -0
- package/dist/svelte/create-jazz-client.js +14 -1
- package/dist/svelte/create-jazz-client.test.js +3 -3
- package/dist/svelte/use-all.svelte.d.ts +1 -2
- package/dist/svelte/use-all.svelte.d.ts.map +1 -1
- package/dist/svelte/use-all.svelte.js +14 -15
- package/dist/svelte/use-all.svelte.test.js +11 -0
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/index.test.js +11 -69
- package/dist/testing/index.test.js.map +1 -1
- package/dist/testing/policy-test-app.d.ts +3 -3
- package/dist/testing/policy-test-app.d.ts.map +1 -1
- package/dist/testing/policy-test-app.js +1 -1
- package/dist/testing/policy-test-app.js.map +1 -1
- package/dist/testing/test-jwt-issuer.d.ts +16 -0
- package/dist/testing/test-jwt-issuer.d.ts.map +1 -0
- package/dist/testing/test-jwt-issuer.js +23 -0
- package/dist/testing/test-jwt-issuer.js.map +1 -0
- package/dist/typed-app.d.ts +24 -32
- package/dist/typed-app.d.ts.map +1 -1
- package/dist/typed-app.js +12 -1
- package/dist/typed-app.js.map +1 -1
- package/dist/vue/create-jazz-client.d.ts.map +1 -1
- package/dist/vue/create-jazz-client.dedup.test.d.ts +2 -0
- package/dist/vue/create-jazz-client.dedup.test.d.ts.map +1 -0
- package/dist/vue/create-jazz-client.dedup.test.js +70 -0
- package/dist/vue/create-jazz-client.dedup.test.js.map +1 -0
- package/dist/vue/create-jazz-client.js +14 -1
- package/dist/vue/create-jazz-client.js.map +1 -1
- package/dist/vue/provider.d.ts +5 -3
- package/dist/vue/provider.d.ts.map +1 -1
- package/dist/vue/provider.js +9 -3
- package/dist/vue/provider.js.map +1 -1
- package/dist/vue/provider.test.d.ts +2 -0
- package/dist/vue/provider.test.d.ts.map +1 -0
- package/dist/vue/provider.test.js +71 -0
- package/dist/vue/provider.test.js.map +1 -0
- package/dist/vue/use-all.d.ts +44 -3
- package/dist/vue/use-all.d.ts.map +1 -1
- package/dist/vue/use-all.js +56 -8
- package/dist/vue/use-all.js.map +1 -1
- package/dist/vue/use-all.test.js +73 -40
- package/dist/vue/use-all.test.js.map +1 -1
- package/dist/web/create-jazz-client.d.ts +20 -0
- package/dist/web/create-jazz-client.d.ts.map +1 -0
- package/dist/web/create-jazz-client.js +61 -0
- package/dist/web/create-jazz-client.js.map +1 -0
- package/dist/web/create-jazz-client.test.d.ts +2 -0
- package/dist/web/create-jazz-client.test.d.ts.map +1 -0
- package/dist/web/create-jazz-client.test.js +159 -0
- package/dist/web/create-jazz-client.test.js.map +1 -0
- package/dist/where-operators.d.ts +12 -0
- package/dist/where-operators.d.ts.map +1 -0
- package/dist/where-operators.js +46 -0
- package/dist/where-operators.js.map +1 -0
- package/dist/worker/broker-worker-bundle.test.d.ts +2 -0
- package/dist/worker/broker-worker-bundle.test.d.ts.map +1 -0
- package/dist/worker/broker-worker-bundle.test.js +40 -0
- package/dist/worker/broker-worker-bundle.test.js.map +1 -0
- package/dist/worker/jazz-broker-worker.d.ts +2 -0
- package/dist/worker/jazz-broker-worker.d.ts.map +1 -0
- package/dist/worker/jazz-broker-worker.js +1090 -0
- package/dist/worker/jazz-worker.js +80 -2
- package/dist/worker/jazz-worker.js.map +1 -1
- package/dist/worker/jazz-worker.ts +104 -2
- package/package.json +27 -8
- package/dist/runtime/client-tests/schema-order.test.d.ts +0 -2
- package/dist/runtime/client-tests/schema-order.test.d.ts.map +0 -1
- package/dist/runtime/client-tests/schema-order.test.js +0 -700
- package/dist/runtime/client-tests/schema-order.test.js.map +0 -1
- package/dist/runtime/storage-reset-coordinator.d.ts +0 -58
- package/dist/runtime/storage-reset-coordinator.d.ts.map +0 -1
- package/dist/runtime/storage-reset-coordinator.js +0 -402
- package/dist/runtime/storage-reset-coordinator.js.map +0 -1
- package/dist/runtime/tab-leader-election.d.ts +0 -97
- package/dist/runtime/tab-leader-election.d.ts.map +0 -1
- package/dist/runtime/tab-leader-election.js +0 -339
- package/dist/runtime/tab-leader-election.js.map +0 -1
- package/dist/runtime/tab-leader-election.test.d.ts +0 -2
- package/dist/runtime/tab-leader-election.test.d.ts.map +0 -1
- package/dist/runtime/tab-leader-election.test.js +0 -278
- package/dist/runtime/tab-leader-election.test.js.map +0 -1
- package/dist/runtime/tab-sync-protocol.d.ts +0 -55
- package/dist/runtime/tab-sync-protocol.d.ts.map +0 -1
- package/dist/runtime/tab-sync-protocol.js +0 -54
- package/dist/runtime/tab-sync-protocol.js.map +0 -1
- package/dist/testing/local-jazz-server.d.ts +0 -2
- package/dist/testing/local-jazz-server.d.ts.map +0 -1
- package/dist/testing/local-jazz-server.js +0 -2
- 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 {
|
|
5
|
-
import { basename,
|
|
6
|
-
import { fileURLToPath
|
|
7
|
-
import {
|
|
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
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
66
|
-
console.warn(`\x1b[33m${
|
|
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
|
-
|
|
72
|
-
|
|
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
|
|
82
|
-
console.log(`Loaded structural schema from ${
|
|
83
|
-
|
|
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
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
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
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
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
|
|
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
|
-
|
|
1132
|
-
|
|
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
|
-
|
|
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
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
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
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
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
|
}
|