@supatype/cli 0.1.0-alpha.10
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 +4 -0
- package/.turbo/turbo-test.log +221 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/bin/dev-entry.ts +2 -0
- package/bin/supatype.js +5 -0
- package/dist/app/framework.d.ts +44 -0
- package/dist/app/framework.d.ts.map +1 -0
- package/dist/app/framework.js +200 -0
- package/dist/app/framework.js.map +1 -0
- package/dist/app/proxy-dev-app.d.ts +13 -0
- package/dist/app/proxy-dev-app.d.ts.map +1 -0
- package/dist/app/proxy-dev-app.js +54 -0
- package/dist/app/proxy-dev-app.js.map +1 -0
- package/dist/app-config.d.ts +7 -0
- package/dist/app-config.d.ts.map +1 -0
- package/dist/app-config.js +113 -0
- package/dist/app-config.js.map +1 -0
- package/dist/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/dist/augmentation-generator.d.ts +2 -0
- package/dist/augmentation-generator.d.ts.map +1 -0
- package/dist/augmentation-generator.js +111 -0
- package/dist/augmentation-generator.js.map +1 -0
- package/dist/binary-cache.d.ts +98 -0
- package/dist/binary-cache.d.ts.map +1 -0
- package/dist/binary-cache.js +687 -0
- package/dist/binary-cache.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/admin.d.ts +4 -0
- package/dist/commands/admin.d.ts.map +1 -0
- package/dist/commands/admin.js +271 -0
- package/dist/commands/admin.js.map +1 -0
- package/dist/commands/app.d.ts +3 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +82 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/cache.d.ts +6 -0
- package/dist/commands/cache.d.ts.map +1 -0
- package/dist/commands/cache.js +105 -0
- package/dist/commands/cache.js.map +1 -0
- package/dist/commands/cloud.d.ts +23 -0
- package/dist/commands/cloud.d.ts.map +1 -0
- package/dist/commands/cloud.js +254 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/db.d.ts +8 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +116 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/deploy-types.d.ts +14 -0
- package/dist/commands/deploy-types.d.ts.map +1 -0
- package/dist/commands/deploy-types.js +38 -0
- package/dist/commands/deploy-types.js.map +1 -0
- package/dist/commands/deploy.d.ts +15 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +322 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +14 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +806 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +54 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/engine.d.ts +7 -0
- package/dist/commands/engine.d.ts.map +1 -0
- package/dist/commands/engine.js +27 -0
- package/dist/commands/engine.js.map +1 -0
- package/dist/commands/functions.d.ts +3 -0
- package/dist/commands/functions.d.ts.map +1 -0
- package/dist/commands/functions.js +749 -0
- package/dist/commands/functions.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +38 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +228 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/keys.d.ts +4 -0
- package/dist/commands/keys.d.ts.map +1 -0
- package/dist/commands/keys.js +57 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/logs.d.ts +6 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +52 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/migrate-from-v1.d.ts +5 -0
- package/dist/commands/migrate-from-v1.d.ts.map +1 -0
- package/dist/commands/migrate-from-v1.js +125 -0
- package/dist/commands/migrate-from-v1.js.map +1 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +75 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/pg.d.ts +8 -0
- package/dist/commands/pg.d.ts.map +1 -0
- package/dist/commands/pg.js +102 -0
- package/dist/commands/pg.js.map +1 -0
- package/dist/commands/plugins.d.ts +3 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +431 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/pull.d.ts +3 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +12 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +3 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +179 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/seed.d.ts +5 -0
- package/dist/commands/seed.d.ts.map +1 -0
- package/dist/commands/seed.js +55 -0
- package/dist/commands/seed.js.map +1 -0
- package/dist/commands/self-host.d.ts +9 -0
- package/dist/commands/self-host.d.ts.map +1 -0
- package/dist/commands/self-host.js +310 -0
- package/dist/commands/self-host.js.map +1 -0
- package/dist/commands/self-update.d.ts +9 -0
- package/dist/commands/self-update.d.ts.map +1 -0
- package/dist/commands/self-update.js +33 -0
- package/dist/commands/self-update.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +70 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/types.d.ts +3 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +62 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +118 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/components.d.ts +5 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +3 -0
- package/dist/components.js.map +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +134 -0
- package/dist/config.js.map +1 -0
- package/dist/dev-compose.d.ts +19 -0
- package/dist/dev-compose.d.ts.map +1 -0
- package/dist/dev-compose.js +468 -0
- package/dist/dev-compose.js.map +1 -0
- 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 +57 -0
- package/dist/dev-logo.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 +9 -0
- package/dist/dev-shutdown.d.ts.map +1 -0
- package/dist/dev-shutdown.js +50 -0
- package/dist/dev-shutdown.js.map +1 -0
- package/dist/dev-task-colors.d.ts +14 -0
- package/dist/dev-task-colors.d.ts.map +1 -0
- package/dist/dev-task-colors.js +44 -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 +4 -0
- package/dist/diff-output.d.ts.map +1 -0
- package/dist/diff-output.js +12 -0
- package/dist/diff-output.js.map +1 -0
- package/dist/docker-postgres.d.ts +57 -0
- package/dist/docker-postgres.d.ts.map +1 -0
- package/dist/docker-postgres.js +208 -0
- package/dist/docker-postgres.js.map +1 -0
- package/dist/engine-client.d.ts +69 -0
- package/dist/engine-client.d.ts.map +1 -0
- package/dist/engine-client.js +157 -0
- package/dist/engine-client.js.map +1 -0
- package/dist/engine-push-output.d.ts +16 -0
- package/dist/engine-push-output.d.ts.map +1 -0
- package/dist/engine-push-output.js +61 -0
- package/dist/engine-push-output.js.map +1 -0
- package/dist/ensure-binary.d.ts +7 -0
- package/dist/ensure-binary.d.ts.map +1 -0
- package/dist/ensure-binary.js +17 -0
- package/dist/ensure-binary.js.map +1 -0
- package/dist/functions-router-gen.d.ts +14 -0
- package/dist/functions-router-gen.d.ts.map +1 -0
- package/dist/functions-router-gen.js +199 -0
- package/dist/functions-router-gen.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.d.ts +3 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +13 -0
- package/dist/jwt.js.map +1 -0
- package/dist/kong-config.d.ts +25 -0
- package/dist/kong-config.d.ts.map +1 -0
- package/dist/kong-config.js +71 -0
- package/dist/kong-config.js.map +1 -0
- package/dist/local-gateway.d.ts +7 -0
- package/dist/local-gateway.d.ts.map +1 -0
- package/dist/local-gateway.js +9 -0
- package/dist/local-gateway.js.map +1 -0
- package/dist/local-storage.d.ts +8 -0
- package/dist/local-storage.d.ts.map +1 -0
- package/dist/local-storage.js +14 -0
- package/dist/local-storage.js.map +1 -0
- package/dist/pgbouncer-userlist.d.ts +5 -0
- package/dist/pgbouncer-userlist.d.ts.map +1 -0
- package/dist/pgbouncer-userlist.js +14 -0
- package/dist/pgbouncer-userlist.js.map +1 -0
- package/dist/postgres-ctl.d.ts +44 -0
- package/dist/postgres-ctl.d.ts.map +1 -0
- package/dist/postgres-ctl.js +137 -0
- package/dist/postgres-ctl.js.map +1 -0
- package/dist/process-manager.d.ts +49 -0
- package/dist/process-manager.d.ts.map +1 -0
- package/dist/process-manager.js +177 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/project-config.d.ts +238 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +159 -0
- package/dist/project-config.js.map +1 -0
- package/dist/pull-utils.d.ts +31 -0
- package/dist/pull-utils.d.ts.map +1 -0
- package/dist/pull-utils.js +77 -0
- package/dist/pull-utils.js.map +1 -0
- package/dist/release-pins.d.ts +7 -0
- package/dist/release-pins.d.ts.map +1 -0
- package/dist/release-pins.js +27 -0
- package/dist/release-pins.js.map +1 -0
- package/dist/release-public-key.d.ts +8 -0
- package/dist/release-public-key.d.ts.map +1 -0
- package/dist/release-public-key.js +13 -0
- package/dist/release-public-key.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 +34 -0
- package/dist/runtime-routes.d.ts.map +1 -0
- package/dist/runtime-routes.js +252 -0
- package/dist/runtime-routes.js.map +1 -0
- package/dist/schema-ast-v2.d.ts +127 -0
- package/dist/schema-ast-v2.d.ts.map +1 -0
- package/dist/schema-ast-v2.js +226 -0
- package/dist/schema-ast-v2.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +11 -0
- package/dist/scripts/postinstall.d.ts.map +1 -0
- package/dist/scripts/postinstall.js +47 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/dist/seed.d.ts +8 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +32 -0
- package/dist/seed.js.map +1 -0
- package/dist/self-host-compose.d.ts +43 -0
- package/dist/self-host-compose.d.ts.map +1 -0
- package/dist/self-host-compose.js +400 -0
- package/dist/self-host-compose.js.map +1 -0
- package/dist/storage-provision.d.ts +24 -0
- package/dist/storage-provision.d.ts.map +1 -0
- package/dist/storage-provision.js +44 -0
- package/dist/storage-provision.js.map +1 -0
- package/dist/studio-admin-roles.d.ts +7 -0
- package/dist/studio-admin-roles.d.ts.map +1 -0
- package/dist/studio-admin-roles.js +14 -0
- package/dist/studio-admin-roles.js.map +1 -0
- package/dist/studio-dev-server.d.ts +22 -0
- package/dist/studio-dev-server.d.ts.map +1 -0
- package/dist/studio-dev-server.js +28 -0
- package/dist/studio-dev-server.js.map +1 -0
- 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.d.ts +26 -0
- package/dist/systemd.d.ts.map +1 -0
- package/dist/systemd.js +102 -0
- package/dist/systemd.js.map +1 -0
- package/dist/tsx-runner.d.ts +18 -0
- package/dist/tsx-runner.d.ts.map +1 -0
- package/dist/tsx-runner.js +69 -0
- package/dist/tsx-runner.js.map +1 -0
- package/dist/type-extractor.d.ts +4 -0
- package/dist/type-extractor.d.ts.map +1 -0
- package/dist/type-extractor.js +1213 -0
- package/dist/type-extractor.js.map +1 -0
- package/dist/type-resolver.d.ts +33 -0
- package/dist/type-resolver.d.ts.map +1 -0
- package/dist/type-resolver.js +338 -0
- package/dist/type-resolver.js.map +1 -0
- package/package.json +41 -0
- package/releases/deno/VERSION +1 -0
- package/scripts/mirror-deno-release.sh +76 -0
- package/src/TYPE-RESOLUTION.md +294 -0
- package/src/app/framework.ts +249 -0
- package/src/app/proxy-dev-app.ts +68 -0
- package/src/app-config.ts +128 -0
- package/src/augmentation-generator.ts +126 -0
- package/src/binary-cache.ts +845 -0
- package/src/cli.ts +63 -0
- package/src/commands/admin.ts +372 -0
- package/src/commands/app.ts +97 -0
- package/src/commands/cache.ts +117 -0
- package/src/commands/cloud.ts +325 -0
- package/src/commands/db.ts +136 -0
- package/src/commands/deploy-types.ts +49 -0
- package/src/commands/deploy.ts +400 -0
- package/src/commands/dev.ts +1009 -0
- package/src/commands/diff.ts +63 -0
- package/src/commands/engine.ts +30 -0
- package/src/commands/functions.ts +901 -0
- package/src/commands/generate.ts +44 -0
- package/src/commands/init.ts +253 -0
- package/src/commands/keys.ts +66 -0
- package/src/commands/logs.ts +58 -0
- package/src/commands/migrate-from-v1.ts +131 -0
- package/src/commands/migrate.ts +87 -0
- package/src/commands/pg.ts +133 -0
- package/src/commands/plugins.ts +508 -0
- package/src/commands/pull.ts +17 -0
- package/src/commands/push.ts +226 -0
- package/src/commands/seed.ts +68 -0
- package/src/commands/self-host.ts +364 -0
- package/src/commands/self-update.ts +45 -0
- package/src/commands/status.ts +84 -0
- package/src/commands/types.ts +76 -0
- package/src/commands/update.ts +136 -0
- package/src/components.ts +6 -0
- package/src/config.ts +223 -0
- package/src/dev-compose.ts +583 -0
- package/src/dev-log-bus.ts +101 -0
- package/src/dev-log-filter.ts +32 -0
- package/src/dev-logo.ts +62 -0
- package/src/dev-session.ts +130 -0
- package/src/dev-shutdown.ts +54 -0
- package/src/dev-task-colors.ts +47 -0
- package/src/dev-tui.ts +232 -0
- package/src/diff-output.ts +12 -0
- package/src/docker-postgres.ts +295 -0
- package/src/engine-client.ts +236 -0
- package/src/engine-push-output.ts +71 -0
- package/src/ensure-binary.ts +28 -0
- package/src/functions-router-gen.ts +224 -0
- package/src/index.ts +11 -0
- package/src/jwt.ts +14 -0
- package/src/kong-config.ts +93 -0
- package/src/local-gateway.ts +9 -0
- package/src/local-storage.ts +14 -0
- package/src/pgbouncer-userlist.ts +15 -0
- package/src/postgres-ctl.ts +171 -0
- package/src/process-manager.ts +220 -0
- package/src/project-config.ts +388 -0
- package/src/pull-utils.ts +81 -0
- package/src/release-pins.ts +31 -0
- package/src/release-public-key.ts +12 -0
- package/src/restore-system-relation-targets.ts +45 -0
- package/src/runtime-routes.ts +291 -0
- package/src/schema-ast-v2.ts +324 -0
- package/src/scripts/postinstall.ts +51 -0
- package/src/seed.ts +43 -0
- package/src/self-host-compose.ts +452 -0
- package/src/storage-provision.ts +58 -0
- package/src/studio-admin-roles.ts +16 -0
- package/src/studio-dev-server.ts +53 -0
- package/src/supatype-eval-1781522769253.mts +1 -0
- package/src/systemd.ts +137 -0
- package/src/tsx-runner.ts +89 -0
- package/src/type-extractor.ts +1479 -0
- package/src/type-resolver.ts +457 -0
- package/tests/app-command.test.ts +54 -0
- package/tests/augmentation-generator.test.ts +59 -0
- package/tests/binary-cache-cloud-overrides.test.ts +123 -0
- package/tests/cached-artifact-format.test.ts +84 -0
- package/tests/cli-help.test.ts +133 -0
- package/tests/config.test.ts +252 -0
- package/tests/dev-ui.test.ts +139 -0
- package/tests/docker-postgres.test.ts +39 -0
- package/tests/engine-distribution.test.ts +418 -0
- package/tests/engine-push-output.test.ts +67 -0
- package/tests/ensure-binary.test.ts +59 -0
- package/tests/init.test.ts +127 -0
- package/tests/keys.test.ts +160 -0
- package/tests/migrate-from-v1.test.ts +29 -0
- package/tests/normalize-admin-config.test.ts +48 -0
- package/tests/pg-spawn-env.test.ts +18 -0
- package/tests/postgres-archive-tag.test.ts +9 -0
- package/tests/proxy-dev-app.test.ts +33 -0
- package/tests/pull-utils.test.ts +150 -0
- package/tests/release-pins.test.ts +28 -0
- package/tests/runtime-contract.test.ts +370 -0
- package/tests/seed-discover.test.ts +31 -0
- package/tests/studio-admin-roles.test.ts +27 -0
- package/tests/tsconfig.json +9 -0
- package/tests/tsx-runner.test.ts +66 -0
- package/tests/type-extractor.test.ts +985 -0
- package/tests/type-resolver.test.ts +59 -0
- package/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +12 -0
package/src/cli.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Command } from "commander"
|
|
2
|
+
import { registerInit } from "./commands/init.js"
|
|
3
|
+
import { registerDev } from "./commands/dev.js"
|
|
4
|
+
import { registerCache } from "./commands/cache.js"
|
|
5
|
+
import { registerUpdate } from "./commands/update.js"
|
|
6
|
+
import { registerPg } from "./commands/pg.js"
|
|
7
|
+
import { registerPush } from "./commands/push.js"
|
|
8
|
+
import { registerDiff } from "./commands/diff.js"
|
|
9
|
+
import { registerPull } from "./commands/pull.js"
|
|
10
|
+
import { registerGenerate } from "./commands/generate.js"
|
|
11
|
+
import { registerMigrate } from "./commands/migrate.js"
|
|
12
|
+
import { registerSeed } from "./commands/seed.js"
|
|
13
|
+
import { registerKeys } from "./commands/keys.js"
|
|
14
|
+
import { registerApp } from "./commands/app.js"
|
|
15
|
+
import { registerSelfHost } from "./commands/self-host.js"
|
|
16
|
+
import { registerCloud } from "./commands/cloud.js"
|
|
17
|
+
import { registerEngine } from "./commands/engine.js"
|
|
18
|
+
import { registerDb } from "./commands/db.js"
|
|
19
|
+
import { registerDeploy } from "./commands/deploy.js"
|
|
20
|
+
import { registerStatus } from "./commands/status.js"
|
|
21
|
+
import { registerLogs } from "./commands/logs.js"
|
|
22
|
+
import { registerAdmin } from "./commands/admin.js"
|
|
23
|
+
import { registerFunctions } from "./commands/functions.js"
|
|
24
|
+
import { registerPlugins } from "./commands/plugins.js"
|
|
25
|
+
import { registerTypes } from "./commands/types.js"
|
|
26
|
+
import { registerMigrateFromV1 } from "./commands/migrate-from-v1.js"
|
|
27
|
+
import { registerSelfUpdate } from "./commands/self-update.js"
|
|
28
|
+
|
|
29
|
+
export function run(): void {
|
|
30
|
+
const program = new Command()
|
|
31
|
+
.name("supatype")
|
|
32
|
+
.description("Supatype — schema-first Postgres API")
|
|
33
|
+
.version("0.1.0")
|
|
34
|
+
|
|
35
|
+
registerInit(program)
|
|
36
|
+
registerDev(program)
|
|
37
|
+
registerCache(program)
|
|
38
|
+
registerSelfUpdate(program)
|
|
39
|
+
registerUpdate(program)
|
|
40
|
+
registerPg(program)
|
|
41
|
+
registerPush(program)
|
|
42
|
+
registerDiff(program)
|
|
43
|
+
registerPull(program)
|
|
44
|
+
registerGenerate(program)
|
|
45
|
+
registerMigrate(program)
|
|
46
|
+
registerSeed(program)
|
|
47
|
+
registerKeys(program)
|
|
48
|
+
registerApp(program)
|
|
49
|
+
registerSelfHost(program)
|
|
50
|
+
registerCloud(program)
|
|
51
|
+
registerEngine(program)
|
|
52
|
+
registerDb(program)
|
|
53
|
+
registerDeploy(program)
|
|
54
|
+
registerStatus(program)
|
|
55
|
+
registerLogs(program)
|
|
56
|
+
registerAdmin(program)
|
|
57
|
+
registerFunctions(program)
|
|
58
|
+
registerPlugins(program)
|
|
59
|
+
registerTypes(program)
|
|
60
|
+
registerMigrateFromV1(program)
|
|
61
|
+
|
|
62
|
+
program.parse()
|
|
63
|
+
}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
// ─── Admin panel CLI commands (Gap Appendices task 48) ──────────────────────
|
|
2
|
+
//
|
|
3
|
+
// `npx supatype admin create-user` — create an admin user in the project's
|
|
4
|
+
// {ref}_auth.users table. Used for initial setup and ongoing admin management.
|
|
5
|
+
|
|
6
|
+
import type { Command } from "commander"
|
|
7
|
+
import { createInterface } from "node:readline"
|
|
8
|
+
import { randomBytes, scrypt } from "node:crypto"
|
|
9
|
+
import { promisify } from "node:util"
|
|
10
|
+
import { loadConfig } from "../config.js"
|
|
11
|
+
import { connectionString } from "../project-config.js"
|
|
12
|
+
import { signJwt } from "../jwt.js"
|
|
13
|
+
|
|
14
|
+
const scryptAsync = promisify(scrypt)
|
|
15
|
+
|
|
16
|
+
export function registerAdmin(program: Command): void {
|
|
17
|
+
const adminCmd = program
|
|
18
|
+
.command("admin")
|
|
19
|
+
.description("Manage admin panel users and configuration")
|
|
20
|
+
|
|
21
|
+
adminCmd
|
|
22
|
+
.command("create-user")
|
|
23
|
+
.description("Create an admin user for the admin panel")
|
|
24
|
+
.option("--email <email>", "Admin user email address")
|
|
25
|
+
.option("--password <password>", "Admin user password (prompted if not provided)")
|
|
26
|
+
.option("--role <role>", "Admin role to assign", "admin")
|
|
27
|
+
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
28
|
+
.action(
|
|
29
|
+
async (opts: {
|
|
30
|
+
email?: string
|
|
31
|
+
password?: string
|
|
32
|
+
role: string
|
|
33
|
+
connection?: string
|
|
34
|
+
}) => {
|
|
35
|
+
const cwd = process.cwd()
|
|
36
|
+
const config = loadConfig(cwd)
|
|
37
|
+
const connection = opts.connection ?? connectionString(config)
|
|
38
|
+
|
|
39
|
+
const email = opts.email ?? (await prompt("Admin email: "))
|
|
40
|
+
if (!email || !email.includes("@")) {
|
|
41
|
+
console.error("A valid email address is required.")
|
|
42
|
+
process.exit(1)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const password =
|
|
46
|
+
opts.password ?? (await prompt("Admin password (min 8 chars): "))
|
|
47
|
+
if (!password || password.length < 8) {
|
|
48
|
+
console.error("Password must be at least 8 characters.")
|
|
49
|
+
process.exit(1)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const role = opts.role
|
|
53
|
+
|
|
54
|
+
console.log(`\nCreating admin user: ${email} (role: ${role})...`)
|
|
55
|
+
|
|
56
|
+
// We use pg directly to insert into the auth.users table
|
|
57
|
+
const pg = await importPg()
|
|
58
|
+
const pool = new pg.Pool({ connectionString: connection, max: 2 })
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
// Ensure the auth schema and users table exist
|
|
62
|
+
await pool.query(`
|
|
63
|
+
CREATE SCHEMA IF NOT EXISTS auth;
|
|
64
|
+
|
|
65
|
+
CREATE TABLE IF NOT EXISTS auth.users (
|
|
66
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
67
|
+
instance_id UUID,
|
|
68
|
+
aud TEXT DEFAULT 'authenticated',
|
|
69
|
+
role TEXT DEFAULT 'authenticated',
|
|
70
|
+
email TEXT UNIQUE,
|
|
71
|
+
encrypted_password TEXT,
|
|
72
|
+
email_confirmed_at TIMESTAMPTZ DEFAULT now(),
|
|
73
|
+
raw_app_meta_data JSONB DEFAULT '{}',
|
|
74
|
+
raw_user_meta_data JSONB DEFAULT '{}',
|
|
75
|
+
created_at TIMESTAMPTZ DEFAULT now(),
|
|
76
|
+
updated_at TIMESTAMPTZ DEFAULT now(),
|
|
77
|
+
confirmation_token TEXT DEFAULT '',
|
|
78
|
+
recovery_token TEXT DEFAULT '',
|
|
79
|
+
email_change_token_new TEXT DEFAULT '',
|
|
80
|
+
email_change TEXT DEFAULT ''
|
|
81
|
+
);
|
|
82
|
+
`)
|
|
83
|
+
|
|
84
|
+
// Check if user already exists
|
|
85
|
+
const existing = await pool.query(
|
|
86
|
+
`SELECT id FROM auth.users WHERE email = $1`,
|
|
87
|
+
[email.toLowerCase()],
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if (existing.rows.length > 0) {
|
|
91
|
+
console.error(
|
|
92
|
+
`\nUser with email "${email}" already exists.`,
|
|
93
|
+
)
|
|
94
|
+
console.log(
|
|
95
|
+
`To update their role, use: supatype admin set-role --email ${email} --role ${role}`,
|
|
96
|
+
)
|
|
97
|
+
process.exit(1)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Hash the password (bcrypt-style for GoTrue compatibility)
|
|
101
|
+
const passwordHash = await hashPassword(password)
|
|
102
|
+
|
|
103
|
+
// Insert the admin user with the admin role in app_metadata
|
|
104
|
+
const appMetadata = JSON.stringify({ role, provider: "email", providers: ["email"] })
|
|
105
|
+
const userMetadata = JSON.stringify({})
|
|
106
|
+
|
|
107
|
+
const result = await pool.query(
|
|
108
|
+
`INSERT INTO auth.users (
|
|
109
|
+
email, encrypted_password, role, aud,
|
|
110
|
+
raw_app_meta_data, raw_user_meta_data,
|
|
111
|
+
email_confirmed_at, created_at, updated_at
|
|
112
|
+
) VALUES (
|
|
113
|
+
$1, $2, 'authenticated', 'authenticated',
|
|
114
|
+
$3::jsonb, $4::jsonb,
|
|
115
|
+
now(), now(), now()
|
|
116
|
+
) RETURNING id, email`,
|
|
117
|
+
[email.toLowerCase(), passwordHash, appMetadata, userMetadata],
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
const user = result.rows[0] as { id: string; email: string }
|
|
121
|
+
|
|
122
|
+
console.log(`\nAdmin user created successfully.`)
|
|
123
|
+
console.log(` ID: ${user.id}`)
|
|
124
|
+
console.log(` Email: ${user.email}`)
|
|
125
|
+
console.log(` Role: ${role}`)
|
|
126
|
+
console.log(
|
|
127
|
+
`\nThis user can now log in to the admin panel at /admin\n`,
|
|
128
|
+
)
|
|
129
|
+
} catch (err) {
|
|
130
|
+
const message =
|
|
131
|
+
err instanceof Error ? err.message : "Unknown error"
|
|
132
|
+
console.error(`\nFailed to create admin user: ${message}`)
|
|
133
|
+
process.exit(1)
|
|
134
|
+
} finally {
|
|
135
|
+
await pool.end()
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
adminCmd
|
|
141
|
+
.command("set-role")
|
|
142
|
+
.description("Change an existing user's admin role")
|
|
143
|
+
.requiredOption("--email <email>", "User email address")
|
|
144
|
+
.requiredOption("--role <role>", "New role to assign")
|
|
145
|
+
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
146
|
+
.action(
|
|
147
|
+
async (opts: { email: string; role: string; connection?: string }) => {
|
|
148
|
+
const cwd = process.cwd()
|
|
149
|
+
const config = loadConfig(cwd)
|
|
150
|
+
const connection = opts.connection ?? connectionString(config)
|
|
151
|
+
|
|
152
|
+
const pg = await importPg()
|
|
153
|
+
const pool = new pg.Pool({ connectionString: connection, max: 2 })
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const result = await pool.query(
|
|
157
|
+
`UPDATE auth.users
|
|
158
|
+
SET raw_app_meta_data = raw_app_meta_data || $1::jsonb,
|
|
159
|
+
updated_at = now()
|
|
160
|
+
WHERE email = $2
|
|
161
|
+
RETURNING id, email, raw_app_meta_data`,
|
|
162
|
+
[JSON.stringify({ role: opts.role }), opts.email.toLowerCase()],
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if (result.rows.length === 0) {
|
|
166
|
+
console.error(`\nNo user found with email "${opts.email}".`)
|
|
167
|
+
process.exit(1)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const user = result.rows[0] as {
|
|
171
|
+
id: string
|
|
172
|
+
email: string
|
|
173
|
+
raw_app_meta_data: Record<string, unknown>
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log(`\nRole updated successfully.`)
|
|
177
|
+
console.log(` ID: ${user.id}`)
|
|
178
|
+
console.log(` Email: ${user.email}`)
|
|
179
|
+
console.log(` Role: ${opts.role}\n`)
|
|
180
|
+
} catch (err) {
|
|
181
|
+
const message =
|
|
182
|
+
err instanceof Error ? err.message : "Unknown error"
|
|
183
|
+
console.error(`\nFailed to update role: ${message}`)
|
|
184
|
+
process.exit(1)
|
|
185
|
+
} finally {
|
|
186
|
+
await pool.end()
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
adminCmd
|
|
192
|
+
.command("list-users")
|
|
193
|
+
.description("List users with admin roles")
|
|
194
|
+
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
195
|
+
.action(async (opts: { connection?: string }) => {
|
|
196
|
+
const cwd = process.cwd()
|
|
197
|
+
const config = loadConfig(cwd)
|
|
198
|
+
const connection = opts.connection ?? connectionString(config)
|
|
199
|
+
|
|
200
|
+
const pg = await importPg()
|
|
201
|
+
const pool = new pg.Pool({ connectionString: connection, max: 2 })
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
const result = await pool.query(
|
|
205
|
+
`SELECT id, email, raw_app_meta_data->>'role' as role, created_at
|
|
206
|
+
FROM auth.users
|
|
207
|
+
WHERE raw_app_meta_data->>'role' IS NOT NULL
|
|
208
|
+
AND raw_app_meta_data->>'role' != 'authenticated'
|
|
209
|
+
ORDER BY created_at ASC`,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
if (result.rows.length === 0) {
|
|
213
|
+
console.log("\nNo admin users found.")
|
|
214
|
+
console.log(
|
|
215
|
+
"Create one with: supatype admin create-user --email admin@example.com --role admin\n",
|
|
216
|
+
)
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
console.log(
|
|
221
|
+
"\n ID Email Role Created",
|
|
222
|
+
)
|
|
223
|
+
console.log(" " + "-".repeat(100))
|
|
224
|
+
for (const row of result.rows) {
|
|
225
|
+
const r = row as {
|
|
226
|
+
id: string
|
|
227
|
+
email: string
|
|
228
|
+
role: string
|
|
229
|
+
created_at: string
|
|
230
|
+
}
|
|
231
|
+
const date = new Date(r.created_at).toISOString().slice(0, 10)
|
|
232
|
+
console.log(
|
|
233
|
+
` ${r.id} ${r.email.padEnd(30)} ${r.role.padEnd(12)} ${date}`,
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
console.log()
|
|
237
|
+
} catch (err) {
|
|
238
|
+
const message =
|
|
239
|
+
err instanceof Error ? err.message : "Unknown error"
|
|
240
|
+
console.error(`\nFailed to list admin users: ${message}`)
|
|
241
|
+
process.exit(1)
|
|
242
|
+
} finally {
|
|
243
|
+
await pool.end()
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ─── First admin user prompt (task 48) ──────────────────────────────────────
|
|
249
|
+
// Called by `supatype push` on initial setup if no admin users exist.
|
|
250
|
+
|
|
251
|
+
export async function promptFirstAdminUser(
|
|
252
|
+
connection: string,
|
|
253
|
+
): Promise<void> {
|
|
254
|
+
const pg = await importPg()
|
|
255
|
+
const pool = new pg.Pool({ connectionString: connection, max: 2 })
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
// Check if auth.users table exists
|
|
259
|
+
const tableExists = await pool.query(
|
|
260
|
+
`SELECT EXISTS (
|
|
261
|
+
SELECT FROM information_schema.tables
|
|
262
|
+
WHERE table_schema = 'auth' AND table_name = 'users'
|
|
263
|
+
) as exists`,
|
|
264
|
+
)
|
|
265
|
+
if (!tableExists.rows[0]?.exists) return
|
|
266
|
+
|
|
267
|
+
// Check if any admin users exist
|
|
268
|
+
const adminCount = await pool.query(
|
|
269
|
+
`SELECT COUNT(*) as count FROM auth.users
|
|
270
|
+
WHERE raw_app_meta_data->>'role' IS NOT NULL
|
|
271
|
+
AND raw_app_meta_data->>'role' != 'authenticated'`,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
const count = parseInt(
|
|
275
|
+
(adminCount.rows[0] as { count: string }).count,
|
|
276
|
+
10,
|
|
277
|
+
)
|
|
278
|
+
if (count > 0) return
|
|
279
|
+
|
|
280
|
+
// No admin users — prompt to create one
|
|
281
|
+
console.log("\n No admin users found for the admin panel.")
|
|
282
|
+
const createAdmin = await confirm(
|
|
283
|
+
" Create an admin user now? [y/N] ",
|
|
284
|
+
)
|
|
285
|
+
if (!createAdmin) {
|
|
286
|
+
console.log(
|
|
287
|
+
" Skipped. You can create one later with: supatype admin create-user\n",
|
|
288
|
+
)
|
|
289
|
+
return
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const email = await prompt(" Admin email: ")
|
|
293
|
+
if (!email || !email.includes("@")) {
|
|
294
|
+
console.log(" Invalid email. Skipping admin user creation.\n")
|
|
295
|
+
return
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const password = await prompt(
|
|
299
|
+
" Admin password (min 8 chars): ",
|
|
300
|
+
)
|
|
301
|
+
if (!password || password.length < 8) {
|
|
302
|
+
console.log(
|
|
303
|
+
" Password too short. Skipping admin user creation.\n",
|
|
304
|
+
)
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const passwordHash = await hashPassword(password)
|
|
309
|
+
const appMetadata = JSON.stringify({
|
|
310
|
+
role: "admin",
|
|
311
|
+
provider: "email",
|
|
312
|
+
providers: ["email"],
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
await pool.query(
|
|
316
|
+
`INSERT INTO auth.users (
|
|
317
|
+
email, encrypted_password, role, aud,
|
|
318
|
+
raw_app_meta_data, raw_user_meta_data,
|
|
319
|
+
email_confirmed_at, created_at, updated_at
|
|
320
|
+
) VALUES (
|
|
321
|
+
$1, $2, 'authenticated', 'authenticated',
|
|
322
|
+
$3::jsonb, '{}'::jsonb,
|
|
323
|
+
now(), now(), now()
|
|
324
|
+
)`,
|
|
325
|
+
[email.toLowerCase(), passwordHash, appMetadata],
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
console.log(`\n Admin user "${email}" created (role: admin).`)
|
|
329
|
+
console.log(` Log in at /admin after starting the dev server.\n`)
|
|
330
|
+
} catch {
|
|
331
|
+
// Non-fatal — if auth schema doesn't exist yet, skip silently
|
|
332
|
+
} finally {
|
|
333
|
+
await pool.end()
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
async function importPg(): Promise<typeof import("pg")> {
|
|
340
|
+
try {
|
|
341
|
+
return await import("pg")
|
|
342
|
+
} catch {
|
|
343
|
+
console.error(
|
|
344
|
+
"pg package is required for admin commands. Install it with: pnpm add pg",
|
|
345
|
+
)
|
|
346
|
+
process.exit(1)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function hashPassword(password: string): Promise<string> {
|
|
351
|
+
const salt = randomBytes(16).toString("hex")
|
|
352
|
+
const derived = (await scryptAsync(password, salt, 64)) as Buffer
|
|
353
|
+
return `${salt}:${derived.toString("hex")}`
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function prompt(question: string): Promise<string> {
|
|
357
|
+
const rl = createInterface({
|
|
358
|
+
input: process.stdin,
|
|
359
|
+
output: process.stdout,
|
|
360
|
+
})
|
|
361
|
+
return new Promise((resolve) => {
|
|
362
|
+
rl.question(question, (answer) => {
|
|
363
|
+
rl.close()
|
|
364
|
+
resolve(answer.trim())
|
|
365
|
+
})
|
|
366
|
+
})
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async function confirm(question: string): Promise<boolean> {
|
|
370
|
+
const answer = await prompt(question)
|
|
371
|
+
return answer.toLowerCase() === "y"
|
|
372
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Command } from "commander"
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs"
|
|
3
|
+
import { resolve } from "node:path"
|
|
4
|
+
import { localKongBaseUrl } from "../local-gateway.js"
|
|
5
|
+
import { updateAppConfigInProject } from "../app-config.js"
|
|
6
|
+
|
|
7
|
+
export function registerApp(program: Command): void {
|
|
8
|
+
const appCmd = program
|
|
9
|
+
.command("app")
|
|
10
|
+
.description("Manage application routing intent in supatype.config.ts")
|
|
11
|
+
|
|
12
|
+
appCmd
|
|
13
|
+
.command("add [dir]")
|
|
14
|
+
.description("Configure app routing: --static for a built site, or proxy to a dev server")
|
|
15
|
+
.option("--static", "Serve a static directory at / (default: ./public, or [dir] argument)")
|
|
16
|
+
.option("--port <port>", "Port your app listens on (proxy mode)", "3000")
|
|
17
|
+
.option("--upstream <url>", "Explicit upstream URL (proxy mode; defaults to localhost:<port>)")
|
|
18
|
+
.option("--dockerfile <path>", "(deprecated) ignored — use supatype.config.ts")
|
|
19
|
+
.action(
|
|
20
|
+
(
|
|
21
|
+
dir: string | undefined,
|
|
22
|
+
opts: {
|
|
23
|
+
static?: boolean
|
|
24
|
+
port: string
|
|
25
|
+
upstream?: string
|
|
26
|
+
dockerfile?: string
|
|
27
|
+
},
|
|
28
|
+
) => {
|
|
29
|
+
if (opts.static) {
|
|
30
|
+
addStaticApp(process.cwd(), resolveStaticDir(dir))
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
if (opts.dockerfile) {
|
|
34
|
+
console.warn("[supatype] --dockerfile is deprecated and ignored.")
|
|
35
|
+
}
|
|
36
|
+
addProxyApp(process.cwd(), opts.port, opts.upstream)
|
|
37
|
+
},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
appCmd
|
|
41
|
+
.command("remove")
|
|
42
|
+
.description("Set app.mode=none in supatype.config.ts")
|
|
43
|
+
.action(() => {
|
|
44
|
+
removeApp(process.cwd())
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
function resolveStaticDir(dir?: string): string {
|
|
51
|
+
const trimmed = dir?.trim()
|
|
52
|
+
return trimmed && trimmed.length > 0 ? trimmed : "./public"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function addStaticApp(cwd: string, staticDir: string): void {
|
|
56
|
+
const abs = resolve(cwd, staticDir)
|
|
57
|
+
if (!existsSync(abs)) {
|
|
58
|
+
mkdirSync(abs, { recursive: true })
|
|
59
|
+
console.log(` created ${staticDir}/`)
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const configPath = updateAppConfigInProject(cwd, { mode: "static", staticDir })
|
|
63
|
+
console.log(` updated ${configPath}`)
|
|
64
|
+
console.log(`\nStatic app directory: ${staticDir}`)
|
|
65
|
+
console.log(`Build your frontend into ${staticDir}/, then:`)
|
|
66
|
+
console.log(` supatype self-host compose render`)
|
|
67
|
+
console.log(` supatype self-host compose up -d`)
|
|
68
|
+
console.log(`\nYour app will be served at ${localKongBaseUrl()}/\n`)
|
|
69
|
+
} catch (err) {
|
|
70
|
+
console.error((err as Error).message)
|
|
71
|
+
process.exit(1)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function addProxyApp(cwd: string, port: string, upstream?: string): void {
|
|
76
|
+
const upstreamUrl = upstream?.trim() || `http://localhost:${port}`
|
|
77
|
+
try {
|
|
78
|
+
const configPath = updateAppConfigInProject(cwd, { mode: "proxy", upstream: upstreamUrl })
|
|
79
|
+
console.log(` updated ${configPath}`)
|
|
80
|
+
console.log(`\nApp upstream set to ${upstreamUrl}. The app will be available at ${localKongBaseUrl()}/\n`)
|
|
81
|
+
console.log("Run: supatype self-host compose render")
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error((err as Error).message)
|
|
84
|
+
process.exit(1)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function removeApp(cwd: string): void {
|
|
89
|
+
try {
|
|
90
|
+
const configPath = updateAppConfigInProject(cwd, { mode: "none" })
|
|
91
|
+
console.log(` updated ${configPath}`)
|
|
92
|
+
console.log("\nApp routing disabled (app.mode=none).\n")
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.error((err as Error).message)
|
|
95
|
+
process.exit(1)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* supatype cache — list and clean cached component binaries.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Command } from "commander"
|
|
6
|
+
import { existsSync, readdirSync, rmSync, statSync } from "node:fs"
|
|
7
|
+
import { join } from "node:path"
|
|
8
|
+
import { cacheRoot, type Component } from "../binary-cache.js"
|
|
9
|
+
|
|
10
|
+
const COMPONENTS: Component[] = ["engine", "server", "postgres", "deno"]
|
|
11
|
+
|
|
12
|
+
export function registerCache(program: Command): void {
|
|
13
|
+
const cache = program
|
|
14
|
+
.command("cache")
|
|
15
|
+
.description("Manage cached component binaries")
|
|
16
|
+
|
|
17
|
+
cache
|
|
18
|
+
.command("list")
|
|
19
|
+
.description("List cached component binaries and their sizes")
|
|
20
|
+
.action(() => {
|
|
21
|
+
const root = cacheRoot()
|
|
22
|
+
if (!existsSync(root)) {
|
|
23
|
+
console.log("Cache is empty.")
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let totalBytes = 0
|
|
28
|
+
let found = false
|
|
29
|
+
|
|
30
|
+
for (const component of COMPONENTS) {
|
|
31
|
+
const compDir = join(root, component)
|
|
32
|
+
if (!existsSync(compDir)) continue
|
|
33
|
+
|
|
34
|
+
const versions = readdirSync(compDir).filter(
|
|
35
|
+
(v) => statSync(join(compDir, v)).isDirectory(),
|
|
36
|
+
)
|
|
37
|
+
for (const version of versions) {
|
|
38
|
+
const vDir = join(compDir, version)
|
|
39
|
+
const size = dirSize(vDir)
|
|
40
|
+
totalBytes += size
|
|
41
|
+
found = true
|
|
42
|
+
console.log(` ${component}@${version} ${formatBytes(size)}`)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!found) {
|
|
47
|
+
console.log("Cache is empty.")
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log(`\nTotal: ${formatBytes(totalBytes)}`)
|
|
52
|
+
console.log(`Cache root: ${root}`)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
cache
|
|
56
|
+
.command("clean [component] [version]")
|
|
57
|
+
.description(
|
|
58
|
+
"Remove cached binaries. Optionally specify a component and/or version.\n" +
|
|
59
|
+
"Examples:\n" +
|
|
60
|
+
" supatype cache clean # remove everything\n" +
|
|
61
|
+
" supatype cache clean engine # remove all engine versions\n" +
|
|
62
|
+
" supatype cache clean engine 0.4.2",
|
|
63
|
+
)
|
|
64
|
+
.action((component?: string, version?: string) => {
|
|
65
|
+
const root = cacheRoot()
|
|
66
|
+
if (!existsSync(root)) {
|
|
67
|
+
console.log("Cache is already empty.")
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const targets = component ? [component as Component] : COMPONENTS
|
|
72
|
+
|
|
73
|
+
for (const comp of targets) {
|
|
74
|
+
const compDir = join(root, comp)
|
|
75
|
+
if (!existsSync(compDir)) continue
|
|
76
|
+
|
|
77
|
+
if (version) {
|
|
78
|
+
const vDir = join(compDir, version)
|
|
79
|
+
if (!existsSync(vDir)) {
|
|
80
|
+
console.log(` ${comp}@${version} not cached.`)
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
rmSync(vDir, { recursive: true, force: true })
|
|
84
|
+
console.log(` removed ${comp}@${version}`)
|
|
85
|
+
} else {
|
|
86
|
+
rmSync(compDir, { recursive: true, force: true })
|
|
87
|
+
console.log(` removed ${comp} (all versions)`)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log("Done.")
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function dirSize(dir: string): number {
|
|
96
|
+
let total = 0
|
|
97
|
+
try {
|
|
98
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
99
|
+
const full = join(dir, entry.name)
|
|
100
|
+
if (entry.isDirectory()) {
|
|
101
|
+
total += dirSize(full)
|
|
102
|
+
} else {
|
|
103
|
+
total += statSync(full).size
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} catch {
|
|
107
|
+
// Skip unreadable entries.
|
|
108
|
+
}
|
|
109
|
+
return total
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function formatBytes(bytes: number): string {
|
|
113
|
+
if (bytes < 1024) return `${bytes} B`
|
|
114
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
|
|
115
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
|
|
116
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`
|
|
117
|
+
}
|