@pushto/cli 0.2.0 → 0.4.6
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/commands/__tests__/deploy-domain.test.d.ts +2 -0
- package/dist/commands/__tests__/deploy-domain.test.d.ts.map +1 -0
- package/dist/commands/__tests__/deploy-domain.test.js +41 -0
- package/dist/commands/__tests__/deploy-domain.test.js.map +1 -0
- package/dist/commands/__tests__/headless-smoke.test.d.ts +2 -0
- package/dist/commands/__tests__/headless-smoke.test.d.ts.map +1 -0
- package/dist/commands/__tests__/headless-smoke.test.js +110 -0
- package/dist/commands/__tests__/headless-smoke.test.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +77 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/cron.d.ts +2 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +157 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/db.d.ts +4 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +63 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/deploy.d.ts +16 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +344 -68
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +401 -69
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/domain.d.ts.map +1 -1
- package/dist/commands/domain.js +70 -18
- package/dist/commands/domain.js.map +1 -1
- package/dist/commands/echo.d.ts +2 -0
- package/dist/commands/echo.d.ts.map +1 -0
- package/dist/commands/echo.js +227 -0
- package/dist/commands/echo.js.map +1 -0
- package/dist/commands/env.d.ts +3 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +76 -50
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +58 -11
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +80 -39
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logs.d.ts +3 -1
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +77 -21
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/mail.d.ts +2 -0
- package/dist/commands/mail.d.ts.map +1 -0
- package/dist/commands/mail.js +105 -0
- package/dist/commands/mail.js.map +1 -0
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +32 -8
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/preview.d.ts +22 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +223 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/status.d.ts +3 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +62 -12
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +73 -10
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/use.d.ts +2 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +108 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/commands/vault.d.ts +2 -0
- package/dist/commands/vault.d.ts.map +1 -0
- package/dist/commands/vault.js +119 -0
- package/dist/commands/vault.js.map +1 -0
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +12 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/index.js +123 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/build-runner.test.d.ts +2 -0
- package/dist/lib/__tests__/build-runner.test.d.ts.map +1 -0
- package/dist/lib/__tests__/build-runner.test.js +119 -0
- package/dist/lib/__tests__/build-runner.test.js.map +1 -0
- package/dist/lib/__tests__/cron-tail.test.d.ts +2 -0
- package/dist/lib/__tests__/cron-tail.test.d.ts.map +1 -0
- package/dist/lib/__tests__/cron-tail.test.js +27 -0
- package/dist/lib/__tests__/cron-tail.test.js.map +1 -0
- package/dist/lib/__tests__/detect-static-framework.test.d.ts +2 -0
- package/dist/lib/__tests__/detect-static-framework.test.d.ts.map +1 -0
- package/dist/lib/__tests__/detect-static-framework.test.js +146 -0
- package/dist/lib/__tests__/detect-static-framework.test.js.map +1 -0
- package/dist/lib/__tests__/errors.test.d.ts +2 -0
- package/dist/lib/__tests__/errors.test.d.ts.map +1 -0
- package/dist/lib/__tests__/errors.test.js +56 -0
- package/dist/lib/__tests__/errors.test.js.map +1 -0
- package/dist/lib/__tests__/interactive.test.d.ts +2 -0
- package/dist/lib/__tests__/interactive.test.d.ts.map +1 -0
- package/dist/lib/__tests__/interactive.test.js +79 -0
- package/dist/lib/__tests__/interactive.test.js.map +1 -0
- package/dist/lib/__tests__/output.test.d.ts +2 -0
- package/dist/lib/__tests__/output.test.d.ts.map +1 -0
- package/dist/lib/__tests__/output.test.js +144 -0
- package/dist/lib/__tests__/output.test.js.map +1 -0
- package/dist/lib/__tests__/prepare-artifact.test.d.ts +2 -0
- package/dist/lib/__tests__/prepare-artifact.test.d.ts.map +1 -0
- package/dist/lib/__tests__/prepare-artifact.test.js +55 -0
- package/dist/lib/__tests__/prepare-artifact.test.js.map +1 -0
- package/dist/lib/__tests__/preview-args.test.d.ts +2 -0
- package/dist/lib/__tests__/preview-args.test.d.ts.map +1 -0
- package/dist/lib/__tests__/preview-args.test.js +37 -0
- package/dist/lib/__tests__/preview-args.test.js.map +1 -0
- package/dist/lib/api.d.ts +2 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +38 -5
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/ask.d.ts +15 -0
- package/dist/lib/ask.d.ts.map +1 -0
- package/dist/lib/ask.js +24 -0
- package/dist/lib/ask.js.map +1 -0
- package/dist/lib/build-runner.d.ts +25 -0
- package/dist/lib/build-runner.d.ts.map +1 -0
- package/dist/lib/build-runner.js +141 -0
- package/dist/lib/build-runner.js.map +1 -0
- package/dist/lib/config.d.ts +6 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +13 -2
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/cron-tail.d.ts +10 -0
- package/dist/lib/cron-tail.d.ts.map +1 -0
- package/dist/lib/cron-tail.js +5 -0
- package/dist/lib/cron-tail.js.map +1 -0
- package/dist/lib/detect-static-framework.d.ts +31 -0
- package/dist/lib/detect-static-framework.d.ts.map +1 -0
- package/dist/lib/detect-static-framework.js +96 -0
- package/dist/lib/detect-static-framework.js.map +1 -0
- package/dist/lib/env-parse.d.ts +48 -0
- package/dist/lib/env-parse.d.ts.map +1 -0
- package/dist/lib/env-parse.js +91 -0
- package/dist/lib/env-parse.js.map +1 -0
- package/dist/lib/errors.d.ts +111 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +64 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/file-walker.d.ts +23 -0
- package/dist/lib/file-walker.d.ts.map +1 -0
- package/dist/lib/file-walker.js +114 -0
- package/dist/lib/file-walker.js.map +1 -0
- package/dist/lib/interactive.d.ts +13 -0
- package/dist/lib/interactive.d.ts.map +1 -0
- package/dist/lib/interactive.js +24 -0
- package/dist/lib/interactive.js.map +1 -0
- package/dist/lib/output.d.ts +24 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +71 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/prepare-artifact.d.ts +22 -0
- package/dist/lib/prepare-artifact.d.ts.map +1 -0
- package/dist/lib/prepare-artifact.js +26 -0
- package/dist/lib/prepare-artifact.js.map +1 -0
- package/dist/lib/preview-args.d.ts +20 -0
- package/dist/lib/preview-args.d.ts.map +1 -0
- package/dist/lib/preview-args.js +19 -0
- package/dist/lib/preview-args.js.map +1 -0
- package/dist/lib/resolve-slug.d.ts.map +1 -1
- package/dist/lib/resolve-slug.js +9 -2
- package/dist/lib/resolve-slug.js.map +1 -1
- package/dist/lib/safe-json.d.ts +7 -2
- package/dist/lib/safe-json.d.ts.map +1 -1
- package/dist/lib/safe-json.js +23 -4
- package/dist/lib/safe-json.js.map +1 -1
- package/dist/lib/update-check.d.ts +17 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +81 -0
- package/dist/lib/update-check.js.map +1 -0
- package/dist/lib/upload-limits.d.ts +17 -0
- package/dist/lib/upload-limits.d.ts.map +1 -0
- package/dist/lib/upload-limits.js +17 -0
- package/dist/lib/upload-limits.js.map +1 -0
- package/dist/lib/zip-project.d.ts +19 -0
- package/dist/lib/zip-project.d.ts.map +1 -0
- package/dist/lib/zip-project.js +39 -0
- package/dist/lib/zip-project.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +16 -0
- package/dist/version.js.map +1 -0
- package/package.json +5 -8
package/dist/commands/domain.js
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { getToken } from '../lib/config.js';
|
|
3
3
|
import { resolveSlug } from '../lib/resolve-slug.js';
|
|
4
4
|
import { api } from '../lib/api.js';
|
|
5
|
+
import { safeJson } from '../lib/safe-json.js';
|
|
5
6
|
export const domain = async (action, domainName) => {
|
|
6
7
|
const token = getToken();
|
|
7
8
|
if (!token) {
|
|
@@ -19,32 +20,83 @@ export const domain = async (action, domainName) => {
|
|
|
19
20
|
process.exit(1);
|
|
20
21
|
}
|
|
21
22
|
console.log(chalk.green(`> registering ${domainName} for ${slug}...`));
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
let res;
|
|
24
|
+
try {
|
|
25
|
+
res = await api(`/cli/projects/${slug}/domain`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
body: JSON.stringify({ domain: domainName }),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
// Same shape as i61 (init), i71 (status), i72 (use) — classify
|
|
32
|
+
// network errors so users don't get the unhandledRejection
|
|
33
|
+
// handler's generic "something went wrong" for what is really
|
|
34
|
+
// a connectivity issue (or a real local problem they should
|
|
35
|
+
// see directly).
|
|
36
|
+
const msg = err instanceof Error ? err.message : '';
|
|
37
|
+
const isNetwork = /fetch|enotfound|econnrefused|timeout|abort|network/i.test(msg);
|
|
38
|
+
if (isNetwork) {
|
|
39
|
+
console.log(chalk.red('> could not reach pushto.host. check your internet.'));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(chalk.red(`> domain setup failed: ${msg || 'unknown error'}`));
|
|
43
|
+
}
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const data = await safeJson(res);
|
|
27
47
|
if (!res.ok) {
|
|
28
48
|
console.log(chalk.red(`> ${data.error ?? 'something went wrong.'}`));
|
|
29
49
|
process.exit(1);
|
|
30
50
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.log(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
const nameservers = data.nameservers;
|
|
52
|
+
const warnings = data.warnings ?? [];
|
|
53
|
+
console.log(chalk.green(`> ${domainName} configured.\n`));
|
|
54
|
+
if (nameservers?.length) {
|
|
55
|
+
console.log(' go to where you bought your domain and change the');
|
|
56
|
+
console.log(' ' + chalk.cyan('nameservers') + ' to:\n');
|
|
57
|
+
for (const ns of nameservers) {
|
|
58
|
+
console.log(` ${chalk.green(ns)}`);
|
|
59
|
+
}
|
|
60
|
+
console.log();
|
|
61
|
+
console.log(chalk.dim(' that\'s it. we handle the rest — DNS records, SSL, everything.'));
|
|
62
|
+
console.log(chalk.dim(' propagation usually takes a few minutes, sometimes up to 24h.'));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(chalk.dim(' DNS is already configured. check status with: pushto status'));
|
|
66
|
+
}
|
|
67
|
+
// Surface partial-failure warnings from the server (i4 fix added these
|
|
68
|
+
// for www CNAME failures and SSL-mode-config failures). Pre-fix the
|
|
69
|
+
// server logged them but the CLI dropped the response field on the
|
|
70
|
+
// floor so the user never knew their www subdomain wouldn't work.
|
|
71
|
+
if (warnings.length > 0) {
|
|
72
|
+
console.log();
|
|
73
|
+
console.log(chalk.yellow(' heads up:'));
|
|
74
|
+
for (const w of warnings) {
|
|
75
|
+
console.log(chalk.yellow(` ${w}`));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
38
78
|
console.log();
|
|
39
|
-
console.log(chalk.dim(' DNS can take a few minutes to propagate.'));
|
|
40
|
-
console.log(chalk.dim(' check status with: pushto status'));
|
|
41
79
|
}
|
|
42
80
|
else if (action === 'remove' || action === 'rm') {
|
|
43
81
|
console.log(chalk.green(`> removing custom domain from ${slug}...`));
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
82
|
+
let res;
|
|
83
|
+
try {
|
|
84
|
+
res = await api(`/cli/projects/${slug}/domain`, {
|
|
85
|
+
method: 'DELETE',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const msg = err instanceof Error ? err.message : '';
|
|
90
|
+
const isNetwork = /fetch|enotfound|econnrefused|timeout|abort|network/i.test(msg);
|
|
91
|
+
if (isNetwork) {
|
|
92
|
+
console.log(chalk.red('> could not reach pushto.host. check your internet.'));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.log(chalk.red(`> domain remove failed: ${msg || 'unknown error'}`));
|
|
96
|
+
}
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
const data = await safeJson(res);
|
|
48
100
|
if (!res.ok) {
|
|
49
101
|
console.log(chalk.red(`> ${data.error ?? 'something went wrong.'}`));
|
|
50
102
|
process.exit(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,MAAc,EAAE,UAAmB,EAAiB,EAAE;IACjF,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,UAAU,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC;QAEvE,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,GAAG,CAAC,iBAAiB,IAAI,SAAS,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;aAC7C,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,+DAA+D;YAC/D,2DAA2D;YAC3D,8DAA8D;YAC9D,4DAA4D;YAC5D,iBAAiB;YACjB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,MAAM,SAAS,GAAG,qDAAqD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClF,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAA0B,GAAG,CAAC,CAAC;QAE1D,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAM,IAAI,CAAC,KAAgB,IAAI,uBAAuB,EAAE,CAAC,CAAC,CAAC;YACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,WAAmC,CAAC;QAC7D,MAAM,QAAQ,GAAI,IAAI,CAAC,QAAiC,IAAI,EAAE,CAAC;QAE/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,UAAU,gBAAgB,CAAC,CAAC,CAAC;QAE1D,IAAI,WAAW,EAAE,MAAM,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC;YACzD,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC,CAAC;YAC3F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC,CAAC;QAC5F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC,CAAC;QAC1F,CAAC;QAED,uEAAuE;QACvE,oEAAoE;QACpE,mEAAmE;QACnE,kEAAkE;QAClE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;YACzC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEhB,CAAC;SAAM,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iCAAiC,IAAI,KAAK,CAAC,CAAC,CAAC;QAErE,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,GAAG,CAAC,iBAAiB,IAAI,SAAS,EAAE;gBAC9C,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,MAAM,SAAS,GAAG,qDAAqD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClF,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2BAA2B,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;YAC9E,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAA0B,GAAG,CAAC,CAAC;QAE1D,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAM,IAAI,CAAC,KAAgB,IAAI,uBAAuB,EAAE,CAAC,CAAC,CAAC;YACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAM,IAAI,CAAC,OAAkB,IAAI,iBAAiB,EAAE,CAAC,CAAC,CAAC;IAEjF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"echo.d.ts","sourceRoot":"","sources":["../../src/commands/echo.ts"],"names":[],"mappings":"AA0QA,eAAO,MAAM,IAAI,GAAU,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAcvE,CAAC"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getToken } from '../lib/config.js';
|
|
3
|
+
import { resolveSlug } from '../lib/resolve-slug.js';
|
|
4
|
+
import { api } from '../lib/api.js';
|
|
5
|
+
import { safeJson } from '../lib/safe-json.js';
|
|
6
|
+
const ensureAuthed = () => {
|
|
7
|
+
const token = getToken();
|
|
8
|
+
if (!token) {
|
|
9
|
+
console.log(chalk.red('> not logged in.'));
|
|
10
|
+
console.log(chalk.dim(' run ') + chalk.cyan('pushto login') + chalk.dim(' first.'));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const slug = resolveSlug();
|
|
14
|
+
if (!slug) {
|
|
15
|
+
console.log(chalk.red('> no project here. run pushto init first.'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
return slug;
|
|
19
|
+
};
|
|
20
|
+
const usage = () => {
|
|
21
|
+
console.log(chalk.dim(' usage:'));
|
|
22
|
+
console.log(chalk.cyan(' pushto echo on') + chalk.dim(' start recording'));
|
|
23
|
+
console.log(chalk.cyan(' pushto echo off') + chalk.dim(' stop recording'));
|
|
24
|
+
console.log(chalk.cyan(' pushto echo status') + chalk.dim(' show settings + 24h routes'));
|
|
25
|
+
console.log(chalk.cyan(' pushto echo replay') + chalk.dim(' replay recent recordings'));
|
|
26
|
+
console.log();
|
|
27
|
+
console.log(chalk.dim(' replay flags:'));
|
|
28
|
+
console.log(chalk.dim(' --target=<url> https url under your project (preview/prod/custom)'));
|
|
29
|
+
console.log(chalk.dim(' --label=<text> optional human label'));
|
|
30
|
+
console.log(chalk.dim(' --since=<iso> only recordings since that timestamp'));
|
|
31
|
+
console.log(chalk.dim(' --route=<sig> filter by route signature, e.g. "GET /api/x"'));
|
|
32
|
+
console.log(chalk.dim(' --status=<n> filter by recorded status code'));
|
|
33
|
+
console.log(chalk.dim(' --limit=<n> max recordings (default 100, max 500)'));
|
|
34
|
+
};
|
|
35
|
+
const parseFlags = (args) => {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const a of args) {
|
|
38
|
+
const m = /^--([\w-]+)(?:=(.*))?$/.exec(a);
|
|
39
|
+
if (!m)
|
|
40
|
+
continue;
|
|
41
|
+
out[m[1]] = m[2] ?? 'true';
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
};
|
|
45
|
+
const showStatus = async (slug) => {
|
|
46
|
+
const res = await api(`/cli/projects/${slug}/echo`);
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
const data = await safeJson(res);
|
|
49
|
+
console.log(chalk.red(`> ${data.error ?? 'failed to load echo status.'}`));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const data = (await res.json());
|
|
53
|
+
const dot = data.enabled ? chalk.green('●') : chalk.dim('○');
|
|
54
|
+
console.log(`${dot} echo ${data.enabled ? chalk.green('on') : chalk.dim('off')}`);
|
|
55
|
+
console.log(chalk.dim(' retention ') +
|
|
56
|
+
`${data.retentionDays}d ${data.retentionDays === 30 ? chalk.dim('(max)') : ''}`);
|
|
57
|
+
console.log(chalk.dim(' recordings ') +
|
|
58
|
+
`${data.usage.recordings.current.toLocaleString()} / ${data.usage.recordings.limit.toLocaleString()} this month`);
|
|
59
|
+
console.log(chalk.dim(' replays ') +
|
|
60
|
+
`${data.usage.replays.current.toLocaleString()} / ${data.usage.replays.limit.toLocaleString()} this month`);
|
|
61
|
+
if (data.routes.length === 0) {
|
|
62
|
+
console.log();
|
|
63
|
+
console.log(chalk.dim(' no routes recorded in the last 24h.'));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log();
|
|
67
|
+
console.log(chalk.dim(' routes (last 24h):'));
|
|
68
|
+
for (const r of data.routes) {
|
|
69
|
+
const ok = chalk.green(`${r.okCount} ok`);
|
|
70
|
+
const err = r.errCount > 0 ? chalk.red(` ${r.errCount} err`) : '';
|
|
71
|
+
console.log(` ${r.routeSignature.padEnd(40)} ${ok}${err}`);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const setEnabled = async (slug, enabled) => {
|
|
75
|
+
const res = await api(`/cli/projects/${slug}/echo`, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
body: JSON.stringify({ enabled }),
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
const data = await safeJson(res);
|
|
81
|
+
console.log(chalk.red(`> ${data.error ?? 'failed.'}`));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
if (enabled) {
|
|
85
|
+
console.log(chalk.green('> recording on.'));
|
|
86
|
+
console.log(chalk.dim(' capturing up to 10k requests/month, retained 7 days.'));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log(chalk.dim('> recording off. existing recordings stay until expiry.'));
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
93
|
+
const formatProgressLine = (p) => {
|
|
94
|
+
const total = p.counts.identical + p.counts.tolerated + p.counts.breaking + p.counts.inconclusive;
|
|
95
|
+
const pct = p.recordingCount > 0 ? Math.round((total / p.recordingCount) * 100) : 0;
|
|
96
|
+
return ` ${total}/${p.recordingCount} (${pct}%) ${chalk.green(p.counts.identical + ' ok')} ${chalk.cyan(p.counts.tolerated + ' tol')} ${chalk.red(p.counts.breaking + ' break')} ${chalk.yellow(p.counts.inconclusive + ' incl')}`;
|
|
97
|
+
};
|
|
98
|
+
const runReplayCmd = async (slug, flags) => {
|
|
99
|
+
const target = flags.target;
|
|
100
|
+
if (!target) {
|
|
101
|
+
console.log(chalk.red('> --target=<url> is required.'));
|
|
102
|
+
console.log(chalk.dim(' e.g. --target=https://') + chalk.cyan(`fix-checkout-${slug}.preview.pushto.host`));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
const isProd = (() => {
|
|
106
|
+
try {
|
|
107
|
+
return new URL(target).hostname.toLowerCase() === `${slug}.pushto.host`;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
})();
|
|
113
|
+
if (isProd) {
|
|
114
|
+
console.log(chalk.yellow('> heads up — that target is your production deploy.'));
|
|
115
|
+
console.log(chalk.dim(' any mutating request will mutate prod data. add an ') +
|
|
116
|
+
chalk.cyan('x-pushto-replay') +
|
|
117
|
+
chalk.dim(' check on your server to no-op writes.'));
|
|
118
|
+
console.log(chalk.dim(` type "${slug}" and press enter to confirm:`));
|
|
119
|
+
const typed = await readLine();
|
|
120
|
+
if (typed.trim() !== slug) {
|
|
121
|
+
console.log(chalk.red('> aborted.'));
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const startBody = { target };
|
|
126
|
+
if (flags.label)
|
|
127
|
+
startBody.label = flags.label;
|
|
128
|
+
if (flags.since)
|
|
129
|
+
startBody.since = flags.since;
|
|
130
|
+
if (flags.route)
|
|
131
|
+
startBody.route = flags.route;
|
|
132
|
+
if (flags.status)
|
|
133
|
+
startBody.status = Number(flags.status);
|
|
134
|
+
if (flags.limit)
|
|
135
|
+
startBody.limit = Number(flags.limit);
|
|
136
|
+
const startRes = await api(`/cli/projects/${slug}/echo/replay`, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
body: JSON.stringify(startBody),
|
|
139
|
+
});
|
|
140
|
+
if (!startRes.ok) {
|
|
141
|
+
const data = await safeJson(startRes);
|
|
142
|
+
console.log(chalk.red(`> ${data.error ?? 'replay start failed.'}`));
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
const start = (await startRes.json());
|
|
146
|
+
console.log(chalk.dim(`> replaying ${start.recordingCount} recordings against ${target}`));
|
|
147
|
+
const startedAt = Date.now();
|
|
148
|
+
const TIMEOUT_MS = 5 * 60 * 1000;
|
|
149
|
+
let done = false;
|
|
150
|
+
let last = null;
|
|
151
|
+
while (!done) {
|
|
152
|
+
if (Date.now() - startedAt > TIMEOUT_MS) {
|
|
153
|
+
console.log(chalk.red('> giving up — replay still running after 5 minutes.'));
|
|
154
|
+
console.log(chalk.dim(` check the dashboard or rerun: pushto echo replay --target=${target}`));
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
await sleep(2_000);
|
|
158
|
+
const r = await api(`/cli/projects/${slug}/echo/replay/${start.replayId}`);
|
|
159
|
+
if (!r.ok)
|
|
160
|
+
continue;
|
|
161
|
+
last = (await r.json());
|
|
162
|
+
process.stdout.write('\r' + formatProgressLine(last) + ' ');
|
|
163
|
+
if (last.replayStatus === 'COMPLETED' || last.replayStatus === 'FAILED') {
|
|
164
|
+
done = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
process.stdout.write('\n');
|
|
168
|
+
if (!last)
|
|
169
|
+
return;
|
|
170
|
+
if (last.replayStatus === 'FAILED') {
|
|
171
|
+
console.log(chalk.red(`> replay failed: ${last.failureReason ?? 'unknown error'}`));
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
console.log();
|
|
175
|
+
console.log(` ${chalk.green('✓')} ${last.counts.identical} identical`);
|
|
176
|
+
if (last.counts.tolerated > 0) {
|
|
177
|
+
console.log(` ${chalk.cyan('~')} ${last.counts.tolerated} tolerated diffs`);
|
|
178
|
+
}
|
|
179
|
+
console.log(` ${chalk.red('✗')} ${last.counts.breaking} breaking`);
|
|
180
|
+
console.log(` ${chalk.yellow('!')} ${last.counts.inconclusive} inconclusive`);
|
|
181
|
+
if (last.breakingExamples.length > 0) {
|
|
182
|
+
console.log();
|
|
183
|
+
console.log(chalk.dim(' breaking examples:'));
|
|
184
|
+
for (const ex of last.breakingExamples) {
|
|
185
|
+
const reasons = (ex.reasons ?? []).slice(0, 1).join('; ');
|
|
186
|
+
const arrow = ex.replayStatus !== null ? `${ex.recordedStatus} → ${ex.replayStatus}` : `${ex.recordedStatus}`;
|
|
187
|
+
console.log(` ${chalk.red(arrow)} ${chalk.dim(reasons)}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
console.log();
|
|
191
|
+
console.log(chalk.dim(` full report: https://pushto.host/dashboard/projects/${slug}/echo`));
|
|
192
|
+
if (last.counts.breaking > 0)
|
|
193
|
+
process.exit(1);
|
|
194
|
+
};
|
|
195
|
+
const readLine = () => new Promise((resolve) => {
|
|
196
|
+
let buf = '';
|
|
197
|
+
process.stdin.setEncoding('utf8');
|
|
198
|
+
const onData = (chunk) => {
|
|
199
|
+
buf += chunk;
|
|
200
|
+
const nl = buf.indexOf('\n');
|
|
201
|
+
if (nl >= 0) {
|
|
202
|
+
process.stdin.off('data', onData);
|
|
203
|
+
process.stdin.pause();
|
|
204
|
+
resolve(buf.slice(0, nl).replace(/\r$/, ''));
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
process.stdin.resume();
|
|
208
|
+
process.stdin.on('data', onData);
|
|
209
|
+
});
|
|
210
|
+
export const echo = async (action, args) => {
|
|
211
|
+
if (!action || action === 'help')
|
|
212
|
+
return usage();
|
|
213
|
+
const slug = ensureAuthed();
|
|
214
|
+
const flags = parseFlags(args);
|
|
215
|
+
if (action === 'status')
|
|
216
|
+
return showStatus(slug);
|
|
217
|
+
if (action === 'on')
|
|
218
|
+
return setEnabled(slug, true);
|
|
219
|
+
if (action === 'off')
|
|
220
|
+
return setEnabled(slug, false);
|
|
221
|
+
if (action === 'replay')
|
|
222
|
+
return runReplayCmd(slug, flags);
|
|
223
|
+
console.log(chalk.red(`> unknown action: ${action}`));
|
|
224
|
+
usage();
|
|
225
|
+
process.exit(1);
|
|
226
|
+
};
|
|
227
|
+
//# sourceMappingURL=echo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"echo.js","sourceRoot":"","sources":["../../src/commands/echo.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/env.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,GAAG,GACd,QAAQ,MAAM,EACd,MAAM,MAAM,EAAE,EACd,OAAM;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,KAC5B,OAAO,CAAC,IAAI,CAwMd,CAAC"}
|
package/dist/commands/env.js
CHANGED
|
@@ -5,31 +5,36 @@ import { getToken } from '../lib/config.js';
|
|
|
5
5
|
import { resolveSlug } from '../lib/resolve-slug.js';
|
|
6
6
|
import { api } from '../lib/api.js';
|
|
7
7
|
import { safeJson } from '../lib/safe-json.js';
|
|
8
|
-
|
|
8
|
+
import { parseEnvContent } from '../lib/env-parse.js';
|
|
9
|
+
import { fail, emitOk, emitErr } from '../lib/output.js';
|
|
10
|
+
import { buildError, exitCodeFor } from '../lib/errors.js';
|
|
11
|
+
export const env = async (action, args, opts = {}) => {
|
|
9
12
|
const token = getToken();
|
|
10
13
|
if (!token) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
fail('NOT_AUTHENTICATED', 'not logged in.', opts, {
|
|
15
|
+
stage: 'auth',
|
|
16
|
+
fix: { label: 'sign in', cmd: 'pushto login', prose: 'run {cmd} first.' },
|
|
17
|
+
});
|
|
14
18
|
}
|
|
15
19
|
const slug = resolveSlug();
|
|
16
20
|
if (!slug) {
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
// This command's copy puts the fix INSIDE the sentence, unlike status.ts
|
|
22
|
+
// which uses a second line. `human` carries it whole and no `fix` is
|
|
23
|
+
// attached, so the rendered line stays byte-identical. Agents still get
|
|
24
|
+
// the actionable part from `code: NO_PROJECT`.
|
|
25
|
+
fail('NO_PROJECT', 'no project here. run pushto init first.', opts);
|
|
19
26
|
}
|
|
20
27
|
if (action === 'set') {
|
|
21
28
|
// pushto env set KEY=value
|
|
22
29
|
const pair = args[0];
|
|
23
30
|
if (!pair || !pair.includes('=')) {
|
|
24
|
-
|
|
25
|
-
process.exit(1);
|
|
31
|
+
fail('BAD_USAGE', 'usage: pushto env set KEY=value', opts);
|
|
26
32
|
}
|
|
27
33
|
const eqIdx = pair.indexOf('=');
|
|
28
34
|
const key = pair.slice(0, eqIdx);
|
|
29
35
|
const value = pair.slice(eqIdx + 1);
|
|
30
36
|
if (!key) {
|
|
31
|
-
|
|
32
|
-
process.exit(1);
|
|
37
|
+
fail('INVALID_ENV_KEY', 'key is empty.', opts);
|
|
33
38
|
}
|
|
34
39
|
// Call the tRPC mutation via REST-like endpoint
|
|
35
40
|
// We'll use a simple CLI API endpoint for this
|
|
@@ -39,20 +44,30 @@ export const env = async (action, args) => {
|
|
|
39
44
|
});
|
|
40
45
|
if (!res.ok) {
|
|
41
46
|
const data = (await safeJson(res));
|
|
42
|
-
|
|
43
|
-
process.exit(1);
|
|
47
|
+
fail('SERVER_ERROR', data.error ?? 'failed to set env var.', opts);
|
|
44
48
|
}
|
|
49
|
+
const setData = await safeJson(res);
|
|
45
50
|
console.log(chalk.green(`> ${key} set.`));
|
|
51
|
+
if (setData.warning) {
|
|
52
|
+
console.log(chalk.yellow(` ${setData.warning}`));
|
|
53
|
+
}
|
|
46
54
|
}
|
|
47
55
|
else if (action === 'list' || action === 'ls') {
|
|
48
56
|
// pushto env list
|
|
49
57
|
const res = await api(`/cli/projects/${slug}/env`);
|
|
50
58
|
if (!res.ok) {
|
|
51
59
|
const data = (await safeJson(res));
|
|
52
|
-
|
|
53
|
-
process.exit(1);
|
|
60
|
+
fail('SERVER_ERROR', data.error ?? 'failed to list env vars.', opts);
|
|
54
61
|
}
|
|
55
62
|
const vars = await safeJson(res);
|
|
63
|
+
// Values are masked in the human table; the machine payload carries keys
|
|
64
|
+
// only for the same reason, so `--json` is not a secrets exfiltration
|
|
65
|
+
// path that the visible output would never permit. `pushto env pull`
|
|
66
|
+
// stays the deliberate way to get values onto disk.
|
|
67
|
+
if (opts.json) {
|
|
68
|
+
emitOk({ project: slug, vars: vars.map((v) => ({ key: v.key })) }, opts);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
56
71
|
if (vars.length === 0) {
|
|
57
72
|
console.log(chalk.dim('> no env vars set.'));
|
|
58
73
|
return;
|
|
@@ -68,8 +83,7 @@ export const env = async (action, args) => {
|
|
|
68
83
|
const res = await api(`/cli/projects/${slug}/env`);
|
|
69
84
|
if (!res.ok) {
|
|
70
85
|
const data = (await safeJson(res));
|
|
71
|
-
|
|
72
|
-
process.exit(1);
|
|
86
|
+
fail('SERVER_ERROR', data.error ?? 'failed to pull env vars.', opts);
|
|
73
87
|
}
|
|
74
88
|
const vars = await safeJson(res);
|
|
75
89
|
if (vars.length === 0) {
|
|
@@ -83,50 +97,59 @@ export const env = async (action, args) => {
|
|
|
83
97
|
console.log(chalk.dim(' make sure .env is in your .gitignore.'));
|
|
84
98
|
}
|
|
85
99
|
else if (action === 'push') {
|
|
86
|
-
// pushto env push — upload local .env to project
|
|
100
|
+
// pushto env push — upload local .env to project in ONE bulk request.
|
|
101
|
+
// Pre-fix this looped a POST per var, and every POST restarts the
|
|
102
|
+
// container — a 50-var .env restarted the user's app 50 times in a row.
|
|
87
103
|
const envFile = args[0] || '.env';
|
|
88
104
|
const envPath = path.join(process.cwd(), envFile);
|
|
89
105
|
if (!fs.existsSync(envPath)) {
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
fail('NO_FILES', `${envFile} not found in this directory.`, opts, {
|
|
107
|
+
details: { file: envFile },
|
|
108
|
+
});
|
|
92
109
|
}
|
|
93
110
|
const content = fs.readFileSync(envPath, 'utf-8');
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
value = value.slice(1, -1);
|
|
108
|
-
}
|
|
109
|
-
if (!key)
|
|
110
|
-
continue;
|
|
111
|
-
const res = await api(`/cli/projects/${slug}/env`, {
|
|
112
|
-
method: 'POST',
|
|
113
|
-
body: JSON.stringify({ key, value }),
|
|
114
|
-
});
|
|
115
|
-
if (res.ok) {
|
|
116
|
-
count++;
|
|
117
|
-
console.log(chalk.dim(` ${key} ✓`));
|
|
111
|
+
const { vars, skipped: localSkipped } = parseEnvContent(content);
|
|
112
|
+
if (Object.keys(vars).length === 0) {
|
|
113
|
+
// Not fail(), because that exits immediately and the original prints
|
|
114
|
+
// the headline BEFORE the per-key reasons. emitErr keeps that order;
|
|
115
|
+
// the exit code is still derived, never hand-picked. The reasons are
|
|
116
|
+
// the actionable part, so machines get them as `details`.
|
|
117
|
+
emitErr(buildError('INVALID_ENV_KEY', `no usable KEY=value pairs in ${envFile}.`, {
|
|
118
|
+
details: { file: envFile, skipped: localSkipped },
|
|
119
|
+
}), opts);
|
|
120
|
+
if (!opts.json) {
|
|
121
|
+
for (const s of localSkipped) {
|
|
122
|
+
console.log(chalk.dim(` ${s.key}: ${s.reason}`));
|
|
123
|
+
}
|
|
118
124
|
}
|
|
119
|
-
|
|
120
|
-
|
|
125
|
+
process.exit(exitCodeFor('INVALID_ENV_KEY'));
|
|
126
|
+
}
|
|
127
|
+
const res = await api(`/cli/projects/${slug}/env`, {
|
|
128
|
+
method: 'PUT',
|
|
129
|
+
body: JSON.stringify({ vars }),
|
|
130
|
+
});
|
|
131
|
+
if (!res.ok) {
|
|
132
|
+
const data = await safeJson(res);
|
|
133
|
+
fail('SERVER_ERROR', data.error ?? 'failed to push env vars.', opts);
|
|
134
|
+
}
|
|
135
|
+
const pushData = await safeJson(res);
|
|
136
|
+
const imported = pushData.imported ?? 0;
|
|
137
|
+
const skipped = [...localSkipped, ...(pushData.skipped ?? [])];
|
|
138
|
+
console.log(chalk.green(`> pushed ${imported} var${imported !== 1 ? 's' : ''} from ${envFile}`));
|
|
139
|
+
if (skipped.length > 0) {
|
|
140
|
+
console.log(chalk.yellow(` ${skipped.length} skipped:`));
|
|
141
|
+
for (const s of skipped) {
|
|
142
|
+
console.log(chalk.dim(` ${s.key}: ${s.reason}`));
|
|
121
143
|
}
|
|
122
144
|
}
|
|
123
|
-
|
|
145
|
+
if (pushData.warning) {
|
|
146
|
+
console.log(chalk.yellow(` ${pushData.warning}`));
|
|
147
|
+
}
|
|
124
148
|
}
|
|
125
149
|
else if (action === 'rm' || action === 'remove' || action === 'delete') {
|
|
126
150
|
const key = args[0];
|
|
127
151
|
if (!key) {
|
|
128
|
-
|
|
129
|
-
process.exit(1);
|
|
152
|
+
fail('BAD_USAGE', 'usage: pushto env rm KEY', opts);
|
|
130
153
|
}
|
|
131
154
|
const res = await api(`/cli/projects/${slug}/env`, {
|
|
132
155
|
method: 'DELETE',
|
|
@@ -134,10 +157,13 @@ export const env = async (action, args) => {
|
|
|
134
157
|
});
|
|
135
158
|
if (!res.ok) {
|
|
136
159
|
const data = (await safeJson(res));
|
|
137
|
-
|
|
138
|
-
process.exit(1);
|
|
160
|
+
fail('SERVER_ERROR', data.error ?? 'failed to delete env var.', opts);
|
|
139
161
|
}
|
|
162
|
+
const rmData = await safeJson(res);
|
|
140
163
|
console.log(chalk.green(`> ${key} removed.`));
|
|
164
|
+
if (rmData.warning) {
|
|
165
|
+
console.log(chalk.yellow(` ${rmData.warning}`));
|
|
166
|
+
}
|
|
141
167
|
}
|
|
142
168
|
else {
|
|
143
169
|
console.log(chalk.dim(' usage:'));
|