@maltty/cli 1.0.0-rc.0 → 1.0.0-rc.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 (107) hide show
  1. package/dist/{_format-CeQhQTl5.js → _format-XTN-U4H5.js} +4 -2
  2. package/dist/{_format-CeQhQTl5.js.map → _format-XTN-U4H5.js.map} +1 -1
  3. package/dist/attemptAsync-D_oWcKfe.js +74 -0
  4. package/dist/attemptAsync-D_oWcKfe.js.map +1 -0
  5. package/dist/commands/add/command.d.ts +0 -1
  6. package/dist/commands/add/command.d.ts.map +1 -1
  7. package/dist/commands/add/command.js +4 -4
  8. package/dist/commands/add/command.js.map +1 -1
  9. package/dist/commands/add/config.d.ts +0 -1
  10. package/dist/commands/add/config.d.ts.map +1 -1
  11. package/dist/commands/add/config.js +3 -3
  12. package/dist/commands/add/config.js.map +1 -1
  13. package/dist/commands/add/index.d.ts +0 -1
  14. package/dist/commands/add/index.d.ts.map +1 -1
  15. package/dist/commands/add/index.js.map +1 -1
  16. package/dist/commands/add/middleware.d.ts +0 -1
  17. package/dist/commands/add/middleware.d.ts.map +1 -1
  18. package/dist/commands/add/middleware.js +3 -3
  19. package/dist/commands/add/middleware.js.map +1 -1
  20. package/dist/commands/build.d.ts +7 -8
  21. package/dist/commands/build.d.ts.map +1 -1
  22. package/dist/commands/build.js +3 -3
  23. package/dist/commands/build.js.map +1 -1
  24. package/dist/commands/commands.d.ts +6 -7
  25. package/dist/commands/commands.d.ts.map +1 -1
  26. package/dist/commands/commands.js +5 -5
  27. package/dist/commands/commands.js.map +1 -1
  28. package/dist/commands/dev.d.ts +5 -6
  29. package/dist/commands/dev.d.ts.map +1 -1
  30. package/dist/commands/dev.js +3 -3
  31. package/dist/commands/dev.js.map +1 -1
  32. package/dist/commands/doctor.d.ts +5 -6
  33. package/dist/commands/doctor.d.ts.map +1 -1
  34. package/dist/commands/doctor.js +7 -6
  35. package/dist/commands/doctor.js.map +1 -1
  36. package/dist/commands/init.d.ts +0 -1
  37. package/dist/commands/init.d.ts.map +1 -1
  38. package/dist/commands/init.js +5 -5
  39. package/dist/commands/init.js.map +1 -1
  40. package/dist/commands/run.d.ts +11 -12
  41. package/dist/commands/run.d.ts.map +1 -1
  42. package/dist/commands/run.js +6 -6
  43. package/dist/commands/run.js.map +1 -1
  44. package/dist/commands/stories.d.ts +3 -4
  45. package/dist/commands/stories.d.ts.map +1 -1
  46. package/dist/commands/stories.js.map +1 -1
  47. package/dist/{config-helpers-pv_2Spux.js → config-helpers-DAy-Arox.js} +1 -1
  48. package/dist/{config-helpers-pv_2Spux.js.map → config-helpers-DAy-Arox.js.map} +1 -1
  49. package/dist/{defu-BBwssjW3.js → defu-BOMYL43b.js} +1 -13
  50. package/dist/{defu-BBwssjW3.js.map → defu-BOMYL43b.js.map} +1 -1
  51. package/dist/{detect-AOq1ehTE.js → detect-Gdceq3rh.js} +4 -4
  52. package/dist/{detect-AOq1ehTE.js.map → detect-Gdceq3rh.js.map} +1 -1
  53. package/dist/{dist-Xa07jNxS.js → dist-BGEDDbkB.js} +1430 -859
  54. package/dist/dist-BGEDDbkB.js.map +1 -0
  55. package/dist/{dist-DW_gRP7_.js → dist-FY8K5na4.js} +37 -8
  56. package/dist/dist-FY8K5na4.js.map +1 -0
  57. package/dist/fs-Uxhr-pvi-AfTuGWmD.js +98 -0
  58. package/dist/fs-Uxhr-pvi-AfTuGWmD.js.map +1 -0
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.js +2 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/{jiti-CxWlVmZ_.js → jiti-DLiXBetA.js} +15 -10
  63. package/dist/{jiti-CxWlVmZ_.js.map → jiti-DLiXBetA.js.map} +1 -1
  64. package/dist/json-DjLTvRvF.js +82 -0
  65. package/dist/json-DjLTvRvF.js.map +1 -0
  66. package/dist/{json5-z-PGDMyy.js → json5-Dgws4cj9.js} +22 -8
  67. package/dist/{json5-z-PGDMyy.js.map → json5-Dgws4cj9.js.map} +1 -1
  68. package/dist/{jsonc-DqZkfC3S.js → jsonc-B3DUZTiW.js} +9 -15
  69. package/dist/jsonc-B3DUZTiW.js.map +1 -0
  70. package/dist/jsonc-BjIiMOLf.js +2 -0
  71. package/dist/{main-C_8x2aB3.js → main-CMmTVJ4V.js} +2 -2
  72. package/dist/{main-C_8x2aB3.js.map → main-CMmTVJ4V.js.map} +1 -1
  73. package/dist/{manifest-BIKVDJML.js → manifest-C192Fk9X.js} +3 -3
  74. package/dist/{manifest-BIKVDJML.js.map → manifest-C192Fk9X.js.map} +1 -1
  75. package/dist/{multipart-parser-MNkxNO83.js → multipart-parser-XnJOfY8C.js} +14 -4
  76. package/dist/{multipart-parser-MNkxNO83.js.map → multipart-parser-XnJOfY8C.js.map} +1 -1
  77. package/dist/{node-C91xGGqn.js → node-Bbe24r0m.js} +28 -105
  78. package/dist/node-Bbe24r0m.js.map +1 -0
  79. package/dist/{node-Drmc03fL.js → node-lkjrm0W1.js} +95 -33
  80. package/dist/{node-Drmc03fL.js.map → node-lkjrm0W1.js.map} +1 -1
  81. package/dist/{ohash-BPoV4zBH.js → ohash-Cgvv31gH.js} +5 -3
  82. package/dist/ohash-Cgvv31gH.js.map +1 -0
  83. package/dist/pnpm-workspace.yaml +10 -10
  84. package/dist/{chunk-DsIazq42.js → rolldown-runtime-C7HZzL1F.js} +2 -2
  85. package/dist/{toml-LuHsHQtV.js → toml-BrfNstp2.js} +34 -3
  86. package/dist/{toml-LuHsHQtV.js.map → toml-BrfNstp2.js.map} +1 -1
  87. package/dist/{utils-DlIJNGLQ.js → utils-ioeFEbm4.js} +208 -236
  88. package/dist/utils-ioeFEbm4.js.map +1 -0
  89. package/dist/{validate-C_SXBoLq.js → validate-CX8axBK6.js} +1 -1
  90. package/dist/{validate-C_SXBoLq.js.map → validate-CX8axBK6.js.map} +1 -1
  91. package/dist/{write-CSwG4Stj.js → write-C6VsyUuc.js} +6 -4
  92. package/dist/{write-CSwG4Stj.js.map → write-C6VsyUuc.js.map} +1 -1
  93. package/dist/{yaml-BS9RDuUr.js → yaml-Cp5SldPx.js} +78 -18
  94. package/dist/yaml-Cp5SldPx.js.map +1 -0
  95. package/package.json +14 -14
  96. package/dist/attemptAsync-BdXzRSIT.js +0 -42
  97. package/dist/attemptAsync-BdXzRSIT.js.map +0 -1
  98. package/dist/dist-DW_gRP7_.js.map +0 -1
  99. package/dist/dist-Xa07jNxS.js.map +0 -1
  100. package/dist/json-D7WbuVK1.js +0 -43
  101. package/dist/json-D7WbuVK1.js.map +0 -1
  102. package/dist/jsonc-DqZkfC3S.js.map +0 -1
  103. package/dist/jsonc-KADMdSjU.js +0 -2
  104. package/dist/node-C91xGGqn.js.map +0 -1
  105. package/dist/ohash-BPoV4zBH.js.map +0 -1
  106. package/dist/utils-DlIJNGLQ.js.map +0 -1
  107. package/dist/yaml-BS9RDuUr.js.map +0 -1
@@ -1,5 +1,7 @@
1
1
  //#region ../../node_modules/.pnpm/confbox@0.2.4/node_modules/confbox/dist/_chunks/_format.mjs
