@supatype/cli 0.1.7 → 0.1.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 +1 -1
- package/.turbo/turbo-test.log +125 -122
- 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 +17 -1
- package/dist/cli-install-method.d.ts.map +1 -1
- package/dist/cli-install-method.js +32 -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 +4 -3
- 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.d.ts.map +1 -1
- package/dist/commands/db.js +12 -11
- 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.d.ts.map +1 -1
- package/dist/commands/functions.js +8 -7
- 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/internal.d.ts.map +1 -1
- package/dist/commands/internal.js +37 -0
- package/dist/commands/internal.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 +23 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +37 -18
- 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.d.ts.map +1 -1
- package/dist/resolve-api-url.js +4 -3
- 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.d.ts +12 -0
- package/dist/tsx-runner.d.ts.map +1 -1
- package/dist/tsx-runner.js +36 -2
- 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 +35 -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 +4 -3
- 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 +12 -11
- 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 +8 -7
- package/src/commands/hooks.ts +6 -6
- package/src/commands/init.ts +28 -28
- package/src/commands/internal.ts +37 -0
- 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 +39 -18
- 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 +4 -3
- 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 +41 -2
- 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/config-load-failure.test.ts +44 -0
- 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
package/src/dev-log-filter.ts
CHANGED
|
@@ -48,7 +48,7 @@ export function filterStackLogLine(line: string): boolean {
|
|
|
48
48
|
return false
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
/** Drop docker noise only
|
|
51
|
+
/** Drop docker noise only, keep diff tables, push status, and command output. */
|
|
52
52
|
export function filterCommandLogLine(line: string): boolean {
|
|
53
53
|
const t = stripAnsi(line).trim()
|
|
54
54
|
if (!t) return false
|
package/src/dev-ports.ts
CHANGED
|
@@ -60,7 +60,7 @@ async function promptPortConflict(
|
|
|
60
60
|
export interface EnsureKongPortOptions {
|
|
61
61
|
/** When false, fail fast instead of prompting (CI / scripts). */
|
|
62
62
|
interactive?: boolean
|
|
63
|
-
/** init wizard
|
|
63
|
+
/** init wizard: slightly different copy */
|
|
64
64
|
context?: "dev" | "init"
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -102,7 +102,7 @@ export async function ensureKongPort(
|
|
|
102
102
|
return port
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
/** Wizard / init
|
|
105
|
+
/** Wizard / init: pick a Kong port without writing `.env` (scaffold writes it). */
|
|
106
106
|
export async function promptKongPortChoice(): Promise<number> {
|
|
107
107
|
const freeDefault = (await isPortInUse(COMPOSE_DEV_KONG_PORT))
|
|
108
108
|
? await findNextFreePort(COMPOSE_DEV_KONG_PORT)
|
|
@@ -139,7 +139,7 @@ async function promptPortConflictWithoutPersist(
|
|
|
139
139
|
const headline =
|
|
140
140
|
reason === "init"
|
|
141
141
|
? `Port ${blockedPort} is already in use on this machine.`
|
|
142
|
-
: `Port ${blockedPort} is in use
|
|
142
|
+
: `Port ${blockedPort} is in use, another Supatype project or service may already be bound to it.`
|
|
143
143
|
|
|
144
144
|
const choice = await p.select<"suggested" | "custom" | "cancel">({
|
|
145
145
|
message: headline,
|
package/src/dev-session.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `supatype dev` output session
|
|
2
|
+
* `supatype dev` output session, Ink dashboard (default) or interleaved stream mode.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { render, type Instance } from "ink"
|
|
@@ -32,7 +32,7 @@ export function beginDevSession(mode: DevUiMode): DevSession {
|
|
|
32
32
|
return activeSession
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
/** @deprecated Ink starts in beginDevSession
|
|
35
|
+
/** @deprecated Ink starts in beginDevSession, kept for callers that invoke late. */
|
|
36
36
|
export function startDevSession(): void {
|
|
37
37
|
activeSession?.startInk()
|
|
38
38
|
}
|
|
@@ -47,7 +47,7 @@ export function endDevSession(): void {
|
|
|
47
47
|
activeSession = null
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/** @deprecated Dev prompts render inside the Ink dashboard
|
|
50
|
+
/** @deprecated Dev prompts render inside the Ink dashboard, no suspend needed. */
|
|
51
51
|
export function suspendDevSessionForPrompt(): void {
|
|
52
52
|
prepareStdinForInteractivePrompt()
|
|
53
53
|
}
|
|
@@ -58,12 +58,12 @@ export function prepareStdinForInteractivePrompt(): void {
|
|
|
58
58
|
process.stdin.resume()
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/** @deprecated Dev prompts render inside the Ink dashboard
|
|
61
|
+
/** @deprecated Dev prompts render inside the Ink dashboard, no resume needed. */
|
|
62
62
|
export function resumeDevSessionAfterPrompt(): void {
|
|
63
|
-
// no-op
|
|
63
|
+
// no-op: prompts are Ink overlays
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
/** @deprecated Use Ink overlay prompts
|
|
66
|
+
/** @deprecated Use Ink overlay prompts, runs fn without tearing down the dashboard. */
|
|
67
67
|
export async function withDevSessionSuspended<T>(fn: () => Promise<T>): Promise<T> {
|
|
68
68
|
return fn()
|
|
69
69
|
}
|
package/src/dev-shutdown.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Graceful shutdown for `supatype dev
|
|
2
|
+
* Graceful shutdown for `supatype dev`, SIGINT, TUI Ctrl+C, terminal close,
|
|
3
3
|
* and a synchronous compose-down fallback on process exit.
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -23,7 +23,7 @@ let forceQuitRequested = false
|
|
|
23
23
|
let hooksRegistered = false
|
|
24
24
|
let ignoreSigintUntil = 0
|
|
25
25
|
|
|
26
|
-
/** SIGINT/SIGTERM hooks
|
|
26
|
+
/** SIGINT/SIGTERM hooks: call as soon as `supatype dev` starts (before compose is up). */
|
|
27
27
|
export function ensureDevShutdownHooks(): void {
|
|
28
28
|
if (hooksRegistered) return
|
|
29
29
|
hooksRegistered = true
|
|
@@ -62,7 +62,7 @@ function syncComposeDownFallback(): void {
|
|
|
62
62
|
{ quiet: true },
|
|
63
63
|
)
|
|
64
64
|
} catch {
|
|
65
|
-
// best-effort
|
|
65
|
+
// best-effort: process is exiting
|
|
66
66
|
}
|
|
67
67
|
if (shutdownCwd) clearDevSessionLock(shutdownCwd)
|
|
68
68
|
}
|
|
@@ -74,7 +74,7 @@ function onProcessExit(): void {
|
|
|
74
74
|
export interface RegisterDevShutdownOptions {
|
|
75
75
|
/** Sync `docker compose down` when async teardown cannot finish (terminal close, kill). */
|
|
76
76
|
compose?: DevComposeShutdownFallback
|
|
77
|
-
/** Project root
|
|
77
|
+
/** Project root: clears `.supatype/dev-session.json` after shutdown. */
|
|
78
78
|
cwd?: string
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -89,7 +89,7 @@ export function registerDevShutdown(
|
|
|
89
89
|
ensureDevShutdownHooks()
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
/** TUI Ctrl+C
|
|
92
|
+
/** TUI Ctrl+C: do not re-emit SIGINT (avoids double-fire on Windows raw mode). */
|
|
93
93
|
export function requestDevShutdown(): void {
|
|
94
94
|
ignoreSigintUntil = Date.now() + 400
|
|
95
95
|
void runDevShutdown()
|
|
@@ -99,7 +99,7 @@ export function isDevShuttingDown(): boolean {
|
|
|
99
99
|
return shuttingDown
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
/** @internal Tests
|
|
102
|
+
/** @internal Tests: reset module state between cases. */
|
|
103
103
|
export function resetDevShutdownForTests(): void {
|
|
104
104
|
shutdownWork = null
|
|
105
105
|
composeFallback = null
|
|
@@ -125,7 +125,7 @@ async function runDevShutdown(): Promise<void> {
|
|
|
125
125
|
} catch {
|
|
126
126
|
// best-effort terminal restore
|
|
127
127
|
}
|
|
128
|
-
process.stderr.write("\n[supatype] Forced quit
|
|
128
|
+
process.stderr.write("\n[supatype] Forced quit: Docker containers may still be running.\n")
|
|
129
129
|
process.stdout.write("\n")
|
|
130
130
|
process.exit(130)
|
|
131
131
|
}
|
|
@@ -145,7 +145,7 @@ async function runDevShutdown(): Promise<void> {
|
|
|
145
145
|
} catch (err) {
|
|
146
146
|
process.stderr.write(`[supatype] Shutdown failed: ${(err as Error).message}\n`)
|
|
147
147
|
process.stderr.write(
|
|
148
|
-
"[supatype] Docker containers may still be running
|
|
148
|
+
"[supatype] Docker containers may still be running, try: supatype self-host compose down\n",
|
|
149
149
|
)
|
|
150
150
|
syncComposeDownFallback()
|
|
151
151
|
shutdownCompleted = true
|
package/src/dev-task-colors.ts
CHANGED
|
@@ -30,7 +30,7 @@ export function levelColor(line: string): string | null {
|
|
|
30
30
|
return null
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
/** Drop redundant prefix
|
|
33
|
+
/** Drop redundant prefix: task pane is already labelled supatype. */
|
|
34
34
|
export function normalizeStackLogLine(line: string): string {
|
|
35
35
|
return line.replace(/^\[supatype\]\s*/, "")
|
|
36
36
|
}
|
package/src/docker-postgres.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* docker-postgres
|
|
2
|
+
* docker-postgres: manage a supatype/postgres Docker container for local dev.
|
|
3
3
|
*
|
|
4
4
|
* Used by `supatype dev` when database.provider = "docker".
|
|
5
5
|
* The container is named supatype-{projectName} and persists data in a
|
|
@@ -11,7 +11,7 @@ import { spawnSync } from "node:child_process"
|
|
|
11
11
|
export interface DockerPgOptions {
|
|
12
12
|
/** Docker image to run. Defaults to supatype/postgres:latest. */
|
|
13
13
|
image: string
|
|
14
|
-
/** Project name
|
|
14
|
+
/** Project name: used to derive the container and volume names. */
|
|
15
15
|
projectName: string
|
|
16
16
|
/** Host port to bind to container's 5432. */
|
|
17
17
|
port: number
|
|
@@ -85,7 +85,7 @@ export function dockerPgStart(opts: DockerPgOptions): void {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* Stop the container (fast
|
|
88
|
+
* Stop the container (fast, does not remove it or the data volume).
|
|
89
89
|
* Safe to call even if the container is not running.
|
|
90
90
|
*/
|
|
91
91
|
export function dockerPgStop(projectName: string): void {
|
|
@@ -120,7 +120,7 @@ export function dockerPgPostInitServing(logs: string): boolean {
|
|
|
120
120
|
|
|
121
121
|
const initDone = logs.lastIndexOf("PostgreSQL init process complete")
|
|
122
122
|
if (initDone === -1) {
|
|
123
|
-
// Reused data volume
|
|
123
|
+
// Reused data volume: this run did not re-run entrypoint init.
|
|
124
124
|
return true
|
|
125
125
|
}
|
|
126
126
|
return initDone < lastReady
|
|
@@ -240,7 +240,7 @@ export function dockerDbUrl(projectName: string, port: number, password = DEFAUL
|
|
|
240
240
|
/**
|
|
241
241
|
* DB URL for processes sharing the Postgres container network namespace
|
|
242
242
|
* (supatype-server migrate in a one-shot container). Uses loopback inside the
|
|
243
|
-
* container where pg_hba grants trust
|
|
243
|
+
* container where pg_hba grants trust, avoids host-published-port SCRAM/SSL issues.
|
|
244
244
|
*/
|
|
245
245
|
export function dockerPgLoopbackDbUrl(projectName: string, password = DEFAULT_DEV_PASSWORD): string {
|
|
246
246
|
return `postgres://${PG_USER}:${password}@127.0.0.1:5432/${projectName}?sslmode=disable`
|
|
@@ -254,7 +254,7 @@ export const DEFAULT_SERVER_DOCKER_IMAGE = "supatype/server:latest"
|
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
256
|
* Run `supatype-server migrate` on the Postgres container network (loopback trust).
|
|
257
|
-
* Used on Windows + database.provider docker
|
|
257
|
+
* Used on Windows + database.provider docker, host-published :5432 breaks libpq TLS there.
|
|
258
258
|
*/
|
|
259
259
|
export function runGotrueMigrationsViaDocker(
|
|
260
260
|
pgContainerName: string,
|
package/src/docker-runtime.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Docker daemon availability
|
|
2
|
+
* Docker daemon availability: used before `docker compose` and other docker CLI calls.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { spawnSync } from "node:child_process"
|
|
@@ -41,7 +41,7 @@ export function probeDockerDaemon(): DockerDaemonProbe {
|
|
|
41
41
|
const versionStderr = (version.stderr ?? "").trim()
|
|
42
42
|
const versionDetail = `${versionStderr}${version.stdout ?? ""}`.trim()
|
|
43
43
|
|
|
44
|
-
// No client version
|
|
44
|
+
// No client version: CLI missing or broken.
|
|
45
45
|
if (!clientVersion) {
|
|
46
46
|
return {
|
|
47
47
|
ok: false,
|
|
@@ -51,7 +51,7 @@ export function probeDockerDaemon(): DockerDaemonProbe {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Client is present but daemon refused (paused/stopped). `docker info` can hang
|
|
54
|
-
// while paused on Docker Desktop
|
|
54
|
+
// while paused on Docker Desktop, use the version stderr and skip info.
|
|
55
55
|
if (version.status !== 0 && versionStderr) {
|
|
56
56
|
return { ok: false, reason: "daemon_unavailable", detail: versionStderr }
|
|
57
57
|
}
|
|
@@ -104,7 +104,7 @@ function dockerUnavailableHints(probe: Extract<DockerDaemonProbe, { ok: false }>
|
|
|
104
104
|
return hints
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
/** @deprecated Tests only
|
|
107
|
+
/** @deprecated Tests only: use `reportDockerUnavailable`. */
|
|
108
108
|
export function formatDockerUnavailableMessage(
|
|
109
109
|
probe: Extract<DockerDaemonProbe, { ok: false }>,
|
|
110
110
|
): string {
|
|
@@ -142,7 +142,7 @@ export function reportDockerUnavailable(
|
|
|
142
142
|
export function requireDockerDaemon(opts?: DockerReportOptions): void {
|
|
143
143
|
const probe = probeDockerDaemon()
|
|
144
144
|
if (probe.ok) return
|
|
145
|
-
// Dev TUI patches console
|
|
145
|
+
// Dev TUI patches console, restore stderr before printing a fatal message.
|
|
146
146
|
if (getActiveDevSession()) {
|
|
147
147
|
endDevSession()
|
|
148
148
|
}
|
package/src/engine-client.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* engine-client.ts
|
|
2
|
+
* engine-client.ts: subprocess-based engine invocation.
|
|
3
3
|
*
|
|
4
4
|
* Replaces the former HTTP-based engine client (Docker container API).
|
|
5
5
|
* All callers use the same interface; only the transport changed.
|
|
@@ -99,7 +99,7 @@ async function getEngineBin(): Promise<string> {
|
|
|
99
99
|
// Otherwise (no valid project config) fall through to default cache scan.
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// No config found
|
|
102
|
+
// No config found: scan the cache for any available engine binary.
|
|
103
103
|
const platform = currentPlatform()
|
|
104
104
|
const engineCacheDir = join(homedir(), ".supatype", "cache", "engine")
|
|
105
105
|
try {
|
|
@@ -208,7 +208,7 @@ export async function engineRequest<T = unknown>(
|
|
|
208
208
|
try {
|
|
209
209
|
return JSON.parse(result.stdout) as T
|
|
210
210
|
} catch {
|
|
211
|
-
// Non-JSON stdout
|
|
211
|
+
// Non-JSON stdout: return as message.
|
|
212
212
|
return { message: result.stdout.trim() } as T
|
|
213
213
|
}
|
|
214
214
|
}
|
|
@@ -43,7 +43,7 @@ export function parseEnginePushOutput(output: string): EnginePushResult | null {
|
|
|
43
43
|
export function formatEnginePushMessage(result: EnginePushResult): string {
|
|
44
44
|
if (result.status === "up_to_date") {
|
|
45
45
|
if (result.admin_refreshed) {
|
|
46
|
-
return "Schema up to date
|
|
46
|
+
return "Schema up to date, Studio metadata synced."
|
|
47
47
|
}
|
|
48
48
|
return "Schema up to date."
|
|
49
49
|
}
|
package/src/ensure-binary.ts
CHANGED
|
@@ -11,8 +11,26 @@ import {
|
|
|
11
11
|
type Component,
|
|
12
12
|
} from "./binary-cache.js"
|
|
13
13
|
import { isDownloadInProgress, waitForComponentDownload } from "./binary-download-lock.js"
|
|
14
|
+
import { currentLibc } from "./cli-artifacts.js"
|
|
14
15
|
import type { SupatypeProjectConfig } from "./project-config.js"
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Components are published for glibc only, so on Alpine the CLI itself runs (it has a musl
|
|
19
|
+
* build) while everything it downloads cannot start. Said once, before the first download,
|
|
20
|
+
* because the alternative is a dynamic loader error naming a file the user never asked for.
|
|
21
|
+
*/
|
|
22
|
+
let warnedAboutMusl = false
|
|
23
|
+
function warnIfMusl(component: Component): void {
|
|
24
|
+
if (warnedAboutMusl || currentLibc() !== "musl") return
|
|
25
|
+
warnedAboutMusl = true
|
|
26
|
+
console.warn(
|
|
27
|
+
`[supatype] This is a musl system (Alpine). Component binaries such as ${component} are ` +
|
|
28
|
+
"published for glibc only, so they may fail to start here.\n" +
|
|
29
|
+
"[supatype] Use a glibc image (for example node:22-bookworm) for local stacks, or run " +
|
|
30
|
+
"against a remote target with `supatype link`.",
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
16
34
|
export async function ensureBinary(
|
|
17
35
|
component: Component,
|
|
18
36
|
config: SupatypeProjectConfig,
|
|
@@ -26,6 +44,8 @@ export async function ensureBinary(
|
|
|
26
44
|
}
|
|
27
45
|
}
|
|
28
46
|
|
|
47
|
+
warnIfMusl(component)
|
|
48
|
+
|
|
29
49
|
const version = await resolveVersionFor(component, config)
|
|
30
50
|
const platform = currentPlatform()
|
|
31
51
|
|
|
@@ -37,7 +37,7 @@ export async function ensureComponentBinaries(
|
|
|
37
37
|
const list = describeRequiredHostComponents(components)
|
|
38
38
|
if (provider === "docker") {
|
|
39
39
|
info(
|
|
40
|
-
`Preparing host CLI tools (${list})
|
|
40
|
+
`Preparing host CLI tools (${list}), Compose still runs Postgres and the API stack.`,
|
|
41
41
|
)
|
|
42
42
|
} else {
|
|
43
43
|
info(`Preparing local runtime components (${list})…`)
|
package/src/env-file.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { join } from "node:path"
|
|
|
10
10
|
* `SUPATYPE_REALTIME_IMAGE` from `.env` and could not override `SUPATYPE_SERVER_IMAGE`, because the
|
|
11
11
|
* latter is derivable from a pin and the former is not. Same file, same shape, different rules.
|
|
12
12
|
*/
|
|
13
|
-
export const MANAGED_MARKER = "# supatype:managed
|
|
13
|
+
export const MANAGED_MARKER = "# supatype:managed, value from versions in supatype.config.ts"
|
|
14
14
|
|
|
15
15
|
interface EnvLine {
|
|
16
16
|
/** `KEY` for an assignment, undefined for comments and blanks. */
|
|
@@ -47,7 +47,7 @@ function parseLines(text: string): EnvLine[] {
|
|
|
47
47
|
|
|
48
48
|
export interface UpsertOptions {
|
|
49
49
|
/**
|
|
50
|
-
* Keys to delete
|
|
50
|
+
* Keys to delete: but only where the CLI wrote them (see [`MANAGED_MARKER`]). A hand-written value
|
|
51
51
|
* is left alone, because the operator putting an image tag in `.env` is the documented way to run a
|
|
52
52
|
* local build and deleting it silently sent them back to `:latest`.
|
|
53
53
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which mechanism will enforce this project's per-column rules
|
|
2
|
+
* Which mechanism will enforce this project's per-column rules, decided offline.
|
|
3
3
|
*
|
|
4
4
|
* The engine makes the same decision at push time by asking the database whether `supatype_mask` is
|
|
5
5
|
* installed. The CLI has to answer earlier: it writes `PGRST_DB_SCHEMA` when it generates compose,
|
|
6
6
|
* before any database necessarily exists. It can, because the extension needs
|
|
7
|
-
* `shared_preload_libraries` and a compiled library on the host, so exactly one path ships it
|
|
7
|
+
* `shared_preload_libraries` and a compiled library on the host, so exactly one path ships it,
|
|
8
8
|
* `supatype/postgres`. Everything else gets the view tier:
|
|
9
9
|
*
|
|
10
10
|
* | Config | Ships the extension | Tier |
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
* Deliberately **not** "is the database external": a native `supatype dev` has no extension either,
|
|
18
18
|
* and treating it as tier 1 would point PostgREST at a schema whose tables the API roles no longer
|
|
19
|
-
* hold privileges on
|
|
19
|
+
* hold privileges on: every request denied.
|
|
20
20
|
*
|
|
21
21
|
* The one case this cannot call is a self-managed Postgres where the operator compiled and installed
|
|
22
22
|
* the extension themselves and points at it with `database.external`. They set `schema.api_schemas`
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
import { existsSync } from "node:fs"
|
|
27
27
|
// Statically imported: these packages are ESM, where `require` does not exist. The first attempt used
|
|
28
|
-
// it for a lazy import and every command that generates compose would have thrown at runtime
|
|
28
|
+
// it for a lazy import and every command that generates compose would have thrown at runtime, caught
|
|
29
29
|
// by the tests that run the built binary rather than the source.
|
|
30
30
|
import { loadSchemaAst } from "./config.js"
|
|
31
31
|
export { nativeMaskLibraryPresent } from "./postgres-ctl.js"
|
|
@@ -77,7 +77,7 @@ export function schemaHasFieldRules(ast: unknown): boolean {
|
|
|
77
77
|
export function fieldMaskingTier(
|
|
78
78
|
config: SupatypeProjectConfig,
|
|
79
79
|
ast: unknown,
|
|
80
|
-
/** Set on the native path once the Postgres install is known
|
|
80
|
+
/** Set on the native path once the Postgres install is known, see [`nativeMaskLibraryPresent`]. */
|
|
81
81
|
maskLibraryPresent?: boolean,
|
|
82
82
|
): FieldMaskingTier {
|
|
83
83
|
if (!schemaHasFieldRules(ast)) return "none"
|
|
@@ -88,7 +88,7 @@ export function fieldMaskingTier(
|
|
|
88
88
|
/**
|
|
89
89
|
* The tier for a project on disk, loading its schema to see whether any column is masked.
|
|
90
90
|
*
|
|
91
|
-
* A schema that fails to load falls back to `"none"
|
|
91
|
+
* A schema that fails to load falls back to `"none"`, the default exposed-schema list. Deciding the
|
|
92
92
|
* tier is the wrong moment to report a syntax error, and `push`/`dev` do it properly moments later
|
|
93
93
|
* with the file and line.
|
|
94
94
|
*/
|
|
@@ -23,7 +23,7 @@ export function functionsDenoAmbientSource(): string {
|
|
|
23
23
|
return `/**
|
|
24
24
|
* ${MARKER}.
|
|
25
25
|
* Runtime is Deno; this file covers APIs edge functions commonly use.
|
|
26
|
-
* Do not add \`@types/deno\` to the app package.json
|
|
26
|
+
* Do not add \`@types/deno\` to the app package.json, it leaks into the
|
|
27
27
|
* whole project when root tsconfig has no \`"types"\` field.
|
|
28
28
|
*
|
|
29
29
|
* Optional: for the full Deno API, install the Deno VS Code/Cursor extension
|
|
@@ -75,7 +75,7 @@ declare namespace Deno {
|
|
|
75
75
|
`
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
/** `functions/tsconfig.json
|
|
78
|
+
/** `functions/tsconfig.json`: owns function files so the app config can exclude them. */
|
|
79
79
|
export function functionsTsConfigSource(): string {
|
|
80
80
|
return `{
|
|
81
81
|
"compilerOptions": {
|
|
@@ -166,7 +166,7 @@ function ensureRootTsconfigExcludesFunctions(
|
|
|
166
166
|
writeFileSync(path, `${JSON.stringify(asJson, null, 2)}\n`, "utf8")
|
|
167
167
|
return "updated"
|
|
168
168
|
} catch {
|
|
169
|
-
// JSONC / trailing commas
|
|
169
|
+
// JSONC / trailing commas, try a conservative string splice into an existing exclude array.
|
|
170
170
|
if (/"exclude"\s*:\s*\[/.test(raw)) {
|
|
171
171
|
const next = raw.replace(/("exclude"\s*:\s*\[)/, `$1\n "functions",`)
|
|
172
172
|
if (next !== raw) {
|
|
@@ -58,7 +58,7 @@ export function generateFunctionsRouterSource(
|
|
|
58
58
|
)
|
|
59
59
|
const routes = fns.map((fn, i) => ` "${fn.name}": handler_${i},`)
|
|
60
60
|
|
|
61
|
-
return `// Auto-generated
|
|
61
|
+
return `// Auto-generated: do not edit (regenerated by supatype dev / functions serve)
|
|
62
62
|
${imports.join("\n")}
|
|
63
63
|
|
|
64
64
|
const handlers: Record<string, (req: Request) => Response | Promise<Response>> = {
|
package/src/gitignore.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
2
|
import { resolve } from "node:path"
|
|
3
3
|
|
|
4
|
-
export const SUPATYPE_GITIGNORE_MARKER = "# Supatype
|
|
4
|
+
export const SUPATYPE_GITIGNORE_MARKER = "# Supatype, local runtime (contains secrets in link.json)"
|
|
5
5
|
export const SUPATYPE_GITIGNORE_BLOCK = `${SUPATYPE_GITIGNORE_MARKER}
|
|
6
6
|
.env
|
|
7
7
|
.supatype/
|
|
@@ -34,7 +34,7 @@ export function ensureSupatypeGitignore(cwd: string, opts?: { silent?: boolean }
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
if (!opts?.silent) {
|
|
37
|
-
console.warn("Added .supatype/ to .gitignore (link.json contains secrets
|
|
37
|
+
console.warn("Added .supatype/ to .gitignore (link.json contains secrets, never commit).")
|
|
38
38
|
}
|
|
39
39
|
return true
|
|
40
40
|
}
|
|
@@ -42,7 +42,7 @@ export function ensureSupatypeGitignore(cwd: string, opts?: { silent?: boolean }
|
|
|
42
42
|
export function warnIfLinkNotGitignored(cwd: string): void {
|
|
43
43
|
if (isSupatypeGitignored(cwd)) return
|
|
44
44
|
console.warn(
|
|
45
|
-
"\n⚠ Warning: .supatype/ is not in .gitignore
|
|
45
|
+
"\n⚠ Warning: .supatype/ is not in .gitignore, link.json contains tokens and must not be committed.",
|
|
46
46
|
)
|
|
47
47
|
console.warn(" Run with link --fix-gitignore to append the Supatype block.\n")
|
|
48
48
|
}
|
package/src/hook-upload.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Package a project's hooks for a managed stack.
|
|
3
3
|
*
|
|
4
4
|
* Self-hosted stacks need none of this: the worker mounts the project directory, so `hooks/` is already
|
|
5
|
-
* where it looks. A managed project has no directory
|
|
5
|
+
* where it looks. A managed project has no directory, its worker reads a ConfigMap, whose keys may only
|
|
6
6
|
* contain alphanumerics, `-`, `_` and `.`. So the tree is flattened here, where it can be checked and
|
|
7
7
|
* explained, rather than in the deploy route where a dropped file would be silent.
|
|
8
8
|
*/
|
|
@@ -28,7 +28,7 @@ export interface HookUpload {
|
|
|
28
28
|
* Rewrite the one import a hook handler is generated to make.
|
|
29
29
|
*
|
|
30
30
|
* `../_supatype/hooks.ts` is a path that cannot survive flattening, and it is the specifier our own
|
|
31
|
-
* scaffold writes
|
|
31
|
+
* scaffold writes: so it is rewritten rather than refused. Any *other* relative import is refused
|
|
32
32
|
* below: it would resolve to nothing on the worker, and a hook that fails to import is a hooked table
|
|
33
33
|
* whose writes all start failing.
|
|
34
34
|
*/
|
|
@@ -55,7 +55,7 @@ function unsupportedImports(source: string): string[] {
|
|
|
55
55
|
* holding the service-role key with nothing able to call it. Uploading it buys nothing and widens what
|
|
56
56
|
* runs with that credential.
|
|
57
57
|
*
|
|
58
|
-
* Throws with a message meant for a terminal when a handler cannot be flattened faithfully
|
|
58
|
+
* Throws with a message meant for a terminal when a handler cannot be flattened faithfully, the
|
|
59
59
|
* alternative is a deploy that succeeds and a hook that fails to import, which reads to the caller as
|
|
60
60
|
* the table's writes being broken for no visible reason.
|
|
61
61
|
*/
|
package/src/hooks-generator.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generate `functions/_supatype/hooks.ts
|
|
2
|
+
* Generate `functions/_supatype/hooks.ts`: the typed handler surface for model hooks.
|
|
3
3
|
*
|
|
4
4
|
* Generated into the project rather than shipped as a package, for two reasons: a Deno function
|
|
5
5
|
* resolves a relative `.ts` import with no npm involved, and the types then move in lockstep with the
|
|
@@ -40,7 +40,7 @@ function hookedModels(ast: unknown): HookedModel[] {
|
|
|
40
40
|
* The module source, or `null` when no model declares a hook.
|
|
41
41
|
*
|
|
42
42
|
* Returning null rather than an empty module keeps a `_supatype/hooks.ts` from appearing in projects
|
|
43
|
-
* that have no hooks
|
|
43
|
+
* that have no hooks, a generated file nobody imports is a file somebody eventually edits.
|
|
44
44
|
*/
|
|
45
45
|
export function generateHooksModule(ast: unknown): string | null {
|
|
46
46
|
const models = hookedModels(ast)
|
|
@@ -56,7 +56,7 @@ export function generateHooksModule(ast: unknown): string | null {
|
|
|
56
56
|
)
|
|
57
57
|
.join("\n")
|
|
58
58
|
|
|
59
|
-
return `// Generated by supatype CLI
|
|
59
|
+
return `// Generated by supatype CLI, do not edit manually.
|
|
60
60
|
//
|
|
61
61
|
// Typed handlers for the models that declare \`hooks\`. Import from a function beside it:
|
|
62
62
|
//
|
|
@@ -103,7 +103,7 @@ interface HookBase {
|
|
|
103
103
|
/**
|
|
104
104
|
* The rows this request is about to overwrite, fetched only if you ask.
|
|
105
105
|
*
|
|
106
|
-
* Resolved by the server from the in-flight request's own filter, as the caller's own role
|
|
106
|
+
* Resolved by the server from the in-flight request's own filter, as the caller's own role, so it
|
|
107
107
|
* cannot show you rows the caller could not read, and you cannot widen the filter. Capped:
|
|
108
108
|
* \`truncated\` is true when there were more, in which case acting on what you got means acting on a
|
|
109
109
|
* prefix you did not choose.
|
|
@@ -131,7 +131,7 @@ export type BeforeDeleteContext<T extends HookedTable> = HookBase & {
|
|
|
131
131
|
|
|
132
132
|
export type AfterChangeContext<T extends HookedTable> = HookBase & {
|
|
133
133
|
readonly operation: "insert" | "update"
|
|
134
|
-
/** Written rows
|
|
134
|
+
/** Written rows: present only when the caller sent \`Prefer: return=representation\`. */
|
|
135
135
|
readonly rows?: HookTables[T]["Row"][]
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -201,7 +201,7 @@ interface WireContext {
|
|
|
201
201
|
*
|
|
202
202
|
* The outcome travels as the **HTTP status**: 200 for proceed, 4xx for a rejection. That keeps the
|
|
203
203
|
* contract in the transport rather than in a second envelope inside the body, so a hook written by
|
|
204
|
-
* hand
|
|
204
|
+
* hand: or in another language, needs to know nothing about this file.
|
|
205
205
|
*/
|
|
206
206
|
export function hook(handler: AnyHandler): (req: Request) => Promise<Response> {
|
|
207
207
|
return async (req: Request): Promise<Response> => {
|
|
@@ -263,7 +263,7 @@ export function hook(handler: AnyHandler): (req: Request) => Promise<Response> {
|
|
|
263
263
|
*
|
|
264
264
|
* The worker takes **one default export per function directory**, so \`hook(single)\` is one hook per
|
|
265
265
|
* directory. That is fine for a single moderation rule and tedious for a model whose whole lifecycle
|
|
266
|
-
* you want in one place
|
|
266
|
+
* you want in one place, hence this. Point every event at the same function name in the schema:
|
|
267
267
|
*
|
|
268
268
|
* hooks: { beforeChange: "post-hooks", afterChange: "post-hooks" }
|
|
269
269
|
*
|
|
@@ -284,7 +284,7 @@ export function hooks(handlers: Record<string, AnyHandler | undefined>): (req: R
|
|
|
284
284
|
* The stack's address from this worker's point of view.
|
|
285
285
|
*
|
|
286
286
|
* \`SUPATYPE_INTERNAL_URL\` in Compose is the in-network gateway; \`SUPATYPE_URL\` is the same value
|
|
287
|
-
* there. Never a public or host URL
|
|
287
|
+
* there. Never a public or host URL, \`localhost\` inside this container is this container.
|
|
288
288
|
*/
|
|
289
289
|
function stackBaseUrl(): string {
|
|
290
290
|
const base =
|
|
@@ -330,7 +330,7 @@ function json(body: unknown, status: number): Response {
|
|
|
330
330
|
* Replace cross-package type imports the client types use but a hook cannot resolve.
|
|
331
331
|
*
|
|
332
332
|
* `RichText` normally generates `import("@supatype/types/lexical").SerializedEditorState`. That works
|
|
333
|
-
* in an app, where the package is installed
|
|
333
|
+
* in an app, where the package is installed, but this file lives in `functions/`, is imported by a
|
|
334
334
|
* Deno handler, and has no node_modules to reach into. Left alone, any hooked model with a rich-text
|
|
335
335
|
* column emitted a module that failed to compile in the user's editor. Caught by compiling the
|
|
336
336
|
* generated file in a test rather than by a reader reporting it.
|
package/src/index.ts
CHANGED
|
@@ -62,7 +62,7 @@ function detectStaticDir(cwd: string): string {
|
|
|
62
62
|
return "./public"
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
/** Inspect `cwd` before init prompts
|
|
65
|
+
/** Inspect `cwd` before init prompts, Vite, static dir, existing Supatype config. */
|
|
66
66
|
export function detectProjectSetup(cwd: string): DetectedProjectSetup {
|
|
67
67
|
let entries: string[] = []
|
|
68
68
|
try {
|
package/src/link.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface ProjectLink {
|
|
|
23
23
|
defaultEnvironment: string
|
|
24
24
|
/** Access token (cloud user JWT) or self-host SERVICE_ROLE_KEY. */
|
|
25
25
|
token?: string
|
|
26
|
-
/** Cloud GoTrue refresh token
|
|
26
|
+
/** Cloud GoTrue refresh token, used to renew short-lived access JWTs. */
|
|
27
27
|
refreshToken?: string
|
|
28
28
|
orgId?: string | undefined
|
|
29
29
|
cloudApiUrl?: string
|
package/src/local-secrets.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The secrets the local stack runs with.
|
|
3
3
|
*
|
|
4
4
|
* **Read from `.env`, never pinned back into it.** These used to be hardcoded constants that
|
|
5
|
-
* `supatype dev` wrote to `.env` on every run
|
|
5
|
+
* `supatype dev` wrote to `.env` on every run, which meant a project could not hold its own
|
|
6
6
|
* secrets: whatever `supatype init` or the developer put there was replaced by the published
|
|
7
7
|
* defaults on the next `dev`, and the same `.env` then went to a server. Resolving instead of
|
|
8
8
|
* pinning is what lets a generated secret survive to production.
|
|
@@ -16,7 +16,7 @@ import { hasEnvValue, readEnvValue } from "./env-file.js"
|
|
|
16
16
|
/**
|
|
17
17
|
* Fallback JWT signing secret for a project that has none.
|
|
18
18
|
*
|
|
19
|
-
* Published, therefore worthless as a secret
|
|
19
|
+
* Published, therefore worthless as a secret, anyone can mint a token for a stack still using
|
|
20
20
|
* it. That is precisely why `init` generates one instead of relying on this.
|
|
21
21
|
*/
|
|
22
22
|
export const FALLBACK_JWT_SECRET = "super-secret-jwt-token-with-at-least-32-characters-long"
|
|
@@ -52,7 +52,7 @@ export function devAuthenticatorPassword(cwd: string): string {
|
|
|
52
52
|
*
|
|
53
53
|
* The compose template requires these with `${VAR:?}` rather than defaulting them, because a
|
|
54
54
|
* default is how a published constant ends up signing a real deployment's tokens. That only
|
|
55
|
-
* works if something guarantees presence
|
|
55
|
+
* works if something guarantees presence, this does, for any project that predates
|
|
56
56
|
* `supatype init` writing them.
|
|
57
57
|
*
|
|
58
58
|
* **Fills with the fallback, does not generate.** Preserving the value such a project has been
|
|
@@ -72,11 +72,11 @@ export function seedMissingLocalSecrets(cwd: string): Record<string, string> {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
* The database identity the local stack connects with
|
|
75
|
+
* The database identity the local stack connects with, seeded, never overwritten.
|
|
76
76
|
*
|
|
77
77
|
* `POSTGRES_DB` in particular is *project configuration*: `supatype init` sets it to the
|
|
78
78
|
* project name, and the running container's database was created from it. Rewriting it to a
|
|
79
|
-
* default afterwards points every tool at a database that does not exist
|
|
79
|
+
* default afterwards points every tool at a database that does not exist, observed as
|
|
80
80
|
* `supatype push` failing with `FATAL: database "supatype" does not exist` on a project called
|
|
81
81
|
* something else, because the push path rewrote `.env` after `self-host compose up` had already
|
|
82
82
|
* created the database under its real name.
|