@runa-cmd/help 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +279 -0
- package/dist/ansi/codes.d.ts +33 -0
- package/dist/ansi/codes.d.ts.map +1 -0
- package/dist/ansi/codes.js +54 -0
- package/dist/ansi/codes.js.map +1 -0
- package/dist/ansi/detect.d.ts +36 -0
- package/dist/ansi/detect.d.ts.map +1 -0
- package/dist/ansi/detect.js +82 -0
- package/dist/ansi/detect.js.map +1 -0
- package/dist/ansi/downsample.d.ts +22 -0
- package/dist/ansi/downsample.d.ts.map +1 -0
- package/dist/ansi/downsample.js +126 -0
- package/dist/ansi/downsample.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +18 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +63 -0
- package/dist/plugin.js.map +1 -0
- package/dist/primitives/box.d.ts +23 -0
- package/dist/primitives/box.d.ts.map +1 -0
- package/dist/primitives/box.js +76 -0
- package/dist/primitives/box.js.map +1 -0
- package/dist/primitives/columns.d.ts +15 -0
- package/dist/primitives/columns.d.ts.map +1 -0
- package/dist/primitives/columns.js +37 -0
- package/dist/primitives/columns.js.map +1 -0
- package/dist/primitives/join.d.ts +32 -0
- package/dist/primitives/join.d.ts.map +1 -0
- package/dist/primitives/join.js +89 -0
- package/dist/primitives/join.js.map +1 -0
- package/dist/primitives/list.d.ts +22 -0
- package/dist/primitives/list.d.ts.map +1 -0
- package/dist/primitives/list.js +25 -0
- package/dist/primitives/list.js.map +1 -0
- package/dist/primitives/styled.d.ts +28 -0
- package/dist/primitives/styled.d.ts.map +1 -0
- package/dist/primitives/styled.js +59 -0
- package/dist/primitives/styled.js.map +1 -0
- package/dist/primitives/table.d.ts +19 -0
- package/dist/primitives/table.d.ts.map +1 -0
- package/dist/primitives/table.js +50 -0
- package/dist/primitives/table.js.map +1 -0
- package/dist/primitives/wrap.d.ts +10 -0
- package/dist/primitives/wrap.d.ts.map +1 -0
- package/dist/primitives/wrap.js +69 -0
- package/dist/primitives/wrap.js.map +1 -0
- package/dist/render.d.ts +8 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +219 -0
- package/dist/render.js.map +1 -0
- package/dist/theme.d.ts +12 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +45 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Block } from '../types.js';
|
|
2
|
+
/** Options for table() */
|
|
3
|
+
export interface TableOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Cell padding [vertical, horizontal] (default: [0, 2]).
|
|
6
|
+
* Horizontal padding is applied as right-padding between columns.
|
|
7
|
+
*/
|
|
8
|
+
padding?: [number, number];
|
|
9
|
+
/** Optional header row (rendered with bold if styles available) */
|
|
10
|
+
headers?: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Render rows as a table with auto-sized columns.
|
|
14
|
+
*
|
|
15
|
+
* @param rows - 2D array of cell content
|
|
16
|
+
* @param opts - Table options
|
|
17
|
+
*/
|
|
18
|
+
export declare function table(rows: Block[][], opts?: TableOptions): Block;
|
|
19
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/primitives/table.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,0BAA0B;AAC1B,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,GAAE,YAAiB,GAAG,KAAK,CAwCrE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @runa-cmd/help — table() primitive
|
|
3
|
+
*
|
|
4
|
+
* Renders a 2D array of strings/Blocks as aligned columns.
|
|
5
|
+
* No grid lines by default — uses padding-based layout.
|
|
6
|
+
*/
|
|
7
|
+
import { visibleWidth } from '../ansi/codes.js';
|
|
8
|
+
/**
|
|
9
|
+
* Render rows as a table with auto-sized columns.
|
|
10
|
+
*
|
|
11
|
+
* @param rows - 2D array of cell content
|
|
12
|
+
* @param opts - Table options
|
|
13
|
+
*/
|
|
14
|
+
export function table(rows, opts = {}) {
|
|
15
|
+
const [_vPad, hPad] = opts.padding ?? [0, 2];
|
|
16
|
+
if (rows.length === 0 && !opts.headers)
|
|
17
|
+
return '';
|
|
18
|
+
// Combine headers + rows for column width calculation
|
|
19
|
+
const allRows = opts.headers ? [opts.headers, ...rows] : rows;
|
|
20
|
+
// Find max number of columns
|
|
21
|
+
const numCols = allRows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
22
|
+
// Calculate max visible width per column
|
|
23
|
+
const colWidths = Array.from({ length: numCols }, () => 0);
|
|
24
|
+
for (const row of allRows) {
|
|
25
|
+
for (let col = 0; col < row.length; col++) {
|
|
26
|
+
colWidths[col] = Math.max(colWidths[col], visibleWidth(row[col]));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Render each row
|
|
30
|
+
const separator = ' '.repeat(hPad);
|
|
31
|
+
const resultLines = [];
|
|
32
|
+
for (const row of allRows) {
|
|
33
|
+
const cells = [];
|
|
34
|
+
for (let col = 0; col < numCols; col++) {
|
|
35
|
+
const cell = row[col] ?? '';
|
|
36
|
+
if (col < numCols - 1) {
|
|
37
|
+
// Pad to column width (using visible width to account for ANSI)
|
|
38
|
+
const padNeeded = colWidths[col] - visibleWidth(cell);
|
|
39
|
+
cells.push(cell + ' '.repeat(Math.max(0, padNeeded)));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Last column — no trailing padding
|
|
43
|
+
cells.push(cell);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
resultLines.push(cells.join(separator));
|
|
47
|
+
}
|
|
48
|
+
return resultLines.join('\n');
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/primitives/table.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAchD;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,IAAe,EAAE,OAAqB,EAAE;IAC7D,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAElD,sDAAsD;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9D,6BAA6B;IAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE3E,yCAAyC;IACzC,MAAM,SAAS,GAAa,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;YAC3C,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnE,CAAC;IACF,CAAC;IAED,kBAAkB;IAClB,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;YACxC,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,GAAG,GAAG,OAAO,GAAG,CAAC,EAAE,CAAC;gBACvB,gEAAgE;gBAChE,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;gBACtD,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACP,oCAAoC;gBACpC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACF,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word-wrap text to fit within a given width.
|
|
3
|
+
*
|
|
4
|
+
* - Splits on spaces, re-joins lines under width limit
|
|
5
|
+
* - Respects existing newlines (each \n starts a new line)
|
|
6
|
+
* - Force-breaks words longer than width
|
|
7
|
+
* - Returns an array of lines (no trailing newline)
|
|
8
|
+
*/
|
|
9
|
+
export declare function wrapText(text: string, width: number): string[];
|
|
10
|
+
//# sourceMappingURL=wrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/primitives/wrap.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAyD9D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @runa-cmd/help — wrapText() internal utility
|
|
3
|
+
*
|
|
4
|
+
* Word-wraps text to a given width. Used internally by box and columns.
|
|
5
|
+
* NOT exported at package root.
|
|
6
|
+
*/
|
|
7
|
+
import { visibleWidth } from '../ansi/codes.js';
|
|
8
|
+
/**
|
|
9
|
+
* Word-wrap text to fit within a given width.
|
|
10
|
+
*
|
|
11
|
+
* - Splits on spaces, re-joins lines under width limit
|
|
12
|
+
* - Respects existing newlines (each \n starts a new line)
|
|
13
|
+
* - Force-breaks words longer than width
|
|
14
|
+
* - Returns an array of lines (no trailing newline)
|
|
15
|
+
*/
|
|
16
|
+
export function wrapText(text, width) {
|
|
17
|
+
if (width <= 0)
|
|
18
|
+
return [text];
|
|
19
|
+
const result = [];
|
|
20
|
+
const paragraphs = text.split('\n');
|
|
21
|
+
for (const paragraph of paragraphs) {
|
|
22
|
+
if (paragraph === '') {
|
|
23
|
+
result.push('');
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const words = paragraph.split(/\s+/);
|
|
27
|
+
let currentLine = '';
|
|
28
|
+
for (const word of words) {
|
|
29
|
+
const wordWidth = visibleWidth(word);
|
|
30
|
+
// Force-break words longer than width
|
|
31
|
+
if (wordWidth > width) {
|
|
32
|
+
// Flush current line if not empty
|
|
33
|
+
if (currentLine) {
|
|
34
|
+
result.push(currentLine);
|
|
35
|
+
currentLine = '';
|
|
36
|
+
}
|
|
37
|
+
// Break the long word into chunks
|
|
38
|
+
let remaining = word;
|
|
39
|
+
while (remaining.length > width) {
|
|
40
|
+
result.push(remaining.slice(0, width));
|
|
41
|
+
remaining = remaining.slice(width);
|
|
42
|
+
}
|
|
43
|
+
if (remaining) {
|
|
44
|
+
currentLine = remaining;
|
|
45
|
+
}
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!currentLine) {
|
|
49
|
+
// First word on line
|
|
50
|
+
currentLine = word;
|
|
51
|
+
}
|
|
52
|
+
else if (visibleWidth(currentLine) + 1 + wordWidth <= width) {
|
|
53
|
+
// Fits with a space
|
|
54
|
+
currentLine += ` ${word}`;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Doesn't fit — flush and start new line
|
|
58
|
+
result.push(currentLine);
|
|
59
|
+
currentLine = word;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Flush last line of paragraph
|
|
63
|
+
if (currentLine) {
|
|
64
|
+
result.push(currentLine);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=wrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/primitives/wrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,KAAa;IACnD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChB,SAAS;QACV,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,WAAW,GAAG,EAAE,CAAC;QAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YAErC,sCAAsC;YACtC,IAAI,SAAS,GAAG,KAAK,EAAE,CAAC;gBACvB,kCAAkC;gBAClC,IAAI,WAAW,EAAE,CAAC;oBACjB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBACzB,WAAW,GAAG,EAAE,CAAC;gBAClB,CAAC;gBACD,kCAAkC;gBAClC,IAAI,SAAS,GAAG,IAAI,CAAC;gBACrB,OAAO,SAAS,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;oBACjC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;oBACvC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACpC,CAAC;gBACD,IAAI,SAAS,EAAE,CAAC;oBACf,WAAW,GAAG,SAAS,CAAC;gBACzB,CAAC;gBACD,SAAS;YACV,CAAC;YAED,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClB,qBAAqB;gBACrB,WAAW,GAAG,IAAI,CAAC;YACpB,CAAC;iBAAM,IAAI,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,SAAS,IAAI,KAAK,EAAE,CAAC;gBAC/D,oBAAoB;gBACpB,WAAW,IAAI,IAAI,IAAI,EAAE,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACP,yCAAyC;gBACzC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACzB,WAAW,GAAG,IAAI,CAAC;YACpB,CAAC;QACF,CAAC;QAED,+BAA+B;QAC/B,IAAI,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RenderFnCtx } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default help renderer — produces formatted help output.
|
|
4
|
+
*
|
|
5
|
+
* Accepts a RenderFnCtx (same shape as the custom render function receives).
|
|
6
|
+
*/
|
|
7
|
+
export declare function defaultRenderer(ctx: RenderFnCtx): string;
|
|
8
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAwB,WAAW,EAAiB,MAAM,YAAY,CAAC;AAEnF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAkBxD"}
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { bold as ansiBold, fg } from './ansi/codes.js';
|
|
2
|
+
import { join } from './primitives/join.js';
|
|
3
|
+
import { styled } from './primitives/styled.js';
|
|
4
|
+
import { table } from './primitives/table.js';
|
|
5
|
+
/**
|
|
6
|
+
* Default help renderer — produces formatted help output.
|
|
7
|
+
*
|
|
8
|
+
* Accepts a RenderFnCtx (same shape as the custom render function receives).
|
|
9
|
+
*/
|
|
10
|
+
export function defaultRenderer(ctx) {
|
|
11
|
+
const { schema, theme } = ctx;
|
|
12
|
+
const renderCtx = { colorDepth: ctx.colorDepth, termWidth: ctx.termWidth };
|
|
13
|
+
const sections = [];
|
|
14
|
+
// Determine if this is a CLISchema (root) or CommandSchema (subcommand)
|
|
15
|
+
const isCLI = 'meta' in schema && 'commands' in schema && 'globalOptions' in schema;
|
|
16
|
+
if (isCLI) {
|
|
17
|
+
const cli = schema;
|
|
18
|
+
sections.push(...renderCLI(cli, theme, renderCtx));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const cmd = schema;
|
|
22
|
+
sections.push(...renderCommand(cmd, theme, renderCtx));
|
|
23
|
+
}
|
|
24
|
+
return join.vertical(sections, { gap: 1 });
|
|
25
|
+
}
|
|
26
|
+
// ─── CLI Root Rendering ─────────────────────────────────────
|
|
27
|
+
function renderCLI(cli, theme, ctx) {
|
|
28
|
+
const sections = [];
|
|
29
|
+
// Header
|
|
30
|
+
const name = cli.meta.name;
|
|
31
|
+
const version = cli.meta.version ? ` v${cli.meta.version}` : '';
|
|
32
|
+
sections.push(styled(`${name}${version}`, { bold: true }, ctx));
|
|
33
|
+
if (cli.meta.description) {
|
|
34
|
+
sections.push(styled(cli.meta.description, { dim: true }, ctx));
|
|
35
|
+
}
|
|
36
|
+
// Usage
|
|
37
|
+
const hasCommands = cli.commands.length > 0;
|
|
38
|
+
const usageParts = [name];
|
|
39
|
+
if (hasCommands)
|
|
40
|
+
usageParts.push('<command>');
|
|
41
|
+
usageParts.push('[options]');
|
|
42
|
+
sections.push(join.vertical([
|
|
43
|
+
sectionTitle('USAGE', theme, ctx),
|
|
44
|
+
styled(` ${usageParts.join(' ')}`, {}, ctx),
|
|
45
|
+
]));
|
|
46
|
+
// Commands
|
|
47
|
+
if (hasCommands) {
|
|
48
|
+
const cmdRows = cli.commands.map((cmd) => [
|
|
49
|
+
styled(cmd.name, { color: 'yellow' }, ctx),
|
|
50
|
+
cmd.description || '',
|
|
51
|
+
]);
|
|
52
|
+
sections.push(join.vertical([sectionTitle('COMMANDS', theme, ctx), indent(table(cmdRows))]));
|
|
53
|
+
}
|
|
54
|
+
// Global Options
|
|
55
|
+
if (cli.globalOptions.length > 0) {
|
|
56
|
+
sections.push(join.vertical([
|
|
57
|
+
sectionTitle('GLOBAL OPTIONS', theme, ctx),
|
|
58
|
+
indent(renderOptionsTable(cli.globalOptions, theme, ctx)),
|
|
59
|
+
]));
|
|
60
|
+
}
|
|
61
|
+
return sections;
|
|
62
|
+
}
|
|
63
|
+
// ─── Command Rendering ──────────────────────────────────────
|
|
64
|
+
function renderCommand(cmd, theme, ctx) {
|
|
65
|
+
const sections = [];
|
|
66
|
+
// Header
|
|
67
|
+
const cmdPath = cmd.fullPath.join(' ');
|
|
68
|
+
sections.push(styled(cmdPath, { bold: true }, ctx));
|
|
69
|
+
if (cmd.description) {
|
|
70
|
+
sections.push(styled(cmd.description, { dim: true }, ctx));
|
|
71
|
+
}
|
|
72
|
+
// Usage
|
|
73
|
+
const usageParts = [cmdPath];
|
|
74
|
+
if (cmd.subcommands && cmd.subcommands.length > 0)
|
|
75
|
+
usageParts.push('<command>');
|
|
76
|
+
if (cmd.args.length > 0) {
|
|
77
|
+
for (const arg of cmd.args) {
|
|
78
|
+
usageParts.push(arg.required ? `<${arg.name}>` : `[${arg.name}]`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
usageParts.push('[options]');
|
|
82
|
+
sections.push(join.vertical([
|
|
83
|
+
sectionTitle('USAGE', theme, ctx),
|
|
84
|
+
styled(` ${usageParts.join(' ')}`, {}, ctx),
|
|
85
|
+
]));
|
|
86
|
+
// Arguments
|
|
87
|
+
if (cmd.args.length > 0) {
|
|
88
|
+
const argRows = cmd.args.map((arg) => renderArgRow(arg, theme, ctx));
|
|
89
|
+
sections.push(join.vertical([sectionTitle('ARGUMENTS', theme, ctx), indent(table(argRows))]));
|
|
90
|
+
}
|
|
91
|
+
// Options (grouped)
|
|
92
|
+
if (cmd.options.length > 0) {
|
|
93
|
+
sections.push(renderOptionsSection(cmd.options, theme, ctx));
|
|
94
|
+
}
|
|
95
|
+
// Subcommands
|
|
96
|
+
if (cmd.subcommands && cmd.subcommands.length > 0) {
|
|
97
|
+
const cmdRows = cmd.subcommands.map((sub) => [
|
|
98
|
+
styled(sub.name, { color: 'yellow' }, ctx),
|
|
99
|
+
sub.description || '',
|
|
100
|
+
]);
|
|
101
|
+
sections.push(join.vertical([sectionTitle('COMMANDS', theme, ctx), indent(table(cmdRows))]));
|
|
102
|
+
}
|
|
103
|
+
return sections;
|
|
104
|
+
}
|
|
105
|
+
// ─── Options Rendering ──────────────────────────────────────
|
|
106
|
+
function renderOptionsSection(options, theme, ctx) {
|
|
107
|
+
// Separate options by group
|
|
108
|
+
const grouped = new Map();
|
|
109
|
+
const ungrouped = [];
|
|
110
|
+
for (const opt of options) {
|
|
111
|
+
if (opt.group) {
|
|
112
|
+
const list = grouped.get(opt.group) ?? [];
|
|
113
|
+
list.push(opt);
|
|
114
|
+
grouped.set(opt.group, list);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
ungrouped.push(opt);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const parts = [];
|
|
121
|
+
// Ungrouped options first
|
|
122
|
+
if (ungrouped.length > 0) {
|
|
123
|
+
parts.push(join.vertical([
|
|
124
|
+
sectionTitle('OPTIONS', theme, ctx),
|
|
125
|
+
indent(renderOptionsTable(ungrouped, theme, ctx)),
|
|
126
|
+
]));
|
|
127
|
+
}
|
|
128
|
+
// Each group gets its own section
|
|
129
|
+
for (const [group, opts] of grouped) {
|
|
130
|
+
parts.push(join.vertical([
|
|
131
|
+
sectionTitle(`${group.toUpperCase()} OPTIONS`, theme, ctx),
|
|
132
|
+
indent(renderOptionsTable(opts, theme, ctx)),
|
|
133
|
+
]));
|
|
134
|
+
}
|
|
135
|
+
// If everything was grouped and there's no ungrouped section
|
|
136
|
+
if (parts.length === 0)
|
|
137
|
+
return '';
|
|
138
|
+
return join.vertical(parts, { gap: 1 });
|
|
139
|
+
}
|
|
140
|
+
function renderOptionsTable(options, theme, ctx) {
|
|
141
|
+
const rows = options.map((opt) => renderOptionRow(opt, theme, ctx));
|
|
142
|
+
return table(rows);
|
|
143
|
+
}
|
|
144
|
+
function renderOptionRow(opt, theme, ctx) {
|
|
145
|
+
// Flag column: --name, -alias
|
|
146
|
+
const flags = [];
|
|
147
|
+
if (opt.alias) {
|
|
148
|
+
for (const a of opt.alias) {
|
|
149
|
+
// Aliases may come with dash prefix ('-e', '--env') or bare ('e', 'env')
|
|
150
|
+
if (a.startsWith('--') || a.startsWith('-')) {
|
|
151
|
+
flags.push(a);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
flags.push(a.length === 1 ? `-${a}` : `--${a}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
flags.push(`--${opt.name}`);
|
|
159
|
+
const flagStr = styled(flags.join(', '), { color: 'yellow' }, ctx);
|
|
160
|
+
// Type column
|
|
161
|
+
const typeParts = [];
|
|
162
|
+
if (opt.type === 'enum' && opt.enumValues) {
|
|
163
|
+
typeParts.push(opt.enumValues.join(' | '));
|
|
164
|
+
}
|
|
165
|
+
else if (opt.type !== 'boolean') {
|
|
166
|
+
typeParts.push(opt.type);
|
|
167
|
+
}
|
|
168
|
+
const typeStr = typeParts.length > 0 ? styled(typeParts.join(''), { dim: true }, ctx) : '';
|
|
169
|
+
// Description column
|
|
170
|
+
const descParts = [];
|
|
171
|
+
if (opt.description)
|
|
172
|
+
descParts.push(opt.description);
|
|
173
|
+
if (opt.required)
|
|
174
|
+
descParts.push(fg('(required)', theme.secondary));
|
|
175
|
+
if (opt.defaultValue !== undefined)
|
|
176
|
+
descParts.push(fg(`[default: ${String(opt.defaultValue)}]`, theme.muted));
|
|
177
|
+
if (opt.deprecated)
|
|
178
|
+
descParts.push(fg(`(deprecated: ${opt.deprecated})`, theme.warning));
|
|
179
|
+
if (opt.env)
|
|
180
|
+
descParts.push(fg(`[env: ${opt.env}]`, theme.muted));
|
|
181
|
+
return [flagStr, typeStr, descParts.join(' ')];
|
|
182
|
+
}
|
|
183
|
+
// ─── Argument Rendering ─────────────────────────────────────
|
|
184
|
+
function renderArgRow(arg, theme, ctx) {
|
|
185
|
+
// Name column
|
|
186
|
+
const nameDisplay = arg.isVariadic ? `${arg.name}...` : arg.name;
|
|
187
|
+
const nameStr = styled(arg.required ? `<${nameDisplay}>` : `[${nameDisplay}]`, { color: 'yellow' }, ctx);
|
|
188
|
+
// Type column
|
|
189
|
+
const typeParts = [];
|
|
190
|
+
if (arg.type === 'enum' && arg.enumValues) {
|
|
191
|
+
typeParts.push(arg.enumValues.join(' | '));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
typeParts.push(arg.type);
|
|
195
|
+
}
|
|
196
|
+
const typeStr = styled(typeParts.join(''), { dim: true }, ctx);
|
|
197
|
+
// Description column
|
|
198
|
+
const descParts = [];
|
|
199
|
+
if (arg.description)
|
|
200
|
+
descParts.push(arg.description);
|
|
201
|
+
if (arg.required)
|
|
202
|
+
descParts.push(fg('(required)', theme.secondary));
|
|
203
|
+
if (arg.defaultValue !== undefined)
|
|
204
|
+
descParts.push(fg(`[default: ${String(arg.defaultValue)}]`, theme.muted));
|
|
205
|
+
return [nameStr, typeStr, descParts.join(' ')];
|
|
206
|
+
}
|
|
207
|
+
// ─── Helpers ────────────────────────────────────────────────
|
|
208
|
+
function sectionTitle(title, theme, _ctx) {
|
|
209
|
+
// theme colors are already ANSI-resolved, so use fg() directly (not styled.color which re-downsamples)
|
|
210
|
+
return ansiBold(fg(title, theme.primary));
|
|
211
|
+
}
|
|
212
|
+
function indent(block, spaces = 2) {
|
|
213
|
+
const prefix = ' '.repeat(spaces);
|
|
214
|
+
return block
|
|
215
|
+
.split('\n')
|
|
216
|
+
.map((line) => `${prefix}${line}`)
|
|
217
|
+
.join('\n');
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RenderContext, ResolvedTheme, Theme } from './types.js';
|
|
2
|
+
/** Default theme colors — Lipgloss-inspired */
|
|
3
|
+
export declare const defaultTheme: Theme;
|
|
4
|
+
/**
|
|
5
|
+
* Merge a partial theme with defaults and downsample all colors
|
|
6
|
+
* to ANSI-ready escape strings for the current color depth.
|
|
7
|
+
*
|
|
8
|
+
* @param partial - User's partial theme override (or undefined for defaults)
|
|
9
|
+
* @param ctx - RenderContext with colorDepth for downsampling
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveTheme(partial: Partial<Theme> | undefined, ctx: RenderContext): ResolvedTheme;
|
|
12
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAItE,+CAA+C;AAC/C,eAAO,MAAM,YAAY,EAAE,KAO1B,CAAC;AAcF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC3B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,SAAS,EACnC,GAAG,EAAE,aAAa,GAChB,aAAa,CAWf"}
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @runa-cmd/help — Theme system
|
|
3
|
+
*
|
|
4
|
+
* Provides a default theme, deep-merges partial overrides,
|
|
5
|
+
* and downsamples all colors to the terminal's color depth.
|
|
6
|
+
*/
|
|
7
|
+
import { downsampleColor } from './ansi/downsample.js';
|
|
8
|
+
// ─── Default Theme ──────────────────────────────────────────
|
|
9
|
+
/** Default theme colors — Lipgloss-inspired */
|
|
10
|
+
export const defaultTheme = {
|
|
11
|
+
primary: '#7D56F4',
|
|
12
|
+
secondary: '#FF6B6B',
|
|
13
|
+
muted: 'dim',
|
|
14
|
+
error: '#FF0000',
|
|
15
|
+
warning: '#FFAA00',
|
|
16
|
+
success: '#00FF00',
|
|
17
|
+
};
|
|
18
|
+
// ─── Theme Resolution ───────────────────────────────────────
|
|
19
|
+
/** Color keys in the Theme interface */
|
|
20
|
+
const THEME_KEYS = [
|
|
21
|
+
'primary',
|
|
22
|
+
'secondary',
|
|
23
|
+
'muted',
|
|
24
|
+
'error',
|
|
25
|
+
'warning',
|
|
26
|
+
'success',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Merge a partial theme with defaults and downsample all colors
|
|
30
|
+
* to ANSI-ready escape strings for the current color depth.
|
|
31
|
+
*
|
|
32
|
+
* @param partial - User's partial theme override (or undefined for defaults)
|
|
33
|
+
* @param ctx - RenderContext with colorDepth for downsampling
|
|
34
|
+
*/
|
|
35
|
+
export function resolveTheme(partial, ctx) {
|
|
36
|
+
// Merge with defaults
|
|
37
|
+
const merged = { ...defaultTheme, ...partial };
|
|
38
|
+
// Downsample every color to an ANSI escape string
|
|
39
|
+
const resolved = {};
|
|
40
|
+
for (const key of THEME_KEYS) {
|
|
41
|
+
resolved[key] = downsampleColor(merged[key], ctx.colorDepth);
|
|
42
|
+
}
|
|
43
|
+
return resolved;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,+DAA+D;AAE/D,+CAA+C;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAU;IAClC,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;CAClB,CAAC;AAEF,+DAA+D;AAE/D,wCAAwC;AACxC,MAAM,UAAU,GAA+B;IAC9C,SAAS;IACT,WAAW;IACX,OAAO;IACP,OAAO;IACP,SAAS;IACT,SAAS;CACT,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC3B,OAAmC,EACnC,GAAkB;IAElB,sBAAsB;IACtB,MAAM,MAAM,GAAU,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC;IAEtD,kDAAkD;IAClD,MAAM,QAAQ,GAAG,EAAmB,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC9B,QAAQ,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @runa-cmd/help — Type definitions
|
|
3
|
+
*
|
|
4
|
+
* All TypeScript types for the help system.
|
|
5
|
+
* Schema types (CLISchema, CommandSchema, etc.) are imported from @runa-cmd/core.
|
|
6
|
+
* This is a type-only module — no runtime code.
|
|
7
|
+
*/
|
|
8
|
+
import type { CLISchema, CommandSchema } from '@runa-cmd/core';
|
|
9
|
+
/** Everything returns a Block — just a string with optional ANSI codes */
|
|
10
|
+
export type Block = string;
|
|
11
|
+
/** Detected color depth of the terminal */
|
|
12
|
+
export type ColorDepth = 'truecolor' | '256' | '16' | 'none';
|
|
13
|
+
/** Render context passed to all primitives (auto-detected or overridden in tests) */
|
|
14
|
+
export interface RenderContext {
|
|
15
|
+
colorDepth: ColorDepth;
|
|
16
|
+
termWidth: number;
|
|
17
|
+
}
|
|
18
|
+
/** Theme colors — all values are hex (#RRGGBB) or named ANSI attribute (e.g. 'dim') */
|
|
19
|
+
export interface Theme {
|
|
20
|
+
/** Titles, borders */
|
|
21
|
+
primary: string;
|
|
22
|
+
/** Required markers, highlights */
|
|
23
|
+
secondary: string;
|
|
24
|
+
/** Descriptions, defaults */
|
|
25
|
+
muted: string;
|
|
26
|
+
/** Error messages */
|
|
27
|
+
error: string;
|
|
28
|
+
/** Warnings */
|
|
29
|
+
warning: string;
|
|
30
|
+
/** Success states */
|
|
31
|
+
success: string;
|
|
32
|
+
}
|
|
33
|
+
/** Theme with all colors resolved to ANSI-ready escape strings */
|
|
34
|
+
export interface ResolvedTheme {
|
|
35
|
+
primary: string;
|
|
36
|
+
secondary: string;
|
|
37
|
+
muted: string;
|
|
38
|
+
error: string;
|
|
39
|
+
warning: string;
|
|
40
|
+
success: string;
|
|
41
|
+
}
|
|
42
|
+
/** What the custom render function receives (Layer 3) */
|
|
43
|
+
export interface RenderFnCtx {
|
|
44
|
+
/** The target schema (root CLI or specific subcommand) */
|
|
45
|
+
schema: CLISchema | CommandSchema;
|
|
46
|
+
/** Resolved theme with ANSI-ready colors */
|
|
47
|
+
theme: ResolvedTheme;
|
|
48
|
+
/** Detected color depth */
|
|
49
|
+
colorDepth: ColorDepth;
|
|
50
|
+
/** Terminal width in columns */
|
|
51
|
+
termWidth: number;
|
|
52
|
+
}
|
|
53
|
+
/** Options for helpPlugin() */
|
|
54
|
+
export interface HelpPluginOptions {
|
|
55
|
+
/** Partial theme override (merged with defaultTheme) */
|
|
56
|
+
theme?: Partial<Theme>;
|
|
57
|
+
/** Custom render function (Layer 3 — full control) */
|
|
58
|
+
render?: (ctx: RenderFnCtx) => string;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI/D,0EAA0E;AAC1E,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC;AAI3B,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;AAE7D,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CAClB;AAID,uFAAuF;AACvF,MAAM,WAAW,KAAK;IACrB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAID,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC3B,0DAA0D;IAC1D,MAAM,EAAE,SAAS,GAAG,aAAa,CAAC;IAClC,4CAA4C;IAC5C,KAAK,EAAE,aAAa,CAAC;IACrB,2BAA2B;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;CAClB;AAID,+BAA+B;AAC/B,MAAM,WAAW,iBAAiB;IACjC,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,sDAAsD;IACtD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;CACtC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runa-cmd/help",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Themeable help output for Runa CLIs with composable layout primitives.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"cli",
|
|
9
|
+
"help",
|
|
10
|
+
"ansi",
|
|
11
|
+
"terminal",
|
|
12
|
+
"layout",
|
|
13
|
+
"theme",
|
|
14
|
+
"runa"
|
|
15
|
+
],
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"zod": "^4.0.0",
|
|
26
|
+
"@runa-cmd/core": "0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.3.0"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/jrodrigopuca/runa-cmd.git",
|
|
37
|
+
"directory": "packages/help"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/jrodrigopuca/runa-cmd/tree/main/packages/help#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/jrodrigopuca/runa-cmd/issues"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md"
|
|
46
|
+
],
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^25.6.0",
|
|
49
|
+
"typescript": "^6.0.2",
|
|
50
|
+
"zod": "^4.3.6",
|
|
51
|
+
"@runa-cmd/core": "0.1.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc",
|
|
55
|
+
"dev": "tsc --watch --preserveWatchOutput",
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:watch": "vitest",
|
|
59
|
+
"lint": "biome check .",
|
|
60
|
+
"lint:fix": "biome check --write .",
|
|
61
|
+
"clean": "rm -rf dist"
|
|
62
|
+
}
|
|
63
|
+
}
|