@supatype/cli 0.1.0-alpha.9 → 0.1.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/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-test.log +285 -69
- package/.turbo/turbo-typecheck.log +1 -1
- package/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/bin/dev-entry.ts +2 -1
- package/dist/app/framework.js +1 -3
- package/dist/app/framework.js.map +1 -1
- package/dist/app/proxy-dev-app.d.ts +14 -0
- package/dist/app/proxy-dev-app.d.ts.map +1 -1
- package/dist/app/proxy-dev-app.js +110 -6
- package/dist/app/proxy-dev-app.js.map +1 -1
- package/dist/app-config.d.ts +10 -0
- package/dist/app-config.d.ts.map +1 -1
- package/dist/app-config.js +72 -0
- package/dist/app-config.js.map +1 -1
- package/dist/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/dist/binary-cache.d.ts +19 -7
- package/dist/binary-cache.d.ts.map +1 -1
- package/dist/binary-cache.js +92 -46
- package/dist/binary-cache.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.d.ts +3 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +86 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/admin.d.ts +28 -1
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +297 -149
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/adopt.d.ts +3 -0
- package/dist/commands/adopt.d.ts.map +1 -0
- package/dist/commands/adopt.js +55 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +20 -17
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/cache.d.ts.map +1 -1
- package/dist/commands/cache.js +11 -10
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/cloud.d.ts +4 -9
- package/dist/commands/cloud.d.ts.map +1 -1
- package/dist/commands/cloud.js +75 -125
- package/dist/commands/cloud.js.map +1 -1
- package/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +37 -58
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +140 -96
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +74 -39
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +39 -39
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +78 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/engine.d.ts.map +1 -1
- package/dist/commands/engine.js +5 -4
- package/dist/commands/engine.js.map +1 -1
- package/dist/commands/functions.d.ts.map +1 -1
- package/dist/commands/functions.js +172 -119
- package/dist/commands/functions.js.map +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +5 -4
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +35 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +883 -107
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/introspect.d.ts +3 -0
- package/dist/commands/introspect.d.ts.map +1 -0
- package/dist/commands/introspect.js +35 -0
- package/dist/commands/introspect.js.map +1 -0
- package/dist/commands/keys.d.ts +15 -1
- package/dist/commands/keys.d.ts.map +1 -1
- package/dist/commands/keys.js +46 -10
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/link-helpers.d.ts +15 -0
- package/dist/commands/link-helpers.d.ts.map +1 -0
- package/dist/commands/link-helpers.js +225 -0
- package/dist/commands/link-helpers.js.map +1 -0
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +5 -4
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/migrate-from-v1.d.ts.map +1 -1
- package/dist/commands/migrate-from-v1.js +3 -2
- package/dist/commands/migrate-from-v1.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +119 -26
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/pg.d.ts.map +1 -1
- package/dist/commands/pg.js +11 -12
- package/dist/commands/pg.js.map +1 -1
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +55 -46
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +33 -5
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +111 -138
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/seed.d.ts.map +1 -1
- package/dist/commands/seed.js +4 -3
- package/dist/commands/seed.js.map +1 -1
- package/dist/commands/self-host.d.ts +2 -2
- package/dist/commands/self-host.d.ts.map +1 -1
- package/dist/commands/self-host.js +65 -50
- package/dist/commands/self-host.js.map +1 -1
- package/dist/commands/self-update.d.ts.map +1 -1
- package/dist/commands/self-update.js +3 -2
- package/dist/commands/self-update.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +95 -29
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js +3 -2
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +54 -21
- package/dist/commands/update.js.map +1 -1
- package/dist/compose-rename.d.ts +10 -0
- package/dist/compose-rename.d.ts.map +1 -0
- package/dist/compose-rename.js +67 -0
- package/dist/compose-rename.js.map +1 -0
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/dev-compose.d.ts +26 -0
- package/dist/dev-compose.d.ts.map +1 -1
- package/dist/dev-compose.js +357 -79
- package/dist/dev-compose.js.map +1 -1
- package/dist/dev-log-bus.d.ts +30 -0
- package/dist/dev-log-bus.d.ts.map +1 -0
- package/dist/dev-log-bus.js +87 -0
- package/dist/dev-log-bus.js.map +1 -0
- package/dist/dev-log-filter.d.ts +10 -0
- package/dist/dev-log-filter.d.ts.map +1 -0
- package/dist/dev-log-filter.js +36 -0
- package/dist/dev-log-filter.js.map +1 -0
- package/dist/dev-logo.d.ts +12 -0
- package/dist/dev-logo.d.ts.map +1 -0
- package/dist/dev-logo.js +56 -0
- package/dist/dev-logo.js.map +1 -0
- package/dist/dev-ports.d.ts +27 -0
- package/dist/dev-ports.d.ts.map +1 -0
- package/dist/dev-ports.js +171 -0
- package/dist/dev-ports.js.map +1 -0
- package/dist/dev-session-lock.d.ts +25 -0
- package/dist/dev-session-lock.d.ts.map +1 -0
- package/dist/dev-session-lock.js +81 -0
- package/dist/dev-session-lock.js.map +1 -0
- package/dist/dev-session.d.ts +26 -0
- package/dist/dev-session.d.ts.map +1 -0
- package/dist/dev-session.js +106 -0
- package/dist/dev-session.js.map +1 -0
- package/dist/dev-shutdown.d.ts +25 -0
- package/dist/dev-shutdown.d.ts.map +1 -0
- package/dist/dev-shutdown.js +114 -0
- package/dist/dev-shutdown.js.map +1 -0
- package/dist/dev-task-colors.d.ts +13 -0
- package/dist/dev-task-colors.d.ts.map +1 -0
- package/dist/dev-task-colors.js +43 -0
- package/dist/dev-task-colors.js.map +1 -0
- package/dist/dev-tui.d.ts +24 -0
- package/dist/dev-tui.d.ts.map +1 -0
- package/dist/dev-tui.js +188 -0
- package/dist/dev-tui.js.map +1 -0
- package/dist/diff-output.d.ts +5 -1
- package/dist/diff-output.d.ts.map +1 -1
- package/dist/diff-output.js +69 -0
- package/dist/diff-output.js.map +1 -1
- package/dist/docker-runtime.d.ts +30 -0
- package/dist/docker-runtime.d.ts.map +1 -0
- package/dist/docker-runtime.js +118 -0
- package/dist/docker-runtime.js.map +1 -0
- package/dist/engine-client.d.ts +10 -1
- package/dist/engine-client.d.ts.map +1 -1
- package/dist/engine-client.js +76 -17
- package/dist/engine-client.js.map +1 -1
- package/dist/engine-push-output.d.ts +17 -0
- package/dist/engine-push-output.d.ts.map +1 -0
- package/dist/engine-push-output.js +64 -0
- package/dist/engine-push-output.js.map +1 -0
- package/dist/ensure-binary.js +2 -2
- package/dist/ensure-binary.js.map +1 -1
- package/dist/env-file.d.ts +5 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +33 -0
- package/dist/env-file.js.map +1 -0
- package/dist/gitignore.d.ts +8 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +41 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/kong-config.d.ts +9 -0
- package/dist/kong-config.d.ts.map +1 -1
- package/dist/kong-config.js +18 -1
- package/dist/kong-config.js.map +1 -1
- package/dist/link.d.ts +66 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +160 -0
- package/dist/link.js.map +1 -0
- package/dist/process-manager.d.ts +8 -0
- package/dist/process-manager.d.ts.map +1 -1
- package/dist/process-manager.js +53 -9
- package/dist/process-manager.js.map +1 -1
- package/dist/project-config.d.ts +30 -3
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +37 -4
- package/dist/project-config.js.map +1 -1
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +3 -0
- package/dist/prompts.js.map +1 -0
- package/dist/pull-utils.d.ts +50 -14
- package/dist/pull-utils.d.ts.map +1 -1
- package/dist/pull-utils.js +152 -12
- package/dist/pull-utils.js.map +1 -1
- package/dist/resolve-target.d.ts +86 -0
- package/dist/resolve-target.d.ts.map +1 -0
- package/dist/resolve-target.js +291 -0
- package/dist/resolve-target.js.map +1 -0
- package/dist/restore-system-relation-targets.d.ts +3 -0
- package/dist/restore-system-relation-targets.d.ts.map +1 -0
- package/dist/restore-system-relation-targets.js +45 -0
- package/dist/restore-system-relation-targets.js.map +1 -0
- package/dist/runtime-routes.d.ts.map +1 -1
- package/dist/runtime-routes.js +7 -0
- package/dist/runtime-routes.js.map +1 -1
- package/dist/schema-ast-v2.d.ts +1 -1
- package/dist/schema-ast-v2.d.ts.map +1 -1
- package/dist/schema-ast-v2.js +2 -2
- package/dist/schema-ast-v2.js.map +1 -1
- package/dist/schema-sources.d.ts +40 -0
- package/dist/schema-sources.d.ts.map +1 -0
- package/dist/schema-sources.js +183 -0
- package/dist/schema-sources.js.map +1 -0
- package/dist/scripts/postinstall.js +5 -1
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/self-host-compose.d.ts +37 -1
- package/dist/self-host-compose.d.ts.map +1 -1
- package/dist/self-host-compose.js +234 -43
- package/dist/self-host-compose.js.map +1 -1
- package/dist/storage-provision.d.ts +4 -0
- package/dist/storage-provision.d.ts.map +1 -1
- package/dist/storage-provision.js +24 -2
- package/dist/storage-provision.js.map +1 -1
- package/dist/supatype-eval-1781522769253.d.mts +2 -0
- package/dist/supatype-eval-1781522769253.d.mts.map +1 -0
- package/dist/supatype-eval-1781522769253.mjs +3 -0
- package/dist/supatype-eval-1781522769253.mjs.map +1 -0
- package/dist/systemd.js +2 -2
- package/dist/systemd.js.map +1 -1
- package/dist/target-client.d.ts +10 -0
- package/dist/target-client.d.ts.map +1 -0
- package/dist/target-client.js +22 -0
- package/dist/target-client.js.map +1 -0
- package/dist/type-extractor.d.ts +11 -0
- package/dist/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor.js +95 -8
- package/dist/type-extractor.js.map +1 -1
- package/dist/ui/brand.d.ts +9 -0
- package/dist/ui/brand.d.ts.map +1 -0
- package/dist/ui/brand.js +11 -0
- package/dist/ui/brand.js.map +1 -0
- package/dist/ui/confirm.d.ts +12 -0
- package/dist/ui/confirm.d.ts.map +1 -0
- package/dist/ui/confirm.js +28 -0
- package/dist/ui/confirm.js.map +1 -0
- package/dist/ui/fatal.d.ts +10 -0
- package/dist/ui/fatal.d.ts.map +1 -0
- package/dist/ui/fatal.js +34 -0
- package/dist/ui/fatal.js.map +1 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/interactive.d.ts +3 -0
- package/dist/ui/interactive.d.ts.map +1 -0
- package/dist/ui/interactive.js +5 -0
- package/dist/ui/interactive.js.map +1 -0
- package/dist/ui/messages.d.ts +10 -0
- package/dist/ui/messages.d.ts.map +1 -0
- package/dist/ui/messages.js +35 -0
- package/dist/ui/messages.js.map +1 -0
- package/dist/ui/next-steps.d.ts +3 -0
- package/dist/ui/next-steps.d.ts.map +1 -0
- package/dist/ui/next-steps.js +10 -0
- package/dist/ui/next-steps.js.map +1 -0
- package/dist/ui/progress.d.ts +5 -0
- package/dist/ui/progress.d.ts.map +1 -0
- package/dist/ui/progress.js +24 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/prompts.d.ts +14 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +34 -0
- package/dist/ui/prompts.js.map +1 -0
- package/package.json +5 -2
- package/src/app/framework.ts +1 -3
- package/src/app/proxy-dev-app.ts +114 -6
- package/src/app-config.ts +80 -0
- package/src/binary-cache.ts +102 -52
- package/src/cli.ts +16 -2
- package/src/commands/add.ts +97 -0
- package/src/commands/admin.ts +381 -190
- package/src/commands/adopt.ts +82 -0
- package/src/commands/app.ts +20 -17
- package/src/commands/cache.ts +11 -10
- package/src/commands/cloud.ts +91 -142
- package/src/commands/db.ts +40 -63
- package/src/commands/deploy.ts +186 -126
- package/src/commands/dev.ts +98 -55
- package/src/commands/diff.ts +52 -43
- package/src/commands/doctor.ts +103 -0
- package/src/commands/engine.ts +5 -4
- package/src/commands/functions.ts +187 -123
- package/src/commands/generate.ts +5 -4
- package/src/commands/init.ts +1087 -104
- package/src/commands/introspect.ts +48 -0
- package/src/commands/keys.ts +56 -14
- package/src/commands/link-helpers.ts +273 -0
- package/src/commands/logs.ts +5 -4
- package/src/commands/migrate-from-v1.ts +3 -2
- package/src/commands/migrate.ts +167 -27
- package/src/commands/pg.ts +13 -18
- package/src/commands/plugins.ts +55 -46
- package/src/commands/pull.ts +38 -9
- package/src/commands/push.ts +148 -175
- package/src/commands/seed.ts +5 -4
- package/src/commands/self-host.ts +85 -54
- package/src/commands/self-update.ts +3 -2
- package/src/commands/status.ts +102 -33
- package/src/commands/types.ts +3 -2
- package/src/commands/update.ts +59 -23
- package/src/compose-rename.ts +76 -0
- package/src/config.ts +2 -1
- package/src/dev-compose.ts +462 -76
- package/src/dev-log-bus.ts +101 -0
- package/src/dev-log-filter.ts +32 -0
- package/src/dev-logo.ts +61 -0
- package/src/dev-ports.ts +212 -0
- package/src/dev-session-lock.ts +101 -0
- package/src/dev-session.ts +130 -0
- package/src/dev-shutdown.ts +147 -0
- package/src/dev-task-colors.ts +47 -0
- package/src/dev-tui.ts +232 -0
- package/src/diff-output.ts +79 -1
- package/src/docker-runtime.ts +151 -0
- package/src/engine-client.ts +81 -17
- package/src/engine-push-output.ts +75 -0
- package/src/ensure-binary.ts +2 -2
- package/src/env-file.ts +37 -0
- package/src/gitignore.ts +48 -0
- package/src/kong-config.ts +24 -1
- package/src/link.ts +243 -0
- package/src/process-manager.ts +66 -10
- package/src/project-config.ts +62 -7
- package/src/prompts.ts +2 -0
- package/src/pull-utils.ts +217 -23
- package/src/resolve-target.ts +419 -0
- package/src/restore-system-relation-targets.ts +45 -0
- package/src/runtime-routes.ts +7 -0
- package/src/schema-ast-v2.ts +2 -1
- package/src/schema-sources.ts +248 -0
- package/src/scripts/postinstall.ts +7 -1
- package/src/self-host-compose.ts +262 -46
- package/src/storage-provision.ts +33 -1
- package/src/supatype-eval-1781522769253.mts +1 -0
- package/src/systemd.ts +2 -2
- package/src/target-client.ts +40 -0
- package/src/type-extractor.ts +124 -11
- package/src/ui/README.md +17 -0
- package/src/ui/brand.ts +12 -0
- package/src/ui/confirm.ts +38 -0
- package/src/ui/fatal.ts +43 -0
- package/src/ui/index.ts +8 -0
- package/src/ui/interactive.ts +4 -0
- package/src/ui/messages.ts +43 -0
- package/src/ui/next-steps.ts +10 -0
- package/src/ui/progress.ts +28 -0
- package/src/ui/prompts.ts +40 -0
- package/tests/admin-ensure.test.ts +59 -0
- package/tests/cli-help.test.ts +27 -2
- package/tests/config.test.ts +29 -2
- package/tests/dev-ports.test.ts +41 -0
- package/tests/dev-session-lock.test.ts +54 -0
- package/tests/dev-ui.test.ts +162 -0
- package/tests/docker-runtime.test.ts +236 -0
- package/tests/engine-push-output.test.ts +67 -0
- package/tests/init.test.ts +197 -18
- package/tests/link.test.ts +148 -0
- package/tests/minisign.test.ts +102 -0
- package/tests/proxy-dev-app.test.ts +45 -1
- package/tests/pull-utils.test.ts +5 -4
- package/tests/runtime-contract.test.ts +186 -2
- package/tests/schema-sources.test.ts +119 -0
- package/tests/storage-provision.test.ts +100 -0
- package/tests/ui-confirm.test.ts +41 -0
- package/tests/ui-messages.test.ts +66 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/commands/migrate.ts
CHANGED
|
@@ -1,11 +1,73 @@
|
|
|
1
1
|
import type { Command } from "commander"
|
|
2
|
-
import {
|
|
2
|
+
import { join } from "node:path"
|
|
3
3
|
import { loadConfig, loadSchemaAst } from "../config.js"
|
|
4
|
-
import { connectionString, schemaPathFromProject } from "../project-config.js"
|
|
4
|
+
import { connectionString, projectRootFromConfig, schemaPathFromProject } from "../project-config.js"
|
|
5
5
|
import { ensureEngine, engineRequest } from "../engine-client.js"
|
|
6
|
+
import { loadProjectLink } from "../link.js"
|
|
7
|
+
import {
|
|
8
|
+
resolveTarget,
|
|
9
|
+
targetSchemaDiff,
|
|
10
|
+
targetSchemaRollback,
|
|
11
|
+
targetListMigrations,
|
|
12
|
+
schemaPgSchema,
|
|
13
|
+
type SchemaRollbackResult,
|
|
14
|
+
} from "../resolve-target.js"
|
|
15
|
+
import {
|
|
16
|
+
restoreSchemaSourcesFromGz,
|
|
17
|
+
findOrphanSchemaFiles,
|
|
18
|
+
type SchemaSourcesManifest,
|
|
19
|
+
} from "../schema-sources.js"
|
|
20
|
+
import { confirm } from "../ui/confirm.js"
|
|
21
|
+
import { info, plain, warn } from "../ui/messages.js"
|
|
6
22
|
|
|
7
23
|
export function registerMigrate(program: Command): void {
|
|
8
|
-
|
|
24
|
+
const migrations = program
|
|
25
|
+
.command("migrations")
|
|
26
|
+
.description("Migration history utilities")
|
|
27
|
+
|
|
28
|
+
migrations
|
|
29
|
+
.command("list")
|
|
30
|
+
.description("List applied migrations with schema snapshot metadata")
|
|
31
|
+
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
32
|
+
.option("--env <name>", "Target environment when linked")
|
|
33
|
+
.option("--direct", "Use local engine subprocess (skip control plane)")
|
|
34
|
+
.action(async (opts: { connection?: string; env?: string; direct?: boolean }) => {
|
|
35
|
+
const cwd = process.cwd()
|
|
36
|
+
const link = loadProjectLink(cwd)
|
|
37
|
+
const useDirect = opts.direct || Boolean(opts.connection)
|
|
38
|
+
|
|
39
|
+
let target
|
|
40
|
+
if (link && !useDirect && !opts.connection) {
|
|
41
|
+
target = resolveTarget(cwd, { env: opts.env })
|
|
42
|
+
} else {
|
|
43
|
+
target = resolveTarget(cwd, {
|
|
44
|
+
env: opts.env,
|
|
45
|
+
direct: true,
|
|
46
|
+
connection: opts.connection,
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const list = await targetListMigrations(target)
|
|
51
|
+
if (list.length === 0) {
|
|
52
|
+
info("No migrations applied.")
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const m of list) {
|
|
57
|
+
const manifest = m.schemaSourcesManifest
|
|
58
|
+
const size =
|
|
59
|
+
manifest?.compressedBytes !== undefined
|
|
60
|
+
? `${(manifest.compressedBytes / 1024).toFixed(1)} KB`
|
|
61
|
+
: "—"
|
|
62
|
+
const files = manifest?.fileCount ?? "—"
|
|
63
|
+
const author = manifest?.pushedBy ?? "—"
|
|
64
|
+
const rolled = m.rolledBack ? " (rolled back)" : ""
|
|
65
|
+
plain(
|
|
66
|
+
`${m.name}${rolled}\n applied: ${m.appliedAt} status: ${m.status}\n author: ${author} files: ${files} snapshot: ${size}`,
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
9
71
|
program
|
|
10
72
|
.command("migrate")
|
|
11
73
|
.description("Apply pending migrations from the migration history")
|
|
@@ -20,28 +82,49 @@ export function registerMigrate(program: Command): void {
|
|
|
20
82
|
schema: "public",
|
|
21
83
|
action: "pending",
|
|
22
84
|
})
|
|
23
|
-
|
|
85
|
+
info(result.message ?? "Migrations applied.")
|
|
24
86
|
})
|
|
25
87
|
|
|
26
|
-
// rollback — undo the last applied migration
|
|
27
88
|
program
|
|
28
89
|
.command("rollback")
|
|
29
90
|
.description("Roll back the last applied migration")
|
|
30
91
|
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
|
|
92
|
+
.option("--env <name>", "Target environment when linked")
|
|
93
|
+
.option("--direct", "Use local engine subprocess (skip control plane)")
|
|
94
|
+
.option("--sync-schema", "Restore schema source files from DB snapshot without prompting")
|
|
95
|
+
.option("--no-sync-schema", "Revert database only; do not restore schema files")
|
|
96
|
+
.action(async (opts: {
|
|
97
|
+
connection?: string
|
|
98
|
+
env?: string
|
|
99
|
+
direct?: boolean
|
|
100
|
+
syncSchema?: boolean
|
|
101
|
+
noSyncSchema?: boolean
|
|
102
|
+
}) => {
|
|
103
|
+
const cwd = process.cwd()
|
|
104
|
+
const config = loadConfig(cwd)
|
|
105
|
+
const pgSchema = schemaPgSchema(cwd)
|
|
106
|
+
const link = loadProjectLink(cwd)
|
|
107
|
+
const useDirect = opts.direct || Boolean(opts.connection)
|
|
34
108
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
109
|
+
let target
|
|
110
|
+
if (link && !useDirect && !opts.connection) {
|
|
111
|
+
target = resolveTarget(cwd, { env: opts.env })
|
|
112
|
+
} else {
|
|
113
|
+
target = resolveTarget(cwd, {
|
|
114
|
+
env: opts.env,
|
|
115
|
+
direct: true,
|
|
116
|
+
connection: opts.connection,
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const result = await targetSchemaRollback(target, { schema: pgSchema })
|
|
121
|
+
info(result.message ?? "Rolled back.")
|
|
122
|
+
|
|
123
|
+
if (!opts.noSyncSchema) {
|
|
124
|
+
await offerSchemaRestore(cwd, config, target, result, pgSchema, opts.syncSchema ?? false)
|
|
125
|
+
}
|
|
42
126
|
})
|
|
43
127
|
|
|
44
|
-
// reset — drop all tables and re-apply from scratch
|
|
45
128
|
program
|
|
46
129
|
.command("reset")
|
|
47
130
|
.description(
|
|
@@ -52,10 +135,11 @@ export function registerMigrate(program: Command): void {
|
|
|
52
135
|
.action(async (opts: { yes?: boolean; connection?: string }) => {
|
|
53
136
|
if (!opts.yes) {
|
|
54
137
|
const confirmed = await confirm(
|
|
55
|
-
"This will DROP all managed tables and re-apply the schema. Proceed?
|
|
138
|
+
"This will DROP all managed tables and re-apply the schema. Proceed?",
|
|
139
|
+
{ default: false },
|
|
56
140
|
)
|
|
57
141
|
if (!confirmed) {
|
|
58
|
-
|
|
142
|
+
plain("Aborted.")
|
|
59
143
|
return
|
|
60
144
|
}
|
|
61
145
|
}
|
|
@@ -72,16 +156,72 @@ export function registerMigrate(program: Command): void {
|
|
|
72
156
|
schema: "public",
|
|
73
157
|
force: true,
|
|
74
158
|
})
|
|
75
|
-
|
|
159
|
+
info(result.message ?? "Reset complete.")
|
|
76
160
|
})
|
|
77
161
|
}
|
|
78
162
|
|
|
79
|
-
async function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
163
|
+
async function offerSchemaRestore(
|
|
164
|
+
cwd: string,
|
|
165
|
+
config: ReturnType<typeof loadConfig>,
|
|
166
|
+
target: ReturnType<typeof resolveTarget>,
|
|
167
|
+
result: SchemaRollbackResult,
|
|
168
|
+
pgSchema: string,
|
|
169
|
+
autoSync: boolean,
|
|
170
|
+
): Promise<void> {
|
|
171
|
+
const manifest = result.schemaSourcesManifest as SchemaSourcesManifest | undefined
|
|
172
|
+
const gzB64 = result.schemaSourcesBase64
|
|
173
|
+
|
|
174
|
+
if (!gzB64 || !manifest) {
|
|
175
|
+
warn(
|
|
176
|
+
"No schema source snapshot on the restored migration (legacy push). Run `supatype pull` to draft from DB if needed.",
|
|
177
|
+
)
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const ast = loadSchemaAst(schemaPathFromProject(config, cwd), cwd)
|
|
182
|
+
const diff = await targetSchemaDiff(target, ast, { schema: pgSchema })
|
|
183
|
+
const drift = (diff.operations ?? []).length > 0
|
|
184
|
+
|
|
185
|
+
if (!drift && !autoSync) {
|
|
186
|
+
info("Schema files match reverted database (no restore needed).")
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const fileList = manifest.files.map((f) => f.path).join(", ")
|
|
191
|
+
const sizeKb = (manifest.compressedBytes / 1024).toFixed(1)
|
|
192
|
+
const label = result.restoredMigrationName ?? result.name
|
|
193
|
+
|
|
194
|
+
let proceed = autoSync
|
|
195
|
+
if (!proceed) {
|
|
196
|
+
proceed = await confirm(
|
|
197
|
+
`Restore ${manifest.fileCount} schema files from database snapshot (${sizeKb} KB)?\n ${fileList}`,
|
|
198
|
+
{ default: true },
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!proceed) {
|
|
203
|
+
info("Skipped schema file restore. Run `supatype diff` to review drift.")
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const root = projectRootFromConfig(config, cwd)
|
|
208
|
+
const backupDir = join(cwd, ".supatype", "schema-backups", `${Date.now()}`)
|
|
209
|
+
const gz = Buffer.from(gzB64, "base64")
|
|
210
|
+
restoreSchemaSourcesFromGz(gz, manifest, root, { backupDir })
|
|
211
|
+
|
|
212
|
+
const manifestPaths = new Set(manifest.files.map((f) => f.path))
|
|
213
|
+
const orphans = findOrphanSchemaFiles(root, manifest.entryPoint, manifestPaths)
|
|
214
|
+
for (const orphan of orphans) {
|
|
215
|
+
warn(`${orphan} not in snapshot — review manually`)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
info(`Restored schema files from migration ${label}.`)
|
|
219
|
+
info(`Backup saved to ${backupDir}`)
|
|
220
|
+
|
|
221
|
+
const postDiff = await targetSchemaDiff(target, ast, { schema: pgSchema })
|
|
222
|
+
if ((postDiff.operations ?? []).length === 0) {
|
|
223
|
+
info("Schema matches database after restore.")
|
|
224
|
+
} else {
|
|
225
|
+
info("Run `supatype diff` — schema may still differ from database.")
|
|
226
|
+
}
|
|
87
227
|
}
|
package/src/commands/pg.ts
CHANGED
|
@@ -11,6 +11,8 @@ import { homedir } from "node:os"
|
|
|
11
11
|
import { join } from "node:path"
|
|
12
12
|
import { loadConfig } from "../config.js"
|
|
13
13
|
import { resolveBinary } from "../binary-cache.js"
|
|
14
|
+
import { confirm } from "../ui/confirm.js"
|
|
15
|
+
import { info, plain } from "../ui/messages.js"
|
|
14
16
|
import {
|
|
15
17
|
initdb,
|
|
16
18
|
start as pgStart,
|
|
@@ -32,9 +34,7 @@ export function registerPg(program: Command): void {
|
|
|
32
34
|
initdb(opts)
|
|
33
35
|
pgStart(opts)
|
|
34
36
|
await waitReady(opts, 10_000)
|
|
35
|
-
|
|
36
|
-
`[supatype] Postgres started on port ${opts.port} (data: ${opts.dataDir})`,
|
|
37
|
-
)
|
|
37
|
+
info(`Postgres started on port ${opts.port} (data: ${opts.dataDir})`)
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
// ── stop ─────────────────────────────────────────────────────────────────
|
|
@@ -44,7 +44,7 @@ export function registerPg(program: Command): void {
|
|
|
44
44
|
const config = loadConfig()
|
|
45
45
|
const opts = await pgOpts(config)
|
|
46
46
|
pgStop(opts)
|
|
47
|
-
|
|
47
|
+
info("Postgres stopped.")
|
|
48
48
|
})
|
|
49
49
|
|
|
50
50
|
// ── reset ─────────────────────────────────────────────────────────────────
|
|
@@ -56,17 +56,12 @@ export function registerPg(program: Command): void {
|
|
|
56
56
|
const pgOpts_ = await pgOpts(config)
|
|
57
57
|
|
|
58
58
|
if (!opts.force) {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
rl.question(
|
|
63
|
-
`This will DELETE all data in ${pgOpts_.dataDir}. Continue? [y/N] `,
|
|
64
|
-
resolve,
|
|
65
|
-
),
|
|
59
|
+
const ok = await confirm(
|
|
60
|
+
`This will DELETE all data in ${pgOpts_.dataDir}. Continue?`,
|
|
61
|
+
{ default: false },
|
|
66
62
|
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
console.log("Aborted.")
|
|
63
|
+
if (!ok) {
|
|
64
|
+
plain("Aborted.")
|
|
70
65
|
return
|
|
71
66
|
}
|
|
72
67
|
}
|
|
@@ -74,13 +69,13 @@ export function registerPg(program: Command): void {
|
|
|
74
69
|
pgStop(pgOpts_)
|
|
75
70
|
if (existsSync(pgOpts_.dataDir)) {
|
|
76
71
|
rmSync(pgOpts_.dataDir, { recursive: true, force: true })
|
|
77
|
-
|
|
72
|
+
info(`Data directory removed: ${pgOpts_.dataDir}`)
|
|
78
73
|
}
|
|
79
74
|
mkdirSync(pgOpts_.dataDir, { recursive: true })
|
|
80
75
|
initdb(pgOpts_)
|
|
81
76
|
pgStart(pgOpts_)
|
|
82
77
|
await waitReady(pgOpts_, 10_000)
|
|
83
|
-
|
|
78
|
+
info("Postgres reset and started.")
|
|
84
79
|
})
|
|
85
80
|
|
|
86
81
|
// ── psql ─────────────────────────────────────────────────────────────────
|
|
@@ -118,9 +113,9 @@ async function pgOpts(
|
|
|
118
113
|
const pgCacheDir = await (async () => {
|
|
119
114
|
const override = config.overrides?.postgres_dir
|
|
120
115
|
if (override) return join(override, "bin")
|
|
121
|
-
const { cachePath, currentPlatform } = await import("../binary-cache.js")
|
|
116
|
+
const { cachePath, currentPlatform, resolveVersionFor } = await import("../binary-cache.js")
|
|
122
117
|
const platform = currentPlatform()
|
|
123
|
-
const version = config
|
|
118
|
+
const version = await resolveVersionFor("postgres", config)
|
|
124
119
|
return join(cachePath("postgres", version), `pg-${version}`, "bin")
|
|
125
120
|
})()
|
|
126
121
|
|
package/src/commands/plugins.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { Command } from "commander"
|
|
|
2
2
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from "node:fs"
|
|
3
3
|
import { resolve, join } from "node:path"
|
|
4
4
|
import { spawnSync } from "node:child_process"
|
|
5
|
+
import { error, info, plain, warn } from "../ui/messages.js"
|
|
6
|
+
import { nextSteps } from "../ui/next-steps.js"
|
|
5
7
|
|
|
6
8
|
// ─── Registration ────────────────────────────────────────────────────────────
|
|
7
9
|
|
|
@@ -61,27 +63,30 @@ function listPlugins(cwd: string): void {
|
|
|
61
63
|
const plugins = discoverInstalledPlugins(cwd)
|
|
62
64
|
|
|
63
65
|
if (plugins.length === 0) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
info("No Supatype plugins installed.")
|
|
67
|
+
nextSteps("Try:", [
|
|
68
|
+
"Search for plugins: npx supatype plugins search <query>",
|
|
69
|
+
"Create a plugin: npx supatype plugins create",
|
|
70
|
+
])
|
|
67
71
|
return
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
plain("Installed plugins:\n")
|
|
75
|
+
plain(` ${"Name".padEnd(35)} ${"Type".padEnd(14)} ${"Version".padEnd(12)} Status`)
|
|
76
|
+
plain(` ${"─".repeat(35)} ${"─".repeat(14)} ${"─".repeat(12)} ${"─".repeat(15)}`)
|
|
73
77
|
|
|
74
78
|
for (const p of plugins) {
|
|
75
79
|
const types = p.supatype?.types?.join(", ") ?? "unknown"
|
|
76
80
|
const status = p.compatible ? "active" : "incompatible"
|
|
77
|
-
|
|
81
|
+
plain(` ${p.name.padEnd(35)} ${types.padEnd(14)} ${p.version.padEnd(12)} ${status}`)
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
// ─── Search ──────────────────────────────────────────────────────────────────
|
|
82
86
|
|
|
83
87
|
async function searchPlugins(query: string): Promise<void> {
|
|
84
|
-
|
|
88
|
+
info(`Searching npm for "${query}" supatype plugins...`)
|
|
89
|
+
plain()
|
|
85
90
|
|
|
86
91
|
try {
|
|
87
92
|
const searchUrl = `https://registry.npmjs.org/-/v1/search?text=supatype-plugin+${encodeURIComponent(query)}&size=20`
|
|
@@ -90,7 +95,7 @@ async function searchPlugins(query: string): Promise<void> {
|
|
|
90
95
|
})
|
|
91
96
|
|
|
92
97
|
if (!res.ok) {
|
|
93
|
-
|
|
98
|
+
error(`Search failed: ${res.statusText}`)
|
|
94
99
|
return
|
|
95
100
|
}
|
|
96
101
|
|
|
@@ -107,31 +112,33 @@ async function searchPlugins(query: string): Promise<void> {
|
|
|
107
112
|
}
|
|
108
113
|
|
|
109
114
|
if (data.objects.length === 0) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
info("No plugins found.")
|
|
116
|
+
nextSteps("Try:", [
|
|
117
|
+
"Try a different search term, or create your own plugin:",
|
|
118
|
+
" npx supatype plugins create",
|
|
119
|
+
])
|
|
113
120
|
return
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
plain(` ${"Package".padEnd(40)} ${"Version".padEnd(12)} Description`)
|
|
124
|
+
plain(` ${"─".repeat(40)} ${"─".repeat(12)} ${"─".repeat(40)}`)
|
|
118
125
|
|
|
119
126
|
for (const obj of data.objects) {
|
|
120
127
|
const pkg = obj.package
|
|
121
128
|
const desc = (pkg.description ?? "").slice(0, 50)
|
|
122
|
-
|
|
129
|
+
plain(` ${pkg.name.padEnd(40)} ${pkg.version.padEnd(12)} ${desc}`)
|
|
123
130
|
}
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
info("Install: npx supatype plugins add <package-name>")
|
|
126
133
|
} catch (err) {
|
|
127
|
-
|
|
134
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
128
135
|
}
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
// ─── Add ─────────────────────────────────────────────────────────────────────
|
|
132
139
|
|
|
133
140
|
function addPlugin(cwd: string, pkg: string): void {
|
|
134
|
-
|
|
141
|
+
info(`Installing ${pkg}...`)
|
|
135
142
|
|
|
136
143
|
// Detect package manager
|
|
137
144
|
const pm = detectPackageManager(cwd)
|
|
@@ -145,7 +152,7 @@ function addPlugin(cwd: string, pkg: string): void {
|
|
|
145
152
|
})
|
|
146
153
|
|
|
147
154
|
if (result.status !== 0) {
|
|
148
|
-
|
|
155
|
+
error(`Failed to install ${pkg}`)
|
|
149
156
|
process.exit(1)
|
|
150
157
|
}
|
|
151
158
|
|
|
@@ -158,14 +165,14 @@ function addPlugin(cwd: string, pkg: string): void {
|
|
|
158
165
|
if (supatype?.["pluginApi"] !== undefined) {
|
|
159
166
|
const pluginApi = supatype["pluginApi"] as number
|
|
160
167
|
if (pluginApi !== 1) {
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
warn(`${pkg} targets plugin API v${pluginApi}, current is v1.`)
|
|
169
|
+
warn("The plugin may not work correctly.")
|
|
163
170
|
}
|
|
164
171
|
}
|
|
165
172
|
}
|
|
166
173
|
|
|
167
|
-
|
|
168
|
-
|
|
174
|
+
info(`${pkg} installed and registered.`)
|
|
175
|
+
info("Run 'npx supatype plugins list' to see active plugins.")
|
|
169
176
|
}
|
|
170
177
|
|
|
171
178
|
// ─── Remove ──────────────────────────────────────────────────────────────────
|
|
@@ -177,12 +184,13 @@ function removePlugin(cwd: string, pkg: string): void {
|
|
|
177
184
|
for (const file of schemaFiles) {
|
|
178
185
|
const content = readFileSync(file, "utf8")
|
|
179
186
|
if (content.includes(pkg)) {
|
|
180
|
-
|
|
181
|
-
|
|
187
|
+
warn(`${pkg} appears to be referenced in ${file}`)
|
|
188
|
+
warn("Removing it may break your schema. Proceed with caution.")
|
|
189
|
+
plain()
|
|
182
190
|
}
|
|
183
191
|
}
|
|
184
192
|
|
|
185
|
-
|
|
193
|
+
info(`Removing ${pkg}...`)
|
|
186
194
|
|
|
187
195
|
const pm = detectPackageManager(cwd)
|
|
188
196
|
const removeCmd = pm === "pnpm" ? ["pnpm", "remove", pkg]
|
|
@@ -195,11 +203,11 @@ function removePlugin(cwd: string, pkg: string): void {
|
|
|
195
203
|
})
|
|
196
204
|
|
|
197
205
|
if (result.status !== 0) {
|
|
198
|
-
|
|
206
|
+
error(`Failed to remove ${pkg}`)
|
|
199
207
|
process.exit(1)
|
|
200
208
|
}
|
|
201
209
|
|
|
202
|
-
|
|
210
|
+
info(`${pkg} removed.`)
|
|
203
211
|
}
|
|
204
212
|
|
|
205
213
|
// ─── Create ──────────────────────────────────────────────────────────────────
|
|
@@ -207,7 +215,7 @@ function removePlugin(cwd: string, pkg: string): void {
|
|
|
207
215
|
function createPlugin(cwd: string, opts: { type: string; name?: string }): void {
|
|
208
216
|
const validTypes = ["field", "composite", "provider", "widget"]
|
|
209
217
|
if (!validTypes.includes(opts.type)) {
|
|
210
|
-
|
|
218
|
+
error(`Invalid plugin type "${opts.type}". Must be one of: ${validTypes.join(", ")}`)
|
|
211
219
|
process.exit(1)
|
|
212
220
|
}
|
|
213
221
|
|
|
@@ -215,7 +223,7 @@ function createPlugin(cwd: string, opts: { type: string; name?: string }): void
|
|
|
215
223
|
const pluginDir = resolve(cwd, name)
|
|
216
224
|
|
|
217
225
|
if (existsSync(pluginDir)) {
|
|
218
|
-
|
|
226
|
+
error(`Directory "${name}" already exists.`)
|
|
219
227
|
process.exit(1)
|
|
220
228
|
}
|
|
221
229
|
|
|
@@ -273,16 +281,17 @@ function createPlugin(cwd: string, opts: { type: string; name?: string }): void
|
|
|
273
281
|
const sourceContent = generatePluginTemplate(opts.type, name)
|
|
274
282
|
writeFileSync(join(pluginDir, "src/index.ts"), sourceContent, "utf8")
|
|
275
283
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
info(`Created plugin project: ${name}/`)
|
|
285
|
+
plain("\n Files:")
|
|
286
|
+
plain(` ${name}/package.json`)
|
|
287
|
+
plain(` ${name}/tsconfig.json`)
|
|
288
|
+
plain(` ${name}/src/index.ts`)
|
|
289
|
+
nextSteps("Next steps:", [
|
|
290
|
+
`cd ${name}`,
|
|
291
|
+
"npm install",
|
|
292
|
+
"npm run build",
|
|
293
|
+
"npx supatype plugins validate",
|
|
294
|
+
])
|
|
286
295
|
}
|
|
287
296
|
|
|
288
297
|
function generatePluginTemplate(type: string, name: string): string {
|
|
@@ -375,7 +384,7 @@ function validatePlugins(cwd: string): void {
|
|
|
375
384
|
const plugins = discoverInstalledPlugins(cwd)
|
|
376
385
|
|
|
377
386
|
if (plugins.length === 0) {
|
|
378
|
-
|
|
387
|
+
info("No plugins to validate.")
|
|
379
388
|
return
|
|
380
389
|
}
|
|
381
390
|
|
|
@@ -398,21 +407,21 @@ function validatePlugins(cwd: string): void {
|
|
|
398
407
|
}
|
|
399
408
|
|
|
400
409
|
if (issues.length === 0) {
|
|
401
|
-
|
|
410
|
+
plain(` ✓ ${p.name} — valid`)
|
|
402
411
|
} else {
|
|
403
412
|
hasErrors = true
|
|
404
|
-
|
|
413
|
+
plain(` ✗ ${p.name}`)
|
|
405
414
|
for (const issue of issues) {
|
|
406
|
-
|
|
415
|
+
plain(` - ${issue}`)
|
|
407
416
|
}
|
|
408
417
|
}
|
|
409
418
|
}
|
|
410
419
|
|
|
411
420
|
if (hasErrors) {
|
|
412
|
-
|
|
421
|
+
error("Some plugins have issues. Fix them before deploying.")
|
|
413
422
|
process.exit(1)
|
|
414
423
|
} else {
|
|
415
|
-
|
|
424
|
+
info("All plugins are valid.")
|
|
416
425
|
}
|
|
417
426
|
}
|
|
418
427
|
|
package/src/commands/pull.ts
CHANGED
|
@@ -1,17 +1,46 @@
|
|
|
1
1
|
import type { Command } from "commander"
|
|
2
|
-
import {
|
|
2
|
+
import { writeFileSync } from "node:fs"
|
|
3
|
+
import { loadConfig } from "../config.js"
|
|
4
|
+
import { schemaPathFromProject } from "../project-config.js"
|
|
5
|
+
import { ensureEngine, engineRequest } from "../engine-client.js"
|
|
6
|
+
import { resolveHostEngineDatabaseUrl } from "../dev-compose.js"
|
|
7
|
+
import { databaseStateToSchemaScaffold, type DatabaseStateJson } from "../pull-utils.js"
|
|
8
|
+
import { info, plain } from "../ui/messages.js"
|
|
3
9
|
|
|
4
10
|
export function registerPull(program: Command): void {
|
|
5
11
|
program
|
|
6
12
|
.command("pull")
|
|
7
|
-
.description(
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
-
.
|
|
13
|
+
.description("Scaffold schema/index.ts from live database introspection (draft — review before push)")
|
|
14
|
+
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
15
|
+
.option("--out <path>", "Write scaffold to file (default: stdout)")
|
|
16
|
+
.option("--dry-run", "Print scaffold to stdout without writing files")
|
|
17
|
+
.action(async (opts: { connection?: string; out?: string; dryRun?: boolean }) => {
|
|
18
|
+
const cwd = process.cwd()
|
|
19
|
+
const config = loadConfig(cwd)
|
|
20
|
+
const connection = await resolveHostEngineDatabaseUrl(cwd, config, opts.connection)
|
|
21
|
+
const pgSchema = config.schema?.pg_schema ?? "public"
|
|
22
|
+
|
|
11
23
|
await ensureEngine()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
|
|
25
|
+
info("Introspecting database...")
|
|
26
|
+
const state = await engineRequest<DatabaseStateJson>("/introspect", {
|
|
27
|
+
database_url: connection,
|
|
28
|
+
schema: pgSchema,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const scaffold = databaseStateToSchemaScaffold(state)
|
|
32
|
+
const defaultOut = schemaPathFromProject(config, cwd)
|
|
33
|
+
|
|
34
|
+
if (opts.dryRun || !opts.out) {
|
|
35
|
+
plain(scaffold)
|
|
36
|
+
if (!opts.dryRun && !opts.out) {
|
|
37
|
+
info("(draft printed to stdout — use --out to write a file)")
|
|
38
|
+
}
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
writeFileSync(opts.out ?? defaultOut, scaffold, "utf8")
|
|
43
|
+
info(`Wrote draft schema to ${opts.out ?? defaultOut}`)
|
|
44
|
+
info("Review access rules and relations, then run `supatype generate`.")
|
|
16
45
|
})
|
|
17
46
|
}
|