@eventmodelers/cli 0.0.24 → 0.0.25
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/cli.js +26 -9
- package/lib/fetch.js +15 -0
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ import { execSync, spawn } from 'child_process';
|
|
|
18
18
|
import { createInterface, emitKeypressEvents, moveCursor, clearScreenDown } from 'readline';
|
|
19
19
|
import { homedir } from 'os';
|
|
20
20
|
import { randomUUID } from 'crypto';
|
|
21
|
-
import { runFetch } from './lib/fetch.js';
|
|
21
|
+
import { runFetch, FetchAuthError } from './lib/fetch.js';
|
|
22
22
|
|
|
23
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
24
|
const __dirname = dirname(__filename);
|
|
@@ -1467,14 +1467,16 @@ program
|
|
|
1467
1467
|
const effective = loadEffectiveConfig(cwd, kitDir, explicitConfig);
|
|
1468
1468
|
let cfg = effective.config;
|
|
1469
1469
|
|
|
1470
|
+
// Same default (project-root .eventmodelers/config.json, or --config) that
|
|
1471
|
+
// installStack uses — kept identical rather than deriving a path from
|
|
1472
|
+
// `effective`, which can point at a kit-dir-scoped config instead.
|
|
1473
|
+
const configPath = explicitConfig ? resolve(cwd, explicitConfig) : join(cwd, '.eventmodelers', 'config.json');
|
|
1470
1474
|
const requiredFields = ['organizationId', 'boardId', 'token'];
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
// Same prompt (paste/manual/instructions/skip) `install`/`init-config` use —
|
|
1477
|
-
// reusing it here means `fetch` also works as a first-run credential setup.
|
|
1475
|
+
|
|
1476
|
+
// Same prompt (paste/manual/instructions/skip) `install`/`init-config` use —
|
|
1477
|
+
// reusing it here means `fetch` also works as a first-run credential setup.
|
|
1478
|
+
// Also re-entered below if the API rejects whatever we already had.
|
|
1479
|
+
async function promptForCredentials() {
|
|
1478
1480
|
cfg = await configureCredentials({
|
|
1479
1481
|
config: cfg,
|
|
1480
1482
|
configPath,
|
|
@@ -1489,7 +1491,22 @@ program
|
|
|
1489
1491
|
process.exit(1);
|
|
1490
1492
|
}
|
|
1491
1493
|
}
|
|
1492
|
-
|
|
1494
|
+
|
|
1495
|
+
if (requiredFields.some((f) => !cfg[f])) await promptForCredentials();
|
|
1496
|
+
|
|
1497
|
+
try {
|
|
1498
|
+
await runFetch({ cwd, kitDir, cfg, opts });
|
|
1499
|
+
} catch (err) {
|
|
1500
|
+
if (!(err instanceof FetchAuthError)) throw err;
|
|
1501
|
+
// Present but wrong, not missing — the connect skill's Step 4 (Verify) treats
|
|
1502
|
+
// 401/403/404 the same way: clear the field that's implicated and re-prompt,
|
|
1503
|
+
// rather than leaving the caller stuck re-running with the same bad value.
|
|
1504
|
+
console.error(`❌ ${err.message}`);
|
|
1505
|
+
if (err.status === 404) delete cfg.boardId;
|
|
1506
|
+
else delete cfg.token;
|
|
1507
|
+
await promptForCredentials();
|
|
1508
|
+
await runFetch({ cwd, kitDir, cfg, opts });
|
|
1509
|
+
}
|
|
1493
1510
|
});
|
|
1494
1511
|
|
|
1495
1512
|
program
|
package/lib/fetch.js
CHANGED
|
@@ -3,6 +3,18 @@ import { join, relative } from 'path';
|
|
|
3
3
|
|
|
4
4
|
const DEFAULT_BASE_URL = 'https://api.eventmodelers.ai';
|
|
5
5
|
|
|
6
|
+
// Thrown instead of exiting on 401/403/404 — these mean the *credentials* (not the
|
|
7
|
+
// network/server) are the problem, so the caller gets a chance to re-prompt and retry
|
|
8
|
+
// instead of just dying, the same way the connect skill's Step 4 (Verify) reacts to
|
|
9
|
+
// each status. Other statuses (500, etc.) still exit directly — reconfiguring
|
|
10
|
+
// credentials wouldn't fix those.
|
|
11
|
+
export class FetchAuthError extends Error {
|
|
12
|
+
constructor(status, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.status = status;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
6
18
|
function readJsonSafe(path) {
|
|
7
19
|
if (!path || !existsSync(path)) return {};
|
|
8
20
|
try {
|
|
@@ -50,6 +62,9 @@ export async function runFetch({ cwd, kitDir, cfg, opts = {} }) {
|
|
|
50
62
|
console.error(`❌ Request failed (${what}): ${err.message}`);
|
|
51
63
|
process.exit(1);
|
|
52
64
|
}
|
|
65
|
+
if (res.status === 401) throw new FetchAuthError(401, `${what}: invalid or expired token`);
|
|
66
|
+
if (res.status === 403) throw new FetchAuthError(403, `${what}: token's organization does not match this board`);
|
|
67
|
+
if (res.status === 404) throw new FetchAuthError(404, `${what}: board not found`);
|
|
53
68
|
if (!res.ok) {
|
|
54
69
|
console.error(`❌ ${what}: HTTP ${res.status}`);
|
|
55
70
|
process.exit(1);
|
package/package.json
CHANGED