@supatype/cli 0.1.0-alpha.9 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/.turbo/turbo-test.log +285 -69
- package/.turbo/turbo-typecheck.log +1 -1
- package/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/bin/dev-entry.ts +2 -1
- package/dist/app/framework.js +1 -3
- package/dist/app/framework.js.map +1 -1
- package/dist/app/proxy-dev-app.d.ts +14 -0
- package/dist/app/proxy-dev-app.d.ts.map +1 -1
- package/dist/app/proxy-dev-app.js +110 -6
- package/dist/app/proxy-dev-app.js.map +1 -1
- package/dist/app-config.d.ts +10 -0
- package/dist/app-config.d.ts.map +1 -1
- package/dist/app-config.js +72 -0
- package/dist/app-config.js.map +1 -1
- package/dist/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/dist/binary-cache.d.ts +19 -7
- package/dist/binary-cache.d.ts.map +1 -1
- package/dist/binary-cache.js +92 -46
- package/dist/binary-cache.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.d.ts +3 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +86 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/admin.d.ts +28 -1
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +297 -149
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/adopt.d.ts +3 -0
- package/dist/commands/adopt.d.ts.map +1 -0
- package/dist/commands/adopt.js +55 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +20 -17
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/cache.d.ts.map +1 -1
- package/dist/commands/cache.js +11 -10
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/cloud.d.ts +4 -9
- package/dist/commands/cloud.d.ts.map +1 -1
- package/dist/commands/cloud.js +75 -125
- package/dist/commands/cloud.js.map +1 -1
- package/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +37 -58
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +140 -96
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +74 -39
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +39 -39
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +78 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/engine.d.ts.map +1 -1
- package/dist/commands/engine.js +5 -4
- package/dist/commands/engine.js.map +1 -1
- package/dist/commands/functions.d.ts.map +1 -1
- package/dist/commands/functions.js +172 -119
- package/dist/commands/functions.js.map +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +5 -4
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +35 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +883 -107
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/introspect.d.ts +3 -0
- package/dist/commands/introspect.d.ts.map +1 -0
- package/dist/commands/introspect.js +35 -0
- package/dist/commands/introspect.js.map +1 -0
- package/dist/commands/keys.d.ts +15 -1
- package/dist/commands/keys.d.ts.map +1 -1
- package/dist/commands/keys.js +46 -10
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/link-helpers.d.ts +15 -0
- package/dist/commands/link-helpers.d.ts.map +1 -0
- package/dist/commands/link-helpers.js +225 -0
- package/dist/commands/link-helpers.js.map +1 -0
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +5 -4
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/migrate-from-v1.d.ts.map +1 -1
- package/dist/commands/migrate-from-v1.js +3 -2
- package/dist/commands/migrate-from-v1.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +119 -26
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/pg.d.ts.map +1 -1
- package/dist/commands/pg.js +11 -12
- package/dist/commands/pg.js.map +1 -1
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +55 -46
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +33 -5
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +111 -138
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/seed.d.ts.map +1 -1
- package/dist/commands/seed.js +4 -3
- package/dist/commands/seed.js.map +1 -1
- package/dist/commands/self-host.d.ts +2 -2
- package/dist/commands/self-host.d.ts.map +1 -1
- package/dist/commands/self-host.js +65 -50
- package/dist/commands/self-host.js.map +1 -1
- package/dist/commands/self-update.d.ts.map +1 -1
- package/dist/commands/self-update.js +3 -2
- package/dist/commands/self-update.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +95 -29
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js +3 -2
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +54 -21
- package/dist/commands/update.js.map +1 -1
- package/dist/compose-rename.d.ts +10 -0
- package/dist/compose-rename.d.ts.map +1 -0
- package/dist/compose-rename.js +67 -0
- package/dist/compose-rename.js.map +1 -0
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/dev-compose.d.ts +26 -0
- package/dist/dev-compose.d.ts.map +1 -1
- package/dist/dev-compose.js +357 -79
- package/dist/dev-compose.js.map +1 -1
- package/dist/dev-log-bus.d.ts +30 -0
- package/dist/dev-log-bus.d.ts.map +1 -0
- package/dist/dev-log-bus.js +87 -0
- package/dist/dev-log-bus.js.map +1 -0
- package/dist/dev-log-filter.d.ts +10 -0
- package/dist/dev-log-filter.d.ts.map +1 -0
- package/dist/dev-log-filter.js +36 -0
- package/dist/dev-log-filter.js.map +1 -0
- package/dist/dev-logo.d.ts +12 -0
- package/dist/dev-logo.d.ts.map +1 -0
- package/dist/dev-logo.js +56 -0
- package/dist/dev-logo.js.map +1 -0
- package/dist/dev-ports.d.ts +27 -0
- package/dist/dev-ports.d.ts.map +1 -0
- package/dist/dev-ports.js +171 -0
- package/dist/dev-ports.js.map +1 -0
- package/dist/dev-session-lock.d.ts +25 -0
- package/dist/dev-session-lock.d.ts.map +1 -0
- package/dist/dev-session-lock.js +81 -0
- package/dist/dev-session-lock.js.map +1 -0
- package/dist/dev-session.d.ts +26 -0
- package/dist/dev-session.d.ts.map +1 -0
- package/dist/dev-session.js +106 -0
- package/dist/dev-session.js.map +1 -0
- package/dist/dev-shutdown.d.ts +25 -0
- package/dist/dev-shutdown.d.ts.map +1 -0
- package/dist/dev-shutdown.js +114 -0
- package/dist/dev-shutdown.js.map +1 -0
- package/dist/dev-task-colors.d.ts +13 -0
- package/dist/dev-task-colors.d.ts.map +1 -0
- package/dist/dev-task-colors.js +43 -0
- package/dist/dev-task-colors.js.map +1 -0
- package/dist/dev-tui.d.ts +24 -0
- package/dist/dev-tui.d.ts.map +1 -0
- package/dist/dev-tui.js +188 -0
- package/dist/dev-tui.js.map +1 -0
- package/dist/diff-output.d.ts +5 -1
- package/dist/diff-output.d.ts.map +1 -1
- package/dist/diff-output.js +69 -0
- package/dist/diff-output.js.map +1 -1
- package/dist/docker-runtime.d.ts +30 -0
- package/dist/docker-runtime.d.ts.map +1 -0
- package/dist/docker-runtime.js +118 -0
- package/dist/docker-runtime.js.map +1 -0
- package/dist/engine-client.d.ts +10 -1
- package/dist/engine-client.d.ts.map +1 -1
- package/dist/engine-client.js +76 -17
- package/dist/engine-client.js.map +1 -1
- package/dist/engine-push-output.d.ts +17 -0
- package/dist/engine-push-output.d.ts.map +1 -0
- package/dist/engine-push-output.js +64 -0
- package/dist/engine-push-output.js.map +1 -0
- package/dist/ensure-binary.js +2 -2
- package/dist/ensure-binary.js.map +1 -1
- package/dist/env-file.d.ts +5 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +33 -0
- package/dist/env-file.js.map +1 -0
- package/dist/gitignore.d.ts +8 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +41 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/kong-config.d.ts +9 -0
- package/dist/kong-config.d.ts.map +1 -1
- package/dist/kong-config.js +18 -1
- package/dist/kong-config.js.map +1 -1
- package/dist/link.d.ts +66 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +160 -0
- package/dist/link.js.map +1 -0
- package/dist/process-manager.d.ts +8 -0
- package/dist/process-manager.d.ts.map +1 -1
- package/dist/process-manager.js +53 -9
- package/dist/process-manager.js.map +1 -1
- package/dist/project-config.d.ts +30 -3
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +37 -4
- package/dist/project-config.js.map +1 -1
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +3 -0
- package/dist/prompts.js.map +1 -0
- package/dist/pull-utils.d.ts +50 -14
- package/dist/pull-utils.d.ts.map +1 -1
- package/dist/pull-utils.js +152 -12
- package/dist/pull-utils.js.map +1 -1
- package/dist/resolve-target.d.ts +86 -0
- package/dist/resolve-target.d.ts.map +1 -0
- package/dist/resolve-target.js +291 -0
- package/dist/resolve-target.js.map +1 -0
- package/dist/restore-system-relation-targets.d.ts +3 -0
- package/dist/restore-system-relation-targets.d.ts.map +1 -0
- package/dist/restore-system-relation-targets.js +45 -0
- package/dist/restore-system-relation-targets.js.map +1 -0
- package/dist/runtime-routes.d.ts.map +1 -1
- package/dist/runtime-routes.js +7 -0
- package/dist/runtime-routes.js.map +1 -1
- package/dist/schema-ast-v2.d.ts +1 -1
- package/dist/schema-ast-v2.d.ts.map +1 -1
- package/dist/schema-ast-v2.js +2 -2
- package/dist/schema-ast-v2.js.map +1 -1
- package/dist/schema-sources.d.ts +40 -0
- package/dist/schema-sources.d.ts.map +1 -0
- package/dist/schema-sources.js +183 -0
- package/dist/schema-sources.js.map +1 -0
- package/dist/scripts/postinstall.js +5 -1
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/self-host-compose.d.ts +37 -1
- package/dist/self-host-compose.d.ts.map +1 -1
- package/dist/self-host-compose.js +234 -43
- package/dist/self-host-compose.js.map +1 -1
- package/dist/storage-provision.d.ts +4 -0
- package/dist/storage-provision.d.ts.map +1 -1
- package/dist/storage-provision.js +24 -2
- package/dist/storage-provision.js.map +1 -1
- package/dist/supatype-eval-1781522769253.d.mts +2 -0
- package/dist/supatype-eval-1781522769253.d.mts.map +1 -0
- package/dist/supatype-eval-1781522769253.mjs +3 -0
- package/dist/supatype-eval-1781522769253.mjs.map +1 -0
- package/dist/systemd.js +2 -2
- package/dist/systemd.js.map +1 -1
- package/dist/target-client.d.ts +10 -0
- package/dist/target-client.d.ts.map +1 -0
- package/dist/target-client.js +22 -0
- package/dist/target-client.js.map +1 -0
- package/dist/type-extractor.d.ts +11 -0
- package/dist/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor.js +95 -8
- package/dist/type-extractor.js.map +1 -1
- package/dist/ui/brand.d.ts +9 -0
- package/dist/ui/brand.d.ts.map +1 -0
- package/dist/ui/brand.js +11 -0
- package/dist/ui/brand.js.map +1 -0
- package/dist/ui/confirm.d.ts +12 -0
- package/dist/ui/confirm.d.ts.map +1 -0
- package/dist/ui/confirm.js +28 -0
- package/dist/ui/confirm.js.map +1 -0
- package/dist/ui/fatal.d.ts +10 -0
- package/dist/ui/fatal.d.ts.map +1 -0
- package/dist/ui/fatal.js +34 -0
- package/dist/ui/fatal.js.map +1 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/interactive.d.ts +3 -0
- package/dist/ui/interactive.d.ts.map +1 -0
- package/dist/ui/interactive.js +5 -0
- package/dist/ui/interactive.js.map +1 -0
- package/dist/ui/messages.d.ts +10 -0
- package/dist/ui/messages.d.ts.map +1 -0
- package/dist/ui/messages.js +35 -0
- package/dist/ui/messages.js.map +1 -0
- package/dist/ui/next-steps.d.ts +3 -0
- package/dist/ui/next-steps.d.ts.map +1 -0
- package/dist/ui/next-steps.js +10 -0
- package/dist/ui/next-steps.js.map +1 -0
- package/dist/ui/progress.d.ts +5 -0
- package/dist/ui/progress.d.ts.map +1 -0
- package/dist/ui/progress.js +24 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/prompts.d.ts +14 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +34 -0
- package/dist/ui/prompts.js.map +1 -0
- package/package.json +5 -2
- package/src/app/framework.ts +1 -3
- package/src/app/proxy-dev-app.ts +114 -6
- package/src/app-config.ts +80 -0
- package/src/binary-cache.ts +102 -52
- package/src/cli.ts +16 -2
- package/src/commands/add.ts +97 -0
- package/src/commands/admin.ts +381 -190
- package/src/commands/adopt.ts +82 -0
- package/src/commands/app.ts +20 -17
- package/src/commands/cache.ts +11 -10
- package/src/commands/cloud.ts +91 -142
- package/src/commands/db.ts +40 -63
- package/src/commands/deploy.ts +186 -126
- package/src/commands/dev.ts +98 -55
- package/src/commands/diff.ts +52 -43
- package/src/commands/doctor.ts +103 -0
- package/src/commands/engine.ts +5 -4
- package/src/commands/functions.ts +187 -123
- package/src/commands/generate.ts +5 -4
- package/src/commands/init.ts +1087 -104
- package/src/commands/introspect.ts +48 -0
- package/src/commands/keys.ts +56 -14
- package/src/commands/link-helpers.ts +273 -0
- package/src/commands/logs.ts +5 -4
- package/src/commands/migrate-from-v1.ts +3 -2
- package/src/commands/migrate.ts +167 -27
- package/src/commands/pg.ts +13 -18
- package/src/commands/plugins.ts +55 -46
- package/src/commands/pull.ts +38 -9
- package/src/commands/push.ts +148 -175
- package/src/commands/seed.ts +5 -4
- package/src/commands/self-host.ts +85 -54
- package/src/commands/self-update.ts +3 -2
- package/src/commands/status.ts +102 -33
- package/src/commands/types.ts +3 -2
- package/src/commands/update.ts +59 -23
- package/src/compose-rename.ts +76 -0
- package/src/config.ts +2 -1
- package/src/dev-compose.ts +462 -76
- package/src/dev-log-bus.ts +101 -0
- package/src/dev-log-filter.ts +32 -0
- package/src/dev-logo.ts +61 -0
- package/src/dev-ports.ts +212 -0
- package/src/dev-session-lock.ts +101 -0
- package/src/dev-session.ts +130 -0
- package/src/dev-shutdown.ts +147 -0
- package/src/dev-task-colors.ts +47 -0
- package/src/dev-tui.ts +232 -0
- package/src/diff-output.ts +79 -1
- package/src/docker-runtime.ts +151 -0
- package/src/engine-client.ts +81 -17
- package/src/engine-push-output.ts +75 -0
- package/src/ensure-binary.ts +2 -2
- package/src/env-file.ts +37 -0
- package/src/gitignore.ts +48 -0
- package/src/kong-config.ts +24 -1
- package/src/link.ts +243 -0
- package/src/process-manager.ts +66 -10
- package/src/project-config.ts +62 -7
- package/src/prompts.ts +2 -0
- package/src/pull-utils.ts +217 -23
- package/src/resolve-target.ts +419 -0
- package/src/restore-system-relation-targets.ts +45 -0
- package/src/runtime-routes.ts +7 -0
- package/src/schema-ast-v2.ts +2 -1
- package/src/schema-sources.ts +248 -0
- package/src/scripts/postinstall.ts +7 -1
- package/src/self-host-compose.ts +262 -46
- package/src/storage-provision.ts +33 -1
- package/src/supatype-eval-1781522769253.mts +1 -0
- package/src/systemd.ts +2 -2
- package/src/target-client.ts +40 -0
- package/src/type-extractor.ts +124 -11
- package/src/ui/README.md +17 -0
- package/src/ui/brand.ts +12 -0
- package/src/ui/confirm.ts +38 -0
- package/src/ui/fatal.ts +43 -0
- package/src/ui/index.ts +8 -0
- package/src/ui/interactive.ts +4 -0
- package/src/ui/messages.ts +43 -0
- package/src/ui/next-steps.ts +10 -0
- package/src/ui/progress.ts +28 -0
- package/src/ui/prompts.ts +40 -0
- package/tests/admin-ensure.test.ts +59 -0
- package/tests/cli-help.test.ts +27 -2
- package/tests/config.test.ts +29 -2
- package/tests/dev-ports.test.ts +41 -0
- package/tests/dev-session-lock.test.ts +54 -0
- package/tests/dev-ui.test.ts +162 -0
- package/tests/docker-runtime.test.ts +236 -0
- package/tests/engine-push-output.test.ts +67 -0
- package/tests/init.test.ts +197 -18
- package/tests/link.test.ts +148 -0
- package/tests/minisign.test.ts +102 -0
- package/tests/proxy-dev-app.test.ts +45 -1
- package/tests/pull-utils.test.ts +5 -4
- package/tests/runtime-contract.test.ts +186 -2
- package/tests/schema-sources.test.ts +119 -0
- package/tests/storage-provision.test.ts +100 -0
- package/tests/ui-confirm.test.ts +41 -0
- package/tests/ui-messages.test.ts +66 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/process-manager.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* colored prefix, and restart on crash with exponential backoff.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { type ChildProcess, spawn } from "node:child_process"
|
|
6
|
+
import { type ChildProcess, spawn, spawnSync } from "node:child_process"
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
8
8
|
import { unlink } from "node:fs/promises"
|
|
9
9
|
import { join } from "node:path"
|
|
10
|
+
import { enhanceProcessOptions } from "./dev-session.js"
|
|
10
11
|
|
|
11
12
|
export interface ProcessOptions {
|
|
12
13
|
/** Human-readable label (used in log prefix and PID filename). */
|
|
@@ -27,6 +28,12 @@ export interface ProcessOptions {
|
|
|
27
28
|
onExit?: () => void
|
|
28
29
|
/** Use shell to spawn (required for pnpm/npm/yarn .cmd shims on Windows). */
|
|
29
30
|
shell?: boolean
|
|
31
|
+
/** When set (TUI mode), receive log lines instead of writing to stdout/stderr. */
|
|
32
|
+
onLine?: (line: string, stream: "stdout" | "stderr") => void
|
|
33
|
+
/** Return false to drop a line before logging. */
|
|
34
|
+
shouldLogLine?: (line: string) => boolean
|
|
35
|
+
/** Called before auto-restart after a non-zero exit (e.g. free a stale port). */
|
|
36
|
+
beforeRestart?: () => void
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
const RESET = "\x1b[0m"
|
|
@@ -35,13 +42,24 @@ export class ProcessManager {
|
|
|
35
42
|
private child: ChildProcess | null = null
|
|
36
43
|
private stopped = false
|
|
37
44
|
private backoffMs: number
|
|
38
|
-
private opts:
|
|
45
|
+
private opts: ProcessOptions & {
|
|
46
|
+
colour: string
|
|
47
|
+
cwd: string
|
|
48
|
+
env: Record<string, string>
|
|
49
|
+
initialBackoffMs: number
|
|
50
|
+
maxBackoffMs: number
|
|
51
|
+
onExit: () => void
|
|
52
|
+
shell: boolean
|
|
53
|
+
}
|
|
54
|
+
/** Skip immediate duplicate lines (npm prints script banners to both streams). */
|
|
55
|
+
private lastLoggedLine = ""
|
|
39
56
|
|
|
40
57
|
constructor(
|
|
41
58
|
private readonly bin: string,
|
|
42
59
|
private readonly args: string[],
|
|
43
60
|
opts: ProcessOptions,
|
|
44
61
|
) {
|
|
62
|
+
const merged = enhanceProcessOptions(opts.label, opts)
|
|
45
63
|
this.opts = {
|
|
46
64
|
colour: "\x1b[36m",
|
|
47
65
|
cwd: process.cwd(),
|
|
@@ -50,7 +68,7 @@ export class ProcessManager {
|
|
|
50
68
|
maxBackoffMs: 30_000,
|
|
51
69
|
onExit: () => {},
|
|
52
70
|
shell: false,
|
|
53
|
-
...
|
|
71
|
+
...merged,
|
|
54
72
|
}
|
|
55
73
|
this.backoffMs = this.opts.initialBackoffMs
|
|
56
74
|
}
|
|
@@ -64,7 +82,20 @@ export class ProcessManager {
|
|
|
64
82
|
/** Stop the process and clear the PID file. */
|
|
65
83
|
async stop(): Promise<void> {
|
|
66
84
|
this.stopped = true
|
|
67
|
-
if (this.child
|
|
85
|
+
if (!this.child || this.child.killed) {
|
|
86
|
+
await this.clearPid()
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const pid = this.child.pid
|
|
91
|
+
if (process.platform === "win32" && this.opts.shell && pid) {
|
|
92
|
+
spawnSync("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore" })
|
|
93
|
+
this.child = null
|
|
94
|
+
await this.clearPid()
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!this.child.killed) {
|
|
68
99
|
this.child.kill("SIGTERM")
|
|
69
100
|
// Give it 5s to exit gracefully, then SIGKILL.
|
|
70
101
|
await new Promise<void>((resolve) => {
|
|
@@ -99,22 +130,43 @@ export class ProcessManager {
|
|
|
99
130
|
? `${this.opts.colour}[${this.opts.label}]${RESET} `
|
|
100
131
|
: `[${this.opts.label}] `
|
|
101
132
|
|
|
133
|
+
const logLine = (line: string, stream: NodeJS.WriteStream): void => {
|
|
134
|
+
if (!line) return
|
|
135
|
+
if (this.opts.shouldLogLine && !this.opts.shouldLogLine(line)) return
|
|
136
|
+
if (this.opts.onLine) {
|
|
137
|
+
if (line !== this.lastLoggedLine) {
|
|
138
|
+
this.lastLoggedLine = line
|
|
139
|
+
this.opts.onLine(line, stream === process.stderr ? "stderr" : "stdout")
|
|
140
|
+
}
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
if (line === this.lastLoggedLine) return
|
|
144
|
+
this.lastLoggedLine = line
|
|
145
|
+
stream.write(prefix + line + "\n")
|
|
146
|
+
}
|
|
147
|
+
|
|
102
148
|
this.child.stdout?.on("data", (chunk: Buffer) => {
|
|
103
149
|
for (const line of chunk.toString().split("\n")) {
|
|
104
|
-
|
|
150
|
+
logLine(line, process.stdout)
|
|
105
151
|
}
|
|
106
152
|
})
|
|
107
153
|
|
|
108
154
|
this.child.stderr?.on("data", (chunk: Buffer) => {
|
|
109
155
|
for (const line of chunk.toString().split("\n")) {
|
|
110
|
-
|
|
156
|
+
logLine(line, process.stderr)
|
|
111
157
|
}
|
|
112
158
|
})
|
|
113
159
|
|
|
114
160
|
this.child.once("error", (err) => {
|
|
115
161
|
if (this.stopped) return
|
|
116
|
-
|
|
162
|
+
const message = `${prefix}failed to start: ${err.message}\n`
|
|
163
|
+
if (this.opts.onLine) {
|
|
164
|
+
this.opts.onLine(`failed to start: ${err.message}`, "stderr")
|
|
165
|
+
} else {
|
|
166
|
+
process.stderr.write(message)
|
|
167
|
+
}
|
|
117
168
|
setTimeout(() => {
|
|
169
|
+
this.opts.beforeRestart?.()
|
|
118
170
|
this.backoffMs = Math.min(this.backoffMs * 2, this.opts.maxBackoffMs)
|
|
119
171
|
this.spawn()
|
|
120
172
|
}, this.backoffMs)
|
|
@@ -129,11 +181,15 @@ export class ProcessManager {
|
|
|
129
181
|
}
|
|
130
182
|
|
|
131
183
|
const reason = signal ? `signal ${signal}` : `code ${code}`
|
|
132
|
-
process.
|
|
133
|
-
|
|
134
|
-
|
|
184
|
+
const restartMsg = `${prefix}process exited (${reason}), restarting in ${this.backoffMs}ms\n`
|
|
185
|
+
if (this.opts.onLine) {
|
|
186
|
+
this.opts.onLine(`process exited (${reason}), restarting in ${this.backoffMs}ms`, "stderr")
|
|
187
|
+
} else {
|
|
188
|
+
process.stderr.write(restartMsg)
|
|
189
|
+
}
|
|
135
190
|
|
|
136
191
|
setTimeout(() => {
|
|
192
|
+
this.opts.beforeRestart?.()
|
|
137
193
|
this.backoffMs = Math.min(this.backoffMs * 2, this.opts.maxBackoffMs)
|
|
138
194
|
this.spawn()
|
|
139
195
|
}, this.backoffMs)
|
package/src/project-config.ts
CHANGED
|
@@ -59,6 +59,16 @@ export interface SupatypeProjectConfig {
|
|
|
59
59
|
postgrestPort?: number
|
|
60
60
|
/** Domain for ACME TLS certificate (mode=standalone). */
|
|
61
61
|
domain?: string
|
|
62
|
+
/**
|
|
63
|
+
* TLS for self-host HTTPS (Kong ACME / Let's Encrypt).
|
|
64
|
+
* Requires `mode: "standalone"` and a non-empty `domain`.
|
|
65
|
+
*/
|
|
66
|
+
tls?: {
|
|
67
|
+
/** ACME contact email for Let's Encrypt (required to enable HTTPS). */
|
|
68
|
+
email?: string
|
|
69
|
+
/** "kong" (default) = Kong acme plugin; "none" = stay HTTP even with a domain. */
|
|
70
|
+
provider?: "kong" | "none"
|
|
71
|
+
}
|
|
62
72
|
}
|
|
63
73
|
app: {
|
|
64
74
|
/**
|
|
@@ -85,10 +95,13 @@ export interface SupatypeProjectConfig {
|
|
|
85
95
|
start?: string
|
|
86
96
|
}
|
|
87
97
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
98
|
+
* Optional pins for engine, server, postgres, and deno.
|
|
99
|
+
* Omitted = resolve latest from CDN at runtime (native) or use Docker :latest.
|
|
100
|
+
* When set, native binaries cache under ~/.supatype/cache/{component}/{version}/
|
|
101
|
+
* and Docker image tags are synced to `.env` on `supatype dev` / `supatype push`.
|
|
102
|
+
* Use **`"local"`** with the matching **`overrides.*`** entry for contributor builds.
|
|
90
103
|
*/
|
|
91
|
-
versions
|
|
104
|
+
versions?: Partial<ComponentVersions>
|
|
92
105
|
/**
|
|
93
106
|
* Override component binaries with local build paths.
|
|
94
107
|
* Intended for supatype contributors testing local changes.
|
|
@@ -198,6 +211,14 @@ export interface SupatypeProjectConfig {
|
|
|
198
211
|
/** Custom response headers for the deployed static site. */
|
|
199
212
|
headers?: Record<string, string>
|
|
200
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Persistent environment defaults for `resolveTarget()` when `--env` is omitted.
|
|
216
|
+
* Ephemeral schema branches (Phase 22) use `.supatype/branch.json`, not this block.
|
|
217
|
+
*/
|
|
218
|
+
environments?: {
|
|
219
|
+
default?: string
|
|
220
|
+
branchDefaults?: Record<string, string>
|
|
221
|
+
}
|
|
201
222
|
/**
|
|
202
223
|
* Optional Postgres URL for CLI commands that talk to the DB (`push`, `migrate`, …).
|
|
203
224
|
* When omitted, `DATABASE_URL` from the environment is used, then a local default DSN.
|
|
@@ -233,7 +254,9 @@ export function mergeProjectConfig(
|
|
|
233
254
|
database: { ...base.database, ...override.database },
|
|
234
255
|
server: { ...base.server, ...override.server },
|
|
235
256
|
app: { ...base.app, ...override.app },
|
|
236
|
-
|
|
257
|
+
...(base.versions !== undefined || override.versions !== undefined
|
|
258
|
+
? { versions: { ...base.versions, ...override.versions } }
|
|
259
|
+
: {}),
|
|
237
260
|
...(base.overrides !== undefined || override.overrides !== undefined
|
|
238
261
|
? {
|
|
239
262
|
overrides: {
|
|
@@ -285,6 +308,23 @@ export function mergeProjectConfig(
|
|
|
285
308
|
...(base.admin !== undefined || override.admin !== undefined
|
|
286
309
|
? { admin: { ...base.admin, ...override.admin } as NonNullable<SupatypeProjectConfig["admin"]> }
|
|
287
310
|
: {}),
|
|
311
|
+
...(base.environments !== undefined || override.environments !== undefined
|
|
312
|
+
? (() => {
|
|
313
|
+
const b = base.environments
|
|
314
|
+
const o = override.environments
|
|
315
|
+
const mergedBranchDefaults =
|
|
316
|
+
b?.branchDefaults !== undefined || o?.branchDefaults !== undefined
|
|
317
|
+
? { ...(b?.branchDefaults ?? {}), ...(o?.branchDefaults ?? {}) }
|
|
318
|
+
: undefined
|
|
319
|
+
return {
|
|
320
|
+
environments: {
|
|
321
|
+
...b,
|
|
322
|
+
...o,
|
|
323
|
+
...(mergedBranchDefaults !== undefined ? { branchDefaults: mergedBranchDefaults } : {}),
|
|
324
|
+
} as NonNullable<SupatypeProjectConfig["environments"]>,
|
|
325
|
+
}
|
|
326
|
+
})()
|
|
327
|
+
: {}),
|
|
288
328
|
}
|
|
289
329
|
}
|
|
290
330
|
|
|
@@ -307,9 +347,6 @@ export function validateProjectConfig(raw: unknown, filename: string): SupatypeP
|
|
|
307
347
|
if (!cfg["app"]) {
|
|
308
348
|
throw new Error(`${filename}: app section is required`)
|
|
309
349
|
}
|
|
310
|
-
if (!cfg["versions"]) {
|
|
311
|
-
throw new Error(`${filename}: versions section is required`)
|
|
312
|
-
}
|
|
313
350
|
|
|
314
351
|
return raw as SupatypeProjectConfig
|
|
315
352
|
}
|
|
@@ -363,6 +400,24 @@ export function serverBaseUrl(cfg: SupatypeProjectConfig): string | undefined {
|
|
|
363
400
|
}
|
|
364
401
|
}
|
|
365
402
|
|
|
403
|
+
/**
|
|
404
|
+
* True when `supatype self-host compose` should render Kong ACME TLS (Let's Encrypt).
|
|
405
|
+
* Gated on a real self-host render (not `supatype dev`), standalone mode, a non-empty
|
|
406
|
+
* domain, an ACME contact email, and `tls.provider !== "none"`.
|
|
407
|
+
*/
|
|
408
|
+
export function selfHostTlsEnabled(
|
|
409
|
+
cfg: SupatypeProjectConfig,
|
|
410
|
+
devLocal = false,
|
|
411
|
+
): boolean {
|
|
412
|
+
if (devLocal) return false
|
|
413
|
+
if (cfg.server.mode !== "standalone") return false
|
|
414
|
+
const domain = cfg.server.domain?.trim()
|
|
415
|
+
if (!domain) return false
|
|
416
|
+
const tls = cfg.server.tls
|
|
417
|
+
if (!tls || tls.provider === "none") return false
|
|
418
|
+
return Boolean(tls.email?.trim())
|
|
419
|
+
}
|
|
420
|
+
|
|
366
421
|
/** Resolved runtime provider (`config.provider` ?? `database.provider` ?? native). */
|
|
367
422
|
export function resolveRuntimeProvider(cfg: SupatypeProjectConfig): "native" | "docker" {
|
|
368
423
|
return cfg.provider ?? cfg.database.provider ?? "native"
|
package/src/prompts.ts
ADDED
package/src/pull-utils.ts
CHANGED
|
@@ -1,41 +1,237 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Utilities for
|
|
2
|
+
* Utilities for `pull` and `introspect` — map engine DatabaseState to Model<> scaffold.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export interface
|
|
5
|
+
export interface DbColumnState {
|
|
6
6
|
name: string
|
|
7
|
-
|
|
7
|
+
dataType: string
|
|
8
|
+
udtName: string
|
|
8
9
|
nullable: boolean
|
|
10
|
+
default?: string | null
|
|
11
|
+
ordinalPosition?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DbTableState {
|
|
15
|
+
schema?: string
|
|
16
|
+
name: string
|
|
17
|
+
columns: DbColumnState[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface DbConstraintState {
|
|
21
|
+
table: string
|
|
22
|
+
name: string
|
|
23
|
+
constraintType: string
|
|
24
|
+
columns: string[]
|
|
25
|
+
foreignTable?: string | null
|
|
26
|
+
foreignColumns?: string[] | null
|
|
27
|
+
comment?: string | null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DbIndexState {
|
|
31
|
+
table: string
|
|
32
|
+
name: string
|
|
33
|
+
columns: string[]
|
|
34
|
+
unique: boolean
|
|
35
|
+
method: string
|
|
9
36
|
isPrimary: boolean
|
|
10
|
-
|
|
11
|
-
hasDefault: boolean
|
|
37
|
+
comment?: string | null
|
|
12
38
|
}
|
|
13
39
|
|
|
14
|
-
|
|
15
|
-
|
|
40
|
+
export interface DatabaseStateJson {
|
|
41
|
+
schema?: string
|
|
42
|
+
tables: DbTableState[]
|
|
43
|
+
constraints?: DbConstraintState[]
|
|
44
|
+
indexes?: DbIndexState[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ColumnInfo {
|
|
16
48
|
name: string
|
|
17
|
-
|
|
49
|
+
pgType: string
|
|
18
50
|
nullable: boolean
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
51
|
+
isPrimary: boolean
|
|
52
|
+
isUnique: boolean
|
|
53
|
+
hasDefault: boolean
|
|
22
54
|
references?: { table: string; column: string }
|
|
23
55
|
}
|
|
24
56
|
|
|
25
|
-
/** Map engine introspection
|
|
26
|
-
export function introspectColumnToColumnInfo(col:
|
|
27
|
-
const def = col.default
|
|
57
|
+
/** Map engine introspection column to {@link ColumnInfo}. */
|
|
58
|
+
export function introspectColumnToColumnInfo(col: DbColumnState): ColumnInfo {
|
|
28
59
|
return {
|
|
29
60
|
name: col.name,
|
|
30
|
-
pgType: col.
|
|
61
|
+
pgType: col.udtName || col.dataType,
|
|
31
62
|
nullable: col.nullable,
|
|
32
|
-
isPrimary: col.
|
|
33
|
-
isUnique:
|
|
34
|
-
hasDefault:
|
|
63
|
+
isPrimary: col.name === "id" && (col.udtName === "uuid" || col.dataType.includes("uuid")),
|
|
64
|
+
isUnique: false,
|
|
65
|
+
hasDefault: col.default != null && col.default !== "",
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function singleColumnUniques(
|
|
70
|
+
table: string,
|
|
71
|
+
constraints: DbConstraintState[] | undefined,
|
|
72
|
+
): Map<string, boolean> {
|
|
73
|
+
const out = new Map<string, boolean>()
|
|
74
|
+
for (const c of constraints ?? []) {
|
|
75
|
+
if (c.table !== table || c.constraintType !== "unique" || c.columns.length !== 1) continue
|
|
76
|
+
out.set(c.columns[0]!, true)
|
|
35
77
|
}
|
|
78
|
+
return out
|
|
36
79
|
}
|
|
37
80
|
|
|
38
|
-
|
|
81
|
+
function compositeIndexes(
|
|
82
|
+
table: string,
|
|
83
|
+
indexes: DbIndexState[] | undefined,
|
|
84
|
+
): Array<{ fields: string[]; unique: boolean }> {
|
|
85
|
+
const out: Array<{ fields: string[]; unique: boolean }> = []
|
|
86
|
+
for (const idx of indexes ?? []) {
|
|
87
|
+
if (idx.table !== table || idx.isPrimary || idx.columns.length < 2) continue
|
|
88
|
+
out.push({ fields: idx.columns, unique: idx.unique })
|
|
89
|
+
}
|
|
90
|
+
return out
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Map a Postgres column to a Model<> field type string (draft). */
|
|
94
|
+
export function pgTypeToModelField(col: ColumnInfo): string {
|
|
95
|
+
const name = col.name
|
|
96
|
+
const type = col.pgType.toLowerCase()
|
|
97
|
+
const optional = col.nullable ? "Optional<" : ""
|
|
98
|
+
const optionalClose = col.nullable ? ">" : ""
|
|
99
|
+
|
|
100
|
+
if (name === "id" && type.includes("uuid")) {
|
|
101
|
+
return `id: SupatypeAuthUserId`
|
|
102
|
+
}
|
|
103
|
+
if (name.endsWith("_id") && type.includes("uuid")) {
|
|
104
|
+
const base = name.replace(/_id$/, "")
|
|
105
|
+
const rel = base.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())
|
|
106
|
+
const relName = rel.charAt(0).toUpperCase() + rel.slice(1)
|
|
107
|
+
return `${name}: UUID\n // TODO: relation — RelatedTo<"${relName}">`
|
|
108
|
+
}
|
|
109
|
+
if (name === "created_at" || name === "updated_at") {
|
|
110
|
+
return `${name}: Timestamp`
|
|
111
|
+
}
|
|
112
|
+
if (name === "deleted_at") {
|
|
113
|
+
return `${name}: Optional<Timestamp>`
|
|
114
|
+
}
|
|
115
|
+
if (type.includes("timestamptz") || type.includes("timestamp with time zone")) {
|
|
116
|
+
return `${name}: ${optional}Timestamp${optionalClose}`
|
|
117
|
+
}
|
|
118
|
+
if (type.includes("uuid")) {
|
|
119
|
+
const inner = col.isUnique ? "Unique<UUID>" : "UUID"
|
|
120
|
+
return `${name}: ${optional}${inner}${optionalClose}`
|
|
121
|
+
}
|
|
122
|
+
if (name.includes("email") && (type.includes("text") || type.includes("varchar"))) {
|
|
123
|
+
const inner = col.isUnique ? "Unique<Email>" : "Email"
|
|
124
|
+
return `${name}: ${optional}${inner}${optionalClose}`
|
|
125
|
+
}
|
|
126
|
+
if (name === "slug" || name.endsWith("_slug")) {
|
|
127
|
+
return `${name}: Slug<"title">`
|
|
128
|
+
}
|
|
129
|
+
if (type.includes("jsonb")) {
|
|
130
|
+
return `${name}: ${optional}JSON${optionalClose}`
|
|
131
|
+
}
|
|
132
|
+
if (type.includes("bool")) {
|
|
133
|
+
return `${name}: ${optional}boolean${optionalClose}`
|
|
134
|
+
}
|
|
135
|
+
if (type.includes("int8") || type.includes("bigint")) {
|
|
136
|
+
return `${name}: ${optional}BigInt${optionalClose}`
|
|
137
|
+
}
|
|
138
|
+
if (type.includes("int")) {
|
|
139
|
+
return `${name}: ${optional}Int${optionalClose}`
|
|
140
|
+
}
|
|
141
|
+
if (type.includes("text") || type.includes("varchar")) {
|
|
142
|
+
const inner = col.isUnique ? "Unique<string>" : "string"
|
|
143
|
+
return `${name}: ${optional}${inner}${optionalClose}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return `${name}: string /* TODO: ${col.pgType} */`
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Convert snake_case table name to PascalCase model export name. */
|
|
150
|
+
export function toModelName(s: string): string {
|
|
151
|
+
return s
|
|
152
|
+
.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())
|
|
153
|
+
.replace(/^([a-z])/, (c: string) => c.toUpperCase())
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Generate draft schema/index.ts content from introspected DatabaseState. */
|
|
157
|
+
export function databaseStateToSchemaScaffold(state: DatabaseStateJson): string {
|
|
158
|
+
const constraints = state.constraints ?? []
|
|
159
|
+
const indexes = state.indexes ?? []
|
|
160
|
+
const skipTables = new Set(["spatial_ref_sys", "schema_migrations"])
|
|
161
|
+
|
|
162
|
+
const lines: string[] = [
|
|
163
|
+
"// DRAFT — generated by `supatype pull`. Review access rules, relations, and indexes before push.",
|
|
164
|
+
'import type { Model, Public, UUID, Timestamp, Optional, Unique, Email, Slug, SupatypeAuthUserId, JSON, Int, BigInt } from "@supatype/types"',
|
|
165
|
+
"",
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
for (const table of state.tables) {
|
|
169
|
+
if (skipTables.has(table.name) || table.name.startsWith("_")) continue
|
|
170
|
+
|
|
171
|
+
const modelName = toModelName(table.name)
|
|
172
|
+
const uniques = singleColumnUniques(table.name, constraints)
|
|
173
|
+
const modelIndexes = compositeIndexes(table.name, indexes)
|
|
174
|
+
|
|
175
|
+
const fieldLines: string[] = []
|
|
176
|
+
for (const col of table.columns) {
|
|
177
|
+
if (col.name === "created_at" || col.name === "updated_at") continue
|
|
178
|
+
const info = introspectColumnToColumnInfo(col)
|
|
179
|
+
info.isPrimary = col.name === "id"
|
|
180
|
+
info.isUnique = uniques.get(col.name) ?? false
|
|
181
|
+
fieldLines.push(` ${pgTypeToModelField(info)}`)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const hasTimestamps = table.columns.some((c) => c.name === "created_at")
|
|
185
|
+
if (hasTimestamps) {
|
|
186
|
+
fieldLines.push(" created_at: Timestamp")
|
|
187
|
+
fieldLines.push(" updated_at: Timestamp")
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const indexBlock =
|
|
191
|
+
modelIndexes.length > 0
|
|
192
|
+
? `\n indexes: [\n${modelIndexes
|
|
193
|
+
.map(
|
|
194
|
+
(idx) =>
|
|
195
|
+
` { fields: [${idx.fields.map((f) => `"${f}"`).join(", ")}]${idx.unique ? ", unique: true" : ""} },`,
|
|
196
|
+
)
|
|
197
|
+
.join("\n")}\n ],`
|
|
198
|
+
: ""
|
|
199
|
+
|
|
200
|
+
lines.push(`export type ${modelName} = Model<{`)
|
|
201
|
+
lines.push(fieldLines.join("\n"))
|
|
202
|
+
lines.push(`}, {`)
|
|
203
|
+
lines.push(` access: {`)
|
|
204
|
+
lines.push(` read: Public`)
|
|
205
|
+
lines.push(` create: Public`)
|
|
206
|
+
lines.push(` update: Public`)
|
|
207
|
+
lines.push(` delete: Public`)
|
|
208
|
+
lines.push(` },${indexBlock}`)
|
|
209
|
+
lines.push(`}>`)
|
|
210
|
+
lines.push("")
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return lines.join("\n")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Human-readable introspection summary for `supatype introspect`. */
|
|
217
|
+
export function printIntrospectSummary(state: DatabaseStateJson): void {
|
|
218
|
+
console.log(`Schema: ${state.schema ?? "public"}`)
|
|
219
|
+
console.log(`Tables: ${state.tables.length}`)
|
|
220
|
+
for (const table of state.tables) {
|
|
221
|
+
console.log(`\n ${table.name} (${table.columns.length} columns)`)
|
|
222
|
+
for (const col of table.columns) {
|
|
223
|
+
const nullMark = col.nullable ? "?" : ""
|
|
224
|
+
console.log(` ${col.name}${nullMark}: ${col.udtName || col.dataType}`)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const constraintCount = state.constraints?.length ?? 0
|
|
228
|
+
const indexCount = state.indexes?.length ?? 0
|
|
229
|
+
if (constraintCount + indexCount > 0) {
|
|
230
|
+
console.log(`\nConstraints: ${constraintCount}, Indexes: ${indexCount}`)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** @deprecated Legacy pull helper — use {@link pgTypeToModelField}. */
|
|
39
235
|
export function pgTypeToField(col: ColumnInfo): string {
|
|
40
236
|
const opts: Record<string, unknown> = { required: !col.nullable }
|
|
41
237
|
if (col.isPrimary) opts["primaryKey"] = true
|
|
@@ -73,9 +269,7 @@ export function pgTypeToField(col: ColumnInfo): string {
|
|
|
73
269
|
return `field.text({ ...${optsStr} }) /* TODO: ${col.pgType} */`
|
|
74
270
|
}
|
|
75
271
|
|
|
76
|
-
/**
|
|
272
|
+
/** @deprecated Use {@link toModelName}. */
|
|
77
273
|
export function toCamelCase(s: string): string {
|
|
78
|
-
return s
|
|
79
|
-
.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())
|
|
80
|
-
.replace(/^([a-z])/, (c: string) => c.toUpperCase())
|
|
274
|
+
return toModelName(s)
|
|
81
275
|
}
|