@eventmodelers/cli 0.0.24 → 0.0.26
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 +30 -12
- package/lib/fetch.js +18 -1
- 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);
|
|
@@ -1110,10 +1110,11 @@ program
|
|
|
1110
1110
|
|
|
1111
1111
|
// Commands exempt from the "is a kit installed here?" gate below: init (with or
|
|
1112
1112
|
// without --modeling) is what installs one in the first place, init-config only
|
|
1113
|
-
// ever touches credentials,
|
|
1113
|
+
// ever touches credentials, stacks/status/config/uninstall are read-only or
|
|
1114
1114
|
// cleanup commands that are meant to work — and report something useful — whether
|
|
1115
|
-
// or not a kit is present
|
|
1116
|
-
|
|
1115
|
+
// or not a kit is present, and fetch only needs credentials plus somewhere to write
|
|
1116
|
+
// .slices/ (cwd, absent a kit dir — see lib/fetch.js), no kit-specific files.
|
|
1117
|
+
const NO_INIT_REQUIRED = new Set(['init', 'init-config', 'stacks', 'status', 'config', 'uninstall', 'fetch']);
|
|
1117
1118
|
|
|
1118
1119
|
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
1119
1120
|
if (NO_INIT_REQUIRED.has(actionCommand.name())) return;
|
|
@@ -1467,14 +1468,16 @@ program
|
|
|
1467
1468
|
const effective = loadEffectiveConfig(cwd, kitDir, explicitConfig);
|
|
1468
1469
|
let cfg = effective.config;
|
|
1469
1470
|
|
|
1471
|
+
// Same default (project-root .eventmodelers/config.json, or --config) that
|
|
1472
|
+
// installStack uses — kept identical rather than deriving a path from
|
|
1473
|
+
// `effective`, which can point at a kit-dir-scoped config instead.
|
|
1474
|
+
const configPath = explicitConfig ? resolve(cwd, explicitConfig) : join(cwd, '.eventmodelers', 'config.json');
|
|
1470
1475
|
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.
|
|
1476
|
+
|
|
1477
|
+
// Same prompt (paste/manual/instructions/skip) `install`/`init-config` use —
|
|
1478
|
+
// reusing it here means `fetch` also works as a first-run credential setup.
|
|
1479
|
+
// Also re-entered below if the API rejects whatever we already had.
|
|
1480
|
+
async function promptForCredentials() {
|
|
1478
1481
|
cfg = await configureCredentials({
|
|
1479
1482
|
config: cfg,
|
|
1480
1483
|
configPath,
|
|
@@ -1489,7 +1492,22 @@ program
|
|
|
1489
1492
|
process.exit(1);
|
|
1490
1493
|
}
|
|
1491
1494
|
}
|
|
1492
|
-
|
|
1495
|
+
|
|
1496
|
+
if (requiredFields.some((f) => !cfg[f])) await promptForCredentials();
|
|
1497
|
+
|
|
1498
|
+
try {
|
|
1499
|
+
await runFetch({ cwd, kitDir, cfg, opts });
|
|
1500
|
+
} catch (err) {
|
|
1501
|
+
if (!(err instanceof FetchAuthError)) throw err;
|
|
1502
|
+
// Present but wrong, not missing — the connect skill's Step 4 (Verify) treats
|
|
1503
|
+
// 401/403/404 the same way: clear the field that's implicated and re-prompt,
|
|
1504
|
+
// rather than leaving the caller stuck re-running with the same bad value.
|
|
1505
|
+
console.error(`❌ ${err.message}`);
|
|
1506
|
+
if (err.status === 404) delete cfg.boardId;
|
|
1507
|
+
else delete cfg.token;
|
|
1508
|
+
await promptForCredentials();
|
|
1509
|
+
await runFetch({ cwd, kitDir, cfg, opts });
|
|
1510
|
+
}
|
|
1493
1511
|
});
|
|
1494
1512
|
|
|
1495
1513
|
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);
|
|
@@ -92,7 +107,9 @@ export async function runFetch({ cwd, kitDir, cfg, opts = {} }) {
|
|
|
92
107
|
return;
|
|
93
108
|
}
|
|
94
109
|
|
|
95
|
-
|
|
110
|
+
// Falls back to cwd when no kit is installed — fetch doesn't need kit-specific
|
|
111
|
+
// files, just somewhere to write .slices/.
|
|
112
|
+
const SLICES_DIR = join(kitDir || cwd, '.slices');
|
|
96
113
|
const contextNames = new Set();
|
|
97
114
|
|
|
98
115
|
for (const slice of allSlices) {
|
package/package.json
CHANGED