@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/engine-client.ts
CHANGED
|
@@ -13,21 +13,25 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, readdirSync } from "n
|
|
|
13
13
|
import { tmpdir, homedir } from "node:os"
|
|
14
14
|
import { join } from "node:path"
|
|
15
15
|
import { loadConfig } from "./config.js"
|
|
16
|
-
import {
|
|
16
|
+
import { currentPlatform, cachePath } from "./binary-cache.js"
|
|
17
|
+
import { ensureBinary } from "./ensure-binary.js"
|
|
17
18
|
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// Types (kept for backward compatibility with existing callers)
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
21
22
|
|
|
22
23
|
export interface Operation {
|
|
23
|
-
kind: "create_table" | "alter_table" | "drop_table" | "create_index" | "drop_index" |
|
|
24
|
-
"create_policy" | "drop_policy" | "add_column" | "drop_column" | "alter_column" |
|
|
25
|
-
"recreate_column"
|
|
26
24
|
type?: string
|
|
25
|
+
kind?: string
|
|
27
26
|
description?: string
|
|
28
27
|
risk?: "safe" | "warn" | "danger" | "cautious" | "destructive"
|
|
29
28
|
warning?: string
|
|
30
29
|
sql?: string
|
|
30
|
+
table?: string
|
|
31
|
+
column?: string
|
|
32
|
+
constraint?: string
|
|
33
|
+
index_name?: string
|
|
34
|
+
index?: { fields?: string[]; name?: string; unique?: boolean }
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
export interface DiffResult {
|
|
@@ -83,10 +87,16 @@ async function getEngineBin(): Promise<string> {
|
|
|
83
87
|
|
|
84
88
|
try {
|
|
85
89
|
const config = loadConfig(cwd)
|
|
86
|
-
|
|
90
|
+
// Download-on-miss (with retry) so a fresh machine or a failed postinstall
|
|
91
|
+
// self-heals on first use instead of silently skipping type/admin refresh.
|
|
92
|
+
_engineBin = await ensureBinary("engine", config)
|
|
87
93
|
return _engineBin
|
|
88
|
-
} catch {
|
|
89
|
-
//
|
|
94
|
+
} catch (err) {
|
|
95
|
+
// A real download/verification failure must surface, not fall back to a
|
|
96
|
+
// possibly-stale cached binary from a different version.
|
|
97
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
98
|
+
if (message.includes("Failed to download")) throw err
|
|
99
|
+
// Otherwise (no valid project config) fall through to default cache scan.
|
|
90
100
|
}
|
|
91
101
|
|
|
92
102
|
// No config found — scan the cache for any available engine binary.
|
|
@@ -146,24 +156,40 @@ export async function engineRequest<T = unknown>(
|
|
|
146
156
|
): Promise<T> {
|
|
147
157
|
const bin = await getEngineBin()
|
|
148
158
|
|
|
149
|
-
// Write request to a temp file.
|
|
150
|
-
// For CLI-mode endpoints the engine reads the input file as a raw SchemaAst,
|
|
151
|
-
// so we extract the `ast` field when present, otherwise write the full body.
|
|
152
159
|
const tmpDir = join(tmpdir(), "supatype-engine")
|
|
153
160
|
mkdirSync(tmpDir, { recursive: true })
|
|
161
|
+
const cleanup: string[] = []
|
|
154
162
|
const reqFile = join(tmpDir, `req-${Date.now()}.json`)
|
|
155
163
|
const inputPayload = body["ast"] !== undefined ? body["ast"] : body
|
|
156
164
|
writeFileSync(reqFile, JSON.stringify(inputPayload))
|
|
165
|
+
cleanup.push(reqFile)
|
|
166
|
+
|
|
167
|
+
let gzPath: string | undefined
|
|
168
|
+
let manifestPath: string | undefined
|
|
169
|
+
if (typeof body["schema_sources_gz_base64"] === "string") {
|
|
170
|
+
gzPath = join(tmpDir, `sources-${Date.now()}.gz`)
|
|
171
|
+
writeFileSync(gzPath, Buffer.from(body["schema_sources_gz_base64"], "base64"))
|
|
172
|
+
cleanup.push(gzPath)
|
|
173
|
+
}
|
|
174
|
+
if (body["schema_sources_manifest"] !== undefined) {
|
|
175
|
+
manifestPath = join(tmpDir, `manifest-${Date.now()}.json`)
|
|
176
|
+
writeFileSync(manifestPath, JSON.stringify(body["schema_sources_manifest"]))
|
|
177
|
+
cleanup.push(manifestPath)
|
|
178
|
+
}
|
|
157
179
|
|
|
158
|
-
const args = endpointToArgs(endpoint, body, reqFile
|
|
180
|
+
const args = endpointToArgs(endpoint, body, reqFile, {
|
|
181
|
+
...(gzPath !== undefined ? { gzPath } : {}),
|
|
182
|
+
...(manifestPath !== undefined ? { manifestPath } : {}),
|
|
183
|
+
})
|
|
159
184
|
|
|
160
185
|
const result = spawnSync(bin, args, {
|
|
161
186
|
encoding: "utf8",
|
|
162
187
|
cwd: process.cwd(),
|
|
163
188
|
})
|
|
164
189
|
|
|
165
|
-
|
|
166
|
-
|
|
190
|
+
for (const f of cleanup) {
|
|
191
|
+
try { unlinkSync(f) } catch { /* ignore */ }
|
|
192
|
+
}
|
|
167
193
|
|
|
168
194
|
if (result.status !== 0) {
|
|
169
195
|
const stderr = result.stderr?.trim() || "(no output)"
|
|
@@ -195,6 +221,7 @@ function endpointToArgs(
|
|
|
195
221
|
endpoint: string,
|
|
196
222
|
body: Record<string, unknown>,
|
|
197
223
|
reqFile: string,
|
|
224
|
+
sources?: { gzPath?: string; manifestPath?: string },
|
|
198
225
|
): string[] {
|
|
199
226
|
const dbUrl = (body["database_url"] as string | undefined) ?? ""
|
|
200
227
|
const schema = (body["schema"] as string | undefined) ?? "public"
|
|
@@ -206,8 +233,26 @@ function endpointToArgs(
|
|
|
206
233
|
case "/diff":
|
|
207
234
|
return ["diff", "--input", reqFile, "--database-url", dbUrl, "--schema", schema]
|
|
208
235
|
|
|
209
|
-
case "/push":
|
|
210
|
-
|
|
236
|
+
case "/push": {
|
|
237
|
+
const sourceArgs: string[] = []
|
|
238
|
+
if (sources?.gzPath) sourceArgs.push("--schema-sources-gz", sources.gzPath)
|
|
239
|
+
if (sources?.manifestPath) sourceArgs.push("--schema-sources-manifest", sources.manifestPath)
|
|
240
|
+
return [
|
|
241
|
+
"push",
|
|
242
|
+
"--input",
|
|
243
|
+
reqFile,
|
|
244
|
+
"--database-url",
|
|
245
|
+
dbUrl,
|
|
246
|
+
"--schema",
|
|
247
|
+
schema,
|
|
248
|
+
...force,
|
|
249
|
+
...nonInteractive,
|
|
250
|
+
...sourceArgs,
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
case "/rollback":
|
|
255
|
+
return ["rollback", "--database-url", dbUrl, "--schema", schema]
|
|
211
256
|
|
|
212
257
|
case "/parse":
|
|
213
258
|
return ["parse", "--input", reqFile]
|
|
@@ -220,6 +265,18 @@ function endpointToArgs(
|
|
|
220
265
|
case "/introspect":
|
|
221
266
|
return ["introspect", "--database-url", dbUrl, "--schema", schema]
|
|
222
267
|
|
|
268
|
+
case "/doctor": {
|
|
269
|
+
const strict = body["strict"] ? ["--strict"] : []
|
|
270
|
+
const noCache = body["no_cache"] ? ["--no-cache"] : []
|
|
271
|
+
return ["doctor", "--input", reqFile, "--database-url", dbUrl, "--schema", schema, ...strict, ...noCache]
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
case "/adopt": {
|
|
275
|
+
const yes = body["yes"] ? ["--yes"] : []
|
|
276
|
+
const noCache = body["no_cache"] ? ["--no-cache"] : []
|
|
277
|
+
return ["adopt", "--input", reqFile, "--database-url", dbUrl, "--schema", schema, ...yes, ...noCache]
|
|
278
|
+
}
|
|
279
|
+
|
|
223
280
|
case "/validate":
|
|
224
281
|
return ["validate", "--input", reqFile]
|
|
225
282
|
|
|
@@ -227,9 +284,16 @@ function endpointToArgs(
|
|
|
227
284
|
return ["admin", "--input", reqFile]
|
|
228
285
|
|
|
229
286
|
default:
|
|
230
|
-
if (endpoint.startsWith("/migrations")) {
|
|
287
|
+
if (endpoint === "/migrations" || endpoint.startsWith("/migrations")) {
|
|
231
288
|
const action = (body["action"] as string | undefined) ?? "list"
|
|
232
|
-
|
|
289
|
+
if (action === "rollback") {
|
|
290
|
+
return ["rollback", "--database-url", dbUrl, "--schema", schema]
|
|
291
|
+
}
|
|
292
|
+
const name = body["name"] as string | undefined
|
|
293
|
+
if (name) {
|
|
294
|
+
return ["migrations", "--database-url", dbUrl, "--name", name]
|
|
295
|
+
}
|
|
296
|
+
return ["migrations", "--database-url", dbUrl]
|
|
233
297
|
}
|
|
234
298
|
return [endpoint.replace(/^\//, ""), "--input", reqFile]
|
|
235
299
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse and format schema-engine push output (compose subprocess or HTTP).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface EnginePushResult {
|
|
6
|
+
status?: string
|
|
7
|
+
operations?: number
|
|
8
|
+
admin_refreshed?: boolean
|
|
9
|
+
message?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Extract the engine JSON object from mixed docker compose stdout/stderr. */
|
|
13
|
+
export function parseEngineJsonOutput<T>(output: string): T | null {
|
|
14
|
+
const trimmed = output.trim()
|
|
15
|
+
if (!trimmed) return null
|
|
16
|
+
|
|
17
|
+
for (const line of trimmed.split(/\r?\n/)) {
|
|
18
|
+
const candidate = line.trim()
|
|
19
|
+
if (!candidate.startsWith("{") || !candidate.endsWith("}")) continue
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(candidate) as T
|
|
22
|
+
} catch {
|
|
23
|
+
/* try next line */
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (trimmed.startsWith("{")) {
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(trimmed) as T
|
|
30
|
+
} catch {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function parseEnginePushOutput(output: string): EnginePushResult | null {
|
|
39
|
+
return parseEngineJsonOutput<EnginePushResult>(output)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Human-readable one-liner for successful push (matches `supatype push` tone). */
|
|
43
|
+
export function formatEnginePushMessage(result: EnginePushResult): string {
|
|
44
|
+
if (result.status === "up_to_date") {
|
|
45
|
+
if (result.admin_refreshed) {
|
|
46
|
+
return "Schema up to date — Studio metadata synced."
|
|
47
|
+
}
|
|
48
|
+
return "Schema up to date."
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const ops = result.operations
|
|
52
|
+
if (typeof ops === "number" && ops > 0) {
|
|
53
|
+
return `Applied ${ops} operation(s).`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result.message?.trim() || "Schema applied."
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const COMPOSE_PROGRESS_LINE =
|
|
60
|
+
/^Container\s+.+\s+(Running|Waiting|Healthy|Created|Starting|Started|Exited|Stopped)\s*$/i
|
|
61
|
+
|
|
62
|
+
/** Drop docker compose progress noise; keep engine JSON and real errors. */
|
|
63
|
+
export function filterComposeNoise(output: string): string {
|
|
64
|
+
return output
|
|
65
|
+
.split(/\r?\n/)
|
|
66
|
+
.map((line) => line.trimEnd())
|
|
67
|
+
.filter((line) => {
|
|
68
|
+
const t = line.trim()
|
|
69
|
+
if (!t) return false
|
|
70
|
+
if (COMPOSE_PROGRESS_LINE.test(t)) return false
|
|
71
|
+
return true
|
|
72
|
+
})
|
|
73
|
+
.join("\n")
|
|
74
|
+
.trim()
|
|
75
|
+
}
|
package/src/ensure-binary.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
resolveBinary,
|
|
7
7
|
download,
|
|
8
8
|
currentPlatform,
|
|
9
|
-
|
|
9
|
+
resolveVersionFor,
|
|
10
10
|
type Component,
|
|
11
11
|
} from "./binary-cache.js"
|
|
12
12
|
import type { SupatypeProjectConfig } from "./project-config.js"
|
|
@@ -24,5 +24,5 @@ export async function ensureBinary(
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
return download(component,
|
|
27
|
+
return download(component, await resolveVersionFor(component, config), currentPlatform())
|
|
28
28
|
}
|
package/src/env-file.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { join } from "node:path"
|
|
3
|
+
|
|
4
|
+
/** Merge key/value updates into a project `.env` without dropping unrelated lines. */
|
|
5
|
+
export function upsertEnvFile(
|
|
6
|
+
cwd: string,
|
|
7
|
+
updates: Record<string, string>,
|
|
8
|
+
removeKeys: readonly string[] = [],
|
|
9
|
+
): void {
|
|
10
|
+
const envPath = join(cwd, ".env")
|
|
11
|
+
const existing = existsSync(envPath) ? readFileSync(envPath, "utf8") : ""
|
|
12
|
+
const keys = new Set([...Object.keys(updates), ...removeKeys])
|
|
13
|
+
const kept = existing
|
|
14
|
+
.split("\n")
|
|
15
|
+
.filter((line) => {
|
|
16
|
+
const key = line.split("=")[0]?.trim()
|
|
17
|
+
return key && line.includes("=") && !keys.has(key)
|
|
18
|
+
})
|
|
19
|
+
const merged = [...kept, ...Object.entries(updates).map(([key, value]) => `${key}=${value}`)]
|
|
20
|
+
writeFileSync(envPath, `${merged.join("\n").trimEnd()}\n`, "utf8")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function readEnvValue(cwd: string, key: string, fallback: string): string {
|
|
24
|
+
const envPath = join(cwd, ".env")
|
|
25
|
+
if (existsSync(envPath)) {
|
|
26
|
+
const m = readFileSync(envPath, "utf8").match(new RegExp(`^${key}=(.+)$`, "m"))
|
|
27
|
+
if (m?.[1]) return m[1].trim()
|
|
28
|
+
}
|
|
29
|
+
return fallback
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function readEnvInt(cwd: string, key: string): number | null {
|
|
33
|
+
const raw = readEnvValue(cwd, key, "")
|
|
34
|
+
if (!raw) return null
|
|
35
|
+
const port = Number(raw)
|
|
36
|
+
return Number.isInteger(port) && port > 0 && port <= 65535 ? port : null
|
|
37
|
+
}
|
package/src/gitignore.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { resolve } from "node:path"
|
|
3
|
+
|
|
4
|
+
export const SUPATYPE_GITIGNORE_MARKER = "# Supatype — local runtime (contains secrets in link.json)"
|
|
5
|
+
export const SUPATYPE_GITIGNORE_BLOCK = `${SUPATYPE_GITIGNORE_MARKER}
|
|
6
|
+
.env
|
|
7
|
+
.supatype/
|
|
8
|
+
supatype.local.config.ts
|
|
9
|
+
supatype.local.config.js
|
|
10
|
+
supatype.local.config.mjs
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
export function isSupatypeGitignored(cwd: string): boolean {
|
|
14
|
+
const gitignorePath = resolve(cwd, ".gitignore")
|
|
15
|
+
if (!existsSync(gitignorePath)) return false
|
|
16
|
+
const content = readFileSync(gitignorePath, "utf8")
|
|
17
|
+
return /\.supatype\/?(\/|\s|$)/m.test(content) || content.includes(".supatype/")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ensureSupatypeGitignore(cwd: string, opts?: { silent?: boolean }): boolean {
|
|
21
|
+
const gitignorePath = resolve(cwd, ".gitignore")
|
|
22
|
+
if (isSupatypeGitignored(cwd)) return true
|
|
23
|
+
|
|
24
|
+
if (existsSync(gitignorePath)) {
|
|
25
|
+
const content = readFileSync(gitignorePath, "utf8")
|
|
26
|
+
const next = content.endsWith("\n") ? content : `${content}\n`
|
|
27
|
+
writeFileSync(gitignorePath, `${next}\n${SUPATYPE_GITIGNORE_BLOCK}`, "utf8")
|
|
28
|
+
} else {
|
|
29
|
+
writeFileSync(
|
|
30
|
+
gitignorePath,
|
|
31
|
+
`.env\nnode_modules/\ndist/\n${SUPATYPE_GITIGNORE_BLOCK}`,
|
|
32
|
+
"utf8",
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!opts?.silent) {
|
|
37
|
+
console.warn("Added .supatype/ to .gitignore (link.json contains secrets — never commit).")
|
|
38
|
+
}
|
|
39
|
+
return true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function warnIfLinkNotGitignored(cwd: string): void {
|
|
43
|
+
if (isSupatypeGitignored(cwd)) return
|
|
44
|
+
console.warn(
|
|
45
|
+
"\n⚠ Warning: .supatype/ is not in .gitignore — link.json contains tokens and must not be committed.",
|
|
46
|
+
)
|
|
47
|
+
console.warn(" Run with link --fix-gitignore to append the Supatype block.\n")
|
|
48
|
+
}
|
package/src/kong-config.ts
CHANGED
|
@@ -18,6 +18,11 @@ export interface KongDeclarativeOptions {
|
|
|
18
18
|
studioServiceUrl?: string | undefined
|
|
19
19
|
/** See {@link RuntimeRouteOptions.studioStripPath}. */
|
|
20
20
|
studioStripPath?: boolean | undefined
|
|
21
|
+
/**
|
|
22
|
+
* When set, append a global Kong `acme` plugin (Let's Encrypt) with Redis/Valkey
|
|
23
|
+
* storage so the self-host gateway provisions and renews TLS automatically.
|
|
24
|
+
*/
|
|
25
|
+
acme?: { email: string; domain: string; redisHost: string } | undefined
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
/** Escape a string for use inside YAML double quotes. */
|
|
@@ -85,9 +90,27 @@ ${route.paths.map((path) => ` - ${path}`).join("\n")}
|
|
|
85
90
|
${protocols}${routePlugins}${graphqlPlugins}`
|
|
86
91
|
}).join("\n")
|
|
87
92
|
|
|
93
|
+
const acme = opts.acme
|
|
94
|
+
const pluginsBlock = acme
|
|
95
|
+
? `
|
|
96
|
+
plugins:
|
|
97
|
+
- name: acme
|
|
98
|
+
config:
|
|
99
|
+
account_email: ${yamlQuotedString(acme.email)}
|
|
100
|
+
tos_accepted: true
|
|
101
|
+
domains:
|
|
102
|
+
- ${yamlQuotedString(acme.domain)}
|
|
103
|
+
storage: redis
|
|
104
|
+
storage_config:
|
|
105
|
+
redis:
|
|
106
|
+
host: ${yamlQuotedString(acme.redisHost)}
|
|
107
|
+
port: 6379
|
|
108
|
+
`
|
|
109
|
+
: ""
|
|
110
|
+
|
|
88
111
|
return `_format_version: "3.0"
|
|
89
112
|
${consumersBlock}
|
|
90
113
|
services:
|
|
91
114
|
${servicesBlock}
|
|
92
|
-
`
|
|
115
|
+
${pluginsBlock}`
|
|
93
116
|
}
|
package/src/link.ts
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { resolve } from "node:path"
|
|
3
|
+
import { warn } from "./ui/messages.js"
|
|
4
|
+
|
|
5
|
+
export const LINK_VERSION = 1 as const
|
|
6
|
+
export const LINK_FILE = ".supatype/link.json"
|
|
7
|
+
export const LEGACY_CLOUD_FILE = ".supatype/cloud.json"
|
|
8
|
+
export const LEGACY_LINKED_FILE = ".supatype/linked.json"
|
|
9
|
+
|
|
10
|
+
export type ProjectLinkKind = "cloud" | "self-host" | "local"
|
|
11
|
+
|
|
12
|
+
export interface EnvironmentTarget {
|
|
13
|
+
name: string
|
|
14
|
+
apiUrl: string
|
|
15
|
+
token?: string
|
|
16
|
+
linkedAt: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ProjectLink {
|
|
20
|
+
version: typeof LINK_VERSION
|
|
21
|
+
kind: ProjectLinkKind
|
|
22
|
+
projectRef: string
|
|
23
|
+
defaultEnvironment: string
|
|
24
|
+
token?: string
|
|
25
|
+
orgId?: string | undefined
|
|
26
|
+
cloudApiUrl?: string
|
|
27
|
+
linkedAt: string
|
|
28
|
+
environments: Record<string, EnvironmentTarget>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface LocalEnvironment {
|
|
32
|
+
target: "local"
|
|
33
|
+
apiUrl: string
|
|
34
|
+
databaseUrl: string
|
|
35
|
+
projectRef: string
|
|
36
|
+
kongPort: number
|
|
37
|
+
provider: "docker" | "native"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface BranchContext {
|
|
41
|
+
mode: "branch"
|
|
42
|
+
branchId: string
|
|
43
|
+
apiUrl: string
|
|
44
|
+
token?: string | undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface LegacyCloudFile {
|
|
48
|
+
apiUrl?: string
|
|
49
|
+
token?: string
|
|
50
|
+
projectSlug?: string
|
|
51
|
+
orgId?: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface LegacyLinkedFile {
|
|
55
|
+
ref?: string
|
|
56
|
+
orgId?: string
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function writeLocalEnvironment(cwd: string, env: LocalEnvironment): void {
|
|
60
|
+
const dir = resolve(cwd, ".supatype")
|
|
61
|
+
mkdirSync(dir, { recursive: true })
|
|
62
|
+
writeFileSync(resolve(dir, "environment.json"), `${JSON.stringify(env, null, 2)}\n`, "utf8")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function loadLocalEnvironment(cwd: string): LocalEnvironment | null {
|
|
66
|
+
const path = resolve(cwd, ".supatype/environment.json")
|
|
67
|
+
if (!existsSync(path)) return null
|
|
68
|
+
return JSON.parse(readFileSync(path, "utf8")) as LocalEnvironment
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function linkPath(cwd: string): string {
|
|
72
|
+
return resolve(cwd, LINK_FILE)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function loadProjectLink(cwd: string): ProjectLink | null {
|
|
76
|
+
migrateLegacyLinkFiles(cwd)
|
|
77
|
+
const path = linkPath(cwd)
|
|
78
|
+
if (!existsSync(path)) return null
|
|
79
|
+
return JSON.parse(readFileSync(path, "utf8")) as ProjectLink
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function saveProjectLink(cwd: string, link: ProjectLink): void {
|
|
83
|
+
const dir = resolve(cwd, ".supatype")
|
|
84
|
+
mkdirSync(dir, { recursive: true })
|
|
85
|
+
writeFileSync(linkPath(cwd), `${JSON.stringify(link, null, 2)}\n`, "utf8")
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isProjectLinked(cwd: string): boolean {
|
|
89
|
+
const link = loadProjectLink(cwd)
|
|
90
|
+
return Boolean(link?.projectRef && Object.keys(link.environments).length > 0)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function resolveEnvironmentName(link: ProjectLink, envFlag?: string): string {
|
|
94
|
+
if (envFlag?.trim()) return envFlag.trim()
|
|
95
|
+
return link.defaultEnvironment || "production"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getEnvironmentTarget(link: ProjectLink, envName: string): EnvironmentTarget | null {
|
|
99
|
+
return link.environments[envName] ?? null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function resolveEnvironmentToken(link: ProjectLink, env: EnvironmentTarget): string | undefined {
|
|
103
|
+
return env.token ?? link.token
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let migrationWarned = false
|
|
107
|
+
|
|
108
|
+
/** Merge legacy cloud.json + linked.json into link.json once. */
|
|
109
|
+
export function migrateLegacyLinkFiles(cwd: string): void {
|
|
110
|
+
const target = linkPath(cwd)
|
|
111
|
+
if (existsSync(target)) return
|
|
112
|
+
|
|
113
|
+
const cloudPath = resolve(cwd, LEGACY_CLOUD_FILE)
|
|
114
|
+
const linkedPath = resolve(cwd, LEGACY_LINKED_FILE)
|
|
115
|
+
const hasCloud = existsSync(cloudPath)
|
|
116
|
+
const hasLinked = existsSync(linkedPath)
|
|
117
|
+
if (!hasCloud && !hasLinked) return
|
|
118
|
+
|
|
119
|
+
let cloud: LegacyCloudFile | null = null
|
|
120
|
+
let linked: LegacyLinkedFile | null = null
|
|
121
|
+
|
|
122
|
+
if (hasCloud) {
|
|
123
|
+
cloud = JSON.parse(readFileSync(cloudPath, "utf8")) as LegacyCloudFile
|
|
124
|
+
}
|
|
125
|
+
if (hasLinked) {
|
|
126
|
+
linked = JSON.parse(readFileSync(linkedPath, "utf8")) as LegacyLinkedFile
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const projectRef = cloud?.projectSlug ?? linked?.ref
|
|
130
|
+
if (!projectRef || !cloud?.token) {
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const now = new Date().toISOString()
|
|
135
|
+
const link: ProjectLink = {
|
|
136
|
+
version: LINK_VERSION,
|
|
137
|
+
kind: "cloud",
|
|
138
|
+
projectRef,
|
|
139
|
+
defaultEnvironment: "production",
|
|
140
|
+
token: cloud.token,
|
|
141
|
+
cloudApiUrl: cloud.apiUrl ?? "https://api.supatype.com",
|
|
142
|
+
linkedAt: now,
|
|
143
|
+
environments: {
|
|
144
|
+
production: {
|
|
145
|
+
name: "production",
|
|
146
|
+
apiUrl: cloud.apiUrl ?? "https://api.supatype.com",
|
|
147
|
+
linkedAt: now,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
...(cloud.orgId !== undefined
|
|
151
|
+
? { orgId: cloud.orgId }
|
|
152
|
+
: linked?.orgId !== undefined
|
|
153
|
+
? { orgId: linked.orgId }
|
|
154
|
+
: {}),
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
saveProjectLink(cwd, link)
|
|
158
|
+
|
|
159
|
+
if (!migrationWarned) {
|
|
160
|
+
migrationWarned = true
|
|
161
|
+
warn(
|
|
162
|
+
"Migrated .supatype/cloud.json → .supatype/link.json (legacy files kept; remove manually when ready).",
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function createSelfHostLink(params: {
|
|
168
|
+
projectRef: string
|
|
169
|
+
apiUrl: string
|
|
170
|
+
token: string
|
|
171
|
+
envName?: string
|
|
172
|
+
existing?: ProjectLink | null
|
|
173
|
+
}): ProjectLink {
|
|
174
|
+
const envName = params.envName ?? "production"
|
|
175
|
+
const now = new Date().toISOString()
|
|
176
|
+
const env: EnvironmentTarget = {
|
|
177
|
+
name: envName,
|
|
178
|
+
apiUrl: params.apiUrl.replace(/\/$/, ""),
|
|
179
|
+
token: params.token,
|
|
180
|
+
linkedAt: now,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (params.existing) {
|
|
184
|
+
return {
|
|
185
|
+
...params.existing,
|
|
186
|
+
kind: params.existing.kind === "cloud" ? "self-host" : params.existing.kind,
|
|
187
|
+
projectRef: params.projectRef,
|
|
188
|
+
defaultEnvironment: params.existing.defaultEnvironment || envName,
|
|
189
|
+
linkedAt: now,
|
|
190
|
+
environments: {
|
|
191
|
+
...params.existing.environments,
|
|
192
|
+
[envName]: env,
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
version: LINK_VERSION,
|
|
199
|
+
kind: "self-host",
|
|
200
|
+
projectRef: params.projectRef,
|
|
201
|
+
defaultEnvironment: envName,
|
|
202
|
+
token: params.token,
|
|
203
|
+
linkedAt: now,
|
|
204
|
+
environments: { [envName]: env },
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function createCloudLink(params: {
|
|
209
|
+
projectRef: string
|
|
210
|
+
cloudApiUrl: string
|
|
211
|
+
token: string
|
|
212
|
+
orgId?: string | undefined
|
|
213
|
+
environments?: Array<{ name: string; apiUrl: string }>
|
|
214
|
+
existing?: ProjectLink | null
|
|
215
|
+
}): ProjectLink {
|
|
216
|
+
const now = new Date().toISOString()
|
|
217
|
+
const envMap: Record<string, EnvironmentTarget> = {}
|
|
218
|
+
const envs = params.environments?.length
|
|
219
|
+
? params.environments
|
|
220
|
+
: [{ name: "production", apiUrl: params.cloudApiUrl }]
|
|
221
|
+
|
|
222
|
+
for (const e of envs) {
|
|
223
|
+
envMap[e.name] = {
|
|
224
|
+
name: e.name,
|
|
225
|
+
apiUrl: e.apiUrl.replace(/\/$/, ""),
|
|
226
|
+
linkedAt: now,
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
version: LINK_VERSION,
|
|
232
|
+
kind: "cloud",
|
|
233
|
+
projectRef: params.projectRef,
|
|
234
|
+
defaultEnvironment: "production",
|
|
235
|
+
token: params.token,
|
|
236
|
+
cloudApiUrl: params.cloudApiUrl.replace(/\/$/, ""),
|
|
237
|
+
linkedAt: now,
|
|
238
|
+
environments: params.existing
|
|
239
|
+
? { ...params.existing.environments, ...envMap }
|
|
240
|
+
: envMap,
|
|
241
|
+
...(params.orgId !== undefined ? { orgId: params.orgId } : {}),
|
|
242
|
+
}
|
|
243
|
+
}
|