@inboxychat/cli 0.0.0-stage → 0.1.0
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/README.md +120 -2
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +56 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +538 -0
- package/dist/cli.js.map +1 -0
- package/dist/doctor.d.ts +32 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +127 -0
- package/dist/doctor.js.map +1 -0
- package/dist/output.d.ts +56 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +161 -0
- package/dist/output.js.map +1 -0
- package/package.json +33 -3
package/README.md
CHANGED
|
@@ -1,3 +1,121 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @inboxychat/cli — `inboxy` (read-only)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A command line for agencies and support: check a key, read orders, contacts and
|
|
4
|
+
usage, and diagnose a setup. It uses only the public API v1
|
|
5
|
+
(`/api/v1/public`) and never writes.
|
|
6
|
+
|
|
7
|
+
Status: local package (plan task API-04). Not published to npm.
|
|
8
|
+
|
|
9
|
+
## Install (local)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm install
|
|
13
|
+
pnpm --filter @inboxychat/cli build # builds the SDK too
|
|
14
|
+
node packages/inboxy-cli/dist/bin.js --help
|
|
15
|
+
# optional: alias inboxy="node $PWD/packages/inboxy-cli/dist/bin.js"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Sign in
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
inboxy auth login # paste the key at the hidden prompt
|
|
22
|
+
pbpaste | inboxy auth login # or pipe it (keeps it out of shell history)
|
|
23
|
+
inboxy auth login --profile client-a # one profile per company (agencies)
|
|
24
|
+
inboxy auth status # where the key comes from + is it accepted
|
|
25
|
+
inboxy auth logout --profile client-a
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The key is read from stdin, never from a command-line argument: `inboxy auth login <key>`
|
|
29
|
+
or a `--key` / `--token` / `--api-key` flag on any command is refused (exit 2) without
|
|
30
|
+
echoing what was typed. It is stored in
|
|
31
|
+
the OS keychain (macOS Keychain via `security`, Linux Secret Service via
|
|
32
|
+
`secret-tool`; the secret goes to those tools on stdin, not argv). Without a
|
|
33
|
+
keychain (or with `--store file`) it goes into the config file with mode `0600`
|
|
34
|
+
in a `0700` directory; a config file other users can read is refused.
|
|
35
|
+
|
|
36
|
+
Config: `$INBOXY_CONFIG_DIR`, else `$XDG_CONFIG_HOME/inboxy`, else
|
|
37
|
+
`~/.config/inboxy/config.json`. It holds the API URL and where the key lives.
|
|
38
|
+
|
|
39
|
+
`INBOXY_API_KEY` / `INBOXY_API_URL` / `INBOXY_PROFILE` override everything.
|
|
40
|
+
`INBOXY_KEYCHAIN=off` disables the keychain.
|
|
41
|
+
|
|
42
|
+
## Commands
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
inboxy whoami company, key name, scopes, expiry, rate limits
|
|
46
|
+
inboxy usage plan usage against limits
|
|
47
|
+
inboxy stores list connected-store count vs plan limit (*)
|
|
48
|
+
inboxy orders list [--status pending] [--payment-status ..] [--fulfillment-status ..]
|
|
49
|
+
[--source shopify] [--store <id>] [--contact <id>] [--search <text>]
|
|
50
|
+
[--after <iso>] [--before <iso>]
|
|
51
|
+
inboxy orders get <id>
|
|
52
|
+
inboxy contacts search [text] [--status ..] [--stage lead] [--tags <ids>]
|
|
53
|
+
[--created-after <iso>] [--created-before <iso>]
|
|
54
|
+
inboxy doctor URL, key, key format, reachability, scopes,
|
|
55
|
+
key expiry, clock skew, config permissions
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
(\*) The public API has no stores route yet, so `stores list` shows the count
|
|
59
|
+
from plan usage and says so (`items: null` in JSON). Per-store health is in the
|
|
60
|
+
dashboard.
|
|
61
|
+
|
|
62
|
+
Paging: `--limit 1-100`, `--cursor <nextCursor>`, or `--all` (follows cursors,
|
|
63
|
+
up to `--max-pages`, default 10). Global: `--json`, `--profile`, `--url`,
|
|
64
|
+
`--timeout <ms>`. Global options may come before or after the command.
|
|
65
|
+
|
|
66
|
+
## `--json`
|
|
67
|
+
|
|
68
|
+
One document on stdout, schema version 1 (fields may be added, never renamed or removed):
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{ "schemaVersion": 1, "ok": true, "command": "orders list",
|
|
72
|
+
"data": [ ... ], "meta": { "limit": 20, "hasMore": true, "nextCursor": "...", "pages": 1 } }
|
|
73
|
+
|
|
74
|
+
{ "schemaVersion": 1, "ok": false, "command": "orders list",
|
|
75
|
+
"error": { "kind": "forbidden", "code": "INSUFFICIENT_PERMISSIONS", "status": 403,
|
|
76
|
+
"message": "This API key does not have the \"orders:read\" scope. ...",
|
|
77
|
+
"details": { "requiredScope": "orders:read" }, "retryAfterSeconds": null } }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`data` items are the public API v1 objects unchanged.
|
|
81
|
+
|
|
82
|
+
## Exit codes
|
|
83
|
+
|
|
84
|
+
| Code | Meaning |
|
|
85
|
+
| ---- | ------------------------------------------------------------------------- |
|
|
86
|
+
| 0 | OK |
|
|
87
|
+
| 1 | Unexpected error |
|
|
88
|
+
| 2 | Usage error (bad flag, bad value, invalid id) — nothing was sent |
|
|
89
|
+
| 3 | Configuration: no key, bad URL, config file permissions, no keychain |
|
|
90
|
+
| 4 | Key refused (401) |
|
|
91
|
+
| 5 | Forbidden (403): missing scope, company paused, key owner no longer admin |
|
|
92
|
+
| 6 | Not found (404) |
|
|
93
|
+
| 7 | Rate limited (429) — see `retryAfterSeconds` |
|
|
94
|
+
| 8 | Network error, timeout or cancelled |
|
|
95
|
+
| 9 | Server error or a response that is not the API envelope |
|
|
96
|
+
| 10 | `doctor` found at least one failing check |
|
|
97
|
+
|
|
98
|
+
## Safety
|
|
99
|
+
|
|
100
|
+
- The key is never printed. Errors and JSON pass through redaction (any
|
|
101
|
+
`inboxy_…` value, any `Bearer …` value and the exact key in use), even when a
|
|
102
|
+
server message echoes the header back. Status output shows only the 8-character
|
|
103
|
+
prefix the dashboard also shows.
|
|
104
|
+
- No shell: inputs reach the API only as validated, percent-encoded path
|
|
105
|
+
segments or query values; ids must be 1–64 letters, digits, `_` or `-`.
|
|
106
|
+
- HTTPS only (plain `http://` for `localhost` only); redirects are refused.
|
|
107
|
+
|
|
108
|
+
## Tests
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
pnpm --filter @inboxychat/cli test
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`test/cli.e2e.test.ts` runs the built binary against the local mock API:
|
|
115
|
+
every command, paging, filters, exit codes, the key never in stdout/stderr,
|
|
116
|
+
no shell interpolation, auth login/status/logout with the 0600 file, refusal
|
|
117
|
+
of a world-readable config, profiles per company, and doctor (clock skew,
|
|
118
|
+
scopes, expiry, refused key, unreachable URL). `test/cli.inprocess.test.ts`
|
|
119
|
+
covers the keychain path with a fake keychain and redaction of a key echoed by
|
|
120
|
+
the server. The macOS Keychain adapter was also checked once by hand with a
|
|
121
|
+
throwaway entry (store, update, read, delete).
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runCli } from './cli.js';
|
|
3
|
+
async function readAll(stream) {
|
|
4
|
+
let data = '';
|
|
5
|
+
stream.setEncoding('utf8');
|
|
6
|
+
for await (const chunk of stream)
|
|
7
|
+
data += chunk;
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
/** Reads a line from the terminal without echoing it. */
|
|
11
|
+
function promptHidden(prompt) {
|
|
12
|
+
const stdin = process.stdin;
|
|
13
|
+
process.stderr.write(prompt);
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
let input = '';
|
|
16
|
+
stdin.setRawMode(true);
|
|
17
|
+
stdin.resume();
|
|
18
|
+
stdin.setEncoding('utf8');
|
|
19
|
+
const onData = (chunk) => {
|
|
20
|
+
for (const ch of chunk) {
|
|
21
|
+
if (ch === '\r' || ch === '\n' || ch === '\u0004') {
|
|
22
|
+
stdin.setRawMode(false);
|
|
23
|
+
stdin.pause();
|
|
24
|
+
stdin.off('data', onData);
|
|
25
|
+
process.stderr.write('\n');
|
|
26
|
+
resolve(input);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (ch === '\u0003') {
|
|
30
|
+
stdin.setRawMode(false);
|
|
31
|
+
process.stderr.write('\n');
|
|
32
|
+
process.exit(130);
|
|
33
|
+
}
|
|
34
|
+
if (ch === '\u007f' || ch === '\b')
|
|
35
|
+
input = input.slice(0, -1);
|
|
36
|
+
else
|
|
37
|
+
input += ch;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
stdin.on('data', onData);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const io = {
|
|
44
|
+
stdout: (t) => process.stdout.write(t),
|
|
45
|
+
stderr: (t) => process.stderr.write(t),
|
|
46
|
+
readSecret: (prompt) => (process.stdin.isTTY ? promptHidden(prompt) : readAll(process.stdin)),
|
|
47
|
+
env: process.env,
|
|
48
|
+
now: () => Date.now(),
|
|
49
|
+
};
|
|
50
|
+
runCli(process.argv.slice(2), io).then((code) => {
|
|
51
|
+
process.exitCode = code;
|
|
52
|
+
}, () => {
|
|
53
|
+
process.stderr.write('inboxy: unexpected failure\n');
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Keychain } from '@inboxychat/sdk';
|
|
2
|
+
import { type CliIO } from './output.js';
|
|
3
|
+
export declare const CLI_VERSION = "0.1.0";
|
|
4
|
+
export interface CliDeps {
|
|
5
|
+
/** Override the OS keychain (tests); undefined = detect, null = none. */
|
|
6
|
+
keychain?: Keychain | null;
|
|
7
|
+
}
|
|
8
|
+
/** Commands that only touch local configuration (no capability behind them). */
|
|
9
|
+
export declare const LOCAL_COMMANDS: readonly ["auth login", "auth logout", "auth status", "doctor"];
|
|
10
|
+
/**
|
|
11
|
+
* Data commands: each is the adapter of one registered capability (UX26-F,
|
|
12
|
+
* apps/api/src/lib/capabilities). A command without one is not offered.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DATA_COMMANDS: string[];
|
|
15
|
+
export declare function runCli(argv: string[], io: CliIO, deps?: CliDeps): Promise<number>;
|
|
16
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AASA,OAAO,EAqBL,KAAK,QAAQ,EAKd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAmC,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAE1E,eAAO,MAAM,WAAW,UAAU,CAAC;AAwDnC,MAAM,WAAW,OAAO;IACtB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC5B;AA6DD,gFAAgF;AAChF,eAAO,MAAM,cAAc,iEAAkE,CAAC;AAE9F;;;GAGG;AACH,eAAO,MAAM,aAAa,UAEzB,CAAC;AAcF,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,GAAE,OAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAub3F"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `inboxy` command line (local, read-only).
|
|
3
|
+
*
|
|
4
|
+
* Inputs are parsed with node:util parseArgs and only ever reach the network
|
|
5
|
+
* as validated, percent-encoded path segments or URLSearchParams values.
|
|
6
|
+
* Nothing here spawns a shell; the only child processes are the OS keychain
|
|
7
|
+
* tools, started with argument arrays by @inboxychat/sdk.
|
|
8
|
+
*/
|
|
9
|
+
import { parseArgs } from 'node:util';
|
|
10
|
+
import { CONTACT_STATUSES, FULFILLMENT_STATUSES, InboxyClient, InboxyError, LIFECYCLE_STAGES, ORDER_SOURCES, ORDER_STATUSES, PAGE_LIMIT_MAX, PAYMENT_STATUSES, PUBLIC_CAPABILITIES, collectPages, loadConfig, looksLikeInboxyKey, normalizeBaseUrl, resolveCredentials, saveConfig, systemKeychain, validateProfileName, } from '@inboxychat/sdk';
|
|
11
|
+
import { runDoctor } from './doctor.js';
|
|
12
|
+
import { EXIT, Output, UsageError, table } from './output.js';
|
|
13
|
+
export const CLI_VERSION = '0.1.0';
|
|
14
|
+
const HELP = `inboxy ${CLI_VERSION} — read-only command line for the Inboxy public API
|
|
15
|
+
|
|
16
|
+
Usage: inboxy <command> [options]
|
|
17
|
+
|
|
18
|
+
Account
|
|
19
|
+
auth login [--store keychain|file] [--no-verify] Store an API key (read from stdin or a hidden prompt)
|
|
20
|
+
auth logout Remove the stored key of the profile
|
|
21
|
+
auth status [--offline] Where the key comes from, and whether Inboxy accepts it
|
|
22
|
+
whoami Company, key name, scopes, expiry, rate limits
|
|
23
|
+
usage Plan usage against limits
|
|
24
|
+
stores list Connected-store count against the plan limit
|
|
25
|
+
doctor Check URL, key, scopes, clock skew and config permissions
|
|
26
|
+
|
|
27
|
+
Data
|
|
28
|
+
orders list [filters] [paging] --status --payment-status --fulfillment-status --source
|
|
29
|
+
--store <id> --contact <id> --search <text>
|
|
30
|
+
--after <iso> --before <iso>
|
|
31
|
+
orders get <id>
|
|
32
|
+
contacts search [text] [paging] --status --stage --tags <ids> --created-after --created-before
|
|
33
|
+
|
|
34
|
+
Paging
|
|
35
|
+
--limit <1-${PAGE_LIMIT_MAX}> --cursor <nextCursor> --all [--max-pages <n>, default 10]
|
|
36
|
+
|
|
37
|
+
Global options
|
|
38
|
+
--json One JSON document on stdout (schemaVersion 1)
|
|
39
|
+
--profile <name> Use a stored profile (one per company; default "default", or INBOXY_PROFILE)
|
|
40
|
+
--url <origin> API origin (default INBOXY_API_URL, the profile, or https://api.inboxy.chat)
|
|
41
|
+
--timeout <ms> Per-request timeout (default 20000)
|
|
42
|
+
-h, --help This help --version Print the version
|
|
43
|
+
|
|
44
|
+
Credentials: INBOXY_API_KEY, else the OS keychain entry written by \`auth login\`,
|
|
45
|
+
else (machines without a keychain) the 0600 config file. The key is never printed.
|
|
46
|
+
Exit codes: 0 ok, 2 usage, 3 config, 4 key refused, 5 forbidden, 6 not found,
|
|
47
|
+
7 rate limited, 8 network/timeout, 9 server, 10 doctor checks failed, 1 unexpected.`;
|
|
48
|
+
const KEY_ON_COMMAND_LINE = 'The API key is never passed as an argument (it would stay in shell history). Run `inboxy auth login` and type it at the hidden prompt, or pipe it: `pbpaste | inboxy auth login`.';
|
|
49
|
+
const GLOBAL_OPTIONS = {
|
|
50
|
+
json: { type: 'boolean' },
|
|
51
|
+
profile: { type: 'string' },
|
|
52
|
+
url: { type: 'string' },
|
|
53
|
+
timeout: { type: 'string' },
|
|
54
|
+
help: { type: 'boolean', short: 'h' },
|
|
55
|
+
version: { type: 'boolean' },
|
|
56
|
+
};
|
|
57
|
+
const PAGING_OPTIONS = {
|
|
58
|
+
limit: { type: 'string' },
|
|
59
|
+
cursor: { type: 'string' },
|
|
60
|
+
all: { type: 'boolean' },
|
|
61
|
+
'max-pages': { type: 'string' },
|
|
62
|
+
};
|
|
63
|
+
function intOption(value, name, min, max) {
|
|
64
|
+
if (value === undefined)
|
|
65
|
+
return undefined;
|
|
66
|
+
if (!/^\d+$/.test(value))
|
|
67
|
+
throw new UsageError(`--${name} must be a whole number.`);
|
|
68
|
+
const n = Number(value);
|
|
69
|
+
if (n < min || n > max)
|
|
70
|
+
throw new UsageError(`--${name} must be between ${min} and ${max}.`);
|
|
71
|
+
return n;
|
|
72
|
+
}
|
|
73
|
+
function enumOption(value, name, allowed) {
|
|
74
|
+
if (value === undefined)
|
|
75
|
+
return undefined;
|
|
76
|
+
if (!allowed.includes(value)) {
|
|
77
|
+
throw new UsageError(`--${name} must be one of: ${allowed.join(', ')}.`);
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
function isoOption(value, name) {
|
|
82
|
+
if (value === undefined)
|
|
83
|
+
return undefined;
|
|
84
|
+
if (Number.isNaN(Date.parse(value)))
|
|
85
|
+
throw new UsageError(`--${name} must be an ISO-8601 date or date-time.`);
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Splits `argv` into the command words and the rest, without interpreting
|
|
90
|
+
* values. Global options may come before the command (`inboxy --profile a whoami`).
|
|
91
|
+
*/
|
|
92
|
+
const GLOBAL_VALUE_FLAGS = new Set(['--profile', '--url', '--timeout']);
|
|
93
|
+
function commandWords(argv) {
|
|
94
|
+
const words = [];
|
|
95
|
+
const rest = [];
|
|
96
|
+
let i = 0;
|
|
97
|
+
while (i < argv.length && words.length < 2) {
|
|
98
|
+
const arg = argv[i];
|
|
99
|
+
if (GLOBAL_VALUE_FLAGS.has(arg)) {
|
|
100
|
+
rest.push(arg, ...(i + 1 < argv.length ? [argv[i + 1]] : []));
|
|
101
|
+
i += 2;
|
|
102
|
+
}
|
|
103
|
+
else if (arg === '--json') {
|
|
104
|
+
rest.push(arg);
|
|
105
|
+
i += 1;
|
|
106
|
+
}
|
|
107
|
+
else if (arg.startsWith('-')) {
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
words.push(arg);
|
|
112
|
+
i += 1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { words, rest: [...rest, ...argv.slice(i)] };
|
|
116
|
+
}
|
|
117
|
+
/** Commands that only touch local configuration (no capability behind them). */
|
|
118
|
+
export const LOCAL_COMMANDS = ['auth login', 'auth logout', 'auth status', 'doctor'];
|
|
119
|
+
/**
|
|
120
|
+
* Data commands: each is the adapter of one registered capability (UX26-F,
|
|
121
|
+
* apps/api/src/lib/capabilities). A command without one is not offered.
|
|
122
|
+
*/
|
|
123
|
+
export const DATA_COMMANDS = PUBLIC_CAPABILITIES.flatMap((c) => c.cliCommand ? [c.cliCommand] : []);
|
|
124
|
+
const COMMANDS = new Set([...LOCAL_COMMANDS, ...DATA_COMMANDS]);
|
|
125
|
+
function matchCommand(words) {
|
|
126
|
+
if (words.length >= 2 && COMMANDS.has(`${words[0]} ${words[1]}`)) {
|
|
127
|
+
return { name: `${words[0]} ${words[1]}`, positionals: [] };
|
|
128
|
+
}
|
|
129
|
+
if (words.length >= 1 && COMMANDS.has(words[0])) {
|
|
130
|
+
return { name: words[0], positionals: words.slice(1) };
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
export async function runCli(argv, io, deps = {}) {
|
|
135
|
+
const wantsJson = argv.includes('--json');
|
|
136
|
+
const { words, rest } = commandWords(argv);
|
|
137
|
+
const matched = matchCommand(words);
|
|
138
|
+
const commandName = matched?.name ?? words.join(' ');
|
|
139
|
+
let activeKey = null;
|
|
140
|
+
const out = new Output(io, wantsJson, commandName || 'help', () => activeKey ? [activeKey] : []);
|
|
141
|
+
try {
|
|
142
|
+
if (!matched) {
|
|
143
|
+
if (argv.includes('--version')) {
|
|
144
|
+
io.stdout(`${CLI_VERSION}\n`);
|
|
145
|
+
return EXIT.OK;
|
|
146
|
+
}
|
|
147
|
+
if (words.length === 0 || argv.includes('--help') || argv.includes('-h')) {
|
|
148
|
+
io.stdout(`${HELP}\n`);
|
|
149
|
+
return words.length === 0 && !argv.includes('--help') && !argv.includes('-h')
|
|
150
|
+
? EXIT.USAGE
|
|
151
|
+
: EXIT.OK;
|
|
152
|
+
}
|
|
153
|
+
throw new UsageError(`Unknown command "${words.join(' ')}".`);
|
|
154
|
+
}
|
|
155
|
+
const extra = {};
|
|
156
|
+
const name = matched.name;
|
|
157
|
+
if (name === 'orders list') {
|
|
158
|
+
Object.assign(extra, PAGING_OPTIONS, {
|
|
159
|
+
status: { type: 'string' },
|
|
160
|
+
'payment-status': { type: 'string' },
|
|
161
|
+
'fulfillment-status': { type: 'string' },
|
|
162
|
+
source: { type: 'string' },
|
|
163
|
+
store: { type: 'string' },
|
|
164
|
+
contact: { type: 'string' },
|
|
165
|
+
search: { type: 'string' },
|
|
166
|
+
after: { type: 'string' },
|
|
167
|
+
before: { type: 'string' },
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else if (name === 'contacts search') {
|
|
171
|
+
Object.assign(extra, PAGING_OPTIONS, {
|
|
172
|
+
status: { type: 'string' },
|
|
173
|
+
stage: { type: 'string' },
|
|
174
|
+
tags: { type: 'string' },
|
|
175
|
+
'created-after': { type: 'string' },
|
|
176
|
+
'created-before': { type: 'string' },
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
else if (name === 'auth login') {
|
|
180
|
+
Object.assign(extra, { store: { type: 'string' }, 'no-verify': { type: 'boolean' } });
|
|
181
|
+
}
|
|
182
|
+
else if (name === 'auth status') {
|
|
183
|
+
Object.assign(extra, { offline: { type: 'boolean' } });
|
|
184
|
+
}
|
|
185
|
+
// A key typed as an argument stays in shell history and process lists:
|
|
186
|
+
// refuse it before parsing, without echoing what was typed.
|
|
187
|
+
const KEY_FLAG = /^--(key|token|api-key|apikey|secret)(=|$)/i;
|
|
188
|
+
if (rest.some((arg) => KEY_FLAG.test(arg))) {
|
|
189
|
+
throw new UsageError(KEY_ON_COMMAND_LINE);
|
|
190
|
+
}
|
|
191
|
+
let parsed;
|
|
192
|
+
try {
|
|
193
|
+
parsed = parseArgs({
|
|
194
|
+
args: rest,
|
|
195
|
+
options: { ...GLOBAL_OPTIONS, ...extra },
|
|
196
|
+
allowPositionals: true,
|
|
197
|
+
strict: true,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
throw new UsageError(error.message.replace(/\. To specify.*$/s, '.'));
|
|
202
|
+
}
|
|
203
|
+
const opts = parsed.values;
|
|
204
|
+
const positionals = [...matched.positionals, ...parsed.positionals];
|
|
205
|
+
if (opts.help) {
|
|
206
|
+
io.stdout(`${HELP}\n`);
|
|
207
|
+
return EXIT.OK;
|
|
208
|
+
}
|
|
209
|
+
const profile = typeof opts.profile === 'string' ? validateProfileName(opts.profile) : undefined;
|
|
210
|
+
const timeoutMs = intOption(opts.timeout, 'timeout', 100, 120_000);
|
|
211
|
+
const env = typeof opts.url === 'string' ? { ...io.env, INBOXY_API_URL: opts.url } : io.env;
|
|
212
|
+
const keychainFor = async () => deps.keychain !== undefined ? deps.keychain : systemKeychain(env);
|
|
213
|
+
const credentials = async () => {
|
|
214
|
+
const creds = await resolveCredentials({ env, profile, keychain: await keychainFor() });
|
|
215
|
+
activeKey = creds.apiKey;
|
|
216
|
+
return creds;
|
|
217
|
+
};
|
|
218
|
+
const clientFrom = (creds) => {
|
|
219
|
+
if (!creds.apiKey) {
|
|
220
|
+
throw new InboxyError({
|
|
221
|
+
kind: 'config',
|
|
222
|
+
code: 'API_KEY_MISSING',
|
|
223
|
+
message: `No API key for profile "${creds.profile}". Set INBOXY_API_KEY or run \`inboxy auth login\`.`,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return new InboxyClient({
|
|
227
|
+
apiKey: creds.apiKey,
|
|
228
|
+
baseUrl: creds.apiUrl,
|
|
229
|
+
timeoutMs,
|
|
230
|
+
userAgent: `inboxy-cli/${CLI_VERSION}`,
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
const noPositionals = () => {
|
|
234
|
+
if (!positionals.length)
|
|
235
|
+
return;
|
|
236
|
+
// `auth login <key>`: never echo the argument back (it is probably the key).
|
|
237
|
+
if (name === 'auth login')
|
|
238
|
+
throw new UsageError(KEY_ON_COMMAND_LINE);
|
|
239
|
+
throw new UsageError(`Unexpected argument "${positionals[0]}".`);
|
|
240
|
+
};
|
|
241
|
+
switch (name) {
|
|
242
|
+
// ------------------------------------------------------------------
|
|
243
|
+
case 'whoami': {
|
|
244
|
+
noPositionals();
|
|
245
|
+
const { data } = await clientFrom(await credentials()).getCompany();
|
|
246
|
+
return out.success(data, undefined, () => [
|
|
247
|
+
`Company ${data.company.name} (${data.company.id})`,
|
|
248
|
+
`Key ${data.token.name} · ${data.token.prefix}…`,
|
|
249
|
+
`Scopes ${data.token.scopes.join(', ') || 'none'}`,
|
|
250
|
+
`Expires ${data.token.expiresAt ?? 'never'}`,
|
|
251
|
+
`Limits ${data.rateLimits.perKey.limit}/min per key · ${data.rateLimits.perCompany.limit}/min per company`,
|
|
252
|
+
].join('\n'));
|
|
253
|
+
}
|
|
254
|
+
// ------------------------------------------------------------------
|
|
255
|
+
case 'usage': {
|
|
256
|
+
noPositionals();
|
|
257
|
+
const { data } = await clientFrom(await credentials()).getUsage();
|
|
258
|
+
return out.success(data, undefined, () => {
|
|
259
|
+
const rows = Object.entries(data.usage).map(([k, c]) => [
|
|
260
|
+
k,
|
|
261
|
+
c.used,
|
|
262
|
+
c.limit === null ? 'unlimited' : c.limit,
|
|
263
|
+
]);
|
|
264
|
+
return [
|
|
265
|
+
`Plan ${data.plan.name} (${data.plan.status}${data.plan.isTrial ? ', trial' : ''}) · period ends ${data.plan.currentPeriodEnd}`,
|
|
266
|
+
table(['counter', 'used', 'limit'], rows),
|
|
267
|
+
`API requests in the last 24 h: ${data.api.requestsLast24h}`,
|
|
268
|
+
].join('\n');
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
// ------------------------------------------------------------------
|
|
272
|
+
case 'stores list': {
|
|
273
|
+
noPositionals();
|
|
274
|
+
const { data } = await clientFrom(await credentials()).getUsage();
|
|
275
|
+
const result = {
|
|
276
|
+
stores: data.usage.stores,
|
|
277
|
+
items: null,
|
|
278
|
+
note: 'Public API v1 has no stores route yet; this is the connected-store count from plan usage. Per-store details and health are in the dashboard.',
|
|
279
|
+
};
|
|
280
|
+
return out.success(result, undefined, () => [
|
|
281
|
+
`Connected stores: ${data.usage.stores.used} of ${data.usage.stores.limit ?? 'unlimited'}`,
|
|
282
|
+
result.note,
|
|
283
|
+
].join('\n'));
|
|
284
|
+
}
|
|
285
|
+
// ------------------------------------------------------------------
|
|
286
|
+
case 'orders list': {
|
|
287
|
+
noPositionals();
|
|
288
|
+
const query = {
|
|
289
|
+
status: enumOption(opts.status, 'status', ORDER_STATUSES),
|
|
290
|
+
paymentStatus: enumOption(opts['payment-status'], 'payment-status', PAYMENT_STATUSES),
|
|
291
|
+
fulfillmentStatus: enumOption(opts['fulfillment-status'], 'fulfillment-status', FULFILLMENT_STATUSES),
|
|
292
|
+
source: enumOption(opts.source, 'source', ORDER_SOURCES),
|
|
293
|
+
storeId: opts.store,
|
|
294
|
+
contactId: opts.contact,
|
|
295
|
+
search: opts.search,
|
|
296
|
+
dateAfter: isoOption(opts.after, 'after'),
|
|
297
|
+
dateBefore: isoOption(opts.before, 'before'),
|
|
298
|
+
limit: intOption(opts.limit, 'limit', 1, PAGE_LIMIT_MAX),
|
|
299
|
+
cursor: opts.cursor,
|
|
300
|
+
};
|
|
301
|
+
const client = clientFrom(await credentials());
|
|
302
|
+
const page = await listPages((q) => client.listOrders(q), query, opts);
|
|
303
|
+
return out.success(page.items, page.meta, () => [
|
|
304
|
+
table(['id', 'number', 'status', 'payment', 'total', 'customer', 'date'], page.items.map((o) => [
|
|
305
|
+
o.id,
|
|
306
|
+
o.orderNumber,
|
|
307
|
+
o.status,
|
|
308
|
+
o.paymentStatus,
|
|
309
|
+
`${o.total} ${o.currency}`,
|
|
310
|
+
o.contact?.name,
|
|
311
|
+
o.orderDate.slice(0, 10),
|
|
312
|
+
])),
|
|
313
|
+
pagingHint(page.meta),
|
|
314
|
+
]
|
|
315
|
+
.filter(Boolean)
|
|
316
|
+
.join('\n'));
|
|
317
|
+
}
|
|
318
|
+
case 'orders get': {
|
|
319
|
+
if (positionals.length !== 1)
|
|
320
|
+
throw new UsageError('Usage: inboxy orders get <id>');
|
|
321
|
+
const { data: o } = await clientFrom(await credentials()).getOrder(positionals[0]);
|
|
322
|
+
return out.success(o, undefined, () => [
|
|
323
|
+
`Order ${o.orderNumber} (${o.id}) · ${o.source}`,
|
|
324
|
+
`Status ${o.status} · payment ${o.paymentStatus} · fulfillment ${o.fulfillmentStatus} · confirmation ${o.confirmationStatus}`,
|
|
325
|
+
`Total ${o.total} ${o.currency} (subtotal ${o.subtotal}, shipping ${o.shipping ?? '-'}, discount ${o.discount ?? '-'})`,
|
|
326
|
+
`Customer ${o.contact ? `${o.contact.name} ${o.contact.phone ?? ''}`.trim() : '-'}`,
|
|
327
|
+
`Date ${o.orderDate}`,
|
|
328
|
+
table(['item', 'sku', 'qty', 'total'], o.items.map((i) => [
|
|
329
|
+
i.variant ? `${i.name} (${i.variant})` : i.name,
|
|
330
|
+
i.sku,
|
|
331
|
+
i.quantity,
|
|
332
|
+
i.totalPrice,
|
|
333
|
+
])),
|
|
334
|
+
].join('\n'));
|
|
335
|
+
}
|
|
336
|
+
// ------------------------------------------------------------------
|
|
337
|
+
case 'contacts search': {
|
|
338
|
+
if (positionals.length > 1)
|
|
339
|
+
throw new UsageError('Usage: inboxy contacts search [text]');
|
|
340
|
+
const query = {
|
|
341
|
+
search: positionals[0],
|
|
342
|
+
status: enumOption(opts.status, 'status', CONTACT_STATUSES),
|
|
343
|
+
lifecycleStage: enumOption(opts.stage, 'stage', LIFECYCLE_STAGES),
|
|
344
|
+
tagIds: opts.tags,
|
|
345
|
+
createdAfter: isoOption(opts['created-after'], 'created-after'),
|
|
346
|
+
createdBefore: isoOption(opts['created-before'], 'created-before'),
|
|
347
|
+
limit: intOption(opts.limit, 'limit', 1, PAGE_LIMIT_MAX),
|
|
348
|
+
cursor: opts.cursor,
|
|
349
|
+
};
|
|
350
|
+
const client = clientFrom(await credentials());
|
|
351
|
+
const page = await listPages((q) => client.listContacts(q), query, opts);
|
|
352
|
+
return out.success(page.items, page.meta, () => [
|
|
353
|
+
table(['id', 'name', 'phone', 'email', 'stage', 'orders'], page.items.map((c) => [
|
|
354
|
+
c.id,
|
|
355
|
+
c.name,
|
|
356
|
+
c.phone,
|
|
357
|
+
c.email,
|
|
358
|
+
c.lifecycleStage,
|
|
359
|
+
c.totalOrders,
|
|
360
|
+
])),
|
|
361
|
+
pagingHint(page.meta),
|
|
362
|
+
]
|
|
363
|
+
.filter(Boolean)
|
|
364
|
+
.join('\n'));
|
|
365
|
+
}
|
|
366
|
+
// ------------------------------------------------------------------
|
|
367
|
+
case 'doctor': {
|
|
368
|
+
noPositionals();
|
|
369
|
+
let creds;
|
|
370
|
+
let credentialError;
|
|
371
|
+
try {
|
|
372
|
+
creds = await credentials();
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
// A refused config (e.g. a key in a world-readable file) is a failed
|
|
376
|
+
// check, not a crash.
|
|
377
|
+
if (!(error instanceof InboxyError) || error.kind !== 'config')
|
|
378
|
+
throw error;
|
|
379
|
+
credentialError = `${error.code}: ${error.message}`;
|
|
380
|
+
creds = {
|
|
381
|
+
profile: profile ?? env.INBOXY_PROFILE ?? 'default',
|
|
382
|
+
apiKey: null,
|
|
383
|
+
keySource: 'none',
|
|
384
|
+
apiUrl: env.INBOXY_API_URL ?? 'https://api.inboxy.chat',
|
|
385
|
+
urlSource: env.INBOXY_API_URL ? 'env' : 'default',
|
|
386
|
+
configPath: '',
|
|
387
|
+
warnings: [],
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
const report = await runDoctor(creds, { env, timeoutMs, now: io.now, credentialError });
|
|
391
|
+
const code = out.success(report, undefined, () => [
|
|
392
|
+
`Profile "${report.profile}" · ${report.apiUrl}`,
|
|
393
|
+
...report.checks.map((c) => `${c.status.toUpperCase().padEnd(4)} ${c.id.padEnd(14)} ${c.message}`),
|
|
394
|
+
report.ok ? 'All checks passed.' : 'Some checks failed.',
|
|
395
|
+
].join('\n'));
|
|
396
|
+
return report.ok ? code : EXIT.CHECKS_FAILED;
|
|
397
|
+
}
|
|
398
|
+
// ------------------------------------------------------------------
|
|
399
|
+
case 'auth status': {
|
|
400
|
+
noPositionals();
|
|
401
|
+
const creds = await credentials();
|
|
402
|
+
const status = {
|
|
403
|
+
profile: creds.profile,
|
|
404
|
+
apiUrl: creds.apiUrl,
|
|
405
|
+
urlSource: creds.urlSource,
|
|
406
|
+
keySource: creds.keySource,
|
|
407
|
+
keyPrefix: creds.apiKey ? `${creds.apiKey.slice(0, 8)}…` : null,
|
|
408
|
+
verified: null,
|
|
409
|
+
company: null,
|
|
410
|
+
};
|
|
411
|
+
if (!creds.apiKey) {
|
|
412
|
+
throw new InboxyError({
|
|
413
|
+
kind: 'config',
|
|
414
|
+
code: 'API_KEY_MISSING',
|
|
415
|
+
message: `Not signed in (profile "${creds.profile}"). Run \`inboxy auth login\` or set INBOXY_API_KEY.`,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
if (!opts.offline) {
|
|
419
|
+
const { data } = await clientFrom(creds).getCompany();
|
|
420
|
+
status.verified = true;
|
|
421
|
+
status.company = { id: data.company.id, name: data.company.name };
|
|
422
|
+
}
|
|
423
|
+
return out.success(status, undefined, () => [
|
|
424
|
+
`Profile ${creds.profile}`,
|
|
425
|
+
`API ${creds.apiUrl} (from ${creds.urlSource})`,
|
|
426
|
+
`Key ${status.keyPrefix} (from ${creds.keySource})`,
|
|
427
|
+
status.company
|
|
428
|
+
? `Verified ${status.company.name} accepts this key`
|
|
429
|
+
: 'Verified skipped (--offline)',
|
|
430
|
+
].join('\n'));
|
|
431
|
+
}
|
|
432
|
+
case 'auth login': {
|
|
433
|
+
noPositionals();
|
|
434
|
+
const profileName = profile ?? io.env.INBOXY_PROFILE ?? 'default';
|
|
435
|
+
validateProfileName(profileName);
|
|
436
|
+
const storeOpt = opts.store;
|
|
437
|
+
if (storeOpt !== undefined && storeOpt !== 'keychain' && storeOpt !== 'file') {
|
|
438
|
+
throw new UsageError('--store must be keychain or file.');
|
|
439
|
+
}
|
|
440
|
+
const apiUrl = normalizeBaseUrl(opts.url ?? io.env.INBOXY_API_URL ?? 'https://api.inboxy.chat');
|
|
441
|
+
const key = (await io.readSecret('Inboxy API key (input hidden): ')).trim();
|
|
442
|
+
activeKey = key;
|
|
443
|
+
if (!key)
|
|
444
|
+
throw new UsageError('No API key received on stdin.');
|
|
445
|
+
if (!looksLikeInboxyKey(key)) {
|
|
446
|
+
throw new InboxyError({
|
|
447
|
+
kind: 'config',
|
|
448
|
+
code: 'API_KEY_INVALID_FORMAT',
|
|
449
|
+
message: 'That does not look like an Inboxy API key (inboxy_ followed by 64 hex characters).',
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
let company = null;
|
|
453
|
+
if (!opts['no-verify']) {
|
|
454
|
+
const client = new InboxyClient({
|
|
455
|
+
apiKey: key,
|
|
456
|
+
baseUrl: apiUrl,
|
|
457
|
+
timeoutMs,
|
|
458
|
+
userAgent: `inboxy-cli/${CLI_VERSION}`,
|
|
459
|
+
});
|
|
460
|
+
const { data } = await client.getCompany();
|
|
461
|
+
company = { id: data.company.id, name: data.company.name };
|
|
462
|
+
}
|
|
463
|
+
const keychain = storeOpt === 'file' ? null : await keychainFor();
|
|
464
|
+
if (storeOpt === 'keychain' && !keychain) {
|
|
465
|
+
throw new InboxyError({
|
|
466
|
+
kind: 'config',
|
|
467
|
+
code: 'KEYCHAIN_UNAVAILABLE',
|
|
468
|
+
message: 'No OS keychain is available on this machine. Use --store file, or set INBOXY_API_KEY.',
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
const loaded = await loadConfig(env);
|
|
472
|
+
const config = loaded.config;
|
|
473
|
+
if (keychain) {
|
|
474
|
+
await keychain.set(profileName, key);
|
|
475
|
+
config.profiles[profileName] = { apiUrl, keyStorage: 'keychain' };
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
config.profiles[profileName] = { apiUrl, keyStorage: 'file', apiKey: key };
|
|
479
|
+
}
|
|
480
|
+
if (!config.defaultProfile)
|
|
481
|
+
config.defaultProfile = profileName;
|
|
482
|
+
const file = await saveConfig(config, env);
|
|
483
|
+
const result = {
|
|
484
|
+
profile: profileName,
|
|
485
|
+
apiUrl,
|
|
486
|
+
keyStorage: keychain ? 'keychain' : 'file',
|
|
487
|
+
keychain: keychain?.name ?? null,
|
|
488
|
+
configPath: file,
|
|
489
|
+
verified: company !== null,
|
|
490
|
+
company,
|
|
491
|
+
};
|
|
492
|
+
if (!keychain)
|
|
493
|
+
out.note(`No OS keychain in use: the key is stored in ${file} (mode 600).`);
|
|
494
|
+
return out.success(result, undefined, () => `Saved profile "${profileName}" (${keychain ? keychain.name : `file ${file}`}).${company ? ` Company: ${company.name}.` : ' Not verified (--no-verify).'}`);
|
|
495
|
+
}
|
|
496
|
+
case 'auth logout': {
|
|
497
|
+
noPositionals();
|
|
498
|
+
const loaded = await loadConfig(env);
|
|
499
|
+
const profileName = profile ?? io.env.INBOXY_PROFILE ?? loaded.config.defaultProfile ?? 'default';
|
|
500
|
+
validateProfileName(profileName);
|
|
501
|
+
const keychain = await keychainFor();
|
|
502
|
+
let removedFromKeychain = false;
|
|
503
|
+
if (keychain)
|
|
504
|
+
removedFromKeychain = await keychain.delete(profileName).catch(() => false);
|
|
505
|
+
const had = profileName in loaded.config.profiles;
|
|
506
|
+
if (had) {
|
|
507
|
+
delete loaded.config.profiles[profileName];
|
|
508
|
+
if (loaded.config.defaultProfile === profileName)
|
|
509
|
+
delete loaded.config.defaultProfile;
|
|
510
|
+
await saveConfig(loaded.config, env);
|
|
511
|
+
}
|
|
512
|
+
const result = { profile: profileName, removedFromKeychain, removedFromConfig: had };
|
|
513
|
+
return out.success(result, undefined, () => had || removedFromKeychain
|
|
514
|
+
? `Removed profile "${profileName}".`
|
|
515
|
+
: `Profile "${profileName}" was not stored.`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
throw new UsageError(`Unknown command "${name}".`);
|
|
519
|
+
}
|
|
520
|
+
catch (error) {
|
|
521
|
+
return out.failure(error);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async function listPages(fetchPage, query, opts) {
|
|
525
|
+
const maxPages = intOption(opts['max-pages'], 'max-pages', 1, 1000);
|
|
526
|
+
if (maxPages !== undefined && !opts.all)
|
|
527
|
+
throw new UsageError('--max-pages needs --all.');
|
|
528
|
+
if (!opts.all) {
|
|
529
|
+
const page = await fetchPage(query);
|
|
530
|
+
return { items: page.data, meta: { ...page.meta, pages: 1 } };
|
|
531
|
+
}
|
|
532
|
+
const all = await collectPages(fetchPage, query, maxPages ?? 10);
|
|
533
|
+
return { items: all.items, meta: { ...all.meta, pages: all.pages } };
|
|
534
|
+
}
|
|
535
|
+
function pagingHint(meta) {
|
|
536
|
+
return meta.hasMore && meta.nextCursor ? `More results: --cursor ${meta.nextCursor}` : '';
|
|
537
|
+
}
|
|
538
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `inboxy doctor` — checks the local setup end to end and says what to fix.
|
|
3
|
+
* Every check is read-only. The key is never printed (only its source and the
|
|
4
|
+
* same short prefix the dashboard shows).
|
|
5
|
+
*/
|
|
6
|
+
import { type ResolvedCredentials } from '@inboxychat/sdk';
|
|
7
|
+
export type CheckStatus = 'pass' | 'warn' | 'fail' | 'skip';
|
|
8
|
+
export interface Check {
|
|
9
|
+
id: string;
|
|
10
|
+
status: CheckStatus;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
export interface DoctorReport {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
profile: string;
|
|
16
|
+
apiUrl: string;
|
|
17
|
+
checks: Check[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Scopes the CLI's read commands use, derived from the capability each
|
|
21
|
+
* command is an adapter of (UX26-F): scope → the commands that need it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const CLI_SCOPES: Record<string, string>;
|
|
24
|
+
export declare const SKEW_WARN_SECONDS = 60;
|
|
25
|
+
export declare const SKEW_FAIL_SECONDS = 300;
|
|
26
|
+
export declare function runDoctor(creds: ResolvedCredentials, options: {
|
|
27
|
+
env: NodeJS.ProcessEnv;
|
|
28
|
+
timeoutMs?: number;
|
|
29
|
+
now: () => number;
|
|
30
|
+
credentialError?: string;
|
|
31
|
+
}): Promise<DoctorReport>;
|
|
32
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAUL,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQxC,CAAC;AAEP,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAGrC,wBAAsB,SAAS,CAC7B,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE;IACP,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,OAAO,CAAC,YAAY,CAAC,CAwIvB"}
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `inboxy doctor` — checks the local setup end to end and says what to fix.
|
|
3
|
+
* Every check is read-only. The key is never printed (only its source and the
|
|
4
|
+
* same short prefix the dashboard shows).
|
|
5
|
+
*/
|
|
6
|
+
import { InboxyClient, InboxyError, describeError, isModeTooOpen, loadConfig, looksLikeInboxyKey, normalizeBaseUrl, PUBLIC_CAPABILITIES, } from '@inboxychat/sdk';
|
|
7
|
+
/**
|
|
8
|
+
* Scopes the CLI's read commands use, derived from the capability each
|
|
9
|
+
* command is an adapter of (UX26-F): scope → the commands that need it.
|
|
10
|
+
*/
|
|
11
|
+
export const CLI_SCOPES = PUBLIC_CAPABILITIES.reduce((acc, capability) => {
|
|
12
|
+
if (!capability.cliCommand || !capability.scope)
|
|
13
|
+
return acc;
|
|
14
|
+
acc[capability.scope] = acc[capability.scope]
|
|
15
|
+
? `${acc[capability.scope]}, ${capability.cliCommand}`
|
|
16
|
+
: capability.cliCommand;
|
|
17
|
+
return acc;
|
|
18
|
+
}, {});
|
|
19
|
+
export const SKEW_WARN_SECONDS = 60;
|
|
20
|
+
export const SKEW_FAIL_SECONDS = 300;
|
|
21
|
+
const EXPIRY_WARN_DAYS = 7;
|
|
22
|
+
export async function runDoctor(creds, options) {
|
|
23
|
+
const checks = [];
|
|
24
|
+
const add = (id, status, message) => checks.push({ id, status, message });
|
|
25
|
+
// 1. Config file
|
|
26
|
+
const loaded = await loadConfig(options.env);
|
|
27
|
+
if (!loaded.exists)
|
|
28
|
+
add('config-file', 'pass', `No config file (${loaded.path}); using environment/defaults.`);
|
|
29
|
+
else if (isModeTooOpen(loaded.mode)) {
|
|
30
|
+
const holdsKey = Object.values(loaded.config.profiles).some((p) => !!p.apiKey);
|
|
31
|
+
add('config-file', holdsKey ? 'fail' : 'warn', `${loaded.path} is readable by other users (mode ${(loaded.mode ?? 0).toString(8)}). Run: chmod 600 "${loaded.path}"`);
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
add('config-file', 'pass', `${loaded.path} (mode ${loaded.mode === null ? 'n/a' : loaded.mode.toString(8)})`);
|
|
35
|
+
// 2. API URL
|
|
36
|
+
let urlOk = true;
|
|
37
|
+
try {
|
|
38
|
+
const url = normalizeBaseUrl(creds.apiUrl);
|
|
39
|
+
add('api-url', 'pass', `${url} (from ${creds.urlSource})`);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
urlOk = false;
|
|
43
|
+
add('api-url', 'fail', error instanceof InboxyError ? error.message : 'Invalid API URL.');
|
|
44
|
+
}
|
|
45
|
+
// 3. Key present + format
|
|
46
|
+
if (options.credentialError) {
|
|
47
|
+
add('api-key', 'fail', options.credentialError);
|
|
48
|
+
}
|
|
49
|
+
else if (!creds.apiKey) {
|
|
50
|
+
add('api-key', 'fail', 'No API key. Set INBOXY_API_KEY or run `inboxy auth login`.');
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
add('api-key', 'pass', `Found (from ${creds.keySource}, starts ${creds.apiKey.slice(0, 8)}…).`);
|
|
54
|
+
add('key-format', looksLikeInboxyKey(creds.apiKey) ? 'pass' : 'warn', looksLikeInboxyKey(creds.apiKey)
|
|
55
|
+
? 'Looks like an Inboxy key (inboxy_ + 64 hex).'
|
|
56
|
+
: 'Does not look like an Inboxy key (expected inboxy_ followed by 64 hex characters).');
|
|
57
|
+
}
|
|
58
|
+
for (const w of creds.warnings)
|
|
59
|
+
add('keychain', 'warn', w);
|
|
60
|
+
// 4. Reach the API with the key
|
|
61
|
+
let company = null;
|
|
62
|
+
if (!creds.apiKey || !urlOk) {
|
|
63
|
+
add('api-reachable', 'skip', 'Skipped: no key or invalid URL.');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const client = new InboxyClient({
|
|
67
|
+
apiKey: creds.apiKey,
|
|
68
|
+
baseUrl: creds.apiUrl,
|
|
69
|
+
timeoutMs: options.timeoutMs,
|
|
70
|
+
});
|
|
71
|
+
const started = options.now();
|
|
72
|
+
try {
|
|
73
|
+
const { body, info } = await client.request('/company');
|
|
74
|
+
company = body.data;
|
|
75
|
+
add('api-reachable', 'pass', `Inboxy answered in ${info.latencyMs} ms.`);
|
|
76
|
+
add('key-valid', 'pass', `Key "${company.token.name}" belongs to ${company.company.name} (${company.company.id}).`);
|
|
77
|
+
// Clock skew: server Date (1 s resolution) vs the request's midpoint.
|
|
78
|
+
if (info.date) {
|
|
79
|
+
const server = Date.parse(info.date);
|
|
80
|
+
const local = started + info.latencyMs / 2;
|
|
81
|
+
const skew = Math.round((local - server) / 1000);
|
|
82
|
+
const abs = Math.abs(skew);
|
|
83
|
+
const status = abs > SKEW_FAIL_SECONDS ? 'fail' : abs > SKEW_WARN_SECONDS ? 'warn' : 'pass';
|
|
84
|
+
add('clock-skew', status, abs <= 1
|
|
85
|
+
? 'Local clock matches the server.'
|
|
86
|
+
: `Local clock is ${abs} s ${skew > 0 ? 'ahead of' : 'behind'} the server${status === 'pass' ? '.' : '. Enable automatic time sync (NTP).'}`);
|
|
87
|
+
}
|
|
88
|
+
else
|
|
89
|
+
add('clock-skew', 'skip', 'The server sent no Date header.');
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const err = error instanceof InboxyError ? error : null;
|
|
93
|
+
if (err && (err.kind === 'network' || err.kind === 'timeout')) {
|
|
94
|
+
add('api-reachable', 'fail', describeError(err));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
add('api-reachable', 'pass', 'Inboxy answered.');
|
|
98
|
+
add('key-valid', 'fail', err ? `${err.code}: ${describeError(err)}` : 'Unexpected error.');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 5. Scopes and expiry (need a valid key)
|
|
103
|
+
if (company) {
|
|
104
|
+
const scopes = new Set(company.token.scopes);
|
|
105
|
+
const missing = Object.entries(CLI_SCOPES).filter(([s]) => !scopes.has(s));
|
|
106
|
+
add('scopes', missing.length ? 'warn' : 'pass', missing.length
|
|
107
|
+
? `Missing ${missing.map(([s, cmds]) => `${s} (${cmds})`).join(', ')}. Key scopes: ${[...scopes].join(', ') || 'none'}.`
|
|
108
|
+
: `Key has ${[...scopes].join(', ')}.`);
|
|
109
|
+
const expiresAt = company.token.expiresAt ? Date.parse(company.token.expiresAt) : null;
|
|
110
|
+
if (expiresAt === null)
|
|
111
|
+
add('key-expiry', 'pass', 'The key does not expire.');
|
|
112
|
+
else {
|
|
113
|
+
const days = (expiresAt - options.now()) / 86_400_000;
|
|
114
|
+
add('key-expiry', days <= 0 ? 'fail' : days <= EXPIRY_WARN_DAYS ? 'warn' : 'pass', days <= 0
|
|
115
|
+
? 'The key has expired.'
|
|
116
|
+
: `The key expires ${company.token.expiresAt} (in ${Math.ceil(days)} day${Math.ceil(days) === 1 ? '' : 's'}).`);
|
|
117
|
+
}
|
|
118
|
+
add('rate-limits', 'pass', `${company.rateLimits.perKey.limit}/${company.rateLimits.perKey.windowSeconds}s per key, ${company.rateLimits.perCompany.limit}/${company.rateLimits.perCompany.windowSeconds}s per company.`);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
ok: !checks.some((c) => c.status === 'fail'),
|
|
122
|
+
profile: creds.profile,
|
|
123
|
+
apiUrl: creds.apiUrl,
|
|
124
|
+
checks,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output contract of the `inboxy` CLI.
|
|
3
|
+
*
|
|
4
|
+
* --json prints exactly one JSON document on stdout (schemaVersion 1):
|
|
5
|
+
* success: { schemaVersion: 1, ok: true, command, data, meta? }
|
|
6
|
+
* failure: { schemaVersion: 1, ok: false, command, error: { kind, code, message, status, details, retryAfterSeconds } }
|
|
7
|
+
* Fields may be added within schemaVersion 1; none is renamed or removed.
|
|
8
|
+
*
|
|
9
|
+
* Exit codes are stable and documented in the README.
|
|
10
|
+
*/
|
|
11
|
+
import { type InboxyErrorKind } from '@inboxychat/sdk';
|
|
12
|
+
export declare const JSON_SCHEMA_VERSION = 1;
|
|
13
|
+
export declare const EXIT: {
|
|
14
|
+
readonly OK: 0;
|
|
15
|
+
readonly UNEXPECTED: 1;
|
|
16
|
+
readonly USAGE: 2;
|
|
17
|
+
readonly CONFIG: 3;
|
|
18
|
+
readonly AUTH: 4;
|
|
19
|
+
readonly FORBIDDEN: 5;
|
|
20
|
+
readonly NOT_FOUND: 6;
|
|
21
|
+
readonly RATE_LIMITED: 7;
|
|
22
|
+
readonly NETWORK: 8;
|
|
23
|
+
readonly SERVER: 9;
|
|
24
|
+
readonly CHECKS_FAILED: 10;
|
|
25
|
+
};
|
|
26
|
+
export declare function exitCodeFor(kind: InboxyErrorKind): number;
|
|
27
|
+
export declare class UsageError extends Error {
|
|
28
|
+
constructor(message: string);
|
|
29
|
+
}
|
|
30
|
+
export interface CliIO {
|
|
31
|
+
stdout(text: string): void;
|
|
32
|
+
stderr(text: string): void;
|
|
33
|
+
/** Reads the API key for `auth login` (piped stdin, or a hidden prompt on a TTY). */
|
|
34
|
+
readSecret(prompt: string): Promise<string>;
|
|
35
|
+
env: NodeJS.ProcessEnv;
|
|
36
|
+
now(): number;
|
|
37
|
+
}
|
|
38
|
+
export declare class Output {
|
|
39
|
+
private readonly io;
|
|
40
|
+
private readonly json;
|
|
41
|
+
private readonly command;
|
|
42
|
+
/** Secrets that must never reach the terminal (the key in use). */
|
|
43
|
+
private readonly secrets;
|
|
44
|
+
constructor(io: CliIO, json: boolean, command: string,
|
|
45
|
+
/** Secrets that must never reach the terminal (the key in use). */
|
|
46
|
+
secrets: () => string[]);
|
|
47
|
+
private clean;
|
|
48
|
+
/** Success. `human` renders the non-JSON view. */
|
|
49
|
+
success(data: unknown, meta: unknown, human: () => string): number;
|
|
50
|
+
failure(error: unknown): number;
|
|
51
|
+
/** Progress or hints for humans; suppressed in --json mode. */
|
|
52
|
+
note(text: string): void;
|
|
53
|
+
}
|
|
54
|
+
/** A plain aligned table; cells are flattened to one line. */
|
|
55
|
+
export declare function table(headers: string[], rows: Array<Array<string | number | null | undefined>>): string;
|
|
56
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAA6C,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElG,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,eAAO,MAAM,IAAI;;;;;;;;;;;;CAYP,CAAC;AAEX,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAwBzD;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,qFAAqF;IACrF,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,GAAG,IAAI,MAAM,CAAC;CACf;AAED,qBAAa,MAAM;IAEf,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAJP,EAAE,EAAE,KAAK,EACT,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM;IAChC,mEAAmE;IAClD,OAAO,EAAE,MAAM,MAAM,EAAE;IAG1C,OAAO,CAAC,KAAK;IAIb,kDAAkD;IAClD,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,GAAG,MAAM;IAiBlE,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAqD/B,+DAA+D;IAC/D,IAAI,CAAC,IAAI,EAAE,MAAM;CAGlB;AAED,8DAA8D;AAC9D,wBAAgB,KAAK,CACnB,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GACrD,MAAM,CAiBR"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output contract of the `inboxy` CLI.
|
|
3
|
+
*
|
|
4
|
+
* --json prints exactly one JSON document on stdout (schemaVersion 1):
|
|
5
|
+
* success: { schemaVersion: 1, ok: true, command, data, meta? }
|
|
6
|
+
* failure: { schemaVersion: 1, ok: false, command, error: { kind, code, message, status, details, retryAfterSeconds } }
|
|
7
|
+
* Fields may be added within schemaVersion 1; none is renamed or removed.
|
|
8
|
+
*
|
|
9
|
+
* Exit codes are stable and documented in the README.
|
|
10
|
+
*/
|
|
11
|
+
import { InboxyError, describeError, redactSecrets } from '@inboxychat/sdk';
|
|
12
|
+
export const JSON_SCHEMA_VERSION = 1;
|
|
13
|
+
export const EXIT = {
|
|
14
|
+
OK: 0,
|
|
15
|
+
UNEXPECTED: 1,
|
|
16
|
+
USAGE: 2,
|
|
17
|
+
CONFIG: 3,
|
|
18
|
+
AUTH: 4,
|
|
19
|
+
FORBIDDEN: 5,
|
|
20
|
+
NOT_FOUND: 6,
|
|
21
|
+
RATE_LIMITED: 7,
|
|
22
|
+
NETWORK: 8,
|
|
23
|
+
SERVER: 9,
|
|
24
|
+
CHECKS_FAILED: 10,
|
|
25
|
+
};
|
|
26
|
+
export function exitCodeFor(kind) {
|
|
27
|
+
switch (kind) {
|
|
28
|
+
case 'config':
|
|
29
|
+
return EXIT.CONFIG;
|
|
30
|
+
case 'auth':
|
|
31
|
+
return EXIT.AUTH;
|
|
32
|
+
case 'forbidden':
|
|
33
|
+
return EXIT.FORBIDDEN;
|
|
34
|
+
case 'not_found':
|
|
35
|
+
return EXIT.NOT_FOUND;
|
|
36
|
+
case 'rate_limited':
|
|
37
|
+
return EXIT.RATE_LIMITED;
|
|
38
|
+
case 'timeout':
|
|
39
|
+
case 'cancelled':
|
|
40
|
+
case 'network':
|
|
41
|
+
return EXIT.NETWORK;
|
|
42
|
+
case 'server':
|
|
43
|
+
case 'invalid_response':
|
|
44
|
+
return EXIT.SERVER;
|
|
45
|
+
case 'invalid_request':
|
|
46
|
+
return EXIT.USAGE;
|
|
47
|
+
default:
|
|
48
|
+
return EXIT.UNEXPECTED;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export class UsageError extends Error {
|
|
52
|
+
constructor(message) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = 'UsageError';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class Output {
|
|
58
|
+
io;
|
|
59
|
+
json;
|
|
60
|
+
command;
|
|
61
|
+
secrets;
|
|
62
|
+
constructor(io, json, command,
|
|
63
|
+
/** Secrets that must never reach the terminal (the key in use). */
|
|
64
|
+
secrets) {
|
|
65
|
+
this.io = io;
|
|
66
|
+
this.json = json;
|
|
67
|
+
this.command = command;
|
|
68
|
+
this.secrets = secrets;
|
|
69
|
+
}
|
|
70
|
+
clean(text) {
|
|
71
|
+
return redactSecrets(text, this.secrets());
|
|
72
|
+
}
|
|
73
|
+
/** Success. `human` renders the non-JSON view. */
|
|
74
|
+
success(data, meta, human) {
|
|
75
|
+
if (this.json) {
|
|
76
|
+
const doc = {
|
|
77
|
+
schemaVersion: JSON_SCHEMA_VERSION,
|
|
78
|
+
ok: true,
|
|
79
|
+
command: this.command,
|
|
80
|
+
data,
|
|
81
|
+
};
|
|
82
|
+
if (meta !== undefined)
|
|
83
|
+
doc.meta = meta;
|
|
84
|
+
this.io.stdout(`${this.clean(JSON.stringify(doc, null, 2))}\n`);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const text = human();
|
|
88
|
+
if (text)
|
|
89
|
+
this.io.stdout(`${this.clean(text)}\n`);
|
|
90
|
+
}
|
|
91
|
+
return EXIT.OK;
|
|
92
|
+
}
|
|
93
|
+
failure(error) {
|
|
94
|
+
let payload;
|
|
95
|
+
let code;
|
|
96
|
+
let human;
|
|
97
|
+
if (error instanceof InboxyError) {
|
|
98
|
+
payload = { ...error.toJSON(), message: describeError(error) };
|
|
99
|
+
code = exitCodeFor(error.kind);
|
|
100
|
+
human = `Error (${error.code}): ${describeError(error)}`;
|
|
101
|
+
}
|
|
102
|
+
else if (error instanceof UsageError) {
|
|
103
|
+
payload = {
|
|
104
|
+
kind: 'usage',
|
|
105
|
+
code: 'USAGE',
|
|
106
|
+
message: error.message,
|
|
107
|
+
status: 0,
|
|
108
|
+
details: {},
|
|
109
|
+
retryAfterSeconds: null,
|
|
110
|
+
};
|
|
111
|
+
code = EXIT.USAGE;
|
|
112
|
+
human = `Error: ${error.message}\nRun \`inboxy --help\` for usage.`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const message = error instanceof Error ? error.message : 'Unexpected error';
|
|
116
|
+
payload = {
|
|
117
|
+
kind: 'unexpected',
|
|
118
|
+
code: 'UNEXPECTED',
|
|
119
|
+
message,
|
|
120
|
+
status: 0,
|
|
121
|
+
details: {},
|
|
122
|
+
retryAfterSeconds: null,
|
|
123
|
+
};
|
|
124
|
+
code = EXIT.UNEXPECTED;
|
|
125
|
+
human = `Error: ${message}`;
|
|
126
|
+
}
|
|
127
|
+
if (this.json) {
|
|
128
|
+
const doc = {
|
|
129
|
+
schemaVersion: JSON_SCHEMA_VERSION,
|
|
130
|
+
ok: false,
|
|
131
|
+
command: this.command,
|
|
132
|
+
error: payload,
|
|
133
|
+
};
|
|
134
|
+
this.io.stdout(`${this.clean(JSON.stringify(doc, null, 2))}\n`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this.io.stderr(`${this.clean(human)}\n`);
|
|
138
|
+
}
|
|
139
|
+
return code;
|
|
140
|
+
}
|
|
141
|
+
/** Progress or hints for humans; suppressed in --json mode. */
|
|
142
|
+
note(text) {
|
|
143
|
+
if (!this.json)
|
|
144
|
+
this.io.stderr(`${this.clean(text)}\n`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/** A plain aligned table; cells are flattened to one line. */
|
|
148
|
+
export function table(headers, rows) {
|
|
149
|
+
const cells = rows.map((r) => r.map((c) => (c === null || c === undefined ? '-' : String(c).replace(/\s+/g, ' '))));
|
|
150
|
+
const widths = headers.map((h, i) => Math.min(48, Math.max(h.length, ...cells.map((r) => (r[i] ?? '').length))));
|
|
151
|
+
const fmt = (r) => r
|
|
152
|
+
.map((c, i) => {
|
|
153
|
+
const w = widths[i];
|
|
154
|
+
const v = c.length > w ? `${c.slice(0, w - 1)}…` : c;
|
|
155
|
+
return v.padEnd(w);
|
|
156
|
+
})
|
|
157
|
+
.join(' ')
|
|
158
|
+
.trimEnd();
|
|
159
|
+
return [fmt(headers), fmt(widths.map((w) => '-'.repeat(w))), ...cells.map(fmt)].join('\n');
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inboxychat/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Inboxy command line: read-only account, orders, contacts and usage, plus doctor diagnostics.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"inboxy": "./dist/bin.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"!dist/.tsbuildinfo",
|
|
13
|
+
"!dist/**/*.tsbuildinfo"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=20.3.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@inboxychat/sdk": "0.1.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^20.10.0",
|
|
23
|
+
"typescript": "^5.3.0",
|
|
24
|
+
"vitest": "^4.0.16"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://inboxy.chat",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc -b tsconfig.build.json",
|
|
32
|
+
"type-check": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"clean": "rm -rf dist .turbo"
|
|
35
|
+
}
|
|
6
36
|
}
|