@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
|
@@ -21,7 +21,11 @@ import {
|
|
|
21
21
|
discoverTsFunctionsInDir,
|
|
22
22
|
generateFunctionsRouterSource,
|
|
23
23
|
} from "../functions-router-gen.js"
|
|
24
|
-
import {
|
|
24
|
+
import { loadProjectLink } from "../link.js"
|
|
25
|
+
import { resolveTarget } from "../resolve-target.js"
|
|
26
|
+
import { targetFetch } from "../target-client.js"
|
|
27
|
+
import { error, info, plain } from "../ui/messages.js"
|
|
28
|
+
import { nextSteps } from "../ui/next-steps.js"
|
|
25
29
|
|
|
26
30
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
27
31
|
|
|
@@ -56,8 +60,9 @@ export function registerFunctions(program: Command): void {
|
|
|
56
60
|
.command("deploy")
|
|
57
61
|
.description("Deploy all functions (or --only <name> for one) to the linked project")
|
|
58
62
|
.option("--only <name>", "Deploy a single function")
|
|
63
|
+
.option("--env <name>", "Target environment when linked")
|
|
59
64
|
.option("--dry-run", "Show what would be deployed without deploying")
|
|
60
|
-
.action(async (opts: { only?: string; dryRun?: boolean }) => {
|
|
65
|
+
.action(async (opts: { only?: string; env?: string; dryRun?: boolean }) => {
|
|
61
66
|
await deploy(process.cwd(), opts)
|
|
62
67
|
})
|
|
63
68
|
|
|
@@ -125,7 +130,7 @@ function scaffoldFunction(cwd: string, name: string): void {
|
|
|
125
130
|
const functionsDir = resolveFunctionsDir(cwd, "write")
|
|
126
131
|
const fnDir = resolve(functionsDir, name)
|
|
127
132
|
if (existsSync(fnDir)) {
|
|
128
|
-
|
|
133
|
+
error(`Function "${name}" already exists at ${relative(cwd, fnDir)}`)
|
|
129
134
|
process.exit(1)
|
|
130
135
|
}
|
|
131
136
|
|
|
@@ -177,11 +182,12 @@ export default async function handler(req: Request): Promise<Response> {
|
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
const functionsDirLabel = relativeFunctionsDir(cwd, functionsDir)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
info(`Created function: ${functionsDirLabel}/${name}/index.ts`)
|
|
186
|
+
nextSteps("Next steps:", [
|
|
187
|
+
"Local dev: npx supatype functions serve",
|
|
188
|
+
`Invoke: npx supatype functions invoke ${name}`,
|
|
189
|
+
"Deploy: npx supatype functions deploy",
|
|
190
|
+
])
|
|
185
191
|
}
|
|
186
192
|
|
|
187
193
|
// ─── Discover functions ──────────────────────────────────────────────────────
|
|
@@ -257,16 +263,16 @@ async function serve(cwd: string, opts: { port: string; envFile: string }): Prom
|
|
|
257
263
|
const functionsDirLabel = relativeFunctionsDir(cwd, functionsDir)
|
|
258
264
|
const routes = discoverTsFunctionsInDir(functionsDir)
|
|
259
265
|
if (routes.length === 0) {
|
|
260
|
-
|
|
261
|
-
|
|
266
|
+
error(`No functions found in ${functionsDirLabel}/`)
|
|
267
|
+
error("Create one with: npx supatype functions new <name>")
|
|
262
268
|
process.exit(1)
|
|
263
269
|
}
|
|
264
270
|
|
|
265
|
-
|
|
271
|
+
plain(`Discovered ${routes.length} function(s):`)
|
|
266
272
|
for (const fn of routes) {
|
|
267
|
-
|
|
273
|
+
plain(` /${fn.name} → ${relative(cwd, fn.entrypoint)}`)
|
|
268
274
|
}
|
|
269
|
-
|
|
275
|
+
plain()
|
|
270
276
|
|
|
271
277
|
// Generate a Deno entry script that routes requests to the correct function
|
|
272
278
|
const routerPath = resolve(functionsDir, ".serve-router.ts")
|
|
@@ -279,14 +285,15 @@ async function serve(cwd: string, opts: { port: string; envFile: string }): Prom
|
|
|
279
285
|
envArgs.push("--env-file", envFilePath)
|
|
280
286
|
}
|
|
281
287
|
|
|
282
|
-
|
|
283
|
-
|
|
288
|
+
info(`Serving functions at http://localhost:${opts.port}/functions/v1/`)
|
|
289
|
+
info("Watching for changes...")
|
|
290
|
+
plain()
|
|
284
291
|
|
|
285
292
|
let denoBin: string
|
|
286
293
|
try {
|
|
287
294
|
denoBin = await ensureBinary("deno", config)
|
|
288
295
|
} catch (err) {
|
|
289
|
-
|
|
296
|
+
error(`Could not provision Deno: ${(err as Error).message}`)
|
|
290
297
|
process.exit(1)
|
|
291
298
|
}
|
|
292
299
|
|
|
@@ -320,14 +327,14 @@ async function serve(cwd: string, opts: { port: string; envFile: string }): Prom
|
|
|
320
327
|
try { unlinkSync(routerPath) } catch { /* ignore */ }
|
|
321
328
|
|
|
322
329
|
if (result.status !== 0) {
|
|
323
|
-
|
|
330
|
+
error("Function server exited with errors.")
|
|
324
331
|
process.exit(result.status ?? 1)
|
|
325
332
|
}
|
|
326
333
|
}
|
|
327
334
|
|
|
328
335
|
// ─── Deploy ──────────────────────────────────────────────────────────────────
|
|
329
336
|
|
|
330
|
-
async function deploy(cwd: string, opts: { only?: string; dryRun?: boolean }): Promise<void> {
|
|
337
|
+
async function deploy(cwd: string, opts: { only?: string; env?: string; dryRun?: boolean }): Promise<void> {
|
|
331
338
|
const allFns = discoverFunctions(cwd)
|
|
332
339
|
const fns = opts.only
|
|
333
340
|
? allFns.filter(f => f.name === opts.only)
|
|
@@ -337,62 +344,120 @@ async function deploy(cwd: string, opts: { only?: string; dryRun?: boolean }): P
|
|
|
337
344
|
const functionsDir = resolveFunctionsDir(cwd, "read")
|
|
338
345
|
const functionsDirLabel = relativeFunctionsDir(cwd, functionsDir)
|
|
339
346
|
if (opts.only) {
|
|
340
|
-
|
|
347
|
+
error(`Function "${opts.only}" not found in ${functionsDirLabel}/`)
|
|
341
348
|
} else {
|
|
342
|
-
|
|
349
|
+
error(`No functions found in ${functionsDirLabel}/`)
|
|
343
350
|
}
|
|
344
351
|
process.exit(1)
|
|
345
352
|
}
|
|
346
353
|
|
|
347
354
|
if (opts.dryRun) {
|
|
348
|
-
|
|
355
|
+
plain("Dry run — the following functions would be deployed:\n")
|
|
349
356
|
for (const fn of fns) {
|
|
350
|
-
|
|
357
|
+
plain(` ${fn.name} → ${relative(cwd, fn.entrypoint)}`)
|
|
351
358
|
}
|
|
352
|
-
|
|
359
|
+
plain(`\nTotal: ${fns.length} function(s)`)
|
|
353
360
|
return
|
|
354
361
|
}
|
|
355
362
|
|
|
363
|
+
const link = loadProjectLink(cwd)
|
|
364
|
+
if (link) {
|
|
365
|
+
try {
|
|
366
|
+
const target = resolveTarget(cwd, { env: opts.env })
|
|
367
|
+
if (target.mode !== "direct" && target.token) {
|
|
368
|
+
await deployViaTarget(cwd, target, fns)
|
|
369
|
+
return
|
|
370
|
+
}
|
|
371
|
+
} catch {
|
|
372
|
+
/* fall through to compose/local */
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const { selfHostComposePaths } = await import("../self-host-compose.js")
|
|
356
377
|
const composePath = selfHostComposePaths(cwd).composePath
|
|
357
378
|
if (existsSync(composePath)) {
|
|
358
379
|
await deploySelfHosted(cwd, fns)
|
|
359
380
|
return
|
|
360
381
|
}
|
|
361
382
|
|
|
362
|
-
await deployCloud(cwd, fns)
|
|
383
|
+
await deployCloud(cwd, fns, opts.env)
|
|
363
384
|
}
|
|
364
385
|
|
|
365
386
|
async function deploySelfHosted(cwd: string, fns: DiscoveredFunction[]): Promise<void> {
|
|
366
|
-
|
|
367
|
-
|
|
387
|
+
info("Self-host Compose deployment.")
|
|
388
|
+
plain("Functions are served from your project functions/ directory (no bundle step).\n")
|
|
389
|
+
|
|
390
|
+
for (const fn of fns) {
|
|
391
|
+
plain(` ${fn.name} → ${relative(cwd, fn.entrypoint)}`)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
plain(`\n${fns.length} function(s) ready on disk.`)
|
|
395
|
+
info("Restart the functions-worker container to load changes:")
|
|
396
|
+
plain(" supatype self-host compose restart functions-worker")
|
|
397
|
+
plain("\nKong → supatype-server → functions-worker (per-project worker).")
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async function deployViaTarget(
|
|
401
|
+
cwd: string,
|
|
402
|
+
target: ReturnType<typeof resolveTarget>,
|
|
403
|
+
fns: DiscoveredFunction[],
|
|
404
|
+
): Promise<void> {
|
|
405
|
+
info(`Deploying to ${target.mode} project: ${target.projectRef} (${target.environment})`)
|
|
406
|
+
plain()
|
|
368
407
|
|
|
369
408
|
for (const fn of fns) {
|
|
370
|
-
|
|
409
|
+
const start = Date.now()
|
|
410
|
+
const source = readFunctionSource(fn)
|
|
411
|
+
|
|
412
|
+
try {
|
|
413
|
+
await targetFetch(
|
|
414
|
+
target.apiBaseUrl,
|
|
415
|
+
target.apiPrefix,
|
|
416
|
+
{
|
|
417
|
+
method: "POST",
|
|
418
|
+
path: `/projects/${target.projectRef}/functions/deploy`,
|
|
419
|
+
body: {
|
|
420
|
+
functions: [{
|
|
421
|
+
name: fn.name,
|
|
422
|
+
source,
|
|
423
|
+
entrypoint: `${fn.name}/index.ts`,
|
|
424
|
+
}],
|
|
425
|
+
},
|
|
426
|
+
token: target.token!,
|
|
427
|
+
orgId: target.orgId,
|
|
428
|
+
environment: target.mode === "cloud" ? target.environment : undefined,
|
|
429
|
+
},
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
const duration = Date.now() - start
|
|
433
|
+
plain(` ${fn.name} ✓ deployed (${duration}ms)`)
|
|
434
|
+
} catch (err) {
|
|
435
|
+
plain(` ${fn.name} ✗ ${err instanceof Error ? err.message : "unknown error"}`)
|
|
436
|
+
}
|
|
371
437
|
}
|
|
372
438
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
console.log(" supatype self-host compose restart functions-worker")
|
|
376
|
-
console.log("\nKong → supatype-server → functions-worker (per-project worker).")
|
|
439
|
+
info(`Deployed ${fns.length} function(s)`)
|
|
440
|
+
void cwd
|
|
377
441
|
}
|
|
378
442
|
|
|
379
|
-
async function deployCloud(cwd: string, fns: DiscoveredFunction[]): Promise<void> {
|
|
443
|
+
async function deployCloud(cwd: string, fns: DiscoveredFunction[], env?: string): Promise<void> {
|
|
380
444
|
const { getLinkedProject, getCloudToken, getCloudApiUrl } = await loadCloudHelpers()
|
|
381
445
|
const linked = getLinkedProject(cwd)
|
|
382
446
|
|
|
383
447
|
if (!linked) {
|
|
384
|
-
|
|
448
|
+
error("No linked project. Run: npx supatype cloud link")
|
|
385
449
|
process.exit(1)
|
|
386
450
|
}
|
|
387
451
|
|
|
388
|
-
const token = getCloudToken()
|
|
452
|
+
const token = getCloudToken(cwd)
|
|
389
453
|
if (!token) {
|
|
390
|
-
|
|
454
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
391
455
|
process.exit(1)
|
|
392
456
|
}
|
|
393
457
|
|
|
394
|
-
const apiUrl = getCloudApiUrl()
|
|
395
|
-
|
|
458
|
+
const apiUrl = getCloudApiUrl(cwd)
|
|
459
|
+
info(`Deploying to project: ${linked.ref}`)
|
|
460
|
+
plain()
|
|
396
461
|
|
|
397
462
|
for (const fn of fns) {
|
|
398
463
|
const start = Date.now()
|
|
@@ -420,19 +485,19 @@ async function deployCloud(cwd: string, fns: DiscoveredFunction[]): Promise<void
|
|
|
420
485
|
|
|
421
486
|
if (!res.ok) {
|
|
422
487
|
const body = await res.json().catch(() => ({})) as Record<string, string>
|
|
423
|
-
|
|
488
|
+
plain(` ${fn.name} ✗ ${body["message"] ?? res.statusText}`)
|
|
424
489
|
continue
|
|
425
490
|
}
|
|
426
491
|
|
|
427
492
|
const duration = Date.now() - start
|
|
428
|
-
|
|
493
|
+
plain(` ${fn.name} ✓ deployed (${duration}ms)`)
|
|
429
494
|
} catch (err) {
|
|
430
|
-
|
|
495
|
+
plain(` ${fn.name} ✗ ${err instanceof Error ? err.message : "unknown error"}`)
|
|
431
496
|
}
|
|
432
497
|
}
|
|
433
498
|
|
|
434
|
-
|
|
435
|
-
|
|
499
|
+
info(`Deployed ${fns.length} function(s)`)
|
|
500
|
+
info(`Invoke: https://${linked.ref}.supatype.dev/functions/v1/<name>`)
|
|
436
501
|
}
|
|
437
502
|
|
|
438
503
|
function readFunctionSource(fn: DiscoveredFunction): string {
|
|
@@ -463,24 +528,24 @@ async function listFunctions(cwd: string): Promise<void> {
|
|
|
463
528
|
// Show local functions instead
|
|
464
529
|
const fns = discoverFunctions(cwd)
|
|
465
530
|
if (fns.length === 0) {
|
|
466
|
-
|
|
531
|
+
info("No functions found locally or remotely.")
|
|
467
532
|
return
|
|
468
533
|
}
|
|
469
|
-
|
|
534
|
+
plain("Local functions (not linked to a cloud project):\n")
|
|
470
535
|
for (const fn of fns) {
|
|
471
|
-
|
|
536
|
+
plain(` ${fn.name.padEnd(30)} ${relative(cwd, fn.entrypoint)}`)
|
|
472
537
|
}
|
|
473
538
|
return
|
|
474
539
|
}
|
|
475
540
|
|
|
476
|
-
const token = getCloudToken()
|
|
541
|
+
const token = getCloudToken(cwd)
|
|
477
542
|
if (!token) {
|
|
478
|
-
|
|
543
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
479
544
|
process.exit(1)
|
|
480
545
|
}
|
|
481
546
|
|
|
482
547
|
try {
|
|
483
|
-
const res = await fetch(`${getCloudApiUrl()}/api/v1/projects/${linked.ref}/functions`, {
|
|
548
|
+
const res = await fetch(`${getCloudApiUrl(cwd)}/api/v1/projects/${linked.ref}/functions`, {
|
|
484
549
|
headers: {
|
|
485
550
|
Authorization: `Bearer ${token}`,
|
|
486
551
|
"X-Org-Id": linked.orgId ?? "",
|
|
@@ -489,29 +554,29 @@ async function listFunctions(cwd: string): Promise<void> {
|
|
|
489
554
|
})
|
|
490
555
|
|
|
491
556
|
if (!res.ok) {
|
|
492
|
-
|
|
557
|
+
error(`Failed to list functions: ${res.statusText}`)
|
|
493
558
|
process.exit(1)
|
|
494
559
|
}
|
|
495
560
|
|
|
496
561
|
const { data } = await res.json() as { data: Array<{ name: string; deployedAt: string; invocations24h: number; avgDurationMs: number }> }
|
|
497
562
|
|
|
498
563
|
if (data.length === 0) {
|
|
499
|
-
|
|
564
|
+
info("No deployed functions.")
|
|
500
565
|
return
|
|
501
566
|
}
|
|
502
567
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
568
|
+
plain("Deployed functions:\n")
|
|
569
|
+
plain(` ${"Name".padEnd(28)} ${"Last Deployed".padEnd(24)} ${"Invocations (24h)".padEnd(20)} Avg Duration`)
|
|
570
|
+
plain(` ${"─".repeat(28)} ${"─".repeat(24)} ${"─".repeat(20)} ${"─".repeat(12)}`)
|
|
506
571
|
|
|
507
572
|
for (const fn of data) {
|
|
508
573
|
const deployed = fn.deployedAt ? new Date(fn.deployedAt).toLocaleString() : "—"
|
|
509
|
-
|
|
574
|
+
plain(
|
|
510
575
|
` ${fn.name.padEnd(28)} ${deployed.padEnd(24)} ${String(fn.invocations24h ?? 0).padEnd(20)} ${fn.avgDurationMs ?? 0}ms`,
|
|
511
576
|
)
|
|
512
577
|
}
|
|
513
578
|
} catch (err) {
|
|
514
|
-
|
|
579
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
515
580
|
process.exit(1)
|
|
516
581
|
}
|
|
517
582
|
}
|
|
@@ -523,18 +588,18 @@ async function deleteFunction(cwd: string, name: string): Promise<void> {
|
|
|
523
588
|
const linked = getLinkedProject(cwd)
|
|
524
589
|
|
|
525
590
|
if (!linked) {
|
|
526
|
-
|
|
591
|
+
error("No linked project. Run: npx supatype cloud link")
|
|
527
592
|
process.exit(1)
|
|
528
593
|
}
|
|
529
594
|
|
|
530
|
-
const token = getCloudToken()
|
|
595
|
+
const token = getCloudToken(cwd)
|
|
531
596
|
if (!token) {
|
|
532
|
-
|
|
597
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
533
598
|
process.exit(1)
|
|
534
599
|
}
|
|
535
600
|
|
|
536
601
|
try {
|
|
537
|
-
const res = await fetch(`${getCloudApiUrl()}/api/v1/projects/${linked.ref}/functions/${name}`, {
|
|
602
|
+
const res = await fetch(`${getCloudApiUrl(cwd)}/api/v1/projects/${linked.ref}/functions/${name}`, {
|
|
538
603
|
method: "DELETE",
|
|
539
604
|
headers: {
|
|
540
605
|
Authorization: `Bearer ${token}`,
|
|
@@ -545,13 +610,13 @@ async function deleteFunction(cwd: string, name: string): Promise<void> {
|
|
|
545
610
|
|
|
546
611
|
if (!res.ok) {
|
|
547
612
|
const body = await res.json().catch(() => ({})) as Record<string, string>
|
|
548
|
-
|
|
613
|
+
error(`Failed to delete "${name}": ${body["message"] ?? res.statusText}`)
|
|
549
614
|
process.exit(1)
|
|
550
615
|
}
|
|
551
616
|
|
|
552
|
-
|
|
617
|
+
info(`Function "${name}" deleted. It will return 404 immediately.`)
|
|
553
618
|
} catch (err) {
|
|
554
|
-
|
|
619
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
555
620
|
process.exit(1)
|
|
556
621
|
}
|
|
557
622
|
}
|
|
@@ -563,19 +628,19 @@ async function functionLogs(cwd: string, name: string, opts: { since: string }):
|
|
|
563
628
|
const linked = getLinkedProject(cwd)
|
|
564
629
|
|
|
565
630
|
if (!linked) {
|
|
566
|
-
|
|
631
|
+
error("No linked project. Run: npx supatype cloud link")
|
|
567
632
|
process.exit(1)
|
|
568
633
|
}
|
|
569
634
|
|
|
570
|
-
const token = getCloudToken()
|
|
635
|
+
const token = getCloudToken(cwd)
|
|
571
636
|
if (!token) {
|
|
572
|
-
|
|
637
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
573
638
|
process.exit(1)
|
|
574
639
|
}
|
|
575
640
|
|
|
576
641
|
try {
|
|
577
642
|
const res = await fetch(
|
|
578
|
-
`${getCloudApiUrl()}/api/v1/projects/${linked.ref}/functions/${name}/logs?since=${opts.since}`,
|
|
643
|
+
`${getCloudApiUrl(cwd)}/api/v1/projects/${linked.ref}/functions/${name}/logs?since=${opts.since}`,
|
|
579
644
|
{
|
|
580
645
|
headers: {
|
|
581
646
|
Authorization: `Bearer ${token}`,
|
|
@@ -586,24 +651,24 @@ async function functionLogs(cwd: string, name: string, opts: { since: string }):
|
|
|
586
651
|
)
|
|
587
652
|
|
|
588
653
|
if (!res.ok) {
|
|
589
|
-
|
|
654
|
+
error(`Failed to fetch logs: ${res.statusText}`)
|
|
590
655
|
process.exit(1)
|
|
591
656
|
}
|
|
592
657
|
|
|
593
658
|
const { data } = await res.json() as { data: Array<{ timestamp: string; level: string; message: string }> }
|
|
594
659
|
|
|
595
660
|
if (data.length === 0) {
|
|
596
|
-
|
|
661
|
+
info(`No logs for "${name}" in the last ${opts.since}.`)
|
|
597
662
|
return
|
|
598
663
|
}
|
|
599
664
|
|
|
600
665
|
for (const entry of data) {
|
|
601
666
|
const ts = new Date(entry.timestamp).toISOString().slice(11, 23)
|
|
602
667
|
const level = entry.level.toUpperCase().padEnd(5)
|
|
603
|
-
|
|
668
|
+
plain(`${ts} [${level}] ${entry.message}`)
|
|
604
669
|
}
|
|
605
670
|
} catch (err) {
|
|
606
|
-
|
|
671
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
607
672
|
process.exit(1)
|
|
608
673
|
}
|
|
609
674
|
}
|
|
@@ -625,7 +690,7 @@ async function invoke(
|
|
|
625
690
|
const linked = getLinkedProject(cwd)
|
|
626
691
|
if (linked) {
|
|
627
692
|
url = `https://${linked.ref}.supatype.dev/functions/v1/${name}`
|
|
628
|
-
const token = getCloudToken()
|
|
693
|
+
const token = getCloudToken(cwd)
|
|
629
694
|
if (token && opts.auth) {
|
|
630
695
|
headers["Authorization"] = `Bearer ${token}`
|
|
631
696
|
}
|
|
@@ -646,7 +711,7 @@ async function invoke(
|
|
|
646
711
|
JSON.parse(opts.data)
|
|
647
712
|
body = opts.data
|
|
648
713
|
} catch {
|
|
649
|
-
|
|
714
|
+
error("Invalid JSON data. Use --data '{\"key\": \"value\"}'")
|
|
650
715
|
process.exit(1)
|
|
651
716
|
}
|
|
652
717
|
|
|
@@ -661,22 +726,22 @@ async function invoke(
|
|
|
661
726
|
const duration = Date.now() - start
|
|
662
727
|
const responseBody = await res.text()
|
|
663
728
|
|
|
664
|
-
|
|
665
|
-
|
|
729
|
+
plain(`Status: ${res.status} (${duration}ms)`)
|
|
730
|
+
plain()
|
|
666
731
|
|
|
667
732
|
// Try to pretty-print JSON
|
|
668
733
|
try {
|
|
669
734
|
const json = JSON.parse(responseBody)
|
|
670
|
-
|
|
735
|
+
plain(JSON.stringify(json, null, 2))
|
|
671
736
|
} catch {
|
|
672
|
-
|
|
737
|
+
plain(responseBody)
|
|
673
738
|
}
|
|
674
739
|
} catch (err) {
|
|
675
740
|
if (err instanceof TypeError && (err as Error).message.includes("fetch")) {
|
|
676
|
-
|
|
677
|
-
|
|
741
|
+
error(`Cannot reach ${url}`)
|
|
742
|
+
error("Is the function server running? Start it with: npx supatype functions serve")
|
|
678
743
|
} else {
|
|
679
|
-
|
|
744
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
680
745
|
}
|
|
681
746
|
process.exit(1)
|
|
682
747
|
}
|
|
@@ -692,32 +757,32 @@ async function envList(cwd: string): Promise<void> {
|
|
|
692
757
|
// Show local env vars
|
|
693
758
|
const envPath = resolve(resolveFunctionsDir(cwd, "read"), ENV_LOCAL)
|
|
694
759
|
if (!existsSync(envPath)) {
|
|
695
|
-
|
|
760
|
+
info("No environment variables configured.")
|
|
696
761
|
return
|
|
697
762
|
}
|
|
698
763
|
|
|
699
764
|
const lines = readFileSync(envPath, "utf8").split("\n")
|
|
700
|
-
|
|
765
|
+
plain("Local environment variables:\n")
|
|
701
766
|
for (const line of lines) {
|
|
702
767
|
const trimmed = line.trim()
|
|
703
768
|
if (!trimmed || trimmed.startsWith("#")) continue
|
|
704
769
|
const eqIdx = trimmed.indexOf("=")
|
|
705
770
|
if (eqIdx > 0) {
|
|
706
771
|
const key = trimmed.slice(0, eqIdx)
|
|
707
|
-
|
|
772
|
+
plain(` ${key} = ••••••••`)
|
|
708
773
|
}
|
|
709
774
|
}
|
|
710
775
|
return
|
|
711
776
|
}
|
|
712
777
|
|
|
713
|
-
const token = getCloudToken()
|
|
778
|
+
const token = getCloudToken(cwd)
|
|
714
779
|
if (!token) {
|
|
715
|
-
|
|
780
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
716
781
|
process.exit(1)
|
|
717
782
|
}
|
|
718
783
|
|
|
719
784
|
try {
|
|
720
|
-
const res = await fetch(`${getCloudApiUrl()}/api/v1/projects/${linked.ref}/functions/env`, {
|
|
785
|
+
const res = await fetch(`${getCloudApiUrl(cwd)}/api/v1/projects/${linked.ref}/functions/env`, {
|
|
721
786
|
headers: {
|
|
722
787
|
Authorization: `Bearer ${token}`,
|
|
723
788
|
"X-Org-Id": linked.orgId ?? "",
|
|
@@ -726,23 +791,23 @@ async function envList(cwd: string): Promise<void> {
|
|
|
726
791
|
})
|
|
727
792
|
|
|
728
793
|
if (!res.ok) {
|
|
729
|
-
|
|
794
|
+
error(`Failed to list env vars: ${res.statusText}`)
|
|
730
795
|
process.exit(1)
|
|
731
796
|
}
|
|
732
797
|
|
|
733
798
|
const { data } = await res.json() as { data: string[] }
|
|
734
799
|
|
|
735
800
|
if (data.length === 0) {
|
|
736
|
-
|
|
801
|
+
info("No environment variables set.")
|
|
737
802
|
return
|
|
738
803
|
}
|
|
739
804
|
|
|
740
|
-
|
|
805
|
+
plain("Environment variables (values masked):\n")
|
|
741
806
|
for (const key of data) {
|
|
742
|
-
|
|
807
|
+
plain(` ${key} = ••••••••`)
|
|
743
808
|
}
|
|
744
809
|
} catch (err) {
|
|
745
|
-
|
|
810
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
746
811
|
process.exit(1)
|
|
747
812
|
}
|
|
748
813
|
}
|
|
@@ -750,7 +815,7 @@ async function envList(cwd: string): Promise<void> {
|
|
|
750
815
|
async function envSet(cwd: string, keyvalue: string): Promise<void> {
|
|
751
816
|
const eqIdx = keyvalue.indexOf("=")
|
|
752
817
|
if (eqIdx <= 0) {
|
|
753
|
-
|
|
818
|
+
error("Invalid format. Use: npx supatype functions env set KEY=value")
|
|
754
819
|
process.exit(1)
|
|
755
820
|
}
|
|
756
821
|
|
|
@@ -774,18 +839,18 @@ async function envSet(cwd: string, keyvalue: string): Promise<void> {
|
|
|
774
839
|
}
|
|
775
840
|
|
|
776
841
|
writeFileSync(envPath, content, "utf8")
|
|
777
|
-
|
|
842
|
+
info(`Set ${key} in local env file.`)
|
|
778
843
|
return
|
|
779
844
|
}
|
|
780
845
|
|
|
781
|
-
const token = getCloudToken()
|
|
846
|
+
const token = getCloudToken(cwd)
|
|
782
847
|
if (!token) {
|
|
783
|
-
|
|
848
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
784
849
|
process.exit(1)
|
|
785
850
|
}
|
|
786
851
|
|
|
787
852
|
try {
|
|
788
|
-
const res = await fetch(`${getCloudApiUrl()}/api/v1/projects/${linked.ref}/functions/env`, {
|
|
853
|
+
const res = await fetch(`${getCloudApiUrl(cwd)}/api/v1/projects/${linked.ref}/functions/env`, {
|
|
789
854
|
method: "POST",
|
|
790
855
|
headers: {
|
|
791
856
|
Authorization: `Bearer ${token}`,
|
|
@@ -798,13 +863,13 @@ async function envSet(cwd: string, keyvalue: string): Promise<void> {
|
|
|
798
863
|
|
|
799
864
|
if (!res.ok) {
|
|
800
865
|
const body = await res.json().catch(() => ({})) as Record<string, string>
|
|
801
|
-
|
|
866
|
+
error(`Failed to set env var: ${body["message"] ?? res.statusText}`)
|
|
802
867
|
process.exit(1)
|
|
803
868
|
}
|
|
804
869
|
|
|
805
|
-
|
|
870
|
+
info(`Set ${key} for project ${linked.ref}.`)
|
|
806
871
|
} catch (err) {
|
|
807
|
-
|
|
872
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
808
873
|
process.exit(1)
|
|
809
874
|
}
|
|
810
875
|
}
|
|
@@ -816,7 +881,7 @@ async function envUnset(cwd: string, key: string): Promise<void> {
|
|
|
816
881
|
if (!linked) {
|
|
817
882
|
const envPath = resolve(resolveFunctionsDir(cwd, "read"), ENV_LOCAL)
|
|
818
883
|
if (!existsSync(envPath)) {
|
|
819
|
-
|
|
884
|
+
error("No local env file found.")
|
|
820
885
|
process.exit(1)
|
|
821
886
|
}
|
|
822
887
|
|
|
@@ -824,18 +889,18 @@ async function envUnset(cwd: string, key: string): Promise<void> {
|
|
|
824
889
|
const regex = new RegExp(`^${key}=.*\n?`, "m")
|
|
825
890
|
content = content.replace(regex, "")
|
|
826
891
|
writeFileSync(envPath, content, "utf8")
|
|
827
|
-
|
|
892
|
+
info(`Removed ${key} from local env file.`)
|
|
828
893
|
return
|
|
829
894
|
}
|
|
830
895
|
|
|
831
|
-
const token = getCloudToken()
|
|
896
|
+
const token = getCloudToken(cwd)
|
|
832
897
|
if (!token) {
|
|
833
|
-
|
|
898
|
+
error("Not logged in. Run: npx supatype cloud login")
|
|
834
899
|
process.exit(1)
|
|
835
900
|
}
|
|
836
901
|
|
|
837
902
|
try {
|
|
838
|
-
const res = await fetch(`${getCloudApiUrl()}/api/v1/projects/${linked.ref}/functions/env/${key}`, {
|
|
903
|
+
const res = await fetch(`${getCloudApiUrl(cwd)}/api/v1/projects/${linked.ref}/functions/env/${key}`, {
|
|
839
904
|
method: "DELETE",
|
|
840
905
|
headers: {
|
|
841
906
|
Authorization: `Bearer ${token}`,
|
|
@@ -846,13 +911,13 @@ async function envUnset(cwd: string, key: string): Promise<void> {
|
|
|
846
911
|
|
|
847
912
|
if (!res.ok) {
|
|
848
913
|
const body = await res.json().catch(() => ({})) as Record<string, string>
|
|
849
|
-
|
|
914
|
+
error(`Failed to unset env var: ${body["message"] ?? res.statusText}`)
|
|
850
915
|
process.exit(1)
|
|
851
916
|
}
|
|
852
917
|
|
|
853
|
-
|
|
918
|
+
info(`Removed ${key} for project ${linked.ref}.`)
|
|
854
919
|
} catch (err) {
|
|
855
|
-
|
|
920
|
+
error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
|
|
856
921
|
process.exit(1)
|
|
857
922
|
}
|
|
858
923
|
}
|
|
@@ -860,32 +925,29 @@ async function envUnset(cwd: string, key: string): Promise<void> {
|
|
|
860
925
|
// ─── Cloud helpers (lazy loaded) ─────────────────────────────────────────────
|
|
861
926
|
|
|
862
927
|
interface CloudHelpers {
|
|
863
|
-
getLinkedProject(cwd: string): { ref: string; orgId?: string } | null
|
|
864
|
-
getCloudToken(): string | null
|
|
865
|
-
getCloudApiUrl(): string
|
|
928
|
+
getLinkedProject(cwd: string): { ref: string; orgId?: string | undefined; kind?: string } | null
|
|
929
|
+
getCloudToken(cwd: string): string | null
|
|
930
|
+
getCloudApiUrl(cwd: string): string
|
|
866
931
|
}
|
|
867
932
|
|
|
868
933
|
async function loadCloudHelpers(): Promise<CloudHelpers> {
|
|
869
|
-
// These helpers read the local .supatype/linked.json and auth token
|
|
870
934
|
return {
|
|
871
|
-
|
|
872
|
-
const
|
|
873
|
-
if (!
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
return ref ? { ref, ...(orgId !== undefined ? { orgId } : {}) } : null
|
|
879
|
-
} catch {
|
|
880
|
-
return null
|
|
935
|
+
getLinkedProject(cwd: string): { ref: string; orgId?: string | undefined; kind?: string } | null {
|
|
936
|
+
const link = loadProjectLink(cwd)
|
|
937
|
+
if (!link?.projectRef) return null
|
|
938
|
+
return {
|
|
939
|
+
ref: link.projectRef,
|
|
940
|
+
kind: link.kind,
|
|
941
|
+
...(link.orgId !== undefined ? { orgId: link.orgId } : {}),
|
|
881
942
|
}
|
|
882
943
|
},
|
|
883
944
|
|
|
884
|
-
getCloudToken(): string | null {
|
|
885
|
-
// Check env first, then config file
|
|
945
|
+
getCloudToken(cwd: string): string | null {
|
|
886
946
|
if (process.env["SUPATYPE_ACCESS_TOKEN"]) {
|
|
887
947
|
return process.env["SUPATYPE_ACCESS_TOKEN"]
|
|
888
948
|
}
|
|
949
|
+
const link = loadProjectLink(cwd)
|
|
950
|
+
if (link?.token) return link.token
|
|
889
951
|
const tokenPath = resolve(
|
|
890
952
|
process.env["HOME"] ?? process.env["USERPROFILE"] ?? "~",
|
|
891
953
|
".supatype/token",
|
|
@@ -894,7 +956,9 @@ async function loadCloudHelpers(): Promise<CloudHelpers> {
|
|
|
894
956
|
return readFileSync(tokenPath, "utf8").trim() || null
|
|
895
957
|
},
|
|
896
958
|
|
|
897
|
-
getCloudApiUrl(): string {
|
|
959
|
+
getCloudApiUrl(cwd: string): string {
|
|
960
|
+
const link = loadProjectLink(cwd)
|
|
961
|
+
if (link?.cloudApiUrl) return link.cloudApiUrl
|
|
898
962
|
return process.env["SUPATYPE_API_URL"] ?? "https://api.supatype.com"
|
|
899
963
|
},
|
|
900
964
|
}
|