@geekmidas/cli 10.0.0-alpha.85 → 10.0.0-alpha.87
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/dist/{HostingerProvider-dxkwynSs.cjs → HostingerProvider-BCB1QJj1.cjs} +2 -2
- package/dist/{HostingerProvider-dxkwynSs.cjs.map → HostingerProvider-BCB1QJj1.cjs.map} +1 -1
- package/dist/{HostingerProvider-D85ayzTi.mjs → HostingerProvider-CVc3rLPB.mjs} +2 -2
- package/dist/{HostingerProvider-D85ayzTi.mjs.map → HostingerProvider-CVc3rLPB.mjs.map} +1 -1
- package/dist/{LegacyStateStore-CJ2o18nT.mjs → LegacyStateStore-B0R4LlX_.mjs} +2 -2
- package/dist/{LegacyStateStore-CJ2o18nT.mjs.map → LegacyStateStore-B0R4LlX_.mjs.map} +1 -1
- package/dist/{LegacyStateStore-xGxPwP-m.cjs → LegacyStateStore-CWG_HVC0.cjs} +7 -7
- package/dist/{LegacyStateStore-xGxPwP-m.cjs.map → LegacyStateStore-CWG_HVC0.cjs.map} +1 -1
- package/dist/{LocalStateStore-CkjFD-4b.cjs → LocalStateStore-CLwa2DpK.cjs} +8 -8
- package/dist/{LocalStateStore-CkjFD-4b.cjs.map → LocalStateStore-CLwa2DpK.cjs.map} +1 -1
- package/dist/{LocalStateStore-ByVjUIvS.mjs → LocalStateStore-Q4vXg2ua.mjs} +2 -2
- package/dist/{LocalStateStore-ByVjUIvS.mjs.map → LocalStateStore-Q4vXg2ua.mjs.map} +1 -1
- package/dist/{S3StateStore-iqMezbES.cjs → S3StateStore-Cea9_5gF.cjs} +5 -5
- package/dist/{S3StateStore-iqMezbES.cjs.map → S3StateStore-Cea9_5gF.cjs.map} +1 -1
- package/dist/{S3StateStore-kpFlGVLE.mjs → S3StateStore-CksKYKRa.mjs} +2 -2
- package/dist/{S3StateStore-kpFlGVLE.mjs.map → S3StateStore-CksKYKRa.mjs.map} +1 -1
- package/dist/{SSMStateStore-Bkz5ztfo.mjs → SSMStateStore-BszSCAS2.mjs} +2 -2
- package/dist/{SSMStateStore-Bkz5ztfo.mjs.map → SSMStateStore-BszSCAS2.mjs.map} +1 -1
- package/dist/{SSMStateStore-Z2OMVCtq.cjs → SSMStateStore-aBOTF018.cjs} +9 -9
- package/dist/{SSMStateStore-Z2OMVCtq.cjs.map → SSMStateStore-aBOTF018.cjs.map} +1 -1
- package/dist/{add-CM7RLj89.cjs → add-5MZAXybv.cjs} +8 -5
- package/dist/add-5MZAXybv.cjs.map +1 -0
- package/dist/{add-jpX7M8RB.mjs → add-D_jNqnfZ.mjs} +8 -5
- package/dist/add-D_jNqnfZ.mjs.map +1 -0
- package/dist/{bundler-lEBH8ENP.cjs → bundler-1REMhKps.cjs} +5 -5
- package/dist/{bundler-lEBH8ENP.cjs.map → bundler-1REMhKps.cjs.map} +1 -1
- package/dist/{bundler-CaAKsbcN.mjs → bundler-BMo-JP5s.mjs} +5 -5
- package/dist/{bundler-CaAKsbcN.mjs.map → bundler-BMo-JP5s.mjs.map} +1 -1
- package/dist/{cli-BV3jzbk0.mjs → cli-7edNFwGk.mjs} +5 -13
- package/dist/cli-7edNFwGk.mjs.map +1 -0
- package/dist/{cli-DQCBcNlN.cjs → cli-BL8ZHsLQ.cjs} +5 -13
- package/dist/cli-BL8ZHsLQ.cjs.map +1 -0
- package/dist/{compose-CQK6StuE.mjs → compose-DbJhRQlh.mjs} +24 -11
- package/dist/compose-DbJhRQlh.mjs.map +1 -0
- package/dist/{compose-CSR0yEJm.cjs → compose-xw86kVYi.cjs} +34 -21
- package/dist/compose-xw86kVYi.cjs.map +1 -0
- package/dist/{config-BzIfP8a-.d.cts → config-CpjsVxru.d.cts} +3 -3
- package/dist/{config-BzIfP8a-.d.cts.map → config-CpjsVxru.d.cts.map} +1 -1
- package/dist/{config-DhdzmndX.d.mts → config-DrCAyoH5.d.mts} +3 -3
- package/dist/{config-DhdzmndX.d.mts.map → config-DrCAyoH5.d.mts.map} +1 -1
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +1 -1
- package/dist/{credentials-pAtB70k3.mjs → credentials-BgJ5mS_d.mjs} +91 -181
- package/dist/credentials-BgJ5mS_d.mjs.map +1 -0
- package/dist/{credentials-BVs7mrtw.cjs → credentials-tr26-KML.cjs} +122 -188
- package/dist/credentials-tr26-KML.cjs.map +1 -0
- package/dist/deploy/public.cjs +24 -20
- package/dist/deploy/public.cjs.map +1 -1
- package/dist/deploy/public.d.cts +95 -13
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +95 -13
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +11 -10
- package/dist/deploy/public.mjs.map +1 -1
- package/dist/{deploy-BuU117CA.mjs → deploy-BTfmXd3g.mjs} +9 -9
- package/dist/deploy-BTfmXd3g.mjs.map +1 -0
- package/dist/{deploy-Bw2Mm3x3.cjs → deploy-CtbZj4zN.cjs} +13 -13
- package/dist/deploy-CtbZj4zN.cjs.map +1 -0
- package/dist/{dokploy-C81J1MVK.cjs → dokploy-TGk3oPwr.cjs} +2 -2
- package/dist/{dokploy-C81J1MVK.cjs.map → dokploy-TGk3oPwr.cjs.map} +1 -1
- package/dist/{dokploy-DWALWk7u.mjs → dokploy-r69yZaIt.mjs} +2 -2
- package/dist/{dokploy-DWALWk7u.mjs.map → dokploy-r69yZaIt.mjs.map} +1 -1
- package/dist/{encryption-DpAum8W7.mjs → encryption-C-8Tt5Hh.mjs} +3 -3
- package/dist/{encryption-DpAum8W7.mjs.map → encryption-C-8Tt5Hh.mjs.map} +1 -1
- package/dist/{encryption-B8h8Tna0.cjs → encryption-CDn7BH5O.cjs} +3 -3
- package/dist/{encryption-B8h8Tna0.cjs.map → encryption-CDn7BH5O.cjs.map} +1 -1
- package/dist/{engine-B01fjhLt.cjs → engine-Bt5k_UMq.cjs} +33 -23
- package/dist/engine-Bt5k_UMq.cjs.map +1 -0
- package/dist/{engine-BXCtEhSH.mjs → engine-jAINgiOB.mjs} +28 -18
- package/dist/engine-jAINgiOB.mjs.map +1 -0
- package/dist/{github-8B68qrLs.mjs → github-CZHAtwPT.mjs} +3 -3
- package/dist/{github-8B68qrLs.mjs.map → github-CZHAtwPT.mjs.map} +1 -1
- package/dist/{github-Cis9tYur.cjs → github-DFhuJQlp.cjs} +3 -3
- package/dist/{github-Cis9tYur.cjs.map → github-DFhuJQlp.cjs.map} +1 -1
- package/dist/{index-f77HdqN5.d.mts → index-MnUJuUlj.d.mts} +2 -2
- package/dist/{index-D1ODeM9s.d.cts.map → index-MnUJuUlj.d.mts.map} +1 -1
- package/dist/{index-D1ODeM9s.d.cts → index-elsLJTUv.d.cts} +2 -2
- package/dist/{index-f77HdqN5.d.mts.map → index-elsLJTUv.d.cts.map} +1 -1
- package/dist/index.cjs +106 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +100 -62
- package/dist/index.mjs.map +1 -1
- package/dist/local-Ciq-bTPr.mjs +224 -0
- package/dist/local-Ciq-bTPr.mjs.map +1 -0
- package/dist/local-Cq8qdgNX.cjs +241 -0
- package/dist/local-Cq8qdgNX.cjs.map +1 -0
- package/dist/{migrate-CPWn7A51.cjs → migrate-B16qgYTn.cjs} +3 -3
- package/dist/{migrate-CPWn7A51.cjs.map → migrate-B16qgYTn.cjs.map} +1 -1
- package/dist/{migrate-BBCp5blp.cjs → migrate-B1rVlwj1.cjs} +3 -3
- package/dist/{migrate-BBCp5blp.cjs.map → migrate-B1rVlwj1.cjs.map} +1 -1
- package/dist/{migrate-sDq7NApJ.mjs → migrate-Dn7nK6sh.mjs} +3 -3
- package/dist/{migrate-sDq7NApJ.mjs.map → migrate-Dn7nK6sh.mjs.map} +1 -1
- package/dist/{migrate-BeTWLSeC.mjs → migrate-ggkPVJRC.mjs} +3 -3
- package/dist/{migrate-BeTWLSeC.mjs.map → migrate-ggkPVJRC.mjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{resolve-CXbwJ_iu.mjs → resolve-BSke45k6.mjs} +4 -4
- package/dist/{resolve-CXbwJ_iu.mjs.map → resolve-BSke45k6.mjs.map} +1 -1
- package/dist/{resolve-CztIqBOI.cjs → resolve-BXeXzpmU.cjs} +4 -4
- package/dist/{resolve-CztIqBOI.cjs.map → resolve-BXeXzpmU.cjs.map} +1 -1
- package/dist/{rollback-ByyFE5lV.mjs → rollback-CEE6dse4.mjs} +6 -6
- package/dist/{rollback-ByyFE5lV.mjs.map → rollback-CEE6dse4.mjs.map} +1 -1
- package/dist/{rollback-CyIJ4xGJ.cjs → rollback-DFMiBWf0.cjs} +8 -8
- package/dist/{rollback-CyIJ4xGJ.cjs.map → rollback-DFMiBWf0.cjs.map} +1 -1
- package/dist/{runtime-CNu2C2hB.d.mts → runtime-D48ZKk8_.d.cts} +2 -2
- package/dist/{runtime-CNu2C2hB.d.mts.map → runtime-D48ZKk8_.d.cts.map} +1 -1
- package/dist/{runtime-DMLgL26v.d.cts → runtime-HabiNBtJ.d.mts} +2 -2
- package/dist/{runtime-DMLgL26v.d.cts.map → runtime-HabiNBtJ.d.mts.map} +1 -1
- package/dist/{seeds-9C5CkDon.mjs → seeds-BYdrtZsC.mjs} +1525 -53
- package/dist/seeds-BYdrtZsC.mjs.map +1 -0
- package/dist/{seeds-B_Beuv0o.cjs → seeds-CsI0A_Ef.cjs} +1628 -65
- package/dist/seeds-CsI0A_Ef.cjs.map +1 -0
- package/dist/{sniffer-DgBkaLAu.mjs → sniffer-B0EU73bj.mjs} +5 -360
- package/dist/sniffer-B0EU73bj.mjs.map +1 -0
- package/dist/{sniffer-3fA0iExx.cjs → sniffer-DJYupBeK.cjs} +4 -413
- package/dist/sniffer-DJYupBeK.cjs.map +1 -0
- package/dist/{sst-DRi3H5TB.mjs → sst-D1Qj4sIs.mjs} +3 -3
- package/dist/{sst-DRi3H5TB.mjs.map → sst-D1Qj4sIs.mjs.map} +1 -1
- package/dist/{sst-hBrKouBy.cjs → sst-DAqUoZKG.cjs} +5 -5
- package/dist/{sst-hBrKouBy.cjs.map → sst-DAqUoZKG.cjs.map} +1 -1
- package/dist/{stages-CS1sjcRb.cjs → stages-Brn3vcdy.cjs} +2 -2
- package/dist/{stages-CS1sjcRb.cjs.map → stages-Brn3vcdy.cjs.map} +1 -1
- package/dist/{stages-CSXt7N2b.mjs → stages-DoHHz6pS.mjs} +2 -2
- package/dist/{stages-CSXt7N2b.mjs.map → stages-DoHHz6pS.mjs.map} +1 -1
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{terminal-BdvrmkaC.mjs → terminal-BTbZlrFV.mjs} +2 -2
- package/dist/{terminal-BdvrmkaC.mjs.map → terminal-BTbZlrFV.mjs.map} +1 -1
- package/dist/{terminal-BL5E0xbR.cjs → terminal-COv23heb.cjs} +2 -2
- package/dist/{terminal-BL5E0xbR.cjs.map → terminal-COv23heb.cjs.map} +1 -1
- package/dist/{types-BZn-8ssD.d.mts → types-0oAyFOfR.d.cts} +48 -49
- package/dist/types-0oAyFOfR.d.cts.map +1 -0
- package/dist/{types-DiZj6hqp.d.cts → types-BZ01tZs-.d.mts} +47 -50
- package/dist/types-BZ01tZs-.d.mts.map +1 -0
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-Bic_R3tz.cjs → workspace-CT0JM3Y8.cjs} +333 -1
- package/dist/workspace-CT0JM3Y8.cjs.map +1 -0
- package/dist/{workspace-Drz4jsvy.mjs → workspace-D2CYLMCW.mjs} +250 -2
- package/dist/workspace-D2CYLMCW.mjs.map +1 -0
- package/package.json +15 -15
- package/dist/add-CM7RLj89.cjs.map +0 -1
- package/dist/add-jpX7M8RB.mjs.map +0 -1
- package/dist/cli-BV3jzbk0.mjs.map +0 -1
- package/dist/cli-DQCBcNlN.cjs.map +0 -1
- package/dist/compose-CQK6StuE.mjs.map +0 -1
- package/dist/compose-CSR0yEJm.cjs.map +0 -1
- package/dist/credentials-BVs7mrtw.cjs.map +0 -1
- package/dist/credentials-pAtB70k3.mjs.map +0 -1
- package/dist/deploy-BuU117CA.mjs.map +0 -1
- package/dist/deploy-Bw2Mm3x3.cjs.map +0 -1
- package/dist/engine-B01fjhLt.cjs.map +0 -1
- package/dist/engine-BXCtEhSH.mjs.map +0 -1
- package/dist/run-BJLIerMM.mjs +0 -133
- package/dist/run-BJLIerMM.mjs.map +0 -1
- package/dist/run-fVZ-rLnc.cjs +0 -174
- package/dist/run-fVZ-rLnc.cjs.map +0 -1
- package/dist/seeds-9C5CkDon.mjs.map +0 -1
- package/dist/seeds-B_Beuv0o.cjs.map +0 -1
- package/dist/sniffer-3fA0iExx.cjs.map +0 -1
- package/dist/sniffer-DgBkaLAu.mjs.map +0 -1
- package/dist/types-BZn-8ssD.d.mts.map +0 -1
- package/dist/types-DiZj6hqp.d.cts.map +0 -1
- package/dist/workspace-Bic_R3tz.cjs.map +0 -1
- package/dist/workspace-Drz4jsvy.mjs.map +0 -1
|
@@ -1,17 +1,32 @@
|
|
|
1
|
-
const require_run = require("./run-fVZ-rLnc.cjs");
|
|
2
|
-
const require_sandbox = require("./sandbox-CL--ZDui.cjs");
|
|
3
1
|
let node_path = require("node:path");
|
|
4
2
|
let node_fs = require("node:fs");
|
|
5
3
|
let node_fs_promises = require("node:fs/promises");
|
|
6
4
|
let node_os = require("node:os");
|
|
7
5
|
let node_child_process = require("node:child_process");
|
|
6
|
+
//#region src/home.ts
|
|
7
|
+
/**
|
|
8
|
+
* Where the CLI keeps what belongs to a person rather than a project: stage
|
|
9
|
+
* keys and stored provider credentials.
|
|
10
|
+
*
|
|
11
|
+
* `GKM_HOME` names it, so a CI job, a shared build runner or a test can give
|
|
12
|
+
* every run its own instead of reaching into whoever's home directory the
|
|
13
|
+
* process happens to have. Unset, it is `~/.gkm`, where it has always been.
|
|
14
|
+
*/
|
|
15
|
+
/** The environment variable that moves the CLI's home. */
|
|
16
|
+
const GKM_HOME_ENV = "GKM_HOME";
|
|
17
|
+
/** The CLI's home: `GKM_HOME` if set, else `~/.gkm`. */
|
|
18
|
+
function gkmHome(env = process.env) {
|
|
19
|
+
const configured = env[GKM_HOME_ENV];
|
|
20
|
+
return configured ? (0, node_path.resolve)(configured) : (0, node_path.join)((0, node_os.homedir)(), ".gkm");
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
8
23
|
//#region src/auth/credentials.ts
|
|
9
24
|
/**
|
|
10
25
|
* Get the path to the credentials directory
|
|
11
26
|
*/
|
|
12
27
|
function getCredentialsDir(options) {
|
|
13
28
|
if (options?.home) return options.home;
|
|
14
|
-
return options?.root ? (0, node_path.join)(options.root, ".gkm") :
|
|
29
|
+
return options?.root ? (0, node_path.join)(options.root, ".gkm") : gkmHome();
|
|
15
30
|
}
|
|
16
31
|
/**
|
|
17
32
|
* Get the path to the credentials file
|
|
@@ -127,190 +142,89 @@ async function getHostingerToken(options) {
|
|
|
127
142
|
return (await readCredentials(options)).hostinger?.token ?? null;
|
|
128
143
|
}
|
|
129
144
|
//#endregion
|
|
130
|
-
//#region src/
|
|
131
|
-
/**
|
|
132
|
-
* What of the host's environment a local sandbox passes on.
|
|
133
|
-
*
|
|
134
|
-
* An allowlist, not a denylist: a credential's variable has any name its
|
|
135
|
-
* owner chose (`DOKPLOY_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `MY_VAULT_TOKEN`), so
|
|
136
|
-
* the only safe default is to name what a program needs to *run* and pass
|
|
137
|
-
* nothing else.
|
|
138
|
-
*/
|
|
145
|
+
//#region src/run.ts
|
|
139
146
|
/**
|
|
140
|
-
*
|
|
141
|
-
* user's locale and reach the network through the host's proxy — and nothing
|
|
142
|
-
* that authenticates as anyone.
|
|
143
|
-
*
|
|
144
|
-
* Deliberately left out:
|
|
145
|
-
* - `NODE_OPTIONS`: it can `--require` or `--import` code into every node
|
|
146
|
-
* process, and CI often holds `--import tsx` there. A step that needs a
|
|
147
|
-
* loader passes its own.
|
|
148
|
-
* - `NODE_AUTH_TOKEN`, `NPM_TOKEN`, `npm_config_*`: registry tokens
|
|
149
|
-
* (`actions/setup-node` writes `NODE_AUTH_TOKEN`), which is why there is no
|
|
150
|
-
* `NODE_*` wildcard.
|
|
151
|
-
* - `AWS_*`, `DOCKER_*`, `DOKPLOY_*`, `GITHUB_TOKEN`, `TURBO_TOKEN`, `GKM_*`:
|
|
152
|
-
* credentials, or where the deploy keeps them.
|
|
153
|
-
* - `SHELL`, `EDITOR` and the rest of a login session: nothing here starts a
|
|
154
|
-
* shell.
|
|
147
|
+
* Start a program with an argument array, never a shell string.
|
|
155
148
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
149
|
+
* `gkm build`, `gkm docker` and `gkm deploy` pass values that come from the
|
|
150
|
+
* workspace — image refs, tags, build args, package names — to `docker` and
|
|
151
|
+
* `turbo`. Joined into a string and handed to a shell, a package named
|
|
152
|
+
* `x;curl …|sh` or a tag holding `$(…)` became part of the command line, which
|
|
153
|
+
* matters most where the CLI builds a repository it didn't write: a CI job for a
|
|
154
|
+
* fork, a shared build runner. Here every value reaches the program as one
|
|
155
|
+
* `argv` element, whatever it contains.
|
|
160
156
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"
|
|
168
|
-
"TEMP",
|
|
169
|
-
"LANG",
|
|
170
|
-
"LANGUAGE",
|
|
171
|
-
"TZ",
|
|
172
|
-
/^LC_[A-Z]+$/,
|
|
173
|
-
"TERM",
|
|
174
|
-
"COLORTERM",
|
|
175
|
-
"NO_COLOR",
|
|
176
|
-
"FORCE_COLOR",
|
|
177
|
-
"CI",
|
|
178
|
-
"NODE_ENV",
|
|
179
|
-
"NODE_EXTRA_CA_CERTS",
|
|
180
|
-
"COREPACK_HOME",
|
|
181
|
-
"PNPM_HOME",
|
|
182
|
-
"XDG_CACHE_HOME",
|
|
183
|
-
"XDG_DATA_HOME",
|
|
184
|
-
"HTTP_PROXY",
|
|
185
|
-
"HTTPS_PROXY",
|
|
186
|
-
"NO_PROXY",
|
|
187
|
-
"http_proxy",
|
|
188
|
-
"https_proxy",
|
|
189
|
-
"no_proxy",
|
|
190
|
-
"SystemRoot",
|
|
191
|
-
"SYSTEMROOT",
|
|
192
|
-
"windir",
|
|
193
|
-
"WINDIR",
|
|
194
|
-
"ComSpec",
|
|
195
|
-
"COMSPEC",
|
|
196
|
-
"PATHEXT",
|
|
197
|
-
"USERPROFILE",
|
|
198
|
-
"APPDATA",
|
|
199
|
-
"LOCALAPPDATA"
|
|
200
|
-
];
|
|
201
|
-
function allowed(name) {
|
|
202
|
-
return SANDBOX_ENV_ALLOWLIST.some((entry) => typeof entry === "string" ? entry === name : entry.test(name));
|
|
157
|
+
/** Long enough for a cold image build; short enough that a hung one ends. */
|
|
158
|
+
const DEFAULT_TIMEOUT_MS = 18e5;
|
|
159
|
+
/** How long a timed-out child has to exit on SIGTERM before it is killed. */
|
|
160
|
+
const KILL_GRACE_MS = 5e3;
|
|
161
|
+
/** The command line as a person would read it — for messages, never to run. */
|
|
162
|
+
function display(command, args) {
|
|
163
|
+
return [command, ...args].join(" ");
|
|
203
164
|
}
|
|
204
|
-
/**
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
165
|
+
/** The program ran and exited unsuccessfully; its own output said why. */
|
|
166
|
+
var CommandFailed = class extends Error {
|
|
167
|
+
command;
|
|
168
|
+
args;
|
|
169
|
+
exitCode;
|
|
170
|
+
signal;
|
|
171
|
+
constructor(command, args, exitCode, signal) {
|
|
172
|
+
super(`\`${display(command, args)}\` ${exitCode === null ? `was stopped by ${signal ?? "a signal"}` : `exited with code ${exitCode}`}. Its output above says why; run it by hand to see it again.`);
|
|
173
|
+
this.command = command;
|
|
174
|
+
this.args = args;
|
|
175
|
+
this.exitCode = exitCode;
|
|
176
|
+
this.signal = signal;
|
|
177
|
+
this.name = "CommandFailed";
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
/** The program ran past its timeout and was killed. */
|
|
181
|
+
var CommandTimedOut = class extends Error {
|
|
182
|
+
command;
|
|
183
|
+
args;
|
|
184
|
+
timeoutMs;
|
|
185
|
+
constructor(command, args, timeoutMs) {
|
|
186
|
+
super(`\`${display(command, args)}\` was still running after ${Math.round(timeoutMs / 1e3)}s and was stopped. Check what it was waiting on — a registry, the Docker daemon, a prompt — and run it again.`);
|
|
187
|
+
this.command = command;
|
|
188
|
+
this.args = args;
|
|
189
|
+
this.timeoutMs = timeoutMs;
|
|
190
|
+
this.name = "CommandTimedOut";
|
|
213
191
|
}
|
|
214
|
-
return env;
|
|
215
|
-
}
|
|
216
|
-
//#endregion
|
|
217
|
-
//#region src/sandbox/local.ts
|
|
218
|
-
/** How long a timed-out command has to exit on SIGTERM before SIGKILL. */
|
|
219
|
-
const KILL_GRACE_MS = 5e3;
|
|
220
|
-
/** Where `output` sends a child's streams. */
|
|
221
|
-
const STDIO = {
|
|
222
|
-
capture: [
|
|
223
|
-
"ignore",
|
|
224
|
-
"pipe",
|
|
225
|
-
"pipe"
|
|
226
|
-
],
|
|
227
|
-
inherit: "inherit",
|
|
228
|
-
stderr: [
|
|
229
|
-
"ignore",
|
|
230
|
-
2,
|
|
231
|
-
2
|
|
232
|
-
],
|
|
233
|
-
ignore: "ignore"
|
|
234
192
|
};
|
|
235
193
|
/**
|
|
236
|
-
*
|
|
237
|
-
* environment.
|
|
238
|
-
*
|
|
239
|
-
* What it withholds from the command: the host's environment beyond
|
|
240
|
-
* {@link SANDBOX_ENV_ALLOWLIST}, a shell, a working directory outside the
|
|
241
|
-
* project, and any time past the timeout. What it does not: the host's
|
|
242
|
-
* filesystem, which the command can read and write as the user running the
|
|
243
|
-
* deploy. So it is not `isolating`, and it is the default for projects the
|
|
244
|
-
* host already trusts — the developer's own, a team's own CI. Code nobody
|
|
245
|
-
* vetted belongs in a sandbox that is.
|
|
194
|
+
* Run `command` with `args`, resolving when it exits 0.
|
|
246
195
|
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
196
|
+
* Rejects with {@link CommandFailed} on any other exit, {@link CommandTimedOut}
|
|
197
|
+
* once `timeoutMs` passes (after the child is gone), and with the spawn error
|
|
198
|
+
* itself when the program cannot be started at all — `ENOENT` already names it.
|
|
249
199
|
*/
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
env;
|
|
254
|
-
constructor(options) {
|
|
255
|
-
this.root = (0, node_path.resolve)(options.root);
|
|
256
|
-
this.env = {
|
|
257
|
-
...allowlistedEnv(options.hostEnv ?? process.env, options.passEnv),
|
|
258
|
-
...options.home ? {
|
|
259
|
-
HOME: options.home,
|
|
260
|
-
USERPROFILE: options.home
|
|
261
|
-
} : {}
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
async exec(command, args, options) {
|
|
265
|
-
const cwd = require_sandbox.confineCwd(this.root, options.cwd);
|
|
266
|
-
require_sandbox.assertSecretNames(options.secrets);
|
|
267
|
-
options.signal?.throwIfAborted();
|
|
268
|
-
const secretsDir = await mountSecrets(options.secrets);
|
|
269
|
-
try {
|
|
270
|
-
return await spawnConfined(command, args, {
|
|
271
|
-
...options,
|
|
272
|
-
cwd,
|
|
273
|
-
env: secretsDir ? {
|
|
274
|
-
...options.env,
|
|
275
|
-
[require_sandbox.SECRETS_DIR_ENV]: secretsDir
|
|
276
|
-
} : options.env
|
|
277
|
-
});
|
|
278
|
-
} finally {
|
|
279
|
-
if (secretsDir) await (0, node_fs_promises.rm)(secretsDir, {
|
|
280
|
-
recursive: true,
|
|
281
|
-
force: true
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
};
|
|
200
|
+
async function run(command, args, options = {}) {
|
|
201
|
+
await spawnChild(command, args, options, false);
|
|
202
|
+
}
|
|
286
203
|
/**
|
|
287
|
-
*
|
|
288
|
-
*
|
|
204
|
+
* {@link run}, resolving with what the program wrote to stdout — for a value
|
|
205
|
+
* the CLI reads back, such as the digest `docker inspect` reports. stderr still
|
|
206
|
+
* reaches the terminal, so a failure explains itself the same way.
|
|
289
207
|
*/
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const dir = await (0, node_fs_promises.mkdtemp)((0, node_path.join)((0, node_os.tmpdir)(), "gkm-secrets-"));
|
|
293
|
-
for (const [name, value] of Object.entries(secrets)) await (0, node_fs_promises.writeFile)((0, node_path.join)(dir, name), value, { mode: 384 });
|
|
294
|
-
return dir;
|
|
208
|
+
function runOutput(command, args, options = {}) {
|
|
209
|
+
return spawnChild(command, args, options, true);
|
|
295
210
|
}
|
|
296
|
-
function
|
|
297
|
-
const {
|
|
298
|
-
return new Promise((
|
|
211
|
+
function spawnChild(command, args, options, capture) {
|
|
212
|
+
const { timeoutMs = DEFAULT_TIMEOUT_MS, ...spawnOptions } = options;
|
|
213
|
+
return new Promise((resolve, reject) => {
|
|
299
214
|
const child = (0, node_child_process.spawn)(command, [...args], {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
stdio:
|
|
303
|
-
|
|
304
|
-
|
|
215
|
+
stdio: "inherit",
|
|
216
|
+
...spawnOptions,
|
|
217
|
+
...capture ? { stdio: [
|
|
218
|
+
"ignore",
|
|
219
|
+
"pipe",
|
|
220
|
+
"inherit"
|
|
221
|
+
] } : {},
|
|
222
|
+
shell: false
|
|
305
223
|
});
|
|
306
224
|
let stdout = "";
|
|
307
|
-
let stderr = "";
|
|
308
225
|
child.stdout?.on("data", (chunk) => {
|
|
309
226
|
stdout += chunk.toString();
|
|
310
227
|
});
|
|
311
|
-
child.stderr?.on("data", (chunk) => {
|
|
312
|
-
stderr += chunk.toString();
|
|
313
|
-
});
|
|
314
228
|
let timedOut = false;
|
|
315
229
|
let killer;
|
|
316
230
|
const timer = setTimeout(() => {
|
|
@@ -326,18 +240,14 @@ function spawnConfined(command, args, options) {
|
|
|
326
240
|
};
|
|
327
241
|
child.on("error", (error) => {
|
|
328
242
|
settle();
|
|
329
|
-
reject(signal?.aborted ? signal.reason : error);
|
|
243
|
+
reject(spawnOptions.signal?.aborted ? spawnOptions.signal.reason : error);
|
|
330
244
|
});
|
|
331
|
-
child.on("close", (code,
|
|
245
|
+
child.on("close", (code, signal) => {
|
|
332
246
|
settle();
|
|
333
|
-
if (signal?.aborted) reject(signal.reason);
|
|
334
|
-
else if (timedOut) reject(new
|
|
335
|
-
else
|
|
336
|
-
|
|
337
|
-
signal: killedBy ?? null,
|
|
338
|
-
stdout,
|
|
339
|
-
stderr
|
|
340
|
-
});
|
|
247
|
+
if (spawnOptions.signal?.aborted) reject(spawnOptions.signal.reason);
|
|
248
|
+
else if (timedOut) reject(new CommandTimedOut(command, args, timeoutMs));
|
|
249
|
+
else if (code === 0) resolve(stdout);
|
|
250
|
+
else reject(new CommandFailed(command, args, code, signal));
|
|
341
251
|
});
|
|
342
252
|
});
|
|
343
253
|
}
|
|
@@ -446,28 +356,34 @@ function storedCredentials(options = {}) {
|
|
|
446
356
|
} };
|
|
447
357
|
}
|
|
448
358
|
//#endregion
|
|
449
|
-
Object.defineProperty(exports, "
|
|
359
|
+
Object.defineProperty(exports, "CommandFailed", {
|
|
450
360
|
enumerable: true,
|
|
451
361
|
get: function() {
|
|
452
|
-
return
|
|
362
|
+
return CommandFailed;
|
|
453
363
|
}
|
|
454
364
|
});
|
|
455
|
-
Object.defineProperty(exports, "
|
|
365
|
+
Object.defineProperty(exports, "CommandTimedOut", {
|
|
456
366
|
enumerable: true,
|
|
457
367
|
get: function() {
|
|
458
|
-
return
|
|
368
|
+
return CommandTimedOut;
|
|
459
369
|
}
|
|
460
370
|
});
|
|
461
|
-
Object.defineProperty(exports, "
|
|
371
|
+
Object.defineProperty(exports, "DEFAULT_TIMEOUT_MS", {
|
|
462
372
|
enumerable: true,
|
|
463
373
|
get: function() {
|
|
464
|
-
return
|
|
374
|
+
return DEFAULT_TIMEOUT_MS;
|
|
465
375
|
}
|
|
466
376
|
});
|
|
467
|
-
Object.defineProperty(exports, "
|
|
377
|
+
Object.defineProperty(exports, "GKM_HOME_ENV", {
|
|
468
378
|
enumerable: true,
|
|
469
379
|
get: function() {
|
|
470
|
-
return
|
|
380
|
+
return GKM_HOME_ENV;
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
Object.defineProperty(exports, "MissingCredential", {
|
|
384
|
+
enumerable: true,
|
|
385
|
+
get: function() {
|
|
386
|
+
return MissingCredential;
|
|
471
387
|
}
|
|
472
388
|
});
|
|
473
389
|
Object.defineProperty(exports, "chainCredentials", {
|
|
@@ -506,12 +422,30 @@ Object.defineProperty(exports, "getHostingerToken", {
|
|
|
506
422
|
return getHostingerToken;
|
|
507
423
|
}
|
|
508
424
|
});
|
|
425
|
+
Object.defineProperty(exports, "gkmHome", {
|
|
426
|
+
enumerable: true,
|
|
427
|
+
get: function() {
|
|
428
|
+
return gkmHome;
|
|
429
|
+
}
|
|
430
|
+
});
|
|
509
431
|
Object.defineProperty(exports, "removeDokployCredentials", {
|
|
510
432
|
enumerable: true,
|
|
511
433
|
get: function() {
|
|
512
434
|
return removeDokployCredentials;
|
|
513
435
|
}
|
|
514
436
|
});
|
|
437
|
+
Object.defineProperty(exports, "run", {
|
|
438
|
+
enumerable: true,
|
|
439
|
+
get: function() {
|
|
440
|
+
return run;
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
Object.defineProperty(exports, "runOutput", {
|
|
444
|
+
enumerable: true,
|
|
445
|
+
get: function() {
|
|
446
|
+
return runOutput;
|
|
447
|
+
}
|
|
448
|
+
});
|
|
515
449
|
Object.defineProperty(exports, "storeDokployCredentials", {
|
|
516
450
|
enumerable: true,
|
|
517
451
|
get: function() {
|
|
@@ -531,4 +465,4 @@ Object.defineProperty(exports, "storedCredentials", {
|
|
|
531
465
|
}
|
|
532
466
|
});
|
|
533
467
|
|
|
534
|
-
//# sourceMappingURL=credentials-
|
|
468
|
+
//# sourceMappingURL=credentials-tr26-KML.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-tr26-KML.cjs","names":["resolve","join","homedir","join","existsSync","readFile","writeFile","spawn"],"sources":["../src/home.ts","../src/auth/credentials.ts","../src/run.ts","../src/deploy/credentials.ts"],"sourcesContent":["/**\n * Where the CLI keeps what belongs to a person rather than a project: stage\n * keys and stored provider credentials.\n *\n * `GKM_HOME` names it, so a CI job, a shared build runner or a test can give\n * every run its own instead of reaching into whoever's home directory the\n * process happens to have. Unset, it is `~/.gkm`, where it has always been.\n */\n\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\n\n/** The environment variable that moves the CLI's home. */\nexport const GKM_HOME_ENV = 'GKM_HOME';\n\n/** The CLI's home: `GKM_HOME` if set, else `~/.gkm`. */\nexport function gkmHome(env: NodeJS.ProcessEnv = process.env): string {\n\tconst configured = env[GKM_HOME_ENV];\n\treturn configured ? resolve(configured) : join(homedir(), '.gkm');\n}\n","import { existsSync, mkdirSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { gkmHome } from '../home';\n\n/**\n * Stored credentials for various services\n */\nexport interface StoredCredentials {\n\tdokploy?: {\n\t\t/** API token */\n\t\ttoken: string;\n\t\t/** Dokploy endpoint URL */\n\t\tendpoint: string;\n\t\t/** Registry ID in Dokploy (for Docker image pulls) */\n\t\tregistryId?: string;\n\t\t/** When the credentials were stored */\n\t\tstoredAt: string;\n\t};\n\thostinger?: {\n\t\t/** API token from hpanel.hostinger.com/profile/api */\n\t\ttoken: string;\n\t\t/** When the credentials were stored */\n\t\tstoredAt: string;\n\t};\n}\n\n/**\n * Options for credential operations\n */\nexport interface CredentialOptions {\n\t/**\n\t * A directory whose `.gkm` holds the credentials. Default: the CLI's home\n\t * (`GKM_HOME`, else `~/.gkm`).\n\t */\n\troot?: string;\n\t/** The CLI's home itself, holding `credentials.json`. Wins over `root`. */\n\thome?: string;\n}\n\n/**\n * Get the path to the credentials directory\n */\nexport function getCredentialsDir(options?: CredentialOptions): string {\n\tif (options?.home) return options.home;\n\treturn options?.root ? join(options.root, '.gkm') : gkmHome();\n}\n\n/**\n * Get the path to the credentials file\n */\nexport function getCredentialsPath(options?: CredentialOptions): string {\n\treturn join(getCredentialsDir(options), 'credentials.json');\n}\n\n/**\n * Ensure the credentials directory exists\n */\nfunction ensureCredentialsDir(options?: CredentialOptions): void {\n\tconst dir = getCredentialsDir(options);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n}\n\n/**\n * Read stored credentials from disk\n */\nexport async function readCredentials(\n\toptions?: CredentialOptions,\n): Promise<StoredCredentials> {\n\tconst path = getCredentialsPath(options);\n\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\ttry {\n\t\tconst content = await readFile(path, 'utf-8');\n\t\treturn JSON.parse(content) as StoredCredentials;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Write credentials to disk\n */\nexport async function writeCredentials(\n\tcredentials: StoredCredentials,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tensureCredentialsDir(options);\n\tconst path = getCredentialsPath(options);\n\n\tawait writeFile(path, JSON.stringify(credentials, null, 2), {\n\t\tmode: 0o600, // Owner read/write only\n\t});\n}\n\n/**\n * Store Dokploy credentials\n */\nexport async function storeDokployCredentials(\n\ttoken: string,\n\tendpoint: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tcredentials.dokploy = {\n\t\ttoken,\n\t\tendpoint,\n\t\tstoredAt: new Date().toISOString(),\n\t};\n\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get stored Dokploy credentials\n */\nexport async function getDokployCredentials(\n\toptions?: CredentialOptions,\n): Promise<{\n\ttoken: string;\n\tendpoint: string;\n\tregistryId?: string;\n} | null> {\n\tconst credentials = await readCredentials(options);\n\n\t// The environment first, and each half independently.\n\t//\n\t// `getDokployToken` has always read `DOKPLOY_API_TOKEN` while this — the\n\t// function the deploy path actually calls — read only the file. So a CI job\n\t// given the token as a secret had a token and nowhere to send it, and the\n\t// only way through was committing a credentials file or running an\n\t// interactive login on the runner.\n\t//\n\t// Read separately rather than as a pair because they arrive separately: a\n\t// token is a secret and belongs in the environment, while an endpoint is\n\t// configuration and usually belongs in `deploy.dokploy.endpoint`. Requiring\n\t// both from the same place is what made either one useless alone.\n\tconst token = process.env.DOKPLOY_API_TOKEN ?? credentials.dokploy?.token;\n\tconst endpoint =\n\t\tprocess.env.DOKPLOY_ENDPOINT ?? credentials.dokploy?.endpoint;\n\n\tif (!token || !endpoint) return null;\n\n\treturn {\n\t\ttoken,\n\t\tendpoint: endpoint.replace(/\\/$/, ''),\n\t\t...(credentials.dokploy?.registryId\n\t\t\t? { registryId: credentials.dokploy.registryId }\n\t\t\t: {}),\n\t};\n}\n\n/**\n * Remove Dokploy credentials\n */\nexport async function removeDokployCredentials(\n\toptions?: CredentialOptions,\n): Promise<boolean> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\treturn false;\n\t}\n\n\tdelete credentials.dokploy;\n\tawait writeCredentials(credentials, options);\n\treturn true;\n}\n\n/**\n * Remove all stored credentials\n */\nexport async function removeAllCredentials(\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst path = getCredentialsPath(options);\n\n\tif (existsSync(path)) {\n\t\tawait unlink(path);\n\t}\n}\n\n/**\n * Get Dokploy API token, checking stored credentials first, then environment\n */\nexport async function getDokployToken(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\t// First check environment variable (takes precedence)\n\tconst envToken = process.env.DOKPLOY_API_TOKEN;\n\tif (envToken) {\n\t\treturn envToken;\n\t}\n\n\t// Then check stored credentials\n\tconst stored = await getDokployCredentials(options);\n\tif (stored) {\n\t\treturn stored.token;\n\t}\n\n\treturn null;\n}\n\n/**\n * Get Dokploy endpoint from stored credentials\n */\nexport async function getDokployEndpoint(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\tconst stored = await getDokployCredentials(options);\n\treturn stored?.endpoint ?? null;\n}\n\n/**\n * Store Dokploy registry ID\n */\nexport async function storeDokployRegistryId(\n\tregistryId: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found. Run \"gkm login --service dokploy\" first.',\n\t\t);\n\t}\n\n\tcredentials.dokploy.registryId = registryId;\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get Dokploy registry ID from stored credentials\n */\nexport async function getDokployRegistryId(\n\toptions?: CredentialOptions,\n): Promise<string | undefined> {\n\tconst stored = await getDokployCredentials(options);\n\treturn stored?.registryId ?? undefined;\n}\n\n// ============================================\n// Hostinger credentials\n// ============================================\n\n/**\n * Store Hostinger API token\n *\n * @param token - API token from hpanel.hostinger.com/profile/api\n */\nexport async function storeHostingerToken(\n\ttoken: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tcredentials.hostinger = {\n\t\ttoken,\n\t\tstoredAt: new Date().toISOString(),\n\t};\n\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get stored Hostinger API token\n *\n * Checks environment variable first (HOSTINGER_API_TOKEN),\n * then falls back to stored credentials.\n */\nexport async function getHostingerToken(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\t// First check environment variable (takes precedence)\n\tconst envToken = process.env.HOSTINGER_API_TOKEN;\n\tif (envToken) {\n\t\treturn envToken;\n\t}\n\n\t// Then check stored credentials\n\tconst credentials = await readCredentials(options);\n\treturn credentials.hostinger?.token ?? null;\n}\n\n/**\n * Remove Hostinger credentials\n */\nexport async function removeHostingerCredentials(\n\toptions?: CredentialOptions,\n): Promise<boolean> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.hostinger) {\n\t\treturn false;\n\t}\n\n\tdelete credentials.hostinger;\n\tawait writeCredentials(credentials, options);\n\treturn true;\n}\n","/**\n * Start a program with an argument array, never a shell string.\n *\n * `gkm build`, `gkm docker` and `gkm deploy` pass values that come from the\n * workspace — image refs, tags, build args, package names — to `docker` and\n * `turbo`. Joined into a string and handed to a shell, a package named\n * `x;curl …|sh` or a tag holding `$(…)` became part of the command line, which\n * matters most where the CLI builds a repository it didn't write: a CI job for a\n * fork, a shared build runner. Here every value reaches the program as one\n * `argv` element, whatever it contains.\n */\n\nimport { type SpawnOptions, spawn } from 'node:child_process';\n\n/** Long enough for a cold image build; short enough that a hung one ends. */\nexport const DEFAULT_TIMEOUT_MS = 30 * 60_000;\n\n/** How long a timed-out child has to exit on SIGTERM before it is killed. */\nconst KILL_GRACE_MS = 5_000;\n\nexport interface RunOptions {\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n\tstdio?: SpawnOptions['stdio'];\n\t/** Kill the child after this long. Defaults to {@link DEFAULT_TIMEOUT_MS}. */\n\ttimeoutMs?: number;\n\t/**\n\t * Kills the child when aborted, and rejects with the signal's reason — the\n\t * same as a stopped deploy's other calls.\n\t */\n\tsignal?: AbortSignal;\n}\n\n/** The command line as a person would read it — for messages, never to run. */\nfunction display(command: string, args: readonly string[]): string {\n\treturn [command, ...args].join(' ');\n}\n\n/** The program ran and exited unsuccessfully; its own output said why. */\nexport class CommandFailed extends Error {\n\tconstructor(\n\t\treadonly command: string,\n\t\treadonly args: readonly string[],\n\t\treadonly exitCode: number | null,\n\t\treadonly signal: NodeJS.Signals | null,\n\t) {\n\t\tsuper(\n\t\t\t`\\`${display(command, args)}\\` ${exitCode === null ? `was stopped by ${signal ?? 'a signal'}` : `exited with code ${exitCode}`}. Its output above says why; run it by hand to see it again.`,\n\t\t);\n\t\tthis.name = 'CommandFailed';\n\t}\n}\n\n/** The program ran past its timeout and was killed. */\nexport class CommandTimedOut extends Error {\n\tconstructor(\n\t\treadonly command: string,\n\t\treadonly args: readonly string[],\n\t\treadonly timeoutMs: number,\n\t) {\n\t\tsuper(\n\t\t\t`\\`${display(command, args)}\\` was still running after ${Math.round(timeoutMs / 1000)}s and was stopped. Check what it was waiting on — a registry, the Docker daemon, a prompt — and run it again.`,\n\t\t);\n\t\tthis.name = 'CommandTimedOut';\n\t}\n}\n\n/**\n * Run `command` with `args`, resolving when it exits 0.\n *\n * Rejects with {@link CommandFailed} on any other exit, {@link CommandTimedOut}\n * once `timeoutMs` passes (after the child is gone), and with the spawn error\n * itself when the program cannot be started at all — `ENOENT` already names it.\n */\nexport async function run(\n\tcommand: string,\n\targs: readonly string[],\n\toptions: RunOptions = {},\n): Promise<void> {\n\tawait spawnChild(command, args, options, false);\n}\n\n/**\n * {@link run}, resolving with what the program wrote to stdout — for a value\n * the CLI reads back, such as the digest `docker inspect` reports. stderr still\n * reaches the terminal, so a failure explains itself the same way.\n */\nexport function runOutput(\n\tcommand: string,\n\targs: readonly string[],\n\toptions: Omit<RunOptions, 'stdio'> = {},\n): Promise<string> {\n\treturn spawnChild(command, args, options, true);\n}\n\nfunction spawnChild(\n\tcommand: string,\n\targs: readonly string[],\n\toptions: RunOptions,\n\tcapture: boolean,\n): Promise<string> {\n\tconst { timeoutMs = DEFAULT_TIMEOUT_MS, ...spawnOptions } = options;\n\n\treturn new Promise<string>((resolve, reject) => {\n\t\tconst child = spawn(command, [...args], {\n\t\t\tstdio: 'inherit',\n\t\t\t...spawnOptions,\n\t\t\t...(capture ? { stdio: ['ignore', 'pipe', 'inherit'] } : {}),\n\t\t\tshell: false,\n\t\t});\n\n\t\tlet stdout = '';\n\t\tchild.stdout?.on('data', (chunk: Buffer) => {\n\t\t\tstdout += chunk.toString();\n\t\t});\n\n\t\tlet timedOut = false;\n\t\tlet killer: NodeJS.Timeout | undefined;\n\t\tconst timer = setTimeout(() => {\n\t\t\ttimedOut = true;\n\t\t\tchild.kill('SIGTERM');\n\t\t\t// A child that ignores SIGTERM would hold the deploy open forever.\n\t\t\tkiller = setTimeout(() => child.kill('SIGKILL'), KILL_GRACE_MS);\n\t\t\tkiller.unref?.();\n\t\t}, timeoutMs);\n\t\ttimer.unref?.();\n\n\t\tconst settle = () => {\n\t\t\tclearTimeout(timer);\n\t\t\tif (killer) clearTimeout(killer);\n\t\t};\n\n\t\tchild.on('error', (error) => {\n\t\t\tsettle();\n\t\t\t// Node reports an abort as its own `AbortError`; the caller asked\n\t\t\t// with a reason, and that is what it should get back.\n\t\t\treject(spawnOptions.signal?.aborted ? spawnOptions.signal.reason : error);\n\t\t});\n\n\t\tchild.on('close', (code: number | null, signal: NodeJS.Signals | null) => {\n\t\t\tsettle();\n\t\t\tif (spawnOptions.signal?.aborted) reject(spawnOptions.signal.reason);\n\t\t\telse if (timedOut) reject(new CommandTimedOut(command, args, timeoutMs));\n\t\t\telse if (code === 0) resolve(stdout);\n\t\t\telse reject(new CommandFailed(command, args, code, signal));\n\t\t});\n\t});\n}\n","/**\n * How a deploy gets the credentials it acts with.\n *\n * `deploy()` never prompts and never reads a terminal: it asks a\n * `CredentialProvider` and, when the provider has nothing, stops with\n * `MissingCredential` naming what it needed and how to supply it. Whether to\n * ask a person, read a vault or fail is the caller's decision — `gkm deploy`\n * prompts at a terminal and stores what was typed; a CI job sets the\n * environment; a host passes its own provider.\n */\n\nimport { readCredentials } from '../auth/credentials';\n\n/**\n * What each kind of credential is asked for with, and what it is.\n *\n * A target that needs a kind the CLI does not know declares it by augmenting\n * this interface, and lists it in its `credentials`:\n *\n * ```ts\n * declare module '@geekmidas/cli/target' {\n * interface CredentialKinds {\n * fly: { request: { org: string }; value: { token: string } };\n * }\n * }\n * ```\n */\nexport interface CredentialKinds {\n\t/** The Dokploy API a stage deploys through. */\n\tdokploy: {\n\t\t/** `deploy.dokploy.endpoint`, when the config names one. */\n\t\trequest: { endpoint?: string };\n\t\tvalue: { endpoint: string; token: string };\n\t};\n\t/**\n\t * A container registry login, for Dokploy to pull with. Asked for only when\n\t * Dokploy has no registry for `deploy.registry` and one has to be\n\t * created.\n\t */\n\tregistry: {\n\t\t/** `deploy.registry`. */\n\t\trequest: { url: string };\n\t\tvalue: { username: string; password: string };\n\t};\n\t/**\n\t * The AWS account a stage deploys to, for the SST target's `sst deploy`.\n\t * Handed to that one command's environment and to nothing else.\n\t */\n\taws: {\n\t\t/** The stage, for a provider that keeps one account per stage. */\n\t\trequest: { stage: string };\n\t\tvalue: AwsCredential;\n\t};\n}\n\n/**\n * Who to act as on AWS: a named profile, or keys.\n *\n * Never both. Given both, every AWS SDK takes the keys and ignores the\n * profile, so `--profile prod` with staging's keys still exported would deploy\n * production's stack into staging's account — the reason `secretsStoreFor`\n * resolves a named profile on its own, and why this cannot express the mix.\n */\nexport type AwsCredential =\n\t| {\n\t\t\t/** A profile in `~/.aws/config` — keys, SSO, an assumed role. */\n\t\t\tprofile: string;\n\t\t\tregion?: string;\n\t }\n\t| {\n\t\t\taccessKeyId: string;\n\t\t\tsecretAccessKey: string;\n\t\t\t/** Present for temporary keys: an assumed role, GitHub's OIDC. */\n\t\t\tsessionToken?: string;\n\t\t\tregion?: string;\n\t };\n\nexport type CredentialKind = keyof CredentialKinds;\n\n/** What a deploy asks a provider for. */\nexport type CredentialRequest<K extends CredentialKind = CredentialKind> = {\n\t[P in K]: { kind: P } & CredentialKinds[P]['request'];\n}[K];\n\n/** What a provider answers with. */\nexport type Credential<K extends CredentialKind> = CredentialKinds[K]['value'];\n\nexport interface CredentialProvider {\n\t/**\n\t * The credential `request` asks for, or `undefined` when this provider has\n\t * none — the deploy then raises {@link MissingCredential}.\n\t */\n\tget<K extends CredentialKind>(\n\t\trequest: CredentialRequest<K>,\n\t\toptions?: { signal?: AbortSignal },\n\t): Promise<Credential<K> | undefined>;\n}\n\n/**\n * How to supply each kind the CLI knows, for the error that says it is\n * missing. A target's own kinds are its to explain.\n */\nconst HOW_TO_PROVIDE: Partial<Record<CredentialKind, string>> = {\n\tdokploy:\n\t\t\"Set DOKPLOY_API_TOKEN (and DOKPLOY_ENDPOINT, or deploy.dokploy.endpoint in gkm.config.ts), run `gkm login --provider dokploy`, or pass them through the deploy's CredentialProvider.\",\n\tregistry:\n\t\t'Add the registry in Dokploy (Settings → Docker Registry) and set deploy.dokploy.registryId, set DOCKER_REGISTRY_USERNAME and DOCKER_REGISTRY_PASSWORD, or run `gkm deploy` at a terminal to be asked for them.',\n\taws: \"Set AWS_PROFILE to the stage account's profile, or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (and AWS_SESSION_TOKEN) — in CI, the keys aws-actions/configure-aws-credentials exports — or pass them through the deploy's CredentialProvider.\",\n};\n\n/** A deploy needed a credential, and its provider had none. */\nexport class MissingCredential extends Error {\n\tconstructor(\n\t\treadonly kind: CredentialKind,\n\t\t/** What it was for: the Dokploy endpoint or the registry URL. */\n\t\treadonly target: string | undefined,\n\t\t/** How to supply it. */\n\t\treadonly howToProvide: string = HOW_TO_PROVIDE[kind] ??\n\t\t\t\"Pass it through the deploy's CredentialProvider.\",\n\t) {\n\t\tconst what =\n\t\t\tkind === 'dokploy'\n\t\t\t\t? `No Dokploy credentials${target ? ` for ${target}` : ''}.`\n\t\t\t\t: kind === 'registry'\n\t\t\t\t\t? `Dokploy has no registry for ${target ?? 'the configured registry'}, and there are no credentials to create one with.`\n\t\t\t\t\t: kind === 'aws'\n\t\t\t\t\t\t? `No AWS credentials${target ? ` for the \"${target}\" stage` : ''}.`\n\t\t\t\t\t\t: `No \"${String(kind)}\" credentials${target ? ` for ${target}` : ''}.`;\n\t\tsuper(`${what} ${howToProvide}`);\n\t\tthis.name = 'MissingCredential';\n\t}\n}\n\n/** Whatever was asked for, from the first provider that has it. */\nexport function chainCredentials(\n\t...providers: CredentialProvider[]\n): CredentialProvider {\n\treturn {\n\t\tasync get(request, options) {\n\t\t\tfor (const provider of providers) {\n\t\t\t\tconst found = await provider.get(request, options);\n\t\t\t\tif (found) return found;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\nexport interface StoredCredentialsOptions {\n\t/** Where to read the variables from. Defaults to `process.env`. */\n\tenv?: NodeJS.ProcessEnv;\n\t/**\n\t * The CLI's home, whose `credentials.json` holds stored logins. Defaults\n\t * to `GKM_HOME`, else `~/.gkm`.\n\t */\n\thome?: string;\n}\n\n/**\n * Credentials from the environment, then from what `gkm login` stored. What\n * `deploy()` uses when it is handed no provider.\n *\n * - Dokploy: `DOKPLOY_API_TOKEN` / `DOKPLOY_ENDPOINT`, each falling back to\n * the stored login, and the endpoint finally to `deploy.dokploy.endpoint`.\n * Each half is read on its own: a token is a secret and belongs in the\n * environment, an endpoint is configuration and belongs in the config.\n * - Registry: `DOCKER_REGISTRY_USERNAME` / `DOCKER_REGISTRY_PASSWORD`.\n * - AWS: `AWS_PROFILE` when it is set, and then nothing else; otherwise\n * `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN`. The\n * profile winning is `secretsStoreFor`'s rule: a profile is a choice of\n * account someone made, exported keys may be left over from another.\n * Read here, by name, and handed only to the command that deploys — the\n * sandbox every other step runs in passes no `AWS_*` on.\n */\nexport function storedCredentials(\n\toptions: StoredCredentialsOptions = {},\n): CredentialProvider {\n\tconst env = options.env ?? process.env;\n\n\treturn {\n\t\tasync get(asked) {\n\t\t\t// The union, so a switch on `kind` narrows it: `K` itself never is.\n\t\t\tconst request = asked as CredentialRequest;\n\t\t\tswitch (request.kind) {\n\t\t\t\tcase 'dokploy': {\n\t\t\t\t\tconst stored = (\n\t\t\t\t\t\tawait readCredentials(\n\t\t\t\t\t\t\toptions.home ? { home: options.home } : undefined,\n\t\t\t\t\t\t)\n\t\t\t\t\t).dokploy;\n\t\t\t\t\tconst token = env.DOKPLOY_API_TOKEN ?? stored?.token;\n\t\t\t\t\tconst endpoint =\n\t\t\t\t\t\tenv.DOKPLOY_ENDPOINT ?? stored?.endpoint ?? request.endpoint;\n\t\t\t\t\tif (!token || !endpoint) return undefined;\n\t\t\t\t\treturn { endpoint: endpoint.replace(/\\/$/, ''), token } as never;\n\t\t\t\t}\n\t\t\t\tcase 'registry': {\n\t\t\t\t\tconst username = env.DOCKER_REGISTRY_USERNAME;\n\t\t\t\t\tconst password = env.DOCKER_REGISTRY_PASSWORD;\n\t\t\t\t\tif (!username || !password) return undefined;\n\t\t\t\t\treturn { username, password } as never;\n\t\t\t\t}\n\t\t\t\tcase 'aws': {\n\t\t\t\t\tconst region = env.AWS_REGION ?? env.AWS_DEFAULT_REGION;\n\t\t\t\t\tconst where = region ? { region } : {};\n\t\t\t\t\tif (env.AWS_PROFILE) {\n\t\t\t\t\t\treturn { profile: env.AWS_PROFILE, ...where } as never;\n\t\t\t\t\t}\n\t\t\t\t\tconst accessKeyId = env.AWS_ACCESS_KEY_ID;\n\t\t\t\t\tconst secretAccessKey = env.AWS_SECRET_ACCESS_KEY;\n\t\t\t\t\tif (!accessKeyId || !secretAccessKey) return undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\taccessKeyId,\n\t\t\t\t\t\tsecretAccessKey,\n\t\t\t\t\t\t...(env.AWS_SESSION_TOKEN\n\t\t\t\t\t\t\t? { sessionToken: env.AWS_SESSION_TOKEN }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t...where,\n\t\t\t\t\t} as never;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// A kind a target declared: nothing stored here can answer it.\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
package/dist/deploy/public.cjs
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_credentials = require("../credentials-BVs7mrtw.cjs");
|
|
2
|
+
const require_credentials = require("../credentials-tr26-KML.cjs");
|
|
4
3
|
const require_discover = require("../discover-D1It5r_h.cjs");
|
|
5
4
|
const require_sandbox = require("../sandbox-CL--ZDui.cjs");
|
|
5
|
+
const require_workspace = require("../workspace-CT0JM3Y8.cjs");
|
|
6
6
|
const require_define = require("../define-DzRz8FgH.cjs");
|
|
7
7
|
const require_config = require("../config.cjs");
|
|
8
|
-
const require_seeds = require("../seeds-
|
|
9
|
-
const require_resolve = require("../resolve-
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
8
|
+
const require_seeds = require("../seeds-CsI0A_Ef.cjs");
|
|
9
|
+
const require_resolve = require("../resolve-BXeXzpmU.cjs");
|
|
10
|
+
const require_local = require("../local-Cq8qdgNX.cjs");
|
|
11
|
+
const require_sniffer = require("../sniffer-DJYupBeK.cjs");
|
|
12
|
+
const require_deploy = require("../deploy-CtbZj4zN.cjs");
|
|
13
|
+
const require_engine = require("../engine-Bt5k_UMq.cjs");
|
|
14
|
+
const require_rollback = require("../rollback-DFMiBWf0.cjs");
|
|
14
15
|
const require_provider = require("../provider-C9_-45d5.cjs");
|
|
15
|
-
const require_sst = require("../sst-
|
|
16
|
+
const require_sst = require("../sst-DAqUoZKG.cjs");
|
|
16
17
|
let node_path = require("node:path");
|
|
17
18
|
let node_fs = require("node:fs");
|
|
18
19
|
//#region src/sandbox/install.ts
|
|
@@ -132,14 +133,15 @@ async function installDependencies(sandbox, options = {}) {
|
|
|
132
133
|
...options.signal ? { signal: options.signal } : {}
|
|
133
134
|
});
|
|
134
135
|
results.push(result);
|
|
135
|
-
if (result.exitCode !== 0) throw new
|
|
136
|
+
if (result.exitCode !== 0) throw new require_credentials.CommandFailed(command, args, result.exitCode, result.signal);
|
|
136
137
|
}
|
|
137
138
|
return results;
|
|
138
139
|
}
|
|
139
140
|
//#endregion
|
|
141
|
+
exports.AllowDevServicesTakesNoValue = require_seeds.AllowDevServicesTakesNoValue;
|
|
140
142
|
exports.BackendDeployFailed = require_engine.BackendDeployFailed;
|
|
141
|
-
exports.CommandFailed =
|
|
142
|
-
exports.CommandTimedOut =
|
|
143
|
+
exports.CommandFailed = require_credentials.CommandFailed;
|
|
144
|
+
exports.CommandTimedOut = require_credentials.CommandTimedOut;
|
|
143
145
|
exports.ConfigLoadFailed = require_config.ConfigLoadFailed;
|
|
144
146
|
exports.ConfigObjectNotSerializable = require_config.ConfigObjectNotSerializable;
|
|
145
147
|
exports.ConstructDiscoveryFailed = require_discover.ConstructDiscoveryFailed;
|
|
@@ -153,25 +155,26 @@ exports.DeploymentTimedOut = require_sniffer.DeploymentTimedOut;
|
|
|
153
155
|
exports.DevServicesNeedServerTarget = require_seeds.DevServicesNeedServerTarget;
|
|
154
156
|
exports.ExternalServicesNotConfigured = require_seeds.ExternalServicesNotConfigured;
|
|
155
157
|
exports.FrontendDeployFailed = require_engine.FrontendDeployFailed;
|
|
156
|
-
exports.GKM_HOME_ENV =
|
|
158
|
+
exports.GKM_HOME_ENV = require_credentials.GKM_HOME_ENV;
|
|
157
159
|
exports.HealthCheckTimedOut = require_engine.HealthCheckTimedOut;
|
|
158
160
|
exports.INSTALL_TIMEOUT_MS = INSTALL_TIMEOUT_MS;
|
|
159
161
|
exports.InstallAllowlistNameInvalid = InstallAllowlistNameInvalid;
|
|
160
162
|
exports.InstallScriptsAllowlistUnsupported = InstallScriptsAllowlistUnsupported;
|
|
161
163
|
exports.InvalidTargetOptions = require_resolve.InvalidTargetOptions;
|
|
162
|
-
exports.LocalSandbox =
|
|
164
|
+
exports.LocalSandbox = require_local.LocalSandbox;
|
|
163
165
|
exports.MissingCredential = require_credentials.MissingCredential;
|
|
164
166
|
exports.MissingEnvVars = require_engine.MissingEnvVars;
|
|
165
167
|
exports.NoDeployableApps = require_deploy.NoDeployableApps;
|
|
166
168
|
exports.NothingToRollBack = require_rollback.NothingToRollBack;
|
|
167
169
|
exports.ProjectNotOwned = require_engine.ProjectNotOwned;
|
|
168
170
|
exports.ProviderRemoved = require_provider.ProviderRemoved;
|
|
171
|
+
exports.ProvisionedBucketUnreachable = require_workspace.ProvisionedBucketUnreachable;
|
|
169
172
|
exports.RegistryAmbiguous = require_engine.RegistryAmbiguous;
|
|
170
173
|
exports.RegistryNotConfigured = require_engine.RegistryNotConfigured;
|
|
171
174
|
exports.RegistryNotFound = require_engine.RegistryNotFound;
|
|
172
175
|
exports.RollbackFailed = require_deploy.RollbackFailed;
|
|
173
176
|
exports.RollbackNeedsApp = require_rollback.RollbackNeedsApp;
|
|
174
|
-
exports.SANDBOX_ENV_ALLOWLIST =
|
|
177
|
+
exports.SANDBOX_ENV_ALLOWLIST = require_local.SANDBOX_ENV_ALLOWLIST;
|
|
175
178
|
exports.SECRETS_DIR_ENV = require_sandbox.SECRETS_DIR_ENV;
|
|
176
179
|
exports.SandboxCwdEscape = require_sandbox.SandboxCwdEscape;
|
|
177
180
|
exports.SandboxWorkerFailed = require_discover.SandboxWorkerFailed;
|
|
@@ -179,8 +182,9 @@ exports.SecretNameInvalid = require_sandbox.SecretNameInvalid;
|
|
|
179
182
|
exports.SstConfigNotFound = require_sst.SstConfigNotFound;
|
|
180
183
|
exports.SstOutputsUnreadable = require_sst.SstOutputsUnreadable;
|
|
181
184
|
exports.StageNeverDeployed = require_rollback.StageNeverDeployed;
|
|
182
|
-
exports.
|
|
183
|
-
exports.
|
|
185
|
+
exports.StageProviderDisabled = require_seeds.StageProviderDisabled;
|
|
186
|
+
exports.StateLocked = require_seeds.StateLocked;
|
|
187
|
+
exports.StateVersionConflict = require_seeds.StateVersionConflict;
|
|
184
188
|
exports.SurfacesUnhealthy = require_sst.SurfacesUnhealthy;
|
|
185
189
|
exports.TargetBuildsNothing = require_deploy.TargetBuildsNothing;
|
|
186
190
|
exports.TargetEntryInvalid = require_resolve.TargetEntryInvalid;
|
|
@@ -190,13 +194,13 @@ exports.TargetRuntimeMismatch = require_resolve.TargetRuntimeMismatch;
|
|
|
190
194
|
exports.TargetRuntimeUndeclared = require_resolve.TargetRuntimeUndeclared;
|
|
191
195
|
exports.UnknownDeployApps = require_deploy.UnknownDeployApps;
|
|
192
196
|
exports.UnknownDeployTarget = require_define.UnknownDeployTarget;
|
|
193
|
-
exports.
|
|
194
|
-
exports.allowlistedEnv =
|
|
197
|
+
exports.UnknownStageProvider = require_workspace.UnknownStageProvider;
|
|
198
|
+
exports.allowlistedEnv = require_local.allowlistedEnv;
|
|
195
199
|
exports.chainCredentials = require_credentials.chainCredentials;
|
|
196
200
|
exports.confineCwd = require_sandbox.confineCwd;
|
|
197
201
|
exports.deploy = require_deploy.deploy;
|
|
198
202
|
exports.deployIdentity = require_seeds.deployIdentity;
|
|
199
|
-
exports.gkmHome =
|
|
203
|
+
exports.gkmHome = require_credentials.gkmHome;
|
|
200
204
|
exports.installDependencies = installDependencies;
|
|
201
205
|
exports.rollbackStage = require_rollback.rollbackStage;
|
|
202
206
|
exports.storedCredentials = require_credentials.storedCredentials;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.cjs","names":["existsSync","join","detectPackageManager","resolve","CommandFailed"],"sources":["../../src/sandbox/install.ts"],"sourcesContent":["/**\n * Installing a project's dependencies in a sandbox, with or without their\n * lifecycle scripts.\n *\n * `postinstall` is the oldest way into a build machine: any package in the\n * lockfile — a dependency of a dependency — runs whatever it likes the moment\n * it is installed. For a build the host trusts that is how native modules get\n * built. For one it does not, the scripts are skipped, and the few packages\n * that genuinely need theirs (esbuild's binary, a database driver) are named\n * and rebuilt — with nothing but the sandbox's environment either way.\n */\n\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { detectPackageManager, type PackageManager } from '../docker/templates';\nimport { CommandFailed } from '../run';\nimport type { Sandbox, SandboxOutput, SandboxResult } from './sandbox';\n\n/** Long enough for a cold install of a large monorepo. */\nexport const INSTALL_TIMEOUT_MS = 15 * 60_000;\n\nexport interface InstallOptions {\n\t/** The directory to install in. Defaults to the sandbox's root. */\n\tcwd?: string;\n\t/** Defaults to the one the lockfile above `cwd` names. */\n\tpackageManager?: PackageManager;\n\t/**\n\t * Skip every lifecycle script — dependencies' and the project's own —\n\t * except those of {@link allowScripts}. Defaults to false: scripts run as\n\t * a plain install runs them, under the package manager's own policy —\n\t * npm 12 and pnpm 10 skip dependencies' scripts nobody approved.\n\t */\n\tignoreScripts?: boolean;\n\t/**\n\t * With `ignoreScripts`, the packages whose scripts still run: rebuilt by\n\t * name once the install is done.\n\t */\n\tallowScripts?: readonly string[];\n\t/** Variables the install needs beyond the sandbox's own. */\n\tenv?: Readonly<Record<string, string>>;\n\t/** Defaults to {@link INSTALL_TIMEOUT_MS}, for each command. */\n\ttimeoutMs?: number;\n\t/** Where the package manager's output goes. Defaults to `inherit`. */\n\toutput?: SandboxOutput;\n\tsignal?: AbortSignal;\n}\n\n/** A name in `allowScripts` that is not a package name. */\nexport class InstallAllowlistNameInvalid extends Error {\n\tconstructor(readonly packageName: string) {\n\t\tsuper(\n\t\t\t`'${packageName}' is not a package name, so its scripts cannot be ` +\n\t\t\t\t'allowed. Name the package as it appears in package.json — ' +\n\t\t\t\t\"'esbuild', '@prisma/client'.\",\n\t\t);\n\t\tthis.name = 'InstallAllowlistNameInvalid';\n\t}\n}\n\n/** The package manager has no way to run only some packages' scripts. */\nexport class InstallScriptsAllowlistUnsupported extends Error {\n\tconstructor(\n\t\treadonly packageManager: string,\n\t\treadonly allowScripts: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`${packageManager} cannot rebuild named packages after an install ` +\n\t\t\t\t`without scripts, so ${allowScripts.join(', ')} cannot be allowed ` +\n\t\t\t\t'theirs. Use pnpm, npm or Yarn 2+, or install with every script ' +\n\t\t\t\t'skipped.',\n\t\t);\n\t\tthis.name = 'InstallScriptsAllowlistUnsupported';\n\t}\n}\n\n/**\n * npm's package-name grammar, less a leading `-`: each name is an argument to\n * `rebuild`, and must never be read as a flag.\n */\nconst PACKAGE_NAME = /^(?:@[a-z0-9~][a-z0-9._~-]*\\/)?[a-z0-9~][a-z0-9._~-]*$/;\n\n/**\n * The commands an install runs, in order. Exported for the tests, which\n * check each package manager's flags without installing with all four.\n */\nexport function installCommands(\n\tpackageManager: PackageManager,\n\tcwd: string,\n\toptions: Pick<InstallOptions, 'ignoreScripts' | 'allowScripts'> = {},\n): [string, string[]][] {\n\tconst ignore = options.ignoreScripts ?? false;\n\tconst allow = ignore ? [...(options.allowScripts ?? [])] : [];\n\tfor (const name of allow) {\n\t\tif (!PACKAGE_NAME.test(name)) throw new InstallAllowlistNameInvalid(name);\n\t}\n\n\tswitch (packageManager) {\n\t\tcase 'pnpm':\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'pnpm',\n\t\t\t\t\t[\n\t\t\t\t\t\t'install',\n\t\t\t\t\t\t'--frozen-lockfile',\n\t\t\t\t\t\t...(ignore ? ['--ignore-scripts'] : []),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// pnpm 10 builds no dependency it was not told to, even by name;\n\t\t\t\t// this command names exactly the ones allowed, so it may build\n\t\t\t\t// what it names.\n\t\t\t\t...(allow.length > 0\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'pnpm',\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t'rebuild',\n\t\t\t\t\t\t\t\t\t'--config.dangerouslyAllowAllBuilds=true',\n\t\t\t\t\t\t\t\t\t...allow,\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t] as [string, string[]],\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t];\n\t\tcase 'npm': {\n\t\t\tconst locked = existsSync(join(cwd, 'package-lock.json'));\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'npm',\n\t\t\t\t\t[locked ? 'ci' : 'install', ...(ignore ? ['--ignore-scripts'] : [])],\n\t\t\t\t],\n\t\t\t\t// npm 12 runs no dependency's install script its `allowScripts`\n\t\t\t\t// policy does not approve, rebuilt by name or not, and refuses\n\t\t\t\t// `--allow-scripts` on a project's command line. This command\n\t\t\t\t// names exactly the packages allowed, so it may run what it names.\n\t\t\t\t...(allow.length > 0\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'npm',\n\t\t\t\t\t\t\t\t['rebuild', '--dangerously-allow-all-scripts', ...allow],\n\t\t\t\t\t\t\t] as [string, string[]],\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t];\n\t\t}\n\t\tcase 'yarn': {\n\t\t\t// Yarn 2+ keeps a `.yarnrc.yml`; it skips builds by mode and can\n\t\t\t// rebuild by name. Yarn 1 can only skip them all.\n\t\t\tconst berry = existsSync(join(cwd, '.yarnrc.yml'));\n\t\t\tif (berry) {\n\t\t\t\treturn [\n\t\t\t\t\t[\n\t\t\t\t\t\t'yarn',\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'install',\n\t\t\t\t\t\t\t'--immutable',\n\t\t\t\t\t\t\t...(ignore ? ['--mode=skip-build'] : []),\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t...(allow.length > 0\n\t\t\t\t\t\t? [['yarn', ['rebuild', ...allow]] as [string, string[]]]\n\t\t\t\t\t\t: []),\n\t\t\t\t];\n\t\t\t}\n\t\t\tif (allow.length > 0) {\n\t\t\t\tthrow new InstallScriptsAllowlistUnsupported('Yarn 1', allow);\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'yarn',\n\t\t\t\t\t[\n\t\t\t\t\t\t'install',\n\t\t\t\t\t\t'--frozen-lockfile',\n\t\t\t\t\t\t...(ignore ? ['--ignore-scripts'] : []),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\t\tcase 'bun':\n\t\t\tif (allow.length > 0) {\n\t\t\t\tthrow new InstallScriptsAllowlistUnsupported('bun', allow);\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'bun',\n\t\t\t\t\t[\n\t\t\t\t\t\t'install',\n\t\t\t\t\t\t'--frozen-lockfile',\n\t\t\t\t\t\t...(ignore ? ['--ignore-scripts'] : []),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t];\n\t}\n}\n\n/**\n * Install the project's dependencies in `sandbox`.\n *\n * ```ts\n * // A checkout nobody has reviewed: no scripts but esbuild's.\n * await installDependencies(sandbox, {\n * ignoreScripts: true,\n * allowScripts: ['esbuild'],\n * });\n * ```\n *\n * Resolves with each command's result, in order — with its output when\n * `output` is `capture`.\n *\n * @throws {CommandFailed} when the package manager exits unsuccessfully.\n * @throws {InstallScriptsAllowlistUnsupported} for an allowlist the package\n * manager cannot honour, before anything is installed.\n */\nexport async function installDependencies(\n\tsandbox: Sandbox,\n\toptions: InstallOptions = {},\n): Promise<SandboxResult[]> {\n\tconst cwd = options.cwd ?? sandbox.root;\n\tconst results: SandboxResult[] = [];\n\tconst packageManager =\n\t\toptions.packageManager ?? detectPackageManager(resolve(sandbox.root, cwd));\n\n\tfor (const [command, args] of installCommands(\n\t\tpackageManager,\n\t\tresolve(sandbox.root, cwd),\n\t\toptions,\n\t)) {\n\t\tconst result = await sandbox.exec(command, args, {\n\t\t\tcwd,\n\t\t\tenv: { ...sandbox.env, ...options.env },\n\t\t\ttimeoutMs: options.timeoutMs ?? INSTALL_TIMEOUT_MS,\n\t\t\toutput: options.output ?? 'inherit',\n\t\t\t...(options.signal ? { signal: options.signal } : {}),\n\t\t});\n\t\tresults.push(result);\n\t\tif (result.exitCode !== 0) {\n\t\t\tthrow new CommandFailed(\n\t\t\t\tcommand,\n\t\t\t\targs,\n\t\t\t\tresult.exitCode,\n\t\t\t\tresult.signal as NodeJS.Signals | null,\n\t\t\t);\n\t\t}\n\t}\n\treturn results;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"public.cjs","names":["existsSync","join","detectPackageManager","resolve","CommandFailed"],"sources":["../../src/sandbox/install.ts"],"sourcesContent":["/**\n * Installing a project's dependencies in a sandbox, with or without their\n * lifecycle scripts.\n *\n * `postinstall` is the oldest way into a build machine: any package in the\n * lockfile — a dependency of a dependency — runs whatever it likes the moment\n * it is installed. For a build the host trusts that is how native modules get\n * built. For one it does not, the scripts are skipped, and the few packages\n * that genuinely need theirs (esbuild's binary, a database driver) are named\n * and rebuilt — with nothing but the sandbox's environment either way.\n */\n\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { detectPackageManager, type PackageManager } from '../docker/templates';\nimport { CommandFailed } from '../run';\nimport type { Sandbox, SandboxOutput, SandboxResult } from './sandbox';\n\n/** Long enough for a cold install of a large monorepo. */\nexport const INSTALL_TIMEOUT_MS = 15 * 60_000;\n\nexport interface InstallOptions {\n\t/** The directory to install in. Defaults to the sandbox's root. */\n\tcwd?: string;\n\t/** Defaults to the one the lockfile above `cwd` names. */\n\tpackageManager?: PackageManager;\n\t/**\n\t * Skip every lifecycle script — dependencies' and the project's own —\n\t * except those of {@link allowScripts}. Defaults to false: scripts run as\n\t * a plain install runs them, under the package manager's own policy —\n\t * npm 12 and pnpm 10 skip dependencies' scripts nobody approved.\n\t */\n\tignoreScripts?: boolean;\n\t/**\n\t * With `ignoreScripts`, the packages whose scripts still run: rebuilt by\n\t * name once the install is done.\n\t */\n\tallowScripts?: readonly string[];\n\t/** Variables the install needs beyond the sandbox's own. */\n\tenv?: Readonly<Record<string, string>>;\n\t/** Defaults to {@link INSTALL_TIMEOUT_MS}, for each command. */\n\ttimeoutMs?: number;\n\t/** Where the package manager's output goes. Defaults to `inherit`. */\n\toutput?: SandboxOutput;\n\tsignal?: AbortSignal;\n}\n\n/** A name in `allowScripts` that is not a package name. */\nexport class InstallAllowlistNameInvalid extends Error {\n\tconstructor(readonly packageName: string) {\n\t\tsuper(\n\t\t\t`'${packageName}' is not a package name, so its scripts cannot be ` +\n\t\t\t\t'allowed. Name the package as it appears in package.json — ' +\n\t\t\t\t\"'esbuild', '@prisma/client'.\",\n\t\t);\n\t\tthis.name = 'InstallAllowlistNameInvalid';\n\t}\n}\n\n/** The package manager has no way to run only some packages' scripts. */\nexport class InstallScriptsAllowlistUnsupported extends Error {\n\tconstructor(\n\t\treadonly packageManager: string,\n\t\treadonly allowScripts: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`${packageManager} cannot rebuild named packages after an install ` +\n\t\t\t\t`without scripts, so ${allowScripts.join(', ')} cannot be allowed ` +\n\t\t\t\t'theirs. Use pnpm, npm or Yarn 2+, or install with every script ' +\n\t\t\t\t'skipped.',\n\t\t);\n\t\tthis.name = 'InstallScriptsAllowlistUnsupported';\n\t}\n}\n\n/**\n * npm's package-name grammar, less a leading `-`: each name is an argument to\n * `rebuild`, and must never be read as a flag.\n */\nconst PACKAGE_NAME = /^(?:@[a-z0-9~][a-z0-9._~-]*\\/)?[a-z0-9~][a-z0-9._~-]*$/;\n\n/**\n * The commands an install runs, in order. Exported for the tests, which\n * check each package manager's flags without installing with all four.\n */\nexport function installCommands(\n\tpackageManager: PackageManager,\n\tcwd: string,\n\toptions: Pick<InstallOptions, 'ignoreScripts' | 'allowScripts'> = {},\n): [string, string[]][] {\n\tconst ignore = options.ignoreScripts ?? false;\n\tconst allow = ignore ? [...(options.allowScripts ?? [])] : [];\n\tfor (const name of allow) {\n\t\tif (!PACKAGE_NAME.test(name)) throw new InstallAllowlistNameInvalid(name);\n\t}\n\n\tswitch (packageManager) {\n\t\tcase 'pnpm':\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'pnpm',\n\t\t\t\t\t[\n\t\t\t\t\t\t'install',\n\t\t\t\t\t\t'--frozen-lockfile',\n\t\t\t\t\t\t...(ignore ? ['--ignore-scripts'] : []),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// pnpm 10 builds no dependency it was not told to, even by name;\n\t\t\t\t// this command names exactly the ones allowed, so it may build\n\t\t\t\t// what it names.\n\t\t\t\t...(allow.length > 0\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'pnpm',\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t'rebuild',\n\t\t\t\t\t\t\t\t\t'--config.dangerouslyAllowAllBuilds=true',\n\t\t\t\t\t\t\t\t\t...allow,\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t] as [string, string[]],\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t];\n\t\tcase 'npm': {\n\t\t\tconst locked = existsSync(join(cwd, 'package-lock.json'));\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'npm',\n\t\t\t\t\t[locked ? 'ci' : 'install', ...(ignore ? ['--ignore-scripts'] : [])],\n\t\t\t\t],\n\t\t\t\t// npm 12 runs no dependency's install script its `allowScripts`\n\t\t\t\t// policy does not approve, rebuilt by name or not, and refuses\n\t\t\t\t// `--allow-scripts` on a project's command line. This command\n\t\t\t\t// names exactly the packages allowed, so it may run what it names.\n\t\t\t\t...(allow.length > 0\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'npm',\n\t\t\t\t\t\t\t\t['rebuild', '--dangerously-allow-all-scripts', ...allow],\n\t\t\t\t\t\t\t] as [string, string[]],\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t];\n\t\t}\n\t\tcase 'yarn': {\n\t\t\t// Yarn 2+ keeps a `.yarnrc.yml`; it skips builds by mode and can\n\t\t\t// rebuild by name. Yarn 1 can only skip them all.\n\t\t\tconst berry = existsSync(join(cwd, '.yarnrc.yml'));\n\t\t\tif (berry) {\n\t\t\t\treturn [\n\t\t\t\t\t[\n\t\t\t\t\t\t'yarn',\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'install',\n\t\t\t\t\t\t\t'--immutable',\n\t\t\t\t\t\t\t...(ignore ? ['--mode=skip-build'] : []),\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t...(allow.length > 0\n\t\t\t\t\t\t? [['yarn', ['rebuild', ...allow]] as [string, string[]]]\n\t\t\t\t\t\t: []),\n\t\t\t\t];\n\t\t\t}\n\t\t\tif (allow.length > 0) {\n\t\t\t\tthrow new InstallScriptsAllowlistUnsupported('Yarn 1', allow);\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'yarn',\n\t\t\t\t\t[\n\t\t\t\t\t\t'install',\n\t\t\t\t\t\t'--frozen-lockfile',\n\t\t\t\t\t\t...(ignore ? ['--ignore-scripts'] : []),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\t\tcase 'bun':\n\t\t\tif (allow.length > 0) {\n\t\t\t\tthrow new InstallScriptsAllowlistUnsupported('bun', allow);\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t[\n\t\t\t\t\t'bun',\n\t\t\t\t\t[\n\t\t\t\t\t\t'install',\n\t\t\t\t\t\t'--frozen-lockfile',\n\t\t\t\t\t\t...(ignore ? ['--ignore-scripts'] : []),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t];\n\t}\n}\n\n/**\n * Install the project's dependencies in `sandbox`.\n *\n * ```ts\n * // A checkout nobody has reviewed: no scripts but esbuild's.\n * await installDependencies(sandbox, {\n * ignoreScripts: true,\n * allowScripts: ['esbuild'],\n * });\n * ```\n *\n * Resolves with each command's result, in order — with its output when\n * `output` is `capture`.\n *\n * @throws {CommandFailed} when the package manager exits unsuccessfully.\n * @throws {InstallScriptsAllowlistUnsupported} for an allowlist the package\n * manager cannot honour, before anything is installed.\n */\nexport async function installDependencies(\n\tsandbox: Sandbox,\n\toptions: InstallOptions = {},\n): Promise<SandboxResult[]> {\n\tconst cwd = options.cwd ?? sandbox.root;\n\tconst results: SandboxResult[] = [];\n\tconst packageManager =\n\t\toptions.packageManager ?? detectPackageManager(resolve(sandbox.root, cwd));\n\n\tfor (const [command, args] of installCommands(\n\t\tpackageManager,\n\t\tresolve(sandbox.root, cwd),\n\t\toptions,\n\t)) {\n\t\tconst result = await sandbox.exec(command, args, {\n\t\t\tcwd,\n\t\t\tenv: { ...sandbox.env, ...options.env },\n\t\t\ttimeoutMs: options.timeoutMs ?? INSTALL_TIMEOUT_MS,\n\t\t\toutput: options.output ?? 'inherit',\n\t\t\t...(options.signal ? { signal: options.signal } : {}),\n\t\t});\n\t\tresults.push(result);\n\t\tif (result.exitCode !== 0) {\n\t\t\tthrow new CommandFailed(\n\t\t\t\tcommand,\n\t\t\t\targs,\n\t\t\t\tresult.exitCode,\n\t\t\t\tresult.signal as NodeJS.Signals | null,\n\t\t\t);\n\t\t}\n\t}\n\treturn results;\n}\n"],"mappings":"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"}
|