@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
package/src/db-preflight.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Written for the bring-your-own-Postgres case: an external database will not look like
|
|
5
5
|
* `supatype/postgres`, and the failures it produces are mostly indirect. The four API roles are
|
|
6
|
-
* the sharpest example
|
|
6
|
+
* the sharpest example: every `GRANT` the engine emits is guarded with
|
|
7
7
|
* `IF EXISTS (SELECT 1 FROM pg_roles …)`, so a missing role is skipped in silence and the symptom
|
|
8
8
|
* is an API that cannot switch roles at all, days later.
|
|
9
9
|
*
|
|
@@ -31,7 +31,7 @@ export interface CheckResult {
|
|
|
31
31
|
/** SQL that resolves it, if SQL can. */
|
|
32
32
|
remedy?: string
|
|
33
33
|
/**
|
|
34
|
-
* True when the remedy cannot run inside a transaction
|
|
34
|
+
* True when the remedy cannot run inside a transaction, server settings, chiefly. `--fix`
|
|
35
35
|
* refuses these and reports them rather than half-applying.
|
|
36
36
|
*/
|
|
37
37
|
remedyNeedsOperator?: boolean
|
|
@@ -117,7 +117,7 @@ const REQUIRED_ROLES = ["anon", "authenticated", "service_role", "authenticator"
|
|
|
117
117
|
* Stands in for the `authenticator` password when the operator has not supplied one.
|
|
118
118
|
*
|
|
119
119
|
* Fine to print for a human to replace; never acceptable to execute. `--fix` refuses when a remedy
|
|
120
|
-
* still contains it, because the decision was that this credential belongs to the operator
|
|
120
|
+
* still contains it, because the decision was that this credential belongs to the operator,
|
|
121
121
|
* Supatype does not invent one for a database it does not own, and creating a role with a
|
|
122
122
|
* placeholder password would be worse than refusing.
|
|
123
123
|
*/
|
|
@@ -225,13 +225,13 @@ export async function runPreflight(
|
|
|
225
225
|
})
|
|
226
226
|
|
|
227
227
|
// `CREATE` on the database, which the check above only asked about when the target schema was
|
|
228
|
-
// missing
|
|
228
|
+
// missing: and `public` always exists, so on a database where the role cannot create schemas that
|
|
229
229
|
// check passed while the stack could not start.
|
|
230
230
|
//
|
|
231
231
|
// Measured on a role with `CONNECT` and `USAGE ON SCHEMA public` but no `CREATE`: storage's
|
|
232
232
|
// bootstrap fails `42501 permission denied for database`, and so does every one of the engine's own
|
|
233
233
|
// schemas. Storage was the least examined service in this plan and this is the whole of what it
|
|
234
|
-
// needs
|
|
234
|
+
// needs: no extensions, no superuser, no replication, just somewhere to put `storage.buckets` and
|
|
235
235
|
// `storage.objects`.
|
|
236
236
|
results.push({
|
|
237
237
|
id: "create-schemas",
|
|
@@ -274,7 +274,7 @@ export async function runPreflight(
|
|
|
274
274
|
// create role" because BYPASSRLS is superuser-only. Better to say so up front.
|
|
275
275
|
(needsSuperuserForRoles(missing, privs.is_super)
|
|
276
276
|
? "\n Note: service_role needs BYPASSRLS, which only a superuser can grant. " +
|
|
277
|
-
`This connection is not a superuser, so --fix cannot create it
|
|
277
|
+
`This connection is not a superuser, so --fix cannot create it, have someone with ` +
|
|
278
278
|
`superuser apply the emitted SQL, or create service_role first.`
|
|
279
279
|
: ""),
|
|
280
280
|
remedy: roleRemedy(missing, opts.authenticatorPassword),
|
|
@@ -333,7 +333,7 @@ export async function runPreflight(
|
|
|
333
333
|
results.push(
|
|
334
334
|
extensionCheck("pgcrypto", installed, available, {
|
|
335
335
|
title: "pgcrypto",
|
|
336
|
-
needs: "UUID primary keys
|
|
336
|
+
needs: "UUID primary keys, the engine emits gen_random_uuid() defaults.",
|
|
337
337
|
whenMissing: "fail",
|
|
338
338
|
}),
|
|
339
339
|
)
|
|
@@ -359,14 +359,14 @@ export async function runPreflight(
|
|
|
359
359
|
detail: installed.has("supatype_mask")
|
|
360
360
|
? "enforced by supatype_mask, the planner rewrite (tier 1)"
|
|
361
361
|
: available.has("supatype_mask")
|
|
362
|
-
? "supatype_mask is available but not installed
|
|
362
|
+
? "supatype_mask is available but not installed, rules will be enforced by generated api views (tier 2)"
|
|
363
363
|
: "enforced by generated api views (tier 2); supatype_mask is not available on this server",
|
|
364
364
|
...(!installed.has("supatype_mask") && {
|
|
365
365
|
impact:
|
|
366
366
|
"Tier 2 puts the masking expression in a view instead of the query planner. It is the same " +
|
|
367
367
|
"behaviour with one exception: an aggregate over a masked column returns the sum of what the " +
|
|
368
|
-
"caller may read, where tier 1 raises. Unreachable through the API
|
|
369
|
-
"aggregates disabled and Supatype never enables them
|
|
368
|
+
"caller may read, where tier 1 raises. Unreachable through the API, PostgREST ships with " +
|
|
369
|
+
"aggregates disabled and Supatype never enables them, so this matters only for direct SQL " +
|
|
370
370
|
"against the api views. PostgREST is pointed at `api` instead of your managed schema, and the " +
|
|
371
371
|
"API roles hold their privileges on the views rather than the tables.",
|
|
372
372
|
...(available.has("supatype_mask") && {
|
|
@@ -413,7 +413,7 @@ export async function runPreflight(
|
|
|
413
413
|
// The definitive realtime check: create the slot realtime would create, then drop it.
|
|
414
414
|
//
|
|
415
415
|
// There is no catalog to consult. `wal2json` is a shared library, not an extension, so it never
|
|
416
|
-
// appears in `pg_available_extensions
|
|
416
|
+
// appears in `pg_available_extensions`: the only way to know whether this database can decode is
|
|
417
417
|
// to ask it to. Cloud SQL does not ship the plugin at all; plenty of managed Postgres will not
|
|
418
418
|
// grant `REPLICATION`. Both produce a stack that looks healthy until the first subscription.
|
|
419
419
|
//
|
|
@@ -448,7 +448,7 @@ export async function runPreflight(
|
|
|
448
448
|
(names.length > 8 ? `, … and ${names.length - 8} more` : ""),
|
|
449
449
|
impact:
|
|
450
450
|
"These are not described by your schema. Model them, or keep them out of the managed " +
|
|
451
|
-
"schema
|
|
451
|
+
"schema: a push only manages what it created.",
|
|
452
452
|
})
|
|
453
453
|
}
|
|
454
454
|
}
|
|
@@ -488,7 +488,7 @@ function extensionCheck(
|
|
|
488
488
|
* SQL to create the missing API roles.
|
|
489
489
|
*
|
|
490
490
|
* `authenticator` needs a password because PostgREST logs in as it; the others never do. The
|
|
491
|
-
* password is the operator's to supply
|
|
491
|
+
* password is the operator's to supply, Supatype does not invent a credential for a database it
|
|
492
492
|
* does not own.
|
|
493
493
|
*/
|
|
494
494
|
function roleRemedy(missing: readonly string[], authenticatorPassword?: string): string {
|
|
@@ -518,7 +518,7 @@ function roleRemedy(missing: readonly string[], authenticatorPassword?: string):
|
|
|
518
518
|
* Whether creating the missing roles needs superuser rather than merely CREATEROLE.
|
|
519
519
|
*
|
|
520
520
|
* `service_role` carries `BYPASSRLS`, and only a superuser may set that attribute. A CREATEROLE
|
|
521
|
-
* operator
|
|
521
|
+
* operator: which is what managed Postgres typically gives you, gets "permission denied to
|
|
522
522
|
* create role" with no indication that the attribute is the reason.
|
|
523
523
|
*/
|
|
524
524
|
function needsSuperuserForRoles(missing: readonly string[], isSuperuser: boolean): boolean {
|
|
@@ -551,7 +551,7 @@ export function operatorRemedies(report: PreflightReport): CheckResult[] {
|
|
|
551
551
|
* Postgres, so any failure rolls the whole thing back and the database is exactly as it was. That
|
|
552
552
|
* is the guarantee worth having when the database belongs to someone else.
|
|
553
553
|
*
|
|
554
|
-
* Server settings are the exception and are never included
|
|
554
|
+
* Server settings are the exception and are never included, `ALTER SYSTEM` cannot run in a
|
|
555
555
|
* transaction, and needs a restart besides. Those are reported for the operator to do.
|
|
556
556
|
*/
|
|
557
557
|
export async function applyRemedies(
|
package/src/dev-compose.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `supatype dev` when `provider: docker
|
|
2
|
+
* `supatype dev` when `provider: docker`, full self-host Compose stack (Kong gateway).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs"
|
|
@@ -99,10 +99,10 @@ async function resolveDevDbPort(cwd: string): Promise<number> {
|
|
|
99
99
|
/**
|
|
100
100
|
* The database URL to hand a tool, from wherever it happens to run.
|
|
101
101
|
*
|
|
102
|
-
* The compose helpers below describe the `db` *container
|
|
102
|
+
* The compose helpers below describe the `db` *container*, on the host at
|
|
103
103
|
* `SUPATYPE_DEV_DB_PORT`, or in-network at `db:5432`. Neither exists for a project pointed at an
|
|
104
104
|
* external database, and passing one produced "pool timed out while waiting for an open connection"
|
|
105
|
-
|
|
105
|
+
*- a message with nothing in it about the URL being wrong.
|
|
106
106
|
*/
|
|
107
107
|
function projectDatabaseUrl(cwd: string, config: SupatypeProjectConfig, inNetwork = false): string {
|
|
108
108
|
if (usesExternalDatabase(config)) return connectionString(config)
|
|
@@ -193,7 +193,7 @@ async function resolveKongPort(cwd: string): Promise<number> {
|
|
|
193
193
|
* Bring up the compose `db` service and wait for it to answer.
|
|
194
194
|
*
|
|
195
195
|
* A no-op when the project uses an external database: there is no such service, the database is
|
|
196
|
-
* already running, and its readiness is the operator's
|
|
196
|
+
* already running, and its readiness is the operator's, `supatype db check` is what reports on it.
|
|
197
197
|
* Four call sites did this inline, so an external project hit `compose up -d db` against a compose
|
|
198
198
|
* file that deliberately has no `db`.
|
|
199
199
|
*/
|
|
@@ -233,7 +233,7 @@ function upsertDevComposeEnv(
|
|
|
233
233
|
// `POSTGRES_PASSWORD` and `JWT_SECRET` are deliberately absent.
|
|
234
234
|
//
|
|
235
235
|
// They used to be pinned here to published constants on every `dev` run, against the same
|
|
236
|
-
// `.env` a self-host deployment reads
|
|
236
|
+
// `.env` a self-host deployment reads, so a project could not hold its own secrets, and one
|
|
237
237
|
// `dev` after generating them put the published values back with nothing to show it. They are
|
|
238
238
|
// now resolved from `.env` (see `local-secrets.ts`) and written by `init` alone.
|
|
239
239
|
//
|
|
@@ -242,12 +242,12 @@ function upsertDevComposeEnv(
|
|
|
242
242
|
// would desync them from the secret that validates them.
|
|
243
243
|
const updates: Record<string, string> = {
|
|
244
244
|
// The docker dev path renders the *self-host* compose file, where the secrets have no
|
|
245
|
-
// defaults
|
|
245
|
+
// defaults: an unset value is a hard compose error rather than a service quietly starting
|
|
246
246
|
// with a published constant. This guarantees presence without overwriting: only keys
|
|
247
247
|
// genuinely absent from `.env` are filled, and with the value the project has been running
|
|
248
248
|
// with rather than a fresh one.
|
|
249
249
|
...seedMissingLocalSecrets(cwd),
|
|
250
|
-
// Project configuration, seeded not overwritten
|
|
250
|
+
// Project configuration, seeded not overwritten, see seedMissingDatabaseIdentity.
|
|
251
251
|
...seedMissingDatabaseIdentity(cwd),
|
|
252
252
|
ANON_KEY: anonKey,
|
|
253
253
|
SERVICE_ROLE_KEY: serviceRoleKey,
|
|
@@ -264,13 +264,13 @@ function upsertDevComposeEnv(
|
|
|
264
264
|
...(localServerImage !== undefined && { SUPATYPE_SERVER_IMAGE: localServerImage }),
|
|
265
265
|
}
|
|
266
266
|
// Never for an external database: this URL describes the `db` container, which that project does
|
|
267
|
-
// not have. Writing it overwrote the operator's own DATABASE_URL
|
|
268
|
-
// every CLI command reads
|
|
267
|
+
// not have. Writing it overwrote the operator's own DATABASE_URL, the value the whole stack and
|
|
268
|
+
// every CLI command reads, with a DSN pointing at a database that does not exist. Found by
|
|
269
269
|
// rehearsing a push against a real external Postgres, where the compose guard then refused to
|
|
270
270
|
// proceed because .env and the config disagreed. They disagreed because of this line.
|
|
271
271
|
if (devDbPort !== undefined && !usesExternalDatabase(config)) {
|
|
272
272
|
updates.SUPATYPE_DEV_DB_PORT = String(devDbPort)
|
|
273
|
-
// User and database from the project, not hardcoded
|
|
273
|
+
// User and database from the project, not hardcoded, same reason as
|
|
274
274
|
// `seedMissingDatabaseIdentity`: a project not named "supatype" had this URL pointing at a
|
|
275
275
|
// database that does not exist.
|
|
276
276
|
const dbUser = readEnvValue(cwd, "POSTGRES_USER", "supatype_admin")
|
|
@@ -358,7 +358,7 @@ function dumpComposeDbLogs(
|
|
|
358
358
|
maxBuffer: 10 * 1024 * 1024,
|
|
359
359
|
})
|
|
360
360
|
const body = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim()
|
|
361
|
-
const content = body || `(empty
|
|
361
|
+
const content = body || `(empty, docker compose logs db exit ${result.status ?? "?"})\n`
|
|
362
362
|
try {
|
|
363
363
|
writeFileSync(logPath, content)
|
|
364
364
|
} catch {
|
|
@@ -403,7 +403,7 @@ async function waitStorageApiReady(
|
|
|
403
403
|
const body = await res.text()
|
|
404
404
|
const kongUpstreamDown = body.includes("invalid response was received from the upstream server")
|
|
405
405
|
if (!kongUpstreamDown && res.status !== 503) {
|
|
406
|
-
// Non-transient storage response (e.g. 401)
|
|
406
|
+
// Non-transient storage response (e.g. 401), stop waiting.
|
|
407
407
|
return
|
|
408
408
|
}
|
|
409
409
|
} catch {
|
|
@@ -412,7 +412,7 @@ async function waitStorageApiReady(
|
|
|
412
412
|
await new Promise((r) => setTimeout(r, 1000))
|
|
413
413
|
}
|
|
414
414
|
console.warn(
|
|
415
|
-
`[supatype] Storage API at ${url} did not become ready within ${maxSec}s
|
|
415
|
+
`[supatype] Storage API at ${url} did not become ready within ${maxSec}s, bucket provisioning may fail.`,
|
|
416
416
|
)
|
|
417
417
|
}
|
|
418
418
|
|
|
@@ -445,7 +445,7 @@ async function refreshSchemaArtifacts(
|
|
|
445
445
|
await ensureEngine()
|
|
446
446
|
} catch (err) {
|
|
447
447
|
console.warn(
|
|
448
|
-
`[supatype] Host engine unavailable
|
|
448
|
+
`[supatype] Host engine unavailable, admin/types not refreshed: ${(err as Error).message}`,
|
|
449
449
|
)
|
|
450
450
|
return
|
|
451
451
|
}
|
|
@@ -480,7 +480,7 @@ async function refreshSchemaArtifacts(
|
|
|
480
480
|
console.log("[supatype] Admin config written to .supatype/admin-config.json")
|
|
481
481
|
} catch (err) {
|
|
482
482
|
console.warn(
|
|
483
|
-
`[supatype] Admin config generation failed
|
|
483
|
+
`[supatype] Admin config generation failed, Studio may show stale field widgets: ${(err as Error).message}`,
|
|
484
484
|
)
|
|
485
485
|
}
|
|
486
486
|
}
|
|
@@ -498,7 +498,7 @@ async function runComposeSchemaPush(
|
|
|
498
498
|
const supatypeDir = join(cwd, ".supatype")
|
|
499
499
|
mkdirSync(supatypeDir, { recursive: true })
|
|
500
500
|
const astPath = join(supatypeDir, "schema.ast.json")
|
|
501
|
-
// Always materialise on disk
|
|
501
|
+
// Always materialise on disk, schema-engine reads via bind mount; skip must not omit the write.
|
|
502
502
|
writeFileSync(astPath, astJson)
|
|
503
503
|
if (astJson === _lastPushedAst && astJson !== _lastFailedAst) return
|
|
504
504
|
|
|
@@ -506,7 +506,7 @@ async function runComposeSchemaPush(
|
|
|
506
506
|
throw new Error(`Failed to write schema AST at ${astPath}`)
|
|
507
507
|
}
|
|
508
508
|
|
|
509
|
-
// Admin + types come from the AST only (no DB)
|
|
509
|
+
// Admin + types come from the AST only (no DB), refresh before push so Studio stays
|
|
510
510
|
// in sync even when migration fails (e.g. bad engine image, lossy column change).
|
|
511
511
|
await refreshSchemaArtifacts(cwd, config, ast)
|
|
512
512
|
|
|
@@ -552,7 +552,7 @@ async function runComposeSchemaPush(
|
|
|
552
552
|
}
|
|
553
553
|
return result
|
|
554
554
|
}
|
|
555
|
-
// B: only hold the advisory lock when realtime is already decoding
|
|
555
|
+
// B: only hold the advisory lock when realtime is already decoding, first-boot
|
|
556
556
|
// push (db only) must not take the lock; that path crashed under lock+DDL in CI.
|
|
557
557
|
const push = composeServiceIsRunning(paths, cwd, composeProject, "realtime")
|
|
558
558
|
? await withComposeSchemaPushLock(paths, cwd, composeProject, runPush)
|
|
@@ -711,7 +711,7 @@ async function runComposeEngineDiff(
|
|
|
711
711
|
|
|
712
712
|
/**
|
|
713
713
|
* `supatype diff` when `provider: docker`. Uses in-compose schema-engine unless
|
|
714
|
-
* `overrides.engine` is set
|
|
714
|
+
* `overrides.engine` is set: then Postgres is published to the host and diff runs
|
|
715
715
|
* through the local engine binary.
|
|
716
716
|
*/
|
|
717
717
|
export async function diffSchemaDocker(cwd: string, config: SupatypeProjectConfig): Promise<DiffResult> {
|
|
@@ -772,7 +772,7 @@ export async function diffSchemaDocker(cwd: string, config: SupatypeProjectConfi
|
|
|
772
772
|
|
|
773
773
|
/**
|
|
774
774
|
* `supatype push` when `provider: docker`. Uses in-compose schema-engine unless
|
|
775
|
-
* `overrides.engine` is set
|
|
775
|
+
* `overrides.engine` is set: then Postgres is published to the host and push runs
|
|
776
776
|
* through the local engine binary (AST v2, contributor builds).
|
|
777
777
|
*/
|
|
778
778
|
export async function pushSchemaDocker(cwd: string, config: SupatypeProjectConfig): Promise<void> {
|
|
@@ -782,7 +782,7 @@ export async function pushSchemaDocker(cwd: string, config: SupatypeProjectConfi
|
|
|
782
782
|
const project = composeProjectName(config.project.name)
|
|
783
783
|
const kongPort = await resolveKongPort(cwd)
|
|
784
784
|
// No dev db port for an external database: `ensureDevDbPort` allocates a host port for the `db`
|
|
785
|
-
// container *and persists a matching DATABASE_URL*, which overwrote the operator's own URL
|
|
785
|
+
// container *and persists a matching DATABASE_URL*, which overwrote the operator's own URL, the
|
|
786
786
|
// one the whole stack and every CLI command reads.
|
|
787
787
|
const devDbPort =
|
|
788
788
|
hasEngineOverride(config) && !usesExternalDatabase(config)
|
|
@@ -798,7 +798,7 @@ export async function pushSchemaDocker(cwd: string, config: SupatypeProjectConfi
|
|
|
798
798
|
const paths = writeSelfHostCompose(cwd, config, { devLocal: true })
|
|
799
799
|
const pushBrand = { intro: "Push schema" }
|
|
800
800
|
|
|
801
|
-
console.log(`[supatype] provider
|
|
801
|
+
console.log(`[supatype] provider docker, applying schema via compose (project ${project})...`)
|
|
802
802
|
await startComposeDatabase(config, paths, cwd, project, pushBrand)
|
|
803
803
|
|
|
804
804
|
const schemaPath = schemaPathFromProject(config, cwd)
|
|
@@ -833,7 +833,7 @@ export async function runDevCompose(cwd: string, config: SupatypeProjectConfig,
|
|
|
833
833
|
const project = composeProjectName(config.project.name)
|
|
834
834
|
const kongPort = await resolveKongPort(cwd)
|
|
835
835
|
// No dev db port for an external database: `ensureDevDbPort` allocates a host port for the `db`
|
|
836
|
-
// container *and persists a matching DATABASE_URL*, which overwrote the operator's own URL
|
|
836
|
+
// container *and persists a matching DATABASE_URL*, which overwrote the operator's own URL, the
|
|
837
837
|
// one the whole stack and every CLI command reads.
|
|
838
838
|
const devDbPort =
|
|
839
839
|
hasEngineOverride(config) && !usesExternalDatabase(config)
|
|
@@ -850,7 +850,7 @@ export async function runDevCompose(cwd: string, config: SupatypeProjectConfig,
|
|
|
850
850
|
|
|
851
851
|
ensureDevComposeEnv(cwd, config, anonKey, serviceRoleKey, kongPort, devDbPort, localServerImage)
|
|
852
852
|
|
|
853
|
-
console.log(`[supatype] provider
|
|
853
|
+
console.log(`[supatype] provider docker, starting self-host Compose stack (project ${project}, gateway :${kongPort})...`)
|
|
854
854
|
const paths = writeSelfHostCompose(cwd, config, { devLocal: true })
|
|
855
855
|
if (ensureDevApiConfig(cwd)) {
|
|
856
856
|
console.log("[supatype] API config written to .supatype/api-config.json")
|
|
@@ -898,7 +898,7 @@ export async function runDevCompose(cwd: string, config: SupatypeProjectConfig,
|
|
|
898
898
|
console.log("[supatype] Bringing up Postgres (compose db)...")
|
|
899
899
|
}
|
|
900
900
|
await startComposeDatabase(config, paths, cwd, project, devBrand, 180_000, endDevSession)
|
|
901
|
-
// Settle before DDL
|
|
901
|
+
// Settle before DDL: pg_isready can pass slightly before the instance is stable.
|
|
902
902
|
await new Promise((r) => setTimeout(r, 3000))
|
|
903
903
|
|
|
904
904
|
// A: apply schema before realtime (and the rest of the stack) starts decoding WAL.
|
|
@@ -1034,7 +1034,7 @@ export async function runDevCompose(cwd: string, config: SupatypeProjectConfig,
|
|
|
1034
1034
|
shutdownState.studioProc = studioProc
|
|
1035
1035
|
if (studioProc) {
|
|
1036
1036
|
console.log(
|
|
1037
|
-
`[supatype] Studio (overrides.studio)
|
|
1037
|
+
`[supatype] Studio (overrides.studio): live reload proxied at http://localhost:${kongPort}/studio/`,
|
|
1038
1038
|
)
|
|
1039
1039
|
}
|
|
1040
1040
|
}
|
|
@@ -1122,6 +1122,6 @@ function grantAuthSchemaAccess(
|
|
|
1122
1122
|
{ cwd: composeDir, encoding: "utf8", timeout: 10_000 },
|
|
1123
1123
|
)
|
|
1124
1124
|
if (result.status !== 0) {
|
|
1125
|
-
console.warn("[supatype] Could not grant service_role access to auth.users
|
|
1125
|
+
console.warn("[supatype] Could not grant service_role access to auth.users, Studio relation preview may fail.")
|
|
1126
1126
|
}
|
|
1127
1127
|
}
|
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
|
}
|