@pushto/cli 0.2.1 → 0.4.9
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/cli.js +0 -0
- 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 +230 -150
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +289 -54
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/domain.d.ts.map +1 -1
- package/dist/commands/domain.js +52 -7
- 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 +50 -23
- 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 +21 -1
- 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 +117 -14
- 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__/npm-packaging.test.d.ts +2 -0
- package/dist/lib/__tests__/npm-packaging.test.d.ts.map +1 -0
- package/dist/lib/__tests__/npm-packaging.test.js +81 -0
- package/dist/lib/__tests__/npm-packaging.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.map +1 -1
- package/dist/lib/api.js +22 -4
- 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 +7 -1
- 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/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/cli.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-domain.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/deploy-domain.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { resolveCustomDomain } from '../deploy.js';
|
|
3
|
+
/**
|
|
4
|
+
* PINs the fix for the bug this whole spec exists for.
|
|
5
|
+
*
|
|
6
|
+
* deploy.ts awaited ask('custom domain? (enter to skip): ') whenever a
|
|
7
|
+
* project had no custom domain — true on the FIRST deploy of every new
|
|
8
|
+
* project, i.e. an agent's first contact with pushto. It could not fail
|
|
9
|
+
* safe: readline's callback never fires on EOF, so the promise never
|
|
10
|
+
* settled. Piped stdin hung to timeout; closed stdin hung forever; and the
|
|
11
|
+
* surrounding try/catch caught nothing, because hanging is not throwing.
|
|
12
|
+
*
|
|
13
|
+
* The assertion that matters is `expect(ask).not.toHaveBeenCalled()` — not
|
|
14
|
+
* that we resolved, but that we never reached for stdin at all.
|
|
15
|
+
*/
|
|
16
|
+
describe('resolveCustomDomain', () => {
|
|
17
|
+
it('never touches stdin when prompting is not allowed', async () => {
|
|
18
|
+
const ask = vi.fn();
|
|
19
|
+
const result = await resolveCustomDomain({ current: null, canPrompt: false, ask });
|
|
20
|
+
expect(result).toBeNull();
|
|
21
|
+
expect(ask).not.toHaveBeenCalled();
|
|
22
|
+
});
|
|
23
|
+
it('skips silently when a custom domain is already set', async () => {
|
|
24
|
+
const ask = vi.fn();
|
|
25
|
+
const result = await resolveCustomDomain({ current: 'x.com', canPrompt: true, ask });
|
|
26
|
+
expect(result).toBeNull();
|
|
27
|
+
expect(ask).not.toHaveBeenCalled();
|
|
28
|
+
});
|
|
29
|
+
it('asks a human on a real terminal and returns the answer', async () => {
|
|
30
|
+
const ask = vi.fn().mockResolvedValue('example.com');
|
|
31
|
+
const result = await resolveCustomDomain({ current: null, canPrompt: true, ask });
|
|
32
|
+
expect(result).toBe('example.com');
|
|
33
|
+
expect(ask).toHaveBeenCalledTimes(1);
|
|
34
|
+
});
|
|
35
|
+
it('treats an empty answer as skip, preserving "enter to skip"', async () => {
|
|
36
|
+
const ask = vi.fn().mockResolvedValue('');
|
|
37
|
+
const result = await resolveCustomDomain({ current: null, canPrompt: true, ask });
|
|
38
|
+
expect(result).toBeNull();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=deploy-domain.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-domain.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/deploy-domain.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;;;;;;;;;GAYG;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAkC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACnF,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAkC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAkC,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAkC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-smoke.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/headless-smoke.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import { spawn, execFile } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const CLI_ROOT = path.resolve(HERE, '../../..');
|
|
11
|
+
const REPO_ROOT = path.resolve(CLI_ROOT, '../..');
|
|
12
|
+
const ENTRY = path.join(CLI_ROOT, 'dist', 'cli.js');
|
|
13
|
+
const runHeadless = (args) => {
|
|
14
|
+
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'pushto-home-'));
|
|
15
|
+
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'pushto-cwd-'));
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const child = spawn(process.execPath, [ENTRY, ...args], {
|
|
18
|
+
cwd,
|
|
19
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
20
|
+
env: {
|
|
21
|
+
...process.env,
|
|
22
|
+
HOME: home,
|
|
23
|
+
USERPROFILE: home,
|
|
24
|
+
XDG_CONFIG_HOME: path.join(home, '.config'),
|
|
25
|
+
PUSHTO_TOKEN: '',
|
|
26
|
+
CI: '1',
|
|
27
|
+
PUSHTO_NONINTERACTIVE: '1',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
let stdout = '';
|
|
31
|
+
let stderr = '';
|
|
32
|
+
let timedOut = false;
|
|
33
|
+
child.stdout.on('data', (d) => { stdout += String(d); });
|
|
34
|
+
child.stderr.on('data', (d) => { stderr += String(d); });
|
|
35
|
+
const timer = setTimeout(() => { timedOut = true; child.kill('SIGKILL'); }, 10_000);
|
|
36
|
+
child.on('close', (code) => {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
resolve({ code, stdout, stderr, timedOut });
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
describe('headless cli', () => {
|
|
43
|
+
beforeAll(async () => {
|
|
44
|
+
await execFileAsync('pnpm', ['--filter', '@pushto/cli', 'build'], { cwd: REPO_ROOT });
|
|
45
|
+
}, 180_000);
|
|
46
|
+
it('exits instead of hanging when stdin is closed', async () => {
|
|
47
|
+
const res = await runHeadless(['deploy', '--json']);
|
|
48
|
+
expect(res.timedOut).toBe(false);
|
|
49
|
+
expect(res.code).not.toBeNull();
|
|
50
|
+
});
|
|
51
|
+
it('reports not-authenticated as one json object on stdout, exit 10', async () => {
|
|
52
|
+
const res = await runHeadless(['deploy', '--json']);
|
|
53
|
+
expect(res.code).toBe(10);
|
|
54
|
+
const parsed = JSON.parse(res.stdout);
|
|
55
|
+
expect(parsed.ok).toBe(false);
|
|
56
|
+
expect(parsed.error.code).toBe('NOT_AUTHENTICATED');
|
|
57
|
+
expect(parsed.retryable).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
it('keeps stdout free of update-check chatter in json mode', async () => {
|
|
60
|
+
const res = await runHeadless(['deploy', '--json']);
|
|
61
|
+
expect(res.stdout.trim().split('\n')).toHaveLength(1);
|
|
62
|
+
});
|
|
63
|
+
it('reports not-authenticated in json for every spine command', async () => {
|
|
64
|
+
const invocations = [
|
|
65
|
+
['status', ['status', '--json']],
|
|
66
|
+
['logs', ['logs', '--json']],
|
|
67
|
+
['env', ['env', 'list', '--json']],
|
|
68
|
+
['init', ['init', 'somename', '--json']],
|
|
69
|
+
];
|
|
70
|
+
for (const [name, args] of invocations) {
|
|
71
|
+
const res = await runHeadless(args);
|
|
72
|
+
expect(res.timedOut, `${name} timed out`).toBe(false);
|
|
73
|
+
expect(res.code, `${name} exit band`).toBe(10);
|
|
74
|
+
const parsed = JSON.parse(res.stdout);
|
|
75
|
+
expect(parsed.ok, `${name} ok`).toBe(false);
|
|
76
|
+
expect(parsed.error.code, `${name} code`).toBe('NOT_AUTHENTICATED');
|
|
77
|
+
}
|
|
78
|
+
}, 90_000);
|
|
79
|
+
it('db reports not-authenticated in json, exit 10', async () => {
|
|
80
|
+
const res = await runHeadless(['db', 'provision', '--json']);
|
|
81
|
+
expect(res.timedOut).toBe(false);
|
|
82
|
+
expect(res.code).toBe(10);
|
|
83
|
+
const parsed = JSON.parse(res.stdout);
|
|
84
|
+
expect(parsed.error.code).toBe('NOT_AUTHENTICATED');
|
|
85
|
+
}, 30_000);
|
|
86
|
+
/**
|
|
87
|
+
* Usage is validated BEFORE auth on purpose: a malformed invocation is a
|
|
88
|
+
* usage error whatever the caller's credentials are, and reporting it
|
|
89
|
+
* without a token round-trip lets an agent correct itself immediately.
|
|
90
|
+
*/
|
|
91
|
+
it('db rejects an unknown action with the usage band, even unauthenticated', async () => {
|
|
92
|
+
const res = await runHeadless(['db', 'frobnicate', '--json']);
|
|
93
|
+
expect(res.code).toBe(2);
|
|
94
|
+
const parsed = JSON.parse(res.stdout);
|
|
95
|
+
expect(parsed.error.code).toBe('BAD_USAGE');
|
|
96
|
+
}, 30_000);
|
|
97
|
+
it('every spine command keeps stdout to exactly one json object', async () => {
|
|
98
|
+
const invocations = [
|
|
99
|
+
['status', '--json'],
|
|
100
|
+
['logs', '--json'],
|
|
101
|
+
['env', 'list', '--json'],
|
|
102
|
+
['init', 'somename', '--json'],
|
|
103
|
+
];
|
|
104
|
+
for (const args of invocations) {
|
|
105
|
+
const res = await runHeadless(args);
|
|
106
|
+
expect(res.stdout.trim().split('\n'), args[0]).toHaveLength(1);
|
|
107
|
+
}
|
|
108
|
+
}, 90_000);
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=headless-smoke.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-smoke.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/headless-smoke.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,IAAI,GAAU,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAuDvE,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
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 auth users') + chalk.dim(' list end-users'));
|
|
23
|
+
console.log(chalk.cyan(' pushto auth users rm <email|id>') + chalk.dim(' remove a user'));
|
|
24
|
+
};
|
|
25
|
+
export const auth = async (action, args) => {
|
|
26
|
+
if (!action || action === 'help')
|
|
27
|
+
return usage();
|
|
28
|
+
const slug = ensureAuthed();
|
|
29
|
+
if (action === 'users') {
|
|
30
|
+
const sub = args[0];
|
|
31
|
+
if (sub === 'rm' || sub === 'remove' || sub === 'delete') {
|
|
32
|
+
const target = args[1];
|
|
33
|
+
if (!target) {
|
|
34
|
+
console.log(chalk.red('> usage: pushto auth users rm <email|id>'));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const isEmail = target.includes('@');
|
|
38
|
+
const qs = isEmail ? `email=${encodeURIComponent(target)}` : `id=${encodeURIComponent(target)}`;
|
|
39
|
+
const res = await api(`/cli/projects/${slug}/auth/users?${qs}`, {
|
|
40
|
+
method: 'DELETE',
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
const data = await safeJson(res);
|
|
44
|
+
console.log(chalk.red(`> ${data.error ?? 'failed to remove user.'}`));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const data = await safeJson(res);
|
|
48
|
+
console.log(chalk.green(`> removed ${data.email ?? target}.`));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// bare `users` → list
|
|
52
|
+
const res = await api(`/cli/projects/${slug}/auth/users`);
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
const data = await safeJson(res);
|
|
55
|
+
console.log(chalk.red(`> ${data.error ?? 'failed to list users.'}`));
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
const data = await safeJson(res);
|
|
59
|
+
if (!data.configured) {
|
|
60
|
+
console.log(chalk.dim('> auth is not enabled on this project.'));
|
|
61
|
+
console.log(chalk.dim(' turn it on in the dashboard.'));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (data.users.length === 0) {
|
|
65
|
+
console.log(chalk.dim('> no users have signed up yet.'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log(chalk.green(`> ${slug} auth — ${data.users.length} user${data.users.length !== 1 ? 's' : ''}\n`));
|
|
69
|
+
for (const u of data.users) {
|
|
70
|
+
const when = new Date(u.createdAt).toISOString().slice(0, 10);
|
|
71
|
+
console.log(` ${chalk.cyan(u.id)} ${chalk.dim(when)} ${chalk.dim(u.provider.padEnd(8))} ${u.email}`);
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
usage();
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/commands/cron.ts"],"names":[],"mappings":"AAqEA,eAAO,MAAM,IAAI,GAAU,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CA6GvE,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
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
|
+
import { selectNewExecutions } from '../lib/cron-tail.js';
|
|
7
|
+
const ensureAuthed = () => {
|
|
8
|
+
const token = getToken();
|
|
9
|
+
if (!token) {
|
|
10
|
+
console.log(chalk.red('> not logged in.'));
|
|
11
|
+
console.log(chalk.dim(' run ') + chalk.cyan('pushto login') + chalk.dim(' first.'));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const slug = resolveSlug();
|
|
15
|
+
if (!slug) {
|
|
16
|
+
console.log(chalk.red('> no project here. run pushto init first.'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
return slug;
|
|
20
|
+
};
|
|
21
|
+
const relTime = (iso) => {
|
|
22
|
+
if (!iso)
|
|
23
|
+
return 'never';
|
|
24
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
25
|
+
if (ms < 0)
|
|
26
|
+
return 'in the future';
|
|
27
|
+
const s = Math.floor(ms / 1000);
|
|
28
|
+
if (s < 60)
|
|
29
|
+
return `${s}s ago`;
|
|
30
|
+
const m = Math.floor(s / 60);
|
|
31
|
+
if (m < 60)
|
|
32
|
+
return `${m}m ago`;
|
|
33
|
+
const h = Math.floor(m / 60);
|
|
34
|
+
if (h < 24)
|
|
35
|
+
return `${h}h ago`;
|
|
36
|
+
const d = Math.floor(h / 24);
|
|
37
|
+
return `${d}d ago`;
|
|
38
|
+
};
|
|
39
|
+
const statusColor = (status) => {
|
|
40
|
+
if (status === 'success')
|
|
41
|
+
return chalk.green(status);
|
|
42
|
+
if (status === 'failed' || status === 'timeout')
|
|
43
|
+
return chalk.red(status);
|
|
44
|
+
return chalk.dim(status ?? 'never run');
|
|
45
|
+
};
|
|
46
|
+
const usage = () => {
|
|
47
|
+
console.log(chalk.dim(' usage:'));
|
|
48
|
+
console.log(chalk.cyan(' pushto cron ls') + chalk.dim(' list cron jobs'));
|
|
49
|
+
console.log(chalk.cyan(' pushto cron run <id|name>') + chalk.dim(' trigger a job now'));
|
|
50
|
+
console.log(chalk.cyan(' pushto cron tail <id|name>') + chalk.dim(' recent runs, then follow live'));
|
|
51
|
+
};
|
|
52
|
+
export const cron = async (action, args) => {
|
|
53
|
+
if (!action || action === 'help')
|
|
54
|
+
return usage();
|
|
55
|
+
const slug = ensureAuthed();
|
|
56
|
+
if (action === 'ls' || action === 'list') {
|
|
57
|
+
const res = await api(`/cli/projects/${slug}/cron`);
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const data = await safeJson(res);
|
|
60
|
+
console.log(chalk.red(`> ${data.error ?? 'failed to list cron jobs.'}`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
const data = await safeJson(res);
|
|
64
|
+
if (data.jobs.length === 0) {
|
|
65
|
+
console.log(chalk.dim('> no cron jobs yet.'));
|
|
66
|
+
console.log(chalk.dim(' set one up in the dashboard or via ') + chalk.cyan('.pushto') + chalk.dim(' config.'));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
console.log(chalk.green(`> ${slug} cron — ${data.jobs.length} job${data.jobs.length !== 1 ? 's' : ''}\n`));
|
|
70
|
+
for (const j of data.jobs) {
|
|
71
|
+
const badge = j.enabled ? chalk.green('●') : chalk.dim('○');
|
|
72
|
+
console.log(` ${badge} ${chalk.cyan(j.id)} ${chalk.bold(j.name)}`);
|
|
73
|
+
console.log(` ${chalk.dim(j.schedule.padEnd(15))} ${chalk.dim(j.method)} ${j.url}`);
|
|
74
|
+
console.log(` ${chalk.dim('last:')} ${statusColor(j.lastStatus)} ${chalk.dim('(' + relTime(j.lastRunAt) + ')')}`);
|
|
75
|
+
console.log('');
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (action === 'run' || action === 'trigger') {
|
|
80
|
+
const jobId = args[0];
|
|
81
|
+
if (!jobId) {
|
|
82
|
+
console.log(chalk.red('> usage: pushto cron run <id or name>'));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
console.log(chalk.dim(' triggering...'));
|
|
86
|
+
const res = await api(`/cli/projects/${slug}/cron/${encodeURIComponent(jobId)}/trigger`, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
});
|
|
89
|
+
if (!res.ok) {
|
|
90
|
+
const data = await safeJson(res);
|
|
91
|
+
console.log(chalk.red(`> ${data.error ?? 'trigger failed.'}`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
const data = await safeJson(res);
|
|
95
|
+
const e = data.execution;
|
|
96
|
+
const line = `${statusColor(e.status)} ${chalk.dim('•')} ${e.httpStatus ?? '—'} ${chalk.dim('•')} ${e.responseTimeMs ?? '—'}ms`;
|
|
97
|
+
console.log(`> ${line}`);
|
|
98
|
+
if (e.error)
|
|
99
|
+
console.log(chalk.dim(` ${e.error}`));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (action === 'tail' || action === 'history') {
|
|
103
|
+
const jobRef = args[0];
|
|
104
|
+
if (!jobRef) {
|
|
105
|
+
console.log(chalk.red('> usage: pushto cron tail <id or name>'));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const printExecution = (e) => {
|
|
109
|
+
const when = new Date(e.executedAt).toISOString().replace('T', ' ').slice(0, 19);
|
|
110
|
+
console.log(` ${chalk.dim(when)} ${statusColor(e.status).padEnd(20)} ${chalk.dim((e.httpStatus ?? '—') + '')} ${chalk.dim((e.responseTimeMs ?? '—') + 'ms')}`);
|
|
111
|
+
if (e.error)
|
|
112
|
+
console.log(chalk.dim(` ${e.error}`));
|
|
113
|
+
};
|
|
114
|
+
const fetchHistory = async () => {
|
|
115
|
+
const res = await api(`/cli/projects/${slug}/cron/${encodeURIComponent(jobRef)}/history`);
|
|
116
|
+
if (!res.ok) {
|
|
117
|
+
const data = await safeJson(res);
|
|
118
|
+
return { error: data.error ?? 'failed to fetch history.' };
|
|
119
|
+
}
|
|
120
|
+
return safeJson(res);
|
|
121
|
+
};
|
|
122
|
+
const first = await fetchHistory();
|
|
123
|
+
if ('error' in first) {
|
|
124
|
+
console.log(chalk.red(`> ${first.error}`));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
if (first.executions.length === 0) {
|
|
128
|
+
console.log(chalk.dim(`> ${first.job.name} hasn't run yet.`));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(chalk.green(`> ${first.job.name} — last ${first.executions.length} run${first.executions.length !== 1 ? 's' : ''}\n`));
|
|
132
|
+
for (const e of first.executions)
|
|
133
|
+
printExecution(e);
|
|
134
|
+
}
|
|
135
|
+
// Follow: keep polling and print runs as they land — this is the
|
|
136
|
+
// "watch a run's output live" the docs promise. The scheduler fires
|
|
137
|
+
// at minute granularity, so a 5s poll reports a new run within
|
|
138
|
+
// seconds of it recording. ctrl+c to stop.
|
|
139
|
+
console.log(chalk.dim('\n watching for new runs. ctrl+c to stop.'));
|
|
140
|
+
const seen = new Set(first.executions.map((e) => e.id));
|
|
141
|
+
// eslint-disable-next-line no-constant-condition -- follow until ctrl+c
|
|
142
|
+
while (true) {
|
|
143
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
144
|
+
const next = await fetchHistory();
|
|
145
|
+
if ('error' in next) {
|
|
146
|
+
console.log(chalk.red(`> ${next.error}`));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
for (const e of selectNewExecutions(seen, next.executions)) {
|
|
150
|
+
seen.add(e.id);
|
|
151
|
+
printExecution(e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
usage();
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/commands/cron.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/commands/db.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,EAAE,GAAU,QAAQ,MAAM,EAAE,OAAM;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,KAAG,OAAO,CAAC,IAAI,CAkEpF,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { getToken } from '../lib/config.js';
|
|
4
|
+
import { api } from '../lib/api.js';
|
|
5
|
+
import { resolveSlug } from '../lib/resolve-slug.js';
|
|
6
|
+
import { safeJson } from '../lib/safe-json.js';
|
|
7
|
+
import { fail, emitOk, spinnerStream } from '../lib/output.js';
|
|
8
|
+
import { CODES } from '../lib/errors.js';
|
|
9
|
+
const ACTIONS = ['provision'];
|
|
10
|
+
/** The server answers with its own `code`; trust it only if it is one we know. */
|
|
11
|
+
const knownCode = (value) => typeof value === 'string' && value in CODES ? value : null;
|
|
12
|
+
export const db = async (action, opts = {}) => {
|
|
13
|
+
// Usage is checked BEFORE auth on purpose. A malformed invocation is a usage
|
|
14
|
+
// error whatever the caller's credentials are, and answering without a token
|
|
15
|
+
// round-trip lets an agent correct itself on the spot.
|
|
16
|
+
if (!ACTIONS.includes(action)) {
|
|
17
|
+
fail('BAD_USAGE', `unknown db action: ${action || '(none)'}.`, opts, {
|
|
18
|
+
fix: { label: 'provision a database', cmd: 'pushto db provision' },
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const token = getToken();
|
|
22
|
+
if (!token) {
|
|
23
|
+
fail('NOT_AUTHENTICATED', 'not logged in.', opts, {
|
|
24
|
+
stage: 'auth',
|
|
25
|
+
fix: { label: 'sign in', cmd: 'pushto login', prose: 'run {cmd} first.' },
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const slug = resolveSlug();
|
|
29
|
+
if (!slug) {
|
|
30
|
+
fail('NO_PROJECT', 'no project here. run pushto init first.', opts);
|
|
31
|
+
}
|
|
32
|
+
const spinner = ora({
|
|
33
|
+
text: 'provisioning postgres...',
|
|
34
|
+
stream: spinnerStream(opts),
|
|
35
|
+
}).start();
|
|
36
|
+
try {
|
|
37
|
+
const res = await api(`/cli/projects/${slug}/db`, { method: 'POST' });
|
|
38
|
+
const data = await safeJson(res);
|
|
39
|
+
if (!res.ok || !data.connectionString) {
|
|
40
|
+
spinner.stop();
|
|
41
|
+
fail(knownCode(data.code) ?? 'DB_PROVISION_FAILED', data.error ?? 'could not provision a database.', opts);
|
|
42
|
+
}
|
|
43
|
+
spinner.stop();
|
|
44
|
+
if (opts.json) {
|
|
45
|
+
emitOk({ project: slug, connectionString: data.connectionString }, opts);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(chalk.green('> database ready.'));
|
|
49
|
+
console.log(chalk.dim(' connection string: ') + chalk.cyan(data.connectionString));
|
|
50
|
+
console.log(chalk.dim(' store it with ') +
|
|
51
|
+
chalk.cyan(`pushto env set DATABASE_URL='${data.connectionString}'`));
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
spinner.stop();
|
|
55
|
+
const msg = err instanceof Error ? err.message : '';
|
|
56
|
+
const isNetwork = /fetch|enotfound|econnrefused|timeout|abort|network/i.test(msg);
|
|
57
|
+
if (isNetwork) {
|
|
58
|
+
fail('NETWORK', 'could not reach pushto.host. check your internet.', opts);
|
|
59
|
+
}
|
|
60
|
+
fail('DB_PROVISION_FAILED', `db provision failed: ${msg || 'unknown error'}`, opts);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/commands/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether to ask for a custom domain, and never reach for stdin when
|
|
3
|
+
* the answer is no. Pre-fix this logic was inline and called ask()
|
|
4
|
+
* unconditionally, which hung every headless caller on their first deploy:
|
|
5
|
+
* readline's callback never fires on EOF, so the promise never settled and
|
|
6
|
+
* the enclosing try/catch was inert, because hanging is not throwing.
|
|
7
|
+
*/
|
|
8
|
+
export declare const resolveCustomDomain: (args: {
|
|
9
|
+
current: string | null | undefined;
|
|
10
|
+
canPrompt: boolean;
|
|
11
|
+
ask: (question: string) => Promise<string>;
|
|
12
|
+
}) => Promise<string | null>;
|
|
13
|
+
export declare const deploy: (opts?: {
|
|
14
|
+
json?: boolean;
|
|
15
|
+
yes?: boolean;
|
|
16
|
+
}) => Promise<void>;
|
|
2
17
|
//# sourceMappingURL=deploy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAgBA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAU,MAAM;IAC9C,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5C,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAKxB,CAAC;AAEF,eAAO,MAAM,MAAM,GAAU,OAAM;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,KAAG,OAAO,CAAC,IAAI,CAsavF,CAAC"}
|