@supatype/cli 0.1.7 → 0.1.9
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 +1 -1
- package/.turbo/turbo-test.log +128 -128
- package/.turbo/turbo-typecheck.log +1 -1
- package/LICENSE +202 -0
- package/deno.d.ts +1 -1
- package/dist/app/framework.js +1 -1
- package/dist/app/framework.js.map +1 -1
- package/dist/augmentation-generator.d.ts +1 -1
- package/dist/augmentation-generator.js +3 -3
- package/dist/augmentation-generator.js.map +1 -1
- package/dist/binary-cache.d.ts +30 -8
- package/dist/binary-cache.d.ts.map +1 -1
- package/dist/binary-cache.js +47 -35
- package/dist/binary-cache.js.map +1 -1
- package/dist/cache-pins.d.ts +1 -1
- package/dist/cache-pins.js +2 -2
- package/dist/cache-pins.js.map +1 -1
- package/dist/cli-artifacts.d.ts +32 -0
- package/dist/cli-artifacts.d.ts.map +1 -0
- package/dist/cli-artifacts.js +49 -0
- package/dist/cli-artifacts.js.map +1 -0
- package/dist/cli-install-method.d.ts +9 -1
- package/dist/cli-install-method.d.ts.map +1 -1
- package/dist/cli-install-method.js +22 -4
- package/dist/cli-install-method.js.map +1 -1
- package/dist/cli-package-version.d.ts +1 -1
- package/dist/cli-package-version.d.ts.map +1 -1
- package/dist/cli-package-version.js +6 -1
- package/dist/cli-package-version.js.map +1 -1
- package/dist/cli-standalone.d.ts +13 -4
- package/dist/cli-standalone.d.ts.map +1 -1
- package/dist/cli-standalone.js +86 -31
- package/dist/cli-standalone.js.map +1 -1
- package/dist/cli-version-embedded.d.ts +10 -0
- package/dist/cli-version-embedded.d.ts.map +1 -0
- package/dist/cli-version-embedded.js +13 -0
- package/dist/cli-version-embedded.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.js +1 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/admin.js +6 -6
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/adopt.js +1 -1
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/app.js +2 -2
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/cache.d.ts +1 -1
- package/dist/commands/cache.js +3 -3
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/db.d.ts +3 -3
- package/dist/commands/db.js +9 -9
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts +9 -9
- package/dist/commands/deploy.js +12 -12
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +3 -3
- package/dist/commands/dev.js +17 -17
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/engine.d.ts +1 -1
- package/dist/commands/engine.js +1 -1
- package/dist/commands/functions.js +5 -5
- package/dist/commands/functions.js.map +1 -1
- package/dist/commands/hooks.d.ts +2 -2
- package/dist/commands/hooks.js +4 -4
- package/dist/commands/hooks.js.map +1 -1
- package/dist/commands/init.js +28 -28
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logs.d.ts +1 -1
- package/dist/commands/migrate.js +5 -5
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/pg.d.ts +1 -1
- package/dist/commands/pg.js +1 -1
- package/dist/commands/plugins.js +1 -1
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/pull.js +2 -2
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.js +3 -3
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/self-host.d.ts +1 -1
- package/dist/commands/self-host.js +1 -1
- package/dist/commands/self-update.d.ts +2 -8
- package/dist/commands/self-update.d.ts.map +1 -1
- package/dist/commands/self-update.js +20 -12
- package/dist/commands/self-update.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/update.d.ts +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/db-preflight.d.ts +4 -4
- package/dist/db-preflight.js +14 -14
- package/dist/db-preflight.js.map +1 -1
- package/dist/dev-compose.d.ts +3 -3
- package/dist/dev-compose.js +27 -27
- package/dist/dev-compose.js.map +1 -1
- package/dist/dev-log-filter.d.ts +1 -1
- package/dist/dev-log-filter.d.ts.map +1 -1
- package/dist/dev-log-filter.js +1 -1
- package/dist/dev-log-filter.js.map +1 -1
- package/dist/dev-ports.d.ts +2 -2
- package/dist/dev-ports.d.ts.map +1 -1
- package/dist/dev-ports.js +2 -2
- package/dist/dev-ports.js.map +1 -1
- package/dist/dev-session.d.ts +5 -5
- package/dist/dev-session.d.ts.map +1 -1
- package/dist/dev-session.js +6 -6
- package/dist/dev-session.js.map +1 -1
- package/dist/dev-shutdown.d.ts +5 -5
- package/dist/dev-shutdown.d.ts.map +1 -1
- package/dist/dev-shutdown.js +7 -7
- package/dist/dev-shutdown.js.map +1 -1
- package/dist/dev-task-colors.d.ts +1 -1
- package/dist/dev-task-colors.d.ts.map +1 -1
- package/dist/dev-task-colors.js +1 -1
- package/dist/dev-task-colors.js.map +1 -1
- package/dist/docker-postgres.d.ts +5 -5
- package/dist/docker-postgres.d.ts.map +1 -1
- package/dist/docker-postgres.js +5 -5
- package/dist/docker-postgres.js.map +1 -1
- package/dist/docker-runtime.d.ts +2 -2
- package/dist/docker-runtime.d.ts.map +1 -1
- package/dist/docker-runtime.js +5 -5
- package/dist/docker-runtime.js.map +1 -1
- package/dist/engine-client.d.ts +1 -1
- package/dist/engine-client.js +3 -3
- package/dist/engine-client.js.map +1 -1
- package/dist/engine-push-output.js +1 -1
- package/dist/engine-push-output.js.map +1 -1
- package/dist/ensure-binary.d.ts.map +1 -1
- package/dist/ensure-binary.js +17 -0
- package/dist/ensure-binary.js.map +1 -1
- package/dist/ensure-component-binaries.js +1 -1
- package/dist/ensure-component-binaries.js.map +1 -1
- package/dist/env-file.d.ts +2 -2
- package/dist/env-file.d.ts.map +1 -1
- package/dist/env-file.js +1 -1
- package/dist/env-file.js.map +1 -1
- package/dist/field-masking-tier.d.ts +5 -5
- package/dist/field-masking-tier.d.ts.map +1 -1
- package/dist/field-masking-tier.js +6 -6
- package/dist/field-masking-tier.js.map +1 -1
- package/dist/functions-deno-types.d.ts +1 -1
- package/dist/functions-deno-types.d.ts.map +1 -1
- package/dist/functions-deno-types.js +3 -3
- package/dist/functions-deno-types.js.map +1 -1
- package/dist/functions-router-gen.js +1 -1
- package/dist/gitignore.d.ts +2 -2
- package/dist/gitignore.d.ts.map +1 -1
- package/dist/gitignore.js +3 -3
- package/dist/gitignore.js.map +1 -1
- package/dist/hook-upload.d.ts +1 -1
- package/dist/hook-upload.js +3 -3
- package/dist/hooks-generator.d.ts +1 -1
- package/dist/hooks-generator.js +9 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/init-project-detect.d.ts +1 -1
- package/dist/init-project-detect.d.ts.map +1 -1
- package/dist/init-project-detect.js +1 -1
- package/dist/init-project-detect.js.map +1 -1
- package/dist/link.d.ts +1 -1
- package/dist/link.d.ts.map +1 -1
- package/dist/local-secrets.d.ts +5 -5
- package/dist/local-secrets.js +5 -5
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +20 -0
- package/dist/main.js.map +1 -0
- package/dist/model-hooks.d.ts +3 -3
- package/dist/model-hooks.js +4 -4
- package/dist/pgbouncer-userlist.d.ts +1 -1
- package/dist/pgbouncer-userlist.d.ts.map +1 -1
- package/dist/pgbouncer-userlist.js +2 -2
- package/dist/pgbouncer-userlist.js.map +1 -1
- package/dist/postgres-ctl.d.ts +1 -1
- package/dist/postgres-ctl.js +4 -4
- package/dist/postgres-ctl.js.map +1 -1
- package/dist/process-manager.d.ts +2 -2
- package/dist/process-manager.d.ts.map +1 -1
- package/dist/process-manager.js +4 -4
- package/dist/process-manager.js.map +1 -1
- package/dist/project-config.d.ts +12 -12
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +9 -9
- package/dist/project-config.js.map +1 -1
- package/dist/pull-utils.d.ts +2 -2
- package/dist/pull-utils.d.ts.map +1 -1
- package/dist/pull-utils.js +4 -4
- package/dist/pull-utils.js.map +1 -1
- package/dist/realtime-launch.js +1 -1
- package/dist/realtime-launch.js.map +1 -1
- package/dist/release-pins.d.ts +1 -1
- package/dist/release-pins.js +2 -2
- package/dist/release-pins.js.map +1 -1
- package/dist/resolve-api-url.js +1 -1
- package/dist/resolve-api-url.js.map +1 -1
- package/dist/resolve-target.d.ts +1 -1
- package/dist/resolve-target.d.ts.map +1 -1
- package/dist/rest-cache-admin.js +2 -2
- package/dist/rest-cache-admin.js.map +1 -1
- package/dist/runtime-routes.d.ts +1 -1
- package/dist/runtime-routes.js +1 -1
- package/dist/schema-ast-v2.d.ts +3 -3
- 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-push-lock.js +3 -3
- package/dist/schema-push-lock.js.map +1 -1
- package/dist/scripts/postinstall.d.ts +1 -1
- package/dist/scripts/postinstall.js +1 -1
- package/dist/self-host-compose.d.ts +5 -5
- package/dist/self-host-compose.d.ts.map +1 -1
- package/dist/self-host-compose.js +24 -24
- package/dist/self-host-compose.js.map +1 -1
- package/dist/service-role-check.js +3 -3
- package/dist/service-role-check.js.map +1 -1
- package/dist/storage-provision.d.ts +1 -1
- package/dist/storage-provision.js +3 -3
- package/dist/storage-provision.js.map +1 -1
- package/dist/studio-dev-server.d.ts +1 -1
- package/dist/studio-dev-server.d.ts.map +1 -1
- package/dist/systemd.d.ts +1 -1
- package/dist/systemd.js +1 -1
- package/dist/target-client.js +1 -1
- package/dist/target-client.js.map +1 -1
- package/dist/tsx-runner.js +1 -1
- package/dist/tsx-runner.js.map +1 -1
- package/dist/type-extractor.js +27 -27
- package/dist/type-extractor.js.map +1 -1
- package/dist/type-resolver.js +1 -1
- package/dist/type-resolver.js.map +1 -1
- package/dist/ui/brand.d.ts +1 -1
- package/dist/ui/brand.js +1 -1
- package/dist/ui/components/LogoWordmark.d.ts +1 -1
- package/dist/ui/components/LogoWordmark.d.ts.map +1 -1
- package/dist/ui/components/LogoWordmark.js +1 -1
- package/dist/ui/components/LogoWordmark.js.map +1 -1
- package/dist/ui/components/SelectField.js +1 -1
- package/dist/ui/components/SelectField.js.map +1 -1
- package/dist/ui/confirm.d.ts +1 -1
- package/dist/ui/confirm.js +1 -1
- package/dist/ui/fatal.d.ts +1 -1
- package/dist/ui/fatal.d.ts.map +1 -1
- package/dist/ui/fatal.js +1 -1
- package/dist/ui/fatal.js.map +1 -1
- package/dist/ui/flows/prompt-fields.js +1 -1
- package/dist/ui/flows/prompt-fields.js.map +1 -1
- package/dist/ui/interactive.d.ts +1 -1
- package/dist/ui/interactive.d.ts.map +1 -1
- package/dist/ui/interactive.js +1 -1
- package/dist/ui/interactive.js.map +1 -1
- package/dist/ui/progress.d.ts +1 -1
- package/dist/ui/progress.js +1 -1
- package/dist/ui/runtime/command-chrome.js +1 -1
- package/dist/ui/runtime/command-chrome.js.map +1 -1
- package/dist/ui/runtime/run-clack-flow.js +1 -1
- package/dist/ui/runtime/run-clack-flow.js.map +1 -1
- package/dist/ui/runtime/stdin-after-ink.js +1 -1
- package/dist/ui/runtime/stdin-after-ink.js.map +1 -1
- package/dist/ui/theme.d.ts +1 -1
- package/dist/ui/theme.js +1 -1
- package/dist/valkey-sidecar.d.ts +1 -1
- package/dist/valkey-sidecar.d.ts.map +1 -1
- package/dist/valkey-sidecar.js +2 -2
- package/dist/valkey-sidecar.js.map +1 -1
- package/package.json +3 -2
- package/scripts/build-release-artifacts.sh +112 -0
- package/scripts/generate-homebrew-formula.mjs +47 -45
- package/scripts/mirror-deno-release.sh +1 -1
- package/src/TYPE-RESOLUTION.md +31 -31
- package/src/app/framework.ts +1 -1
- package/src/augmentation-generator.ts +3 -3
- package/src/binary-cache.ts +51 -36
- package/src/cache-pins.ts +2 -2
- package/src/cli-artifacts.ts +65 -0
- package/src/cli-install-method.ts +24 -4
- package/src/cli-package-version.ts +5 -1
- package/src/cli-standalone.ts +116 -34
- package/src/cli-version-embedded.ts +12 -0
- package/src/cli.ts +1 -1
- package/src/commands/add.ts +1 -1
- package/src/commands/admin.ts +6 -6
- package/src/commands/adopt.ts +1 -1
- package/src/commands/app.ts +2 -2
- package/src/commands/cache.ts +3 -3
- package/src/commands/db.ts +9 -9
- package/src/commands/deploy.ts +12 -12
- package/src/commands/dev.ts +19 -19
- package/src/commands/doctor.ts +3 -3
- package/src/commands/engine.ts +1 -1
- package/src/commands/functions.ts +5 -5
- package/src/commands/hooks.ts +6 -6
- package/src/commands/init.ts +28 -28
- package/src/commands/login.ts +2 -2
- package/src/commands/logs.ts +1 -1
- package/src/commands/migrate.ts +5 -5
- package/src/commands/pg.ts +1 -1
- package/src/commands/plugins.ts +1 -1
- package/src/commands/pull.ts +2 -2
- package/src/commands/push.ts +3 -3
- package/src/commands/self-host.ts +1 -1
- package/src/commands/self-update.ts +23 -73
- package/src/commands/status.ts +1 -1
- package/src/commands/update.ts +1 -1
- package/src/config.ts +3 -3
- package/src/db-preflight.ts +15 -15
- package/src/dev-compose.ts +27 -27
- package/src/dev-log-filter.ts +1 -1
- package/src/dev-ports.ts +3 -3
- package/src/dev-session.ts +6 -6
- package/src/dev-shutdown.ts +8 -8
- package/src/dev-task-colors.ts +1 -1
- package/src/docker-postgres.ts +6 -6
- package/src/docker-runtime.ts +5 -5
- package/src/engine-client.ts +3 -3
- package/src/engine-push-output.ts +1 -1
- package/src/ensure-binary.ts +20 -0
- package/src/ensure-component-binaries.ts +1 -1
- package/src/env-file.ts +2 -2
- package/src/field-masking-tier.ts +6 -6
- package/src/functions-deno-types.ts +3 -3
- package/src/functions-router-gen.ts +1 -1
- package/src/gitignore.ts +3 -3
- package/src/hook-upload.ts +3 -3
- package/src/hooks-generator.ts +9 -9
- package/src/index.ts +1 -1
- package/src/init-project-detect.ts +1 -1
- package/src/link.ts +1 -1
- package/src/local-secrets.ts +5 -5
- package/src/main.ts +20 -0
- package/src/model-hooks.ts +4 -4
- package/src/pgbouncer-userlist.ts +2 -2
- package/src/postgres-ctl.ts +4 -4
- package/src/process-manager.ts +4 -4
- package/src/project-config.ts +16 -16
- package/src/pull-utils.ts +4 -4
- package/src/realtime-launch.ts +1 -1
- package/src/release-pins.ts +2 -2
- package/src/resolve-api-url.ts +1 -1
- package/src/resolve-target.ts +1 -1
- package/src/rest-cache-admin.ts +2 -2
- package/src/runtime-routes.ts +2 -2
- package/src/schema-ast-v2.ts +4 -4
- package/src/schema-push-lock.ts +3 -3
- package/src/scripts/postinstall.ts +1 -1
- package/src/self-host-compose.ts +25 -25
- package/src/service-role-check.ts +3 -3
- package/src/storage-provision.ts +3 -3
- package/src/studio-dev-server.ts +1 -1
- package/src/systemd.ts +1 -1
- package/src/target-client.ts +1 -1
- package/src/tsx-runner.ts +1 -1
- package/src/type-extractor.ts +27 -27
- package/src/type-resolver.ts +1 -1
- package/src/ui/README.md +1 -1
- package/src/ui/brand.ts +1 -1
- package/src/ui/components/LogoWordmark.tsx +1 -1
- package/src/ui/components/SelectField.tsx +1 -1
- package/src/ui/confirm.ts +1 -1
- package/src/ui/fatal.ts +1 -1
- package/src/ui/flows/prompt-fields.tsx +1 -1
- package/src/ui/interactive.ts +1 -1
- package/src/ui/progress.ts +1 -1
- package/src/ui/runtime/command-chrome.ts +1 -1
- package/src/ui/runtime/run-clack-flow.tsx +1 -1
- package/src/ui/runtime/stdin-after-ink.ts +1 -1
- package/src/ui/theme.ts +1 -1
- package/src/valkey-sidecar.ts +2 -2
- package/tests/access-composition.test.ts +6 -6
- package/tests/admin-studio-membership.test.ts +1 -1
- package/tests/api-schemas.test.ts +1 -1
- package/tests/archive-name-alias.test.ts +1 -1
- package/tests/cli-help.test.ts +8 -2
- package/tests/db-preflight.test.ts +1 -1
- package/tests/doctor-render.test.ts +3 -3
- package/tests/doctor-service-role.test.ts +2 -2
- package/tests/engine-push-output.test.ts +1 -1
- package/tests/env-file.test.ts +3 -3
- package/tests/external-database-compose.test.ts +5 -5
- package/tests/external-database-config.test.ts +2 -2
- package/tests/field-masking-tier.test.ts +1 -1
- package/tests/homebrew-formula.test.ts +68 -26
- package/tests/hook-upload.test.ts +1 -1
- package/tests/hooks-generator.test.ts +1 -1
- package/tests/init.test.ts +2 -2
- package/tests/keys.test.ts +8 -2
- package/tests/local-secrets.test.ts +3 -3
- package/tests/model-hooks.test.ts +6 -6
- package/tests/runtime-contract.test.ts +2 -2
- package/tests/service-role-check.test.ts +3 -3
- package/tests/storage-provision.test.ts +1 -1
- package/tests/type-extractor.test.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +7 -1
- package/scripts/build-release-bundle.mjs +0 -27
|
@@ -138,7 +138,7 @@ function scaffoldFunction(cwd: string, name: string): void {
|
|
|
138
138
|
|
|
139
139
|
mkdirSync(fnDir, { recursive: true })
|
|
140
140
|
|
|
141
|
-
const indexContent = `// ${name}
|
|
141
|
+
const indexContent = `// ${name}, Supatype Edge Function
|
|
142
142
|
// Docs: https://supatype.com/docs/edge-functions
|
|
143
143
|
|
|
144
144
|
export default async function handler(req: Request): Promise<Response> {
|
|
@@ -257,7 +257,7 @@ function discoverFunctions(cwd: string): DiscoveredFunction[] {
|
|
|
257
257
|
const stat = statSync(fullPath)
|
|
258
258
|
|
|
259
259
|
if (stat.isDirectory()) {
|
|
260
|
-
// Directory function
|
|
260
|
+
// Directory function: look for index.ts
|
|
261
261
|
const indexPath = join(fullPath, "index.ts")
|
|
262
262
|
if (existsSync(indexPath)) {
|
|
263
263
|
fns.push({ name: entry, entrypoint: indexPath, absPath: fullPath })
|
|
@@ -369,7 +369,7 @@ async function deploy(cwd: string, opts: { only?: string; env?: string; dryRun?:
|
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
if (opts.dryRun) {
|
|
372
|
-
plain("Dry run
|
|
372
|
+
plain("Dry run: the following functions would be deployed:\n")
|
|
373
373
|
for (const fn of fns) {
|
|
374
374
|
plain(` ${fn.name} → ${relative(cwd, fn.entrypoint)}`)
|
|
375
375
|
}
|
|
@@ -543,7 +543,7 @@ function readFunctionSource(fn: DiscoveredFunction): string {
|
|
|
543
543
|
return readFileSync(fn.absPath, "utf8")
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
// Directory function
|
|
546
|
+
// Directory function: read all .ts files
|
|
547
547
|
const files: Record<string, string> = {}
|
|
548
548
|
const entries = readdirSync(fn.absPath, { recursive: true }) as string[]
|
|
549
549
|
for (const entry of entries) {
|
|
@@ -607,7 +607,7 @@ async function listFunctions(cwd: string): Promise<void> {
|
|
|
607
607
|
plain(` ${"─".repeat(28)} ${"─".repeat(24)} ${"─".repeat(20)} ${"─".repeat(12)}`)
|
|
608
608
|
|
|
609
609
|
for (const fn of data) {
|
|
610
|
-
const deployed = fn.deployedAt ? new Date(fn.deployedAt).toLocaleString() : "
|
|
610
|
+
const deployed = fn.deployedAt ? new Date(fn.deployedAt).toLocaleString() : "-"
|
|
611
611
|
plain(
|
|
612
612
|
` ${fn.name.padEnd(28)} ${deployed.padEnd(24)} ${String(fn.invocations24h ?? 0).padEnd(20)} ${fn.avgDurationMs ?? 0}ms`,
|
|
613
613
|
)
|
package/src/commands/hooks.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `supatype hooks
|
|
2
|
+
* `supatype hooks`: scaffold and inspect model hooks.
|
|
3
3
|
*
|
|
4
4
|
* Separate from `supatype functions` because the two are different things wearing the same runtime.
|
|
5
5
|
* A function is a **public endpoint**: anyone holding the anon key can invoke it. A hook is
|
|
6
|
-
* **procedural
|
|
6
|
+
* **procedural**: only the API server calls it, around a write, and the gateway refuses the route
|
|
7
7
|
* from outside. Keeping them in separate directories is what makes that boundary structural instead
|
|
8
8
|
* of a list somebody has to maintain.
|
|
9
9
|
*/
|
|
@@ -85,7 +85,7 @@ function scaffoldHook(cwd: string, name: string): void {
|
|
|
85
85
|
/**
|
|
86
86
|
* The scaffold deliberately imports from `../_supatype/hooks.ts`, which `push` generates.
|
|
87
87
|
*
|
|
88
|
-
* Before the first push that file does not exist, so the handler will not compile
|
|
88
|
+
* Before the first push that file does not exist, so the handler will not compile, which is the
|
|
89
89
|
* honest state: the types come from the schema, and a handler typed against a model that has not been
|
|
90
90
|
* pushed is a handler typed against a guess.
|
|
91
91
|
*/
|
|
@@ -94,7 +94,7 @@ function handlerTemplate(name: string, declared: { model: string; event: string
|
|
|
94
94
|
const model = declared[0]?.model ?? "YourModel"
|
|
95
95
|
|
|
96
96
|
if (event.startsWith("after")) {
|
|
97
|
-
return `// ${name}
|
|
97
|
+
return `// ${name}: model hook (${event})
|
|
98
98
|
//
|
|
99
99
|
// Runs after the write has succeeded. It cannot change or undo it: a rejection here would be a
|
|
100
100
|
// rejection of something that already happened. Failures are logged, not surfaced to the caller.
|
|
@@ -109,7 +109,7 @@ export default hook(handler)
|
|
|
109
109
|
`
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
return `// ${name}
|
|
112
|
+
return `// ${name}: model hook (${event}) for ${model}
|
|
113
113
|
//
|
|
114
114
|
// Runs before the write reaches Postgres, so it can reject it or rewrite the body.
|
|
115
115
|
//
|
|
@@ -125,7 +125,7 @@ const handler: BeforeChange<"your_table"> = async (ctx) => {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// \`ctx.patch\` is the submitted partial; \`ctx.previous()\` reads the rows about to change.
|
|
128
|
-
// Those come back as stored
|
|
128
|
+
// Those come back as stored, unmasked, so do not echo them into a rejection message.
|
|
129
129
|
return {}
|
|
130
130
|
|
|
131
131
|
// Reject with a message the caller sees, and a status of your choosing:
|
package/src/commands/init.ts
CHANGED
|
@@ -248,7 +248,7 @@ interface InteractiveInitArgs {
|
|
|
248
248
|
opts: InitCliOptions
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
/** Interactive init
|
|
251
|
+
/** Interactive init: one Ink session for wizard + scaffold + install + finish. */
|
|
252
252
|
async function runInteractiveInit(args: InteractiveInitArgs): Promise<void> {
|
|
253
253
|
const { name, dir, defaultName, modeTarget, opts } = args
|
|
254
254
|
|
|
@@ -501,7 +501,7 @@ async function promptAdminUser(): Promise<{ adminEmail?: string; adminPassword?:
|
|
|
501
501
|
)
|
|
502
502
|
if (!createAdmin) return {}
|
|
503
503
|
|
|
504
|
-
p.note("First sign-in at /admin
|
|
504
|
+
p.note("First sign-in at /admin, created automatically on supatype dev or push.")
|
|
505
505
|
|
|
506
506
|
const adminEmail = ensureNotCancelled(
|
|
507
507
|
await p.text({
|
|
@@ -686,7 +686,7 @@ export function scaffold(
|
|
|
686
686
|
writeFileSync(pkgPath, `${JSON.stringify(merged, null, 2)}\n`, "utf8")
|
|
687
687
|
file("updated", "package.json (added Supatype dependencies)")
|
|
688
688
|
} catch {
|
|
689
|
-
warn("Could not merge into package.json
|
|
689
|
+
warn("Could not merge into package.json, add @supatype/cli and @supatype/types manually.")
|
|
690
690
|
file("skipped", "package.json (invalid JSON)")
|
|
691
691
|
}
|
|
692
692
|
}
|
|
@@ -891,7 +891,7 @@ function localConfigTemplate(app: ScaffoldAppOptions): string {
|
|
|
891
891
|
const lines: string[] = [
|
|
892
892
|
`import type { SupatypeConfig } from "@supatype/cli"`,
|
|
893
893
|
``,
|
|
894
|
-
`// Local development overrides
|
|
894
|
+
`// Local development overrides, gitignored, deep-merged over supatype.config.ts.`,
|
|
895
895
|
`// Keeps \`supatype dev\` in local mode while the committed config targets production.`,
|
|
896
896
|
`const localConfig: Partial<SupatypeConfig> = {`,
|
|
897
897
|
` server: { mode: "dev" },`,
|
|
@@ -997,8 +997,8 @@ function holdingPageTemplate(projectName: string): string {
|
|
|
997
997
|
<head>
|
|
998
998
|
<meta charset="UTF-8" />
|
|
999
999
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1000
|
-
<title>${name}
|
|
1001
|
-
<meta name="description" content="A Supatype project. Define your types
|
|
1000
|
+
<title>${name}: Supatype</title>
|
|
1001
|
+
<meta name="description" content="A Supatype project. Define your types, we generate your platform." />
|
|
1002
1002
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
1003
1003
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
1004
1004
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
@@ -1146,12 +1146,12 @@ function storageConfigLines(
|
|
|
1146
1146
|
): string[] {
|
|
1147
1147
|
const lines: string[] = []
|
|
1148
1148
|
if (storageLocal === "s3") {
|
|
1149
|
-
lines.push(` storage: { provider: "s3" }, // dev
|
|
1149
|
+
lines.push(` storage: { provider: "s3" }, // dev, configure S3_* in .env`)
|
|
1150
1150
|
} else {
|
|
1151
1151
|
lines.push(` storage: { provider: "local", local_path: ".supatype/storage" },`)
|
|
1152
1152
|
}
|
|
1153
1153
|
if (storageProduction === "s3" && storageLocal !== "s3") {
|
|
1154
|
-
lines.push(` // Production storage: external S3 bucket
|
|
1154
|
+
lines.push(` // Production storage: external S3 bucket, set production S3_* in .env`)
|
|
1155
1155
|
} else if (storageProduction === "local" && storageLocal === "s3") {
|
|
1156
1156
|
lines.push(` // Production storage: MinIO on your server (included in self-host compose)`)
|
|
1157
1157
|
}
|
|
@@ -1174,7 +1174,7 @@ export type Profile = Model<{
|
|
|
1174
1174
|
}
|
|
1175
1175
|
}>
|
|
1176
1176
|
|
|
1177
|
-
/** Example singleton global
|
|
1177
|
+
/** Example singleton global: editable in Studio under Settings. */
|
|
1178
1178
|
export type SiteSettings = Model<{
|
|
1179
1179
|
id: UUID
|
|
1180
1180
|
site_name: string
|
|
@@ -1191,7 +1191,7 @@ export type SiteSettings = Model<{
|
|
|
1191
1191
|
function envTemplate(opts: ScaffoldOptions): string {
|
|
1192
1192
|
const sections: string[] = []
|
|
1193
1193
|
// Generated, not constant. These reach a server: the previous defaults meant a self-host
|
|
1194
|
-
// deployment ran with a password of `postgres` and a JWT secret published in this repo
|
|
1194
|
+
// deployment ran with a password of `postgres` and a JWT secret published in this repo,
|
|
1195
1195
|
// and anyone holding that secret can mint a token naming any Postgres role. Safe to generate
|
|
1196
1196
|
// only because `supatype dev` no longer overwrites them on every run (see local-secrets.ts).
|
|
1197
1197
|
const postgresPassword = randomBytes(24).toString("base64url")
|
|
@@ -1202,14 +1202,14 @@ POSTGRES_PASSWORD=${postgresPassword}
|
|
|
1202
1202
|
POSTGRES_DB=${opts.projectName}
|
|
1203
1203
|
|
|
1204
1204
|
# PostgREST's own database credential. It connects as \`authenticator\`, a role that holds no
|
|
1205
|
-
# privileges and can only switch to anon/authenticated/service_role
|
|
1205
|
+
# privileges and can only switch to anon/authenticated/service_role, so a request whose JWT
|
|
1206
1206
|
# names any other role is refused by Postgres rather than honoured.
|
|
1207
1207
|
#
|
|
1208
1208
|
# Deliberately NOT the same as POSTGRES_PASSWORD: that one is yours, for direct SQL access, and
|
|
1209
1209
|
# rotating it should never take the REST API down with it.
|
|
1210
1210
|
AUTHENTICATOR_PASSWORD=${randomBytes(24).toString("base64url")}`)
|
|
1211
1211
|
|
|
1212
|
-
sections.push(`# JWT
|
|
1212
|
+
sections.push(`# JWT: ANON_KEY and SERVICE_ROLE_KEY are derived from this secret.
|
|
1213
1213
|
# Changing it invalidates every issued token; re-run \`supatype keys\` afterwards.
|
|
1214
1214
|
JWT_SECRET=${randomBytes(48).toString("base64url")}
|
|
1215
1215
|
ANON_KEY=
|
|
@@ -1221,7 +1221,7 @@ SITE_URL=http://localhost:3000`)
|
|
|
1221
1221
|
if (opts.provider === "docker" && opts.kongPort !== undefined) {
|
|
1222
1222
|
const apiUrl = `http://localhost:${opts.kongPort}`
|
|
1223
1223
|
sections.push(
|
|
1224
|
-
`# Local API gateway (Kong)
|
|
1224
|
+
`# Local API gateway (Kong), unique per project so multiple stacks can run concurrently
|
|
1225
1225
|
SUPATYPE_KONG_PORT=${opts.kongPort}
|
|
1226
1226
|
PUBLIC_SUPATYPE_URL=${apiUrl}
|
|
1227
1227
|
API_EXTERNAL_URL=${apiUrl}
|
|
@@ -1235,7 +1235,7 @@ VITE_SUPATYPE_ANON_KEY=`,
|
|
|
1235
1235
|
|
|
1236
1236
|
if (opts.adminEmail && opts.adminPassword) {
|
|
1237
1237
|
sections.push(
|
|
1238
|
-
`# First admin for /admin
|
|
1238
|
+
`# First admin for /admin, consumed on first supatype dev or push (password removed after use)
|
|
1239
1239
|
SUPATYPE_ADMIN_EMAIL=${opts.adminEmail}
|
|
1240
1240
|
SUPATYPE_ADMIN_PASSWORD=${opts.adminPassword}`,
|
|
1241
1241
|
)
|
|
@@ -1269,7 +1269,7 @@ SMTP_PASS=
|
|
|
1269
1269
|
SMTP_SENDER_NAME=${projectName}`
|
|
1270
1270
|
case "console":
|
|
1271
1271
|
default:
|
|
1272
|
-
return `# SMTP
|
|
1272
|
+
return `# SMTP: leave empty to use email autoconfirm in dev (no emails sent)
|
|
1273
1273
|
SMTP_HOST=
|
|
1274
1274
|
SMTP_PORT=
|
|
1275
1275
|
SMTP_USER=
|
|
@@ -1284,7 +1284,7 @@ function storageEnvSections(
|
|
|
1284
1284
|
): string {
|
|
1285
1285
|
if (storageLocal === storageProduction) {
|
|
1286
1286
|
if (storageLocal === "s3") {
|
|
1287
|
-
return `# Storage (local development and production
|
|
1287
|
+
return `# Storage (local development and production, external bucket)
|
|
1288
1288
|
# Use separate buckets for dev and production in your provider.
|
|
1289
1289
|
S3_ENDPOINT=
|
|
1290
1290
|
S3_REGION=us-east-1
|
|
@@ -1295,7 +1295,7 @@ S3_SECRET_KEY=`
|
|
|
1295
1295
|
return `${localStorageEnvSection("local")}
|
|
1296
1296
|
|
|
1297
1297
|
# Production storage (MinIO on your server)
|
|
1298
|
-
# Included in the self-host compose stack
|
|
1298
|
+
# Included in the self-host compose stack, no extra configuration needed.`
|
|
1299
1299
|
}
|
|
1300
1300
|
|
|
1301
1301
|
return [localStorageEnvSection(storageLocal), productionStorageEnvSection(storageProduction)].join(
|
|
@@ -1305,14 +1305,14 @@ S3_SECRET_KEY=`
|
|
|
1305
1305
|
|
|
1306
1306
|
function localStorageEnvSection(storage: StorageProvider): string {
|
|
1307
1307
|
if (storage === "s3") {
|
|
1308
|
-
return `# Storage (local development
|
|
1308
|
+
return `# Storage (local development, external bucket)
|
|
1309
1309
|
S3_ENDPOINT=
|
|
1310
1310
|
S3_REGION=us-east-1
|
|
1311
1311
|
S3_BUCKET=
|
|
1312
1312
|
S3_ACCESS_KEY=
|
|
1313
1313
|
S3_SECRET_KEY=`
|
|
1314
1314
|
}
|
|
1315
|
-
return `# Storage (local development
|
|
1315
|
+
return `# Storage (local development, MinIO)
|
|
1316
1316
|
S3_ENDPOINT=http://localhost:9000
|
|
1317
1317
|
S3_ACCESS_KEY=supatype
|
|
1318
1318
|
S3_SECRET_KEY=supatype-secret`
|
|
@@ -1320,15 +1320,15 @@ S3_SECRET_KEY=supatype-secret`
|
|
|
1320
1320
|
|
|
1321
1321
|
function productionStorageEnvSection(storage: StorageProvider): string {
|
|
1322
1322
|
if (storage === "s3") {
|
|
1323
|
-
return `# Storage (production
|
|
1323
|
+
return `# Storage (production, external bucket)
|
|
1324
1324
|
S3_ENDPOINT=
|
|
1325
1325
|
S3_REGION=us-east-1
|
|
1326
1326
|
S3_BUCKET=
|
|
1327
1327
|
S3_ACCESS_KEY=
|
|
1328
1328
|
S3_SECRET_KEY=`
|
|
1329
1329
|
}
|
|
1330
|
-
return `# Storage (production
|
|
1331
|
-
# Included in the self-host compose stack
|
|
1330
|
+
return `# Storage (production, MinIO on your server)
|
|
1331
|
+
# Included in the self-host compose stack, no extra configuration needed.`
|
|
1332
1332
|
}
|
|
1333
1333
|
|
|
1334
1334
|
function seedTemplate(projectName: string): string {
|
|
@@ -1358,7 +1358,7 @@ seed().catch((e) => {
|
|
|
1358
1358
|
}
|
|
1359
1359
|
|
|
1360
1360
|
function helloFunctionTemplate(): string {
|
|
1361
|
-
return `// hello
|
|
1361
|
+
return `// hello: Supatype Edge Function
|
|
1362
1362
|
// Docs: https://supatype.com/docs/edge-functions
|
|
1363
1363
|
|
|
1364
1364
|
export default async function handler(req: Request): Promise<Response> {
|
|
@@ -1397,7 +1397,7 @@ dist/
|
|
|
1397
1397
|
supatype.local.config.ts
|
|
1398
1398
|
supatype.local.config.js
|
|
1399
1399
|
supatype.local.config.mjs
|
|
1400
|
-
# Generated by supatype push (legacy paths
|
|
1400
|
+
# Generated by supatype push (legacy paths, prefer output.types in config)
|
|
1401
1401
|
src/types/supatype.d.ts
|
|
1402
1402
|
src/lib/supatype.ts
|
|
1403
1403
|
`
|
|
@@ -1408,7 +1408,7 @@ export function mergeGitignoreTemplate(existingContent: string): string {
|
|
|
1408
1408
|
return existingContent
|
|
1409
1409
|
}
|
|
1410
1410
|
const block = `
|
|
1411
|
-
# Supatype
|
|
1411
|
+
# Supatype: local runtime (contains secrets in link.json)
|
|
1412
1412
|
.supatype/
|
|
1413
1413
|
`
|
|
1414
1414
|
return existingContent.endsWith("\n") ? `${existingContent}${block}` : `${existingContent}\n${block}`
|
|
@@ -1460,9 +1460,9 @@ function printNextSteps(args: {
|
|
|
1460
1460
|
nextSteps(setupComplete ? "Next steps:" : "Finish setup:", steps)
|
|
1461
1461
|
|
|
1462
1462
|
// Shown once, at creation. These are generated per project rather than shipped as
|
|
1463
|
-
// constants, so this is the moment to say they exist and where they live
|
|
1463
|
+
// constants, so this is the moment to say they exist and where they live, nothing prints
|
|
1464
1464
|
// them again, and the JWT secret is only echoed as a fingerprint from here on.
|
|
1465
|
-
nextSteps("Secrets
|
|
1465
|
+
nextSteps("Secrets: generated for this project, kept in .env:", [
|
|
1466
1466
|
"POSTGRES_PASSWORD direct SQL access as the superuser",
|
|
1467
1467
|
"AUTHENTICATOR_PASSWORD PostgREST's own login; rotating the one above does not affect it",
|
|
1468
1468
|
"JWT_SECRET signs ANON_KEY and SERVICE_ROLE_KEY; changing it invalidates every token",
|
|
@@ -1496,7 +1496,7 @@ function printNextSteps(args: {
|
|
|
1496
1496
|
selfHostSteps.push("supatype self-host compose up -d # Kong provisions HTTPS automatically")
|
|
1497
1497
|
selfHostSteps.push(`Your Supatype platform goes live at https://${domain}`)
|
|
1498
1498
|
selfHostSteps.push(
|
|
1499
|
-
"Your app, REST, Auth, Storage, Realtime, Functions, and Studio
|
|
1499
|
+
"Your app, REST, Auth, Storage, Realtime, Functions, and Studio, all behind one HTTPS domain (certs persist in valkey-data)",
|
|
1500
1500
|
)
|
|
1501
1501
|
} else {
|
|
1502
1502
|
selfHostSteps.push(
|
package/src/commands/login.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cloud session login / logout for CLI control-plane auth.
|
|
3
|
-
* Self-host uses SERVICE_ROLE_KEY via `supatype link --url
|
|
3
|
+
* Self-host uses SERVICE_ROLE_KEY via `supatype link --url`, not this command.
|
|
4
4
|
*/
|
|
5
5
|
import type { Command } from "commander"
|
|
6
6
|
import {
|
|
@@ -77,7 +77,7 @@ export function registerLogin(program: Command): void {
|
|
|
77
77
|
if (link?.kind === "cloud") {
|
|
78
78
|
info(`Updated cloud session for linked project ${link.projectRef}`)
|
|
79
79
|
} else if (!session.refreshToken) {
|
|
80
|
-
plain("Warning: no refresh_token returned
|
|
80
|
+
plain("Warning: no refresh_token returned, session may expire in ~1h. Update control plane.")
|
|
81
81
|
} else {
|
|
82
82
|
plain("Tip: link a project with: supatype link --project <slug>")
|
|
83
83
|
}
|
package/src/commands/logs.ts
CHANGED
package/src/commands/migrate.ts
CHANGED
|
@@ -58,9 +58,9 @@ export function registerMigrate(program: Command): void {
|
|
|
58
58
|
const size =
|
|
59
59
|
manifest?.compressedBytes !== undefined
|
|
60
60
|
? `${(manifest.compressedBytes / 1024).toFixed(1)} KB`
|
|
61
|
-
: "
|
|
62
|
-
const files = manifest?.fileCount ?? "
|
|
63
|
-
const author = manifest?.pushedBy ?? "
|
|
61
|
+
: "-"
|
|
62
|
+
const files = manifest?.fileCount ?? "-"
|
|
63
|
+
const author = manifest?.pushedBy ?? "-"
|
|
64
64
|
const rolled = m.rolledBack ? " (rolled back)" : ""
|
|
65
65
|
plain(
|
|
66
66
|
`${m.name}${rolled}\n applied: ${m.appliedAt} status: ${m.status}\n author: ${author} files: ${files} snapshot: ${size}`,
|
|
@@ -212,7 +212,7 @@ async function offerSchemaRestore(
|
|
|
212
212
|
const manifestPaths = new Set(manifest.files.map((f) => f.path))
|
|
213
213
|
const orphans = findOrphanSchemaFiles(root, manifest.entryPoint, manifestPaths)
|
|
214
214
|
for (const orphan of orphans) {
|
|
215
|
-
warn(`${orphan} not in snapshot
|
|
215
|
+
warn(`${orphan} not in snapshot, review manually`)
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
info(`Restored schema files from migration ${label}.`)
|
|
@@ -222,6 +222,6 @@ async function offerSchemaRestore(
|
|
|
222
222
|
if ((postDiff.operations ?? []).length === 0) {
|
|
223
223
|
info("Schema matches database after restore.")
|
|
224
224
|
} else {
|
|
225
|
-
info("Run `supatype diff
|
|
225
|
+
info("Run `supatype diff`: schema may still differ from database.")
|
|
226
226
|
}
|
|
227
227
|
}
|
package/src/commands/pg.ts
CHANGED
package/src/commands/plugins.ts
CHANGED
package/src/commands/pull.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { info, plain } from "../ui/messages.js"
|
|
|
10
10
|
export function registerPull(program: Command): void {
|
|
11
11
|
program
|
|
12
12
|
.command("pull")
|
|
13
|
-
.description("Scaffold schema/index.ts from live database introspection (draft
|
|
13
|
+
.description("Scaffold schema/index.ts from live database introspection (draft, review before push)")
|
|
14
14
|
.option("--connection <url>", "Database connection URL (overrides config)")
|
|
15
15
|
.option("--out <path>", "Write scaffold to file (default: stdout)")
|
|
16
16
|
.option("--dry-run", "Print scaffold to stdout without writing files")
|
|
@@ -34,7 +34,7 @@ export function registerPull(program: Command): void {
|
|
|
34
34
|
if (opts.dryRun || !opts.out) {
|
|
35
35
|
plain(scaffold)
|
|
36
36
|
if (!opts.dryRun && !opts.out) {
|
|
37
|
-
info("(draft printed to stdout
|
|
37
|
+
info("(draft printed to stdout, use --out to write a file)")
|
|
38
38
|
}
|
|
39
39
|
return
|
|
40
40
|
}
|
package/src/commands/push.ts
CHANGED
|
@@ -167,7 +167,7 @@ async function pushViaTarget(
|
|
|
167
167
|
await generateTypesLocal(ast, config)
|
|
168
168
|
await provisionLocalStorage(ast, config)
|
|
169
169
|
|
|
170
|
-
// Local Studio only
|
|
170
|
+
// Local Studio only: a cloud/self-host push must not advertise the local
|
|
171
171
|
// gateway URL from config, which may not even be running.
|
|
172
172
|
const baseUrl = (serverBaseUrl(config) ?? "").replace(/\/$/, "")
|
|
173
173
|
if (baseUrl) {
|
|
@@ -191,7 +191,7 @@ async function pushViaTarget(
|
|
|
191
191
|
* into a 503.
|
|
192
192
|
*
|
|
193
193
|
* The handler types are written locally as well. A project pushing to cloud still edits its hooks on
|
|
194
|
-
* this machine, and `hooks/_supatype/hooks.ts` is what makes them typed
|
|
194
|
+
* this machine, and `hooks/_supatype/hooks.ts` is what makes them typed, it is generated, never
|
|
195
195
|
* committed, so a fresh clone that has only ever pushed to cloud would otherwise have no types at all.
|
|
196
196
|
*/
|
|
197
197
|
async function deployHooksToTarget(
|
|
@@ -285,7 +285,7 @@ async function writeLocalAdminConfig(ast: unknown, config: SupatypeProjectConfig
|
|
|
285
285
|
* Stop the push when a declared hook names a function that is not there.
|
|
286
286
|
*
|
|
287
287
|
* A hook is only enforcement if it runs. A typo'd name would extract cleanly, reach the manifest, and
|
|
288
|
-
* then never fire
|
|
288
|
+
* then never fire: so the write it was meant to validate would succeed and look fine. Cheaper to
|
|
289
289
|
* fail here, naming the directory searched.
|
|
290
290
|
*/
|
|
291
291
|
/**
|
|
@@ -1,139 +1,89 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
* supatype self-update — Phase 10.6C8.
|
|
4
|
-
|
|
2
|
+
* supatype self-update
|
|
5
3
|
*
|
|
6
|
-
|
|
7
4
|
* npm-installed CLI: instruct to use `npm update -g`.
|
|
8
|
-
|
|
9
5
|
* Homebrew: instruct to use `brew upgrade supatype`.
|
|
10
|
-
|
|
11
|
-
* Standalone curl|sh installs: replace binary from releases.supatype.com/cli/.
|
|
12
|
-
|
|
6
|
+
* Standalone curl|sh installs: replace the binary from releases.supatype.com/cli/.
|
|
13
7
|
*/
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
9
|
import type { Command } from "commander"
|
|
18
|
-
|
|
19
10
|
import { copyFileSync, renameSync } from "node:fs"
|
|
20
|
-
|
|
21
|
-
import { detectCliInstallMethod } from "../cli-install-method.js"
|
|
22
|
-
|
|
11
|
+
import { cliPackageVersion } from "../cli-package-version.js"
|
|
12
|
+
import { detectCliInstallMethod, runningBinaryPath } from "../cli-install-method.js"
|
|
23
13
|
import { downloadStandaloneCli, fetchStandaloneCliLatestVersion } from "../cli-standalone.js"
|
|
24
|
-
|
|
25
14
|
import { error, info, plain } from "../ui/messages.js"
|
|
26
15
|
|
|
27
|
-
|
|
28
|
-
|
|
29
16
|
export function registerSelfUpdate(program: Command): void {
|
|
30
|
-
|
|
31
17
|
program
|
|
32
|
-
|
|
33
18
|
.command("self-update")
|
|
34
|
-
|
|
35
19
|
.description("Update the supatype CLI (npm or standalone CDN binary)")
|
|
36
|
-
|
|
37
|
-
.action(async () => {
|
|
38
|
-
|
|
20
|
+
.option("--force", "Reinstall even if the latest version is already installed")
|
|
21
|
+
.action(async (opts: { force?: boolean }) => {
|
|
39
22
|
const method = detectCliInstallMethod()
|
|
40
23
|
|
|
41
|
-
|
|
42
|
-
|
|
43
24
|
if (method === "npm") {
|
|
44
|
-
|
|
45
25
|
plain(
|
|
46
|
-
|
|
47
26
|
"This CLI was installed via npm (or runs from the package workspace).\n" +
|
|
48
|
-
|
|
49
27
|
"Update with:\n\n npm update -g @supatype/cli\n\n" +
|
|
50
|
-
|
|
51
28
|
"To bump engine/server/postgres/deno/realtime pinned in supatype.config.ts, use:\n\n supatype update\n",
|
|
52
|
-
|
|
53
29
|
)
|
|
54
|
-
|
|
55
30
|
return
|
|
56
|
-
|
|
57
31
|
}
|
|
58
32
|
|
|
59
|
-
|
|
60
|
-
|
|
61
33
|
if (method === "homebrew") {
|
|
62
|
-
|
|
63
34
|
plain(
|
|
64
|
-
|
|
65
35
|
"This CLI was installed via Homebrew.\n" +
|
|
66
|
-
|
|
67
36
|
"Update with:\n\n brew update && brew upgrade supatype\n\n" +
|
|
68
|
-
|
|
69
37
|
"To bump component binaries pinned in supatype.config.ts, use:\n\n supatype update\n",
|
|
70
|
-
|
|
71
38
|
)
|
|
72
|
-
|
|
73
39
|
return
|
|
74
|
-
|
|
75
40
|
}
|
|
76
41
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const currentPath =
|
|
80
|
-
|
|
42
|
+
// The binary on disk, not argv[1]: in a compiled binary argv[1] points into the embedded
|
|
43
|
+
// filesystem, so backing it up failed with ENOENT and no update could ever complete.
|
|
44
|
+
const currentPath = runningBinaryPath()
|
|
81
45
|
if (!currentPath) {
|
|
82
|
-
|
|
83
46
|
error("Could not determine current CLI path.")
|
|
84
|
-
|
|
85
47
|
process.exit(1)
|
|
86
|
-
|
|
87
48
|
}
|
|
88
49
|
|
|
89
|
-
|
|
90
|
-
|
|
91
50
|
try {
|
|
92
|
-
|
|
93
51
|
const latest = await fetchStandaloneCliLatestVersion()
|
|
52
|
+
const current = cliPackageVersion()
|
|
53
|
+
|
|
54
|
+
// Without this the command re-downloaded on every run: it compared nothing, so a
|
|
55
|
+
// machine already on the latest version fetched and rewrote the same binary.
|
|
56
|
+
if (latest === current && !opts.force) {
|
|
57
|
+
info(`Already on v${current}, the latest release.`)
|
|
58
|
+
plain("Reinstall anyway with `supatype self-update --force`.")
|
|
59
|
+
return
|
|
60
|
+
}
|
|
94
61
|
|
|
95
|
-
info(
|
|
96
|
-
|
|
62
|
+
info(
|
|
63
|
+
latest === current
|
|
64
|
+
? `Reinstalling v${latest}...`
|
|
65
|
+
: `Downloading supatype CLI v${latest} (current: v${current})...`,
|
|
66
|
+
)
|
|
97
67
|
const downloaded = await downloadStandaloneCli(latest)
|
|
98
68
|
|
|
99
69
|
const backup = `${currentPath}.bak`
|
|
100
|
-
|
|
101
70
|
copyFileSync(currentPath, backup)
|
|
102
|
-
|
|
103
71
|
try {
|
|
104
|
-
|
|
105
72
|
renameSync(downloaded, currentPath)
|
|
106
|
-
|
|
107
73
|
} catch {
|
|
108
|
-
|
|
109
74
|
copyFileSync(downloaded, currentPath)
|
|
110
|
-
|
|
111
75
|
}
|
|
112
76
|
|
|
113
77
|
info(`Updated to v${latest}.`)
|
|
114
|
-
|
|
115
78
|
plain("Run `supatype --version` to verify.")
|
|
116
|
-
|
|
117
79
|
} catch (err) {
|
|
118
|
-
|
|
119
80
|
error(
|
|
120
|
-
|
|
121
81
|
`Standalone CLI self-update failed: ${(err as Error).message}\n\n` +
|
|
122
|
-
|
|
123
82
|
"Install or upgrade via npm:\n npm install -g @supatype/cli\n\n" +
|
|
124
|
-
|
|
125
83
|
"Or Homebrew:\n brew upgrade supatype\n\n" +
|
|
126
|
-
|
|
127
84
|
"Component binaries (engine, server, postgres, deno, realtime):\n supatype update\n",
|
|
128
|
-
|
|
129
85
|
)
|
|
130
|
-
|
|
131
86
|
process.exit(1)
|
|
132
|
-
|
|
133
87
|
}
|
|
134
|
-
|
|
135
88
|
})
|
|
136
|
-
|
|
137
89
|
}
|
|
138
|
-
|
|
139
|
-
|
package/src/commands/status.ts
CHANGED
package/src/commands/update.ts
CHANGED
package/src/config.ts
CHANGED
|
@@ -72,7 +72,7 @@ export interface AppConfig {
|
|
|
72
72
|
headers?: Record<string, string>
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
/** Identity helper
|
|
75
|
+
/** Identity helper: provides type inference for config files. */
|
|
76
76
|
export function defineConfig(config: SupatypeProjectConfig): SupatypeProjectConfig {
|
|
77
77
|
return config
|
|
78
78
|
}
|
|
@@ -137,7 +137,7 @@ export function loadConfig(cwd: string = process.cwd()): SupatypeProjectConfig {
|
|
|
137
137
|
|
|
138
138
|
const localNorm = normalizeProjectJson(localRaw) as Partial<SupatypeProjectConfig>
|
|
139
139
|
// Re-validated after merging: the local override can reintroduce a combination the base file was
|
|
140
|
-
// rejected for
|
|
140
|
+
// rejected for: `database.provider` beside an inherited `database.external`, say, and merging
|
|
141
141
|
// has no opinion about that.
|
|
142
142
|
return validateProjectConfig(
|
|
143
143
|
mergeProjectConfig(base, localNorm),
|
|
@@ -149,7 +149,7 @@ export function loadConfig(cwd: string = process.cwd()): SupatypeProjectConfig {
|
|
|
149
149
|
* Environment for the child process that imports the config module.
|
|
150
150
|
*
|
|
151
151
|
* `supatype.config.ts` is TypeScript, so the natural way to keep a database password out of version
|
|
152
|
-
* control is `process.env.DATABASE_URL
|
|
152
|
+
* control is `process.env.DATABASE_URL`: which only works if the project's `.env` is visible to the
|
|
153
153
|
* process doing the import. A real environment variable still wins over the file, matching how every
|
|
154
154
|
* other dotenv reader behaves and how Compose itself resolves the same names.
|
|
155
155
|
*/
|