@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-runner.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/build-runner.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { runStaticBuild, writeArtifactMeta, ARTIFACT_META_NAME } from '../build-runner.js';
|
|
6
|
+
let dir;
|
|
7
|
+
beforeEach(() => { dir = fs.mkdtempSync(path.join(os.tmpdir(), 'pushto-build-')); });
|
|
8
|
+
afterEach(() => { fs.rmSync(dir, { recursive: true, force: true }); });
|
|
9
|
+
const vite = { framework: 'vite', spa: true, outputDirs: ['dist'] };
|
|
10
|
+
const writePkg = (scripts) => {
|
|
11
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: 'fx', private: true, scripts }));
|
|
12
|
+
// node_modules present → the runner must NOT attempt an install
|
|
13
|
+
fs.mkdirSync(path.join(dir, 'node_modules'), { recursive: true });
|
|
14
|
+
};
|
|
15
|
+
/** A .bin shim so `npx --no-install <name>` and `npm run` resolve it. */
|
|
16
|
+
const writeShim = (name, exitCode, body) => {
|
|
17
|
+
const bin = path.join(dir, 'node_modules', '.bin');
|
|
18
|
+
fs.mkdirSync(bin, { recursive: true });
|
|
19
|
+
const file = path.join(bin, name);
|
|
20
|
+
fs.writeFileSync(file, `#!/bin/sh\n${body}\nexit ${exitCode}\n`);
|
|
21
|
+
fs.chmodSync(file, 0o755);
|
|
22
|
+
};
|
|
23
|
+
describe('runStaticBuild', () => {
|
|
24
|
+
it('runs the build script and resolves the expected output dir', async () => {
|
|
25
|
+
writePkg({ build: 'node -e "require(\'fs\').mkdirSync(\'dist\',{recursive:true});require(\'fs\').writeFileSync(\'dist/index.html\',\'hi\')"' });
|
|
26
|
+
const r = await runStaticBuild(dir, vite);
|
|
27
|
+
expect(r).toEqual({ ok: true, outputDir: path.join(dir, 'dist'), typeWarnings: null });
|
|
28
|
+
});
|
|
29
|
+
it('fails honestly when the build script fails (custom script, no fallback)', async () => {
|
|
30
|
+
writePkg({ build: 'node -e "console.error(\'boom\');process.exit(1)"' });
|
|
31
|
+
const r = await runStaticBuild(dir, vite);
|
|
32
|
+
expect(r.ok).toBe(false);
|
|
33
|
+
if (!r.ok)
|
|
34
|
+
expect(r.buildOutput).toContain('boom');
|
|
35
|
+
});
|
|
36
|
+
it('fails honestly when the build produces no index.html anywhere', async () => {
|
|
37
|
+
writePkg({ build: 'node -e "require(\'fs\').mkdirSync(\'dist\',{recursive:true})"' });
|
|
38
|
+
const r = await runStaticBuild(dir, vite);
|
|
39
|
+
expect(r.ok).toBe(false);
|
|
40
|
+
if (!r.ok)
|
|
41
|
+
expect(r.message).toContain('index.html');
|
|
42
|
+
});
|
|
43
|
+
it('fails with a named fix when there is no build script', async () => {
|
|
44
|
+
writePkg({});
|
|
45
|
+
const r = await runStaticBuild(dir, vite);
|
|
46
|
+
expect(r.ok).toBe(false);
|
|
47
|
+
if (!r.ok)
|
|
48
|
+
expect(r.message).toContain('build');
|
|
49
|
+
});
|
|
50
|
+
it('build script suggestion for angular uses ng build, not angular build', async () => {
|
|
51
|
+
const angular = { framework: 'angular', spa: true, outputDirs: ['dist/x/browser'] };
|
|
52
|
+
writePkg({});
|
|
53
|
+
const r = await runStaticBuild(dir, angular);
|
|
54
|
+
expect(r.ok).toBe(false);
|
|
55
|
+
if (!r.ok) {
|
|
56
|
+
expect(r.message).toContain('ng build');
|
|
57
|
+
expect(r.message).not.toContain('angular build');
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
it('stock `tsc -b && vite build` shape: tsc fails → retries vite build alone, ships, carries type warnings', async () => {
|
|
61
|
+
writePkg({ build: 'tsc -b && vite build' });
|
|
62
|
+
writeShim('tsc', 2, 'echo "src/App.tsx(3,7): error TS2322" 1>&2');
|
|
63
|
+
writeShim('vite', 0, 'mkdir -p dist && echo hi > dist/index.html');
|
|
64
|
+
const r = await runStaticBuild(dir, vite);
|
|
65
|
+
expect(r.ok).toBe(true);
|
|
66
|
+
if (r.ok) {
|
|
67
|
+
expect(r.outputDir).toBe(path.join(dir, 'dist'));
|
|
68
|
+
expect(r.typeWarnings).toContain('TS2322');
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
it('custom script containing tsc is NOT second-guessed', async () => {
|
|
72
|
+
writePkg({ build: 'tsc -b && vite build && node gen-sitemap.js' });
|
|
73
|
+
writeShim('tsc', 2, 'echo "error TS2322" 1>&2');
|
|
74
|
+
writeShim('vite', 0, 'mkdir -p dist && echo hi > dist/index.html');
|
|
75
|
+
const r = await runStaticBuild(dir, vite);
|
|
76
|
+
expect(r.ok).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
it('falls back to scanning conventional dirs when the expected dir is empty', async () => {
|
|
79
|
+
writePkg({ build: 'node -e "require(\'fs\').mkdirSync(\'build\',{recursive:true});require(\'fs\').writeFileSync(\'build/index.html\',\'hi\')"' });
|
|
80
|
+
const r = await runStaticBuild(dir, vite); // expected dist, actual build/
|
|
81
|
+
expect(r.ok).toBe(true);
|
|
82
|
+
if (r.ok)
|
|
83
|
+
expect(r.outputDir).toBe(path.join(dir, 'build'));
|
|
84
|
+
});
|
|
85
|
+
it('stale output is not trusted: pre-existing dist without a fresh build fails', async () => {
|
|
86
|
+
fs.mkdirSync(path.join(dir, 'dist'), { recursive: true });
|
|
87
|
+
fs.writeFileSync(path.join(dir, 'dist', 'index.html'), 'stale');
|
|
88
|
+
// Backdate the stale file so mtime-based freshness sees it as old.
|
|
89
|
+
const old = new Date(Date.now() - 60 * 60 * 1000);
|
|
90
|
+
fs.utimesSync(path.join(dir, 'dist', 'index.html'), old, old);
|
|
91
|
+
writePkg({ build: 'node -e "process.exit(1)"' });
|
|
92
|
+
const r = await runStaticBuild(dir, vite);
|
|
93
|
+
expect(r.ok).toBe(false); // build failed → NEVER ship the stale dir
|
|
94
|
+
});
|
|
95
|
+
it('a successful build with ONLY stale output fails honestly (mtime guard)', async () => {
|
|
96
|
+
fs.mkdirSync(path.join(dir, 'dist'), { recursive: true });
|
|
97
|
+
fs.writeFileSync(path.join(dir, 'dist', 'index.html'), 'stale');
|
|
98
|
+
const old = new Date(Date.now() - 60 * 60 * 1000);
|
|
99
|
+
fs.utimesSync(path.join(dir, 'dist', 'index.html'), old, old);
|
|
100
|
+
fs.utimesSync(path.join(dir, 'dist'), old, old);
|
|
101
|
+
writePkg({ build: 'node -e "process.exit(0)"' }); // succeeds, writes nothing
|
|
102
|
+
const r = await runStaticBuild(dir, vite);
|
|
103
|
+
expect(r.ok).toBe(false); // stale dist/index.html must NOT be shipped
|
|
104
|
+
if (!r.ok)
|
|
105
|
+
expect(r.message).toContain('no fresh index.html');
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('writeArtifactMeta', () => {
|
|
109
|
+
it('writes the marker and cleanup removes it', () => {
|
|
110
|
+
const out = path.join(dir, 'dist');
|
|
111
|
+
fs.mkdirSync(out, { recursive: true });
|
|
112
|
+
const cleanup = writeArtifactMeta(out, { framework: 'vite', spa: true });
|
|
113
|
+
const metaPath = path.join(out, ARTIFACT_META_NAME);
|
|
114
|
+
expect(JSON.parse(fs.readFileSync(metaPath, 'utf-8'))).toMatchObject({ framework: 'vite', spa: true });
|
|
115
|
+
cleanup();
|
|
116
|
+
expect(fs.existsSync(metaPath)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
//# sourceMappingURL=build-runner.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-runner.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/build-runner.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-tail.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/cron-tail.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { selectNewExecutions } from '../cron-tail.js';
|
|
3
|
+
// `pushto cron tail` follows a job live (the docs promise "watch a run's
|
|
4
|
+
// output live" — pre-fix it was a one-shot fetch). The follow loop polls
|
|
5
|
+
// the history endpoint, which returns newest-first; the tail must print
|
|
6
|
+
// only unseen rows, oldest-first, like tail -f.
|
|
7
|
+
const exec = (id, at) => ({ id, executedAt: at });
|
|
8
|
+
describe('selectNewExecutions', () => {
|
|
9
|
+
it('returns only rows not yet seen', () => {
|
|
10
|
+
const seen = new Set(['e1']);
|
|
11
|
+
const out = selectNewExecutions(seen, [exec('e2', '2026-07-19T00:01:00Z'), exec('e1', '2026-07-19T00:00:00Z')]);
|
|
12
|
+
expect(out.map((e) => e.id)).toEqual(['e2']);
|
|
13
|
+
});
|
|
14
|
+
it('orders fresh rows oldest-first for printing', () => {
|
|
15
|
+
const out = selectNewExecutions(new Set(), [
|
|
16
|
+
exec('e3', '2026-07-19T00:03:00Z'),
|
|
17
|
+
exec('e2', '2026-07-19T00:02:00Z'),
|
|
18
|
+
exec('e1', '2026-07-19T00:01:00Z'),
|
|
19
|
+
]);
|
|
20
|
+
expect(out.map((e) => e.id)).toEqual(['e1', 'e2', 'e3']);
|
|
21
|
+
});
|
|
22
|
+
it('returns nothing when everything is seen', () => {
|
|
23
|
+
const seen = new Set(['e1', 'e2']);
|
|
24
|
+
expect(selectNewExecutions(seen, [exec('e1', '2026-07-19T00:00:00Z'), exec('e2', '2026-07-19T00:01:00Z')])).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=cron-tail.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-tail.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/cron-tail.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,yEAAyE;AACzE,yEAAyE;AACzE,wEAAwE;AACxE,gDAAgD;AAEhD,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;AAElE,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAChH,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,GAAG,EAAE,EAAE;YACzC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC;YAClC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC;YAClC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC;SACnC,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACnC,MAAM,CACJ,mBAAmB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC,CACpG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-static-framework.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/detect-static-framework.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { detectStaticFramework } from '../detect-static-framework.js';
|
|
6
|
+
let dir;
|
|
7
|
+
beforeEach(() => { dir = fs.mkdtempSync(path.join(os.tmpdir(), 'pushto-detect-')); });
|
|
8
|
+
afterEach(() => { fs.rmSync(dir, { recursive: true, force: true }); });
|
|
9
|
+
const writePkg = (pkg) => {
|
|
10
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify(pkg));
|
|
11
|
+
};
|
|
12
|
+
describe('detectStaticFramework', () => {
|
|
13
|
+
it('detects a stock vite scaffold (no start script) as vite, spa', () => {
|
|
14
|
+
writePkg({ devDependencies: { vite: '^5.0.0' }, scripts: { dev: 'vite', build: 'tsc -b && vite build', preview: 'vite preview' } });
|
|
15
|
+
const d = detectStaticFramework(dir);
|
|
16
|
+
expect(d).toEqual({ framework: 'vite', spa: true, outputDirs: ['dist'] });
|
|
17
|
+
});
|
|
18
|
+
it('detects vite via config file when the dep is indirect', () => {
|
|
19
|
+
writePkg({ scripts: { build: 'vite build' } });
|
|
20
|
+
fs.writeFileSync(path.join(dir, 'vite.config.ts'), 'export default {}');
|
|
21
|
+
expect(detectStaticFramework(dir)?.framework).toBe('vite');
|
|
22
|
+
});
|
|
23
|
+
it('start script wins: vite + start stays dynamic (null)', () => {
|
|
24
|
+
writePkg({ dependencies: { vite: '^5.0.0', express: '^4.0.0' }, scripts: { build: 'vite build', start: 'node server.js' } });
|
|
25
|
+
expect(detectStaticFramework(dir)).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
it('SSR frameworks are never static-build: next/nuxt/sveltekit/remix/solidstart', () => {
|
|
28
|
+
for (const deps of [
|
|
29
|
+
{ next: '1' }, { nuxt: '1' }, { '@sveltejs/kit': '1' },
|
|
30
|
+
{ '@remix-run/node': '1' }, { '@remix-run/dev': '1' }, { '@solidjs/start': '1' },
|
|
31
|
+
]) {
|
|
32
|
+
writePkg({ dependencies: { ...deps, vite: '^5.0.0' }, scripts: { build: 'x' } });
|
|
33
|
+
expect(detectStaticFramework(dir)).toBeNull();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
it('specific frameworks beat the vite catch-all', () => {
|
|
37
|
+
writePkg({ dependencies: { astro: '^4.0.0' }, scripts: { build: 'astro build' } });
|
|
38
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'astro', spa: false, outputDirs: ['dist'] });
|
|
39
|
+
});
|
|
40
|
+
it('detects gatsby (public/), cra (build/), eleventy (_site/)', () => {
|
|
41
|
+
writePkg({ dependencies: { gatsby: '^5.0.0' }, scripts: { build: 'gatsby build' } });
|
|
42
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'gatsby', spa: false, outputDirs: ['public'] });
|
|
43
|
+
writePkg({ dependencies: { 'react-scripts': '^5.0.0' }, scripts: { build: 'react-scripts build' } });
|
|
44
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'cra', spa: true, outputDirs: ['build'] });
|
|
45
|
+
writePkg({ devDependencies: { '@11ty/eleventy': '^2.0.0' }, scripts: { build: 'eleventy' } });
|
|
46
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'eleventy', spa: false, outputDirs: ['_site'] });
|
|
47
|
+
});
|
|
48
|
+
it('angular: expands output candidates from angular.json outputPath', () => {
|
|
49
|
+
writePkg({ dependencies: { '@angular/core': '^17.0.0' }, scripts: { build: 'ng build' } });
|
|
50
|
+
fs.writeFileSync(path.join(dir, 'angular.json'), JSON.stringify({
|
|
51
|
+
projects: { 'my-app': { architect: { build: { options: { outputPath: 'dist/my-app' } } } } },
|
|
52
|
+
}));
|
|
53
|
+
expect(detectStaticFramework(dir)).toEqual({
|
|
54
|
+
framework: 'angular', spa: true,
|
|
55
|
+
outputDirs: ['dist/my-app/browser', 'dist/my-app'],
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
it('angular: falls back to dist/<projectName>/browser when outputPath absent', () => {
|
|
59
|
+
writePkg({ dependencies: { '@angular/core': '^17.0.0' }, scripts: { build: 'ng build' } });
|
|
60
|
+
fs.writeFileSync(path.join(dir, 'angular.json'), JSON.stringify({
|
|
61
|
+
projects: { 'my-app': { architect: { build: { options: {} } } } },
|
|
62
|
+
}));
|
|
63
|
+
expect(detectStaticFramework(dir)?.outputDirs).toEqual(['dist/my-app/browser', 'dist/my-app']);
|
|
64
|
+
});
|
|
65
|
+
it('no package.json → null; malformed package.json → null', () => {
|
|
66
|
+
expect(detectStaticFramework(dir)).toBeNull();
|
|
67
|
+
fs.writeFileSync(path.join(dir, 'package.json'), '{nope');
|
|
68
|
+
expect(detectStaticFramework(dir)).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('detectStaticFramework — stock dev-server start scripts do not defeat detection', () => {
|
|
72
|
+
// Stock scaffolds ship a `start` script that runs the framework's OWN
|
|
73
|
+
// dev server, not an app server: CRA `react-scripts start`, Angular
|
|
74
|
+
// `ng serve`, Gatsby `gatsby develop`, Eleventy `eleventy --serve`. The
|
|
75
|
+
// old rule ("any start script means dynamic") routed every one of these
|
|
76
|
+
// past the static-build path even though none of them run a real server.
|
|
77
|
+
it('real CRA script block (react-scripts start/build/test/eject) is still detected as cra', () => {
|
|
78
|
+
writePkg({
|
|
79
|
+
dependencies: { 'react-scripts': '^5.0.0' },
|
|
80
|
+
scripts: {
|
|
81
|
+
start: 'react-scripts start',
|
|
82
|
+
build: 'react-scripts build',
|
|
83
|
+
test: 'react-scripts test',
|
|
84
|
+
eject: 'react-scripts eject',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'cra', spa: true, outputDirs: ['build'] });
|
|
88
|
+
});
|
|
89
|
+
it('real Angular script block (ng serve) is still detected as angular', () => {
|
|
90
|
+
writePkg({
|
|
91
|
+
dependencies: { '@angular/core': '^17.0.0' },
|
|
92
|
+
scripts: { ng: 'ng', start: 'ng serve', build: 'ng build' },
|
|
93
|
+
});
|
|
94
|
+
expect(detectStaticFramework(dir)?.framework).toBe('angular');
|
|
95
|
+
});
|
|
96
|
+
it('real Gatsby script block (gatsby develop) is still detected as gatsby', () => {
|
|
97
|
+
writePkg({
|
|
98
|
+
dependencies: { gatsby: '^5.0.0' },
|
|
99
|
+
scripts: { develop: 'gatsby develop', start: 'gatsby develop', build: 'gatsby build' },
|
|
100
|
+
});
|
|
101
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'gatsby', spa: false, outputDirs: ['public'] });
|
|
102
|
+
});
|
|
103
|
+
it('real Eleventy script block (eleventy --serve) is still detected as eleventy', () => {
|
|
104
|
+
writePkg({
|
|
105
|
+
devDependencies: { '@11ty/eleventy': '^2.0.0' },
|
|
106
|
+
scripts: { build: 'eleventy', start: 'eleventy --serve' },
|
|
107
|
+
});
|
|
108
|
+
expect(detectStaticFramework(dir)).toEqual({ framework: 'eleventy', spa: false, outputDirs: ['_site'] });
|
|
109
|
+
});
|
|
110
|
+
it('eleventy-base-blog real scaffold: npx-prefixed start script stays static-build', () => {
|
|
111
|
+
writePkg({
|
|
112
|
+
devDependencies: { '@11ty/eleventy': '^3.0.0' },
|
|
113
|
+
scripts: { build: 'npx @11ty/eleventy', start: 'npx @11ty/eleventy --serve --quiet' },
|
|
114
|
+
});
|
|
115
|
+
expect(detectStaticFramework(dir)?.framework).toBe('eleventy');
|
|
116
|
+
});
|
|
117
|
+
it('cra with a CUSTOM start script stays dynamic (null)', () => {
|
|
118
|
+
writePkg({
|
|
119
|
+
dependencies: { 'react-scripts': '^5.0.0' },
|
|
120
|
+
scripts: { start: 'node server.js', build: 'react-scripts build' },
|
|
121
|
+
});
|
|
122
|
+
expect(detectStaticFramework(dir)).toBeNull();
|
|
123
|
+
});
|
|
124
|
+
it('vite + start script that is just "vite preview" is still static-build (own dev server)', () => {
|
|
125
|
+
writePkg({
|
|
126
|
+
dependencies: { vite: '^5.0.0' },
|
|
127
|
+
scripts: { build: 'vite build', start: 'vite preview' },
|
|
128
|
+
});
|
|
129
|
+
expect(detectStaticFramework(dir)?.framework).toBe('vite');
|
|
130
|
+
});
|
|
131
|
+
it('vite + start script with extra flags still counts as the dev server (word-boundary match)', () => {
|
|
132
|
+
writePkg({
|
|
133
|
+
dependencies: { vite: '^5.0.0' },
|
|
134
|
+
scripts: { build: 'vite build', start: 'vite preview --port 4173' },
|
|
135
|
+
});
|
|
136
|
+
expect(detectStaticFramework(dir)?.framework).toBe('vite');
|
|
137
|
+
});
|
|
138
|
+
it('vite + a lookalike start script that only shares a prefix is NOT a word-boundary match (stays dynamic)', () => {
|
|
139
|
+
writePkg({
|
|
140
|
+
dependencies: { vite: '^5.0.0' },
|
|
141
|
+
scripts: { build: 'vite build', start: 'vite-custom-wrapper.js' },
|
|
142
|
+
});
|
|
143
|
+
expect(detectStaticFramework(dir)).toBeNull();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=detect-static-framework.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-static-framework.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/detect-static-framework.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/errors.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CODES, EXIT, exitCodeFor, isRetryable, buildError } from '../errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* PINs the exit-code contract that makes the CLI machine-consumable.
|
|
5
|
+
*
|
|
6
|
+
* Before this existed, 112 of the CLI's 113 process.exit() calls resolved
|
|
7
|
+
* to 1, so a caller reading $? could not tell "your repo is broken" from
|
|
8
|
+
* "our server blipped". The registry is closed and the band is DERIVED
|
|
9
|
+
* from the code precisely so no future call site gets to pick a number.
|
|
10
|
+
*
|
|
11
|
+
* The "never 1" assertion is the load-bearing one: 1 is reserved for
|
|
12
|
+
* genuinely unclassified failures, so any KNOWN code reaching it means
|
|
13
|
+
* someone added a code without deciding what it means.
|
|
14
|
+
*/
|
|
15
|
+
describe('exit code registry', () => {
|
|
16
|
+
it('derives a band for every registered code', () => {
|
|
17
|
+
for (const code of Object.keys(CODES)) {
|
|
18
|
+
expect(typeof exitCodeFor(code)).toBe('number');
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it('never maps a known code to the unclassified band', () => {
|
|
22
|
+
for (const code of Object.keys(CODES)) {
|
|
23
|
+
expect(exitCodeFor(code)).not.toBe(EXIT.UNCLASSIFIED);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
it('marks upstream failures retryable and local failures not', () => {
|
|
27
|
+
expect(isRetryable('NETWORK')).toBe(true);
|
|
28
|
+
expect(isRetryable('SERVER_ERROR')).toBe(true);
|
|
29
|
+
expect(isRetryable('ARTIFACT_TOO_LARGE')).toBe(false);
|
|
30
|
+
expect(isRetryable('NOT_AUTHENTICATED')).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it('puts auth at 10, local input at 30, quota at 50, upstream at 60', () => {
|
|
33
|
+
expect(exitCodeFor('NOT_AUTHENTICATED')).toBe(10);
|
|
34
|
+
expect(exitCodeFor('MISSING_ENTRYPOINT')).toBe(30);
|
|
35
|
+
expect(exitCodeFor('PAID_FEATURE')).toBe(50);
|
|
36
|
+
expect(exitCodeFor('NETWORK')).toBe(60);
|
|
37
|
+
});
|
|
38
|
+
it('builds an error carrying its own retryable bit', () => {
|
|
39
|
+
const err = buildError('NETWORK', "couldn't reach pushto.host.", {
|
|
40
|
+
fix: { label: 'try again', cmd: 'pushto deploy' },
|
|
41
|
+
});
|
|
42
|
+
expect(err).toEqual({
|
|
43
|
+
code: 'NETWORK',
|
|
44
|
+
human: "couldn't reach pushto.host.",
|
|
45
|
+
retryable: true,
|
|
46
|
+
fix: { label: 'try again', cmd: 'pushto deploy' },
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
it('omits optional keys it was not given', () => {
|
|
50
|
+
const err = buildError('NO_PROJECT', 'no project here.');
|
|
51
|
+
expect(err).toEqual({ code: 'NO_PROJECT', human: 'no project here.', retryable: false });
|
|
52
|
+
expect('fix' in err).toBe(false);
|
|
53
|
+
expect('stage' in err).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=errors.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/errors.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/interactive.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { canPrompt } from '../interactive.js';
|
|
3
|
+
/**
|
|
4
|
+
* PINs the rule that an agent gets correct behavior with ZERO flags.
|
|
5
|
+
*
|
|
6
|
+
* Requiring --yes would not have fixed the deploy hang, because an agent
|
|
7
|
+
* that has never read our docs does not know the flag exists. So prompting
|
|
8
|
+
* is RESOLVED from ambient state, and a flag can only ever turn it further
|
|
9
|
+
* off. Every branch below is a real way a machine invokes us.
|
|
10
|
+
*/
|
|
11
|
+
const orig = {
|
|
12
|
+
stdin: process.stdin.isTTY,
|
|
13
|
+
stdout: process.stdout.isTTY,
|
|
14
|
+
ci: process.env.CI,
|
|
15
|
+
ni: process.env.PUSHTO_NONINTERACTIVE,
|
|
16
|
+
};
|
|
17
|
+
const setTTY = (stdin, stdout) => {
|
|
18
|
+
Object.defineProperty(process.stdin, 'isTTY', { value: stdin, configurable: true });
|
|
19
|
+
Object.defineProperty(process.stdout, 'isTTY', { value: stdout, configurable: true });
|
|
20
|
+
};
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
setTTY(orig.stdin, orig.stdout);
|
|
23
|
+
if (orig.ci === undefined)
|
|
24
|
+
delete process.env.CI;
|
|
25
|
+
else
|
|
26
|
+
process.env.CI = orig.ci;
|
|
27
|
+
if (orig.ni === undefined)
|
|
28
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
29
|
+
else
|
|
30
|
+
process.env.PUSHTO_NONINTERACTIVE = orig.ni;
|
|
31
|
+
});
|
|
32
|
+
describe('canPrompt', () => {
|
|
33
|
+
it('allows prompting for a human on a full terminal', () => {
|
|
34
|
+
setTTY(true, true);
|
|
35
|
+
delete process.env.CI;
|
|
36
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
37
|
+
expect(canPrompt()).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
it('refuses when stdin is not a tty (the agent case)', () => {
|
|
40
|
+
setTTY(false, true);
|
|
41
|
+
delete process.env.CI;
|
|
42
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
43
|
+
expect(canPrompt()).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
it('refuses when stdout is piped', () => {
|
|
46
|
+
setTTY(true, false);
|
|
47
|
+
delete process.env.CI;
|
|
48
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
49
|
+
expect(canPrompt()).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
it('refuses under CI', () => {
|
|
52
|
+
setTTY(true, true);
|
|
53
|
+
process.env.CI = '1';
|
|
54
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
55
|
+
expect(canPrompt()).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
it('refuses under PUSHTO_NONINTERACTIVE', () => {
|
|
58
|
+
setTTY(true, true);
|
|
59
|
+
delete process.env.CI;
|
|
60
|
+
process.env.PUSHTO_NONINTERACTIVE = '1';
|
|
61
|
+
expect(canPrompt()).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it('refuses when --json or --yes was passed, even on a real terminal', () => {
|
|
64
|
+
setTTY(true, true);
|
|
65
|
+
delete process.env.CI;
|
|
66
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
67
|
+
expect(canPrompt({ json: true })).toBe(false);
|
|
68
|
+
expect(canPrompt({ yes: true })).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
it('treats CI="" and CI="false" as not set, matching shell convention', () => {
|
|
71
|
+
setTTY(true, true);
|
|
72
|
+
delete process.env.PUSHTO_NONINTERACTIVE;
|
|
73
|
+
process.env.CI = '';
|
|
74
|
+
expect(canPrompt()).toBe(true);
|
|
75
|
+
process.env.CI = 'false';
|
|
76
|
+
expect(canPrompt()).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=interactive.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/interactive.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/output.test.ts"],"names":[],"mappings":""}
|