2
- const t = Symbol.for(`__confbox_fmt__`), n = /^(\s+)/, r = /(\s+)$/;
2
+ const t = Symbol.for(`__confbox_fmt__`);
3
+ const n = /^(\s+)/;
4
+ const r = /(\s+)$/;
3
5
  function i(e, t = {}) {
4
6
  return {
5
7
  sample: t.indent === void 0 && t.preserveIndentation !== !1 && e.slice(0, t?.sampleSize || 1024),
@@ -20,4 +22,4 @@ function a(e, n, r) {
20
22
  //#endregion
21
23
  export { a as t };
22
24
 
23
- //# sourceMappingURL=_format-CeQhQTl5.js.map
25
+ //# sourceMappingURL=_format-XTN-U4H5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"_format-CeQhQTl5.js","names":[],"sources":["../../../node_modules/.pnpm/confbox@0.2.4/node_modules/confbox/dist/_chunks/_format.mjs"],"sourcesContent":["import{t as e}from\"./libs/detect-indent.mjs\";const t=Symbol.for(`__confbox_fmt__`),n=/^(\\s+)/,r=/(\\s+)$/;function i(e,t={}){return{sample:t.indent===void 0&&t.preserveIndentation!==!1&&e.slice(0,t?.sampleSize||1024),whiteSpace:t.preserveWhitespace===!1?void 0:{start:n.exec(e)?.[0]||``,end:r.exec(e)?.[0]||``}}}function a(e,n,r){!n||typeof n!=`object`||Object.defineProperty(n,t,{enumerable:!1,configurable:!0,writable:!0,value:i(e,r)})}function o(n,r){if(!n||typeof n!=`object`||!(t in n))return{indent:r?.indent??2,whitespace:{start:``,end:``}};let i=n[t];return{indent:r?.indent||e(i.sample||``).indent,whitespace:i.whiteSpace||{start:``,end:``}}}export{a as n,o as t};"],"x_google_ignoreList":[0],"mappings":";AAA6C,MAAM,IAAE,OAAO,IAAI,kBAAkB,EAAC,IAAE,UAAS,IAAE;AAAS,SAAS,EAAE,GAAE,IAAE,EAAE,EAAC;AAAC,QAAM;EAAC,QAAO,EAAE,WAAS,KAAK,KAAG,EAAE,wBAAsB,CAAC,KAAG,EAAE,MAAM,GAAE,GAAG,cAAY,KAAK;EAAC,YAAW,EAAE,uBAAqB,CAAC,IAAE,KAAK,IAAE;GAAC,OAAM,EAAE,KAAK,EAAE,GAAG,MAAI;GAAG,KAAI,EAAE,KAAK,EAAE,GAAG,MAAI;GAAG;EAAC;;AAAC,SAAS,EAAE,GAAE,GAAE,GAAE;AAAC,EAAC,KAAG,OAAO,KAAG,YAAU,OAAO,eAAe,GAAE,GAAE;EAAC,YAAW,CAAC;EAAE,cAAa,CAAC;EAAE,UAAS,CAAC;EAAE,OAAM,EAAE,GAAE,EAAE;EAAC,CAAC"}
1
+ {"version":3,"file":"_format-XTN-U4H5.js","names":[],"sources":["../../../node_modules/.pnpm/confbox@0.2.4/node_modules/confbox/dist/_chunks/_format.mjs"],"sourcesContent":["import{t as e}from\"./libs/detect-indent.mjs\";const t=Symbol.for(`__confbox_fmt__`),n=/^(\\s+)/,r=/(\\s+)$/;function i(e,t={}){return{sample:t.indent===void 0&&t.preserveIndentation!==!1&&e.slice(0,t?.sampleSize||1024),whiteSpace:t.preserveWhitespace===!1?void 0:{start:n.exec(e)?.[0]||``,end:r.exec(e)?.[0]||``}}}function a(e,n,r){!n||typeof n!=`object`||Object.defineProperty(n,t,{enumerable:!1,configurable:!0,writable:!0,value:i(e,r)})}function o(n,r){if(!n||typeof n!=`object`||!(t in n))return{indent:r?.indent??2,whitespace:{start:``,end:``}};let i=n[t];return{indent:r?.indent||e(i.sample||``).indent,whitespace:i.whiteSpace||{start:``,end:``}}}export{a as n,o as t};"],"x_google_ignoreList":[0],"mappings":";AAA6C,MAAM,IAAE,OAAO,IAAI,iBAAiB;AAAE,MAAA,IAAE;AAAS,MAAA,IAAE;AAAS,SAAS,EAAE,GAAE,IAAE,CAAC,GAAE;CAAC,OAAM;EAAC,QAAO,EAAE,WAAS,KAAK,KAAG,EAAE,wBAAsB,CAAC,KAAG,EAAE,MAAM,GAAE,GAAG,cAAY,IAAI;EAAE,YAAW,EAAE,uBAAqB,CAAC,IAAE,KAAK,IAAE;GAAC,OAAM,EAAE,KAAK,CAAC,CAAC,GAAG,MAAI;GAAG,KAAI,EAAE,KAAK,CAAC,CAAC,GAAG,MAAI;EAAE;CAAC;AAAC;AAAC,SAAS,EAAE,GAAE,GAAE,GAAE;CAAC,CAAC,KAAG,OAAO,KAAG,YAAU,OAAO,eAAe,GAAE,GAAE;EAAC,YAAW,CAAC;EAAE,cAAa,CAAC;EAAE,UAAS,CAAC;EAAE,OAAM,EAAE,GAAE,CAAC;CAAC,CAAC;AAAC"}
@@ -0,0 +1,74 @@
1
+ //#region ../utils/dist/result-BFErFpFT.js
2
+ /**
3
+ * Normalize an unknown caught value into an Error instance.
4
+ *
5
+ * If already an Error, returns it as-is. Otherwise wraps via `new Error(String(value))`.
6
+ *
7
+ * @param value - The unknown value to normalize.
8
+ * @returns An Error instance.
9
+ */
10
+ function toError(value) {
11
+ if (value instanceof Error) return value;
12
+ return new Error(String(value));
13
+ }
14
+ function ok(value) {
15
+ return [null, value];
16
+ }
17
+ /**
18
+ * Construct a failure Result tuple.
19
+ *
20
+ * Coerces any value to an `Error` via {@link toError} and returns `[Error, null]`.
21
+ * For domain-specific error types (e.g. `AuthError`, `IconsError`), use raw
22
+ * tuple literals instead: `[domainError, null] as const`.
23
+ *
24
+ * @param error - The error value (coerced to Error).
25
+ * @returns A Result tuple `[Error, null]`.
26
+ */
27
+ function err(error) {
28
+ return [toError(error), null];
29
+ }
30
+ //#endregion
31
+ //#region ../../node_modules/.pnpm/es-toolkit@1.50.0/node_modules/es-toolkit/dist/util/attemptAsync.mjs
32
+ /**
33
+ * Attempt to execute an async function and return the result or error.
34
+ * Returns a Promise that resolves to a tuple where:
35
+ * - On success: [null, Result] - First element is null, second is the result
36
+ * - On error: [Error, null] - First element is the caught error, second is null
37
+ *
38
+ * @template {unknown} T - The type of the result of the async function.
39
+ * @template {unknown} E - The type of the error that can be thrown by the async function.
40
+ * @param func - The async function to execute.
41
+ * @returns A Promise that resolves to a tuple containing either [null, result] or [error, null].
42
+ *
43
+ * @example
44
+ * // Successful execution
45
+ * const [error, data] = await attemptAsync(async () => {
46
+ * const response = await fetch('https://api.example.com/data');
47
+ * return response.json();
48
+ * });
49
+ * // If successful: [null, { ... data ... }]
50
+ *
51
+ * // Failed execution
52
+ * const [error, data] = await attemptAsync(async () => {
53
+ * throw new Error('Network error');
54
+ * });
55
+ * // [Error, null]
56
+ *
57
+ * // With type parameter
58
+ * const [error, users] = await attemptAsync<User[]>(async () => {
59
+ * const response = await fetch('https://api.example.com/users');
60
+ * return response.json();
61
+ * });
62
+ * // users is typed as User[]
63
+ */
64
+ async function attemptAsync(func) {
65
+ try {
66
+ return [null, await func()];
67
+ } catch (error) {
68
+ return [error, null];
69
+ }
70
+ }
71
+ //#endregion
72
+ export { toError as i, err as n, ok as r, attemptAsync as t };
73
+
74
+ //# sourceMappingURL=attemptAsync-D_oWcKfe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attemptAsync-D_oWcKfe.js","names":[],"sources":["../../utils/dist/result-BFErFpFT.js","../../../node_modules/.pnpm/es-toolkit@1.50.0/node_modules/es-toolkit/dist/util/attemptAsync.mjs"],"sourcesContent":["//#region src/fp/transform.ts\n/**\n* Normalize an unknown caught value into an Error instance.\n*\n* If already an Error, returns it as-is. Otherwise wraps via `new Error(String(value))`.\n*\n* @param value - The unknown value to normalize.\n* @returns An Error instance.\n*/\nfunction toError(value) {\n\tif (value instanceof Error) return value;\n\treturn new Error(String(value));\n}\n//#endregion\n//#region src/fp/result.ts\nfunction ok(value) {\n\treturn [null, value];\n}\n/**\n* Construct a failure Result tuple.\n*\n* Coerces any value to an `Error` via {@link toError} and returns `[Error, null]`.\n* For domain-specific error types (e.g. `AuthError`, `IconsError`), use raw\n* tuple literals instead: `[domainError, null] as const`.\n*\n* @param error - The error value (coerced to Error).\n* @returns A Result tuple `[Error, null]`.\n*/\nfunction err(error) {\n\treturn [toError(error), null];\n}\n//#endregion\nexport { ok as n, toError as r, err as t };\n\n//# sourceMappingURL=result-BFErFpFT.js.map","//#region src/util/attemptAsync.ts\n/**\n* Attempt to execute an async function and return the result or error.\n* Returns a Promise that resolves to a tuple where:\n* - On success: [null, Result] - First element is null, second is the result\n* - On error: [Error, null] - First element is the caught error, second is null\n*\n* @template {unknown} T - The type of the result of the async function.\n* @template {unknown} E - The type of the error that can be thrown by the async function.\n* @param func - The async function to execute.\n* @returns A Promise that resolves to a tuple containing either [null, result] or [error, null].\n*\n* @example\n* // Successful execution\n* const [error, data] = await attemptAsync(async () => {\n* const response = await fetch('https://api.example.com/data');\n* return response.json();\n* });\n* // If successful: [null, { ... data ... }]\n*\n* // Failed execution\n* const [error, data] = await attemptAsync(async () => {\n* throw new Error('Network error');\n* });\n* // [Error, null]\n*\n* // With type parameter\n* const [error, users] = await attemptAsync<User[]>(async () => {\n* const response = await fetch('https://api.example.com/users');\n* return response.json();\n* });\n* // users is typed as User[]\n*/\nasync function attemptAsync(func) {\n\ttry {\n\t\treturn [null, await func()];\n\t} catch (error) {\n\t\treturn [error, null];\n\t}\n}\n//#endregion\nexport { attemptAsync };\n"],"x_google_ignoreList":[1],"mappings":";;;;;;;;;AASA,SAAS,QAAQ,OAAO;CACvB,IAAI,iBAAiB,OAAO,OAAO;CACnC,OAAO,IAAI,MAAM,OAAO,KAAK,CAAC;AAC/B;AAGA,SAAS,GAAG,OAAO;CAClB,OAAO,CAAC,MAAM,KAAK;AACpB;;;;;;;;;;;AAWA,SAAS,IAAI,OAAO;CACnB,OAAO,CAAC,QAAQ,KAAK,GAAG,IAAI;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACGA,eAAe,aAAa,MAAM;CACjC,IAAI;EACH,OAAO,CAAC,MAAM,MAAM,KAAK,CAAC;CAC3B,SAAS,OAAO;EACf,OAAO,CAAC,OAAO,IAAI;CACpB;AACD"}
@@ -1,5 +1,4 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/add/command.d.ts
4
3
  declare const addCommandCommand: Command;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","names":[],"sources":["../../../src/commands/add/command.ts"],"mappings":";;;cAqBM,iBAAA,EAAmB,OAAA"}
1
+ {"version":3,"file":"command.d.ts","names":[],"sources":["../../../src/commands/add/command.ts"],"mappings":";;cAqBM,mBAAmB"}
@@ -1,7 +1,7 @@
1
- import { n as loadConfig } from "../../utils-DlIJNGLQ.js";
2
- import { n as renderTemplate, t as writeFiles } from "../../write-CSwG4Stj.js";
3
- import { t as isKebabCase } from "../../validate-C_SXBoLq.js";
4
- import { t as detectProject } from "../../detect-AOq1ehTE.js";
1
+ import { n as loadConfig } from "../../utils-ioeFEbm4.js";
2
+ import { n as renderTemplate, t as writeFiles } from "../../write-C6VsyUuc.js";
3
+ import { t as isKebabCase } from "../../validate-CX8axBK6.js";
4
+ import { t as detectProject } from "../../detect-Gdceq3rh.js";
5
5
  import { command } from "maltty";
6
6
  import { join } from "node:path";
7
7
  import { z } from "zod";
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","names":[],"sources":["../../../src/commands/add/command.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { loadConfig } from '@maltty/config/utils'\nimport type { LoadConfigResult } from '@maltty/config/utils'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\nimport { z } from 'zod'\n\nimport { detectProject } from '../../lib/detect.js'\nimport { renderTemplate } from '../../lib/render.js'\nimport { isKebabCase } from '../../lib/validate.js'\nimport { writeFiles } from '../../lib/write.js'\n\nconst options = z.object({\n args: z.boolean().describe('Include args schema').optional(),\n description: z.string().describe('Command description').optional(),\n name: z.string().describe('Command name (kebab-case)').optional(),\n})\n\ntype AddCommandArgs = z.infer<typeof options>\n\nconst addCommandCommand: Command = command({\n options,\n description: 'Add a new command to your project',\n handler: async (ctx: CommandContext<AddCommandArgs>) => {\n const cwd = process.cwd()\n\n const [detectError, project] = await detectProject(cwd)\n if (detectError) {\n return ctx.fail(detectError.message)\n }\n if (!project) {\n return ctx.fail('Not in a maltty project. Run `maltty init` first.')\n }\n\n const [, configResult] = await loadConfig({ cwd: project.rootDir })\n\n const commandName = await resolveCommandName(ctx)\n const commandDescription = await resolveDescription(ctx)\n const includeArgs = await resolveIncludeArgs(ctx)\n\n ctx.status.spinner.start('Generating command...')\n\n const templateDir = join(import.meta.dirname, '..', '..', 'lib', 'templates', 'command')\n const [renderError, rendered] = await renderTemplate({\n templateDir,\n variables: { commandName, description: commandDescription, includeArgs },\n })\n\n if (renderError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(renderError.message)\n }\n\n const outputDir = resolveCommandsDir(configResult, project.rootDir)\n const files = rendered.map((file) => ({\n content: file.content,\n relativePath: file.relativePath.replace('command.ts', `${commandName}.ts`),\n }))\n\n const [writeError, result] = await writeFiles({ files, outputDir, overwrite: false })\n\n if (writeError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(writeError.message)\n }\n\n ctx.status.spinner.stop('Command created!')\n\n const lines = [\n ...result.written.map((file) => ` created ${file}`),\n ...result.skipped.map((file) => ` skipped ${file} (already exists)`),\n ]\n const summary = lines.join('\\n')\n if (summary.length > 0) {\n ctx.log.raw(summary)\n }\n },\n})\n\nexport default addCommandCommand\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the command name from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The validated command name.\n * @private\n */\nasync function resolveCommandName(ctx: CommandContext<AddCommandArgs>): Promise<string> {\n if (ctx.args.name) {\n if (!isKebabCase(ctx.args.name)) {\n return ctx.fail('Command name must be kebab-case (e.g. deploy)')\n }\n return ctx.args.name\n }\n return ctx.prompts.text({\n message: 'Command name',\n placeholder: 'deploy',\n validate: (value: string | undefined) => {\n if (value === undefined || !isKebabCase(value)) {\n return 'Must be kebab-case (e.g. deploy)'\n }\n return undefined\n },\n })\n}\n\n/**\n * Resolve the command description from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The command description string.\n * @private\n */\nasync function resolveDescription(ctx: CommandContext<AddCommandArgs>): Promise<string> {\n if (ctx.args.description) {\n return ctx.args.description\n }\n return ctx.prompts.text({\n defaultValue: '',\n message: 'Description',\n placeholder: 'What does this command do?',\n })\n}\n\n/**\n * Resolve whether to include args from args or prompt.\n *\n * @param ctx - Command context.\n * @returns True when the command should include a zod args schema.\n * @private\n */\nasync function resolveIncludeArgs(ctx: CommandContext<AddCommandArgs>): Promise<boolean> {\n if (ctx.args.args !== undefined) {\n return ctx.args.args\n }\n return ctx.prompts.confirm({\n initialValue: true,\n message: 'Include args schema?',\n })\n}\n\n/**\n * Resolve the commands output directory from the maltty config.\n *\n * Uses the `commands` field from `maltty.config.ts` when available,\n * falling back to the maltty default of `'commands'`.\n *\n * @param configResult - The loaded config result, or null when loading failed.\n * @param rootDir - The project root directory.\n * @returns The absolute path to the commands directory.\n * @private\n */\nfunction resolveCommandsDir(configResult: LoadConfigResult | null, rootDir: string): string {\n const DEFAULT_COMMANDS = 'commands'\n\n if (configResult) {\n return join(rootDir, configResult.config.commands ?? DEFAULT_COMMANDS)\n }\n\n return join(rootDir, DEFAULT_COMMANDS)\n}\n"],"mappings":";;;;;;;;AAqBA,MAAM,oBAA6B,QAAQ;CACzC,SATc,EAAE,OAAO;EACvB,MAAM,EAAE,SAAS,CAAC,SAAS,sBAAsB,CAAC,UAAU;EAC5D,aAAa,EAAE,QAAQ,CAAC,SAAS,sBAAsB,CAAC,UAAU;EAClE,MAAM,EAAE,QAAQ,CAAC,SAAS,4BAA4B,CAAC,UAAU;EAClE,CAAC;CAMA,aAAa;CACb,SAAS,OAAO,QAAwC;EAGtD,MAAM,CAAC,aAAa,WAAW,MAAM,cAFzB,QAAQ,KAAK,CAE8B;AACvD,MAAI,YACF,QAAO,IAAI,KAAK,YAAY,QAAQ;AAEtC,MAAI,CAAC,QACH,QAAO,IAAI,KAAK,oDAAoD;EAGtE,MAAM,GAAG,gBAAgB,MAAM,WAAW,EAAE,KAAK,QAAQ,SAAS,CAAC;EAEnE,MAAM,cAAc,MAAM,mBAAmB,IAAI;EACjD,MAAM,qBAAqB,MAAM,mBAAmB,IAAI;EACxD,MAAM,cAAc,MAAM,mBAAmB,IAAI;AAEjD,MAAI,OAAO,QAAQ,MAAM,wBAAwB;EAGjD,MAAM,CAAC,aAAa,YAAY,MAAM,eAAe;GACnD,aAFkB,KAAK,OAAO,KAAK,SAAS,MAAM,MAAM,OAAO,aAAa,UAAU;GAGtF,WAAW;IAAE;IAAa,aAAa;IAAoB;IAAa;GACzE,CAAC;AAEF,MAAI,aAAa;AACf,OAAI,OAAO,QAAQ,KAAK,SAAS;AACjC,UAAO,IAAI,KAAK,YAAY,QAAQ;;EAGtC,MAAM,YAAY,mBAAmB,cAAc,QAAQ,QAAQ;EAMnE,MAAM,CAAC,YAAY,UAAU,MAAM,WAAW;GAAE,OALlC,SAAS,KAAK,UAAU;IACpC,SAAS,KAAK;IACd,cAAc,KAAK,aAAa,QAAQ,cAAc,GAAG,YAAY,KAAK;IAC3E,EAAE;GAEoD;GAAW,WAAW;GAAO,CAAC;AAErF,MAAI,YAAY;AACd,OAAI,OAAO,QAAQ,KAAK,SAAS;AACjC,UAAO,IAAI,KAAK,WAAW,QAAQ;;AAGrC,MAAI,OAAO,QAAQ,KAAK,mBAAmB;EAM3C,MAAM,UAJQ,CACZ,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,OAAO,EACpD,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,KAAK,mBAAmB,CACtE,CACqB,KAAK,KAAK;AAChC,MAAI,QAAQ,SAAS,EACnB,KAAI,IAAI,IAAI,QAAQ;;CAGzB,CAAC;;;;;;;;AAeF,eAAe,mBAAmB,KAAsD;AACtF,KAAI,IAAI,KAAK,MAAM;AACjB,MAAI,CAAC,YAAY,IAAI,KAAK,KAAK,CAC7B,QAAO,IAAI,KAAK,gDAAgD;AAElE,SAAO,IAAI,KAAK;;AAElB,QAAO,IAAI,QAAQ,KAAK;EACtB,SAAS;EACT,aAAa;EACb,WAAW,UAA8B;AACvC,OAAI,UAAU,KAAA,KAAa,CAAC,YAAY,MAAM,CAC5C,QAAO;;EAIZ,CAAC;;;;;;;;;AAUJ,eAAe,mBAAmB,KAAsD;AACtF,KAAI,IAAI,KAAK,YACX,QAAO,IAAI,KAAK;AAElB,QAAO,IAAI,QAAQ,KAAK;EACtB,cAAc;EACd,SAAS;EACT,aAAa;EACd,CAAC;;;;;;;;;AAUJ,eAAe,mBAAmB,KAAuD;AACvF,KAAI,IAAI,KAAK,SAAS,KAAA,EACpB,QAAO,IAAI,KAAK;AAElB,QAAO,IAAI,QAAQ,QAAQ;EACzB,cAAc;EACd,SAAS;EACV,CAAC;;;;;;;;;;;;;AAcJ,SAAS,mBAAmB,cAAuC,SAAyB;CAC1F,MAAM,mBAAmB;AAEzB,KAAI,aACF,QAAO,KAAK,SAAS,aAAa,OAAO,YAAY,iBAAiB;AAGxE,QAAO,KAAK,SAAS,iBAAiB"}
1
+ {"version":3,"file":"command.js","names":[],"sources":["../../../src/commands/add/command.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { loadConfig } from '@maltty/config/utils'\nimport type { LoadConfigResult } from '@maltty/config/utils'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\nimport { z } from 'zod'\n\nimport { detectProject } from '../../lib/detect.js'\nimport { renderTemplate } from '../../lib/render.js'\nimport { isKebabCase } from '../../lib/validate.js'\nimport { writeFiles } from '../../lib/write.js'\n\nconst options = z.object({\n args: z.boolean().describe('Include args schema').optional(),\n description: z.string().describe('Command description').optional(),\n name: z.string().describe('Command name (kebab-case)').optional(),\n})\n\ntype AddCommandArgs = z.infer<typeof options>\n\nconst addCommandCommand: Command = command({\n options,\n description: 'Add a new command to your project',\n handler: async (ctx: CommandContext<AddCommandArgs>) => {\n const cwd = process.cwd()\n\n const [detectError, project] = await detectProject(cwd)\n if (detectError) {\n return ctx.fail(detectError.message)\n }\n if (!project) {\n return ctx.fail('Not in a maltty project. Run `maltty init` first.')\n }\n\n const [, configResult] = await loadConfig({ cwd: project.rootDir })\n\n const commandName = await resolveCommandName(ctx)\n const commandDescription = await resolveDescription(ctx)\n const includeArgs = await resolveIncludeArgs(ctx)\n\n ctx.status.spinner.start('Generating command...')\n\n const templateDir = join(import.meta.dirname, '..', '..', 'lib', 'templates', 'command')\n const [renderError, rendered] = await renderTemplate({\n templateDir,\n variables: { commandName, description: commandDescription, includeArgs },\n })\n\n if (renderError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(renderError.message)\n }\n\n const outputDir = resolveCommandsDir(configResult, project.rootDir)\n const files = rendered.map((file) => ({\n content: file.content,\n relativePath: file.relativePath.replace('command.ts', `${commandName}.ts`),\n }))\n\n const [writeError, result] = await writeFiles({ files, outputDir, overwrite: false })\n\n if (writeError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(writeError.message)\n }\n\n ctx.status.spinner.stop('Command created!')\n\n const lines = [\n ...result.written.map((file) => ` created ${file}`),\n ...result.skipped.map((file) => ` skipped ${file} (already exists)`),\n ]\n const summary = lines.join('\\n')\n if (summary.length > 0) {\n ctx.log.raw(summary)\n }\n },\n})\n\nexport default addCommandCommand\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the command name from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The validated command name.\n * @private\n */\nasync function resolveCommandName(ctx: CommandContext<AddCommandArgs>): Promise<string> {\n if (ctx.args.name) {\n if (!isKebabCase(ctx.args.name)) {\n return ctx.fail('Command name must be kebab-case (e.g. deploy)')\n }\n return ctx.args.name\n }\n return ctx.prompts.text({\n message: 'Command name',\n placeholder: 'deploy',\n validate: (value: string | undefined) => {\n if (value === undefined || !isKebabCase(value)) {\n return 'Must be kebab-case (e.g. deploy)'\n }\n return undefined\n },\n })\n}\n\n/**\n * Resolve the command description from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The command description string.\n * @private\n */\nasync function resolveDescription(ctx: CommandContext<AddCommandArgs>): Promise<string> {\n if (ctx.args.description) {\n return ctx.args.description\n }\n return ctx.prompts.text({\n defaultValue: '',\n message: 'Description',\n placeholder: 'What does this command do?',\n })\n}\n\n/**\n * Resolve whether to include args from args or prompt.\n *\n * @param ctx - Command context.\n * @returns True when the command should include a zod args schema.\n * @private\n */\nasync function resolveIncludeArgs(ctx: CommandContext<AddCommandArgs>): Promise<boolean> {\n if (ctx.args.args !== undefined) {\n return ctx.args.args\n }\n return ctx.prompts.confirm({\n initialValue: true,\n message: 'Include args schema?',\n })\n}\n\n/**\n * Resolve the commands output directory from the maltty config.\n *\n * Uses the `commands` field from `maltty.config.ts` when available,\n * falling back to the maltty default of `'commands'`.\n *\n * @param configResult - The loaded config result, or null when loading failed.\n * @param rootDir - The project root directory.\n * @returns The absolute path to the commands directory.\n * @private\n */\nfunction resolveCommandsDir(configResult: LoadConfigResult | null, rootDir: string): string {\n const DEFAULT_COMMANDS = 'commands'\n\n if (configResult) {\n return join(rootDir, configResult.config.commands ?? DEFAULT_COMMANDS)\n }\n\n return join(rootDir, DEFAULT_COMMANDS)\n}\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/add/config.d.ts
4
3
  declare const addConfigCommand: Command;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/commands/add/config.ts"],"mappings":";;;cAUM,gBAAA,EAAkB,OAAA"}
1
+ {"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/commands/add/config.ts"],"mappings":";;cAUM,kBAAkB"}
@@ -1,6 +1,6 @@
1
- import { t as readManifest } from "../../manifest-BIKVDJML.js";
2
- import { n as renderTemplate, t as writeFiles } from "../../write-CSwG4Stj.js";
3
- import { t as detectProject } from "../../detect-AOq1ehTE.js";
1
+ import { t as readManifest } from "../../manifest-C192Fk9X.js";
2
+ import { n as renderTemplate, t as writeFiles } from "../../write-C6VsyUuc.js";
3
+ import { t as detectProject } from "../../detect-Gdceq3rh.js";
4
4
  import { command } from "maltty";
5
5
  import { join } from "node:path";
6
6
  //#region src/commands/add/config.ts
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../src/commands/add/config.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { readManifest } from '@maltty/utils/manifest'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\n\nimport { detectProject } from '../../lib/detect.js'\nimport { renderTemplate } from '../../lib/render.js'\nimport { writeFiles } from '../../lib/write.js'\n\nconst addConfigCommand: Command = command({\n description: 'Add a config schema to your project',\n handler: async (ctx: CommandContext) => {\n const cwd = process.cwd()\n\n const [detectError, project] = await detectProject(cwd)\n if (detectError) {\n return ctx.fail(detectError.message)\n }\n if (!project) {\n return ctx.fail('Not in a maltty project. Run `maltty init` first.')\n }\n\n const projectName = await resolveProjectName(project.rootDir)\n\n ctx.status.spinner.start('Generating config...')\n\n const templateDir = join(import.meta.dirname, '..', '..', 'lib', 'templates', 'config')\n const [renderError, rendered] = await renderTemplate({\n templateDir,\n variables: { name: projectName },\n })\n\n if (renderError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(renderError.message)\n }\n\n const outputDir = join(project.rootDir, 'src')\n const [writeError, result] = await writeFiles({ files: rendered, outputDir, overwrite: false })\n\n if (writeError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(writeError.message)\n }\n\n ctx.status.spinner.stop('Config created!')\n\n const lines = [\n ...result.written.map((file) => ` created ${file}`),\n ...result.skipped.map((file) => ` skipped ${file} (already exists)`),\n ]\n const summary = lines.join('\\n')\n if (summary.length > 0) {\n ctx.log.raw(summary)\n }\n\n ctx.log.newline()\n ctx.log.raw('Next steps:')\n ctx.log.raw(' 1. Add fields to the config schema in src/config.ts')\n ctx.log.raw(' 2. Import and pass the schema to cli({ config: { schema: configSchema } })')\n },\n})\n\nexport default addConfigCommand\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_NAME = 'my-app'\n\n/**\n * Resolve the project name from the project's package.json.\n *\n * @param rootDir - The project root directory.\n * @returns The project name from package.json, or a default fallback.\n * @private\n */\nasync function resolveProjectName(rootDir: string): Promise<string> {\n const [error, manifest] = await readManifest(rootDir)\n if (error || !manifest.name) {\n return DEFAULT_NAME\n }\n return manifest.name\n}\n"],"mappings":";;;;;;AAUA,MAAM,mBAA4B,QAAQ;CACxC,aAAa;CACb,SAAS,OAAO,QAAwB;EAGtC,MAAM,CAAC,aAAa,WAAW,MAAM,cAFzB,QAAQ,KAAK,CAE8B;AACvD,MAAI,YACF,QAAO,IAAI,KAAK,YAAY,QAAQ;AAEtC,MAAI,CAAC,QACH,QAAO,IAAI,KAAK,oDAAoD;EAGtE,MAAM,cAAc,MAAM,mBAAmB,QAAQ,QAAQ;AAE7D,MAAI,OAAO,QAAQ,MAAM,uBAAuB;EAGhD,MAAM,CAAC,aAAa,YAAY,MAAM,eAAe;GACnD,aAFkB,KAAK,OAAO,KAAK,SAAS,MAAM,MAAM,OAAO,aAAa,SAAS;GAGrF,WAAW,EAAE,MAAM,aAAa;GACjC,CAAC;AAEF,MAAI,aAAa;AACf,OAAI,OAAO,QAAQ,KAAK,SAAS;AACjC,UAAO,IAAI,KAAK,YAAY,QAAQ;;EAItC,MAAM,CAAC,YAAY,UAAU,MAAM,WAAW;GAAE,OAAO;GAAU,WAD/C,KAAK,QAAQ,SAAS,MAAM;GAC8B,WAAW;GAAO,CAAC;AAE/F,MAAI,YAAY;AACd,OAAI,OAAO,QAAQ,KAAK,SAAS;AACjC,UAAO,IAAI,KAAK,WAAW,QAAQ;;AAGrC,MAAI,OAAO,QAAQ,KAAK,kBAAkB;EAM1C,MAAM,UAJQ,CACZ,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,OAAO,EACpD,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,KAAK,mBAAmB,CACtE,CACqB,KAAK,KAAK;AAChC,MAAI,QAAQ,SAAS,EACnB,KAAI,IAAI,IAAI,QAAQ;AAGtB,MAAI,IAAI,SAAS;AACjB,MAAI,IAAI,IAAI,cAAc;AAC1B,MAAI,IAAI,IAAI,wDAAwD;AACpE,MAAI,IAAI,IAAI,+EAA+E;;CAE9F,CAAC;AAQF,MAAM,eAAe;;;;;;;;AASrB,eAAe,mBAAmB,SAAkC;CAClE,MAAM,CAAC,OAAO,YAAY,MAAM,aAAa,QAAQ;AACrD,KAAI,SAAS,CAAC,SAAS,KACrB,QAAO;AAET,QAAO,SAAS"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../src/commands/add/config.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { readManifest } from '@maltty/utils/manifest'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\n\nimport { detectProject } from '../../lib/detect.js'\nimport { renderTemplate } from '../../lib/render.js'\nimport { writeFiles } from '../../lib/write.js'\n\nconst addConfigCommand: Command = command({\n description: 'Add a config schema to your project',\n handler: async (ctx: CommandContext) => {\n const cwd = process.cwd()\n\n const [detectError, project] = await detectProject(cwd)\n if (detectError) {\n return ctx.fail(detectError.message)\n }\n if (!project) {\n return ctx.fail('Not in a maltty project. Run `maltty init` first.')\n }\n\n const projectName = await resolveProjectName(project.rootDir)\n\n ctx.status.spinner.start('Generating config...')\n\n const templateDir = join(import.meta.dirname, '..', '..', 'lib', 'templates', 'config')\n const [renderError, rendered] = await renderTemplate({\n templateDir,\n variables: { name: projectName },\n })\n\n if (renderError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(renderError.message)\n }\n\n const outputDir = join(project.rootDir, 'src')\n const [writeError, result] = await writeFiles({ files: rendered, outputDir, overwrite: false })\n\n if (writeError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(writeError.message)\n }\n\n ctx.status.spinner.stop('Config created!')\n\n const lines = [\n ...result.written.map((file) => ` created ${file}`),\n ...result.skipped.map((file) => ` skipped ${file} (already exists)`),\n ]\n const summary = lines.join('\\n')\n if (summary.length > 0) {\n ctx.log.raw(summary)\n }\n\n ctx.log.newline()\n ctx.log.raw('Next steps:')\n ctx.log.raw(' 1. Add fields to the config schema in src/config.ts')\n ctx.log.raw(' 2. Import and pass the schema to cli({ config: { schema: configSchema } })')\n },\n})\n\nexport default addConfigCommand\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_NAME = 'my-app'\n\n/**\n * Resolve the project name from the project's package.json.\n *\n * @param rootDir - The project root directory.\n * @returns The project name from package.json, or a default fallback.\n * @private\n */\nasync function resolveProjectName(rootDir: string): Promise<string> {\n const [error, manifest] = await readManifest(rootDir)\n if (error || !manifest.name) {\n return DEFAULT_NAME\n }\n return manifest.name\n}\n"],"mappings":";;;;;;AAUA,MAAM,mBAA4B,QAAQ;CACxC,aAAa;CACb,SAAS,OAAO,QAAwB;EAGtC,MAAM,CAAC,aAAa,WAAW,MAAM,cAFzB,QAAQ,IAEiC,CAAC;EACtD,IAAI,aACF,OAAO,IAAI,KAAK,YAAY,OAAO;EAErC,IAAI,CAAC,SACH,OAAO,IAAI,KAAK,mDAAmD;EAGrE,MAAM,cAAc,MAAM,mBAAmB,QAAQ,OAAO;EAE5D,IAAI,OAAO,QAAQ,MAAM,sBAAsB;EAG/C,MAAM,CAAC,aAAa,YAAY,MAAM,eAAe;GACnD,aAFkB,KAAK,OAAO,KAAK,SAAS,MAAM,MAAM,OAAO,aAAa,QAElE;GACV,WAAW,EAAE,MAAM,YAAY;EACjC,CAAC;EAED,IAAI,aAAa;GACf,IAAI,OAAO,QAAQ,KAAK,QAAQ;GAChC,OAAO,IAAI,KAAK,YAAY,OAAO;EACrC;EAGA,MAAM,CAAC,YAAY,UAAU,MAAM,WAAW;GAAE,OAAO;GAAU,WAD/C,KAAK,QAAQ,SAAS,KACiC;GAAG,WAAW;EAAM,CAAC;EAE9F,IAAI,YAAY;GACd,IAAI,OAAO,QAAQ,KAAK,QAAQ;GAChC,OAAO,IAAI,KAAK,WAAW,OAAO;EACpC;EAEA,IAAI,OAAO,QAAQ,KAAK,iBAAiB;EAMzC,MAAM,UAAU,CAHd,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,MAAM,GACnD,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,KAAK,kBAAkB,CAElD,CAAC,CAAC,KAAK,IAAI;EAC/B,IAAI,QAAQ,SAAS,GACnB,IAAI,IAAI,IAAI,OAAO;EAGrB,IAAI,IAAI,QAAQ;EAChB,IAAI,IAAI,IAAI,aAAa;EACzB,IAAI,IAAI,IAAI,uDAAuD;EACnE,IAAI,IAAI,IAAI,8EAA8E;CAC5F;AACF,CAAC;AAQD,MAAM,eAAe;;;;;;;;AASrB,eAAe,mBAAmB,SAAkC;CAClE,MAAM,CAAC,OAAO,YAAY,MAAM,aAAa,OAAO;CACpD,IAAI,SAAS,CAAC,SAAS,MACrB,OAAO;CAET,OAAO,SAAS;AAClB"}
@@ -1,5 +1,4 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/add/index.d.ts
4
3
  declare const addCommand: Command;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/commands/add/index.ts"],"mappings":";;;cAGM,UAAA,EAAY,OAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/commands/add/index.ts"],"mappings":";;cAGM,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/commands/add/index.ts"],"sourcesContent":["import { command } from 'maltty'\nimport type { Command } from 'maltty'\n\nconst addCommand: Command = command({\n description: 'Add a command, middleware, or config to your project',\n})\n\nexport default addCommand\n"],"mappings":";;AAGA,MAAM,aAAsB,QAAQ,EAClC,aAAa,wDACd,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/commands/add/index.ts"],"sourcesContent":["import { command } from 'maltty'\nimport type { Command } from 'maltty'\n\nconst addCommand: Command = command({\n description: 'Add a command, middleware, or config to your project',\n})\n\nexport default addCommand\n"],"mappings":";;AAGA,MAAM,aAAsB,QAAQ,EAClC,aAAa,uDACf,CAAC"}
@@ -1,5 +1,4 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/add/middleware.d.ts
4
3
  declare const addMiddlewareCommand: Command;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","names":[],"sources":["../../../src/commands/add/middleware.ts"],"mappings":";;;cAkBM,oBAAA,EAAsB,OAAA"}
1
+ {"version":3,"file":"middleware.d.ts","names":[],"sources":["../../../src/commands/add/middleware.ts"],"mappings":";;cAkBM,sBAAsB"}
@@ -1,6 +1,6 @@
1
- import { n as renderTemplate, t as writeFiles } from "../../write-CSwG4Stj.js";
2
- import { t as isKebabCase } from "../../validate-C_SXBoLq.js";
3
- import { t as detectProject } from "../../detect-AOq1ehTE.js";
1
+ import { n as renderTemplate, t as writeFiles } from "../../write-C6VsyUuc.js";
2
+ import { t as isKebabCase } from "../../validate-CX8axBK6.js";
3
+ import { t as detectProject } from "../../detect-Gdceq3rh.js";
4
4
  import { command } from "maltty";
5
5
  import { join } from "node:path";
6
6
  import { z } from "zod";
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","names":[],"sources":["../../../src/commands/add/middleware.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\nimport { z } from 'zod'\n\nimport { detectProject } from '../../lib/detect.js'\nimport { renderTemplate } from '../../lib/render.js'\nimport { isKebabCase } from '../../lib/validate.js'\nimport { writeFiles } from '../../lib/write.js'\n\nconst options = z.object({\n description: z.string().describe('Middleware description').optional(),\n name: z.string().describe('Middleware name (kebab-case)').optional(),\n})\n\ntype AddMiddlewareArgs = z.infer<typeof options>\n\nconst addMiddlewareCommand: Command = command({\n options,\n description: 'Add a new middleware to your project',\n handler: async (ctx: CommandContext<AddMiddlewareArgs>) => {\n const [detectError, project] = await detectProject(process.cwd())\n if (detectError) {\n return ctx.fail(detectError.message)\n }\n if (!project) {\n return ctx.fail('Not in a maltty project. Run `maltty init` first.')\n }\n\n const middlewareName = await resolveMiddlewareName(ctx)\n const middlewareDescription = await resolveDescription(ctx)\n\n ctx.status.spinner.start('Generating middleware...')\n\n const templateDir = join(import.meta.dirname, '..', '..', 'lib', 'templates', 'middleware')\n const [renderError, rendered] = await renderTemplate({\n templateDir,\n variables: { description: middlewareDescription, middlewareName },\n })\n\n if (renderError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(renderError.message)\n }\n\n const outputDir = join(project.rootDir, 'src', 'middleware')\n const files = rendered.map((file) => ({\n content: file.content,\n relativePath: file.relativePath.replace('middleware.ts', `${middlewareName}.ts`),\n }))\n\n const [writeError, result] = await writeFiles({ files, outputDir, overwrite: false })\n\n if (writeError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(writeError.message)\n }\n\n ctx.status.spinner.stop('Middleware created!')\n\n const lines = [\n ...result.written.map((file) => ` created ${file}`),\n ...result.skipped.map((file) => ` skipped ${file} (already exists)`),\n ]\n const summary = lines.join('\\n')\n if (summary.length > 0) {\n ctx.log.raw(summary)\n }\n },\n})\n\nexport default addMiddlewareCommand\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the middleware name from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The validated middleware name.\n * @private\n */\nasync function resolveMiddlewareName(ctx: CommandContext<AddMiddlewareArgs>): Promise<string> {\n if (ctx.args.name) {\n if (!isKebabCase(ctx.args.name)) {\n return ctx.fail('Middleware name must be kebab-case (e.g. auth)')\n }\n return ctx.args.name\n }\n return ctx.prompts.text({\n message: 'Middleware name',\n placeholder: 'auth',\n validate: (value: string | undefined) => {\n if (value === undefined || !isKebabCase(value)) {\n return 'Must be kebab-case (e.g. auth)'\n }\n return undefined\n },\n })\n}\n\n/**\n * Resolve the middleware description from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The middleware description string.\n * @private\n */\nasync function resolveDescription(ctx: CommandContext<AddMiddlewareArgs>): Promise<string> {\n if (ctx.args.description) {\n return ctx.args.description\n }\n return ctx.prompts.text({\n defaultValue: '',\n message: 'Description',\n placeholder: 'What does this middleware do?',\n })\n}\n"],"mappings":";;;;;;;AAkBA,MAAM,uBAAgC,QAAQ;CAC5C,SARc,EAAE,OAAO;EACvB,aAAa,EAAE,QAAQ,CAAC,SAAS,yBAAyB,CAAC,UAAU;EACrE,MAAM,EAAE,QAAQ,CAAC,SAAS,+BAA+B,CAAC,UAAU;EACrE,CAAC;CAMA,aAAa;CACb,SAAS,OAAO,QAA2C;EACzD,MAAM,CAAC,aAAa,WAAW,MAAM,cAAc,QAAQ,KAAK,CAAC;AACjE,MAAI,YACF,QAAO,IAAI,KAAK,YAAY,QAAQ;AAEtC,MAAI,CAAC,QACH,QAAO,IAAI,KAAK,oDAAoD;EAGtE,MAAM,iBAAiB,MAAM,sBAAsB,IAAI;EACvD,MAAM,wBAAwB,MAAM,mBAAmB,IAAI;AAE3D,MAAI,OAAO,QAAQ,MAAM,2BAA2B;EAGpD,MAAM,CAAC,aAAa,YAAY,MAAM,eAAe;GACnD,aAFkB,KAAK,OAAO,KAAK,SAAS,MAAM,MAAM,OAAO,aAAa,aAAa;GAGzF,WAAW;IAAE,aAAa;IAAuB;IAAgB;GAClE,CAAC;AAEF,MAAI,aAAa;AACf,OAAI,OAAO,QAAQ,KAAK,SAAS;AACjC,UAAO,IAAI,KAAK,YAAY,QAAQ;;EAGtC,MAAM,YAAY,KAAK,QAAQ,SAAS,OAAO,aAAa;EAM5D,MAAM,CAAC,YAAY,UAAU,MAAM,WAAW;GAAE,OALlC,SAAS,KAAK,UAAU;IACpC,SAAS,KAAK;IACd,cAAc,KAAK,aAAa,QAAQ,iBAAiB,GAAG,eAAe,KAAK;IACjF,EAAE;GAEoD;GAAW,WAAW;GAAO,CAAC;AAErF,MAAI,YAAY;AACd,OAAI,OAAO,QAAQ,KAAK,SAAS;AACjC,UAAO,IAAI,KAAK,WAAW,QAAQ;;AAGrC,MAAI,OAAO,QAAQ,KAAK,sBAAsB;EAM9C,MAAM,UAJQ,CACZ,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,OAAO,EACpD,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,KAAK,mBAAmB,CACtE,CACqB,KAAK,KAAK;AAChC,MAAI,QAAQ,SAAS,EACnB,KAAI,IAAI,IAAI,QAAQ;;CAGzB,CAAC;;;;;;;;AAeF,eAAe,sBAAsB,KAAyD;AAC5F,KAAI,IAAI,KAAK,MAAM;AACjB,MAAI,CAAC,YAAY,IAAI,KAAK,KAAK,CAC7B,QAAO,IAAI,KAAK,iDAAiD;AAEnE,SAAO,IAAI,KAAK;;AAElB,QAAO,IAAI,QAAQ,KAAK;EACtB,SAAS;EACT,aAAa;EACb,WAAW,UAA8B;AACvC,OAAI,UAAU,KAAA,KAAa,CAAC,YAAY,MAAM,CAC5C,QAAO;;EAIZ,CAAC;;;;;;;;;AAUJ,eAAe,mBAAmB,KAAyD;AACzF,KAAI,IAAI,KAAK,YACX,QAAO,IAAI,KAAK;AAElB,QAAO,IAAI,QAAQ,KAAK;EACtB,cAAc;EACd,SAAS;EACT,aAAa;EACd,CAAC"}
1
+ {"version":3,"file":"middleware.js","names":[],"sources":["../../../src/commands/add/middleware.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\nimport { z } from 'zod'\n\nimport { detectProject } from '../../lib/detect.js'\nimport { renderTemplate } from '../../lib/render.js'\nimport { isKebabCase } from '../../lib/validate.js'\nimport { writeFiles } from '../../lib/write.js'\n\nconst options = z.object({\n description: z.string().describe('Middleware description').optional(),\n name: z.string().describe('Middleware name (kebab-case)').optional(),\n})\n\ntype AddMiddlewareArgs = z.infer<typeof options>\n\nconst addMiddlewareCommand: Command = command({\n options,\n description: 'Add a new middleware to your project',\n handler: async (ctx: CommandContext<AddMiddlewareArgs>) => {\n const [detectError, project] = await detectProject(process.cwd())\n if (detectError) {\n return ctx.fail(detectError.message)\n }\n if (!project) {\n return ctx.fail('Not in a maltty project. Run `maltty init` first.')\n }\n\n const middlewareName = await resolveMiddlewareName(ctx)\n const middlewareDescription = await resolveDescription(ctx)\n\n ctx.status.spinner.start('Generating middleware...')\n\n const templateDir = join(import.meta.dirname, '..', '..', 'lib', 'templates', 'middleware')\n const [renderError, rendered] = await renderTemplate({\n templateDir,\n variables: { description: middlewareDescription, middlewareName },\n })\n\n if (renderError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(renderError.message)\n }\n\n const outputDir = join(project.rootDir, 'src', 'middleware')\n const files = rendered.map((file) => ({\n content: file.content,\n relativePath: file.relativePath.replace('middleware.ts', `${middlewareName}.ts`),\n }))\n\n const [writeError, result] = await writeFiles({ files, outputDir, overwrite: false })\n\n if (writeError) {\n ctx.status.spinner.stop('Failed')\n return ctx.fail(writeError.message)\n }\n\n ctx.status.spinner.stop('Middleware created!')\n\n const lines = [\n ...result.written.map((file) => ` created ${file}`),\n ...result.skipped.map((file) => ` skipped ${file} (already exists)`),\n ]\n const summary = lines.join('\\n')\n if (summary.length > 0) {\n ctx.log.raw(summary)\n }\n },\n})\n\nexport default addMiddlewareCommand\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the middleware name from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The validated middleware name.\n * @private\n */\nasync function resolveMiddlewareName(ctx: CommandContext<AddMiddlewareArgs>): Promise<string> {\n if (ctx.args.name) {\n if (!isKebabCase(ctx.args.name)) {\n return ctx.fail('Middleware name must be kebab-case (e.g. auth)')\n }\n return ctx.args.name\n }\n return ctx.prompts.text({\n message: 'Middleware name',\n placeholder: 'auth',\n validate: (value: string | undefined) => {\n if (value === undefined || !isKebabCase(value)) {\n return 'Must be kebab-case (e.g. auth)'\n }\n return undefined\n },\n })\n}\n\n/**\n * Resolve the middleware description from args or prompt.\n *\n * @param ctx - Command context.\n * @returns The middleware description string.\n * @private\n */\nasync function resolveDescription(ctx: CommandContext<AddMiddlewareArgs>): Promise<string> {\n if (ctx.args.description) {\n return ctx.args.description\n }\n return ctx.prompts.text({\n defaultValue: '',\n message: 'Description',\n placeholder: 'What does this middleware do?',\n })\n}\n"],"mappings":";;;;;;;AAkBA,MAAM,uBAAgC,QAAQ;CAC5C,SARc,EAAE,OAAO;EACvB,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,wBAAwB,CAAC,CAAC,SAAS;EACpE,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,8BAA8B,CAAC,CAAC,SAAS;CACrE,CAKQ;CACN,aAAa;CACb,SAAS,OAAO,QAA2C;EACzD,MAAM,CAAC,aAAa,WAAW,MAAM,cAAc,QAAQ,IAAI,CAAC;EAChE,IAAI,aACF,OAAO,IAAI,KAAK,YAAY,OAAO;EAErC,IAAI,CAAC,SACH,OAAO,IAAI,KAAK,mDAAmD;EAGrE,MAAM,iBAAiB,MAAM,sBAAsB,GAAG;EACtD,MAAM,wBAAwB,MAAM,mBAAmB,GAAG;EAE1D,IAAI,OAAO,QAAQ,MAAM,0BAA0B;EAGnD,MAAM,CAAC,aAAa,YAAY,MAAM,eAAe;GACnD,aAFkB,KAAK,OAAO,KAAK,SAAS,MAAM,MAAM,OAAO,aAAa,YAElE;GACV,WAAW;IAAE,aAAa;IAAuB;GAAe;EAClE,CAAC;EAED,IAAI,aAAa;GACf,IAAI,OAAO,QAAQ,KAAK,QAAQ;GAChC,OAAO,IAAI,KAAK,YAAY,OAAO;EACrC;EAEA,MAAM,YAAY,KAAK,QAAQ,SAAS,OAAO,YAAY;EAM3D,MAAM,CAAC,YAAY,UAAU,MAAM,WAAW;GAAE,OALlC,SAAS,KAAK,UAAU;IACpC,SAAS,KAAK;IACd,cAAc,KAAK,aAAa,QAAQ,iBAAiB,GAAG,eAAe,IAAI;GACjF,EAEoD;GAAG;GAAW,WAAW;EAAM,CAAC;EAEpF,IAAI,YAAY;GACd,IAAI,OAAO,QAAQ,KAAK,QAAQ;GAChC,OAAO,IAAI,KAAK,WAAW,OAAO;EACpC;EAEA,IAAI,OAAO,QAAQ,KAAK,qBAAqB;EAM7C,MAAM,UAAU,CAHd,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,MAAM,GACnD,GAAG,OAAO,QAAQ,KAAK,SAAS,aAAa,KAAK,kBAAkB,CAElD,CAAC,CAAC,KAAK,IAAI;EAC/B,IAAI,QAAQ,SAAS,GACnB,IAAI,IAAI,IAAI,OAAO;CAEvB;AACF,CAAC;;;;;;;;AAeD,eAAe,sBAAsB,KAAyD;CAC5F,IAAI,IAAI,KAAK,MAAM;EACjB,IAAI,CAAC,YAAY,IAAI,KAAK,IAAI,GAC5B,OAAO,IAAI,KAAK,gDAAgD;EAElE,OAAO,IAAI,KAAK;CAClB;CACA,OAAO,IAAI,QAAQ,KAAK;EACtB,SAAS;EACT,aAAa;EACb,WAAW,UAA8B;GACvC,IAAI,UAAU,KAAA,KAAa,CAAC,YAAY,KAAK,GAC3C,OAAO;EAGX;CACF,CAAC;AACH;;;;;;;;AASA,eAAe,mBAAmB,KAAyD;CACzF,IAAI,IAAI,KAAK,aACX,OAAO,IAAI,KAAK;CAElB,OAAO,IAAI,QAAQ,KAAK;EACtB,cAAc;EACd,SAAS;EACT,aAAa;CACf,CAAC;AACH"}
@@ -1,14 +1,13 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/build.d.ts
4
3
  /**
5
- * Build a maltty CLI project for production.
6
- *
7
- * Loads the project's `maltty.config.ts`, invokes the bundler, and reports
8
- * the output entry file and directory on success. When `--compile` or
9
- * `--targets` is provided (or `compile` is set in config), also compiles
10
- * to standalone binaries via Bun.
11
- */
4
+ * Build a maltty CLI project for production.
5
+ *
6
+ * Loads the project's `maltty.config.ts`, invokes the bundler, and reports
7
+ * the output entry file and directory on success. When `--compile` or
8
+ * `--targets` is provided (or `compile` is set in config), also compiles
9
+ * to standalone binaries via Bun.
10
+ */
12
11
  declare const buildCommand: Command;
13
12
  //#endregion
14
13
  export { buildCommand as default };
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","names":[],"sources":["../../src/commands/build.ts"],"mappings":";;;;;AAO6C;;;;;;cA0BvC,YAAA,EAAc,OAAA"}
1
+ {"version":3,"file":"build.d.ts","names":[],"sources":["../../src/commands/build.ts"],"mappings":";;;;;;;;;;cAiCM,cAAc"}
@@ -1,6 +1,6 @@
1
- import { i as normalizeCompileOptions, r as createBundler } from "../dist-DW_gRP7_.js";
2
- import { n as loadConfig } from "../utils-DlIJNGLQ.js";
3
- import { t as extractConfig } from "../config-helpers-pv_2Spux.js";
1
+ import { i as normalizeCompileOptions, r as createBundler } from "../dist-FY8K5na4.js";
2
+ import { n as loadConfig } from "../utils-ioeFEbm4.js";
3
+ import { t as extractConfig } from "../config-helpers-DAy-Arox.js";
4
4
  import { command } from "maltty";
5
5
  import { relative } from "node:path";
6
6
  import { z } from "zod";
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","names":[],"sources":["../../src/commands/build.ts"],"sourcesContent":["import { relative } from 'node:path'\n\nimport { createBundler, normalizeCompileOptions } from '@maltty/bundler'\nimport type { CompiledBinary } from '@maltty/bundler'\nimport type { CompileTarget, MalttyConfig } from '@maltty/config'\nimport { loadConfig } from '@maltty/config/utils'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\nimport pc from 'picocolors'\nimport { z } from 'zod'\n\nimport { extractConfig } from '../lib/config-helpers.js'\n\nconst options = z.object({\n clean: z.boolean().optional().describe('Clean build artifacts before bundling (default: true)'),\n compile: z.boolean().optional().describe('Compile to standalone binaries after bundling'),\n targets: z.array(z.string()).optional().describe('Compile targets (implies --compile)'),\n verbose: z\n .boolean()\n .optional()\n .describe('Show detailed error output on bundle or compile failure'),\n})\n\ntype BuildArgs = z.infer<typeof options>\n\n/**\n * Build a maltty CLI project for production.\n *\n * Loads the project's `maltty.config.ts`, invokes the bundler, and reports\n * the output entry file and directory on success. When `--compile` or\n * `--targets` is provided (or `compile` is set in config), also compiles\n * to standalone binaries via Bun.\n */\nconst buildCommand: Command = command({\n options,\n description: 'Build a maltty CLI project for production',\n handler: async (ctx: CommandContext<BuildArgs>) => {\n const cwd = process.cwd()\n const startTime = Date.now()\n\n const [, configResult] = await loadConfig({ cwd })\n const config = mergeCleanOption({ config: extractConfig(configResult), clean: ctx.args.clean })\n\n const shouldCompile = resolveCompileIntent({\n compileFlag: ctx.args.compile,\n configCompile: config.compile,\n targets: ctx.args.targets,\n })\n\n const mergedConfig = resolveMergedConfig({\n config,\n shouldCompile,\n targets: ctx.args.targets,\n })\n\n const bundler = await createBundler({\n config: mergedConfig,\n cwd,\n onStepStart: ({ meta }) =>\n ctx.status.spinner.message(`Compiling ${String(meta.label ?? 'target')}...`),\n onStepFinish: ({ meta }) =>\n ctx.status.spinner.message(`Compiled ${String(meta.label ?? 'target')}`),\n })\n\n ctx.status.spinner.start('Bundling...')\n\n const [buildError, buildOutput] = await bundler.build({ verbose: ctx.args.verbose })\n\n if (buildError) {\n ctx.status.spinner.stop('Bundle failed')\n return ctx.fail(buildError.message)\n }\n\n if (!shouldCompile) {\n ctx.status.spinner.stop('Build complete')\n ctx.log.note(\n formatBuildNote({\n cwd,\n define: buildOutput.define,\n entryFile: buildOutput.entryFile,\n outDir: buildOutput.outDir,\n version: buildOutput.version,\n }),\n 'Bundle'\n )\n ctx.log.outro(formatOutroSummary({ binaries: 0, duration: Date.now() - startTime }))\n return\n }\n\n ctx.status.spinner.message('Bundled, compiling binaries...')\n\n const [compileError, compileOutput] = await bundler.compile({\n verbose: ctx.args.verbose,\n })\n\n if (compileError) {\n ctx.status.spinner.stop('Compile failed')\n return ctx.fail(compileError.message)\n }\n\n ctx.status.spinner.stop('Build complete')\n ctx.log.note(\n formatBuildNote({\n cwd,\n define: buildOutput.define,\n entryFile: buildOutput.entryFile,\n outDir: buildOutput.outDir,\n version: buildOutput.version,\n }),\n 'Bundle'\n )\n ctx.log.note(formatBinariesNote({ binaries: compileOutput.binaries, cwd }), 'Binaries')\n ctx.log.outro(\n formatOutroSummary({\n binaries: compileOutput.binaries.length,\n duration: Date.now() - startTime,\n })\n )\n },\n})\n\nexport default buildCommand\n\n// ---------------------------------------------------------------------------\n\n/**\n * Apply compile-target overrides to the config when compilation will run.\n *\n * @private\n * @param params - The base config, compile decision, and CLI target overrides.\n * @returns The config to hand to the bundler.\n */\nfunction resolveMergedConfig(params: {\n readonly config: MalttyConfig\n readonly shouldCompile: boolean\n readonly targets: readonly string[] | undefined\n}): MalttyConfig {\n if (params.shouldCompile) {\n return mergeCompileTargets({ config: params.config, targets: params.targets })\n }\n return params.config\n}\n\n/**\n * Determine whether compilation should run based on CLI flags and config.\n *\n * Resolution order:\n * 1. `--targets` provided → compile (implied)\n * 2. `--compile` flag → use its boolean value\n * 3. Fall back to config `compile` field (truthy = compile)\n *\n * @private\n * @param params - The CLI flags and config compile field.\n * @returns Whether to run the compile step.\n */\nfunction resolveCompileIntent(params: {\n readonly targets: readonly string[] | undefined\n readonly compileFlag: boolean | undefined\n readonly configCompile: boolean | MalttyConfig['compile']\n}): boolean {\n if (params.targets && params.targets.length > 0) {\n return true\n }\n\n if (params.compileFlag !== undefined) {\n return params.compileFlag\n }\n\n if (params.configCompile === true) {\n return true\n }\n\n if (typeof params.configCompile === 'object') {\n return true\n }\n\n return false\n}\n\n/**\n * Merge CLI `--targets` into the config's compile options.\n *\n * @private\n * @param params - The config and optional CLI targets.\n * @returns A config with compile targets merged in.\n */\nfunction mergeCompileTargets(params: {\n readonly config: MalttyConfig\n readonly targets: readonly string[] | undefined\n}): MalttyConfig {\n if (!params.targets || params.targets.length === 0) {\n return params.config\n }\n\n const existingCompile = normalizeCompileOptions(params.config.compile)\n\n return {\n ...params.config,\n compile: {\n ...existingCompile,\n targets: params.targets as CompileTarget[],\n },\n }\n}\n\n/**\n * Merge the CLI `--clean` / `--no-clean` flag into the loaded config.\n *\n * @private\n * @param params - The loaded config and optional CLI clean flag.\n * @returns A config with the clean option merged in.\n */\nfunction mergeCleanOption(params: {\n readonly config: MalttyConfig\n readonly clean: boolean | undefined\n}): MalttyConfig {\n if (params.clean === undefined) {\n return params.config\n }\n\n return {\n ...params.config,\n build: {\n ...params.config.build,\n clean: params.clean,\n },\n }\n}\n\n/**\n * Format bundle output into a multi-line string for display.\n *\n * @private\n * @param params - The build output paths and working directory.\n * @returns A formatted string with entry and output directory.\n */\nfunction formatBuildNote(params: {\n readonly entryFile: string\n readonly outDir: string\n readonly cwd: string\n readonly version: string | undefined\n readonly define: Readonly<Record<string, string>>\n}): string {\n return [\n `entry ${relative(params.cwd, params.entryFile)}`,\n `output ${relative(params.cwd, params.outDir)}`,\n ...formatVersionLine(params.version),\n ...formatDefineLines(params.define),\n ].join('\\n')\n}\n\n/**\n * Format a version line for the build note, if a version is available.\n *\n * @private\n * @param version - The version string, or undefined.\n * @returns A single-element array with the formatted line, or an empty array.\n */\nfunction formatVersionLine(version: string | undefined): string[] {\n if (!version) {\n return []\n }\n\n return [`version ${version}`]\n}\n\n/**\n * Format define constants into display lines.\n *\n * Omits `__MALTTY_VERSION__` (already shown as `version`) and returns\n * remaining entries as `define key = value` lines.\n *\n * @private\n * @param define - The resolved define map.\n * @returns An array of formatted lines (empty when no user-defined constants).\n */\n/**\n * Format the outro summary line with build stats.\n *\n * @private\n * @param params - Build stats for the summary.\n * @returns A formatted inline summary string.\n */\nfunction formatOutroSummary(params: {\n readonly binaries: number\n readonly duration: number\n}): string {\n const stats = [\n ...formatBinariesSegment(params.binaries),\n `finished in ${formatDuration(params.duration)}`,\n ]\n\n return stats.join(pc.gray(' · '))\n}\n\n/**\n * Build the optional \"binaries compiled\" segment of the outro summary.\n *\n * @private\n * @param count - The number of compiled binaries.\n * @returns A single-element array describing the count, or an empty array.\n */\nfunction formatBinariesSegment(count: number): readonly string[] {\n if (count > 0) {\n return [`${count} binaries compiled`]\n }\n return []\n}\n\n/**\n * Format a millisecond duration into a human-readable string.\n *\n * @private\n * @param ms - Duration in milliseconds.\n * @returns A formatted duration string (e.g. \"1.2s\", \"350ms\").\n */\nfunction formatDuration(ms: number): string {\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(1)}s`\n }\n return `${ms}ms`\n}\n\nfunction formatDefineLines(define: Readonly<Record<string, string>>): string[] {\n return Object.entries(define).map(([key, value]) => `build_var ${key} = ${value}`)\n}\n\n/**\n * Format compiled binaries into an aligned, multi-line string for display.\n *\n * @private\n * @param params - The binaries and working directory for relative path resolution.\n * @returns A formatted string with one line per binary.\n */\nfunction formatBinariesNote(params: {\n readonly binaries: readonly CompiledBinary[]\n readonly cwd: string\n}): string {\n const maxLen = Math.max(...params.binaries.map((b) => b.label.length))\n\n return params.binaries\n .map((binary) => `${binary.label.padEnd(maxLen)} ${relative(params.cwd, binary.path)}`)\n .join('\\n')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"build.js","names":[],"sources":["../../src/commands/build.ts"],"sourcesContent":["import { relative } from 'node:path'\n\nimport { createBundler, normalizeCompileOptions } from '@maltty/bundler'\nimport type { CompiledBinary } from '@maltty/bundler'\nimport type { CompileTarget, MalttyConfig } from '@maltty/config'\nimport { loadConfig } from '@maltty/config/utils'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\nimport pc from 'picocolors'\nimport { z } from 'zod'\n\nimport { extractConfig } from '../lib/config-helpers.js'\n\nconst options = z.object({\n clean: z.boolean().optional().describe('Clean build artifacts before bundling (default: true)'),\n compile: z.boolean().optional().describe('Compile to standalone binaries after bundling'),\n targets: z.array(z.string()).optional().describe('Compile targets (implies --compile)'),\n verbose: z\n .boolean()\n .optional()\n .describe('Show detailed error output on bundle or compile failure'),\n})\n\ntype BuildArgs = z.infer<typeof options>\n\n/**\n * Build a maltty CLI project for production.\n *\n * Loads the project's `maltty.config.ts`, invokes the bundler, and reports\n * the output entry file and directory on success. When `--compile` or\n * `--targets` is provided (or `compile` is set in config), also compiles\n * to standalone binaries via Bun.\n */\nconst buildCommand: Command = command({\n options,\n description: 'Build a maltty CLI project for production',\n handler: async (ctx: CommandContext<BuildArgs>) => {\n const cwd = process.cwd()\n const startTime = Date.now()\n\n const [, configResult] = await loadConfig({ cwd })\n const config = mergeCleanOption({ config: extractConfig(configResult), clean: ctx.args.clean })\n\n const shouldCompile = resolveCompileIntent({\n compileFlag: ctx.args.compile,\n configCompile: config.compile,\n targets: ctx.args.targets,\n })\n\n const mergedConfig = resolveMergedConfig({\n config,\n shouldCompile,\n targets: ctx.args.targets,\n })\n\n const bundler = await createBundler({\n config: mergedConfig,\n cwd,\n onStepStart: ({ meta }) =>\n ctx.status.spinner.message(`Compiling ${String(meta.label ?? 'target')}...`),\n onStepFinish: ({ meta }) =>\n ctx.status.spinner.message(`Compiled ${String(meta.label ?? 'target')}`),\n })\n\n ctx.status.spinner.start('Bundling...')\n\n const [buildError, buildOutput] = await bundler.build({ verbose: ctx.args.verbose })\n\n if (buildError) {\n ctx.status.spinner.stop('Bundle failed')\n return ctx.fail(buildError.message)\n }\n\n if (!shouldCompile) {\n ctx.status.spinner.stop('Build complete')\n ctx.log.note(\n formatBuildNote({\n cwd,\n define: buildOutput.define,\n entryFile: buildOutput.entryFile,\n outDir: buildOutput.outDir,\n version: buildOutput.version,\n }),\n 'Bundle'\n )\n ctx.log.outro(formatOutroSummary({ binaries: 0, duration: Date.now() - startTime }))\n return\n }\n\n ctx.status.spinner.message('Bundled, compiling binaries...')\n\n const [compileError, compileOutput] = await bundler.compile({\n verbose: ctx.args.verbose,\n })\n\n if (compileError) {\n ctx.status.spinner.stop('Compile failed')\n return ctx.fail(compileError.message)\n }\n\n ctx.status.spinner.stop('Build complete')\n ctx.log.note(\n formatBuildNote({\n cwd,\n define: buildOutput.define,\n entryFile: buildOutput.entryFile,\n outDir: buildOutput.outDir,\n version: buildOutput.version,\n }),\n 'Bundle'\n )\n ctx.log.note(formatBinariesNote({ binaries: compileOutput.binaries, cwd }), 'Binaries')\n ctx.log.outro(\n formatOutroSummary({\n binaries: compileOutput.binaries.length,\n duration: Date.now() - startTime,\n })\n )\n },\n})\n\nexport default buildCommand\n\n// ---------------------------------------------------------------------------\n\n/**\n * Apply compile-target overrides to the config when compilation will run.\n *\n * @private\n * @param params - The base config, compile decision, and CLI target overrides.\n * @returns The config to hand to the bundler.\n */\nfunction resolveMergedConfig(params: {\n readonly config: MalttyConfig\n readonly shouldCompile: boolean\n readonly targets: readonly string[] | undefined\n}): MalttyConfig {\n if (params.shouldCompile) {\n return mergeCompileTargets({ config: params.config, targets: params.targets })\n }\n return params.config\n}\n\n/**\n * Determine whether compilation should run based on CLI flags and config.\n *\n * Resolution order:\n * 1. `--targets` provided → compile (implied)\n * 2. `--compile` flag → use its boolean value\n * 3. Fall back to config `compile` field (truthy = compile)\n *\n * @private\n * @param params - The CLI flags and config compile field.\n * @returns Whether to run the compile step.\n */\nfunction resolveCompileIntent(params: {\n readonly targets: readonly string[] | undefined\n readonly compileFlag: boolean | undefined\n readonly configCompile: boolean | MalttyConfig['compile']\n}): boolean {\n if (params.targets && params.targets.length > 0) {\n return true\n }\n\n if (params.compileFlag !== undefined) {\n return params.compileFlag\n }\n\n if (params.configCompile === true) {\n return true\n }\n\n if (typeof params.configCompile === 'object') {\n return true\n }\n\n return false\n}\n\n/**\n * Merge CLI `--targets` into the config's compile options.\n *\n * @private\n * @param params - The config and optional CLI targets.\n * @returns A config with compile targets merged in.\n */\nfunction mergeCompileTargets(params: {\n readonly config: MalttyConfig\n readonly targets: readonly string[] | undefined\n}): MalttyConfig {\n if (!params.targets || params.targets.length === 0) {\n return params.config\n }\n\n const existingCompile = normalizeCompileOptions(params.config.compile)\n\n return {\n ...params.config,\n compile: {\n ...existingCompile,\n targets: params.targets as CompileTarget[],\n },\n }\n}\n\n/**\n * Merge the CLI `--clean` / `--no-clean` flag into the loaded config.\n *\n * @private\n * @param params - The loaded config and optional CLI clean flag.\n * @returns A config with the clean option merged in.\n */\nfunction mergeCleanOption(params: {\n readonly config: MalttyConfig\n readonly clean: boolean | undefined\n}): MalttyConfig {\n if (params.clean === undefined) {\n return params.config\n }\n\n return {\n ...params.config,\n build: {\n ...params.config.build,\n clean: params.clean,\n },\n }\n}\n\n/**\n * Format bundle output into a multi-line string for display.\n *\n * @private\n * @param params - The build output paths and working directory.\n * @returns A formatted string with entry and output directory.\n */\nfunction formatBuildNote(params: {\n readonly entryFile: string\n readonly outDir: string\n readonly cwd: string\n readonly version: string | undefined\n readonly define: Readonly<Record<string, string>>\n}): string {\n return [\n `entry ${relative(params.cwd, params.entryFile)}`,\n `output ${relative(params.cwd, params.outDir)}`,\n ...formatVersionLine(params.version),\n ...formatDefineLines(params.define),\n ].join('\\n')\n}\n\n/**\n * Format a version line for the build note, if a version is available.\n *\n * @private\n * @param version - The version string, or undefined.\n * @returns A single-element array with the formatted line, or an empty array.\n */\nfunction formatVersionLine(version: string | undefined): string[] {\n if (!version) {\n return []\n }\n\n return [`version ${version}`]\n}\n\n/**\n * Format define constants into display lines.\n *\n * Omits `__MALTTY_VERSION__` (already shown as `version`) and returns\n * remaining entries as `define key = value` lines.\n *\n * @private\n * @param define - The resolved define map.\n * @returns An array of formatted lines (empty when no user-defined constants).\n */\n/**\n * Format the outro summary line with build stats.\n *\n * @private\n * @param params - Build stats for the summary.\n * @returns A formatted inline summary string.\n */\nfunction formatOutroSummary(params: {\n readonly binaries: number\n readonly duration: number\n}): string {\n const stats = [\n ...formatBinariesSegment(params.binaries),\n `finished in ${formatDuration(params.duration)}`,\n ]\n\n return stats.join(pc.gray(' · '))\n}\n\n/**\n * Build the optional \"binaries compiled\" segment of the outro summary.\n *\n * @private\n * @param count - The number of compiled binaries.\n * @returns A single-element array describing the count, or an empty array.\n */\nfunction formatBinariesSegment(count: number): readonly string[] {\n if (count > 0) {\n return [`${count} binaries compiled`]\n }\n return []\n}\n\n/**\n * Format a millisecond duration into a human-readable string.\n *\n * @private\n * @param ms - Duration in milliseconds.\n * @returns A formatted duration string (e.g. \"1.2s\", \"350ms\").\n */\nfunction formatDuration(ms: number): string {\n if (ms >= 1000) {\n return `${(ms / 1000).toFixed(1)}s`\n }\n return `${ms}ms`\n}\n\nfunction formatDefineLines(define: Readonly<Record<string, string>>): string[] {\n return Object.entries(define).map(([key, value]) => `build_var ${key} = ${value}`)\n}\n\n/**\n * Format compiled binaries into an aligned, multi-line string for display.\n *\n * @private\n * @param params - The binaries and working directory for relative path resolution.\n * @returns A formatted string with one line per binary.\n */\nfunction formatBinariesNote(params: {\n readonly binaries: readonly CompiledBinary[]\n readonly cwd: string\n}): string {\n const maxLen = Math.max(...params.binaries.map((b) => b.label.length))\n\n return params.binaries\n .map((binary) => `${binary.label.padEnd(maxLen)} ${relative(params.cwd, binary.path)}`)\n .join('\\n')\n}\n"],"mappings":"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"}
@@ -1,13 +1,12 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/commands.d.ts
4
3
  /**
5
- * Display the command tree for a maltty CLI project.
6
- *
7
- * Loads the project's `maltty.config.ts` to locate the commands directory,
8
- * scans it with the autoloader, and prints an ASCII tree of all discovered
9
- * commands and subcommands.
10
- */
4
+ * Display the command tree for a maltty CLI project.
5
+ *
6
+ * Loads the project's `maltty.config.ts` to locate the commands directory,
7
+ * scans it with the autoloader, and prints an ASCII tree of all discovered
8
+ * commands and subcommands.
9
+ */
11
10
  declare const commandsCommand: Command;
12
11
  //#endregion
13
12
  export { commandsCommand as default };
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","names":[],"sources":["../../src/commands/commands.ts"],"mappings":";;;;;AAK8D;;;;;cAoBxD,eAAA,EAAiB,OAAA"}
1
+ {"version":3,"file":"commands.d.ts","names":[],"sources":["../../src/commands/commands.ts"],"mappings":";;;;;;;;;cAyBM,iBAAiB"}
@@ -1,6 +1,6 @@
1
- import { r as fs_exports } from "../node-C91xGGqn.js";
2
- import { n as loadConfig } from "../utils-DlIJNGLQ.js";
3
- import { t as extractConfig } from "../config-helpers-pv_2Spux.js";
1
+ import { t as fs_exports } from "../fs-Uxhr-pvi-AfTuGWmD.js";
2
+ import { n as loadConfig } from "../utils-ioeFEbm4.js";
3
+ import { t as extractConfig } from "../config-helpers-DAy-Arox.js";
4
4
  import { autoload, command } from "maltty";
5
5
  import { join } from "node:path";
6
6
  //#region src/commands/commands.ts
@@ -109,12 +109,12 @@ function validateOrder(params) {
109
109
  if (!nameSet.has(name)) {
110
110
  console.warn(`Warning: unknown command "${name}" in order array`);
111
111
  return {
112
- seen: new Set([...acc.seen, name]),
112
+ seen: /* @__PURE__ */ new Set([...acc.seen, name]),
113
113
  valid: acc.valid
114
114
  };
115
115
  }
116
116
  return {
117
- seen: new Set([...acc.seen, name]),
117
+ seen: /* @__PURE__ */ new Set([...acc.seen, name]),
118
118
  valid: [...acc.valid, name]
119
119
  };
120
120
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","names":["fs"],"sources":["../../src/commands/commands.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { loadConfig } from '@maltty/config/utils'\nimport { fs } from '@maltty/utils/node'\nimport { autoload, command } from 'maltty'\nimport type { Command as MalttyCommand, CommandContext } from 'maltty'\n\nimport { extractConfig } from '../lib/config-helpers.js'\n\n/**\n * A single node in the rendered command tree.\n */\ninterface TreeEntry {\n readonly name: string\n readonly description: string\n readonly children: readonly TreeEntry[]\n}\n\n/**\n * Display the command tree for a maltty CLI project.\n *\n * Loads the project's `maltty.config.ts` to locate the commands directory,\n * scans it with the autoloader, and prints an ASCII tree of all discovered\n * commands and subcommands.\n */\nconst commandsCommand: MalttyCommand = command({\n description: 'Display the command tree for a maltty CLI project',\n handler: async (ctx: CommandContext) => {\n const cwd = process.cwd()\n\n const [, configResult] = await loadConfig({ cwd })\n const config = extractConfig(configResult)\n\n const commandsDir = join(cwd, config.commands ?? 'commands')\n\n if (!(await fs.exists(commandsDir))) {\n return ctx.fail(`Commands directory not found: ${commandsDir}`)\n }\n\n ctx.status.spinner.start('Scanning commands...')\n\n const commandMap = await autoload({ dir: commandsDir })\n const tree = await buildTree(commandMap)\n\n ctx.status.spinner.stop('Commands')\n\n if (tree.length === 0) {\n ctx.log.raw('No commands found')\n return\n }\n\n ctx.log.raw(renderTree(tree))\n },\n})\n\nexport default commandsCommand\n\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a command's subcommands field, which may be a Promise, a map, or undefined.\n *\n * @private\n * @param commands - The raw subcommands value from a Command object.\n * @returns The resolved CommandMap, or an empty object when none exist.\n */\nasync function resolveSubcommands(\n commands: Record<string, MalttyCommand> | Promise<Record<string, MalttyCommand>> | undefined\n): Promise<Record<string, MalttyCommand>> {\n if (!commands) {\n return {}\n }\n\n if (commands instanceof Promise) {\n return commands\n }\n\n return commands\n}\n\n/**\n * Recursively build a sorted tree of entries from a CommandMap.\n *\n * Commands listed in the order array appear first in the specified order;\n * omitted commands fall back to alphabetical sort.\n *\n * @private\n * @param commandMap - The map of command names to Command objects.\n * @param order - Optional array of command names defining display order.\n * @returns A sorted array of TreeEntry nodes.\n */\nasync function buildTree(\n commandMap: Record<string, MalttyCommand>,\n order?: readonly string[]\n): Promise<readonly TreeEntry[]> {\n const entries = sortEntries({ entries: Object.entries(commandMap), order })\n\n return Promise.all(\n entries.map(async ([name, cmd]): Promise<TreeEntry> => {\n const subMap = await resolveSubcommands(cmd.commands)\n const children = await buildTree(subMap, cmd.help?.order)\n\n return {\n children,\n description: cmd.description ?? '',\n name,\n }\n })\n )\n}\n\n/**\n * Sort command entries with ordered names first (in specified order),\n * remaining names alphabetically.\n *\n * Validates the order array against available command names and logs a\n * warning for unknown or duplicate entries rather than failing silently.\n *\n * @private\n * @param params - The command entries and optional order array.\n * @returns Sorted array of entries.\n */\nfunction sortEntries(params: {\n readonly entries: [string, MalttyCommand][]\n readonly order?: readonly string[]\n}): [string, MalttyCommand][] {\n const { entries, order } = params\n\n if (!order || order.length === 0) {\n return entries.toSorted(([a], [b]) => a.localeCompare(b))\n }\n\n const commandNames = entries.map(([name]) => name)\n const validOrder = validateOrder({ commandNames, order })\n\n const entryMap = new Map(entries)\n const orderedSet = new Set(validOrder)\n\n const ordered = validOrder\n .filter((name) => entryMap.has(name))\n .map((name): [string, MalttyCommand] => [name, entryMap.get(name) as MalttyCommand])\n\n const remaining = entries\n .filter(([name]) => !orderedSet.has(name))\n .toSorted(([a], [b]) => a.localeCompare(b))\n\n return [...ordered, ...remaining]\n}\n\n/**\n * Validate the order array by filtering out unknown and duplicate names.\n *\n * Logs warnings for invalid entries so developers see the mismatch\n * during `maltty commands` introspection, matching the runtime behaviour.\n *\n * @private\n * @param params - The order array and available command names.\n * @returns A deduplicated array of valid order names.\n */\nfunction validateOrder(params: {\n readonly commandNames: readonly string[]\n readonly order: readonly string[]\n}): readonly string[] {\n const { commandNames, order } = params\n const nameSet = new Set(commandNames)\n\n const { valid } = order.reduce<{\n readonly seen: ReadonlySet<string>\n readonly valid: readonly string[]\n }>(\n (acc, name) => {\n if (acc.seen.has(name)) {\n console.warn(`Warning: duplicate command name \"${name}\" in order array`)\n return acc\n }\n\n if (!nameSet.has(name)) {\n console.warn(`Warning: unknown command \"${name}\" in order array`)\n return { seen: new Set([...acc.seen, name]), valid: acc.valid }\n }\n\n return { seen: new Set([...acc.seen, name]), valid: [...acc.valid, name] }\n },\n { seen: new Set<string>(), valid: [] }\n )\n\n return valid\n}\n\n/**\n * Render a tree of entries into an ASCII tree string.\n *\n * @private\n * @param entries - The top-level tree entries to render.\n * @returns The formatted tree string.\n */\nfunction renderTree(entries: readonly TreeEntry[]): string {\n return renderEntries(entries, '').join('\\n')\n}\n\n/**\n * Recursively render tree entries with proper box-drawing connectors.\n *\n * @private\n * @param entries - The entries at this level.\n * @param prefix - The prefix string for indentation.\n * @returns An array of formatted lines.\n */\nfunction renderEntries(entries: readonly TreeEntry[], prefix: string): readonly string[] {\n return entries.flatMap((entry, index) => {\n const isLast = index === entries.length - 1\n const connector = resolveConnector(isLast)\n const childPrefix = resolveChildPrefix(isLast)\n const label = formatLabel(entry.name, entry.description)\n const line = `${prefix}${connector}${label}`\n const childLines = renderEntries(entry.children, `${prefix}${childPrefix}`)\n\n return [line, ...childLines]\n })\n}\n\n/**\n * Get the box-drawing connector for a tree entry.\n *\n * @private\n * @param isLast - Whether this is the last entry at its level.\n * @returns The connector string.\n */\nfunction resolveConnector(isLast: boolean): string {\n if (isLast) {\n return '└── '\n }\n\n return '├── '\n}\n\n/**\n * Get the indentation prefix for children of a tree entry.\n *\n * @private\n * @param isLast - Whether the parent is the last entry at its level.\n * @returns The child prefix string.\n */\nfunction resolveChildPrefix(isLast: boolean): string {\n if (isLast) {\n return ' '\n }\n\n return '│ '\n}\n\n/**\n * Format a command name and description into a tree label.\n *\n * @private\n * @param name - The command name.\n * @param description - The command description (may be empty).\n * @returns The formatted label string.\n */\nfunction formatLabel(name: string, description: string): string {\n if (description) {\n return `${name} — ${description}`\n }\n\n return name\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","names":["fs"],"sources":["../../src/commands/commands.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { loadConfig } from '@maltty/config/utils'\nimport { fs } from '@maltty/utils/node'\nimport { autoload, command } from 'maltty'\nimport type { Command as MalttyCommand, CommandContext } from 'maltty'\n\nimport { extractConfig } from '../lib/config-helpers.js'\n\n/**\n * A single node in the rendered command tree.\n */\ninterface TreeEntry {\n readonly name: string\n readonly description: string\n readonly children: readonly TreeEntry[]\n}\n\n/**\n * Display the command tree for a maltty CLI project.\n *\n * Loads the project's `maltty.config.ts` to locate the commands directory,\n * scans it with the autoloader, and prints an ASCII tree of all discovered\n * commands and subcommands.\n */\nconst commandsCommand: MalttyCommand = command({\n description: 'Display the command tree for a maltty CLI project',\n handler: async (ctx: CommandContext) => {\n const cwd = process.cwd()\n\n const [, configResult] = await loadConfig({ cwd })\n const config = extractConfig(configResult)\n\n const commandsDir = join(cwd, config.commands ?? 'commands')\n\n if (!(await fs.exists(commandsDir))) {\n return ctx.fail(`Commands directory not found: ${commandsDir}`)\n }\n\n ctx.status.spinner.start('Scanning commands...')\n\n const commandMap = await autoload({ dir: commandsDir })\n const tree = await buildTree(commandMap)\n\n ctx.status.spinner.stop('Commands')\n\n if (tree.length === 0) {\n ctx.log.raw('No commands found')\n return\n }\n\n ctx.log.raw(renderTree(tree))\n },\n})\n\nexport default commandsCommand\n\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a command's subcommands field, which may be a Promise, a map, or undefined.\n *\n * @private\n * @param commands - The raw subcommands value from a Command object.\n * @returns The resolved CommandMap, or an empty object when none exist.\n */\nasync function resolveSubcommands(\n commands: Record<string, MalttyCommand> | Promise<Record<string, MalttyCommand>> | undefined\n): Promise<Record<string, MalttyCommand>> {\n if (!commands) {\n return {}\n }\n\n if (commands instanceof Promise) {\n return commands\n }\n\n return commands\n}\n\n/**\n * Recursively build a sorted tree of entries from a CommandMap.\n *\n * Commands listed in the order array appear first in the specified order;\n * omitted commands fall back to alphabetical sort.\n *\n * @private\n * @param commandMap - The map of command names to Command objects.\n * @param order - Optional array of command names defining display order.\n * @returns A sorted array of TreeEntry nodes.\n */\nasync function buildTree(\n commandMap: Record<string, MalttyCommand>,\n order?: readonly string[]\n): Promise<readonly TreeEntry[]> {\n const entries = sortEntries({ entries: Object.entries(commandMap), order })\n\n return Promise.all(\n entries.map(async ([name, cmd]): Promise<TreeEntry> => {\n const subMap = await resolveSubcommands(cmd.commands)\n const children = await buildTree(subMap, cmd.help?.order)\n\n return {\n children,\n description: cmd.description ?? '',\n name,\n }\n })\n )\n}\n\n/**\n * Sort command entries with ordered names first (in specified order),\n * remaining names alphabetically.\n *\n * Validates the order array against available command names and logs a\n * warning for unknown or duplicate entries rather than failing silently.\n *\n * @private\n * @param params - The command entries and optional order array.\n * @returns Sorted array of entries.\n */\nfunction sortEntries(params: {\n readonly entries: [string, MalttyCommand][]\n readonly order?: readonly string[]\n}): [string, MalttyCommand][] {\n const { entries, order } = params\n\n if (!order || order.length === 0) {\n return entries.toSorted(([a], [b]) => a.localeCompare(b))\n }\n\n const commandNames = entries.map(([name]) => name)\n const validOrder = validateOrder({ commandNames, order })\n\n const entryMap = new Map(entries)\n const orderedSet = new Set(validOrder)\n\n const ordered = validOrder\n .filter((name) => entryMap.has(name))\n .map((name): [string, MalttyCommand] => [name, entryMap.get(name) as MalttyCommand])\n\n const remaining = entries\n .filter(([name]) => !orderedSet.has(name))\n .toSorted(([a], [b]) => a.localeCompare(b))\n\n return [...ordered, ...remaining]\n}\n\n/**\n * Validate the order array by filtering out unknown and duplicate names.\n *\n * Logs warnings for invalid entries so developers see the mismatch\n * during `maltty commands` introspection, matching the runtime behaviour.\n *\n * @private\n * @param params - The order array and available command names.\n * @returns A deduplicated array of valid order names.\n */\nfunction validateOrder(params: {\n readonly commandNames: readonly string[]\n readonly order: readonly string[]\n}): readonly string[] {\n const { commandNames, order } = params\n const nameSet = new Set(commandNames)\n\n const { valid } = order.reduce<{\n readonly seen: ReadonlySet<string>\n readonly valid: readonly string[]\n }>(\n (acc, name) => {\n if (acc.seen.has(name)) {\n console.warn(`Warning: duplicate command name \"${name}\" in order array`)\n return acc\n }\n\n if (!nameSet.has(name)) {\n console.warn(`Warning: unknown command \"${name}\" in order array`)\n return { seen: new Set([...acc.seen, name]), valid: acc.valid }\n }\n\n return { seen: new Set([...acc.seen, name]), valid: [...acc.valid, name] }\n },\n { seen: new Set<string>(), valid: [] }\n )\n\n return valid\n}\n\n/**\n * Render a tree of entries into an ASCII tree string.\n *\n * @private\n * @param entries - The top-level tree entries to render.\n * @returns The formatted tree string.\n */\nfunction renderTree(entries: readonly TreeEntry[]): string {\n return renderEntries(entries, '').join('\\n')\n}\n\n/**\n * Recursively render tree entries with proper box-drawing connectors.\n *\n * @private\n * @param entries - The entries at this level.\n * @param prefix - The prefix string for indentation.\n * @returns An array of formatted lines.\n */\nfunction renderEntries(entries: readonly TreeEntry[], prefix: string): readonly string[] {\n return entries.flatMap((entry, index) => {\n const isLast = index === entries.length - 1\n const connector = resolveConnector(isLast)\n const childPrefix = resolveChildPrefix(isLast)\n const label = formatLabel(entry.name, entry.description)\n const line = `${prefix}${connector}${label}`\n const childLines = renderEntries(entry.children, `${prefix}${childPrefix}`)\n\n return [line, ...childLines]\n })\n}\n\n/**\n * Get the box-drawing connector for a tree entry.\n *\n * @private\n * @param isLast - Whether this is the last entry at its level.\n * @returns The connector string.\n */\nfunction resolveConnector(isLast: boolean): string {\n if (isLast) {\n return '└── '\n }\n\n return '├── '\n}\n\n/**\n * Get the indentation prefix for children of a tree entry.\n *\n * @private\n * @param isLast - Whether the parent is the last entry at its level.\n * @returns The child prefix string.\n */\nfunction resolveChildPrefix(isLast: boolean): string {\n if (isLast) {\n return ' '\n }\n\n return '│ '\n}\n\n/**\n * Format a command name and description into a tree label.\n *\n * @private\n * @param name - The command name.\n * @param description - The command description (may be empty).\n * @returns The formatted label string.\n */\nfunction formatLabel(name: string, description: string): string {\n if (description) {\n return `${name} — ${description}`\n }\n\n return name\n}\n"],"mappings":";;;;;;;;;;;;;AAyBA,MAAM,kBAAiC,QAAQ;CAC7C,aAAa;CACb,SAAS,OAAO,QAAwB;EACtC,MAAM,MAAM,QAAQ,IAAI;EAExB,MAAM,GAAG,gBAAgB,MAAM,WAAW,EAAE,IAAI,CAAC;EAGjD,MAAM,cAAc,KAAK,KAFV,cAAc,YAEM,CAAC,CAAC,YAAY,UAAU;EAE3D,IAAI,CAAE,MAAMA,WAAG,OAAO,WAAW,GAC/B,OAAO,IAAI,KAAK,iCAAiC,aAAa;EAGhE,IAAI,OAAO,QAAQ,MAAM,sBAAsB;EAG/C,MAAM,OAAO,MAAM,UAAU,MADJ,SAAS,EAAE,KAAK,YAAY,CAAC,CACf;EAEvC,IAAI,OAAO,QAAQ,KAAK,UAAU;EAElC,IAAI,KAAK,WAAW,GAAG;GACrB,IAAI,IAAI,IAAI,mBAAmB;GAC/B;EACF;EAEA,IAAI,IAAI,IAAI,WAAW,IAAI,CAAC;CAC9B;AACF,CAAC;;;;;;;;AAaD,eAAe,mBACb,UACwC;CACxC,IAAI,CAAC,UACH,OAAO,CAAC;CAGV,IAAI,oBAAoB,SACtB,OAAO;CAGT,OAAO;AACT;;;;;;;;;;;;AAaA,eAAe,UACb,YACA,OAC+B;CAC/B,MAAM,UAAU,YAAY;EAAE,SAAS,OAAO,QAAQ,UAAU;EAAG;CAAM,CAAC;CAE1E,OAAO,QAAQ,IACb,QAAQ,IAAI,OAAO,CAAC,MAAM,SAA6B;EAIrD,OAAO;GACL,UAAA,MAHqB,UAAU,MADZ,mBAAmB,IAAI,QAAQ,GACX,IAAI,MAAM,KAAK;GAItD,aAAa,IAAI,eAAe;GAChC;EACF;CACF,CAAC,CACH;AACF;;;;;;;;;;;;AAaA,SAAS,YAAY,QAGS;CAC5B,MAAM,EAAE,SAAS,UAAU;CAE3B,IAAI,CAAC,SAAS,MAAM,WAAW,GAC7B,OAAO,QAAQ,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;CAI1D,MAAM,aAAa,cAAc;EAAE,cADd,QAAQ,KAAK,CAAC,UAAU,IACC;EAAG;CAAM,CAAC;CAExD,MAAM,WAAW,IAAI,IAAI,OAAO;CAChC,MAAM,aAAa,IAAI,IAAI,UAAU;CAErC,MAAM,UAAU,WACb,QAAQ,SAAS,SAAS,IAAI,IAAI,CAAC,CAAC,CACpC,KAAK,SAAkC,CAAC,MAAM,SAAS,IAAI,IAAI,CAAkB,CAAC;CAErF,MAAM,YAAY,QACf,QAAQ,CAAC,UAAU,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CACzC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;CAE5C,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS;AAClC;;;;;;;;;;;AAYA,SAAS,cAAc,QAGD;CACpB,MAAM,EAAE,cAAc,UAAU;CAChC,MAAM,UAAU,IAAI,IAAI,YAAY;CAEpC,MAAM,EAAE,UAAU,MAAM,QAIrB,KAAK,SAAS;EACb,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG;GACtB,QAAQ,KAAK,oCAAoC,KAAK,iBAAiB;GACvE,OAAO;EACT;EAEA,IAAI,CAAC,QAAQ,IAAI,IAAI,GAAG;GACtB,QAAQ,KAAK,6BAA6B,KAAK,iBAAiB;GAChE,OAAO;IAAE,sBAAM,IAAI,IAAI,CAAC,GAAG,IAAI,MAAM,IAAI,CAAC;IAAG,OAAO,IAAI;GAAM;EAChE;EAEA,OAAO;GAAE,sBAAM,IAAI,IAAI,CAAC,GAAG,IAAI,MAAM,IAAI,CAAC;GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,IAAI;EAAE;CAC3E,GACA;EAAE,sBAAM,IAAI,IAAY;EAAG,OAAO,CAAC;CAAE,CACvC;CAEA,OAAO;AACT;;;;;;;;AASA,SAAS,WAAW,SAAuC;CACzD,OAAO,cAAc,SAAS,EAAE,CAAC,CAAC,KAAK,IAAI;AAC7C;;;;;;;;;AAUA,SAAS,cAAc,SAA+B,QAAmC;CACvF,OAAO,QAAQ,SAAS,OAAO,UAAU;EACvC,MAAM,SAAS,UAAU,QAAQ,SAAS;EAC1C,MAAM,YAAY,iBAAiB,MAAM;EACzC,MAAM,cAAc,mBAAmB,MAAM;EAK7C,OAAO,CAAC,GAHQ,SAAS,YADX,YAAY,MAAM,MAAM,MAAM,WACH,KAG3B,GAFK,cAAc,MAAM,UAAU,GAAG,SAAS,aAEnC,CAAC;CAC7B,CAAC;AACH;;;;;;;;AASA,SAAS,iBAAiB,QAAyB;CACjD,IAAI,QACF,OAAO;CAGT,OAAO;AACT;;;;;;;;AASA,SAAS,mBAAmB,QAAyB;CACnD,IAAI,QACF,OAAO;CAGT,OAAO;AACT;;;;;;;;;AAUA,SAAS,YAAY,MAAc,aAA6B;CAC9D,IAAI,aACF,OAAO,GAAG,KAAK,KAAK;CAGtB,OAAO;AACT"}
@@ -1,12 +1,11 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/dev.d.ts
4
3
  /**
5
- * Start a maltty CLI project in development mode with file watching.
6
- *
7
- * Loads the project's `maltty.config.ts`, starts the bundler in watch mode, and
8
- * logs rebuild status on each successful build.
9
- */
4
+ * Start a maltty CLI project in development mode with file watching.
5
+ *
6
+ * Loads the project's `maltty.config.ts`, starts the bundler in watch mode, and
7
+ * logs rebuild status on each successful build.
8
+ */
10
9
  declare const devCommand: Command;
11
10
  //#endregion
12
11
  export { devCommand as default };
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","names":[],"sources":["../../src/commands/dev.ts"],"mappings":";;;;;AAG6C;;;;cAUvC,UAAA,EAAY,OAAA"}
1
+ {"version":3,"file":"dev.d.ts","names":[],"sources":["../../src/commands/dev.ts"],"mappings":";;;;;;;;cAaM,YAAY"}
@@ -1,6 +1,6 @@
1
- import { r as createBundler } from "../dist-DW_gRP7_.js";
2
- import { n as loadConfig } from "../utils-DlIJNGLQ.js";
3
- import { t as extractConfig } from "../config-helpers-pv_2Spux.js";
1
+ import { r as createBundler } from "../dist-FY8K5na4.js";
2
+ import { n as loadConfig } from "../utils-ioeFEbm4.js";
3
+ import { t as extractConfig } from "../config-helpers-DAy-Arox.js";
4
4
  import { command } from "maltty";
5
5
  //#region src/commands/dev.ts
6
6
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","names":[],"sources":["../../src/commands/dev.ts"],"sourcesContent":["import { createBundler } from '@maltty/bundler'\nimport { loadConfig } from '@maltty/config/utils'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\n\nimport { extractConfig } from '../lib/config-helpers.js'\n\n/**\n * Start a maltty CLI project in development mode with file watching.\n *\n * Loads the project's `maltty.config.ts`, starts the bundler in watch mode, and\n * logs rebuild status on each successful build.\n */\nconst devCommand: Command = command({\n description: 'Start a maltty CLI project in development mode',\n handler: async (ctx: CommandContext) => {\n const cwd = process.cwd()\n\n const [, configResult] = await loadConfig({ cwd })\n const config = extractConfig(configResult)\n\n ctx.status.spinner.start('Starting dev server...')\n\n const bundler = await createBundler({ config, cwd })\n const onSuccess = createOnSuccess(ctx)\n\n const [watchError] = await bundler.watch({ onSuccess })\n\n if (watchError) {\n ctx.status.spinner.stop('Watch failed')\n return ctx.fail(watchError.message)\n }\n },\n})\n\nexport default devCommand\n\n// ---------------------------------------------------------------------------\n\n/**\n * Create an onSuccess callback that tracks first-build state.\n *\n * On the first invocation the spinner is stopped and a \"watching\" message is\n * logged. Subsequent invocations log a \"rebuilt\" message instead.\n *\n * Uses a mutable container object inside the closure to track build count\n * without `let` reassignment.\n *\n * @private\n * @param ctx - The command context for logging and spinner access.\n * @returns A callback suitable for the watch `onSuccess` parameter.\n */\nfunction createOnSuccess(ctx: CommandContext): () => void {\n const state = { buildCount: 0 }\n\n return () => {\n if (state.buildCount === 0) {\n state.buildCount = 1\n ctx.status.spinner.stop('Watching for changes...')\n return\n }\n\n ctx.log.success('Rebuilt successfully')\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,aAAsB,QAAQ;CAClC,aAAa;CACb,SAAS,OAAO,QAAwB;EACtC,MAAM,MAAM,QAAQ,KAAK;EAEzB,MAAM,GAAG,gBAAgB,MAAM,WAAW,EAAE,KAAK,CAAC;EAClD,MAAM,SAAS,cAAc,aAAa;AAE1C,MAAI,OAAO,QAAQ,MAAM,yBAAyB;EAElD,MAAM,UAAU,MAAM,cAAc;GAAE;GAAQ;GAAK,CAAC;EACpD,MAAM,YAAY,gBAAgB,IAAI;EAEtC,MAAM,CAAC,cAAc,MAAM,QAAQ,MAAM,EAAE,WAAW,CAAC;AAEvD,MAAI,YAAY;AACd,OAAI,OAAO,QAAQ,KAAK,eAAe;AACvC,UAAO,IAAI,KAAK,WAAW,QAAQ;;;CAGxC,CAAC;;;;;;;;;;;;;;AAmBF,SAAS,gBAAgB,KAAiC;CACxD,MAAM,QAAQ,EAAE,YAAY,GAAG;AAE/B,cAAa;AACX,MAAI,MAAM,eAAe,GAAG;AAC1B,SAAM,aAAa;AACnB,OAAI,OAAO,QAAQ,KAAK,0BAA0B;AAClD;;AAGF,MAAI,IAAI,QAAQ,uBAAuB"}
1
+ {"version":3,"file":"dev.js","names":[],"sources":["../../src/commands/dev.ts"],"sourcesContent":["import { createBundler } from '@maltty/bundler'\nimport { loadConfig } from '@maltty/config/utils'\nimport { command } from 'maltty'\nimport type { Command, CommandContext } from 'maltty'\n\nimport { extractConfig } from '../lib/config-helpers.js'\n\n/**\n * Start a maltty CLI project in development mode with file watching.\n *\n * Loads the project's `maltty.config.ts`, starts the bundler in watch mode, and\n * logs rebuild status on each successful build.\n */\nconst devCommand: Command = command({\n description: 'Start a maltty CLI project in development mode',\n handler: async (ctx: CommandContext) => {\n const cwd = process.cwd()\n\n const [, configResult] = await loadConfig({ cwd })\n const config = extractConfig(configResult)\n\n ctx.status.spinner.start('Starting dev server...')\n\n const bundler = await createBundler({ config, cwd })\n const onSuccess = createOnSuccess(ctx)\n\n const [watchError] = await bundler.watch({ onSuccess })\n\n if (watchError) {\n ctx.status.spinner.stop('Watch failed')\n return ctx.fail(watchError.message)\n }\n },\n})\n\nexport default devCommand\n\n// ---------------------------------------------------------------------------\n\n/**\n * Create an onSuccess callback that tracks first-build state.\n *\n * On the first invocation the spinner is stopped and a \"watching\" message is\n * logged. Subsequent invocations log a \"rebuilt\" message instead.\n *\n * Uses a mutable container object inside the closure to track build count\n * without `let` reassignment.\n *\n * @private\n * @param ctx - The command context for logging and spinner access.\n * @returns A callback suitable for the watch `onSuccess` parameter.\n */\nfunction createOnSuccess(ctx: CommandContext): () => void {\n const state = { buildCount: 0 }\n\n return () => {\n if (state.buildCount === 0) {\n state.buildCount = 1\n ctx.status.spinner.stop('Watching for changes...')\n return\n }\n\n ctx.log.success('Rebuilt successfully')\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,aAAsB,QAAQ;CAClC,aAAa;CACb,SAAS,OAAO,QAAwB;EACtC,MAAM,MAAM,QAAQ,IAAI;EAExB,MAAM,GAAG,gBAAgB,MAAM,WAAW,EAAE,IAAI,CAAC;EACjD,MAAM,SAAS,cAAc,YAAY;EAEzC,IAAI,OAAO,QAAQ,MAAM,wBAAwB;EAEjD,MAAM,UAAU,MAAM,cAAc;GAAE;GAAQ;EAAI,CAAC;EACnD,MAAM,YAAY,gBAAgB,GAAG;EAErC,MAAM,CAAC,cAAc,MAAM,QAAQ,MAAM,EAAE,UAAU,CAAC;EAEtD,IAAI,YAAY;GACd,IAAI,OAAO,QAAQ,KAAK,cAAc;GACtC,OAAO,IAAI,KAAK,WAAW,OAAO;EACpC;CACF;AACF,CAAC;;;;;;;;;;;;;;AAmBD,SAAS,gBAAgB,KAAiC;CACxD,MAAM,QAAQ,EAAE,YAAY,EAAE;CAE9B,aAAa;EACX,IAAI,MAAM,eAAe,GAAG;GAC1B,MAAM,aAAa;GACnB,IAAI,OAAO,QAAQ,KAAK,yBAAyB;GACjD;EACF;EAEA,IAAI,IAAI,QAAQ,sBAAsB;CACxC;AACF"}
@@ -1,12 +1,11 @@
1
1
  import { Command } from "maltty";
2
-
3
2
  //#region src/commands/doctor.d.ts
4
3
  /**
5
- * Diagnose common maltty project issues.
6
- *
7
- * Validates config, checks package.json setup, verifies entry points exist,
8
- * and catches anything that could cause build or runtime failures.
9
- */
4
+ * Diagnose common maltty project issues.
5
+ *
6
+ * Validates config, checks package.json setup, verifies entry points exist,
7
+ * and catches anything that could cause build or runtime failures.
8
+ */
10
9
  declare const doctorCommand: Command;
11
10
  //#endregion
12
11
  export { doctorCommand as default };
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","names":[],"sources":["../../src/commands/doctor.ts"],"mappings":";;;;;AAI6C;;;;cAmBvC,aAAA,EAAe,OAAA"}
1
+ {"version":3,"file":"doctor.d.ts","names":[],"sources":["../../src/commands/doctor.ts"],"mappings":";;;;;;;;cAuBM,eAAe"}