@nexusbloom/cli 0.1.6 → 0.1.8
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/package.json +1 -1
- package/src/index.js +111 -25
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -159,7 +159,7 @@ program
|
|
|
159
159
|
.argument("<slug>", "Tool slug")
|
|
160
160
|
.argument("[args...]", "Key=value arguments (e.g. domain=example.com)")
|
|
161
161
|
.option("-k, --key <key>", "API key (or set NEXUSBLOOM_API_KEY env var)")
|
|
162
|
-
.option("-i, --input <json>", "Inline JSON input (e.g. '{\"domain\":\"example.com\"}')")
|
|
162
|
+
.option("-i, --input <json>", "Inline JSON input or @- for stdin (e.g. '{\"domain\":\"example.com\"}' or @-)")
|
|
163
163
|
.option("-f, --file <path>", "Read input from a JSON file")
|
|
164
164
|
.option("--local", "Execute coreLogic locally (fetches tool source, caches it)")
|
|
165
165
|
.action(async (slug, args, opts, cmd) => {
|
|
@@ -182,8 +182,23 @@ program
|
|
|
182
182
|
// ── Build input body ────────────────────────────────────────────────
|
|
183
183
|
let body = {};
|
|
184
184
|
|
|
185
|
-
//
|
|
186
|
-
|
|
185
|
+
// 0. Detect stdin pipe (auto-detect or explicit @-)
|
|
186
|
+
const isPiped = opts.input === "@-" || opts.input === "@stdin" || (!opts.input && !opts.file && !process.stdin.isTTY);
|
|
187
|
+
if (isPiped) {
|
|
188
|
+
try {
|
|
189
|
+
const stdin = await readStdin();
|
|
190
|
+
if (stdin && stdin.trim()) {
|
|
191
|
+
body = JSON.parse(stdin);
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
if (jsonMode) return console.log(JSON.stringify({ error: "Invalid JSON from stdin" }));
|
|
195
|
+
console.error(chalk.red("Error: Invalid JSON received from stdin"));
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 1. --input flag takes highest priority (skip if @- was used)
|
|
201
|
+
if (opts.input && opts.input !== "@-" && opts.input !== "@stdin") {
|
|
187
202
|
try {
|
|
188
203
|
body = JSON.parse(opts.input);
|
|
189
204
|
} catch {
|
|
@@ -409,9 +424,21 @@ program
|
|
|
409
424
|
program
|
|
410
425
|
.command("info")
|
|
411
426
|
.description("Show tool schema and details")
|
|
412
|
-
.argument("<slug>", "Tool slug")
|
|
427
|
+
.argument("<slug>", "Tool slug or abbreviation")
|
|
413
428
|
.action(async (slug, opts, cmd) => {
|
|
414
429
|
const jsonMode = (cmd?.parent?.opts().json) || false;
|
|
430
|
+
|
|
431
|
+
// Resolve abbreviation
|
|
432
|
+
try {
|
|
433
|
+
const res = await fetch(`${API_BASE}/api/tools`);
|
|
434
|
+
const { tools } = await res.json();
|
|
435
|
+
const slugs = (tools || []).map((t) => t.slug);
|
|
436
|
+
const abbrMap = generateAbbreviations(slugs);
|
|
437
|
+
if (abbrMap[slug] && slugs.includes(abbrMap[slug])) {
|
|
438
|
+
if (!jsonMode) console.log(chalk.dim(` Resolved: ${slug} → ${abbrMap[slug]}`));
|
|
439
|
+
slug = abbrMap[slug];
|
|
440
|
+
}
|
|
441
|
+
} catch { /* ignore */ }
|
|
415
442
|
try {
|
|
416
443
|
const res = await fetch(`${API_BASE}/api/run/${slug}`);
|
|
417
444
|
if (!res.ok) {
|
|
@@ -611,8 +638,6 @@ cacheCmd
|
|
|
611
638
|
console.log();
|
|
612
639
|
});
|
|
613
640
|
|
|
614
|
-
program.parse(process.argv);
|
|
615
|
-
|
|
616
641
|
// ─── Abbreviation generator ──────────────────────────────────────────────────
|
|
617
642
|
|
|
618
643
|
function generateAbbreviations(slugs) {
|
|
@@ -645,16 +670,32 @@ function generateAbbreviations(slugs) {
|
|
|
645
670
|
program
|
|
646
671
|
.command("abbr")
|
|
647
672
|
.description("Show tool abbreviations")
|
|
648
|
-
.
|
|
673
|
+
.argument("[query]", "Search/filter abbreviations (e.g. 'ip' shows all IP-related tools)")
|
|
674
|
+
.action(async (query, opts, cmd) => {
|
|
649
675
|
try {
|
|
650
676
|
const res = await fetch(`${API_BASE}/api/tools`);
|
|
651
677
|
const { tools } = await res.json();
|
|
652
678
|
const slugs = (tools || []).map((t) => t.slug);
|
|
653
679
|
const abbrMap = generateAbbreviations(slugs);
|
|
654
680
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
681
|
+
// Filter by query if provided
|
|
682
|
+
let filtered = slugs;
|
|
683
|
+
if (query) {
|
|
684
|
+
const q = query.toLowerCase();
|
|
685
|
+
filtered = slugs.filter(
|
|
686
|
+
(slug) => slug.includes(q) || abbrMap[slug].includes(q) || (tools || []).find(t => t.slug === slug)?.name?.toLowerCase().includes(q)
|
|
687
|
+
);
|
|
688
|
+
if (filtered.length === 0) {
|
|
689
|
+
console.log(chalk.yellow(` No abbreviations matching "${query}"`));
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
console.log(chalk.bold(`\n Tool Abbreviations${query ? ` matching "${query}"` : ""}:\n`));
|
|
695
|
+
filtered.forEach((slug) => {
|
|
696
|
+
const tool = (tools || []).find(t => t.slug === slug);
|
|
697
|
+
const name = tool?.name || slug;
|
|
698
|
+
console.log(` ${chalk.cyan(abbrMap[slug].padEnd(15))} → ${chalk.dim(slug.padEnd(30))} ${chalk.gray(name)}`);
|
|
658
699
|
});
|
|
659
700
|
console.log();
|
|
660
701
|
} catch (err) {
|
|
@@ -669,6 +710,8 @@ program
|
|
|
669
710
|
.description("Create JSON input for tools (pipe into nxb run)")
|
|
670
711
|
.option("-t, --template <slug>", "Generate JSON template for a specific tool")
|
|
671
712
|
.option("-i, --interactive", "Interactive mode - prompts for each field")
|
|
713
|
+
.option("-s, --set <key=value...>", "Set specific field values (e.g. -s count=10 format=csv)")
|
|
714
|
+
.option("-a, --add <json>", "Merge additional JSON into the output (e.g. -a '{\"count\":20}')")
|
|
672
715
|
.action(async (opts, cmd) => {
|
|
673
716
|
const jsonMode = cmd.parent.opts().json;
|
|
674
717
|
|
|
@@ -683,11 +726,12 @@ program
|
|
|
683
726
|
const manifest = data.data?.manifest || data.manifest || data;
|
|
684
727
|
const schema = manifest.input_schema || {};
|
|
685
728
|
|
|
729
|
+
let result = {};
|
|
730
|
+
|
|
686
731
|
if (opts.interactive) {
|
|
687
732
|
// Interactive mode
|
|
688
733
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
689
734
|
const ask = (q) => new Promise((r) => rl.question(q, r));
|
|
690
|
-
const result = {};
|
|
691
735
|
|
|
692
736
|
if (schema.properties) {
|
|
693
737
|
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
@@ -696,35 +740,75 @@ program
|
|
|
696
740
|
const def = prop.default ? ` [${prop.default}]` : "";
|
|
697
741
|
const answer = await ask(chalk.cyan(` ${key}${hint}${def}: `));
|
|
698
742
|
const val = answer || prop.default;
|
|
699
|
-
if (val
|
|
743
|
+
if (val !== undefined && val !== "") {
|
|
744
|
+
result[key] = prop.type === "number" || prop.type === "integer" ? Number(val) : val;
|
|
745
|
+
}
|
|
700
746
|
}
|
|
701
747
|
}
|
|
702
748
|
rl.close();
|
|
703
|
-
if (jsonMode) return console.log(JSON.stringify(result, null, 2));
|
|
704
|
-
console.log(JSON.stringify(result));
|
|
705
749
|
} else {
|
|
706
750
|
// Generate template with defaults
|
|
707
|
-
const template = {};
|
|
708
751
|
if (schema.properties) {
|
|
709
752
|
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
710
753
|
if (prop.default !== undefined) {
|
|
711
|
-
|
|
754
|
+
result[key] = prop.default;
|
|
712
755
|
} else if (prop.type === "string") {
|
|
713
|
-
|
|
756
|
+
result[key] = prop.enum ? prop.enum[0] : "";
|
|
714
757
|
} else if (prop.type === "number" || prop.type === "integer") {
|
|
715
|
-
|
|
758
|
+
result[key] = 0;
|
|
716
759
|
} else if (prop.type === "boolean") {
|
|
717
|
-
|
|
760
|
+
result[key] = false;
|
|
761
|
+
} else if (prop.type === "array") {
|
|
762
|
+
result[key] = [];
|
|
763
|
+
} else if (prop.type === "object") {
|
|
764
|
+
result[key] = {};
|
|
718
765
|
}
|
|
719
766
|
}
|
|
720
767
|
}
|
|
721
|
-
if (jsonMode) return console.log(JSON.stringify(template, null, 2));
|
|
722
|
-
console.log(JSON.stringify(template, null, 2));
|
|
723
768
|
}
|
|
769
|
+
|
|
770
|
+
// ── Apply --set overrides ──────────────────────────────────────
|
|
771
|
+
if (opts.set) {
|
|
772
|
+
const sets = Array.isArray(opts.set) ? opts.set : [opts.set];
|
|
773
|
+
for (const pair of sets) {
|
|
774
|
+
const eqIdx = pair.indexOf("=");
|
|
775
|
+
if (eqIdx > 0) {
|
|
776
|
+
const k = pair.slice(0, eqIdx);
|
|
777
|
+
let v = pair.slice(eqIdx + 1);
|
|
778
|
+
// Try parsing as number or boolean
|
|
779
|
+
if (v === "true") v = true;
|
|
780
|
+
else if (v === "false") v = false;
|
|
781
|
+
else if (!isNaN(v) && v.trim() !== "") v = Number(v);
|
|
782
|
+
result[k] = v;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// ── Apply --add merge ──────────────────────────────────────────
|
|
788
|
+
if (opts.add) {
|
|
789
|
+
try {
|
|
790
|
+
const extra = typeof opts.add === "string" ? JSON.parse(opts.add) : opts.add;
|
|
791
|
+
result = { ...result, ...extra };
|
|
792
|
+
} catch {
|
|
793
|
+
console.error(chalk.red("Error: --add must be valid JSON"));
|
|
794
|
+
process.exit(1);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
const output = JSON.stringify(result, null, jsonMode ? 2 : 0);
|
|
799
|
+
if (jsonMode) return console.log(output);
|
|
800
|
+
console.log(output);
|
|
724
801
|
} else {
|
|
725
|
-
console.log(chalk.yellow("Usage:
|
|
726
|
-
console.log(chalk.dim("
|
|
727
|
-
console.log(chalk.dim("
|
|
802
|
+
console.log(chalk.yellow("Usage:"));
|
|
803
|
+
console.log(chalk.dim(" nxb json --template <slug> Generate JSON template with defaults"));
|
|
804
|
+
console.log(chalk.dim(" nxb json --template <slug> -i Interactive mode (prompts for fields)"));
|
|
805
|
+
console.log(chalk.dim(" nxb json --template <slug> -s count=10 Set specific field values"));
|
|
806
|
+
console.log(chalk.dim(" nxb json --template <slug> -a '{\"x\":1}' Merge additional JSON"));
|
|
807
|
+
console.log(chalk.dim(""));
|
|
808
|
+
console.log(chalk.dim(" Examples:"));
|
|
809
|
+
console.log(chalk.dim(" nxb json --template data-generator | nxb run data-generator --input @-"));
|
|
810
|
+
console.log(chalk.dim(" nxb run data-generator --input \"$(nxb json --template dg -s count=5)\""));
|
|
811
|
+
console.log(chalk.dim(" nxb json --template color-palette -s color=#4A5D23 --json"));
|
|
728
812
|
}
|
|
729
813
|
});
|
|
730
814
|
|
|
@@ -738,4 +822,6 @@ function readStdin() {
|
|
|
738
822
|
process.stdin.on("end", () => resolve(chunks.join("")));
|
|
739
823
|
if (process.stdin.isTTY) resolve("");
|
|
740
824
|
});
|
|
741
|
-
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
program.parse(process.argv);
|