@hanzogui/get 8.3.1 → 8.3.2

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.
Files changed (48) hide show
  1. package/dist/cjs/cli.js +62 -0
  2. package/dist/cjs/cli.js.map +1 -0
  3. package/dist/cjs/commands/add.js +20 -0
  4. package/dist/cjs/commands/add.js.map +1 -0
  5. package/dist/cjs/commands/init.js +19 -0
  6. package/dist/cjs/commands/init.js.map +1 -0
  7. package/dist/cjs/commands/list.js +24 -0
  8. package/dist/cjs/commands/list.js.map +1 -0
  9. package/dist/cjs/commands/pick.js +56 -0
  10. package/dist/cjs/commands/pick.js.map +1 -0
  11. package/dist/cjs/constants.js +5 -0
  12. package/dist/cjs/constants.js.map +1 -0
  13. package/dist/cjs/lib/ansi.js +14 -0
  14. package/dist/cjs/lib/ansi.js.map +1 -0
  15. package/dist/cjs/package.json +1 -0
  16. package/dist/esm/cli.js +61 -0
  17. package/dist/esm/cli.js.map +1 -0
  18. package/dist/esm/commands/add.js +17 -0
  19. package/dist/esm/commands/add.js.map +1 -0
  20. package/dist/esm/commands/init.js +15 -0
  21. package/dist/esm/commands/init.js.map +1 -0
  22. package/dist/esm/commands/list.js +21 -0
  23. package/dist/esm/commands/list.js.map +1 -0
  24. package/dist/esm/commands/pick.js +52 -0
  25. package/dist/esm/commands/pick.js.map +1 -0
  26. package/dist/esm/constants.js +2 -0
  27. package/dist/esm/constants.js.map +1 -0
  28. package/dist/esm/lib/ansi.js +11 -0
  29. package/dist/esm/lib/ansi.js.map +1 -0
  30. package/package.json +19 -13
  31. package/src/cli.ts +1 -0
  32. package/src/commands/init.test.ts +44 -0
  33. package/src/lib/ansi.test.ts +12 -0
  34. package/types/cli.d.ts +3 -0
  35. package/types/cli.d.ts.map +1 -0
  36. package/types/commands/add.d.ts +2 -0
  37. package/types/commands/add.d.ts.map +1 -0
  38. package/types/commands/init.d.ts +2 -0
  39. package/types/commands/init.d.ts.map +1 -0
  40. package/types/commands/list.d.ts +2 -0
  41. package/types/commands/list.d.ts.map +1 -0
  42. package/types/commands/pick.d.ts +2 -0
  43. package/types/commands/pick.d.ts.map +1 -0
  44. package/types/constants.d.ts +2 -0
  45. package/types/constants.d.ts.map +1 -0
  46. package/types/lib/ansi.d.ts +8 -0
  47. package/types/lib/ansi.d.ts.map +1 -0
  48. package/dist/cli.js +0 -1703
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ const constants_js_1 = require("./constants.js");
6
+ const ansi_js_1 = require("./lib/ansi.js");
7
+ const HELP = `${constants_js_1.CLI_NAME} — install Hanzo GUI recipes into your project.
8
+
9
+ Usage:
10
+ ${constants_js_1.CLI_NAME} Interactive picker.
11
+ ${constants_js_1.CLI_NAME} add <slug> Install a single recipe.
12
+ ${constants_js_1.CLI_NAME} list List all available recipes.
13
+ ${constants_js_1.CLI_NAME} init Write gui.config.json.
14
+ ${constants_js_1.CLI_NAME} --help Show this message.
15
+ ${constants_js_1.CLI_NAME} --version Print version.
16
+
17
+ Recipes are fetched from Hanzo Base at $HANZO_BASE_URL (default https://base.hanzo.ai).
18
+ Recipe files vendor into src/gui/ by default; override via gui.config.json.
19
+ `;
20
+ async function main() {
21
+ const [, , cmd, ...rest] = process.argv;
22
+ if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
23
+ process.stdout.write(HELP);
24
+ return;
25
+ }
26
+ if (cmd === '--version' || cmd === '-v') {
27
+ const pkg = await Promise.resolve().then(() => tslib_1.__importStar(require('../package.json')));
28
+ process.stdout.write((pkg.default?.version ?? 'unknown') + '\n');
29
+ return;
30
+ }
31
+ if (!cmd) {
32
+ const { pick } = await Promise.resolve().then(() => tslib_1.__importStar(require('./commands/pick.js')));
33
+ await pick();
34
+ return;
35
+ }
36
+ if (cmd === 'add') {
37
+ if (!rest[0]) {
38
+ process.stderr.write(`Usage: ${constants_js_1.CLI_NAME} add <recipe-slug>\n`);
39
+ process.exit(1);
40
+ }
41
+ const { add } = await Promise.resolve().then(() => tslib_1.__importStar(require('./commands/add.js')));
42
+ await add(rest[0]);
43
+ return;
44
+ }
45
+ if (cmd === 'list') {
46
+ const { list } = await Promise.resolve().then(() => tslib_1.__importStar(require('./commands/list.js')));
47
+ await list();
48
+ return;
49
+ }
50
+ if (cmd === 'init') {
51
+ const { init } = await Promise.resolve().then(() => tslib_1.__importStar(require('./commands/init.js')));
52
+ await init();
53
+ return;
54
+ }
55
+ process.stderr.write(`Unknown command: ${cmd}\n\n${HELP}`);
56
+ process.exit(1);
57
+ }
58
+ main().catch((e) => {
59
+ process.stderr.write((0, ansi_js_1.red)(e instanceof Error ? e.message : String(e)) + '\n');
60
+ process.exit(1);
61
+ });
62
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";;;;AACA,iDAAyC;AACzC,2CAAmC;AAEnC,MAAM,IAAI,GAAG,GAAG,uBAAQ;;;IAGpB,uBAAQ;IACR,uBAAQ;IACR,uBAAQ;IACR,uBAAQ;IACR,uBAAQ;IACR,uBAAQ;;;;CAIX,CAAA;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAA;IAEvC,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,gEAAa,iBAAiB,GAEnB,CAAA;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,CAAE,GAA0C,CAAC,OAAO,EAAE,OAAO,IAAI,SAAS,CAAC,GAAG,IAAI,CACnF,CAAA;QACD,OAAM;IACR,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,EAAE,IAAI,EAAE,GAAG,gEAAa,oBAAoB,GAAC,CAAA;QACnD,MAAM,IAAI,EAAE,CAAA;QACZ,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,uBAAQ,sBAAsB,CAAC,CAAA;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,gEAAa,mBAAmB,GAAC,CAAA;QACjD,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QAClB,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,EAAE,IAAI,EAAE,GAAG,gEAAa,oBAAoB,GAAC,CAAA;QACnD,MAAM,IAAI,EAAE,CAAA;QACZ,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,EAAE,IAAI,EAAE,GAAG,gEAAa,oBAAoB,GAAC,CAAA;QACnD,MAAM,IAAI,EAAE,CAAA;QACZ,OAAM;IACR,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,GAAG,OAAO,IAAI,EAAE,CAAC,CAAA;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,aAAG,EAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.add = add;
4
+ const recipes_1 = require("@hanzogui/recipes");
5
+ const ansi_js_1 = require("../lib/ansi.js");
6
+ async function add(slug) {
7
+ const plan = await (0, recipes_1.resolveRecipe)(slug);
8
+ const paths = await (0, recipes_1.installPlan)(plan);
9
+ process.stdout.write((0, ansi_js_1.green)(`Installed "${plan.recipe.name}"`) + '\n');
10
+ if (plan.transitiveRecipes.length > 0) {
11
+ process.stdout.write((0, ansi_js_1.gray)(`+ ${plan.transitiveRecipes.length} dependent recipe${plan.transitiveRecipes.length === 1 ? '' : 's'}: ${plan.transitiveRecipes.map((r) => r.slug).join(', ')}\n`));
12
+ }
13
+ for (const p of paths)
14
+ process.stdout.write(` ${p}\n`);
15
+ if (plan.recipe.npmDeps.length > 0) {
16
+ process.stdout.write('\n' + (0, ansi_js_1.gray)('Install these npm deps:') + '\n');
17
+ process.stdout.write(` ${(0, ansi_js_1.bold)('npm i ' + plan.recipe.npmDeps.join(' '))}\n`);
18
+ }
19
+ }
20
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/commands/add.ts"],"names":[],"mappings":";;;AAAA,+CAA8D;AAC9D,4CAAkD;AAE3C,KAAK,cAAc,IAAY;IACpC,MAAM,IAAI,GAAG,MAAM,IAAA,uBAAa,EAAC,IAAI,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAW,EAAC,IAAI,CAAC,CAAA;IAErC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,eAAK,EAAC,cAAc,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;IACrE,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAA,cAAI,EACF,KAAK,IAAI,CAAC,iBAAiB,CAAC,MAAM,oBAChC,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC7C,KAAK,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAC9D,CACF,CAAA;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvD,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAA,cAAI,EAAC,yBAAyB,CAAC,GAAG,IAAI,CAAC,CAAA;QACnE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAA,cAAI,EAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;IAC/E,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.init = init;
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
7
+ const recipes_1 = require("@hanzogui/recipes");
8
+ const ansi_js_1 = require("../lib/ansi.js");
9
+ async function init() {
10
+ const root = await (0, recipes_1.findProjectRoot)();
11
+ const dest = node_path_1.default.join(root, 'gui.config.json');
12
+ if ((0, node_fs_1.existsSync)(dest)) {
13
+ process.stdout.write((0, ansi_js_1.yellow)(`gui.config.json already exists at ${dest}\n`));
14
+ return;
15
+ }
16
+ await node_fs_1.promises.writeFile(dest, JSON.stringify({ installDir: recipes_1.DEFAULT_INSTALL_DIR }, null, 2) + '\n');
17
+ process.stdout.write((0, ansi_js_1.green)(`Wrote ${dest}\n`));
18
+ }
19
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":";;;;AAAA,qCAAoD;AACpD,kEAA4B;AAC5B,+CAAwE;AACxE,4CAA8C;AAEvC,KAAK;IACV,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAe,GAAE,CAAA;IACpC,MAAM,IAAI,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAA;IAC/C,IAAI,IAAA,oBAAU,EAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,gBAAM,EAAC,qCAAqC,IAAI,IAAI,CAAC,CAAC,CAAA;QAC3E,OAAM;IACR,CAAC;IACD,MAAM,kBAAE,CAAC,SAAS,CAChB,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,6BAAmB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CACpE,CAAA;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,eAAK,EAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAA;AAChD,CAAC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.list = list;
4
+ const recipes_1 = require("@hanzogui/recipes");
5
+ const ansi_js_1 = require("../lib/ansi.js");
6
+ async function list() {
7
+ var _a;
8
+ const recipes = await (0, recipes_1.listRecipes)();
9
+ if (recipes.length === 0) {
10
+ process.stdout.write((0, ansi_js_1.yellow)('No recipes published yet.\n'));
11
+ return;
12
+ }
13
+ const byCategory = {};
14
+ for (const r of recipes)
15
+ (byCategory[_a = r.category || 'misc'] || (byCategory[_a] = [])).push(r);
16
+ for (const [cat, items] of Object.entries(byCategory)) {
17
+ process.stdout.write(`\n${(0, ansi_js_1.bold)(cat)}\n`);
18
+ for (const r of items) {
19
+ process.stdout.write(` ${(0, ansi_js_1.cyan)(r.slug.padEnd(24))} ${(0, ansi_js_1.gray)(r.description)}\n`);
20
+ }
21
+ }
22
+ process.stdout.write('\n');
23
+ }
24
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAC/C,4CAAyD;AAElD,KAAK;;IACV,MAAM,OAAO,GAAG,MAAM,IAAA,qBAAW,GAAE,CAAA;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,gBAAM,EAAC,6BAA6B,CAAC,CAAC,CAAA;QAC3D,OAAM;IACR,CAAC;IACD,MAAM,UAAU,GAAmC,EAAE,CAAA;IACrD,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,CAAC,UAAU,MAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,MAA/B,UAAU,OAA2B,EAAE,EAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC1E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAA,cAAI,EAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACxC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAA,cAAI,EAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,IAAA,cAAI,EAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QAChF,CAAC;IACH,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pick = pick;
4
+ const tslib_1 = require("tslib");
5
+ const fuse_js_1 = tslib_1.__importDefault(require("fuse.js"));
6
+ const readline = tslib_1.__importStar(require("node:readline/promises"));
7
+ const recipes_1 = require("@hanzogui/recipes");
8
+ const ansi_js_1 = require("../lib/ansi.js");
9
+ const add_js_1 = require("./add.js");
10
+ async function pick() {
11
+ const recipes = await (0, recipes_1.listRecipes)();
12
+ if (recipes.length === 0) {
13
+ process.stdout.write('No recipes published yet.\n');
14
+ return;
15
+ }
16
+ const fuse = new fuse_js_1.default(recipes, {
17
+ keys: ['name', 'slug', 'category', 'description'],
18
+ threshold: 0.4,
19
+ });
20
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21
+ try {
22
+ const query = (await rl.question((0, ansi_js_1.bold)('Search recipes') + ' (empty = show all): ')).trim();
23
+ const hits = query ? fuse.search(query).map((h) => h.item) : recipes;
24
+ if (hits.length === 0) {
25
+ process.stdout.write((0, ansi_js_1.dim)('No matches.\n'));
26
+ return;
27
+ }
28
+ process.stdout.write('\n');
29
+ hits.slice(0, 20).forEach((r, i) => {
30
+ process.stdout.write(` ${(0, ansi_js_1.cyan)(String(i + 1).padStart(2))} ${(0, ansi_js_1.bold)(r.name)} ${(0, ansi_js_1.gray)(r.slug)}\n`);
31
+ process.stdout.write(` ${(0, ansi_js_1.gray)(r.description)}\n`);
32
+ });
33
+ process.stdout.write('\n');
34
+ const pickRaw = (await rl.question('Pick a number (or paste a slug): ')).trim();
35
+ if (!pickRaw)
36
+ return;
37
+ let slug;
38
+ const asNum = Number.parseInt(pickRaw, 10);
39
+ if (!Number.isNaN(asNum) && asNum >= 1 && asNum <= hits.length) {
40
+ slug = hits[asNum - 1].slug;
41
+ }
42
+ else if (recipes.find((r) => r.slug === pickRaw)) {
43
+ slug = pickRaw;
44
+ }
45
+ if (!slug) {
46
+ process.stdout.write((0, ansi_js_1.dim)(`No recipe matches "${pickRaw}".\n`));
47
+ return;
48
+ }
49
+ process.stdout.write('\n');
50
+ await (0, add_js_1.add)(slug);
51
+ }
52
+ finally {
53
+ rl.close();
54
+ }
55
+ }
56
+ //# sourceMappingURL=pick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick.js","sourceRoot":"","sources":["../../../src/commands/pick.ts"],"names":[],"mappings":";;;;AAAA,8DAA0B;AAC1B,MAAY,QAAQ,2DAA8B;AAClD,+CAA+C;AAC/C,4CAAsD;AACtD,qCAA8B;AAEvB,KAAK;IACV,MAAM,OAAO,GAAG,MAAM,IAAA,qBAAW,GAAE,CAAA;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;QACnD,OAAM;IACR,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,iBAAI,CAAC,OAAO,EAAE;QAC7B,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC;QACjD,SAAS,EAAE,GAAG;KACf,CAAC,CAAA;IAEF,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAErF,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,CACZ,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAA,cAAI,EAAC,gBAAgB,CAAC,GAAG,uBAAuB,CAAC,CACpE,CAAC,IAAI,EAAE,CAAA;QACR,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;QACpE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,aAAG,EAAC,eAAe,CAAC,CAAC,CAAA;YAC1C,OAAM;QACR,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,IAAA,cAAI,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,IAAA,cAAI,EAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAA,cAAI,EAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAC3E,CAAA;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAA,cAAI,EAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAE1B,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/E,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,IAAI,IAAwB,CAAA;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/D,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC,IAAI,CAAA;QAC9B,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,GAAG,OAAO,CAAA;QAChB,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,aAAG,EAAC,sBAAsB,OAAO,MAAM,CAAC,CAAC,CAAA;YAC9D,OAAM;QACR,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC1B,MAAM,IAAA,YAAG,EAAC,IAAI,CAAC,CAAA;IACjB,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAA;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLI_NAME = void 0;
4
+ exports.CLI_NAME = 'hanzo-gui-get';
5
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,QAAQ,GAAG,eAAe,CAAA"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.gray = exports.cyan = exports.yellow = exports.green = exports.red = exports.dim = exports.bold = void 0;
4
+ const ESC = '\x1b[';
5
+ const isTTY = process.stdout.isTTY === true;
6
+ const wrap = (open, close) => (s) => isTTY ? `${ESC}${open}m${s}${ESC}${close}m` : s;
7
+ exports.bold = wrap(1, 22);
8
+ exports.dim = wrap(2, 22);
9
+ exports.red = wrap(31, 39);
10
+ exports.green = wrap(32, 39);
11
+ exports.yellow = wrap(33, 39);
12
+ exports.cyan = wrap(36, 39);
13
+ exports.gray = wrap(90, 39);
14
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../../src/lib/ansi.ts"],"names":[],"mappings":";;;AAAA,MAAM,GAAG,GAAG,OAAO,CAAA;AACnB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAA;AAC3C,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAC1D,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAEpC,QAAA,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAClB,QAAA,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AACjB,QAAA,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AAClB,QAAA,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AACpB,QAAA,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AACrB,QAAA,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AACnB,QAAA,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ { "type": "commonjs" }
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ import { CLI_NAME } from './constants.js';
3
+ import { red } from './lib/ansi.js';
4
+ const HELP = `${CLI_NAME} — install Hanzo GUI recipes into your project.
5
+
6
+ Usage:
7
+ ${CLI_NAME} Interactive picker.
8
+ ${CLI_NAME} add <slug> Install a single recipe.
9
+ ${CLI_NAME} list List all available recipes.
10
+ ${CLI_NAME} init Write gui.config.json.
11
+ ${CLI_NAME} --help Show this message.
12
+ ${CLI_NAME} --version Print version.
13
+
14
+ Recipes are fetched from Hanzo Base at $HANZO_BASE_URL (default https://base.hanzo.ai).
15
+ Recipe files vendor into src/gui/ by default; override via gui.config.json.
16
+ `;
17
+ async function main() {
18
+ const [, , cmd, ...rest] = process.argv;
19
+ if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
20
+ process.stdout.write(HELP);
21
+ return;
22
+ }
23
+ if (cmd === '--version' || cmd === '-v') {
24
+ const pkg = await import('../package.json', {
25
+ with: { type: 'json' },
26
+ });
27
+ process.stdout.write((pkg.default?.version ?? 'unknown') + '\n');
28
+ return;
29
+ }
30
+ if (!cmd) {
31
+ const { pick } = await import('./commands/pick.js');
32
+ await pick();
33
+ return;
34
+ }
35
+ if (cmd === 'add') {
36
+ if (!rest[0]) {
37
+ process.stderr.write(`Usage: ${CLI_NAME} add <recipe-slug>\n`);
38
+ process.exit(1);
39
+ }
40
+ const { add } = await import('./commands/add.js');
41
+ await add(rest[0]);
42
+ return;
43
+ }
44
+ if (cmd === 'list') {
45
+ const { list } = await import('./commands/list.js');
46
+ await list();
47
+ return;
48
+ }
49
+ if (cmd === 'init') {
50
+ const { init } = await import('./commands/init.js');
51
+ await init();
52
+ return;
53
+ }
54
+ process.stderr.write(`Unknown command: ${cmd}\n\n${HELP}`);
55
+ process.exit(1);
56
+ }
57
+ main().catch((e) => {
58
+ process.stderr.write(red(e instanceof Error ? e.message : String(e)) + '\n');
59
+ process.exit(1);
60
+ });
61
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAEnC,MAAM,IAAI,GAAG,GAAG,QAAQ;;;IAGpB,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;;;;CAIX,CAAA;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAA;IAEvC,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC1B,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE;YAC1C,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;SACF,CAAC,CAAA;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,CAAE,GAA0C,CAAC,OAAO,EAAE,OAAO,IAAI,SAAS,CAAC,GAAG,IAAI,CACnF,CAAA;QACD,OAAM;IACR,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;QACnD,MAAM,IAAI,EAAE,CAAA;QACZ,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,QAAQ,sBAAsB,CAAC,CAAA;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;QACjD,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QAClB,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;QACnD,MAAM,IAAI,EAAE,CAAA;QACZ,OAAM;IACR,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;QACnD,MAAM,IAAI,EAAE,CAAA;QACZ,OAAM;IACR,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,GAAG,OAAO,IAAI,EAAE,CAAC,CAAA;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { resolveRecipe, installPlan } from '@hanzogui/recipes';
2
+ import { green, gray, bold } from '../lib/ansi.js';
3
+ export async function add(slug) {
4
+ const plan = await resolveRecipe(slug);
5
+ const paths = await installPlan(plan);
6
+ process.stdout.write(green(`Installed "${plan.recipe.name}"`) + '\n');
7
+ if (plan.transitiveRecipes.length > 0) {
8
+ process.stdout.write(gray(`+ ${plan.transitiveRecipes.length} dependent recipe${plan.transitiveRecipes.length === 1 ? '' : 's'}: ${plan.transitiveRecipes.map((r) => r.slug).join(', ')}\n`));
9
+ }
10
+ for (const p of paths)
11
+ process.stdout.write(` ${p}\n`);
12
+ if (plan.recipe.npmDeps.length > 0) {
13
+ process.stdout.write('\n' + gray('Install these npm deps:') + '\n');
14
+ process.stdout.write(` ${bold('npm i ' + plan.recipe.npmDeps.join(' '))}\n`);
15
+ }
16
+ }
17
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAElD,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAY;IACpC,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;IACtC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;IAErC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;IACrE,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CACF,KAAK,IAAI,CAAC,iBAAiB,CAAC,MAAM,oBAChC,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC7C,KAAK,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAC9D,CACF,CAAA;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvD,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,yBAAyB,CAAC,GAAG,IAAI,CAAC,CAAA;QACnE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;IAC/E,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { existsSync, promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { findProjectRoot, DEFAULT_INSTALL_DIR } from '@hanzogui/recipes';
4
+ import { green, yellow } from '../lib/ansi.js';
5
+ export async function init() {
6
+ const root = await findProjectRoot();
7
+ const dest = path.join(root, 'gui.config.json');
8
+ if (existsSync(dest)) {
9
+ process.stdout.write(yellow(`gui.config.json already exists at ${dest}\n`));
10
+ return;
11
+ }
12
+ await fs.writeFile(dest, JSON.stringify({ installDir: DEFAULT_INSTALL_DIR }, null, 2) + '\n');
13
+ process.stdout.write(green(`Wrote ${dest}\n`));
14
+ }
15
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;AACpD,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAE9C,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,IAAI,GAAG,MAAM,eAAe,EAAE,CAAA;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAA;IAC/C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,qCAAqC,IAAI,IAAI,CAAC,CAAC,CAAA;QAC3E,OAAM;IACR,CAAC;IACD,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CACpE,CAAA;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAA;AAChD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { listRecipes } from '@hanzogui/recipes';
2
+ import { bold, cyan, gray, yellow } from '../lib/ansi.js';
3
+ export async function list() {
4
+ var _a;
5
+ const recipes = await listRecipes();
6
+ if (recipes.length === 0) {
7
+ process.stdout.write(yellow('No recipes published yet.\n'));
8
+ return;
9
+ }
10
+ const byCategory = {};
11
+ for (const r of recipes)
12
+ (byCategory[_a = r.category || 'misc'] || (byCategory[_a] = [])).push(r);
13
+ for (const [cat, items] of Object.entries(byCategory)) {
14
+ process.stdout.write(`\n${bold(cat)}\n`);
15
+ for (const r of items) {
16
+ process.stdout.write(` ${cyan(r.slug.padEnd(24))} ${gray(r.description)}\n`);
17
+ }
18
+ }
19
+ process.stdout.write('\n');
20
+ }
21
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,IAAI;;IACxB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAA;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAA;QAC3D,OAAM;IACR,CAAC;IACD,MAAM,UAAU,GAAmC,EAAE,CAAA;IACrD,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,CAAC,UAAU,MAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,MAA/B,UAAU,OAA2B,EAAE,EAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC1E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACxC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QAChF,CAAC;IACH,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,52 @@
1
+ import Fuse from 'fuse.js';
2
+ import * as readline from 'node:readline/promises';
3
+ import { listRecipes } from '@hanzogui/recipes';
4
+ import { bold, cyan, dim, gray } from '../lib/ansi.js';
5
+ import { add } from './add.js';
6
+ export async function pick() {
7
+ const recipes = await listRecipes();
8
+ if (recipes.length === 0) {
9
+ process.stdout.write('No recipes published yet.\n');
10
+ return;
11
+ }
12
+ const fuse = new Fuse(recipes, {
13
+ keys: ['name', 'slug', 'category', 'description'],
14
+ threshold: 0.4,
15
+ });
16
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
17
+ try {
18
+ const query = (await rl.question(bold('Search recipes') + ' (empty = show all): ')).trim();
19
+ const hits = query ? fuse.search(query).map((h) => h.item) : recipes;
20
+ if (hits.length === 0) {
21
+ process.stdout.write(dim('No matches.\n'));
22
+ return;
23
+ }
24
+ process.stdout.write('\n');
25
+ hits.slice(0, 20).forEach((r, i) => {
26
+ process.stdout.write(` ${cyan(String(i + 1).padStart(2))} ${bold(r.name)} ${gray(r.slug)}\n`);
27
+ process.stdout.write(` ${gray(r.description)}\n`);
28
+ });
29
+ process.stdout.write('\n');
30
+ const pickRaw = (await rl.question('Pick a number (or paste a slug): ')).trim();
31
+ if (!pickRaw)
32
+ return;
33
+ let slug;
34
+ const asNum = Number.parseInt(pickRaw, 10);
35
+ if (!Number.isNaN(asNum) && asNum >= 1 && asNum <= hits.length) {
36
+ slug = hits[asNum - 1].slug;
37
+ }
38
+ else if (recipes.find((r) => r.slug === pickRaw)) {
39
+ slug = pickRaw;
40
+ }
41
+ if (!slug) {
42
+ process.stdout.write(dim(`No recipe matches "${pickRaw}".\n`));
43
+ return;
44
+ }
45
+ process.stdout.write('\n');
46
+ await add(slug);
47
+ }
48
+ finally {
49
+ rl.close();
50
+ }
51
+ }
52
+ //# sourceMappingURL=pick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick.js","sourceRoot":"","sources":["../../../src/commands/pick.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export const CLI_NAME = 'hanzo-gui-get';
2
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,eAAe,CAAA"}
@@ -0,0 +1,11 @@
1
+ const ESC = '\x1b[';
2
+ const isTTY = process.stdout.isTTY === true;
3
+ const wrap = (open, close) => (s) => isTTY ? `${ESC}${open}m${s}${ESC}${close}m` : s;
4
+ export const bold = wrap(1, 22);
5
+ export const dim = wrap(2, 22);
6
+ export const red = wrap(31, 39);
7
+ export const green = wrap(32, 39);
8
+ export const yellow = wrap(33, 39);
9
+ export const cyan = wrap(36, 39);
10
+ export const gray = wrap(90, 39);
11
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../../src/lib/ansi.ts"],"names":[],"mappings":"AAAA,MAAM,GAAG,GAAG,OAAO,CAAA;AACnB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAA;AAC3C,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAC1D,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAEjD,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAC/B,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAC9B,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AAC/B,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AACjC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AAClC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;AAChC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,37 +1,43 @@
1
1
  {
2
2
  "name": "@hanzogui/get",
3
- "version": "8.3.1",
3
+ "version": "8.3.2",
4
4
  "description": "CLI installer for Hanzo GUI recipes.",
5
+ "homepage": "https://gui.hanzo.ai",
5
6
  "license": "BSD-3-Clause",
6
7
  "author": "Hanzo AI <dev@hanzo.ai>",
7
- "homepage": "https://gui.hanzo.ai",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/hanzoai/gui.git",
10
+ "url": "git+https://github.com/hanzoai/gui.git",
11
11
  "directory": "pkgs/get"
12
12
  },
13
13
  "bin": {
14
- "hanzo-gui-get": "./dist/cli.js"
14
+ "hanzo-gui-get": "./dist/esm/cli.js"
15
15
  },
16
- "type": "module",
17
- "main": "./dist/cli.js",
18
16
  "source": "src/cli.ts",
19
17
  "files": [
20
- "src/**/*.ts",
21
- "!src/**/*.test.ts",
18
+ "src",
19
+ "types",
22
20
  "dist"
23
21
  ],
22
+ "type": "module",
23
+ "exports": {
24
+ "./package.json": "./package.json"
25
+ },
24
26
  "publishConfig": {
25
27
  "access": "public"
26
28
  },
27
29
  "scripts": {
28
- "build": "bun run build.ts",
29
- "clean": "rm -rf dist",
30
- "test": "bun test"
30
+ "build": "hanzogui-build --skip-native",
31
+ "test": "bun test",
32
+ "clean": "hanzogui-build clean",
33
+ "clean:build": "hanzogui-build clean:build"
31
34
  },
32
35
  "dependencies": {
33
- "@hanzogui/recipes": "8.3.1",
34
- "fuse.js": "7.1.0"
36
+ "@hanzogui/recipes": "8.3.2",
37
+ "fuse.js": "^7.5.0"
38
+ },
39
+ "devDependencies": {
40
+ "@hanzogui/build": "8.3.2"
35
41
  },
36
42
  "engines": {
37
43
  "node": ">=20"
package/src/cli.ts CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import { CLI_NAME } from './constants.js'
2
3
  import { red } from './lib/ansi.js'
3
4
 
@@ -0,0 +1,44 @@
1
+ import { test, expect, afterEach } from 'bun:test'
2
+ import { mkdtemp, readFile, writeFile, rm } from 'node:fs/promises'
3
+ import path from 'node:path'
4
+ import os from 'node:os'
5
+ import { init } from './init.js'
6
+
7
+ const created: string[] = []
8
+ afterEach(async () => {
9
+ for (const d of created.splice(0)) await rm(d, { recursive: true, force: true })
10
+ })
11
+
12
+ async function project(): Promise<string> {
13
+ const dir = await mkdtemp(path.join(os.tmpdir(), 'guiget-init-'))
14
+ await writeFile(path.join(dir, 'package.json'), JSON.stringify({ workspaces: [] }))
15
+ created.push(dir)
16
+ return dir
17
+ }
18
+
19
+ test('init writes gui.config.json with default installDir', async () => {
20
+ const dir = await project()
21
+ const cwd = process.cwd()
22
+ process.chdir(dir)
23
+ try {
24
+ await init()
25
+ const written = JSON.parse(await readFile(path.join(dir, 'gui.config.json'), 'utf8'))
26
+ expect(written).toEqual({ installDir: 'src/gui' })
27
+ } finally {
28
+ process.chdir(cwd)
29
+ }
30
+ })
31
+
32
+ test('init is idempotent (no overwrite when file exists)', async () => {
33
+ const dir = await project()
34
+ const existing = JSON.stringify({ installDir: 'src/widgets' })
35
+ await writeFile(path.join(dir, 'gui.config.json'), existing)
36
+ const cwd = process.cwd()
37
+ process.chdir(dir)
38
+ try {
39
+ await init()
40
+ expect(await readFile(path.join(dir, 'gui.config.json'), 'utf8')).toBe(existing)
41
+ } finally {
42
+ process.chdir(cwd)
43
+ }
44
+ })
@@ -0,0 +1,12 @@
1
+ import { test, expect } from 'bun:test'
2
+ import { bold, red, green, gray } from './ansi.js'
3
+
4
+ test('color helpers return wrapped strings on TTY, plain otherwise', () => {
5
+ // In the test runner stdout typically isn't a TTY, so we get pass-through.
6
+ // The contract: result is always a string that contains the input substring.
7
+ for (const fn of [bold, red, green, gray]) {
8
+ const out = fn('hello')
9
+ expect(typeof out).toBe('string')
10
+ expect(out.includes('hello')).toBe(true)
11
+ }
12
+ })
package/types/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function add(slug: string): Promise<void>;
2
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAGA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBrD"}
@@ -0,0 +1,2 @@
1
+ export declare function init(): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAKA,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAY1C"}
@@ -0,0 +1,2 @@
1
+ export declare function list(): Promise<void>;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAGA,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAe1C"}
@@ -0,0 +1,2 @@
1
+ export declare function pick(): Promise<void>;
2
+ //# sourceMappingURL=pick.d.ts.map