everything-dev 1.53.2 → 2.0.0-rc.1
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/README.md +2 -11
- package/dist/_virtual/_rolldown/runtime.cjs +17 -2
- package/dist/_virtual/_rolldown/runtime.mjs +36 -0
- package/dist/api/auth-middleware.cjs +161 -0
- package/dist/api/auth-middleware.cjs.map +1 -0
- package/dist/api/auth-middleware.d.cts +69 -0
- package/dist/api/auth-middleware.d.mts +69 -0
- package/dist/api/auth-middleware.mjs +160 -0
- package/dist/api/auth-middleware.mjs.map +1 -0
- package/dist/api-contract.cjs +250 -62
- package/dist/api-contract.cjs.map +1 -1
- package/dist/api-contract.mjs +246 -65
- package/dist/api-contract.mjs.map +1 -1
- package/dist/app.cjs +99 -26
- package/dist/app.cjs.map +1 -1
- package/dist/app.d.cts +3 -0
- package/dist/app.d.mts +3 -0
- package/dist/app.mjs +100 -27
- package/dist/app.mjs.map +1 -1
- package/dist/auth-login.cjs +163 -0
- package/dist/auth-login.cjs.map +1 -0
- package/dist/auth-login.mjs +162 -0
- package/dist/auth-login.mjs.map +1 -0
- package/dist/auth-session.cjs +64 -0
- package/dist/auth-session.cjs.map +1 -0
- package/dist/auth-session.mjs +58 -0
- package/dist/auth-session.mjs.map +1 -0
- package/dist/auth-types-gen.cjs +0 -1
- package/dist/auth-types-gen.cjs.map +1 -1
- package/dist/build.cjs +37 -173
- package/dist/build.cjs.map +1 -1
- package/dist/build.mjs +37 -171
- package/dist/build.mjs.map +1 -1
- package/dist/bundle-cache.cjs +74 -0
- package/dist/bundle-cache.cjs.map +1 -0
- package/dist/bundle-cache.d.cts +27 -0
- package/dist/bundle-cache.d.mts +27 -0
- package/dist/bundle-cache.mjs +68 -0
- package/dist/bundle-cache.mjs.map +1 -0
- package/dist/bundle-fs-resolve.cjs +209 -0
- package/dist/bundle-fs-resolve.cjs.map +1 -0
- package/dist/bundle-fs-resolve.d.cts +76 -0
- package/dist/bundle-fs-resolve.d.mts +76 -0
- package/dist/bundle-fs-resolve.mjs +202 -0
- package/dist/bundle-fs-resolve.mjs.map +1 -0
- package/dist/cdn-deploy.cjs +126 -0
- package/dist/cdn-deploy.cjs.map +1 -0
- package/dist/cdn-deploy.mjs +124 -0
- package/dist/cdn-deploy.mjs.map +1 -0
- package/dist/cli/db-doctor.cjs +19 -19
- package/dist/cli/db-doctor.cjs.map +1 -1
- package/dist/cli/db-doctor.mjs +18 -18
- package/dist/cli/db-doctor.mjs.map +1 -1
- package/dist/cli/db-repair.cjs +9 -32
- package/dist/cli/db-repair.cjs.map +1 -1
- package/dist/cli/db-repair.mjs +9 -32
- package/dist/cli/db-repair.mjs.map +1 -1
- package/dist/cli/framework-version.cjs +7 -3
- package/dist/cli/framework-version.cjs.map +1 -1
- package/dist/cli/framework-version.mjs +7 -3
- package/dist/cli/framework-version.mjs.map +1 -1
- package/dist/cli/infra.cjs +159 -251
- package/dist/cli/infra.cjs.map +1 -1
- package/dist/cli/infra.mjs +154 -242
- package/dist/cli/infra.mjs.map +1 -1
- package/dist/cli/init.cjs +627 -199
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +61 -8
- package/dist/cli/init.d.mts +61 -8
- package/dist/cli/init.mjs +616 -197
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/parse.cjs +8 -7
- package/dist/cli/parse.cjs.map +1 -1
- package/dist/cli/parse.mjs +9 -7
- package/dist/cli/parse.mjs.map +1 -1
- package/dist/cli/prompts.cjs +14 -1
- package/dist/cli/prompts.cjs.map +1 -1
- package/dist/cli/prompts.mjs +14 -1
- package/dist/cli/prompts.mjs.map +1 -1
- package/dist/cli/prune.cjs +220 -0
- package/dist/cli/prune.cjs.map +1 -0
- package/dist/cli/prune.mjs +220 -0
- package/dist/cli/prune.mjs.map +1 -0
- package/dist/cli/snapshot.cjs +2 -1
- package/dist/cli/snapshot.cjs.map +1 -1
- package/dist/cli/snapshot.mjs +2 -1
- package/dist/cli/snapshot.mjs.map +1 -1
- package/dist/cli/status.cjs +5 -4
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.mjs +6 -5
- package/dist/cli/status.mjs.map +1 -1
- package/dist/cli/sync.cjs +156 -58
- package/dist/cli/sync.cjs.map +1 -1
- package/dist/cli/sync.mjs +158 -63
- package/dist/cli/sync.mjs.map +1 -1
- package/dist/cli/timing.cjs +0 -1
- package/dist/cli/timing.cjs.map +1 -1
- package/dist/cli/upgrade.cjs +95 -69
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +97 -72
- package/dist/cli/upgrade.mjs.map +1 -1
- package/dist/cli/utils/helpers.cjs.map +1 -1
- package/dist/cli.cjs +320 -72
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +316 -68
- package/dist/cli.mjs.map +1 -1
- package/dist/code-artifacts.cjs +76 -8
- package/dist/code-artifacts.cjs.map +1 -1
- package/dist/code-artifacts.mjs +76 -10
- package/dist/code-artifacts.mjs.map +1 -1
- package/dist/commands/build.cjs +65 -0
- package/dist/commands/build.cjs.map +1 -0
- package/dist/commands/build.mjs +65 -0
- package/dist/commands/build.mjs.map +1 -0
- package/dist/commands/config.cjs +77 -0
- package/dist/commands/config.cjs.map +1 -0
- package/dist/commands/config.d.cts +8 -0
- package/dist/commands/config.d.mts +8 -0
- package/dist/commands/config.mjs +74 -0
- package/dist/commands/config.mjs.map +1 -0
- package/dist/commands/db.cjs +107 -0
- package/dist/commands/db.cjs.map +1 -0
- package/dist/commands/db.mjs +107 -0
- package/dist/commands/db.mjs.map +1 -0
- package/dist/commands/deploy.cjs +336 -0
- package/dist/commands/deploy.cjs.map +1 -0
- package/dist/commands/deploy.mjs +334 -0
- package/dist/commands/deploy.mjs.map +1 -0
- package/dist/commands/dev.cjs +75 -0
- package/dist/commands/dev.cjs.map +1 -0
- package/dist/commands/dev.mjs +73 -0
- package/dist/commands/dev.mjs.map +1 -0
- package/dist/commands/init.cjs +234 -0
- package/dist/commands/init.cjs.map +1 -0
- package/dist/commands/init.mjs +231 -0
- package/dist/commands/init.mjs.map +1 -0
- package/dist/commands/keys.cjs +255 -0
- package/dist/commands/keys.cjs.map +1 -0
- package/dist/commands/keys.mjs +253 -0
- package/dist/commands/keys.mjs.map +1 -0
- package/dist/commands/ops.cjs +199 -0
- package/dist/commands/ops.cjs.map +1 -0
- package/dist/commands/ops.mjs +197 -0
- package/dist/commands/ops.mjs.map +1 -0
- package/dist/commands/plugins.cjs +211 -0
- package/dist/commands/plugins.cjs.map +1 -0
- package/dist/commands/plugins.mjs +211 -0
- package/dist/commands/plugins.mjs.map +1 -0
- package/dist/commands/shared.cjs +8 -0
- package/dist/commands/shared.cjs.map +1 -0
- package/dist/commands/shared.d.cts +6 -0
- package/dist/commands/shared.d.mts +6 -0
- package/dist/commands/shared.mjs +8 -0
- package/dist/commands/shared.mjs.map +1 -0
- package/dist/commands/upgrade.cjs +325 -0
- package/dist/commands/upgrade.cjs.map +1 -0
- package/dist/commands/upgrade.mjs +323 -0
- package/dist/commands/upgrade.mjs.map +1 -0
- package/dist/components/dev-render.cjs +340 -0
- package/dist/components/dev-render.cjs.map +1 -0
- package/dist/components/dev-render.mjs +332 -0
- package/dist/components/dev-render.mjs.map +1 -0
- package/dist/config.cjs +460 -221
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +491 -48
- package/dist/config.d.mts +491 -48
- package/dist/config.mjs +439 -212
- package/dist/config.mjs.map +1 -1
- package/dist/contract.cjs +327 -50
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +1951 -1062
- package/dist/contract.d.mts +1951 -1062
- package/dist/contract.meta.cjs +107 -12
- package/dist/contract.meta.cjs.map +1 -1
- package/dist/contract.meta.d.cts +166 -8
- package/dist/contract.meta.d.mts +166 -8
- package/dist/contract.meta.mjs +107 -11
- package/dist/contract.meta.mjs.map +1 -1
- package/dist/contract.mjs +580 -327
- package/dist/contract.mjs.map +1 -1
- package/dist/dag.cjs +5 -3
- package/dist/dag.cjs.map +1 -1
- package/dist/dag.mjs +6 -3
- package/dist/dag.mjs.map +1 -1
- package/dist/db/binding.cjs +80 -0
- package/dist/db/binding.cjs.map +1 -0
- package/dist/db/binding.d.cts +39 -0
- package/dist/db/binding.d.mts +39 -0
- package/dist/db/binding.mjs +78 -0
- package/dist/db/binding.mjs.map +1 -0
- package/dist/db/bindings.cjs +78 -0
- package/dist/db/bindings.cjs.map +1 -0
- package/dist/db/bindings.d.cts +34 -0
- package/dist/db/bindings.d.mts +34 -0
- package/dist/db/bindings.mjs +76 -0
- package/dist/db/bindings.mjs.map +1 -0
- package/dist/db/core.cjs +204 -0
- package/dist/db/core.cjs.map +1 -0
- package/dist/db/core.d.cts +69 -0
- package/dist/db/core.d.mts +69 -0
- package/dist/db/core.mjs +192 -0
- package/dist/db/core.mjs.map +1 -0
- package/dist/db/driver.cjs +167 -0
- package/dist/db/driver.cjs.map +1 -0
- package/dist/db/driver.d.cts +50 -0
- package/dist/db/driver.d.mts +50 -0
- package/dist/db/driver.mjs +165 -0
- package/dist/db/driver.mjs.map +1 -0
- package/dist/db/drizzle-kit.cjs +177 -0
- package/dist/db/drizzle-kit.cjs.map +1 -0
- package/dist/db/drizzle-kit.d.cts +25 -0
- package/dist/db/drizzle-kit.d.mts +25 -0
- package/dist/db/drizzle-kit.mjs +175 -0
- package/dist/db/drizzle-kit.mjs.map +1 -0
- package/dist/db/errors.cjs +27 -0
- package/dist/db/errors.cjs.map +1 -0
- package/dist/db/errors.d.cts +16 -0
- package/dist/db/errors.d.mts +16 -0
- package/dist/db/errors.mjs +26 -0
- package/dist/db/errors.mjs.map +1 -0
- package/dist/db/identity.cjs +55 -0
- package/dist/db/identity.cjs.map +1 -0
- package/dist/db/identity.d.cts +40 -0
- package/dist/db/identity.d.mts +40 -0
- package/dist/db/identity.mjs +53 -0
- package/dist/db/identity.mjs.map +1 -0
- package/dist/db/index.cjs +43 -0
- package/dist/db/index.d.cts +9 -0
- package/dist/db/index.d.mts +9 -0
- package/dist/db/index.mjs +10 -0
- package/dist/db/run-migrations.cjs +343 -0
- package/dist/db/run-migrations.cjs.map +1 -0
- package/dist/db/run-migrations.d.cts +87 -0
- package/dist/db/run-migrations.d.mts +87 -0
- package/dist/db/run-migrations.mjs +341 -0
- package/dist/db/run-migrations.mjs.map +1 -0
- package/dist/delegate-signer.cjs +85 -0
- package/dist/delegate-signer.cjs.map +1 -0
- package/dist/delegate-signer.mjs +84 -0
- package/dist/delegate-signer.mjs.map +1 -0
- package/dist/deploy-diff.cjs +119 -0
- package/dist/deploy-diff.cjs.map +1 -0
- package/dist/deploy-diff.mjs +109 -0
- package/dist/deploy-diff.mjs.map +1 -0
- package/dist/descriptor/constructors.cjs +49 -0
- package/dist/descriptor/constructors.cjs.map +1 -0
- package/dist/descriptor/constructors.d.cts +27 -0
- package/dist/descriptor/constructors.d.mts +27 -0
- package/dist/descriptor/constructors.mjs +45 -0
- package/dist/descriptor/constructors.mjs.map +1 -0
- package/dist/descriptor/index.cjs +24 -0
- package/dist/descriptor/index.d.cts +5 -0
- package/dist/descriptor/index.d.mts +5 -0
- package/dist/descriptor/index.mjs +6 -0
- package/dist/descriptor/resolve.cjs +258 -0
- package/dist/descriptor/resolve.cjs.map +1 -0
- package/dist/descriptor/resolve.d.cts +50 -0
- package/dist/descriptor/resolve.d.mts +50 -0
- package/dist/descriptor/resolve.mjs +252 -0
- package/dist/descriptor/resolve.mjs.map +1 -0
- package/dist/descriptor/schema.cjs +109 -0
- package/dist/descriptor/schema.cjs.map +1 -0
- package/dist/descriptor/schema.d.cts +217 -0
- package/dist/descriptor/schema.d.mts +217 -0
- package/dist/descriptor/schema.mjs +102 -0
- package/dist/descriptor/schema.mjs.map +1 -0
- package/dist/descriptor/serialize.cjs +45 -0
- package/dist/descriptor/serialize.cjs.map +1 -0
- package/dist/descriptor/serialize.d.cts +7 -0
- package/dist/descriptor/serialize.d.mts +7 -0
- package/dist/descriptor/serialize.mjs +45 -0
- package/dist/descriptor/serialize.mjs.map +1 -0
- package/dist/dev-log-pipeline.cjs +273 -0
- package/dist/dev-log-pipeline.cjs.map +1 -0
- package/dist/dev-log-pipeline.mjs +267 -0
- package/dist/dev-log-pipeline.mjs.map +1 -0
- package/dist/dev-logs.cjs +39 -8
- package/dist/dev-logs.cjs.map +1 -1
- package/dist/dev-logs.mjs +37 -9
- package/dist/dev-logs.mjs.map +1 -1
- package/dist/dev-program.cjs +405 -0
- package/dist/dev-program.cjs.map +1 -0
- package/dist/dev-program.d.cts +10 -0
- package/dist/dev-program.d.mts +10 -0
- package/dist/dev-program.mjs +395 -0
- package/dist/dev-program.mjs.map +1 -0
- package/dist/dev-session-data.d.cts +27 -0
- package/dist/dev-session-data.d.mts +27 -0
- package/dist/dev-session.cjs +178 -105
- package/dist/dev-session.cjs.map +1 -1
- package/dist/dev-session.mjs +180 -105
- package/dist/dev-session.mjs.map +1 -1
- package/dist/env/process-env.cjs +16 -0
- package/dist/env/process-env.cjs.map +1 -0
- package/dist/env/process-env.mjs +13 -0
- package/dist/env/process-env.mjs.map +1 -0
- package/dist/env/project-env.cjs +144 -0
- package/dist/env/project-env.cjs.map +1 -0
- package/dist/env/project-env.d.cts +1 -0
- package/dist/env/project-env.d.mts +1 -0
- package/dist/env/project-env.mjs +132 -0
- package/dist/env/project-env.mjs.map +1 -0
- package/dist/fastkv.cjs +59 -12
- package/dist/fastkv.cjs.map +1 -1
- package/dist/fastkv.d.cts +42 -6
- package/dist/fastkv.d.mts +42 -6
- package/dist/fastkv.mjs +58 -13
- package/dist/fastkv.mjs.map +1 -1
- package/dist/fingerprint.cjs +57 -0
- package/dist/fingerprint.cjs.map +1 -0
- package/dist/fingerprint.d.cts +14 -0
- package/dist/fingerprint.d.mts +14 -0
- package/dist/fingerprint.mjs +55 -0
- package/dist/fingerprint.mjs.map +1 -0
- package/dist/http-client.cjs +17 -17
- package/dist/http-client.cjs.map +1 -1
- package/dist/http-client.mjs +17 -17
- package/dist/http-client.mjs.map +1 -1
- package/dist/image-deploy.cjs +186 -0
- package/dist/image-deploy.cjs.map +1 -0
- package/dist/image-deploy.mjs +182 -0
- package/dist/image-deploy.mjs.map +1 -0
- package/dist/index.cjs +66 -18
- package/dist/index.d.cts +8 -7
- package/dist/index.d.mts +8 -7
- package/dist/index.mjs +6 -5
- package/dist/infra/docker.cjs +77 -0
- package/dist/infra/docker.cjs.map +1 -0
- package/dist/infra/docker.d.cts +10 -0
- package/dist/infra/docker.d.mts +10 -0
- package/dist/infra/docker.mjs +69 -0
- package/dist/infra/docker.mjs.map +1 -0
- package/dist/infra/materializer.cjs +74 -0
- package/dist/infra/materializer.cjs.map +1 -0
- package/dist/infra/materializer.mjs +70 -0
- package/dist/infra/materializer.mjs.map +1 -0
- package/dist/infra/planner.cjs +135 -103
- package/dist/infra/planner.cjs.map +1 -1
- package/dist/infra/planner.mjs +137 -104
- package/dist/infra/planner.mjs.map +1 -1
- package/dist/infra/port-ownership.cjs +57 -0
- package/dist/infra/port-ownership.cjs.map +1 -0
- package/dist/infra/port-ownership.mjs +57 -0
- package/dist/infra/port-ownership.mjs.map +1 -0
- package/dist/infra/preflight.cjs +45 -33
- package/dist/infra/preflight.cjs.map +1 -1
- package/dist/infra/preflight.d.cts +1 -0
- package/dist/infra/preflight.d.mts +1 -0
- package/dist/infra/preflight.mjs +46 -34
- package/dist/infra/preflight.mjs.map +1 -1
- package/dist/infra/types.cjs.map +1 -1
- package/dist/infra/types.d.cts +2 -0
- package/dist/infra/types.d.mts +2 -0
- package/dist/infra/types.mjs.map +1 -1
- package/dist/integrity.cjs +50 -61
- package/dist/integrity.cjs.map +1 -1
- package/dist/integrity.d.cts +16 -10
- package/dist/integrity.d.mts +16 -10
- package/dist/integrity.mjs +50 -59
- package/dist/integrity.mjs.map +1 -1
- package/dist/internal/manifest-normalizer.cjs +8 -2
- package/dist/internal/manifest-normalizer.cjs.map +1 -1
- package/dist/internal/manifest-normalizer.mjs +9 -3
- package/dist/internal/manifest-normalizer.mjs.map +1 -1
- package/dist/merge.cjs +19 -1
- package/dist/merge.cjs.map +1 -1
- package/dist/merge.d.cts +1 -1
- package/dist/merge.d.mts +1 -1
- package/dist/merge.mjs +19 -2
- package/dist/merge.mjs.map +1 -1
- package/dist/mf.cjs +190 -3
- package/dist/mf.cjs.map +1 -1
- package/dist/mf.d.cts +24 -2
- package/dist/mf.d.mts +24 -2
- package/dist/mf.mjs +189 -4
- package/dist/mf.mjs.map +1 -1
- package/dist/near-cli.cjs +59 -91
- package/dist/near-cli.cjs.map +1 -1
- package/dist/near-cli.mjs +58 -90
- package/dist/near-cli.mjs.map +1 -1
- package/dist/near-signer.cjs +73 -0
- package/dist/near-signer.cjs.map +1 -0
- package/dist/near-signer.mjs +70 -0
- package/dist/near-signer.mjs.map +1 -0
- package/dist/network.cjs +0 -1
- package/dist/network.cjs.map +1 -1
- package/dist/orchestrator.cjs +256 -87
- package/dist/orchestrator.cjs.map +1 -1
- package/dist/orchestrator.mjs +248 -87
- package/dist/orchestrator.mjs.map +1 -1
- package/dist/platform-deploy.cjs +81 -0
- package/dist/platform-deploy.cjs.map +1 -0
- package/dist/platform-deploy.mjs +80 -0
- package/dist/platform-deploy.mjs.map +1 -0
- package/dist/plugin.cjs +54 -1389
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +6 -896
- package/dist/plugin.d.mts +6 -896
- package/dist/plugin.mjs +53 -1387
- package/dist/plugin.mjs.map +1 -1
- package/dist/process-kill.cjs +44 -0
- package/dist/process-kill.cjs.map +1 -0
- package/dist/process-kill.mjs +43 -0
- package/dist/process-kill.mjs.map +1 -0
- package/dist/process-registry.cjs +64 -9
- package/dist/process-registry.cjs.map +1 -1
- package/dist/process-registry.mjs +61 -10
- package/dist/process-registry.mjs.map +1 -1
- package/dist/progress.cjs +45 -0
- package/dist/progress.cjs.map +1 -0
- package/dist/progress.d.cts +13 -0
- package/dist/progress.d.mts +13 -0
- package/dist/progress.mjs +42 -0
- package/dist/progress.mjs.map +1 -0
- package/dist/publish.cjs +513 -79
- package/dist/publish.cjs.map +1 -1
- package/dist/publish.mjs +515 -82
- package/dist/publish.mjs.map +1 -1
- package/dist/registry-use.cjs +41 -0
- package/dist/registry-use.cjs.map +1 -0
- package/dist/registry-use.mjs +40 -0
- package/dist/registry-use.mjs.map +1 -0
- package/dist/resolution/session.cjs +335 -0
- package/dist/resolution/session.cjs.map +1 -0
- package/dist/resolution/session.d.cts +105 -0
- package/dist/resolution/session.d.mts +105 -0
- package/dist/resolution/session.mjs +331 -0
- package/dist/resolution/session.mjs.map +1 -0
- package/dist/rollback.cjs +131 -0
- package/dist/rollback.cjs.map +1 -0
- package/dist/rollback.mjs +128 -0
- package/dist/rollback.mjs.map +1 -0
- package/dist/sdk.cjs +7 -7
- package/dist/sdk.d.cts +3 -3
- package/dist/sdk.d.mts +3 -3
- package/dist/sdk.mjs +2 -2
- package/dist/service-descriptor.cjs +67 -34
- package/dist/service-descriptor.cjs.map +1 -1
- package/dist/service-descriptor.d.cts +4 -1
- package/dist/service-descriptor.d.mts +3 -0
- package/dist/service-descriptor.mjs +63 -35
- package/dist/service-descriptor.mjs.map +1 -1
- package/dist/shared-deps.cjs +17 -16
- package/dist/shared-deps.cjs.map +1 -1
- package/dist/shared-deps.mjs +17 -16
- package/dist/shared-deps.mjs.map +1 -1
- package/dist/start-config-source.cjs +24 -0
- package/dist/start-config-source.cjs.map +1 -0
- package/dist/start-config-source.d.cts +29 -0
- package/dist/start-config-source.d.mts +29 -0
- package/dist/start-config-source.mjs +22 -0
- package/dist/start-config-source.mjs.map +1 -0
- package/dist/storage-upload.cjs +145 -0
- package/dist/storage-upload.cjs.map +1 -0
- package/dist/storage-upload.mjs +143 -0
- package/dist/storage-upload.mjs.map +1 -0
- package/dist/types.cjs +126 -20
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +867 -585
- package/dist/types.d.mts +867 -585
- package/dist/types.mjs +307 -208
- package/dist/types.mjs.map +1 -1
- package/dist/ui/api.cjs +105 -0
- package/dist/ui/api.cjs.map +1 -0
- package/dist/ui/api.d.cts +31 -0
- package/dist/ui/api.d.mts +31 -0
- package/dist/ui/api.mjs +99 -0
- package/dist/ui/api.mjs.map +1 -0
- package/dist/ui/auth-guards.cjs +50 -0
- package/dist/ui/auth-guards.cjs.map +1 -0
- package/dist/ui/auth-guards.d.cts +39 -0
- package/dist/ui/auth-guards.d.mts +39 -0
- package/dist/ui/auth-guards.mjs +48 -0
- package/dist/ui/auth-guards.mjs.map +1 -0
- package/dist/ui/auth.cjs +197 -0
- package/dist/ui/auth.cjs.map +1 -0
- package/dist/ui/auth.d.cts +56 -0
- package/dist/ui/auth.d.mts +56 -0
- package/dist/ui/auth.mjs +179 -0
- package/dist/ui/auth.mjs.map +1 -0
- package/dist/ui/entry.cjs +16 -0
- package/dist/ui/entry.cjs.map +1 -0
- package/dist/ui/entry.d.cts +12 -0
- package/dist/ui/entry.d.mts +12 -0
- package/dist/ui/entry.mjs +15 -0
- package/dist/ui/entry.mjs.map +1 -0
- package/dist/ui/head.cjs +14 -7
- package/dist/ui/head.cjs.map +1 -1
- package/dist/ui/head.mjs +15 -7
- package/dist/ui/head.mjs.map +1 -1
- package/dist/ui/hydrate.cjs +265 -0
- package/dist/ui/hydrate.cjs.map +1 -0
- package/dist/ui/hydrate.d.cts +48 -0
- package/dist/ui/hydrate.d.mts +48 -0
- package/dist/ui/hydrate.mjs +263 -0
- package/dist/ui/hydrate.mjs.map +1 -0
- package/dist/ui/i18n.cjs +153 -0
- package/dist/ui/i18n.cjs.map +1 -0
- package/dist/ui/i18n.d.cts +29 -0
- package/dist/ui/i18n.d.mts +29 -0
- package/dist/ui/i18n.mjs +140 -0
- package/dist/ui/i18n.mjs.map +1 -0
- package/dist/ui/index.cjs +19 -1
- package/dist/ui/index.d.cts +6 -3
- package/dist/ui/index.d.mts +6 -3
- package/dist/ui/index.mjs +5 -2
- package/dist/ui/locale.cjs +53 -0
- package/dist/ui/locale.cjs.map +1 -0
- package/dist/ui/locale.d.cts +18 -0
- package/dist/ui/locale.d.mts +18 -0
- package/dist/ui/locale.mjs +49 -0
- package/dist/ui/locale.mjs.map +1 -0
- package/dist/ui/manifest/index.cjs +25 -0
- package/dist/ui/manifest/index.cjs.map +1 -0
- package/dist/ui/manifest/index.d.cts +9 -0
- package/dist/ui/manifest/index.d.mts +9 -0
- package/dist/ui/manifest/index.mjs +13 -0
- package/dist/ui/manifest/index.mjs.map +1 -0
- package/dist/ui/manifest-generator.cjs +8 -0
- package/dist/ui/manifest-generator.d.cts +1 -0
- package/dist/ui/manifest-generator.d.mts +1 -0
- package/dist/ui/manifest-generator.mjs +3 -0
- package/dist/ui/message-catalogs.cjs +8 -0
- package/dist/ui/message-catalogs.cjs.map +1 -0
- package/dist/ui/message-catalogs.d.cts +5 -0
- package/dist/ui/message-catalogs.d.mts +5 -0
- package/dist/ui/message-catalogs.mjs +8 -0
- package/dist/ui/message-catalogs.mjs.map +1 -0
- package/dist/ui/metadata.cjs +0 -1
- package/dist/ui/metadata.cjs.map +1 -1
- package/dist/ui/metadata.d.cts +1 -1
- package/dist/ui/metadata.d.mts +1 -1
- package/dist/ui/plugin-path.cjs +37 -0
- package/dist/ui/plugin-path.cjs.map +1 -0
- package/dist/ui/plugin-path.d.cts +25 -0
- package/dist/ui/plugin-path.d.mts +25 -0
- package/dist/ui/plugin-path.mjs +35 -0
- package/dist/ui/plugin-path.mjs.map +1 -0
- package/dist/ui/router-client.cjs +61 -0
- package/dist/ui/router-client.cjs.map +1 -0
- package/dist/ui/router-client.d.cts +20 -0
- package/dist/ui/router-client.d.mts +20 -0
- package/dist/ui/router-client.mjs +60 -0
- package/dist/ui/router-client.mjs.map +1 -0
- package/dist/ui/router-defaults.cjs +48 -0
- package/dist/ui/router-defaults.cjs.map +1 -0
- package/dist/ui/router-defaults.d.cts +8 -0
- package/dist/ui/router-defaults.d.mts +8 -0
- package/dist/ui/router-defaults.mjs +45 -0
- package/dist/ui/router-defaults.mjs.map +1 -0
- package/dist/ui/router-error.cjs +70 -0
- package/dist/ui/router-error.cjs.map +1 -0
- package/dist/ui/router-error.d.cts +19 -0
- package/dist/ui/router-error.d.mts +19 -0
- package/dist/ui/router-error.mjs +69 -0
- package/dist/ui/router-error.mjs.map +1 -0
- package/dist/ui/router-server.cjs +153 -0
- package/dist/ui/router-server.cjs.map +1 -0
- package/dist/ui/router-server.d.cts +38 -0
- package/dist/ui/router-server.d.mts +38 -0
- package/dist/ui/router-server.mjs +152 -0
- package/dist/ui/router-server.mjs.map +1 -0
- package/dist/ui/router.cjs +4 -16
- package/dist/ui/router.cjs.map +1 -1
- package/dist/ui/router.mjs +4 -15
- package/dist/ui/router.mjs.map +1 -1
- package/dist/ui/runtime.cjs +5 -1
- package/dist/ui/runtime.cjs.map +1 -1
- package/dist/ui/runtime.d.cts +2 -1
- package/dist/ui/runtime.d.mts +2 -1
- package/dist/ui/runtime.mjs +5 -1
- package/dist/ui/runtime.mjs.map +1 -1
- package/dist/ui/slot.cjs +34 -0
- package/dist/ui/slot.cjs.map +1 -0
- package/dist/ui/slot.d.cts +43 -0
- package/dist/ui/slot.d.mts +43 -0
- package/dist/ui/slot.mjs +34 -0
- package/dist/ui/slot.mjs.map +1 -0
- package/dist/ui/tenant.cjs +300 -0
- package/dist/ui/tenant.cjs.map +1 -0
- package/dist/ui/tenant.d.cts +122 -0
- package/dist/ui/tenant.d.mts +122 -0
- package/dist/ui/tenant.mjs +279 -0
- package/dist/ui/tenant.mjs.map +1 -0
- package/dist/ui/types.d.cts +32 -2
- package/dist/ui/types.d.mts +32 -2
- package/dist/ui/version-check.cjs +47 -0
- package/dist/ui/version-check.cjs.map +1 -0
- package/dist/ui/version-check.d.cts +23 -0
- package/dist/ui/version-check.d.mts +23 -0
- package/dist/ui/version-check.mjs +46 -0
- package/dist/ui/version-check.mjs.map +1 -0
- package/dist/utils/banner.cjs +2 -2
- package/dist/utils/banner.cjs.map +1 -1
- package/dist/utils/banner.mjs +2 -2
- package/dist/utils/banner.mjs.map +1 -1
- package/dist/utils/linkify.cjs +1 -1
- package/dist/utils/linkify.cjs.map +1 -1
- package/dist/utils/linkify.mjs +1 -0
- package/dist/utils/linkify.mjs.map +1 -1
- package/dist/utils/run.cjs +6 -6
- package/dist/utils/run.cjs.map +1 -1
- package/dist/utils/run.mjs +6 -6
- package/dist/utils/run.mjs.map +1 -1
- package/dist/utils/save-config.cjs +12 -0
- package/dist/utils/save-config.cjs.map +1 -1
- package/dist/utils/save-config.mjs +12 -0
- package/dist/utils/save-config.mjs.map +1 -1
- package/dist/utils/snapshot-hash.cjs +10 -0
- package/dist/utils/snapshot-hash.cjs.map +1 -0
- package/dist/utils/snapshot-hash.mjs +10 -0
- package/dist/utils/snapshot-hash.mjs.map +1 -0
- package/dist/utils/string.cjs +0 -1
- package/dist/utils/string.cjs.map +1 -1
- package/dist/utils/theme.cjs +30 -12
- package/dist/utils/theme.cjs.map +1 -1
- package/dist/utils/theme.mjs +30 -11
- package/dist/utils/theme.mjs.map +1 -1
- package/dist/version-manifest-deploy.cjs +50 -0
- package/dist/version-manifest-deploy.cjs.map +1 -0
- package/dist/version-manifest-deploy.mjs +49 -0
- package/dist/version-manifest-deploy.mjs.map +1 -0
- package/dist/version-manifest-resolve.cjs +42 -0
- package/dist/version-manifest-resolve.cjs.map +1 -0
- package/dist/version-manifest-resolve.d.cts +38 -0
- package/dist/version-manifest-resolve.d.mts +38 -0
- package/dist/version-manifest-resolve.mjs +40 -0
- package/dist/version-manifest-resolve.mjs.map +1 -0
- package/dist/version-status.cjs +18 -0
- package/dist/version-status.cjs.map +1 -0
- package/dist/version-status.d.cts +22 -0
- package/dist/version-status.d.mts +22 -0
- package/dist/version-status.mjs +17 -0
- package/dist/version-status.mjs.map +1 -0
- package/dist/workspace-catalog.cjs +53 -0
- package/dist/workspace-catalog.cjs.map +1 -0
- package/dist/workspace-catalog.mjs +51 -0
- package/dist/workspace-catalog.mjs.map +1 -0
- package/dist/workspace.cjs +237 -0
- package/dist/workspace.cjs.map +1 -0
- package/dist/workspace.mjs +233 -0
- package/dist/workspace.mjs.map +1 -0
- package/package.json +179 -27
- package/skills/add-a-route/SKILL.md +132 -0
- package/skills/api-and-auth/SKILL.md +87 -21
- package/skills/api-and-auth/references/middleware.md +1 -1
- package/skills/cli-reference/SKILL.md +48 -21
- package/skills/code-style/SKILL.md +8 -0
- package/skills/dev-workflow/SKILL.md +50 -26
- package/skills/extends-config/SKILL.md +31 -19
- package/skills/init-upgrade/SKILL.md +29 -16
- package/skills/plugin-development/SKILL.md +46 -112
- package/skills/plugin-development/references/database.md +82 -0
- package/skills/plugin-development/references/request-context.md +67 -0
- package/skills/publish-sync/SKILL.md +99 -22
- package/skills/registry/SKILL.md +82 -0
- package/skills/super-app/SKILL.md +25 -15
- package/skills/talk-to-the-app/SKILL.md +138 -0
- package/skills/ui-integration/SKILL.md +93 -11
- package/dist/cli/db-studio.cjs +0 -131
- package/dist/cli/db-studio.cjs.map +0 -1
- package/dist/cli/db-studio.mjs +0 -127
- package/dist/cli/db-studio.mjs.map +0 -1
- package/dist/cli/init.d.cts.map +0 -1
- package/dist/cli/init.d.mts.map +0 -1
- package/dist/components/dev-view.cjs +0 -309
- package/dist/components/dev-view.cjs.map +0 -1
- package/dist/components/dev-view.mjs +0 -309
- package/dist/components/dev-view.mjs.map +0 -1
- package/dist/components/streaming-view.cjs +0 -134
- package/dist/components/streaming-view.cjs.map +0 -1
- package/dist/components/streaming-view.mjs +0 -132
- package/dist/components/streaming-view.mjs.map +0 -1
- package/dist/config.d.cts.map +0 -1
- package/dist/config.d.mts.map +0 -1
- package/dist/contract.d.cts.map +0 -1
- package/dist/contract.d.mts.map +0 -1
- package/dist/contract.meta.d.cts.map +0 -1
- package/dist/contract.meta.d.mts.map +0 -1
- package/dist/dag.d.cts.map +0 -1
- package/dist/dag.d.mts.map +0 -1
- package/dist/db.cjs +0 -81
- package/dist/db.cjs.map +0 -1
- package/dist/db.d.cts +0 -30
- package/dist/db.d.cts.map +0 -1
- package/dist/db.d.mts +0 -30
- package/dist/db.d.mts.map +0 -1
- package/dist/db.mjs +0 -75
- package/dist/db.mjs.map +0 -1
- package/dist/fastkv.d.cts.map +0 -1
- package/dist/fastkv.d.mts.map +0 -1
- package/dist/integrity.d.cts.map +0 -1
- package/dist/integrity.d.mts.map +0 -1
- package/dist/merge.d.cts.map +0 -1
- package/dist/merge.d.mts.map +0 -1
- package/dist/mf.d.cts.map +0 -1
- package/dist/mf.d.mts.map +0 -1
- package/dist/plugin.d.cts.map +0 -1
- package/dist/plugin.d.mts.map +0 -1
- package/dist/service-descriptor.d.cts.map +0 -1
- package/dist/service-descriptor.d.mts.map +0 -1
- package/dist/types.d.cts.map +0 -1
- package/dist/types.d.mts.map +0 -1
- package/dist/ui/head.d.cts.map +0 -1
- package/dist/ui/head.d.mts.map +0 -1
- package/dist/ui/metadata.d.cts.map +0 -1
- package/dist/ui/metadata.d.mts.map +0 -1
- package/dist/ui/router.d.cts.map +0 -1
- package/dist/ui/router.d.mts.map +0 -1
- package/dist/ui/runtime.d.cts.map +0 -1
- package/dist/ui/runtime.d.mts.map +0 -1
- package/dist/ui/types.d.cts.map +0 -1
- package/dist/ui/types.d.mts.map +0 -1
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { DUPLICATE_OBJECT_SQLSTATES, extractExpectedTables, getMigrationStorage, isConcurrentDdlUniqueViolation, isRetryableMigrationExecutionError, toSqlArray, visitCauses } from "./core.mjs";
|
|
2
|
+
import { DatabaseError } from "./errors.mjs";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { Effect, Option, Schedule, Schema } from "effect";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { sql } from "drizzle-orm";
|
|
8
|
+
|
|
9
|
+
//#region src/db/run-migrations.ts
|
|
10
|
+
const migrationJournalSchema = Schema.Struct({ entries: Schema.Array(Schema.Struct({
|
|
11
|
+
idx: Schema.Finite,
|
|
12
|
+
when: Schema.Finite,
|
|
13
|
+
tag: Schema.String
|
|
14
|
+
})) });
|
|
15
|
+
const DEFAULT_DUPLICATE_SQLSTATES = DUPLICATE_OBJECT_SQLSTATES;
|
|
16
|
+
function normalizeRows(result) {
|
|
17
|
+
if (Array.isArray(result)) return result;
|
|
18
|
+
if (result && typeof result === "object" && "rows" in result) return result.rows;
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
function isDuplicateObjectError(error, codes) {
|
|
22
|
+
return visitCauses(error, 6, (link) => {
|
|
23
|
+
const code = link.code;
|
|
24
|
+
return typeof code === "string" && codes.includes(code);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Whether a failed migration statement should be treated as duplicate-DDL
|
|
29
|
+
* tolerance: either an explicit duplicate-object class, or the concurrent-DDL
|
|
30
|
+
* catalog collision (SQLSTATE 23505 on a pg_catalog unique index) that two
|
|
31
|
+
* booting processes can produce when they run the same `CREATE TABLE` against
|
|
32
|
+
* a fresh database at the same time.
|
|
33
|
+
*/
|
|
34
|
+
function isTolerableDuplicateDdl(error, codes) {
|
|
35
|
+
return isDuplicateObjectError(error, codes) || isConcurrentDdlUniqueViolation(error);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check which of the given expected tables already exist in the target schema.
|
|
39
|
+
* The schema name is bound as a query parameter.
|
|
40
|
+
*/
|
|
41
|
+
async function existingTablesIn(executor, tables, schemaName) {
|
|
42
|
+
if (tables.length === 0) return /* @__PURE__ */ new Set();
|
|
43
|
+
const schema = schemaName ?? "public";
|
|
44
|
+
const result = await executor.execute(sql`
|
|
45
|
+
SELECT table_name FROM information_schema.tables
|
|
46
|
+
WHERE table_schema = ${schema}
|
|
47
|
+
AND table_name = ANY(${sql.raw(toSqlArray(tables))})
|
|
48
|
+
`);
|
|
49
|
+
return new Set(normalizeRows(result).map((r) => r.table_name));
|
|
50
|
+
}
|
|
51
|
+
/** Read applied hashes from the migration journal. */
|
|
52
|
+
async function readAppliedHashesIn(executor, ref) {
|
|
53
|
+
const result = await executor.execute(sql`SELECT hash FROM ${ref}`);
|
|
54
|
+
return new Set(normalizeRows(result).map((r) => r.hash));
|
|
55
|
+
}
|
|
56
|
+
function loadMigrations(opts = {}) {
|
|
57
|
+
return Effect.gen(function* () {
|
|
58
|
+
if (opts.virtual) {
|
|
59
|
+
const mod = yield* Effect.tryPromise({
|
|
60
|
+
try: () => opts.virtual(),
|
|
61
|
+
catch: (cause) => new DatabaseError({
|
|
62
|
+
stage: "load",
|
|
63
|
+
cause
|
|
64
|
+
})
|
|
65
|
+
}).pipe(Effect.option);
|
|
66
|
+
const migrations = Option.getOrUndefined(mod)?.default;
|
|
67
|
+
if (migrations?.length) {
|
|
68
|
+
yield* Effect.logInfo(`[Database] Loaded ${migrations.length} migration(s) from virtual module`);
|
|
69
|
+
return {
|
|
70
|
+
migrations,
|
|
71
|
+
source: "virtual"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
yield* Effect.logDebug("[Database] Virtual migrations unavailable, loading from disk");
|
|
75
|
+
}
|
|
76
|
+
const diskMigrations = Option.getOrUndefined(yield* loadMigrationsFromDisk(opts.fromDir).pipe(Effect.option));
|
|
77
|
+
if (diskMigrations) {
|
|
78
|
+
yield* Effect.logInfo(`[Database] Loaded ${diskMigrations.length} migration(s) from disk`);
|
|
79
|
+
return {
|
|
80
|
+
migrations: diskMigrations,
|
|
81
|
+
source: "disk"
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
yield* Effect.logWarning("[Database] No migrations found from virtual or disk");
|
|
85
|
+
return {
|
|
86
|
+
migrations: [],
|
|
87
|
+
source: "disk"
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function loadMigrationsFromDisk(fromDir) {
|
|
92
|
+
return Effect.gen(function* () {
|
|
93
|
+
const migrationsDir = resolve(fromDir ?? import.meta.dirname, "migrations");
|
|
94
|
+
const journalPath = join(migrationsDir, "meta", "_journal.json");
|
|
95
|
+
if (!existsSync(journalPath)) return yield* new DatabaseError({
|
|
96
|
+
stage: "load",
|
|
97
|
+
cause: /* @__PURE__ */ new Error(`Migrations journal not found at ${journalPath}. Run \`db:generate\` first.`)
|
|
98
|
+
});
|
|
99
|
+
const journalContents = yield* Effect.try({
|
|
100
|
+
try: () => readFileSync(journalPath, "utf8"),
|
|
101
|
+
catch: (cause) => new DatabaseError({
|
|
102
|
+
stage: "load",
|
|
103
|
+
cause
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
const json = yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Json))(journalContents).pipe(Effect.mapError((cause) => new DatabaseError({
|
|
107
|
+
stage: "load",
|
|
108
|
+
cause
|
|
109
|
+
})));
|
|
110
|
+
const journal = yield* Schema.decodeUnknownEffect(migrationJournalSchema)(json).pipe(Effect.mapError((cause) => new DatabaseError({
|
|
111
|
+
stage: "load",
|
|
112
|
+
cause
|
|
113
|
+
})));
|
|
114
|
+
return yield* Effect.forEach(journal.entries, (entry) => Effect.try({
|
|
115
|
+
try: () => {
|
|
116
|
+
const sqlPath = join(migrationsDir, `${entry.tag}.sql`);
|
|
117
|
+
if (!existsSync(sqlPath)) throw new Error(`Migration SQL file not found: ${sqlPath}`);
|
|
118
|
+
const raw = readFileSync(sqlPath, "utf8");
|
|
119
|
+
const sqlStatements = raw.split("--> statement-breakpoint").map((statement) => statement.trim());
|
|
120
|
+
const hash = createHash("sha256").update(raw).digest("hex");
|
|
121
|
+
return {
|
|
122
|
+
idx: entry.idx,
|
|
123
|
+
when: entry.when,
|
|
124
|
+
tag: entry.tag,
|
|
125
|
+
hash,
|
|
126
|
+
sql: sqlStatements
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
catch: (cause) => new DatabaseError({
|
|
130
|
+
stage: "load",
|
|
131
|
+
cause
|
|
132
|
+
})
|
|
133
|
+
}));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function journalRef(s) {
|
|
137
|
+
return sql.raw(`"${s.schema}"."${s.table}"`);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Apply one statement under a savepoint, tolerating duplicate DDL: either an
|
|
141
|
+
* explicit duplicate-object class or the concurrent-DDL catalog collision a
|
|
142
|
+
* non-participant migrator (drizzle-kit) can still produce.
|
|
143
|
+
*/
|
|
144
|
+
async function applyWithSavepoint(tx, query, migrationTag, savepoint, duplicateSqlStates) {
|
|
145
|
+
await tx.execute(sql.raw(`SAVEPOINT ${savepoint}`));
|
|
146
|
+
try {
|
|
147
|
+
await tx.execute(query);
|
|
148
|
+
} catch (cause) {
|
|
149
|
+
if (isTolerableDuplicateDdl(cause, duplicateSqlStates)) {
|
|
150
|
+
await tx.execute(sql.raw(`ROLLBACK TO SAVEPOINT ${savepoint}`));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
throw new DatabaseError({
|
|
154
|
+
stage: "migration",
|
|
155
|
+
migrationTag,
|
|
156
|
+
cause
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
await tx.execute(sql.raw(`RELEASE SAVEPOINT ${savepoint}`));
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The whole migration run inside ONE transaction that opens with a
|
|
163
|
+
* journal-scoped `pg_advisory_xact_lock`. Drizzle's `db.transaction` pins a
|
|
164
|
+
* single pooled client for the callback, so the lock, the journal read, the
|
|
165
|
+
* DDL, and the journal inserts all share one session; the lock releases at
|
|
166
|
+
* COMMIT/ROLLBACK or on connection death — a crashed migrator can never
|
|
167
|
+
* orphan it. A concurrent migrator blocks (bounded by the driver's
|
|
168
|
+
* `lock_timeout`), then reads the winner's committed journal rows and applies
|
|
169
|
+
* nothing.
|
|
170
|
+
*/
|
|
171
|
+
async function runLockedTransaction(db, args) {
|
|
172
|
+
const { sorted, journal, ref, schemaName, duplicateSqlStates } = args;
|
|
173
|
+
const appliedTags = [];
|
|
174
|
+
const logs = [];
|
|
175
|
+
await db.transaction(async (tx) => {
|
|
176
|
+
await tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended(${`${journal.schema}.${journal.table}`}, 0))`);
|
|
177
|
+
await applyWithSavepoint(tx, sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(`"${journal.schema}"`)}`, "init-schema", "sp_init_schema", duplicateSqlStates);
|
|
178
|
+
await applyWithSavepoint(tx, sql`
|
|
179
|
+
CREATE TABLE IF NOT EXISTS ${ref} (
|
|
180
|
+
id SERIAL PRIMARY KEY,
|
|
181
|
+
hash text NOT NULL,
|
|
182
|
+
created_at bigint
|
|
183
|
+
)
|
|
184
|
+
`, "init-table", "sp_init_table", duplicateSqlStates);
|
|
185
|
+
if (schemaName) await applyWithSavepoint(tx, sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(`"${schemaName}"`)}`, "init-data-schema", "sp_init_data_schema", duplicateSqlStates);
|
|
186
|
+
const appliedHashes = await readAppliedHashesIn(tx, ref);
|
|
187
|
+
for (const migration of sorted) {
|
|
188
|
+
if (appliedHashes.has(migration.hash) || appliedHashes.has(migration.hash.slice(0, 12))) continue;
|
|
189
|
+
const expectedTables = extractExpectedTables([migration]);
|
|
190
|
+
if (expectedTables.length > 0) {
|
|
191
|
+
const existing = await existingTablesIn(tx, expectedTables, schemaName);
|
|
192
|
+
const missingTables = expectedTables.filter((t) => !existing.has(t));
|
|
193
|
+
if (missingTables.length === 0) {
|
|
194
|
+
logs.push(`[Database] All tables for migration ${migration.tag} already exist — recording as applied without replaying DDL`);
|
|
195
|
+
await tx.execute(sql`INSERT INTO ${ref} (hash, created_at) VALUES (${migration.hash}, ${migration.when})`);
|
|
196
|
+
appliedHashes.add(migration.hash);
|
|
197
|
+
appliedTags.push(migration.tag);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (missingTables.length < expectedTables.length) logs.push(`[Database] Partial table overlap for migration ${migration.tag}: ${expectedTables.length - missingTables.length} table(s) exist but not all. Applying migration — existing tables: ${expectedTables.filter((t) => existing.has(t)).join(", ")}`);
|
|
201
|
+
}
|
|
202
|
+
logs.push(`[Database] Applying migration: ${migration.tag}`);
|
|
203
|
+
for (const [i, statement] of migration.sql.entries()) {
|
|
204
|
+
const stmt = schemaName ? statement.replace(/"public"\./g, "") : statement;
|
|
205
|
+
await applyWithSavepoint(tx, sql.raw(stmt), migration.tag, `stmt_${i}`, duplicateSqlStates);
|
|
206
|
+
}
|
|
207
|
+
await tx.execute(sql`INSERT INTO ${ref} (hash, created_at) VALUES (${migration.hash}, ${migration.when})`);
|
|
208
|
+
appliedTags.push(migration.tag);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
appliedTags,
|
|
213
|
+
logs
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Apply pending migrations to the target database.
|
|
218
|
+
*
|
|
219
|
+
* Namespace model: `opts.schemaName` (`plugin_<slug>`) scopes data tables; the
|
|
220
|
+
* journal lives in `opts.journal` (default the shared `drizzle.__drizzle_migrations`).
|
|
221
|
+
* Undefined `schemaName` means public-schema (api) or dedicated-DB (auth) topology.
|
|
222
|
+
*
|
|
223
|
+
* Concurrency: the run serializes on a journal-scoped Postgres advisory
|
|
224
|
+
* transaction lock, so the dev double-boot (plugin dev-server + the host's
|
|
225
|
+
* in-process load), parallel test files, and overlapping production replicas
|
|
226
|
+
* converge instead of colliding in pg_catalog. SAVEPOINT-based duplicate-DDL
|
|
227
|
+
* tolerance stays as defense-in-depth for non-participants (drizzle-kit).
|
|
228
|
+
*
|
|
229
|
+
* Reliability floor: hash-tracked idempotence with a preflight that records
|
|
230
|
+
* fully-overlapped migrations as applied, everything in one locked
|
|
231
|
+
* transaction, retried on deadlock/serialization/lock-timeout/connection
|
|
232
|
+
* states — a failed attempt rolls back cleanly and re-runs.
|
|
233
|
+
*/
|
|
234
|
+
function runMigrations(db, migrations, opts = {}) {
|
|
235
|
+
return Effect.gen(function* () {
|
|
236
|
+
const sorted = [...migrations].sort((a, b) => a.idx - b.idx);
|
|
237
|
+
const journal = opts.journal ?? getMigrationStorage();
|
|
238
|
+
const schemaName = opts.schemaName;
|
|
239
|
+
const duplicateSqlStates = opts.duplicateSqlStates ?? DEFAULT_DUPLICATE_SQLSTATES;
|
|
240
|
+
const { appliedTags, logs } = yield* Effect.retry(Effect.tryPromise({
|
|
241
|
+
try: () => runLockedTransaction(db, {
|
|
242
|
+
sorted,
|
|
243
|
+
journal,
|
|
244
|
+
ref: journalRef(journal),
|
|
245
|
+
schemaName,
|
|
246
|
+
duplicateSqlStates
|
|
247
|
+
}),
|
|
248
|
+
catch: (cause) => cause instanceof DatabaseError ? cause : new DatabaseError({
|
|
249
|
+
stage: "migration",
|
|
250
|
+
migrationTag: "run",
|
|
251
|
+
cause
|
|
252
|
+
})
|
|
253
|
+
}), {
|
|
254
|
+
schedule: Schedule.spaced("500 millis"),
|
|
255
|
+
times: 3,
|
|
256
|
+
while: isRetryableMigrationExecutionError
|
|
257
|
+
});
|
|
258
|
+
for (const line of logs) yield* Effect.logInfo(line);
|
|
259
|
+
return {
|
|
260
|
+
applied: appliedTags.length,
|
|
261
|
+
total: sorted.length,
|
|
262
|
+
storage: journal,
|
|
263
|
+
schema: schemaName
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Detect drift between the local migration set and the database journal.
|
|
269
|
+
*
|
|
270
|
+
* Pass an explicit `journal` resolved from the caller's workspace for reliable
|
|
271
|
+
* slug derivation; the default relies on `process.env.npm_package_name`, which is
|
|
272
|
+
* unreliable under bundlers and Module Federation remotes.
|
|
273
|
+
*/
|
|
274
|
+
function detectDrift(db, migrations, journal, schemaName) {
|
|
275
|
+
return Effect.gen(function* () {
|
|
276
|
+
const storage = journal ?? getMigrationStorage();
|
|
277
|
+
const expectedTables = extractExpectedTables(migrations);
|
|
278
|
+
const ref = journalRef(storage);
|
|
279
|
+
const appliedCount = (yield* Effect.tryPromise({
|
|
280
|
+
try: () => readAppliedHashesIn(db, ref),
|
|
281
|
+
catch: (cause) => new DatabaseError({
|
|
282
|
+
stage: "migration",
|
|
283
|
+
migrationTag: "read-applied",
|
|
284
|
+
cause
|
|
285
|
+
})
|
|
286
|
+
}).pipe(Effect.orElseSucceed(() => /* @__PURE__ */ new Set()))).size;
|
|
287
|
+
if (expectedTables.length === 0) return {
|
|
288
|
+
status: "empty",
|
|
289
|
+
expectedTables: [],
|
|
290
|
+
missingTables: [],
|
|
291
|
+
appliedHashes: appliedCount,
|
|
292
|
+
localHashes: migrations.length,
|
|
293
|
+
storage
|
|
294
|
+
};
|
|
295
|
+
const existing = yield* Effect.tryPromise({
|
|
296
|
+
try: () => existingTablesIn(db, expectedTables, schemaName),
|
|
297
|
+
catch: (cause) => new DatabaseError({
|
|
298
|
+
stage: "migration",
|
|
299
|
+
migrationTag: "preflight-table-check",
|
|
300
|
+
cause
|
|
301
|
+
})
|
|
302
|
+
}).pipe(Effect.orElseSucceed(() => /* @__PURE__ */ new Set()));
|
|
303
|
+
const missingTables = expectedTables.filter((t) => !existing.has(t));
|
|
304
|
+
if (appliedCount === 0 && missingTables.length === 0) return {
|
|
305
|
+
status: "untracked-existing-schema",
|
|
306
|
+
expectedTables,
|
|
307
|
+
missingTables: [],
|
|
308
|
+
appliedHashes: 0,
|
|
309
|
+
localHashes: migrations.length,
|
|
310
|
+
storage
|
|
311
|
+
};
|
|
312
|
+
if (missingTables.length === 0) return {
|
|
313
|
+
status: "healthy",
|
|
314
|
+
expectedTables,
|
|
315
|
+
missingTables: [],
|
|
316
|
+
appliedHashes: appliedCount,
|
|
317
|
+
localHashes: migrations.length,
|
|
318
|
+
storage
|
|
319
|
+
};
|
|
320
|
+
if (missingTables.length === expectedTables.length) return {
|
|
321
|
+
status: "drift-safe-repair",
|
|
322
|
+
expectedTables,
|
|
323
|
+
missingTables,
|
|
324
|
+
appliedHashes: appliedCount,
|
|
325
|
+
localHashes: migrations.length,
|
|
326
|
+
storage
|
|
327
|
+
};
|
|
328
|
+
return {
|
|
329
|
+
status: "drift-manual",
|
|
330
|
+
expectedTables,
|
|
331
|
+
missingTables,
|
|
332
|
+
appliedHashes: appliedCount,
|
|
333
|
+
localHashes: migrations.length,
|
|
334
|
+
storage
|
|
335
|
+
};
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
//#endregion
|
|
340
|
+
export { detectDrift, loadMigrations, runMigrations };
|
|
341
|
+
//# sourceMappingURL=run-migrations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-migrations.mjs","names":[],"sources":["../../src/db/run-migrations.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { sql } from \"drizzle-orm\";\nimport { Effect, Option, Schedule, Schema } from \"effect\";\nimport {\n DUPLICATE_OBJECT_SQLSTATES,\n extractExpectedTables,\n getMigrationStorage,\n isConcurrentDdlUniqueViolation,\n isRetryableMigrationExecutionError,\n type MigrationStorage,\n toSqlArray,\n visitCauses,\n} from \"./core\";\nimport { DatabaseError } from \"./errors\";\n\nexport interface Migration {\n idx: number;\n when: number;\n tag: string;\n hash: string;\n sql: string[];\n}\n\n/**\n * Minimal structural view of a drizzle PgDatabase — the concrete per-workspace\n * `PgDatabase<PgQueryResultHKT, TSchema>` values satisfy this.\n */\nexport interface MigrationDatabase {\n execute(query: unknown): Promise<unknown>;\n transaction<T>(fn: (tx: { execute(query: unknown): Promise<unknown> }) => Promise<T>): Promise<T>;\n}\n\nexport interface LoadedMigrations {\n migrations: Migration[];\n source: \"virtual\" | \"disk\";\n}\n\nconst migrationJournalSchema = Schema.Struct({\n entries: Schema.Array(\n Schema.Struct({\n idx: Schema.Finite,\n when: Schema.Finite,\n tag: Schema.String,\n }),\n ),\n});\n\nexport interface DriftReport {\n status: \"healthy\" | \"empty\" | \"untracked-existing-schema\" | \"drift-safe-repair\" | \"drift-manual\";\n expectedTables: string[];\n missingTables: string[];\n appliedHashes: number;\n localHashes: number;\n storage: MigrationStorage;\n}\n\nexport interface MigrationReport {\n applied: number;\n total: number;\n storage: MigrationStorage;\n schema: string | undefined;\n}\n\nexport interface RunMigrationsOptions {\n schemaName?: string;\n journal?: MigrationStorage;\n duplicateSqlStates?: readonly string[];\n}\n\nconst DEFAULT_DUPLICATE_SQLSTATES: readonly string[] = DUPLICATE_OBJECT_SQLSTATES;\n\nfunction normalizeRows<T>(result: unknown): T[] {\n if (Array.isArray(result)) return result as T[];\n if (result && typeof result === \"object\" && \"rows\" in result) {\n return (result as { rows: T[] }).rows;\n }\n return [];\n}\n\ntype QueryExecutor = { execute(query: unknown): Promise<unknown> };\n\nfunction isDuplicateObjectError(error: unknown, codes: readonly string[]): boolean {\n return visitCauses(error, 6, (link) => {\n const code = (link as { code?: unknown }).code;\n return typeof code === \"string\" && codes.includes(code);\n });\n}\n\n/**\n * Whether a failed migration statement should be treated as duplicate-DDL\n * tolerance: either an explicit duplicate-object class, or the concurrent-DDL\n * catalog collision (SQLSTATE 23505 on a pg_catalog unique index) that two\n * booting processes can produce when they run the same `CREATE TABLE` against\n * a fresh database at the same time.\n */\nfunction isTolerableDuplicateDdl(error: unknown, codes: readonly string[]): boolean {\n return isDuplicateObjectError(error, codes) || isConcurrentDdlUniqueViolation(error);\n}\n\n/**\n * Check which of the given expected tables already exist in the target schema.\n * The schema name is bound as a query parameter.\n */\nasync function existingTablesIn(\n executor: QueryExecutor,\n tables: string[],\n schemaName?: string,\n): Promise<Set<string>> {\n if (tables.length === 0) return new Set<string>();\n const schema = schemaName ?? \"public\";\n const result = await executor.execute(sql`\n SELECT table_name FROM information_schema.tables\n WHERE table_schema = ${schema}\n AND table_name = ANY(${sql.raw(toSqlArray(tables))})\n `);\n return new Set(normalizeRows<{ table_name: string }>(result).map((r) => r.table_name));\n}\n\n/** Read applied hashes from the migration journal. */\nasync function readAppliedHashesIn(\n executor: QueryExecutor,\n ref: ReturnType<typeof sql.raw>,\n): Promise<Set<string>> {\n const result = await executor.execute(sql`SELECT hash FROM ${ref}`);\n return new Set(normalizeRows<{ hash: string }>(result).map((r) => r.hash));\n}\n\nexport interface LoadMigrationsOptions {\n /** Directory containing the workspace's drizzle `migrations/` folder for the disk fallback. */\n fromDir?: string;\n /**\n * Bundler-provided virtual-module loader (e.g. `virtual:drizzle-migrations.sql`\n * registered by rspack). Lives at the call site — the shared package must not\n * name the virtual module, which only exists inside plugin bundles.\n */\n virtual?: () => Promise<{ default?: Migration[] }>;\n}\n\nexport function loadMigrations(\n opts: LoadMigrationsOptions = {},\n): Effect.Effect<LoadedMigrations, DatabaseError> {\n return Effect.gen(function* () {\n if (opts.virtual) {\n const mod = yield* Effect.tryPromise({\n try: () => opts.virtual!(),\n catch: (cause) => new DatabaseError({ stage: \"load\", cause }),\n }).pipe(Effect.option);\n const migrations = Option.getOrUndefined(mod)?.default;\n if (migrations?.length) {\n yield* Effect.logInfo(\n `[Database] Loaded ${migrations.length} migration(s) from virtual module`,\n );\n return { migrations, source: \"virtual\" as const };\n }\n yield* Effect.logDebug(\"[Database] Virtual migrations unavailable, loading from disk\");\n }\n\n const diskMigrations = Option.getOrUndefined(\n yield* loadMigrationsFromDisk(opts.fromDir).pipe(Effect.option),\n );\n if (diskMigrations) {\n yield* Effect.logInfo(`[Database] Loaded ${diskMigrations.length} migration(s) from disk`);\n return { migrations: diskMigrations, source: \"disk\" as const };\n }\n\n yield* Effect.logWarning(\"[Database] No migrations found from virtual or disk\");\n return { migrations: [], source: \"disk\" as const };\n });\n}\n\nfunction loadMigrationsFromDisk(fromDir?: string): Effect.Effect<Migration[], DatabaseError> {\n return Effect.gen(function* () {\n const migrationsDir = resolve(fromDir ?? import.meta.dirname, \"migrations\");\n const journalPath = join(migrationsDir, \"meta\", \"_journal.json\");\n\n if (!existsSync(journalPath)) {\n return yield* new DatabaseError({\n stage: \"load\",\n cause: new Error(\n `Migrations journal not found at ${journalPath}. Run \\`db:generate\\` first.`,\n ),\n });\n }\n\n const journalContents = yield* Effect.try({\n try: () => readFileSync(journalPath, \"utf8\"),\n catch: (cause) => new DatabaseError({ stage: \"load\", cause }),\n });\n const json = yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Json))(\n journalContents,\n ).pipe(Effect.mapError((cause) => new DatabaseError({ stage: \"load\", cause })));\n const journal = yield* Schema.decodeUnknownEffect(migrationJournalSchema)(json).pipe(\n Effect.mapError((cause) => new DatabaseError({ stage: \"load\", cause })),\n );\n\n return yield* Effect.forEach(journal.entries, (entry) =>\n Effect.try({\n try: () => {\n const sqlPath = join(migrationsDir, `${entry.tag}.sql`);\n if (!existsSync(sqlPath)) {\n throw new Error(`Migration SQL file not found: ${sqlPath}`);\n }\n const raw = readFileSync(sqlPath, \"utf8\");\n const sqlStatements = raw\n .split(\"--> statement-breakpoint\")\n .map((statement) => statement.trim());\n const hash = createHash(\"sha256\").update(raw).digest(\"hex\");\n return { idx: entry.idx, when: entry.when, tag: entry.tag, hash, sql: sqlStatements };\n },\n catch: (cause) => new DatabaseError({ stage: \"load\", cause }),\n }),\n );\n });\n}\n\nfunction journalRef(s: MigrationStorage): ReturnType<typeof sql> {\n return sql.raw(`\"${s.schema}\".\"${s.table}\"`);\n}\n\n/**\n * Apply one statement under a savepoint, tolerating duplicate DDL: either an\n * explicit duplicate-object class or the concurrent-DDL catalog collision a\n * non-participant migrator (drizzle-kit) can still produce.\n */\nasync function applyWithSavepoint(\n tx: QueryExecutor,\n query: ReturnType<typeof sql>,\n migrationTag: string,\n savepoint: string,\n duplicateSqlStates: readonly string[],\n): Promise<void> {\n await tx.execute(sql.raw(`SAVEPOINT ${savepoint}`));\n try {\n await tx.execute(query);\n } catch (cause) {\n if (isTolerableDuplicateDdl(cause, duplicateSqlStates)) {\n await tx.execute(sql.raw(`ROLLBACK TO SAVEPOINT ${savepoint}`));\n return;\n }\n throw new DatabaseError({ stage: \"migration\", migrationTag, cause });\n }\n await tx.execute(sql.raw(`RELEASE SAVEPOINT ${savepoint}`));\n}\n\ninterface LockedRunArgs {\n sorted: Migration[];\n journal: MigrationStorage;\n ref: ReturnType<typeof sql.raw>;\n schemaName: string | undefined;\n duplicateSqlStates: readonly string[];\n}\n\n/**\n * The whole migration run inside ONE transaction that opens with a\n * journal-scoped `pg_advisory_xact_lock`. Drizzle's `db.transaction` pins a\n * single pooled client for the callback, so the lock, the journal read, the\n * DDL, and the journal inserts all share one session; the lock releases at\n * COMMIT/ROLLBACK or on connection death — a crashed migrator can never\n * orphan it. A concurrent migrator blocks (bounded by the driver's\n * `lock_timeout`), then reads the winner's committed journal rows and applies\n * nothing.\n */\nasync function runLockedTransaction(\n db: MigrationDatabase,\n args: LockedRunArgs,\n): Promise<{ appliedTags: string[]; logs: string[] }> {\n const { sorted, journal, ref, schemaName, duplicateSqlStates } = args;\n const appliedTags: string[] = [];\n const logs: string[] = [];\n\n await db.transaction(async (tx) => {\n await tx.execute(\n sql`SELECT pg_advisory_xact_lock(hashtextextended(${`${journal.schema}.${journal.table}`}, 0))`,\n );\n\n await applyWithSavepoint(\n tx,\n sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(`\"${journal.schema}\"`)}`,\n \"init-schema\",\n \"sp_init_schema\",\n duplicateSqlStates,\n );\n await applyWithSavepoint(\n tx,\n sql`\n CREATE TABLE IF NOT EXISTS ${ref} (\n id SERIAL PRIMARY KEY,\n hash text NOT NULL,\n created_at bigint\n )\n `,\n \"init-table\",\n \"sp_init_table\",\n duplicateSqlStates,\n );\n if (schemaName) {\n await applyWithSavepoint(\n tx,\n sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(`\"${schemaName}\"`)}`,\n \"init-data-schema\",\n \"sp_init_data_schema\",\n duplicateSqlStates,\n );\n }\n\n const appliedHashes = await readAppliedHashesIn(tx, ref);\n\n for (const migration of sorted) {\n const isApplied =\n appliedHashes.has(migration.hash) || appliedHashes.has(migration.hash.slice(0, 12));\n if (isApplied) continue;\n\n // Preflight: if this migration's expected tables already exist, record it\n // as applied rather than crashing on a duplicate DDL error.\n const expectedTables = extractExpectedTables([migration]);\n if (expectedTables.length > 0) {\n const existing = await existingTablesIn(tx, expectedTables, schemaName);\n const missingTables = expectedTables.filter((t) => !existing.has(t));\n if (missingTables.length === 0) {\n logs.push(\n `[Database] All tables for migration ${migration.tag} already exist — ` +\n `recording as applied without replaying DDL`,\n );\n await tx.execute(\n sql`INSERT INTO ${ref} (hash, created_at) VALUES (${migration.hash}, ${migration.when})`,\n );\n appliedHashes.add(migration.hash);\n appliedTags.push(migration.tag);\n continue;\n }\n if (missingTables.length < expectedTables.length) {\n logs.push(\n `[Database] Partial table overlap for migration ${migration.tag}: ` +\n `${expectedTables.length - missingTables.length} table(s) exist but not all. ` +\n `Applying migration — existing tables: ${expectedTables.filter((t) => existing.has(t)).join(\", \")}`,\n );\n }\n }\n\n logs.push(`[Database] Applying migration: ${migration.tag}`);\n\n for (const [i, statement] of migration.sql.entries()) {\n const stmt = schemaName ? statement.replace(/\"public\"\\./g, \"\") : statement;\n await applyWithSavepoint(tx, sql.raw(stmt), migration.tag, `stmt_${i}`, duplicateSqlStates);\n }\n await tx.execute(\n sql`INSERT INTO ${ref} (hash, created_at) VALUES (${migration.hash}, ${migration.when})`,\n );\n appliedTags.push(migration.tag);\n }\n });\n\n return { appliedTags, logs };\n}\n\n/**\n * Apply pending migrations to the target database.\n *\n * Namespace model: `opts.schemaName` (`plugin_<slug>`) scopes data tables; the\n * journal lives in `opts.journal` (default the shared `drizzle.__drizzle_migrations`).\n * Undefined `schemaName` means public-schema (api) or dedicated-DB (auth) topology.\n *\n * Concurrency: the run serializes on a journal-scoped Postgres advisory\n * transaction lock, so the dev double-boot (plugin dev-server + the host's\n * in-process load), parallel test files, and overlapping production replicas\n * converge instead of colliding in pg_catalog. SAVEPOINT-based duplicate-DDL\n * tolerance stays as defense-in-depth for non-participants (drizzle-kit).\n *\n * Reliability floor: hash-tracked idempotence with a preflight that records\n * fully-overlapped migrations as applied, everything in one locked\n * transaction, retried on deadlock/serialization/lock-timeout/connection\n * states — a failed attempt rolls back cleanly and re-runs.\n */\nexport function runMigrations(\n db: MigrationDatabase,\n migrations: Migration[],\n opts: RunMigrationsOptions = {},\n): Effect.Effect<MigrationReport, DatabaseError> {\n return Effect.gen(function* () {\n const sorted = [...migrations].sort((a, b) => a.idx - b.idx);\n const journal = opts.journal ?? getMigrationStorage();\n const schemaName = opts.schemaName;\n const duplicateSqlStates = opts.duplicateSqlStates ?? DEFAULT_DUPLICATE_SQLSTATES;\n\n const { appliedTags, logs } = yield* Effect.retry(\n Effect.tryPromise({\n try: () =>\n runLockedTransaction(db, {\n sorted,\n journal,\n ref: journalRef(journal),\n schemaName,\n duplicateSqlStates,\n }),\n catch: (cause) =>\n cause instanceof DatabaseError\n ? cause\n : new DatabaseError({ stage: \"migration\", migrationTag: \"run\", cause }),\n }),\n {\n schedule: Schedule.spaced(\"500 millis\"),\n times: 3,\n while: isRetryableMigrationExecutionError,\n },\n );\n\n for (const line of logs) yield* Effect.logInfo(line);\n\n return {\n applied: appliedTags.length,\n total: sorted.length,\n storage: journal,\n schema: schemaName,\n };\n });\n}\n\n/**\n * Detect drift between the local migration set and the database journal.\n *\n * Pass an explicit `journal` resolved from the caller's workspace for reliable\n * slug derivation; the default relies on `process.env.npm_package_name`, which is\n * unreliable under bundlers and Module Federation remotes.\n */\nexport function detectDrift(\n db: MigrationDatabase,\n migrations: Migration[],\n journal?: MigrationStorage,\n schemaName?: string,\n): Effect.Effect<DriftReport, DatabaseError> {\n return Effect.gen(function* () {\n const storage = journal ?? getMigrationStorage();\n const expectedTables = extractExpectedTables(migrations);\n const ref = journalRef(storage);\n\n // Lenient by design: drift detection reports on whatever it can read —\n // a failed journal read just means \"nothing tracked yet\".\n const appliedHashes = yield* Effect.tryPromise({\n try: () => readAppliedHashesIn(db, ref),\n catch: (cause) =>\n new DatabaseError({ stage: \"migration\", migrationTag: \"read-applied\", cause }),\n }).pipe(Effect.orElseSucceed(() => new Set<string>()));\n const appliedCount = appliedHashes.size;\n\n if (expectedTables.length === 0) {\n return {\n status: \"empty\",\n expectedTables: [],\n missingTables: [],\n appliedHashes: appliedCount,\n localHashes: migrations.length,\n storage,\n };\n }\n\n const existing = yield* Effect.tryPromise({\n try: () => existingTablesIn(db, expectedTables, schemaName),\n catch: (cause) =>\n new DatabaseError({ stage: \"migration\", migrationTag: \"preflight-table-check\", cause }),\n }).pipe(Effect.orElseSucceed(() => new Set<string>()));\n const missingTables = expectedTables.filter((t) => !existing.has(t));\n\n if (appliedCount === 0 && missingTables.length === 0) {\n // Journal is empty but all expected tables already exist.\n return {\n status: \"untracked-existing-schema\",\n expectedTables,\n missingTables: [],\n appliedHashes: 0,\n localHashes: migrations.length,\n storage,\n };\n }\n\n if (missingTables.length === 0) {\n return {\n status: \"healthy\",\n expectedTables,\n missingTables: [],\n appliedHashes: appliedCount,\n localHashes: migrations.length,\n storage,\n };\n }\n\n if (missingTables.length === expectedTables.length) {\n return {\n status: \"drift-safe-repair\",\n expectedTables,\n missingTables,\n appliedHashes: appliedCount,\n localHashes: migrations.length,\n storage,\n };\n }\n\n return {\n status: \"drift-manual\",\n expectedTables,\n missingTables,\n appliedHashes: appliedCount,\n localHashes: migrations.length,\n storage,\n };\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const require_auth_session = require('./auth-session.cjs');
|
|
2
|
+
const require_auth_login = require('./auth-login.cjs');
|
|
3
|
+
const require_near_cli = require('./near-cli.cjs');
|
|
4
|
+
let near_kit = require("near-kit");
|
|
5
|
+
|
|
6
|
+
//#region src/delegate-signer.ts
|
|
7
|
+
function relayErrorMessage(message) {
|
|
8
|
+
return message.replace(/\n/g, " ");
|
|
9
|
+
}
|
|
10
|
+
async function submitRegistryWriteDelegated(opts) {
|
|
11
|
+
const delegate = await new near_kit.Near({
|
|
12
|
+
network: opts.network,
|
|
13
|
+
defaultSignerId: opts.account,
|
|
14
|
+
privateKey: assertPrivateKey(opts.delegatePrivateKey)
|
|
15
|
+
}).transaction(opts.account).functionCall(opts.contract, "__fastdata_kv", opts.args, {
|
|
16
|
+
gas: "300 Tgas",
|
|
17
|
+
attachedDeposit: "0 yocto"
|
|
18
|
+
}).delegate({
|
|
19
|
+
receiverId: opts.contract,
|
|
20
|
+
blockHeightOffset: 200
|
|
21
|
+
});
|
|
22
|
+
const response = await fetch(opts.relayEndpoint, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: {
|
|
25
|
+
"x-api-key": opts.apiKey,
|
|
26
|
+
"content-type": "application/json"
|
|
27
|
+
},
|
|
28
|
+
body: JSON.stringify({ payload: delegate.payload })
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
let detail = `Relay rejected the transaction (HTTP ${response.status})`;
|
|
32
|
+
try {
|
|
33
|
+
const body = await response.json();
|
|
34
|
+
const relayMessage = body.message ?? body.error;
|
|
35
|
+
if (relayMessage) detail = `${detail}: ${relayErrorMessage(relayMessage)}`;
|
|
36
|
+
} catch {}
|
|
37
|
+
throw new Error(detail);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
txHash: (await response.json()).txHash
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function assertPrivateKey(key) {
|
|
45
|
+
if (!(0, near_kit.isPrivateKey)(key)) throw new Error("Invalid delegate key format (expected ed25519:…)");
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
48
|
+
async function ensureDelegateKey(opts) {
|
|
49
|
+
const existing = require_auth_session.readSessionHandle(opts.configDir)?.delegateKey;
|
|
50
|
+
if (existing && existing.accountId === opts.account && existing.contract === opts.contract && existing.network === opts.network) return existing;
|
|
51
|
+
const keyPair = require_near_cli.generateNearKeyPair();
|
|
52
|
+
const login = await require_auth_login.startDeviceLogin({
|
|
53
|
+
siteUrl: opts.siteUrl,
|
|
54
|
+
delegate: {
|
|
55
|
+
pubKey: keyPair.publicKey,
|
|
56
|
+
contract: opts.contract,
|
|
57
|
+
network: opts.network
|
|
58
|
+
},
|
|
59
|
+
account: opts.account
|
|
60
|
+
});
|
|
61
|
+
console.log(` One-time code: ${login.userCode}`);
|
|
62
|
+
await require_auth_login.openInBrowser(login.verificationUrl).catch((error) => {
|
|
63
|
+
console.log(` ⚠ ${error.message}`);
|
|
64
|
+
});
|
|
65
|
+
console.log(` Waiting for delegate-key approval at ${login.verificationUrl}…`);
|
|
66
|
+
await login.waitForApproval();
|
|
67
|
+
const record = {
|
|
68
|
+
publicKey: keyPair.publicKey,
|
|
69
|
+
privateKey: keyPair.privateKey,
|
|
70
|
+
accountId: opts.account,
|
|
71
|
+
network: opts.network,
|
|
72
|
+
contract: opts.contract,
|
|
73
|
+
mintedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
74
|
+
};
|
|
75
|
+
require_auth_session.updateSessionHandle(opts.configDir, (current) => ({
|
|
76
|
+
...current,
|
|
77
|
+
delegateKey: record
|
|
78
|
+
}));
|
|
79
|
+
return record;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
exports.ensureDelegateKey = ensureDelegateKey;
|
|
84
|
+
exports.submitRegistryWriteDelegated = submitRegistryWriteDelegated;
|
|
85
|
+
//# sourceMappingURL=delegate-signer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate-signer.cjs","names":["Near","isPrivateKey","readSessionHandle","generateNearKeyPair","startDeviceLogin","openInBrowser"],"sources":["../src/delegate-signer.ts"],"sourcesContent":["import { isPrivateKey, Near, type PrivateKey } from \"near-kit\";\nimport { openInBrowser, startDeviceLogin } from \"./auth-login\";\nimport { type DelegateKeyRecord, readSessionHandle, updateSessionHandle } from \"./auth-session\";\nimport type { NetworkId } from \"./fastkv\";\nimport { generateNearKeyPair } from \"./near-cli\";\n\nexport interface RelayResult {\n success: true;\n txHash?: string;\n}\n\nexport interface DelegateSubmitOptions {\n account: string;\n contract: string;\n network: NetworkId;\n args: Record<string, string>;\n delegatePrivateKey: string;\n relayEndpoint: string;\n apiKey: string;\n gas?: string;\n}\n\nfunction relayErrorMessage(message: string): string {\n return message.replace(/\\n/g, \" \");\n}\n\nexport async function submitRegistryWriteDelegated(\n opts: DelegateSubmitOptions,\n): Promise<RelayResult> {\n const near = new Near({\n network: opts.network,\n defaultSignerId: opts.account,\n privateKey: assertPrivateKey(opts.delegatePrivateKey),\n });\n\n const delegate = await near\n .transaction(opts.account)\n .functionCall(opts.contract, \"__fastdata_kv\", opts.args, {\n gas: \"300 Tgas\",\n attachedDeposit: \"0 yocto\",\n })\n .delegate({ receiverId: opts.contract, blockHeightOffset: 200 });\n\n const response = await fetch(opts.relayEndpoint, {\n method: \"POST\",\n headers: {\n \"x-api-key\": opts.apiKey,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({ payload: delegate.payload }),\n });\n\n if (!response.ok) {\n let detail = `Relay rejected the transaction (HTTP ${response.status})`;\n try {\n const body = (await response.json()) as { message?: string; error?: string };\n const relayMessage = body.message ?? body.error;\n if (relayMessage) {\n detail = `${detail}: ${relayErrorMessage(relayMessage)}`;\n }\n } catch {\n // keep the generic message\n }\n throw new Error(detail);\n }\n\n const body = (await response.json()) as { txHash?: string };\n return { success: true, txHash: body.txHash };\n}\n\nfunction assertPrivateKey(key: string): PrivateKey {\n if (!isPrivateKey(key)) {\n throw new Error(\"Invalid delegate key format (expected ed25519:…)\");\n }\n return key as PrivateKey;\n}\n\nexport interface EnsureDelegateKeyOptions {\n configDir: string;\n account: string;\n contract: string;\n network: NetworkId;\n siteUrl: string;\n}\n\nexport async function ensureDelegateKey(\n opts: EnsureDelegateKeyOptions,\n): Promise<DelegateKeyRecord> {\n const existing = readSessionHandle(opts.configDir)?.delegateKey;\n if (\n existing &&\n existing.accountId === opts.account &&\n existing.contract === opts.contract &&\n existing.network === opts.network\n ) {\n return existing;\n }\n\n const keyPair = generateNearKeyPair();\n\n const login = await startDeviceLogin({\n siteUrl: opts.siteUrl,\n delegate: {\n pubKey: keyPair.publicKey,\n contract: opts.contract,\n network: opts.network,\n },\n account: opts.account,\n });\n\n console.log(` One-time code: ${login.userCode}`);\n await openInBrowser(login.verificationUrl).catch((error: unknown) => {\n console.log(` ⚠ ${(error as Error).message}`);\n });\n console.log(` Waiting for delegate-key approval at ${login.verificationUrl}…`);\n\n await login.waitForApproval();\n\n const record: DelegateKeyRecord = {\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n accountId: opts.account,\n network: opts.network,\n contract: opts.contract,\n mintedAt: new Date().toISOString(),\n };\n updateSessionHandle(opts.configDir, (current) => ({ ...current, delegateKey: record }));\n return record;\n}\n"],"mappings":";;;;;;AAsBA,SAAS,kBAAkB,SAAyB;CAClD,OAAO,QAAQ,QAAQ,OAAO,GAAG;AACnC;AAEA,eAAsB,6BACpB,MACsB;CAOtB,MAAM,WAAW,MAAM,IANNA,cAAK;EACpB,SAAS,KAAK;EACd,iBAAiB,KAAK;EACtB,YAAY,iBAAiB,KAAK,kBAAkB;CACtD,CAE0B,CAAC,CACxB,YAAY,KAAK,OAAO,CAAC,CACzB,aAAa,KAAK,UAAU,iBAAiB,KAAK,MAAM;EACvD,KAAK;EACL,iBAAiB;CACnB,CAAC,CAAC,CACD,SAAS;EAAE,YAAY,KAAK;EAAU,mBAAmB;CAAI,CAAC;CAEjE,MAAM,WAAW,MAAM,MAAM,KAAK,eAAe;EAC/C,QAAQ;EACR,SAAS;GACP,aAAa,KAAK;GAClB,gBAAgB;EAClB;EACA,MAAM,KAAK,UAAU,EAAE,SAAS,SAAS,QAAQ,CAAC;CACpD,CAAC;CAED,IAAI,CAAC,SAAS,IAAI;EAChB,IAAI,SAAS,wCAAwC,SAAS,OAAO;EACrE,IAAI;GACF,MAAM,OAAQ,MAAM,SAAS,KAAK;GAClC,MAAM,eAAe,KAAK,WAAW,KAAK;GAC1C,IAAI,cACF,SAAS,GAAG,OAAO,IAAI,kBAAkB,YAAY;EAEzD,QAAQ,CAER;EACA,MAAM,IAAI,MAAM,MAAM;CACxB;CAGA,OAAO;EAAE,SAAS;EAAM,SAAQ,MADZ,SAAS,KAAK,EACE,CAAC;CAAO;AAC9C;AAEA,SAAS,iBAAiB,KAAyB;CACjD,IAAI,KAACC,uBAAa,GAAG,GACnB,MAAM,IAAI,MAAM,kDAAkD;CAEpE,OAAO;AACT;AAUA,eAAsB,kBACpB,MAC4B;CAC5B,MAAM,WAAWC,uCAAkB,KAAK,SAAS,CAAC,EAAE;CACpD,IACE,YACA,SAAS,cAAc,KAAK,WAC5B,SAAS,aAAa,KAAK,YAC3B,SAAS,YAAY,KAAK,SAE1B,OAAO;CAGT,MAAM,UAAUC,qCAAoB;CAEpC,MAAM,QAAQ,MAAMC,oCAAiB;EACnC,SAAS,KAAK;EACd,UAAU;GACR,QAAQ,QAAQ;GAChB,UAAU,KAAK;GACf,SAAS,KAAK;EAChB;EACA,SAAS,KAAK;CAChB,CAAC;CAED,QAAQ,IAAI,oBAAoB,MAAM,UAAU;CAChD,MAAMC,iCAAc,MAAM,eAAe,CAAC,CAAC,OAAO,UAAmB;EACnE,QAAQ,IAAI,OAAQ,MAAgB,SAAS;CAC/C,CAAC;CACD,QAAQ,IAAI,0CAA0C,MAAM,gBAAgB,EAAE;CAE9E,MAAM,MAAM,gBAAgB;CAE5B,MAAM,SAA4B;EAChC,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB,WAAW,KAAK;EAChB,SAAS,KAAK;EACd,UAAU,KAAK;EACf,2BAAU,IAAI,KAAK,EAAC,CAAC,YAAY;CACnC;CACA,yCAAoB,KAAK,YAAY,aAAa;EAAE,GAAG;EAAS,aAAa;CAAO,EAAE;CACtF,OAAO;AACT"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { readSessionHandle, updateSessionHandle } from "./auth-session.mjs";
|
|
2
|
+
import { openInBrowser, startDeviceLogin } from "./auth-login.mjs";
|
|
3
|
+
import { generateNearKeyPair } from "./near-cli.mjs";
|
|
4
|
+
import { Near, isPrivateKey } from "near-kit";
|
|
5
|
+
|
|
6
|
+
//#region src/delegate-signer.ts
|
|
7
|
+
function relayErrorMessage(message) {
|
|
8
|
+
return message.replace(/\n/g, " ");
|
|
9
|
+
}
|
|
10
|
+
async function submitRegistryWriteDelegated(opts) {
|
|
11
|
+
const delegate = await new Near({
|
|
12
|
+
network: opts.network,
|
|
13
|
+
defaultSignerId: opts.account,
|
|
14
|
+
privateKey: assertPrivateKey(opts.delegatePrivateKey)
|
|
15
|
+
}).transaction(opts.account).functionCall(opts.contract, "__fastdata_kv", opts.args, {
|
|
16
|
+
gas: "300 Tgas",
|
|
17
|
+
attachedDeposit: "0 yocto"
|
|
18
|
+
}).delegate({
|
|
19
|
+
receiverId: opts.contract,
|
|
20
|
+
blockHeightOffset: 200
|
|
21
|
+
});
|
|
22
|
+
const response = await fetch(opts.relayEndpoint, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: {
|
|
25
|
+
"x-api-key": opts.apiKey,
|
|
26
|
+
"content-type": "application/json"
|
|
27
|
+
},
|
|
28
|
+
body: JSON.stringify({ payload: delegate.payload })
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
let detail = `Relay rejected the transaction (HTTP ${response.status})`;
|
|
32
|
+
try {
|
|
33
|
+
const body = await response.json();
|
|
34
|
+
const relayMessage = body.message ?? body.error;
|
|
35
|
+
if (relayMessage) detail = `${detail}: ${relayErrorMessage(relayMessage)}`;
|
|
36
|
+
} catch {}
|
|
37
|
+
throw new Error(detail);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
txHash: (await response.json()).txHash
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function assertPrivateKey(key) {
|
|
45
|
+
if (!isPrivateKey(key)) throw new Error("Invalid delegate key format (expected ed25519:…)");
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
48
|
+
async function ensureDelegateKey(opts) {
|
|
49
|
+
const existing = readSessionHandle(opts.configDir)?.delegateKey;
|
|
50
|
+
if (existing && existing.accountId === opts.account && existing.contract === opts.contract && existing.network === opts.network) return existing;
|
|
51
|
+
const keyPair = generateNearKeyPair();
|
|
52
|
+
const login = await startDeviceLogin({
|
|
53
|
+
siteUrl: opts.siteUrl,
|
|
54
|
+
delegate: {
|
|
55
|
+
pubKey: keyPair.publicKey,
|
|
56
|
+
contract: opts.contract,
|
|
57
|
+
network: opts.network
|
|
58
|
+
},
|
|
59
|
+
account: opts.account
|
|
60
|
+
});
|
|
61
|
+
console.log(` One-time code: ${login.userCode}`);
|
|
62
|
+
await openInBrowser(login.verificationUrl).catch((error) => {
|
|
63
|
+
console.log(` ⚠ ${error.message}`);
|
|
64
|
+
});
|
|
65
|
+
console.log(` Waiting for delegate-key approval at ${login.verificationUrl}…`);
|
|
66
|
+
await login.waitForApproval();
|
|
67
|
+
const record = {
|
|
68
|
+
publicKey: keyPair.publicKey,
|
|
69
|
+
privateKey: keyPair.privateKey,
|
|
70
|
+
accountId: opts.account,
|
|
71
|
+
network: opts.network,
|
|
72
|
+
contract: opts.contract,
|
|
73
|
+
mintedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
74
|
+
};
|
|
75
|
+
updateSessionHandle(opts.configDir, (current) => ({
|
|
76
|
+
...current,
|
|
77
|
+
delegateKey: record
|
|
78
|
+
}));
|
|
79
|
+
return record;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
export { ensureDelegateKey, submitRegistryWriteDelegated };
|
|
84
|
+
//# sourceMappingURL=delegate-signer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegate-signer.mjs","names":[],"sources":["../src/delegate-signer.ts"],"sourcesContent":["import { isPrivateKey, Near, type PrivateKey } from \"near-kit\";\nimport { openInBrowser, startDeviceLogin } from \"./auth-login\";\nimport { type DelegateKeyRecord, readSessionHandle, updateSessionHandle } from \"./auth-session\";\nimport type { NetworkId } from \"./fastkv\";\nimport { generateNearKeyPair } from \"./near-cli\";\n\nexport interface RelayResult {\n success: true;\n txHash?: string;\n}\n\nexport interface DelegateSubmitOptions {\n account: string;\n contract: string;\n network: NetworkId;\n args: Record<string, string>;\n delegatePrivateKey: string;\n relayEndpoint: string;\n apiKey: string;\n gas?: string;\n}\n\nfunction relayErrorMessage(message: string): string {\n return message.replace(/\\n/g, \" \");\n}\n\nexport async function submitRegistryWriteDelegated(\n opts: DelegateSubmitOptions,\n): Promise<RelayResult> {\n const near = new Near({\n network: opts.network,\n defaultSignerId: opts.account,\n privateKey: assertPrivateKey(opts.delegatePrivateKey),\n });\n\n const delegate = await near\n .transaction(opts.account)\n .functionCall(opts.contract, \"__fastdata_kv\", opts.args, {\n gas: \"300 Tgas\",\n attachedDeposit: \"0 yocto\",\n })\n .delegate({ receiverId: opts.contract, blockHeightOffset: 200 });\n\n const response = await fetch(opts.relayEndpoint, {\n method: \"POST\",\n headers: {\n \"x-api-key\": opts.apiKey,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({ payload: delegate.payload }),\n });\n\n if (!response.ok) {\n let detail = `Relay rejected the transaction (HTTP ${response.status})`;\n try {\n const body = (await response.json()) as { message?: string; error?: string };\n const relayMessage = body.message ?? body.error;\n if (relayMessage) {\n detail = `${detail}: ${relayErrorMessage(relayMessage)}`;\n }\n } catch {\n // keep the generic message\n }\n throw new Error(detail);\n }\n\n const body = (await response.json()) as { txHash?: string };\n return { success: true, txHash: body.txHash };\n}\n\nfunction assertPrivateKey(key: string): PrivateKey {\n if (!isPrivateKey(key)) {\n throw new Error(\"Invalid delegate key format (expected ed25519:…)\");\n }\n return key as PrivateKey;\n}\n\nexport interface EnsureDelegateKeyOptions {\n configDir: string;\n account: string;\n contract: string;\n network: NetworkId;\n siteUrl: string;\n}\n\nexport async function ensureDelegateKey(\n opts: EnsureDelegateKeyOptions,\n): Promise<DelegateKeyRecord> {\n const existing = readSessionHandle(opts.configDir)?.delegateKey;\n if (\n existing &&\n existing.accountId === opts.account &&\n existing.contract === opts.contract &&\n existing.network === opts.network\n ) {\n return existing;\n }\n\n const keyPair = generateNearKeyPair();\n\n const login = await startDeviceLogin({\n siteUrl: opts.siteUrl,\n delegate: {\n pubKey: keyPair.publicKey,\n contract: opts.contract,\n network: opts.network,\n },\n account: opts.account,\n });\n\n console.log(` One-time code: ${login.userCode}`);\n await openInBrowser(login.verificationUrl).catch((error: unknown) => {\n console.log(` ⚠ ${(error as Error).message}`);\n });\n console.log(` Waiting for delegate-key approval at ${login.verificationUrl}…`);\n\n await login.waitForApproval();\n\n const record: DelegateKeyRecord = {\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n accountId: opts.account,\n network: opts.network,\n contract: opts.contract,\n mintedAt: new Date().toISOString(),\n };\n updateSessionHandle(opts.configDir, (current) => ({ ...current, delegateKey: record }));\n return record;\n}\n"],"mappings":";;;;;;AAsBA,SAAS,kBAAkB,SAAyB;CAClD,OAAO,QAAQ,QAAQ,OAAO,GAAG;AACnC;AAEA,eAAsB,6BACpB,MACsB;CAOtB,MAAM,WAAW,MAAM,IANN,KAAK;EACpB,SAAS,KAAK;EACd,iBAAiB,KAAK;EACtB,YAAY,iBAAiB,KAAK,kBAAkB;CACtD,CAE0B,CAAC,CACxB,YAAY,KAAK,OAAO,CAAC,CACzB,aAAa,KAAK,UAAU,iBAAiB,KAAK,MAAM;EACvD,KAAK;EACL,iBAAiB;CACnB,CAAC,CAAC,CACD,SAAS;EAAE,YAAY,KAAK;EAAU,mBAAmB;CAAI,CAAC;CAEjE,MAAM,WAAW,MAAM,MAAM,KAAK,eAAe;EAC/C,QAAQ;EACR,SAAS;GACP,aAAa,KAAK;GAClB,gBAAgB;EAClB;EACA,MAAM,KAAK,UAAU,EAAE,SAAS,SAAS,QAAQ,CAAC;CACpD,CAAC;CAED,IAAI,CAAC,SAAS,IAAI;EAChB,IAAI,SAAS,wCAAwC,SAAS,OAAO;EACrE,IAAI;GACF,MAAM,OAAQ,MAAM,SAAS,KAAK;GAClC,MAAM,eAAe,KAAK,WAAW,KAAK;GAC1C,IAAI,cACF,SAAS,GAAG,OAAO,IAAI,kBAAkB,YAAY;EAEzD,QAAQ,CAER;EACA,MAAM,IAAI,MAAM,MAAM;CACxB;CAGA,OAAO;EAAE,SAAS;EAAM,SAAQ,MADZ,SAAS,KAAK,EACE,CAAC;CAAO;AAC9C;AAEA,SAAS,iBAAiB,KAAyB;CACjD,IAAI,CAAC,aAAa,GAAG,GACnB,MAAM,IAAI,MAAM,kDAAkD;CAEpE,OAAO;AACT;AAUA,eAAsB,kBACpB,MAC4B;CAC5B,MAAM,WAAW,kBAAkB,KAAK,SAAS,CAAC,EAAE;CACpD,IACE,YACA,SAAS,cAAc,KAAK,WAC5B,SAAS,aAAa,KAAK,YAC3B,SAAS,YAAY,KAAK,SAE1B,OAAO;CAGT,MAAM,UAAU,oBAAoB;CAEpC,MAAM,QAAQ,MAAM,iBAAiB;EACnC,SAAS,KAAK;EACd,UAAU;GACR,QAAQ,QAAQ;GAChB,UAAU,KAAK;GACf,SAAS,KAAK;EAChB;EACA,SAAS,KAAK;CAChB,CAAC;CAED,QAAQ,IAAI,oBAAoB,MAAM,UAAU;CAChD,MAAM,cAAc,MAAM,eAAe,CAAC,CAAC,OAAO,UAAmB;EACnE,QAAQ,IAAI,OAAQ,MAAgB,SAAS;CAC/C,CAAC;CACD,QAAQ,IAAI,0CAA0C,MAAM,gBAAgB,EAAE;CAE9E,MAAM,MAAM,gBAAgB;CAE5B,MAAM,SAA4B;EAChC,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB,WAAW,KAAK;EAChB,SAAS,KAAK;EACd,UAAU,KAAK;EACf,2BAAU,IAAI,KAAK,EAAC,CAAC,YAAY;CACnC;CACA,oBAAoB,KAAK,YAAY,aAAa;EAAE,GAAG;EAAS,aAAa;CAAO,EAAE;CACtF,OAAO;AACT"}
|