@supatype/cli 0.1.0-alpha.6 → 0.1.0-alpha.7
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 +203 -1
- package/.turbo/turbo-typecheck.log +1 -1
- 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 +89 -0
- package/dist/binary-cache.d.ts.map +1 -0
- package/dist/binary-cache.js +656 -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 +12 -0
- package/dist/commands/cloud.d.ts.map +1 -1
- package/dist/commands/cloud.js +36 -46
- 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 +92 -51
- 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 +751 -384
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +20 -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 +124 -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 +99 -39
- 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 +77 -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/docker-postgres.d.ts +39 -0
- package/dist/docker-postgres.d.ts.map +1 -0
- package/dist/docker-postgres.js +96 -0
- package/dist/docker-postgres.js.map +1 -0
- package/dist/engine-client.d.ts +67 -0
- package/dist/engine-client.d.ts.map +1 -0
- package/dist/engine-client.js +156 -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 +21 -0
- package/dist/kong-config.d.ts.map +1 -0
- package/dist/kong-config.js +60 -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 +41 -0
- package/dist/process-manager.d.ts.map +1 -0
- package/dist/process-manager.js +120 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/project-config.d.ts +215 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +145 -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 +25 -0
- package/dist/runtime-routes.d.ts.map +1 -0
- package/dist/runtime-routes.js +189 -0
- package/dist/runtime-routes.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 +14 -0
- package/dist/self-host-compose.d.ts.map +1 -0
- package/dist/self-host-compose.js +236 -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/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 +31 -0
- package/dist/type-extractor.d.ts.map +1 -0
- package/dist/type-extractor.js +876 -0
- package/dist/type-extractor.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/app-config.ts +128 -0
- package/src/augmentation-generator.ts +126 -0
- package/src/binary-cache.ts +802 -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 +46 -57
- package/src/commands/db.ts +54 -63
- package/src/commands/deploy.ts +110 -61
- package/src/commands/dev.ts +930 -405
- package/src/commands/diff.ts +21 -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 +136 -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 +128 -59
- 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 +92 -0
- package/src/components.ts +6 -0
- package/src/config.ts +127 -94
- package/src/docker-postgres.ts +138 -0
- package/src/engine-client.ts +231 -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 +78 -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 +151 -0
- package/src/project-config.ts +353 -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 +216 -0
- package/src/scripts/postinstall.ts +36 -25
- package/src/self-host-compose.ts +257 -0
- package/src/storage-provision.ts +58 -0
- package/src/systemd.ts +137 -0
- package/src/tsx-runner.ts +11 -1
- package/src/type-extractor.ts +1016 -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 +140 -37
- 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/pg-spawn-env.test.ts +18 -0
- package/tests/postgres-archive-tag.test.ts +9 -0
- package/tests/pull-utils.test.ts +36 -1
- package/tests/release-pins.test.ts +28 -0
- package/tests/runtime-contract.test.ts +236 -0
- package/tests/seed-discover.test.ts +31 -0
- package/tests/tsconfig.json +9 -0
- package/tests/type-extractor.test.ts +401 -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
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release pins read from files under packages/cli/releases/.
|
|
3
|
+
* CI (deno-releases workflow) uses the same paths — bump only releases/deno/VERSION.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFileSync } from "node:fs"
|
|
7
|
+
import { dirname, join } from "node:path"
|
|
8
|
+
import { fileURLToPath } from "node:url"
|
|
9
|
+
|
|
10
|
+
const CLI_PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..")
|
|
11
|
+
|
|
12
|
+
function readPinFile(...segments: string[]): string {
|
|
13
|
+
const path = join(CLI_PACKAGE_ROOT, "releases", ...segments)
|
|
14
|
+
let raw: string
|
|
15
|
+
try {
|
|
16
|
+
raw = readFileSync(path, "utf8")
|
|
17
|
+
} catch {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Missing release pin file: ${path}\n` +
|
|
20
|
+
"Expected packages/cli/releases/… — reinstall @supatype/cli or build from the monorepo.",
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
const version = raw.trim()
|
|
24
|
+
if (!/^\d+\.\d+\.\d+/.test(version)) {
|
|
25
|
+
throw new Error(`Invalid pin in ${path}: expected semver like 2.2.0, got ${JSON.stringify(raw)}`)
|
|
26
|
+
}
|
|
27
|
+
return version
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Pinned Deno runtime for edge functions (also published to CDN under /deno/v{version}/). */
|
|
31
|
+
export const DENO_RELEASE_PIN = readPinFile("deno", "VERSION")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minisign public key for CDN release verification.
|
|
3
|
+
* Populated at publish via scripts/embed-release-pubkey.mjs (MINISIGN_PUBLIC_KEY secret),
|
|
4
|
+
* or overridden at runtime with SUPATYPE_RELEASE_PUBLIC_KEY.
|
|
5
|
+
*/
|
|
6
|
+
export const EMBEDDED_RELEASE_PUBLIC_KEY = "untrusted comment: minisign public key DE133E99689AE71D\nRWQd55pomT4T3t+5FLZZ6+h0DoHrtiuU9RBUHHm9BcFHeGRvW7BXxBCr"
|
|
7
|
+
|
|
8
|
+
export function releasePublicKey(): string {
|
|
9
|
+
const fromEnv = process.env["SUPATYPE_RELEASE_PUBLIC_KEY"]?.trim()
|
|
10
|
+
if (fromEnv) return fromEnv
|
|
11
|
+
return EMBEDDED_RELEASE_PUBLIC_KEY.trim()
|
|
12
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
export interface RuntimeRoute {
|
|
2
|
+
name: string
|
|
3
|
+
serviceName: string
|
|
4
|
+
serviceUrl: string
|
|
5
|
+
paths: string[]
|
|
6
|
+
stripPath?: boolean
|
|
7
|
+
protocols?: string[]
|
|
8
|
+
engineProtected?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RuntimeRouteOptions {
|
|
12
|
+
appUpstream?: string
|
|
13
|
+
staticAppServiceUrl?: string
|
|
14
|
+
/** Compose self-host: supatype-server container (functions proxy). */
|
|
15
|
+
functionsServiceUrl?: string
|
|
16
|
+
/**
|
|
17
|
+
* Self-host Compose: Kong forwards API traffic to supatype-server (unified gateway),
|
|
18
|
+
* which proxies to internal services — same model as `supatype dev`.
|
|
19
|
+
*/
|
|
20
|
+
unifiedGateway?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const SERVER_GATEWAY = "http://server:9999"
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Kong routes when self-host uses supatype-server as the single API gateway.
|
|
27
|
+
*/
|
|
28
|
+
function runtimeRouteSpecUnified(): RuntimeRoute[] {
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
name: "rest-v1",
|
|
32
|
+
serviceName: "supatype-server-rest",
|
|
33
|
+
serviceUrl: SERVER_GATEWAY,
|
|
34
|
+
paths: ["/rest/v1/"],
|
|
35
|
+
stripPath: false,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "auth-v1",
|
|
39
|
+
serviceName: "supatype-server-auth",
|
|
40
|
+
serviceUrl: SERVER_GATEWAY,
|
|
41
|
+
paths: ["/auth/v1/"],
|
|
42
|
+
stripPath: false,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "admin-v1",
|
|
46
|
+
serviceName: "supatype-server-admin",
|
|
47
|
+
serviceUrl: SERVER_GATEWAY,
|
|
48
|
+
paths: ["/admin/v1/"],
|
|
49
|
+
stripPath: false,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "storage-v1",
|
|
53
|
+
serviceName: "supatype-server-storage",
|
|
54
|
+
serviceUrl: SERVER_GATEWAY,
|
|
55
|
+
paths: ["/storage/v1/"],
|
|
56
|
+
stripPath: false,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "realtime-v1",
|
|
60
|
+
serviceName: "supatype-server-realtime",
|
|
61
|
+
serviceUrl: SERVER_GATEWAY,
|
|
62
|
+
paths: ["/realtime/v1/"],
|
|
63
|
+
stripPath: false,
|
|
64
|
+
protocols: ["http", "https", "ws", "wss"],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "functions-v1",
|
|
68
|
+
serviceName: "supatype-server-functions",
|
|
69
|
+
serviceUrl: SERVER_GATEWAY,
|
|
70
|
+
paths: ["/functions/v1/"],
|
|
71
|
+
stripPath: false,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "graphql-v1",
|
|
75
|
+
serviceName: "supatype-server-graphql",
|
|
76
|
+
serviceUrl: SERVER_GATEWAY,
|
|
77
|
+
paths: ["/graphql/v1/"],
|
|
78
|
+
stripPath: false,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "studio-config-route",
|
|
82
|
+
serviceName: "supatype-server-studio-config",
|
|
83
|
+
serviceUrl: SERVER_GATEWAY,
|
|
84
|
+
paths: ["/studio-config"],
|
|
85
|
+
stripPath: false,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "sql-route",
|
|
89
|
+
serviceName: "supatype-server-sql",
|
|
90
|
+
serviceUrl: SERVER_GATEWAY,
|
|
91
|
+
paths: ["/sql"],
|
|
92
|
+
stripPath: false,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "studio",
|
|
96
|
+
serviceName: "studio",
|
|
97
|
+
serviceUrl: "http://studio:3002",
|
|
98
|
+
paths: ["/studio/"],
|
|
99
|
+
stripPath: true,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "app-root",
|
|
103
|
+
serviceName: "supatype-server-app",
|
|
104
|
+
serviceUrl: SERVER_GATEWAY,
|
|
105
|
+
paths: ["/"],
|
|
106
|
+
stripPath: false,
|
|
107
|
+
},
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Legacy split-stack routes (PostgREST/storage/realtime directly from Kong).
|
|
113
|
+
* Kept for tests or explicit opt-out only — self-host uses unifiedGateway.
|
|
114
|
+
*/
|
|
115
|
+
function runtimeRouteSpecSplit(opts: RuntimeRouteOptions): RuntimeRoute[] {
|
|
116
|
+
const routes: RuntimeRoute[] = [
|
|
117
|
+
{
|
|
118
|
+
name: "rest-v1",
|
|
119
|
+
serviceName: "rest-v1",
|
|
120
|
+
serviceUrl: "http://postgrest:3000",
|
|
121
|
+
paths: ["/rest/v1/"],
|
|
122
|
+
stripPath: true,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "auth-v1",
|
|
126
|
+
serviceName: "auth-v1",
|
|
127
|
+
serviceUrl: "http://server:9999",
|
|
128
|
+
paths: ["/auth/v1/"],
|
|
129
|
+
stripPath: true,
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "admin-v1",
|
|
133
|
+
serviceName: "admin-v1",
|
|
134
|
+
serviceUrl: "http://server:9999",
|
|
135
|
+
paths: ["/admin/v1/"],
|
|
136
|
+
stripPath: false,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "storage-v1",
|
|
140
|
+
serviceName: "storage-v1",
|
|
141
|
+
serviceUrl: "http://storage:5000",
|
|
142
|
+
paths: ["/storage/v1/"],
|
|
143
|
+
stripPath: true,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "realtime-v1",
|
|
147
|
+
serviceName: "realtime-v1",
|
|
148
|
+
serviceUrl: "http://realtime:4000",
|
|
149
|
+
paths: ["/realtime/v1/"],
|
|
150
|
+
stripPath: true,
|
|
151
|
+
protocols: ["http", "https", "ws", "wss"],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "functions-v1",
|
|
155
|
+
serviceName: "functions-v1",
|
|
156
|
+
serviceUrl: opts.functionsServiceUrl?.trim() || "http://server:9999",
|
|
157
|
+
paths: ["/functions/v1/"],
|
|
158
|
+
stripPath: false,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "studio",
|
|
162
|
+
serviceName: "studio",
|
|
163
|
+
serviceUrl: "http://studio:3002",
|
|
164
|
+
paths: ["/studio/"],
|
|
165
|
+
stripPath: true,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "studio-config-route",
|
|
169
|
+
serviceName: "engine-studio-config",
|
|
170
|
+
serviceUrl: "http://engine:7500",
|
|
171
|
+
paths: ["/studio-config"],
|
|
172
|
+
engineProtected: true,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "sql-route",
|
|
176
|
+
serviceName: "engine-sql",
|
|
177
|
+
serviceUrl: "http://engine:7500",
|
|
178
|
+
paths: ["/sql"],
|
|
179
|
+
engineProtected: true,
|
|
180
|
+
},
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
const staticServiceUrl = opts.staticAppServiceUrl?.trim()
|
|
184
|
+
if (staticServiceUrl && staticServiceUrl.length > 0) {
|
|
185
|
+
routes.push({
|
|
186
|
+
name: "app-root",
|
|
187
|
+
serviceName: "app-root",
|
|
188
|
+
serviceUrl: staticServiceUrl,
|
|
189
|
+
paths: ["/"],
|
|
190
|
+
stripPath: false,
|
|
191
|
+
})
|
|
192
|
+
return routes
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (opts.appUpstream && opts.appUpstream.trim().length > 0) {
|
|
196
|
+
routes.push({
|
|
197
|
+
name: "app-root",
|
|
198
|
+
serviceName: "app-root",
|
|
199
|
+
serviceUrl: opts.appUpstream.trim(),
|
|
200
|
+
paths: ["/"],
|
|
201
|
+
stripPath: false,
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return routes
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Shared route contract used by local/self-host renderers.
|
|
210
|
+
*/
|
|
211
|
+
export function runtimeRouteSpec(opts: RuntimeRouteOptions = {}): RuntimeRoute[] {
|
|
212
|
+
if (opts.unifiedGateway) {
|
|
213
|
+
return runtimeRouteSpecUnified()
|
|
214
|
+
}
|
|
215
|
+
return runtimeRouteSpecSplit(opts)
|
|
216
|
+
}
|
|
@@ -1,40 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Postinstall script — downloads
|
|
3
|
-
* platform and caches it at ~/.supatype/engine/{version}/supatype-engine[.exe].
|
|
2
|
+
* Postinstall script — downloads component binaries on first install.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
4
|
+
* Components: supatype-engine, supatype-server, supatype-pg (Postgres), deno.
|
|
5
|
+
* Binaries are cached in ~/.supatype/cache/{component}/{version}/.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* 2. SHA256 checksum of binary (proves binary matches signed checksum)
|
|
7
|
+
* Failures are non-fatal: an installation message is printed and the user
|
|
8
|
+
* can run `supatype update` manually to retry.
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
|
-
import {
|
|
13
|
-
import { detectPlatform } from "../engine/platform.js"
|
|
14
|
-
import { hasCachedBinary } from "../engine/cache.js"
|
|
15
|
-
import { resolveEngine } from "../engine/resolve.js"
|
|
11
|
+
import { download, currentPlatform, fetchAllLatestVersions, type Component } from "../binary-cache.js"
|
|
16
12
|
|
|
17
|
-
async function main()
|
|
18
|
-
const platform =
|
|
13
|
+
async function main() {
|
|
14
|
+
const platform = currentPlatform()
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.log(
|
|
16
|
+
let versions: Record<Component, string>
|
|
17
|
+
try {
|
|
18
|
+
console.log("[supatype] Fetching latest component versions...")
|
|
19
|
+
versions = await fetchAllLatestVersions()
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error(`[supatype] Failed to fetch latest versions: ${(err as Error).message}`)
|
|
22
|
+
console.error("[supatype] Run 'supatype update' to download component binaries.")
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
console.log(
|
|
27
|
-
`[supatype] Downloading engine v${ENGINE_VERSION} for ${platform.os}-${platform.arch}...`,
|
|
28
|
-
)
|
|
26
|
+
console.log(`[supatype] Downloading component binaries for ${platform.os}/${platform.arch}...`)
|
|
29
27
|
|
|
30
|
-
const
|
|
31
|
-
|
|
28
|
+
const components = Object.entries(versions) as [Component, string][]
|
|
29
|
+
|
|
30
|
+
let anyFailed = false
|
|
31
|
+
for (const [component, version] of components) {
|
|
32
|
+
try {
|
|
33
|
+
await download(component, version, platform)
|
|
34
|
+
} catch (err) {
|
|
35
|
+
console.error(`[supatype] Failed to download ${component} v${version}: ${(err as Error).message}`)
|
|
36
|
+
anyFailed = true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (anyFailed) {
|
|
41
|
+
console.error("[supatype] Some downloads failed. Run 'supatype update' to retry.")
|
|
42
|
+
} else {
|
|
43
|
+
console.log("[supatype] All component binaries downloaded successfully.")
|
|
44
|
+
}
|
|
32
45
|
}
|
|
33
46
|
|
|
34
47
|
main().catch((err) => {
|
|
35
|
-
|
|
36
|
-
console.error(
|
|
37
|
-
|
|
38
|
-
)
|
|
39
|
-
// Don't exit(1) — let npm install succeed even if binary download fails.
|
|
48
|
+
// Non-fatal — postinstall failures should not break npm install.
|
|
49
|
+
console.error("[supatype] Postinstall failed:", err)
|
|
50
|
+
process.exit(0)
|
|
40
51
|
})
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { dirname, join, relative, resolve } from "node:path"
|
|
3
|
+
import { spawnSync } from "node:child_process"
|
|
4
|
+
import type { SupatypeProjectConfig } from "./project-config.js"
|
|
5
|
+
import { buildKongDeclarative } from "./kong-config.js"
|
|
6
|
+
|
|
7
|
+
export interface SelfHostComposePaths {
|
|
8
|
+
dir: string
|
|
9
|
+
composePath: string
|
|
10
|
+
kongPath: string
|
|
11
|
+
nginxPath: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function selfHostComposePaths(cwd: string): SelfHostComposePaths {
|
|
15
|
+
const dir = resolve(cwd, ".supatype", "self-host")
|
|
16
|
+
return {
|
|
17
|
+
dir,
|
|
18
|
+
composePath: join(dir, "docker-compose.yml"),
|
|
19
|
+
kongPath: join(dir, "kong.yml"),
|
|
20
|
+
nginxPath: join(dir, "nginx.conf"),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function appUpstreamForCompose(config: SupatypeProjectConfig): string | undefined {
|
|
25
|
+
if (config.app.mode !== "proxy") return undefined
|
|
26
|
+
const upstream = config.app.upstream?.trim()
|
|
27
|
+
return upstream && upstream.length > 0 ? upstream : undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function staticDirForCompose(config: SupatypeProjectConfig): string | undefined {
|
|
31
|
+
if (config.app.mode !== "static") return undefined
|
|
32
|
+
const dir = config.app.static_dir?.trim()
|
|
33
|
+
return dir && dir.length > 0 ? dir : "./public"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function projectMountPath(cwd: string): string {
|
|
37
|
+
const composeDir = resolve(cwd, ".supatype", "self-host")
|
|
38
|
+
let rel = relative(composeDir, resolve(cwd)).replace(/\\/g, "/")
|
|
39
|
+
if (!rel.startsWith(".") && !rel.startsWith("/")) {
|
|
40
|
+
rel = `./${rel}`
|
|
41
|
+
}
|
|
42
|
+
return rel || "../.."
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function serverAppEnvForCompose(config: SupatypeProjectConfig): string {
|
|
46
|
+
const mode = config.app.mode ?? "none"
|
|
47
|
+
const lines = [` SUPATYPE_APP_MODE: ${mode}`]
|
|
48
|
+
if (mode === "static") {
|
|
49
|
+
const dir = staticDirForCompose(config) ?? "./public"
|
|
50
|
+
lines.push(` SUPATYPE_APP_STATIC_DIR: /project/${dir.replace(/^\.\//, "")}`)
|
|
51
|
+
} else if (mode === "proxy" && config.app.upstream?.trim()) {
|
|
52
|
+
lines.push(` SUPATYPE_APP_UPSTREAM: ${config.app.upstream.trim()}`)
|
|
53
|
+
}
|
|
54
|
+
return lines.join("\n")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function renderSelfHostCompose(config: SupatypeProjectConfig, cwd: string = process.cwd()): string {
|
|
58
|
+
const projectMount = projectMountPath(cwd)
|
|
59
|
+
const appEnv = serverAppEnvForCompose(config)
|
|
60
|
+
|
|
61
|
+
return `# Generated by supatype self-host compose
|
|
62
|
+
# Kong → supatype-server (unified gateway) → internal PostgREST / storage / etc.
|
|
63
|
+
services:
|
|
64
|
+
db:
|
|
65
|
+
image: \${SUPATYPE_POSTGRES_IMAGE:-supatype/postgres:17-latest}
|
|
66
|
+
environment:
|
|
67
|
+
POSTGRES_USER: \${POSTGRES_USER:-supatype_admin}
|
|
68
|
+
POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-postgres}
|
|
69
|
+
POSTGRES_DB: \${POSTGRES_DB:-supatype}
|
|
70
|
+
ports:
|
|
71
|
+
- "5432:5432"
|
|
72
|
+
volumes:
|
|
73
|
+
- db-data:/var/lib/postgresql/data
|
|
74
|
+
healthcheck:
|
|
75
|
+
test: ["CMD-SHELL", "pg_isready -U \${POSTGRES_USER:-supatype_admin}"]
|
|
76
|
+
interval: 5s
|
|
77
|
+
timeout: 5s
|
|
78
|
+
retries: 20
|
|
79
|
+
|
|
80
|
+
postgrest:
|
|
81
|
+
image: postgrest/postgrest:v12.2.8
|
|
82
|
+
expose:
|
|
83
|
+
- "3000"
|
|
84
|
+
environment:
|
|
85
|
+
PGRST_DB_URI: postgresql://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}
|
|
86
|
+
PGRST_DB_SCHEMA: "public, supatype"
|
|
87
|
+
PGRST_DB_ANON_ROLE: anon
|
|
88
|
+
PGRST_JWT_SECRET: \${JWT_SECRET:-super-secret-jwt-token-change-in-production}
|
|
89
|
+
PGRST_DB_EXTRA_SEARCH_PATH: public,extensions
|
|
90
|
+
PGRST_DB_POOL: 3
|
|
91
|
+
depends_on:
|
|
92
|
+
db:
|
|
93
|
+
condition: service_healthy
|
|
94
|
+
|
|
95
|
+
storage:
|
|
96
|
+
image: \${SUPATYPE_STORAGE_IMAGE:-supatype/storage:latest}
|
|
97
|
+
expose:
|
|
98
|
+
- "5000"
|
|
99
|
+
environment:
|
|
100
|
+
PORT: 5000
|
|
101
|
+
DATABASE_URL: "postgresql://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}"
|
|
102
|
+
JWT_SECRET: \${JWT_SECRET:-super-secret-jwt-token-change-in-production}
|
|
103
|
+
S3_ENDPOINT: http://minio:9000
|
|
104
|
+
S3_REGION: us-east-1
|
|
105
|
+
S3_ACCESS_KEY: supatype
|
|
106
|
+
S3_SECRET_KEY: supatype-secret
|
|
107
|
+
S3_FORCE_PATH_STYLE: "true"
|
|
108
|
+
depends_on:
|
|
109
|
+
db:
|
|
110
|
+
condition: service_healthy
|
|
111
|
+
|
|
112
|
+
functions-worker:
|
|
113
|
+
image: \${SUPATYPE_FUNCTIONS_WORKER_IMAGE:-supatype/functions-worker:latest}
|
|
114
|
+
expose:
|
|
115
|
+
- "8001"
|
|
116
|
+
volumes:
|
|
117
|
+
- ${projectMount}:/project:ro
|
|
118
|
+
environment:
|
|
119
|
+
SUPATYPE_FUNCTIONS_ROOT: /project/functions
|
|
120
|
+
SUPATYPE_DENO_FUNCTIONS_DIR: /project/functions
|
|
121
|
+
PORT: "8001"
|
|
122
|
+
SUPATYPE_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
|
|
123
|
+
SUPATYPE_ANON_KEY: \${ANON_KEY:-}
|
|
124
|
+
SUPATYPE_SERVICE_ROLE_KEY: \${SERVICE_ROLE_KEY:-}
|
|
125
|
+
depends_on:
|
|
126
|
+
db:
|
|
127
|
+
condition: service_healthy
|
|
128
|
+
|
|
129
|
+
server:
|
|
130
|
+
image: \${SUPATYPE_SERVER_IMAGE:-\${SUPATYPE_AUTH_IMAGE:-supatype/server:latest}}
|
|
131
|
+
ports:
|
|
132
|
+
- "9999:9999"
|
|
133
|
+
volumes:
|
|
134
|
+
- ${projectMount}:/project:ro
|
|
135
|
+
working_dir: /project
|
|
136
|
+
environment:
|
|
137
|
+
SUPATYPE_MODE: standalone
|
|
138
|
+
SUPATYPE_MANIFEST_PATH: /project/.supatype/manifest.json
|
|
139
|
+
SUPATYPE_ADMIN_CONFIG_PATH: /project/.supatype/admin-config.json
|
|
140
|
+
SUPATYPE_API_CONFIG_PATH: /project/.supatype/api-config.json
|
|
141
|
+
SUPATYPE_POSTGREST_URL: http://postgrest:3000
|
|
142
|
+
SUPATYPE_GRAPHQL_URL: http://postgrest:3000
|
|
143
|
+
SUPATYPE_STORAGE_URL: http://storage:5000
|
|
144
|
+
SUPATYPE_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
|
|
145
|
+
SUPATYPE_ANON_KEY: \${ANON_KEY:-}
|
|
146
|
+
SUPATYPE_SERVICE_ROLE_KEY: \${SERVICE_ROLE_KEY:-}
|
|
147
|
+
SUPATYPE_SQL_DATABASE_URL: "postgresql://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}"
|
|
148
|
+
SUPATYPE_DENO_FUNCTIONS_DIR: /project/functions
|
|
149
|
+
SUPATYPE_FUNCTIONS_WORKER_URL: http://functions-worker:8001
|
|
150
|
+
${appEnv}
|
|
151
|
+
GOTRUE_API_HOST: 0.0.0.0
|
|
152
|
+
GOTRUE_API_PORT: 9999
|
|
153
|
+
API_EXTERNAL_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
|
|
154
|
+
GOTRUE_API_EXTERNAL_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
|
|
155
|
+
GOTRUE_DB_DRIVER: postgres
|
|
156
|
+
GOTRUE_DB_DATABASE_URL: "postgres://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}?search_path=auth"
|
|
157
|
+
GOTRUE_SITE_URL: \${SITE_URL:-http://localhost:3000}
|
|
158
|
+
GOTRUE_JWT_SECRET: \${JWT_SECRET:-super-secret-jwt-token-change-in-production}
|
|
159
|
+
GOTRUE_JWT_EXP: 3600
|
|
160
|
+
GOTRUE_JWT_AUD: authenticated
|
|
161
|
+
GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
|
|
162
|
+
GOTRUE_JWT_ADMIN_ROLES: service_role,supatype_admin
|
|
163
|
+
GOTRUE_MAILER_AUTOCONFIRM: \${GOTRUE_MAILER_AUTOCONFIRM:-true}
|
|
164
|
+
GOTRUE_DISABLE_SIGNUP: \${DISABLE_SIGNUP:-false}
|
|
165
|
+
depends_on:
|
|
166
|
+
db:
|
|
167
|
+
condition: service_healthy
|
|
168
|
+
postgrest:
|
|
169
|
+
condition: service_started
|
|
170
|
+
storage:
|
|
171
|
+
condition: service_started
|
|
172
|
+
functions-worker:
|
|
173
|
+
condition: service_started
|
|
174
|
+
|
|
175
|
+
minio:
|
|
176
|
+
image: minio/minio:RELEASE.2024-11-07T00-52-20Z
|
|
177
|
+
command: server /data --console-address ":9001"
|
|
178
|
+
environment:
|
|
179
|
+
MINIO_ROOT_USER: supatype
|
|
180
|
+
MINIO_ROOT_PASSWORD: supatype-secret
|
|
181
|
+
ports:
|
|
182
|
+
- "9000:9000"
|
|
183
|
+
- "9001:9001"
|
|
184
|
+
volumes:
|
|
185
|
+
- minio-data:/data
|
|
186
|
+
|
|
187
|
+
studio:
|
|
188
|
+
image: \${SUPATYPE_STUDIO_IMAGE:-supatype/studio:latest}
|
|
189
|
+
expose:
|
|
190
|
+
- "3002"
|
|
191
|
+
|
|
192
|
+
kong:
|
|
193
|
+
image: kong:3.6
|
|
194
|
+
environment:
|
|
195
|
+
KONG_DATABASE: "off"
|
|
196
|
+
KONG_DECLARATIVE_CONFIG: /etc/kong/kong.yml
|
|
197
|
+
KONG_PROXY_ACCESS_LOG: /dev/stdout
|
|
198
|
+
KONG_ADMIN_ACCESS_LOG: /dev/stdout
|
|
199
|
+
KONG_PROXY_ERROR_LOG: /dev/stderr
|
|
200
|
+
KONG_ADMIN_ERROR_LOG: /dev/stderr
|
|
201
|
+
volumes:
|
|
202
|
+
- ./kong.yml:/etc/kong/kong.yml:ro
|
|
203
|
+
ports:
|
|
204
|
+
- "18473:8000"
|
|
205
|
+
depends_on:
|
|
206
|
+
- server
|
|
207
|
+
- studio
|
|
208
|
+
|
|
209
|
+
volumes:
|
|
210
|
+
db-data:
|
|
211
|
+
minio-data:
|
|
212
|
+
`
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function ensureComposeManifest(cwd: string): void {
|
|
216
|
+
const manifestPath = join(cwd, ".supatype", "manifest.json")
|
|
217
|
+
if (existsSync(manifestPath)) return
|
|
218
|
+
mkdirSync(dirname(manifestPath), { recursive: true })
|
|
219
|
+
const manifest = {
|
|
220
|
+
schema: "public",
|
|
221
|
+
postgrest_url: "http://postgrest:3000",
|
|
222
|
+
storage_url: "http://storage:5000",
|
|
223
|
+
realtime_enabled: true,
|
|
224
|
+
functions_enabled: false,
|
|
225
|
+
}
|
|
226
|
+
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8")
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function writeSelfHostCompose(cwd: string, config: SupatypeProjectConfig): SelfHostComposePaths {
|
|
230
|
+
const paths = selfHostComposePaths(cwd)
|
|
231
|
+
mkdirSync(paths.dir, { recursive: true })
|
|
232
|
+
ensureComposeManifest(cwd)
|
|
233
|
+
writeFileSync(paths.composePath, renderSelfHostCompose(config, cwd), "utf8")
|
|
234
|
+
writeFileSync(
|
|
235
|
+
paths.kongPath,
|
|
236
|
+
buildKongDeclarative({
|
|
237
|
+
unifiedGateway: true,
|
|
238
|
+
}),
|
|
239
|
+
"utf8",
|
|
240
|
+
)
|
|
241
|
+
return paths
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function runDockerCompose(composePath: string, args: string[], projectRoot: string = process.cwd()): number {
|
|
245
|
+
const envFile = resolve(projectRoot, ".env")
|
|
246
|
+
const composeArgs = ["compose", "-f", composePath]
|
|
247
|
+
if (existsSync(envFile)) {
|
|
248
|
+
composeArgs.push("--env-file", envFile)
|
|
249
|
+
}
|
|
250
|
+
composeArgs.push(...args)
|
|
251
|
+
const result = spawnSync(
|
|
252
|
+
"docker",
|
|
253
|
+
composeArgs,
|
|
254
|
+
{ stdio: "inherit", cwd: dirname(composePath) },
|
|
255
|
+
)
|
|
256
|
+
return result.status ?? 1
|
|
257
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provision storage buckets declared in a schema AST via the storage server API.
|
|
3
|
+
*
|
|
4
|
+
* The storage server is the authority on bucket existence — going through the API
|
|
5
|
+
* ensures it creates any backing resources (directories, S3 buckets, etc.).
|
|
6
|
+
* Buckets already registered return 409 Conflict, which is treated as success.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface BucketSpec {
|
|
10
|
+
id: string
|
|
11
|
+
public: boolean
|
|
12
|
+
allowed_mime_types?: string[] | null
|
|
13
|
+
file_size_limit?: number | null
|
|
14
|
+
access_mode?: "public" | "private" | "custom"
|
|
15
|
+
s3_bucket_policy?: string | null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ensure all declared buckets exist in the storage server.
|
|
20
|
+
*
|
|
21
|
+
* @param storageApiUrl Base URL of the storage API, e.g. "http://localhost:54321/storage/v1"
|
|
22
|
+
* @param serviceRoleKey A service_role JWT for the storage server
|
|
23
|
+
* @param buckets Buckets to provision (from the resolved AST)
|
|
24
|
+
*/
|
|
25
|
+
export async function provisionBuckets(
|
|
26
|
+
storageApiUrl: string,
|
|
27
|
+
serviceRoleKey: string,
|
|
28
|
+
buckets: BucketSpec[],
|
|
29
|
+
): Promise<void> {
|
|
30
|
+
const base = storageApiUrl.replace(/\/$/, "")
|
|
31
|
+
const headers = {
|
|
32
|
+
"Authorization": `Bearer ${serviceRoleKey}`,
|
|
33
|
+
"Content-Type": "application/json",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (const bucket of buckets) {
|
|
37
|
+
const body = JSON.stringify({
|
|
38
|
+
id: bucket.id,
|
|
39
|
+
name: bucket.id,
|
|
40
|
+
public: bucket.public,
|
|
41
|
+
...(bucket.allowed_mime_types != null && { allowed_mime_types: bucket.allowed_mime_types }),
|
|
42
|
+
...(bucket.file_size_limit != null && { file_size_limit: bucket.file_size_limit }),
|
|
43
|
+
...(bucket.access_mode != null && { access_mode: bucket.access_mode }),
|
|
44
|
+
...(bucket.s3_bucket_policy != null &&
|
|
45
|
+
bucket.s3_bucket_policy !== "" && { s3_bucket_policy: bucket.s3_bucket_policy }),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const res = await fetch(`${base}/bucket`, { method: "POST", headers, body })
|
|
49
|
+
.catch(() => null)
|
|
50
|
+
|
|
51
|
+
if (res === null) continue // server not reachable — skip silently
|
|
52
|
+
if (res.status === 409) continue // already exists — fine
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
const msg = await res.text().catch(() => res.statusText)
|
|
55
|
+
console.warn(`[storage] Failed to provision bucket "${bucket.id}": ${msg}`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|