komplian 0.6.1 → 0.7.1
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 +1 -1
- package/komplian-db-all-dev.mjs +32 -29
- package/komplian-localhost.mjs +73 -48
- package/komplian-mcp-tools.mjs +46 -41
- package/komplian-onboard.mjs +42 -19
- package/komplian-postman.mjs +57 -19
- package/komplian-setup.mjs +668 -0
- package/package.json +4 -3
package/komplian-onboard.mjs
CHANGED
|
@@ -37,6 +37,7 @@ const c = {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
function log(s = "") {
|
|
40
|
+
if (process.env.KOMPLIAN_CLI_QUIET === "1") return;
|
|
40
41
|
console.log(s);
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -247,12 +248,14 @@ function cloudLine(org, name, status) {
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
function cloneOne(org, name, workspace, useSsh) {
|
|
251
|
+
const q = process.env.KOMPLIAN_CLI_QUIET === "1";
|
|
250
252
|
const gitDir = join(workspace, name, ".git");
|
|
251
253
|
if (existsSync(gitDir)) {
|
|
252
|
-
log(
|
|
254
|
+
if (q) console.log(`${c.yellow}○${c.reset} ${name}`);
|
|
255
|
+
else log(cloudLine(org, name, "skip"));
|
|
253
256
|
return true;
|
|
254
257
|
}
|
|
255
|
-
process.stdout.write(`\r${cloudLine(org, name, "pending")}`);
|
|
258
|
+
if (!q) process.stdout.write(`\r${cloudLine(org, name, "pending")}`);
|
|
256
259
|
const args = useSsh
|
|
257
260
|
? ["clone", `git@github.com:${org}/${name}.git`, name]
|
|
258
261
|
: ["repo", "clone", `${org}/${name}`, name];
|
|
@@ -264,13 +267,17 @@ function cloneOne(org, name, workspace, useSsh) {
|
|
|
264
267
|
stdio: ["ignore", "pipe", "pipe"],
|
|
265
268
|
}),
|
|
266
269
|
});
|
|
267
|
-
process.stdout.write("\r\x1b[K");
|
|
270
|
+
if (!q) process.stdout.write("\r\x1b[K");
|
|
268
271
|
if (r.status === 0) {
|
|
269
|
-
log(
|
|
272
|
+
if (q) console.log(`${c.green}✓${c.reset} ${name}`);
|
|
273
|
+
else log(cloudLine(org, name, "ok"));
|
|
270
274
|
return true;
|
|
271
275
|
}
|
|
272
|
-
|
|
273
|
-
|
|
276
|
+
if (q) console.error(`${c.red}✗${c.reset} ${name}`);
|
|
277
|
+
else {
|
|
278
|
+
log(cloudLine(org, name, "fail"));
|
|
279
|
+
if (r.stderr) log(`${c.dim}${r.stderr.trim()}${c.reset}`);
|
|
280
|
+
}
|
|
274
281
|
return false;
|
|
275
282
|
}
|
|
276
283
|
|
|
@@ -315,6 +322,9 @@ function npmInstallOneRepo(dir, name) {
|
|
|
315
322
|
const pkg = join(dir, "package.json");
|
|
316
323
|
if (!existsSync(pkg)) return { ok: true, skipped: true };
|
|
317
324
|
|
|
325
|
+
const stdio =
|
|
326
|
+
process.env.KOMPLIAN_CLI_QUIET === "1" ? "ignore" : "inherit";
|
|
327
|
+
|
|
318
328
|
const yarnLock = join(dir, "yarn.lock");
|
|
319
329
|
const pnpmLock = join(dir, "pnpm-lock.yaml");
|
|
320
330
|
const npmLock = join(dir, "package-lock.json");
|
|
@@ -330,7 +340,7 @@ function npmInstallOneRepo(dir, name) {
|
|
|
330
340
|
const r = spawnSync(
|
|
331
341
|
"yarn",
|
|
332
342
|
["install", "--frozen-lockfile"],
|
|
333
|
-
spawnWin({ cwd: dir, stdio
|
|
343
|
+
spawnWin({ cwd: dir, stdio })
|
|
334
344
|
);
|
|
335
345
|
return { ok: r.status === 0, skipped: false };
|
|
336
346
|
}
|
|
@@ -346,7 +356,7 @@ function npmInstallOneRepo(dir, name) {
|
|
|
346
356
|
const r = spawnSync(
|
|
347
357
|
"pnpm",
|
|
348
358
|
["install", "--frozen-lockfile"],
|
|
349
|
-
spawnWin({ cwd: dir, stdio
|
|
359
|
+
spawnWin({ cwd: dir, stdio })
|
|
350
360
|
);
|
|
351
361
|
return { ok: r.status === 0, skipped: false };
|
|
352
362
|
}
|
|
@@ -360,7 +370,7 @@ function npmInstallOneRepo(dir, name) {
|
|
|
360
370
|
|
|
361
371
|
if (existsSync(npmLock)) {
|
|
362
372
|
log(`${c.dim}→${c.reset} ${name} ${c.dim}(npm ci — lock sin cambios)${c.reset}`);
|
|
363
|
-
const r = spawnSync("npm", ["ci", ...quiet], spawnWin({ cwd: dir, stdio
|
|
373
|
+
const r = spawnSync("npm", ["ci", ...quiet], spawnWin({ cwd: dir, stdio }));
|
|
364
374
|
if (r.status === 0) return { ok: true, skipped: false };
|
|
365
375
|
log(
|
|
366
376
|
`${c.yellow}○${c.reset} ${name}: npm ci falló (¿lock desincronizado?). ${c.dim}Revisa con npm install en ese repo.${c.reset}`
|
|
@@ -372,20 +382,25 @@ function npmInstallOneRepo(dir, name) {
|
|
|
372
382
|
const r = spawnSync(
|
|
373
383
|
"npm",
|
|
374
384
|
["install", ...quiet, "--no-package-lock"],
|
|
375
|
-
spawnWin({ cwd: dir, stdio
|
|
385
|
+
spawnWin({ cwd: dir, stdio })
|
|
376
386
|
);
|
|
377
387
|
return { ok: r.status === 0, skipped: false };
|
|
378
388
|
}
|
|
379
389
|
|
|
380
390
|
function npmInstallEach(workspace) {
|
|
381
|
-
|
|
382
|
-
|
|
391
|
+
const q = process.env.KOMPLIAN_CLI_QUIET === "1";
|
|
392
|
+
if (!q) {
|
|
393
|
+
log("");
|
|
394
|
+
log(`${c.cyan}━━ dependencies ━━${c.reset}`);
|
|
395
|
+
}
|
|
383
396
|
for (const ent of readdirSync(workspace)) {
|
|
384
397
|
const d = join(workspace, ent);
|
|
385
398
|
if (!statSync(d).isDirectory()) continue;
|
|
386
399
|
const { ok, skipped } = npmInstallOneRepo(d, ent);
|
|
387
400
|
if (skipped) continue;
|
|
388
|
-
if (
|
|
401
|
+
if (q) {
|
|
402
|
+
console.log(`${ok ? c.green + "✓" + c.reset : c.yellow + "○" + c.reset} ${ent}`);
|
|
403
|
+
} else if (ok) {
|
|
389
404
|
log(`${c.green}✓${c.reset} ${ent}`);
|
|
390
405
|
} else {
|
|
391
406
|
log(`${c.yellow}○${c.reset} ${ent}`);
|
|
@@ -394,10 +409,11 @@ function npmInstallEach(workspace) {
|
|
|
394
409
|
}
|
|
395
410
|
|
|
396
411
|
function usage() {
|
|
397
|
-
log(`Uso: komplian onboard | postman | mcp-tools | db:all:dev | localhost | db …`);
|
|
398
|
-
log(` ${c.bold}
|
|
412
|
+
log(`Uso: komplian setup | onboard | postman | mcp-tools | db:all:dev | localhost | db …`);
|
|
413
|
+
log(` ${c.bold}Todo en uno:${c.reset} ${c.cyan}npx komplian setup${c.reset} ${c.dim}(onboard+postman+mcp+db+localhost; formulario en navegador si hace falta)${c.reset}`);
|
|
414
|
+
log(` ${c.bold}Setup por pasos:${c.reset}`);
|
|
399
415
|
log(` 1. npx komplian onboard --yes`);
|
|
400
|
-
log(` 2. npx komplian postman
|
|
416
|
+
log(` 2. npx komplian postman --yes ${c.dim}(@komplian.com)${c.reset}`);
|
|
401
417
|
log(` 3. npx komplian mcp-tools --yes`);
|
|
402
418
|
log(` 4. npx komplian db:all:dev ${c.dim}(Postman + 3 URLs dev → ~/.komplian + .env.local)${c.reset}`);
|
|
403
419
|
log(` 5. npx komplian localhost --yes`);
|
|
@@ -486,6 +502,11 @@ function normalizeArgv(argv) {
|
|
|
486
502
|
|
|
487
503
|
async function main() {
|
|
488
504
|
const rawArgv = process.argv.slice(2);
|
|
505
|
+
if (rawArgv[0] === "setup") {
|
|
506
|
+
const { runSetup } = await import("./komplian-setup.mjs");
|
|
507
|
+
await runSetup(rawArgv.slice(1));
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
489
510
|
if (rawArgv[0] === "postman") {
|
|
490
511
|
const { runPostman } = await import("./komplian-postman.mjs");
|
|
491
512
|
await runPostman(rawArgv.slice(1));
|
|
@@ -566,13 +587,15 @@ async function main() {
|
|
|
566
587
|
);
|
|
567
588
|
|
|
568
589
|
if (!ghOk()) {
|
|
569
|
-
|
|
590
|
+
console.error(`${c.red}✗${c.reset} GitHub CLI not logged in.`);
|
|
570
591
|
if (!runGhAuth()) {
|
|
571
|
-
|
|
592
|
+
console.error(`${c.red}✗${c.reset} GitHub auth cancelled.`);
|
|
572
593
|
process.exit(1);
|
|
573
594
|
}
|
|
574
595
|
}
|
|
575
|
-
|
|
596
|
+
if (!process.env.KOMPLIAN_CLI_QUIET) {
|
|
597
|
+
log(`${c.green}✓${c.reset} GitHub CLI OK`);
|
|
598
|
+
}
|
|
576
599
|
|
|
577
600
|
const org = process.env.KOMPLIAN_ORG || cfg.org || "Komplian";
|
|
578
601
|
verifyOrgMembership(org);
|
package/komplian-postman.mjs
CHANGED
|
@@ -35,6 +35,7 @@ const c = {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
function log(s = "") {
|
|
38
|
+
if (process.env.KOMPLIAN_CLI_QUIET === "1") return;
|
|
38
39
|
console.log(s);
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -126,9 +127,8 @@ function logApiFailure(context, status, body) {
|
|
|
126
127
|
extra = " [debug: no serializable]";
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
);
|
|
130
|
+
const line = `${c.yellow}○${c.reset} ${context}: HTTP ${status}${hint ? ` — ${hint}` : ""}${extra}`;
|
|
131
|
+
console.error(line);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
function ensureSecureKomplianDir() {
|
|
@@ -216,7 +216,7 @@ function defaultKeyPath() {
|
|
|
216
216
|
/**
|
|
217
217
|
* Orden: POSTMAN_API_KEY → ~/.komplian/postman-api-key (o KOMPLIAN_POSTMAN_KEY_FILE).
|
|
218
218
|
*/
|
|
219
|
-
function resolveApiKey() {
|
|
219
|
+
export function resolveApiKey() {
|
|
220
220
|
const env = process.env.POSTMAN_API_KEY?.trim();
|
|
221
221
|
if (env) return { key: env, source: "POSTMAN_API_KEY" };
|
|
222
222
|
const path = defaultKeyPath();
|
|
@@ -227,22 +227,31 @@ function resolveApiKey() {
|
|
|
227
227
|
return { key: "", source: null };
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
/** Guarda la clave en ~/.komplian/postman-api-key (uso: `komplian setup` vía navegador). */
|
|
231
|
+
export function savePostmanApiKeyToKomplianHome(apiKey) {
|
|
232
|
+
const k = (apiKey || "").trim();
|
|
233
|
+
if (!k) return false;
|
|
234
|
+
const keyPath = defaultKeyPath();
|
|
235
|
+
ensureSecureKomplianDir();
|
|
236
|
+
writeFileSync(keyPath, `${k}\n`, { encoding: "utf8", mode: 0o600 });
|
|
237
|
+
try {
|
|
238
|
+
chmodSync(keyPath, 0o600);
|
|
239
|
+
} catch {
|
|
240
|
+
/* Windows u otros */
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
|
|
230
245
|
function printMissingKeyHelp() {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
);
|
|
240
|
-
log(``);
|
|
241
|
-
log(` ${c.bold}Sin TTY (CI, pipes):${c.reset}`);
|
|
242
|
-
log(` ${c.dim}export POSTMAN_API_KEY=…${c.reset}`);
|
|
243
|
-
log(
|
|
244
|
-
`${c.dim} Archivo: ${formatHomePath(defaultKeyPath())} (permiso 600)${c.reset}`
|
|
245
|
-
);
|
|
246
|
+
const w = (s) => console.error(s);
|
|
247
|
+
w(`${c.red}✗${c.reset} No Postman API key.`);
|
|
248
|
+
w(``);
|
|
249
|
+
w(` ${c.bold}Interactive terminal:${c.reset}`);
|
|
250
|
+
w(` ${c.cyan}npx komplian postman --yes${c.reset}`);
|
|
251
|
+
w(` ${c.cyan}npx komplian postman login${c.reset}`);
|
|
252
|
+
w(``);
|
|
253
|
+
w(` ${c.bold}CI / no TTY:${c.reset} ${c.dim}POSTMAN_API_KEY${c.reset}`);
|
|
254
|
+
w(`${c.dim} ${formatHomePath(defaultKeyPath())}${c.reset}`);
|
|
246
255
|
process.exit(1);
|
|
247
256
|
}
|
|
248
257
|
|
|
@@ -656,6 +665,32 @@ async function pickWorkspaceId(apiKey, explicit) {
|
|
|
656
665
|
return w.id;
|
|
657
666
|
}
|
|
658
667
|
|
|
668
|
+
/** Validación sin `process.exit` (p. ej. formulario web local en `komplian setup`). */
|
|
669
|
+
export async function validatePostmanApiKeyForKomplian(apiKey, domain) {
|
|
670
|
+
const d = (domain || "komplian.com").trim().replace(/^@/, "");
|
|
671
|
+
const { ok, status, body } = await pmFetch(apiKey, "/me");
|
|
672
|
+
if (!ok) {
|
|
673
|
+
return {
|
|
674
|
+
ok: false,
|
|
675
|
+
error: `Postman rechazó la clave (HTTP ${status}).`,
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
const email = extractEmail(body);
|
|
679
|
+
if (!email) {
|
|
680
|
+
return {
|
|
681
|
+
ok: false,
|
|
682
|
+
error: "La API de Postman no devolvió email en /me.",
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
if (!emailAllowed(email, d)) {
|
|
686
|
+
return {
|
|
687
|
+
ok: false,
|
|
688
|
+
error: `Se requiere una cuenta con email @${d}.`,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
return { ok: true };
|
|
692
|
+
}
|
|
693
|
+
|
|
659
694
|
async function verifyKomplianEmail(apiKey, domain, opts = {}) {
|
|
660
695
|
const quietOk = opts.quietSuccess === true;
|
|
661
696
|
const { ok, status, body } = await pmFetch(apiKey, "/me");
|
|
@@ -994,6 +1029,9 @@ export async function runPostman(argv) {
|
|
|
994
1029
|
`${c.dim} Para rellenar apiKey: exporta API_KEY o pon api/.env y vuelve a ejecutar este comando.${c.reset}`
|
|
995
1030
|
);
|
|
996
1031
|
}
|
|
1032
|
+
if (process.env.KOMPLIAN_CLI_QUIET === "1") {
|
|
1033
|
+
console.log(`${c.green}✓${c.reset} postman`);
|
|
1034
|
+
}
|
|
997
1035
|
}
|
|
998
1036
|
|
|
999
1037
|
/**
|