@supatype/cli 0.1.0-alpha.6 → 0.1.0-alpha.8
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 +208 -1
- package/.turbo/turbo-typecheck.log +1 -1
- 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 +53 -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/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 +94 -0
- package/dist/binary-cache.d.ts.map +1 -0
- package/dist/binary-cache.js +669 -0
- package/dist/binary-cache.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +13 -7
- package/dist/cli.js.map +1 -1
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +4 -3
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +56 -209
- package/dist/commands/app.js.map +1 -1
- 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 +20 -0
- package/dist/commands/cloud.d.ts.map +1 -1
- package/dist/commands/cloud.js +50 -52
- package/dist/commands/cloud.js.map +1 -1
- package/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +47 -54
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts +2 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +79 -52
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +11 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +759 -385
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +30 -15
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/engine.d.ts +1 -3
- package/dist/commands/engine.d.ts.map +1 -1
- package/dist/commands/engine.js +13 -85
- package/dist/commands/engine.js.map +1 -1
- package/dist/commands/functions.d.ts.map +1 -1
- package/dist/commands/functions.js +92 -105
- package/dist/commands/functions.js.map +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +22 -12
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +137 -410
- package/dist/commands/init.js.map +1 -1
- 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.map +1 -1
- package/dist/commands/migrate.js +27 -23
- package/dist/commands/migrate.js.map +1 -1
- 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/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +5 -66
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +128 -38
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/seed.d.ts +2 -0
- package/dist/commands/seed.d.ts.map +1 -1
- package/dist/commands/seed.js +44 -11
- package/dist/commands/seed.js.map +1 -1
- package/dist/commands/self-host.d.ts +7 -1
- package/dist/commands/self-host.d.ts.map +1 -1
- package/dist/commands/self-host.js +272 -758
- package/dist/commands/self-host.js.map +1 -1
- 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.map +1 -1
- package/dist/commands/status.js +4 -3
- package/dist/commands/status.js.map +1 -1
- 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 +93 -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 +10 -51
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +101 -33
- package/dist/config.js.map +1 -1
- package/dist/dev-compose.d.ts +17 -0
- package/dist/dev-compose.d.ts.map +1 -0
- package/dist/dev-compose.js +374 -0
- package/dist/dev-compose.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/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 +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- 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 +43 -0
- package/dist/process-manager.d.ts.map +1 -0
- package/dist/process-manager.js +135 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/project-config.d.ts +235 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +160 -0
- package/dist/project-config.js.map +1 -0
- package/dist/pull-utils.d.ts +15 -0
- package/dist/pull-utils.d.ts.map +1 -1
- package/dist/pull-utils.js +12 -0
- package/dist/pull-utils.js.map +1 -1
- 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/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 +5 -6
- package/dist/scripts/postinstall.d.ts.map +1 -1
- package/dist/scripts/postinstall.js +36 -20
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/self-host-compose.d.ts +22 -0
- package/dist/self-host-compose.d.ts.map +1 -0
- package/dist/self-host-compose.js +347 -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/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.map +1 -1
- package/dist/tsx-runner.js +9 -2
- package/dist/tsx-runner.js.map +1 -1
- 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 +4 -3
- package/releases/deno/VERSION +1 -0
- package/scripts/mirror-deno-release.sh +76 -0
- package/src/TYPE-RESOLUTION.md +294 -0
- package/src/app/proxy-dev-app.ts +67 -0
- package/src/app-config.ts +128 -0
- package/src/augmentation-generator.ts +126 -0
- package/src/binary-cache.ts +822 -0
- package/src/cli.ts +13 -8
- package/src/commands/admin.ts +4 -3
- package/src/commands/app.ts +67 -231
- package/src/commands/cache.ts +117 -0
- package/src/commands/cloud.ts +63 -64
- package/src/commands/db.ts +54 -63
- package/src/commands/deploy.ts +96 -62
- package/src/commands/dev.ts +933 -405
- package/src/commands/diff.ts +31 -29
- package/src/commands/engine.ts +13 -116
- package/src/commands/functions.ts +97 -115
- package/src/commands/generate.ts +23 -10
- package/src/commands/init.ts +149 -414
- package/src/commands/migrate-from-v1.ts +131 -0
- package/src/commands/migrate.ts +27 -23
- package/src/commands/pg.ts +133 -0
- package/src/commands/pull.ts +6 -85
- package/src/commands/push.ts +161 -56
- package/src/commands/seed.ts +54 -12
- package/src/commands/self-host.ts +312 -880
- package/src/commands/self-update.ts +45 -0
- package/src/commands/status.ts +4 -3
- package/src/commands/types.ts +76 -0
- package/src/commands/update.ts +109 -0
- package/src/components.ts +6 -0
- package/src/config.ts +127 -94
- package/src/dev-compose.ts +455 -0
- package/src/diff-output.ts +12 -0
- package/src/docker-postgres.ts +295 -0
- package/src/engine-client.ts +236 -0
- package/src/ensure-binary.ts +28 -0
- package/src/functions-router-gen.ts +224 -0
- package/src/index.ts +4 -12
- 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 +168 -0
- package/src/project-config.ts +386 -0
- package/src/pull-utils.ts +24 -0
- package/src/release-pins.ts +31 -0
- package/src/release-public-key.ts +12 -0
- package/src/runtime-routes.ts +291 -0
- package/src/schema-ast-v2.ts +324 -0
- package/src/scripts/postinstall.ts +36 -25
- package/src/self-host-compose.ts +389 -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/systemd.ts +137 -0
- package/src/tsx-runner.ts +11 -1
- 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 +40 -14
- package/tests/config.test.ts +171 -37
- package/tests/docker-postgres.test.ts +39 -0
- package/tests/engine-distribution.test.ts +3 -3
- package/tests/ensure-binary.test.ts +59 -0
- package/tests/init.test.ts +28 -86
- 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 +36 -1
- package/tests/release-pins.test.ts +28 -0
- package/tests/runtime-contract.test.ts +351 -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/type-extractor.test.ts +985 -0
- package/tests/type-resolver.test.ts +59 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +12 -0
- package/dist/engine/cache.d.ts +0 -37
- package/dist/engine/cache.d.ts.map +0 -1
- package/dist/engine/cache.js +0 -121
- package/dist/engine/cache.js.map +0 -1
- package/dist/engine/download.d.ts +0 -19
- package/dist/engine/download.d.ts.map +0 -1
- package/dist/engine/download.js +0 -108
- package/dist/engine/download.js.map +0 -1
- package/dist/engine/platform.d.ts +0 -24
- package/dist/engine/platform.d.ts.map +0 -1
- package/dist/engine/platform.js +0 -50
- package/dist/engine/platform.js.map +0 -1
- package/dist/engine/resolve.d.ts +0 -37
- package/dist/engine/resolve.d.ts.map +0 -1
- package/dist/engine/resolve.js +0 -133
- package/dist/engine/resolve.js.map +0 -1
- package/dist/engine/update-notify.d.ts +0 -11
- package/dist/engine/update-notify.d.ts.map +0 -1
- package/dist/engine/update-notify.js +0 -43
- package/dist/engine/update-notify.js.map +0 -1
- package/dist/engine/verify.d.ts +0 -50
- package/dist/engine/verify.d.ts.map +0 -1
- package/dist/engine/verify.js +0 -161
- package/dist/engine/verify.js.map +0 -1
- package/dist/engine-version.d.ts +0 -35
- package/dist/engine-version.d.ts.map +0 -1
- package/dist/engine-version.js +0 -35
- package/dist/engine-version.js.map +0 -1
- package/dist/engine.d.ts +0 -34
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -76
- package/dist/engine.js.map +0 -1
- package/src/engine/cache.ts +0 -135
- package/src/engine/download.ts +0 -143
- package/src/engine/platform.ts +0 -66
- package/src/engine/resolve.ts +0 -197
- package/src/engine/update-notify.ts +0 -50
- package/src/engine/verify.ts +0 -206
- package/src/engine-version.ts +0 -39
- package/src/engine.ts +0 -99
package/src/engine/resolve.ts
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Engine resolver — orchestrates binary download, verification, and caching.
|
|
3
|
-
*
|
|
4
|
-
* Resolution flow:
|
|
5
|
-
* 1. Check local cache for the pinned version
|
|
6
|
-
* 2. If cached and valid, return cached path
|
|
7
|
-
* 3. If not cached, download from CDN (with GitHub Releases fallback)
|
|
8
|
-
* 4. Verify signature + checksum
|
|
9
|
-
* 5. Cache the verified binary
|
|
10
|
-
* 6. Return the cached path
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { chmodSync, existsSync } from "node:fs"
|
|
14
|
-
import { rename, unlink, copyFile } from "node:fs/promises"
|
|
15
|
-
import { join } from "node:path"
|
|
16
|
-
import { detectPlatform, getArtifactName, getCdnUrl } from "./platform.js"
|
|
17
|
-
import { getCachedBinaryPath, hasCachedBinary, ensureCacheDir } from "./cache.js"
|
|
18
|
-
import { downloadFile, fetchJson } from "./download.js"
|
|
19
|
-
import { verifyBinary, verifyChecksumOnly } from "./verify.js"
|
|
20
|
-
import {
|
|
21
|
-
ENGINE_VERSION,
|
|
22
|
-
CDN_BASE_URL,
|
|
23
|
-
GITHUB_RELEASES_FALLBACK_URL,
|
|
24
|
-
} from "../engine-version.js"
|
|
25
|
-
|
|
26
|
-
export interface ResolveResult {
|
|
27
|
-
binaryPath: string
|
|
28
|
-
version: string
|
|
29
|
-
fromCache: boolean
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Resolve the engine binary path, downloading if necessary.
|
|
34
|
-
*/
|
|
35
|
-
export async function resolveEngine(
|
|
36
|
-
version: string = ENGINE_VERSION,
|
|
37
|
-
): Promise<ResolveResult> {
|
|
38
|
-
const platform = detectPlatform()
|
|
39
|
-
|
|
40
|
-
// Check cache first
|
|
41
|
-
if (hasCachedBinary(version, platform)) {
|
|
42
|
-
return {
|
|
43
|
-
binaryPath: getCachedBinaryPath(version, platform),
|
|
44
|
-
version,
|
|
45
|
-
fromCache: true,
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Not cached — need to download
|
|
50
|
-
const artifactName = getArtifactName(version, platform)
|
|
51
|
-
const cacheDir = ensureCacheDir(version)
|
|
52
|
-
const binaryDest = getCachedBinaryPath(version, platform)
|
|
53
|
-
const tempBinary = `${binaryDest}.tmp`
|
|
54
|
-
const checksumDest = join(cacheDir, "checksums.sha256")
|
|
55
|
-
const signatureDest = join(cacheDir, "checksums.sha256.minisig")
|
|
56
|
-
|
|
57
|
-
// Try CDN first, then GitHub Releases fallback
|
|
58
|
-
let downloaded = false
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
downloaded = await downloadFromSource(
|
|
62
|
-
CDN_BASE_URL,
|
|
63
|
-
version,
|
|
64
|
-
artifactName,
|
|
65
|
-
tempBinary,
|
|
66
|
-
checksumDest,
|
|
67
|
-
signatureDest,
|
|
68
|
-
)
|
|
69
|
-
} catch {
|
|
70
|
-
// CDN failed, try fallback
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!downloaded) {
|
|
74
|
-
try {
|
|
75
|
-
downloaded = await downloadFromSource(
|
|
76
|
-
GITHUB_RELEASES_FALLBACK_URL,
|
|
77
|
-
version,
|
|
78
|
-
artifactName,
|
|
79
|
-
tempBinary,
|
|
80
|
-
checksumDest,
|
|
81
|
-
signatureDest,
|
|
82
|
-
)
|
|
83
|
-
} catch {
|
|
84
|
-
// Fallback also failed
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (!downloaded) {
|
|
89
|
-
throw new Error(
|
|
90
|
-
"Cannot download Supatype engine. Check your internet connection.\n" +
|
|
91
|
-
"If this persists, report at https://github.com/supatype/supatype/issues",
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Verify the downloaded binary
|
|
96
|
-
if (existsSync(signatureDest)) {
|
|
97
|
-
// Full two-step verification: signature + checksum
|
|
98
|
-
await verifyBinary(tempBinary, checksumDest, signatureDest, artifactName)
|
|
99
|
-
} else {
|
|
100
|
-
// Checksum-only verification (GitHub Releases may not have .minisig)
|
|
101
|
-
await verifyChecksumOnly(tempBinary, checksumDest, artifactName)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Move verified binary to final location
|
|
105
|
-
await rename(tempBinary, binaryDest)
|
|
106
|
-
|
|
107
|
-
// Set executable permission on Unix
|
|
108
|
-
if (process.platform !== "win32") {
|
|
109
|
-
chmodSync(binaryDest, 0o755)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
binaryPath: binaryDest,
|
|
114
|
-
version,
|
|
115
|
-
fromCache: false,
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async function downloadFromSource(
|
|
120
|
-
baseUrl: string,
|
|
121
|
-
version: string,
|
|
122
|
-
artifactName: string,
|
|
123
|
-
binaryDest: string,
|
|
124
|
-
checksumDest: string,
|
|
125
|
-
signatureDest: string,
|
|
126
|
-
): Promise<boolean> {
|
|
127
|
-
const binaryUrl = getCdnUrl(baseUrl, version, artifactName)
|
|
128
|
-
const checksumUrl = getCdnUrl(baseUrl, version, "checksums.sha256")
|
|
129
|
-
const signatureUrl = getCdnUrl(baseUrl, version, "checksums.sha256.minisig")
|
|
130
|
-
|
|
131
|
-
// Download binary with progress
|
|
132
|
-
await downloadFile({
|
|
133
|
-
url: binaryUrl,
|
|
134
|
-
dest: binaryDest,
|
|
135
|
-
showProgress: true,
|
|
136
|
-
label: `Downloading Supatype engine v${version} for ${detectPlatform().os}-${detectPlatform().arch}`,
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
// Download checksum file
|
|
140
|
-
await downloadFile({
|
|
141
|
-
url: checksumUrl,
|
|
142
|
-
dest: checksumDest,
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
// Try to download signature file (may not exist for GitHub Releases)
|
|
146
|
-
try {
|
|
147
|
-
await downloadFile({
|
|
148
|
-
url: signatureUrl,
|
|
149
|
-
dest: signatureDest,
|
|
150
|
-
})
|
|
151
|
-
} catch {
|
|
152
|
-
// Signature file optional for fallback sources
|
|
153
|
-
// But for CDN, we require it — verifyBinary will enforce this
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return true
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Check for the latest engine version from CDN.
|
|
161
|
-
*/
|
|
162
|
-
export interface LatestVersionInfo {
|
|
163
|
-
version: string
|
|
164
|
-
date: string
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export async function checkLatestVersion(): Promise<LatestVersionInfo | undefined> {
|
|
168
|
-
return fetchJson<LatestVersionInfo>(`${CDN_BASE_URL}/latest.json`)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Check version compatibility.
|
|
173
|
-
* Engine and CLI must share the same major version.
|
|
174
|
-
*/
|
|
175
|
-
export function checkVersionCompatibility(
|
|
176
|
-
engineVersion: string,
|
|
177
|
-
expectedVersion: string,
|
|
178
|
-
): { compatible: boolean; message?: string } {
|
|
179
|
-
const engineMajor = parseMajor(engineVersion)
|
|
180
|
-
const expectedMajor = parseMajor(expectedVersion)
|
|
181
|
-
|
|
182
|
-
if (engineMajor !== expectedMajor) {
|
|
183
|
-
return {
|
|
184
|
-
compatible: false,
|
|
185
|
-
message:
|
|
186
|
-
`Engine version ${engineVersion} is not compatible with CLI version ${expectedVersion}.\n` +
|
|
187
|
-
`Run: npm update @supatype/cli`,
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return { compatible: true }
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function parseMajor(version: string): number {
|
|
195
|
-
const match = version.match(/^(\d+)/)
|
|
196
|
-
return match ? parseInt(match[1]!, 10) : 0
|
|
197
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Non-blocking update notification shown after CLI commands.
|
|
3
|
-
* Checks once per 24 hours. Skips in CI environments.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ENGINE_VERSION } from "../engine-version.js"
|
|
7
|
-
import {
|
|
8
|
-
shouldCheckForUpdates,
|
|
9
|
-
saveUpdateCheck,
|
|
10
|
-
getLastKnownLatestVersion,
|
|
11
|
-
} from "./cache.js"
|
|
12
|
-
import { checkLatestVersion } from "./resolve.js"
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Show an update notification if a newer engine version is available.
|
|
16
|
-
* This runs after every CLI command, but only actually checks the network
|
|
17
|
-
* once per 24 hours (throttled via ~/.supatype/update-check.json).
|
|
18
|
-
*/
|
|
19
|
-
export async function showUpdateNotification(): Promise<void> {
|
|
20
|
-
try {
|
|
21
|
-
const shouldCheck = await shouldCheckForUpdates()
|
|
22
|
-
|
|
23
|
-
if (shouldCheck) {
|
|
24
|
-
// Perform network check
|
|
25
|
-
const latest = await checkLatestVersion()
|
|
26
|
-
if (latest) {
|
|
27
|
-
await saveUpdateCheck(latest.version)
|
|
28
|
-
if (latest.version !== ENGINE_VERSION) {
|
|
29
|
-
printNotification(latest.version)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
// Use cached info from last check
|
|
34
|
-
const cachedLatest = await getLastKnownLatestVersion()
|
|
35
|
-
if (cachedLatest && cachedLatest !== ENGINE_VERSION) {
|
|
36
|
-
printNotification(cachedLatest)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
} catch {
|
|
40
|
-
// Never fail the CLI command because of update check
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function printNotification(latestVersion: string): void {
|
|
45
|
-
console.log()
|
|
46
|
-
console.log(
|
|
47
|
-
`Supatype engine v${latestVersion} is available. ` +
|
|
48
|
-
`Run: npm update @supatype/cli`,
|
|
49
|
-
)
|
|
50
|
-
}
|
package/src/engine/verify.ts
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checksum and signature verification for engine binaries.
|
|
3
|
-
*
|
|
4
|
-
* Two-step verification:
|
|
5
|
-
* 1. Verify minisign signature on checksums.sha256 file
|
|
6
|
-
* 2. Verify SHA256 hash of binary against signed checksum file
|
|
7
|
-
*
|
|
8
|
-
* Both steps MUST pass before the CLI executes the binary.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { createHash } from "node:crypto"
|
|
12
|
-
import { readFile, unlink } from "node:fs/promises"
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Embedded minisign public key.
|
|
16
|
-
*
|
|
17
|
-
* This key is used to verify the signature on the checksum file.
|
|
18
|
-
* It ensures the checksum file was produced by Supatype's CI,
|
|
19
|
-
* not by an attacker who compromised the CDN.
|
|
20
|
-
*
|
|
21
|
-
* Generated with: minisign -G
|
|
22
|
-
* The corresponding private key is stored as a GitHub Actions secret.
|
|
23
|
-
*
|
|
24
|
-
* TODO: Replace with actual public key once generated.
|
|
25
|
-
*/
|
|
26
|
-
export const MINISIGN_PUBLIC_KEY = "RWS0000000000000000000000000000000000000000000000000"
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Verify the minisign signature on a checksum file.
|
|
30
|
-
*
|
|
31
|
-
* Uses a pure-JS minisign verification (Ed25519).
|
|
32
|
-
* Returns true if the signature is valid, false otherwise.
|
|
33
|
-
*/
|
|
34
|
-
export async function verifySignature(
|
|
35
|
-
checksumPath: string,
|
|
36
|
-
signaturePath: string,
|
|
37
|
-
publicKey: string = MINISIGN_PUBLIC_KEY,
|
|
38
|
-
): Promise<boolean> {
|
|
39
|
-
// Minisign signature format:
|
|
40
|
-
// Line 1: untrusted comment
|
|
41
|
-
// Line 2: base64-encoded signature
|
|
42
|
-
// Line 3 (optional): trusted comment
|
|
43
|
-
// Line 4 (optional): base64-encoded global signature
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const sigContent = await readFile(signaturePath, "utf8")
|
|
47
|
-
const checksumContent = await readFile(checksumPath)
|
|
48
|
-
|
|
49
|
-
const sigLines = sigContent.trim().split("\n")
|
|
50
|
-
if (sigLines.length < 2) return false
|
|
51
|
-
|
|
52
|
-
// Parse the signature (line 2 is the base64-encoded signature)
|
|
53
|
-
const sigBase64 = sigLines[1]!.trim()
|
|
54
|
-
const sigBytes = Buffer.from(sigBase64, "base64")
|
|
55
|
-
|
|
56
|
-
// Minisign signature: 2 bytes algorithm + 8 bytes key ID + 64 bytes Ed25519 sig
|
|
57
|
-
if (sigBytes.length < 74) return false
|
|
58
|
-
|
|
59
|
-
const algorithm = sigBytes.subarray(0, 2)
|
|
60
|
-
const keyId = sigBytes.subarray(2, 10)
|
|
61
|
-
const signature = sigBytes.subarray(10, 74)
|
|
62
|
-
|
|
63
|
-
// Parse public key
|
|
64
|
-
const pkBytes = Buffer.from(publicKey.slice(2), "base64") // Skip "RW" prefix
|
|
65
|
-
if (pkBytes.length < 42) return false
|
|
66
|
-
|
|
67
|
-
// Public key: 2 bytes algorithm + 8 bytes key ID + 32 bytes Ed25519 pubkey
|
|
68
|
-
const pkKeyId = pkBytes.subarray(2, 10)
|
|
69
|
-
const pk = pkBytes.subarray(10, 42)
|
|
70
|
-
|
|
71
|
-
// Verify key IDs match
|
|
72
|
-
if (!keyId.equals(pkKeyId)) return false
|
|
73
|
-
|
|
74
|
-
// Verify Ed25519 signature using Node.js crypto
|
|
75
|
-
const { verify, createPublicKey } = await import("node:crypto")
|
|
76
|
-
|
|
77
|
-
const publicKeyObj = createPublicKey({
|
|
78
|
-
key: Buffer.concat([
|
|
79
|
-
// Ed25519 public key DER prefix
|
|
80
|
-
Buffer.from("302a300506032b6570032100", "hex"),
|
|
81
|
-
pk,
|
|
82
|
-
]),
|
|
83
|
-
format: "der",
|
|
84
|
-
type: "spki",
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
const isValid = verify(null, checksumContent, publicKeyObj, signature)
|
|
88
|
-
|
|
89
|
-
// If there's a trusted comment (line 3-4), verify the global signature too
|
|
90
|
-
if (sigLines.length >= 4 && isValid) {
|
|
91
|
-
const trustedComment = sigLines[2]?.replace(/^trusted comment: ?/, "") || ""
|
|
92
|
-
const globalSigBase64 = sigLines[3]!.trim()
|
|
93
|
-
const globalSig = Buffer.from(globalSigBase64, "base64")
|
|
94
|
-
|
|
95
|
-
const globalMessage = Buffer.concat([signature, Buffer.from(trustedComment)])
|
|
96
|
-
const globalValid = verify(null, globalMessage, publicKeyObj, globalSig)
|
|
97
|
-
return globalValid
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return isValid
|
|
101
|
-
} catch {
|
|
102
|
-
return false
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Verify the SHA256 checksum of a binary against a signed checksum file.
|
|
108
|
-
*
|
|
109
|
-
* The checksum file format follows sha256sum output:
|
|
110
|
-
* <hash> <filename>
|
|
111
|
-
*/
|
|
112
|
-
export async function verifyChecksum(
|
|
113
|
-
binaryPath: string,
|
|
114
|
-
checksumPath: string,
|
|
115
|
-
expectedFilename: string,
|
|
116
|
-
): Promise<boolean> {
|
|
117
|
-
const checksumContent = await readFile(checksumPath, "utf8")
|
|
118
|
-
|
|
119
|
-
// Find the line matching our filename
|
|
120
|
-
const lines = checksumContent.trim().split("\n")
|
|
121
|
-
let expectedHash: string | undefined
|
|
122
|
-
|
|
123
|
-
for (const line of lines) {
|
|
124
|
-
// Format: "<hash> <filename>" (two spaces)
|
|
125
|
-
const parts = line.trim().split(/\s+/)
|
|
126
|
-
if (parts.length >= 2 && parts[1] === expectedFilename) {
|
|
127
|
-
expectedHash = parts[0]!.toLowerCase()
|
|
128
|
-
break
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (!expectedHash) {
|
|
133
|
-
throw new Error(
|
|
134
|
-
`No checksum found for ${expectedFilename} in checksum file`,
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const binaryData = await readFile(binaryPath)
|
|
139
|
-
const actualHash = createHash("sha256").update(binaryData).digest("hex")
|
|
140
|
-
|
|
141
|
-
return actualHash === expectedHash
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Run the full two-step verification pipeline.
|
|
146
|
-
* Deletes the binary if verification fails.
|
|
147
|
-
*
|
|
148
|
-
* Step 1: Verify minisign signature on checksums.sha256
|
|
149
|
-
* Step 2: Verify SHA256 hash of binary against signed checksum
|
|
150
|
-
*/
|
|
151
|
-
export async function verifyBinary(
|
|
152
|
-
binaryPath: string,
|
|
153
|
-
checksumPath: string,
|
|
154
|
-
signaturePath: string,
|
|
155
|
-
artifactName: string,
|
|
156
|
-
): Promise<void> {
|
|
157
|
-
// Step 1: Verify signature
|
|
158
|
-
const sigValid = await verifySignature(checksumPath, signaturePath)
|
|
159
|
-
if (!sigValid) {
|
|
160
|
-
await safeDelete(binaryPath)
|
|
161
|
-
throw new Error(
|
|
162
|
-
"Engine checksum signature verification failed.\n" +
|
|
163
|
-
"The checksum file may have been tampered with.\n" +
|
|
164
|
-
"If this persists, report at https://github.com/supatype/supatype/issues",
|
|
165
|
-
)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Step 2: Verify checksum
|
|
169
|
-
const checksumValid = await verifyChecksum(binaryPath, checksumPath, artifactName)
|
|
170
|
-
if (!checksumValid) {
|
|
171
|
-
await safeDelete(binaryPath)
|
|
172
|
-
throw new Error(
|
|
173
|
-
"Engine binary checksum mismatch.\n" +
|
|
174
|
-
"This could indicate a corrupt download or a tampered binary.\n" +
|
|
175
|
-
"Try again or report at https://github.com/supatype/supatype/issues",
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Simple checksum-only verification (no signature).
|
|
182
|
-
* Used as a fallback when signature files are not available.
|
|
183
|
-
*/
|
|
184
|
-
export async function verifyChecksumOnly(
|
|
185
|
-
binaryPath: string,
|
|
186
|
-
checksumPath: string,
|
|
187
|
-
artifactName: string,
|
|
188
|
-
): Promise<void> {
|
|
189
|
-
const valid = await verifyChecksum(binaryPath, checksumPath, artifactName)
|
|
190
|
-
if (!valid) {
|
|
191
|
-
await safeDelete(binaryPath)
|
|
192
|
-
throw new Error(
|
|
193
|
-
"Engine binary checksum mismatch.\n" +
|
|
194
|
-
"This could indicate a corrupt download or a tampered binary.\n" +
|
|
195
|
-
"Try again or report at https://github.com/supatype/supatype/issues",
|
|
196
|
-
)
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async function safeDelete(path: string): Promise<void> {
|
|
201
|
-
try {
|
|
202
|
-
await unlink(path)
|
|
203
|
-
} catch {
|
|
204
|
-
// Ignore deletion errors
|
|
205
|
-
}
|
|
206
|
-
}
|
package/src/engine-version.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The engine binary version this CLI package expects.
|
|
3
|
-
* Update this whenever a new engine binary is released.
|
|
4
|
-
*
|
|
5
|
-
* The CLI always downloads and uses this exact version.
|
|
6
|
-
* Upgrading the CLI (npm update) may bump the pinned engine version.
|
|
7
|
-
* This ensures CLI and engine are always compatible.
|
|
8
|
-
*
|
|
9
|
-
* Versioning policy:
|
|
10
|
-
* 0.x.y-alpha.N — alpha
|
|
11
|
-
* 0.x.y-beta.N — beta
|
|
12
|
-
* 0.x.y — stable pre-1.0
|
|
13
|
-
* 1.0.0 — cloud launch
|
|
14
|
-
* Major bumps (1.0 → 2.0) indicate breaking changes to the schema AST format.
|
|
15
|
-
*/
|
|
16
|
-
export const ENGINE_VERSION = "0.1.0"
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Primary CDN for engine binary distribution.
|
|
20
|
-
* Hetzner Object Storage behind Cloudflare edge caching.
|
|
21
|
-
*/
|
|
22
|
-
export const CDN_BASE_URL = "https://releases.supatype.io/engine"
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Fallback: GitHub Releases on the public engine-releases repo.
|
|
26
|
-
* Used when the primary CDN is unavailable.
|
|
27
|
-
* Contains only binaries — no source code.
|
|
28
|
-
*/
|
|
29
|
-
export const ENGINE_RELEASES_REPO = "supatype/engine-releases"
|
|
30
|
-
export const GITHUB_RELEASES_FALLBACK_URL =
|
|
31
|
-
`https://github.com/${ENGINE_RELEASES_REPO}/releases/download`
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Legacy: GitHub repository for direct engine releases (before CDN).
|
|
35
|
-
* Kept for backwards compatibility with existing downloads.
|
|
36
|
-
*/
|
|
37
|
-
export const ENGINE_REPO = "supatype/schema-engine"
|
|
38
|
-
export const ENGINE_DOWNLOAD_BASE =
|
|
39
|
-
`https://github.com/${ENGINE_REPO}/releases/download/v${ENGINE_VERSION}`
|
package/src/engine.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Locates the engine binary (from cache) and provides a helper to invoke it.
|
|
3
|
-
*
|
|
4
|
-
* The engine binary is cached at ~/.supatype/engine/{version}/supatype-engine[.exe].
|
|
5
|
-
* On first use, it's automatically downloaded, verified, and cached.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { spawnSync, type SpawnSyncReturns } from "node:child_process"
|
|
9
|
-
import { ENGINE_VERSION } from "./engine-version.js"
|
|
10
|
-
import { detectPlatform } from "./engine/platform.js"
|
|
11
|
-
import { getCachedBinaryPath, hasCachedBinary } from "./engine/cache.js"
|
|
12
|
-
import { resolveEngine, checkVersionCompatibility } from "./engine/resolve.js"
|
|
13
|
-
|
|
14
|
-
export interface EngineResult {
|
|
15
|
-
stdout: string
|
|
16
|
-
stderr: string
|
|
17
|
-
exitCode: number
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Get the path to the engine binary, downloading if needed.
|
|
22
|
-
* This is the async version — use when you can await.
|
|
23
|
-
*/
|
|
24
|
-
export async function getEnginePathAsync(): Promise<string> {
|
|
25
|
-
const platform = detectPlatform()
|
|
26
|
-
|
|
27
|
-
// Fast path: binary already cached
|
|
28
|
-
if (hasCachedBinary(ENGINE_VERSION, platform)) {
|
|
29
|
-
return getCachedBinaryPath(ENGINE_VERSION, platform)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Need to download
|
|
33
|
-
const result = await resolveEngine(ENGINE_VERSION)
|
|
34
|
-
return result.binaryPath
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Get the path to the engine binary (sync).
|
|
39
|
-
* Throws if the binary is not cached — caller must ensure it's downloaded first.
|
|
40
|
-
*/
|
|
41
|
-
export function getEnginePath(): string {
|
|
42
|
-
const platform = detectPlatform()
|
|
43
|
-
const path = getCachedBinaryPath(ENGINE_VERSION, platform)
|
|
44
|
-
|
|
45
|
-
if (!hasCachedBinary(ENGINE_VERSION, platform)) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
`Supatype engine binary not found in cache.\n` +
|
|
48
|
-
`Expected: ${path}\n` +
|
|
49
|
-
`Run any supatype command to trigger automatic download,\n` +
|
|
50
|
-
`or run: npx supatype engine version`,
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return path
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Ensure the engine binary is available, downloading if necessary.
|
|
59
|
-
* Call this before invokeEngine() in command handlers.
|
|
60
|
-
*/
|
|
61
|
-
export async function ensureEngine(): Promise<string> {
|
|
62
|
-
const result = await resolveEngine(ENGINE_VERSION)
|
|
63
|
-
|
|
64
|
-
if (!result.fromCache) {
|
|
65
|
-
// Just downloaded — version is correct
|
|
66
|
-
return result.binaryPath
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Cached — check compatibility
|
|
70
|
-
const compat = checkVersionCompatibility(ENGINE_VERSION, ENGINE_VERSION)
|
|
71
|
-
if (!compat.compatible) {
|
|
72
|
-
throw new Error(compat.message)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return result.binaryPath
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Invoke the engine binary with the given arguments.
|
|
80
|
-
* Input JSON is passed via stdin.
|
|
81
|
-
*
|
|
82
|
-
* The caller must call ensureEngine() first to guarantee the binary exists.
|
|
83
|
-
*/
|
|
84
|
-
export function invokeEngine(
|
|
85
|
-
args: string[],
|
|
86
|
-
input?: string,
|
|
87
|
-
): EngineResult {
|
|
88
|
-
const enginePath = getEnginePath()
|
|
89
|
-
const result: SpawnSyncReturns<Buffer> = spawnSync(enginePath, args, {
|
|
90
|
-
input: input ? Buffer.from(input, "utf8") : undefined,
|
|
91
|
-
maxBuffer: 50 * 1024 * 1024, // 50MB
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
stdout: result.stdout?.toString("utf8") ?? "",
|
|
96
|
-
stderr: result.stderr?.toString("utf8") ?? "",
|
|
97
|
-
exitCode: result.status ?? 1,
|
|
98
|
-
}
|
|
99
|
-
}
|