@supatype/cli 0.1.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test.log +221 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/bin/dev-entry.ts +2 -0
- package/bin/supatype.js +5 -0
- package/dist/app/framework.d.ts +44 -0
- package/dist/app/framework.d.ts.map +1 -0
- package/dist/app/framework.js +200 -0
- package/dist/app/framework.js.map +1 -0
- package/dist/app/proxy-dev-app.d.ts +13 -0
- package/dist/app/proxy-dev-app.d.ts.map +1 -0
- package/dist/app/proxy-dev-app.js +54 -0
- package/dist/app/proxy-dev-app.js.map +1 -0
- package/dist/app-config.d.ts +7 -0
- package/dist/app-config.d.ts.map +1 -0
- package/dist/app-config.js +113 -0
- package/dist/app-config.js.map +1 -0
- package/dist/assets/supatype-logo-wordmark.ascii.txt +6 -0
- package/dist/augmentation-generator.d.ts +2 -0
- package/dist/augmentation-generator.d.ts.map +1 -0
- package/dist/augmentation-generator.js +111 -0
- package/dist/augmentation-generator.js.map +1 -0
- package/dist/binary-cache.d.ts +98 -0
- package/dist/binary-cache.d.ts.map +1 -0
- package/dist/binary-cache.js +687 -0
- package/dist/binary-cache.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/admin.d.ts +4 -0
- package/dist/commands/admin.d.ts.map +1 -0
- package/dist/commands/admin.js +271 -0
- package/dist/commands/admin.js.map +1 -0
- package/dist/commands/app.d.ts +3 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +82 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/cache.d.ts +6 -0
- package/dist/commands/cache.d.ts.map +1 -0
- package/dist/commands/cache.js +105 -0
- package/dist/commands/cache.js.map +1 -0
- package/dist/commands/cloud.d.ts +23 -0
- package/dist/commands/cloud.d.ts.map +1 -0
- package/dist/commands/cloud.js +254 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/db.d.ts +8 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +116 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/deploy-types.d.ts +14 -0
- package/dist/commands/deploy-types.d.ts.map +1 -0
- package/dist/commands/deploy-types.js +38 -0
- package/dist/commands/deploy-types.js.map +1 -0
- package/dist/commands/deploy.d.ts +15 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +322 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +14 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +806 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +54 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/engine.d.ts +7 -0
- package/dist/commands/engine.d.ts.map +1 -0
- package/dist/commands/engine.js +27 -0
- package/dist/commands/engine.js.map +1 -0
- package/dist/commands/functions.d.ts +3 -0
- package/dist/commands/functions.d.ts.map +1 -0
- package/dist/commands/functions.js +749 -0
- package/dist/commands/functions.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +38 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +228 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/keys.d.ts +4 -0
- package/dist/commands/keys.d.ts.map +1 -0
- package/dist/commands/keys.js +57 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/logs.d.ts +6 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +52 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/migrate-from-v1.d.ts +5 -0
- package/dist/commands/migrate-from-v1.d.ts.map +1 -0
- package/dist/commands/migrate-from-v1.js +125 -0
- package/dist/commands/migrate-from-v1.js.map +1 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +75 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/pg.d.ts +8 -0
- package/dist/commands/pg.d.ts.map +1 -0
- package/dist/commands/pg.js +102 -0
- package/dist/commands/pg.js.map +1 -0
- package/dist/commands/plugins.d.ts +3 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +431 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/pull.d.ts +3 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +12 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +3 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +179 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/seed.d.ts +5 -0
- package/dist/commands/seed.d.ts.map +1 -0
- package/dist/commands/seed.js +55 -0
- package/dist/commands/seed.js.map +1 -0
- package/dist/commands/self-host.d.ts +9 -0
- package/dist/commands/self-host.d.ts.map +1 -0
- package/dist/commands/self-host.js +310 -0
- package/dist/commands/self-host.js.map +1 -0
- package/dist/commands/self-update.d.ts +9 -0
- package/dist/commands/self-update.d.ts.map +1 -0
- package/dist/commands/self-update.js +33 -0
- package/dist/commands/self-update.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +70 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/types.d.ts +3 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +62 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +118 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/components.d.ts +5 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +3 -0
- package/dist/components.js.map +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +134 -0
- package/dist/config.js.map +1 -0
- package/dist/dev-compose.d.ts +19 -0
- package/dist/dev-compose.d.ts.map +1 -0
- package/dist/dev-compose.js +468 -0
- package/dist/dev-compose.js.map +1 -0
- package/dist/dev-log-bus.d.ts +30 -0
- package/dist/dev-log-bus.d.ts.map +1 -0
- package/dist/dev-log-bus.js +87 -0
- package/dist/dev-log-bus.js.map +1 -0
- package/dist/dev-log-filter.d.ts +10 -0
- package/dist/dev-log-filter.d.ts.map +1 -0
- package/dist/dev-log-filter.js +36 -0
- package/dist/dev-log-filter.js.map +1 -0
- package/dist/dev-logo.d.ts +12 -0
- package/dist/dev-logo.d.ts.map +1 -0
- package/dist/dev-logo.js +57 -0
- package/dist/dev-logo.js.map +1 -0
- package/dist/dev-session.d.ts +26 -0
- package/dist/dev-session.d.ts.map +1 -0
- package/dist/dev-session.js +106 -0
- package/dist/dev-session.js.map +1 -0
- package/dist/dev-shutdown.d.ts +9 -0
- package/dist/dev-shutdown.d.ts.map +1 -0
- package/dist/dev-shutdown.js +50 -0
- package/dist/dev-shutdown.js.map +1 -0
- package/dist/dev-task-colors.d.ts +14 -0
- package/dist/dev-task-colors.d.ts.map +1 -0
- package/dist/dev-task-colors.js +44 -0
- package/dist/dev-task-colors.js.map +1 -0
- package/dist/dev-tui.d.ts +24 -0
- package/dist/dev-tui.d.ts.map +1 -0
- package/dist/dev-tui.js +188 -0
- package/dist/dev-tui.js.map +1 -0
- package/dist/diff-output.d.ts +4 -0
- package/dist/diff-output.d.ts.map +1 -0
- package/dist/diff-output.js +12 -0
- package/dist/diff-output.js.map +1 -0
- package/dist/docker-postgres.d.ts +57 -0
- package/dist/docker-postgres.d.ts.map +1 -0
- package/dist/docker-postgres.js +208 -0
- package/dist/docker-postgres.js.map +1 -0
- package/dist/engine-client.d.ts +69 -0
- package/dist/engine-client.d.ts.map +1 -0
- package/dist/engine-client.js +157 -0
- package/dist/engine-client.js.map +1 -0
- package/dist/engine-push-output.d.ts +16 -0
- package/dist/engine-push-output.d.ts.map +1 -0
- package/dist/engine-push-output.js +61 -0
- package/dist/engine-push-output.js.map +1 -0
- package/dist/ensure-binary.d.ts +7 -0
- package/dist/ensure-binary.d.ts.map +1 -0
- package/dist/ensure-binary.js +17 -0
- package/dist/ensure-binary.js.map +1 -0
- package/dist/functions-router-gen.d.ts +14 -0
- package/dist/functions-router-gen.d.ts.map +1 -0
- package/dist/functions-router-gen.js +199 -0
- package/dist/functions-router-gen.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.d.ts +3 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +13 -0
- package/dist/jwt.js.map +1 -0
- package/dist/kong-config.d.ts +25 -0
- package/dist/kong-config.d.ts.map +1 -0
- package/dist/kong-config.js +71 -0
- package/dist/kong-config.js.map +1 -0
- package/dist/local-gateway.d.ts +7 -0
- package/dist/local-gateway.d.ts.map +1 -0
- package/dist/local-gateway.js +9 -0
- package/dist/local-gateway.js.map +1 -0
- package/dist/local-storage.d.ts +8 -0
- package/dist/local-storage.d.ts.map +1 -0
- package/dist/local-storage.js +14 -0
- package/dist/local-storage.js.map +1 -0
- package/dist/pgbouncer-userlist.d.ts +5 -0
- package/dist/pgbouncer-userlist.d.ts.map +1 -0
- package/dist/pgbouncer-userlist.js +14 -0
- package/dist/pgbouncer-userlist.js.map +1 -0
- package/dist/postgres-ctl.d.ts +44 -0
- package/dist/postgres-ctl.d.ts.map +1 -0
- package/dist/postgres-ctl.js +137 -0
- package/dist/postgres-ctl.js.map +1 -0
- package/dist/process-manager.d.ts +49 -0
- package/dist/process-manager.d.ts.map +1 -0
- package/dist/process-manager.js +177 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/project-config.d.ts +238 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +159 -0
- package/dist/project-config.js.map +1 -0
- package/dist/pull-utils.d.ts +31 -0
- package/dist/pull-utils.d.ts.map +1 -0
- package/dist/pull-utils.js +77 -0
- package/dist/pull-utils.js.map +1 -0
- package/dist/release-pins.d.ts +7 -0
- package/dist/release-pins.d.ts.map +1 -0
- package/dist/release-pins.js +27 -0
- package/dist/release-pins.js.map +1 -0
- package/dist/release-public-key.d.ts +8 -0
- package/dist/release-public-key.d.ts.map +1 -0
- package/dist/release-public-key.js +13 -0
- package/dist/release-public-key.js.map +1 -0
- package/dist/restore-system-relation-targets.d.ts +3 -0
- package/dist/restore-system-relation-targets.d.ts.map +1 -0
- package/dist/restore-system-relation-targets.js +45 -0
- package/dist/restore-system-relation-targets.js.map +1 -0
- package/dist/runtime-routes.d.ts +34 -0
- package/dist/runtime-routes.d.ts.map +1 -0
- package/dist/runtime-routes.js +252 -0
- package/dist/runtime-routes.js.map +1 -0
- package/dist/schema-ast-v2.d.ts +127 -0
- package/dist/schema-ast-v2.d.ts.map +1 -0
- package/dist/schema-ast-v2.js +226 -0
- package/dist/schema-ast-v2.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +11 -0
- package/dist/scripts/postinstall.d.ts.map +1 -0
- package/dist/scripts/postinstall.js +47 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/dist/seed.d.ts +8 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +32 -0
- package/dist/seed.js.map +1 -0
- package/dist/self-host-compose.d.ts +43 -0
- package/dist/self-host-compose.d.ts.map +1 -0
- package/dist/self-host-compose.js +400 -0
- package/dist/self-host-compose.js.map +1 -0
- package/dist/storage-provision.d.ts +24 -0
- package/dist/storage-provision.d.ts.map +1 -0
- package/dist/storage-provision.js +44 -0
- package/dist/storage-provision.js.map +1 -0
- package/dist/studio-admin-roles.d.ts +7 -0
- package/dist/studio-admin-roles.d.ts.map +1 -0
- package/dist/studio-admin-roles.js +14 -0
- package/dist/studio-admin-roles.js.map +1 -0
- package/dist/studio-dev-server.d.ts +22 -0
- package/dist/studio-dev-server.d.ts.map +1 -0
- package/dist/studio-dev-server.js +28 -0
- package/dist/studio-dev-server.js.map +1 -0
- package/dist/supatype-eval-1781522769253.d.mts +2 -0
- package/dist/supatype-eval-1781522769253.d.mts.map +1 -0
- package/dist/supatype-eval-1781522769253.mjs +3 -0
- package/dist/supatype-eval-1781522769253.mjs.map +1 -0
- package/dist/systemd.d.ts +26 -0
- package/dist/systemd.d.ts.map +1 -0
- package/dist/systemd.js +102 -0
- package/dist/systemd.js.map +1 -0
- package/dist/tsx-runner.d.ts +18 -0
- package/dist/tsx-runner.d.ts.map +1 -0
- package/dist/tsx-runner.js +69 -0
- package/dist/tsx-runner.js.map +1 -0
- package/dist/type-extractor.d.ts +4 -0
- package/dist/type-extractor.d.ts.map +1 -0
- package/dist/type-extractor.js +1213 -0
- package/dist/type-extractor.js.map +1 -0
- package/dist/type-resolver.d.ts +33 -0
- package/dist/type-resolver.d.ts.map +1 -0
- package/dist/type-resolver.js +338 -0
- package/dist/type-resolver.js.map +1 -0
- package/package.json +41 -0
- package/releases/deno/VERSION +1 -0
- package/scripts/mirror-deno-release.sh +76 -0
- package/src/TYPE-RESOLUTION.md +294 -0
- package/src/app/framework.ts +249 -0
- package/src/app/proxy-dev-app.ts +68 -0
- package/src/app-config.ts +128 -0
- package/src/augmentation-generator.ts +126 -0
- package/src/binary-cache.ts +845 -0
- package/src/cli.ts +63 -0
- package/src/commands/admin.ts +372 -0
- package/src/commands/app.ts +97 -0
- package/src/commands/cache.ts +117 -0
- package/src/commands/cloud.ts +325 -0
- package/src/commands/db.ts +136 -0
- package/src/commands/deploy-types.ts +49 -0
- package/src/commands/deploy.ts +400 -0
- package/src/commands/dev.ts +1009 -0
- package/src/commands/diff.ts +63 -0
- package/src/commands/engine.ts +30 -0
- package/src/commands/functions.ts +901 -0
- package/src/commands/generate.ts +44 -0
- package/src/commands/init.ts +253 -0
- package/src/commands/keys.ts +66 -0
- package/src/commands/logs.ts +58 -0
- package/src/commands/migrate-from-v1.ts +131 -0
- package/src/commands/migrate.ts +87 -0
- package/src/commands/pg.ts +133 -0
- package/src/commands/plugins.ts +508 -0
- package/src/commands/pull.ts +17 -0
- package/src/commands/push.ts +226 -0
- package/src/commands/seed.ts +68 -0
- package/src/commands/self-host.ts +364 -0
- package/src/commands/self-update.ts +45 -0
- package/src/commands/status.ts +84 -0
- package/src/commands/types.ts +76 -0
- package/src/commands/update.ts +136 -0
- package/src/components.ts +6 -0
- package/src/config.ts +223 -0
- package/src/dev-compose.ts +583 -0
- package/src/dev-log-bus.ts +101 -0
- package/src/dev-log-filter.ts +32 -0
- package/src/dev-logo.ts +62 -0
- package/src/dev-session.ts +130 -0
- package/src/dev-shutdown.ts +54 -0
- package/src/dev-task-colors.ts +47 -0
- package/src/dev-tui.ts +232 -0
- package/src/diff-output.ts +12 -0
- package/src/docker-postgres.ts +295 -0
- package/src/engine-client.ts +236 -0
- package/src/engine-push-output.ts +71 -0
- package/src/ensure-binary.ts +28 -0
- package/src/functions-router-gen.ts +224 -0
- package/src/index.ts +11 -0
- package/src/jwt.ts +14 -0
- package/src/kong-config.ts +93 -0
- package/src/local-gateway.ts +9 -0
- package/src/local-storage.ts +14 -0
- package/src/pgbouncer-userlist.ts +15 -0
- package/src/postgres-ctl.ts +171 -0
- package/src/process-manager.ts +220 -0
- package/src/project-config.ts +388 -0
- package/src/pull-utils.ts +81 -0
- package/src/release-pins.ts +31 -0
- package/src/release-public-key.ts +12 -0
- package/src/restore-system-relation-targets.ts +45 -0
- package/src/runtime-routes.ts +291 -0
- package/src/schema-ast-v2.ts +324 -0
- package/src/scripts/postinstall.ts +51 -0
- package/src/seed.ts +43 -0
- package/src/self-host-compose.ts +452 -0
- package/src/storage-provision.ts +58 -0
- package/src/studio-admin-roles.ts +16 -0
- package/src/studio-dev-server.ts +53 -0
- package/src/supatype-eval-1781522769253.mts +1 -0
- package/src/systemd.ts +137 -0
- package/src/tsx-runner.ts +89 -0
- package/src/type-extractor.ts +1479 -0
- package/src/type-resolver.ts +457 -0
- package/tests/app-command.test.ts +54 -0
- package/tests/augmentation-generator.test.ts +59 -0
- package/tests/binary-cache-cloud-overrides.test.ts +123 -0
- package/tests/cached-artifact-format.test.ts +84 -0
- package/tests/cli-help.test.ts +133 -0
- package/tests/config.test.ts +252 -0
- package/tests/dev-ui.test.ts +139 -0
- package/tests/docker-postgres.test.ts +39 -0
- package/tests/engine-distribution.test.ts +418 -0
- package/tests/engine-push-output.test.ts +67 -0
- package/tests/ensure-binary.test.ts +59 -0
- package/tests/init.test.ts +127 -0
- package/tests/keys.test.ts +160 -0
- package/tests/migrate-from-v1.test.ts +29 -0
- package/tests/normalize-admin-config.test.ts +48 -0
- package/tests/pg-spawn-env.test.ts +18 -0
- package/tests/postgres-archive-tag.test.ts +9 -0
- package/tests/proxy-dev-app.test.ts +33 -0
- package/tests/pull-utils.test.ts +150 -0
- package/tests/release-pins.test.ts +28 -0
- package/tests/runtime-contract.test.ts +370 -0
- package/tests/seed-discover.test.ts +31 -0
- package/tests/studio-admin-roles.test.ts +27 -0
- package/tests/tsconfig.json +9 -0
- package/tests/tsx-runner.test.ts +66 -0
- package/tests/type-extractor.test.ts +985 -0
- package/tests/type-resolver.test.ts +59 -0
- package/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +12 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line filters for subprocess output during `supatype dev`.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Strip ANSI SGR sequences for TUI rendering. */
|
|
6
|
+
export function stripAnsi(text: string): string {
|
|
7
|
+
return text.replace(/\x1b\[[0-9;]*m/g, "")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Drop npm/vite noise from frontend dev servers (proxy app + Studio). */
|
|
11
|
+
export function filterDevSubprocessLine(taskId: string, line: string): boolean {
|
|
12
|
+
if (taskId !== "app" && taskId !== "studio") return true
|
|
13
|
+
const trimmed = stripAnsi(line).trim()
|
|
14
|
+
if (!trimmed) return false
|
|
15
|
+
if (/^>\s+\S/.test(trimmed)) return false
|
|
16
|
+
if (trimmed.includes("Network:") && trimmed.includes("➜")) return false
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Format console.* arguments the way Node does for a single log line. */
|
|
21
|
+
export function formatConsoleArgs(args: unknown[]): string {
|
|
22
|
+
return args
|
|
23
|
+
.map((arg) => {
|
|
24
|
+
if (typeof arg === "string") return arg
|
|
25
|
+
try {
|
|
26
|
+
return JSON.stringify(arg)
|
|
27
|
+
} catch {
|
|
28
|
+
return String(arg)
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
.join(" ")
|
|
32
|
+
}
|
package/src/dev-logo.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supatype ASCII wordmark for the dev TUI header.
|
|
3
|
+
* Baked from `figlet -f slant supatype` → assets/supatype-logo-wordmark.ascii.txt
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
7
|
+
import { dirname, join } from "node:path"
|
|
8
|
+
import { fileURLToPath } from "node:url"
|
|
9
|
+
import { BOLD, RESET, taskColor } from "./dev-task-colors.js"
|
|
10
|
+
|
|
11
|
+
const EMBEDDED_LOGO_WORDMARK = [
|
|
12
|
+
" __ ",
|
|
13
|
+
" _______ ______ ____ _/ /___ ______ ___ ",
|
|
14
|
+
" / ___/ / / / __ \\/ __ `/ __/ / / / __ \\/ _ \\",
|
|
15
|
+
" (__ ) /_/ / /_/ / /_/ / /_/ /_/ / /_/ / __/",
|
|
16
|
+
"/____/\\__,_/ .___/\\__,_/\\__/\\__, / .___/\\___/ ",
|
|
17
|
+
" /_/ /____/_/ ",
|
|
18
|
+
] as const
|
|
19
|
+
|
|
20
|
+
function readLogoFile(basename: string): readonly string[] | null {
|
|
21
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
22
|
+
const candidates = [
|
|
23
|
+
join(here, "assets", basename),
|
|
24
|
+
join(here, "..", "assets", basename),
|
|
25
|
+
]
|
|
26
|
+
for (const path of candidates) {
|
|
27
|
+
if (!existsSync(path)) continue
|
|
28
|
+
const lines = readFileSync(path, "utf8")
|
|
29
|
+
.split(/\r?\n/)
|
|
30
|
+
.map((line) => (line.endsWith("\r") ? line.slice(0, -1) : line))
|
|
31
|
+
.filter((line) => line.length > 0)
|
|
32
|
+
if (lines.length > 0) return lines
|
|
33
|
+
}
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function loadWordmarkLogoLines(): readonly string[] {
|
|
38
|
+
const fromFile = readLogoFile("supatype-logo-wordmark.ascii.txt")
|
|
39
|
+
if (fromFile) return fromFile
|
|
40
|
+
return [...EMBEDDED_LOGO_WORDMARK]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Figlet slant wordmark (~46×6). */
|
|
44
|
+
export const SUPATYPE_ASCII_LOGO_WORDMARK = loadWordmarkLogoLines()
|
|
45
|
+
|
|
46
|
+
export function pickLogoLines(): readonly string[] {
|
|
47
|
+
return SUPATYPE_ASCII_LOGO_WORDMARK
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function logoRowCount(): number {
|
|
51
|
+
return pickLogoLines().length
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Return logo rows exactly as authored (spaces preserved). */
|
|
55
|
+
export function layoutLogoBlock(lines: readonly string[]): string[] {
|
|
56
|
+
return [...lines]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function colorLogoLines(lines: readonly string[]): string[] {
|
|
60
|
+
const purple = taskColor("stack")
|
|
61
|
+
return lines.map((line) => `${purple}${BOLD}${line}${RESET}`)
|
|
62
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `supatype dev` output session — TUI (default) or interleaved stream mode.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ProcessOptions } from "./process-manager.js"
|
|
6
|
+
import { filterDevSubprocessLine, formatConsoleArgs } from "./dev-log-filter.js"
|
|
7
|
+
import { DevLogBus, type DevLogLevel } from "./dev-log-bus.js"
|
|
8
|
+
import { DevTui } from "./dev-tui.js"
|
|
9
|
+
|
|
10
|
+
export type DevUiMode = "tui" | "stream"
|
|
11
|
+
|
|
12
|
+
export function resolveDevUiMode(streamFlag: boolean): DevUiMode {
|
|
13
|
+
if (streamFlag) return "stream"
|
|
14
|
+
if (!process.stdout.isTTY || !process.stdin.isTTY) return "stream"
|
|
15
|
+
return "tui"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let activeSession: DevSession | null = null
|
|
19
|
+
|
|
20
|
+
export function beginDevSession(mode: DevUiMode): DevSession {
|
|
21
|
+
activeSession?.stop()
|
|
22
|
+
activeSession = new DevSession(mode)
|
|
23
|
+
return activeSession
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Enter console capture + TUI. */
|
|
27
|
+
export function startDevSession(): void {
|
|
28
|
+
activeSession?.start()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function endDevSession(): void {
|
|
32
|
+
activeSession?.stop()
|
|
33
|
+
activeSession = null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getActiveDevSession(): DevSession | null {
|
|
37
|
+
return activeSession
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Log to a TUI task stream, or prefixed console output in stream mode. */
|
|
41
|
+
export function appendDevTaskLog(
|
|
42
|
+
taskId: string,
|
|
43
|
+
taskTitle: string,
|
|
44
|
+
line: string,
|
|
45
|
+
level: DevLogLevel = "log",
|
|
46
|
+
): void {
|
|
47
|
+
const session = getActiveDevSession()
|
|
48
|
+
if (session?.isTui()) {
|
|
49
|
+
session.bus.ensureTask(taskId, taskTitle)
|
|
50
|
+
session.bus.append(taskId, line, level)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
const prefix = taskId === "stack" ? "[supatype]" : `[${taskId}]`
|
|
54
|
+
const write = level === "warn" ? console.warn : level === "error" ? console.error : console.log
|
|
55
|
+
write(`${prefix} ${line}`)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class DevSession {
|
|
59
|
+
readonly bus = new DevLogBus()
|
|
60
|
+
readonly mode: DevUiMode
|
|
61
|
+
private tui: DevTui | null = null
|
|
62
|
+
private restoreConsole: (() => void) | null = null
|
|
63
|
+
|
|
64
|
+
constructor(mode: DevUiMode) {
|
|
65
|
+
this.mode = mode
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
isTui(): boolean {
|
|
69
|
+
return this.mode === "tui"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
start(): void {
|
|
73
|
+
if (!this.isTui()) return
|
|
74
|
+
this.restoreConsole = patchConsole(this.bus)
|
|
75
|
+
this.tui = new DevTui(this.bus)
|
|
76
|
+
this.tui.start()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
stop(): void {
|
|
80
|
+
this.tui?.stop()
|
|
81
|
+
this.tui = null
|
|
82
|
+
this.restoreConsole?.()
|
|
83
|
+
this.restoreConsole = null
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function enhanceProcessOptions(label: string, opts: ProcessOptions): ProcessOptions {
|
|
88
|
+
const session = getActiveDevSession()
|
|
89
|
+
const subprocessFilter =
|
|
90
|
+
label === "app" || label === "studio"
|
|
91
|
+
? { shouldLogLine: (line: string) => filterDevSubprocessLine(label, line) }
|
|
92
|
+
: {}
|
|
93
|
+
|
|
94
|
+
if (!session?.isTui()) {
|
|
95
|
+
return { ...opts, ...subprocessFilter }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
session.bus.ensureTask(label, label)
|
|
99
|
+
return {
|
|
100
|
+
...opts,
|
|
101
|
+
...subprocessFilter,
|
|
102
|
+
onLine: (line, stream) => {
|
|
103
|
+
session.bus.append(label, line, stream === "stderr" ? "error" : "log")
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function patchConsole(bus: DevLogBus): () => void {
|
|
109
|
+
const original = {
|
|
110
|
+
log: console.log,
|
|
111
|
+
warn: console.warn,
|
|
112
|
+
error: console.error,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log = (...args: unknown[]) => {
|
|
116
|
+
bus.append("stack", formatConsoleArgs(args), "log")
|
|
117
|
+
}
|
|
118
|
+
console.warn = (...args: unknown[]) => {
|
|
119
|
+
bus.append("stack", formatConsoleArgs(args), "warn")
|
|
120
|
+
}
|
|
121
|
+
console.error = (...args: unknown[]) => {
|
|
122
|
+
bus.append("stack", formatConsoleArgs(args), "error")
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return () => {
|
|
126
|
+
console.log = original.log
|
|
127
|
+
console.warn = original.warn
|
|
128
|
+
console.error = original.error
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graceful shutdown for `supatype dev` — single path from SIGINT and TUI Ctrl+C.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { endDevSession } from "./dev-session.js"
|
|
6
|
+
|
|
7
|
+
let shutdownWork: (() => Promise<void>) | null = null
|
|
8
|
+
let shuttingDown = false
|
|
9
|
+
let signalsRegistered = false
|
|
10
|
+
|
|
11
|
+
function onSignal(): void {
|
|
12
|
+
void runDevShutdown()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Register async teardown (stop children, compose down, etc.). Call once per dev session. */
|
|
16
|
+
export function registerDevShutdown(work: () => Promise<void>): void {
|
|
17
|
+
shutdownWork = work
|
|
18
|
+
if (signalsRegistered) return
|
|
19
|
+
signalsRegistered = true
|
|
20
|
+
process.on("SIGINT", onSignal)
|
|
21
|
+
process.on("SIGTERM", onSignal)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** TUI Ctrl+C — do not re-emit SIGINT (avoids double-fire on Windows raw mode). */
|
|
25
|
+
export function requestDevShutdown(): void {
|
|
26
|
+
void runDevShutdown()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function isDevShuttingDown(): boolean {
|
|
30
|
+
return shuttingDown
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function runDevShutdown(): Promise<void> {
|
|
34
|
+
if (shuttingDown) {
|
|
35
|
+
try {
|
|
36
|
+
endDevSession()
|
|
37
|
+
} catch {
|
|
38
|
+
// best-effort terminal restore
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write("\n")
|
|
41
|
+
process.exit(130)
|
|
42
|
+
}
|
|
43
|
+
shuttingDown = true
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
endDevSession()
|
|
47
|
+
process.stdout.write("\n")
|
|
48
|
+
await shutdownWork?.()
|
|
49
|
+
process.exit(0)
|
|
50
|
+
} catch (err) {
|
|
51
|
+
process.stderr.write(`[supatype] Shutdown failed: ${(err as Error).message}\n`)
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI colours for `supatype dev` TUI task list and log panes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const RESET = "\x1b[0m"
|
|
6
|
+
export const DIM = "\x1b[2m"
|
|
7
|
+
export const BOLD = "\x1b[1m"
|
|
8
|
+
|
|
9
|
+
/** Purple for orchestrator logs, green for Vite/app, etc. */
|
|
10
|
+
export function taskColor(taskId: string): string {
|
|
11
|
+
switch (taskId) {
|
|
12
|
+
case "stack":
|
|
13
|
+
return "\x1b[35m"
|
|
14
|
+
case "app":
|
|
15
|
+
return "\x1b[32m"
|
|
16
|
+
case "studio":
|
|
17
|
+
return "\x1b[96m"
|
|
18
|
+
case "server":
|
|
19
|
+
return "\x1b[32m"
|
|
20
|
+
case "postgrest":
|
|
21
|
+
return "\x1b[36m"
|
|
22
|
+
default:
|
|
23
|
+
return "\x1b[37m"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function levelColor(line: string): string | null {
|
|
28
|
+
if (line.startsWith("✗ ")) return "\x1b[31m"
|
|
29
|
+
if (line.startsWith("⚠ ")) return "\x1b[33m"
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Drop redundant prefix — task pane is already labelled supatype. */
|
|
34
|
+
export function normalizeStackLogLine(line: string): string {
|
|
35
|
+
return line.replace(/^\[supatype\]\s*/, "")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function colorizeLogLine(taskId: string, line: string): string {
|
|
39
|
+
const level = levelColor(line)
|
|
40
|
+
const base = level ?? taskColor(taskId)
|
|
41
|
+
return `${base}${line}${RESET}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function colorizeTaskLabel(taskId: string, label: string, focused: boolean): string {
|
|
45
|
+
const style = focused ? BOLD + taskColor(taskId) : taskColor(taskId)
|
|
46
|
+
return `${style}${label}${RESET}`
|
|
47
|
+
}
|
package/src/dev-tui.ts
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive terminal UI for `supatype dev` — task list + focused log pane.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { stripAnsi } from "./dev-log-filter.js"
|
|
6
|
+
import type { DevLogBus } from "./dev-log-bus.js"
|
|
7
|
+
import {
|
|
8
|
+
colorizeLogLine,
|
|
9
|
+
colorizeTaskLabel,
|
|
10
|
+
DIM,
|
|
11
|
+
RESET,
|
|
12
|
+
taskColor,
|
|
13
|
+
} from "./dev-task-colors.js"
|
|
14
|
+
import {
|
|
15
|
+
colorLogoLines,
|
|
16
|
+
layoutLogoBlock,
|
|
17
|
+
logoRowCount,
|
|
18
|
+
pickLogoLines,
|
|
19
|
+
} from "./dev-logo.js"
|
|
20
|
+
import { requestDevShutdown } from "./dev-shutdown.js"
|
|
21
|
+
|
|
22
|
+
const ENTER_ALT_SCREEN = "\x1b[?1049h"
|
|
23
|
+
const LEAVE_ALT_SCREEN = "\x1b[?1049l"
|
|
24
|
+
const HIDE_CURSOR = "\x1b[?25l"
|
|
25
|
+
const SHOW_CURSOR = "\x1b[?25h"
|
|
26
|
+
const CLEAR_SCREEN = "\x1b[2J\x1b[H"
|
|
27
|
+
|
|
28
|
+
const TASK_COL_WIDTH = 22
|
|
29
|
+
const MIN_WIDTH = 60
|
|
30
|
+
const MIN_HEIGHT = 14
|
|
31
|
+
|
|
32
|
+
export class DevTui {
|
|
33
|
+
private active = false
|
|
34
|
+
private scrollFromBottom = 0
|
|
35
|
+
private renderPending = false
|
|
36
|
+
private unsubscribeBus: (() => void) | null = null
|
|
37
|
+
private readonly onResize = (): void => this.scheduleRender()
|
|
38
|
+
private readonly onData = (chunk: Buffer): void => this.handleInput(chunk)
|
|
39
|
+
|
|
40
|
+
constructor(private readonly bus: DevLogBus) {}
|
|
41
|
+
|
|
42
|
+
start(): void {
|
|
43
|
+
if (this.active) return
|
|
44
|
+
this.active = true
|
|
45
|
+
this.scrollFromBottom = 0
|
|
46
|
+
|
|
47
|
+
if (process.stdin.isTTY) {
|
|
48
|
+
process.stdin.setRawMode(true)
|
|
49
|
+
process.stdin.resume()
|
|
50
|
+
process.stdin.on("data", this.onData)
|
|
51
|
+
}
|
|
52
|
+
process.stdout.on("resize", this.onResize)
|
|
53
|
+
|
|
54
|
+
process.stdout.write(ENTER_ALT_SCREEN + HIDE_CURSOR)
|
|
55
|
+
this.unsubscribeBus = this.bus.onUpdate(() => this.scheduleRender())
|
|
56
|
+
this.scheduleRender()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
stop(): void {
|
|
60
|
+
if (!this.active) return
|
|
61
|
+
this.active = false
|
|
62
|
+
|
|
63
|
+
this.unsubscribeBus?.()
|
|
64
|
+
this.unsubscribeBus = null
|
|
65
|
+
|
|
66
|
+
process.stdout.off("resize", this.onResize)
|
|
67
|
+
if (process.stdin.isTTY) {
|
|
68
|
+
process.stdin.off("data", this.onData)
|
|
69
|
+
process.stdin.setRawMode(false)
|
|
70
|
+
process.stdin.pause()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
process.stdout.write(SHOW_CURSOR + LEAVE_ALT_SCREEN)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private scheduleRender(): void {
|
|
77
|
+
if (!this.active || this.renderPending) return
|
|
78
|
+
this.renderPending = true
|
|
79
|
+
setImmediate(() => {
|
|
80
|
+
this.renderPending = false
|
|
81
|
+
if (this.active) this.render()
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private handleInput(chunk: Buffer): void {
|
|
86
|
+
const key = chunk.toString()
|
|
87
|
+
|
|
88
|
+
if (key === "\x03") {
|
|
89
|
+
requestDevShutdown()
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
switch (key) {
|
|
94
|
+
case "j":
|
|
95
|
+
case "\x1b[B":
|
|
96
|
+
this.bus.focusNext()
|
|
97
|
+
this.scrollFromBottom = 0
|
|
98
|
+
break
|
|
99
|
+
case "k":
|
|
100
|
+
case "\x1b[A":
|
|
101
|
+
this.bus.focusPrevious()
|
|
102
|
+
this.scrollFromBottom = 0
|
|
103
|
+
break
|
|
104
|
+
case "u":
|
|
105
|
+
this.scrollFromBottom = Math.min(
|
|
106
|
+
this.scrollFromBottom + 3,
|
|
107
|
+
this.maxScroll(this.bus.getFocusedTaskId()),
|
|
108
|
+
)
|
|
109
|
+
break
|
|
110
|
+
case "d":
|
|
111
|
+
this.scrollFromBottom = Math.max(this.scrollFromBottom - 3, 0)
|
|
112
|
+
break
|
|
113
|
+
case "g":
|
|
114
|
+
this.scrollFromBottom = this.maxScroll(this.bus.getFocusedTaskId())
|
|
115
|
+
break
|
|
116
|
+
case "G":
|
|
117
|
+
this.scrollFromBottom = 0
|
|
118
|
+
break
|
|
119
|
+
default:
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
this.scheduleRender()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private maxScroll(taskId: string): number {
|
|
126
|
+
const task = this.bus.getTask(taskId)
|
|
127
|
+
if (!task) return 0
|
|
128
|
+
const logHeight = this.splitPaneHeight()
|
|
129
|
+
return Math.max(0, task.lines.length - logHeight)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private chromeRowCount(): number {
|
|
133
|
+
// logo + separator + keybind hint + footer
|
|
134
|
+
return logoRowCount() + 3
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private splitPaneHeight(): number {
|
|
138
|
+
const rows = Math.max(MIN_HEIGHT, process.stdout.rows ?? 24)
|
|
139
|
+
return Math.max(4, rows - this.chromeRowCount())
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private render(): void {
|
|
143
|
+
const cols = Math.max(MIN_WIDTH, process.stdout.columns ?? 80)
|
|
144
|
+
const logWidth = cols - TASK_COL_WIDTH - 1
|
|
145
|
+
const logHeight = this.splitPaneHeight()
|
|
146
|
+
|
|
147
|
+
const lines: string[] = []
|
|
148
|
+
|
|
149
|
+
const logoPlain = layoutLogoBlock(pickLogoLines())
|
|
150
|
+
for (const colored of colorLogoLines(logoPlain)) {
|
|
151
|
+
lines.push(formatLogoRow(colored, cols))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
lines.push(`${DIM}${"─".repeat(cols)}${RESET}`)
|
|
155
|
+
lines.push(
|
|
156
|
+
`${DIM}${truncate(
|
|
157
|
+
" ↑/k ↓/j task u/d scroll g/G top/bottom Ctrl+C quit",
|
|
158
|
+
cols,
|
|
159
|
+
)}${RESET}`,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
const taskIds = this.bus.getTaskOrder()
|
|
163
|
+
const focusedId = this.bus.getFocusedTaskId()
|
|
164
|
+
|
|
165
|
+
for (let row = 0; row < logHeight; row++) {
|
|
166
|
+
let left = " ".repeat(TASK_COL_WIDTH)
|
|
167
|
+
const taskId = taskIds[row]
|
|
168
|
+
if (taskId) {
|
|
169
|
+
const task = this.bus.getTask(taskId)
|
|
170
|
+
if (task) {
|
|
171
|
+
const marker = taskId === focusedId ? "▶" : " "
|
|
172
|
+
const unread = task.unread ? " •" : " "
|
|
173
|
+
const label = truncate(`${marker} ${task.title}${unread}`, TASK_COL_WIDTH - 1)
|
|
174
|
+
left = padVisible(
|
|
175
|
+
colorizeTaskLabel(taskId, label, taskId === focusedId),
|
|
176
|
+
TASK_COL_WIDTH,
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const logLine = this.logLineAt(focusedId, row, logHeight, logWidth)
|
|
182
|
+
lines.push(left + `${DIM}│${RESET}` + logLine)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const focusedTitle = this.bus.getTask(focusedId)?.title ?? focusedId
|
|
186
|
+
lines.push(`${DIM} focused:${RESET} ${colorizeTaskLabel(focusedId, focusedTitle, true)}`)
|
|
187
|
+
|
|
188
|
+
process.stdout.write(CLEAR_SCREEN + lines.join("\n"))
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private logLineAt(taskId: string, row: number, logHeight: number, width: number): string {
|
|
192
|
+
const task = this.bus.getTask(taskId)
|
|
193
|
+
if (!task || task.lines.length === 0) {
|
|
194
|
+
return " ".repeat(width)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const total = task.lines.length
|
|
198
|
+
const end = total - this.scrollFromBottom
|
|
199
|
+
const start = Math.max(0, end - logHeight)
|
|
200
|
+
const index = start + row
|
|
201
|
+
if (index >= end || index >= total) {
|
|
202
|
+
return " ".repeat(width)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const raw = stripAnsi(task.lines[index] ?? "")
|
|
206
|
+
const clipped = truncate(raw, width)
|
|
207
|
+
return padVisible(colorizeLogLine(taskId, clipped), width)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function truncate(text: string, width: number): string {
|
|
212
|
+
if (width <= 0) return ""
|
|
213
|
+
if (text.length <= width) return text
|
|
214
|
+
if (width <= 1) return text.slice(0, width)
|
|
215
|
+
return `${text.slice(0, width - 1)}…`
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Pad to visible width (ignores ANSI sequences already stripped from input). */
|
|
219
|
+
function padVisible(text: string, width: number): string {
|
|
220
|
+
const visible = stripAnsi(text)
|
|
221
|
+
if (visible.length >= width) return text
|
|
222
|
+
return text + " ".repeat(width - visible.length)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function formatLogoRow(colored: string, cols: number): string {
|
|
226
|
+
const plain = stripAnsi(colored)
|
|
227
|
+
if (plain.length <= cols) {
|
|
228
|
+
return plain.length < cols ? `${colored}${" ".repeat(cols - plain.length)}` : colored
|
|
229
|
+
}
|
|
230
|
+
const purple = taskColor("stack")
|
|
231
|
+
return `${purple}\x1b[1m${plain.slice(0, cols)}${RESET}`
|
|
232
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DiffResult } from "./engine-client.js"
|
|
2
|
+
|
|
3
|
+
/** Print engine diff warnings before the operation list. */
|
|
4
|
+
export function printDiffWarnings(diff: DiffResult): void {
|
|
5
|
+
const warnings = diff.warnings ?? []
|
|
6
|
+
if (warnings.length === 0) return
|
|
7
|
+
console.log(`\n${warnings.length} warning(s):\n`)
|
|
8
|
+
for (const w of warnings) {
|
|
9
|
+
console.log(` [!] ${w}`)
|
|
10
|
+
}
|
|
11
|
+
console.log()
|
|
12
|
+
}
|