yargs-file-commands 0.0.19 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -13
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/Command.js +1 -0
- package/dist/lib/Command.js.map +1 -0
- package/dist/lib/buildSegmentTree.d.ts +1 -1
- package/dist/lib/buildSegmentTree.js +7 -3
- package/dist/lib/buildSegmentTree.js.map +1 -0
- package/dist/lib/buildSegmentTree.test.js +279 -26
- package/dist/lib/buildSegmentTree.test.js.map +1 -0
- package/dist/lib/fileCommands.d.ts +2 -1
- package/dist/lib/fileCommands.js +39 -21
- package/dist/lib/fileCommands.js.map +1 -0
- package/dist/lib/fileCommands.test.js +107 -30
- package/dist/lib/fileCommands.test.js.map +1 -0
- package/dist/lib/fixtures/commands/$default.js +1 -0
- package/dist/lib/fixtures/commands/$default.js.map +1 -0
- package/dist/lib/fixtures/commands/create.js +1 -0
- package/dist/lib/fixtures/commands/create.js.map +1 -0
- package/dist/lib/fixtures/commands/db/health.d.ts +2 -1
- package/dist/lib/fixtures/commands/db/health.js +2 -3
- package/dist/lib/fixtures/commands/db/health.js.map +1 -0
- package/dist/lib/fixtures/commands/db/migration/command.d.ts +9 -2
- package/dist/lib/fixtures/commands/db/migration/command.js +6 -7
- package/dist/lib/fixtures/commands/db/migration/command.js.map +1 -0
- package/dist/lib/importCommand.d.ts +8 -4
- package/dist/lib/importCommand.js +66 -21
- package/dist/lib/importCommand.js.map +1 -0
- package/dist/lib/importCommand.test.js +157 -34
- package/dist/lib/importCommand.test.js.map +1 -0
- package/dist/lib/scanDirectory.js +54 -25
- package/dist/lib/scanDirectory.js.map +1 -0
- package/dist/lib/scanDirectory.test.js +148 -25
- package/dist/lib/scanDirectory.test.js.map +1 -0
- package/dist/lib/segmentPath.js +8 -6
- package/dist/lib/segmentPath.js.map +1 -0
- package/dist/lib/segmentPath.test.js +10 -38
- package/dist/lib/segmentPath.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +6 -9
- package/CHANGELOG.md +0 -56
- package/src/index.ts +0 -1
- package/src/lib/Command.ts +0 -16
- package/src/lib/buildSegmentTree.test.ts +0 -90
- package/src/lib/buildSegmentTree.ts +0 -149
- package/src/lib/fileCommands.test.ts +0 -55
- package/src/lib/fileCommands.ts +0 -149
- package/src/lib/fixtures/commands/$default.ts +0 -5
- package/src/lib/fixtures/commands/create.ts +0 -6
- package/src/lib/fixtures/commands/db/health.ts +0 -9
- package/src/lib/fixtures/commands/db/migration/command.ts +0 -12
- package/src/lib/importCommand.test.ts +0 -65
- package/src/lib/importCommand.ts +0 -148
- package/src/lib/scanDirectory.test.ts +0 -75
- package/src/lib/scanDirectory.ts +0 -109
- package/src/lib/segmentPath.test.ts +0 -71
- package/src/lib/segmentPath.ts +0 -38
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[![NPM Package][npm]][npm-url]
|
|
4
4
|
[![NPM Downloads][npm-downloads]][npmtrends-url]
|
|
5
|
+
[![Tests][tests-badge]][tests-url]
|
|
6
|
+
[![Coverage][coverage-badge]][coverage-url]
|
|
5
7
|
|
|
6
8
|
This Yargs helper function lets you define all your commands as individual files and their file names and directory structure defines via implication your nested command structure.
|
|
7
9
|
|
|
@@ -111,6 +113,52 @@ db health
|
|
|
111
113
|
studio start
|
|
112
114
|
```
|
|
113
115
|
|
|
116
|
+
### Alternative Type-Safe Command Definition
|
|
117
|
+
|
|
118
|
+
YOu can also use this type-safe way to define commands using the `CommandModule` type from yargs directly. This is the preferred method as it provides better TypeScript support and catches potential errors at compile time rather than runtime:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import type { ArgumentsCamelCase, CommandModule } from 'yargs';
|
|
122
|
+
|
|
123
|
+
type TriageArgs = {
|
|
124
|
+
owner: string;
|
|
125
|
+
repo: string;
|
|
126
|
+
issue: number;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export const command: CommandModule<object, TriageArgs> = {
|
|
130
|
+
command: 'triage <owner> <repo> <issue>',
|
|
131
|
+
describe: 'Triage a GitHub issue',
|
|
132
|
+
builder: {
|
|
133
|
+
owner: {
|
|
134
|
+
type: 'string',
|
|
135
|
+
description: 'GitHub repository owner',
|
|
136
|
+
demandOption: true
|
|
137
|
+
},
|
|
138
|
+
repo: {
|
|
139
|
+
type: 'string',
|
|
140
|
+
description: 'GitHub repository name',
|
|
141
|
+
demandOption: true
|
|
142
|
+
},
|
|
143
|
+
issue: {
|
|
144
|
+
type: 'number',
|
|
145
|
+
description: 'Issue number',
|
|
146
|
+
demandOption: true
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
handler: async (argv: ArgumentsCamelCase<TriageArgs>) => {
|
|
150
|
+
// Implementation
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
This approach has several advantages:
|
|
156
|
+
|
|
157
|
+
- Full TypeScript support with proper type inference
|
|
158
|
+
- Compile-time checking of command structure
|
|
159
|
+
- No risk of misspelling exports
|
|
160
|
+
- Better IDE support with autocompletion
|
|
161
|
+
|
|
114
162
|
## Options
|
|
115
163
|
|
|
116
164
|
The "fileCommands" method takes the following options:
|
|
@@ -141,25 +189,19 @@ If you want to contribute, just check out [this git project](https://github.com/
|
|
|
141
189
|
|
|
142
190
|
```sh
|
|
143
191
|
# install dependencies
|
|
144
|
-
|
|
192
|
+
pnpm install
|
|
145
193
|
|
|
146
194
|
# build everything
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
# prettify
|
|
150
|
-
npm run format
|
|
195
|
+
pnpm run build
|
|
151
196
|
|
|
152
|
-
#
|
|
153
|
-
|
|
197
|
+
# biome
|
|
198
|
+
pnpm run chec
|
|
154
199
|
|
|
155
|
-
#
|
|
156
|
-
|
|
200
|
+
# tests
|
|
201
|
+
pnpm vitest
|
|
157
202
|
|
|
158
203
|
# clean everything, should be like doing a fresh git checkout of the repo.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
# publish the npm package
|
|
162
|
-
npm run publish
|
|
204
|
+
pnpm clean
|
|
163
205
|
|
|
164
206
|
# run example cli
|
|
165
207
|
npx example-cli
|
|
@@ -171,3 +213,7 @@ Underneath the hood, we are using [NX](https://nx.dev) to manage the monorepo an
|
|
|
171
213
|
[npm-url]: https://www.npmjs.com/package/yargs-file-commands
|
|
172
214
|
[npm-downloads]: https://img.shields.io/npm/dw/yargs-file-commands
|
|
173
215
|
[npmtrends-url]: https://www.npmtrends.com/yargs-file-commands
|
|
216
|
+
[tests-badge]: https://github.com/bhouston/yargs-file-commands/workflows/Tests/badge.svg
|
|
217
|
+
[tests-url]: https://github.com/bhouston/yargs-file-commands/actions/workflows/test.yml
|
|
218
|
+
[coverage-badge]: https://codecov.io/gh/bhouston/yargs-file-commands/branch/main/graph/badge.svg
|
|
219
|
+
[coverage-url]: https://codecov.io/gh/bhouston/yargs-file-commands
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|
package/dist/lib/Command.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Command.js","sourceRoot":"","sources":["../../src/lib/Command.ts"],"names":[],"mappings":""}
|
|
@@ -38,6 +38,6 @@ export declare const buildSegmentTree: (commands: Command[]) => CommandTreeNode[
|
|
|
38
38
|
* For leaf nodes, returns the actual command implementation.
|
|
39
39
|
* For internal nodes, creates a parent command that manages subcommands.
|
|
40
40
|
*/
|
|
41
|
-
export declare const createCommand: (treeNode: CommandTreeNode) => CommandModule
|
|
41
|
+
export declare const createCommand: (treeNode: CommandTreeNode) => CommandModule<{}, {}>;
|
|
42
42
|
export declare const logCommandTree: (commands: CommandTreeNode[], level?: number) => void;
|
|
43
43
|
export {};
|
|
@@ -27,6 +27,9 @@ function insertIntoTree(treeNodes, command, depth) {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
const currentSegmentName = command.segments[depth];
|
|
30
|
+
if (currentSegmentName === undefined) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
30
33
|
let currentSegment = treeNodes.find((s) => s.segmentName === currentSegmentName);
|
|
31
34
|
// If this is the last segment, create a leaf node
|
|
32
35
|
if (depth === command.segments.length - 1) {
|
|
@@ -34,7 +37,7 @@ function insertIntoTree(treeNodes, command, depth) {
|
|
|
34
37
|
treeNodes.push({
|
|
35
38
|
type: 'leaf',
|
|
36
39
|
segmentName: currentSegmentName,
|
|
37
|
-
command
|
|
40
|
+
command,
|
|
38
41
|
});
|
|
39
42
|
}
|
|
40
43
|
else if (currentSegment.type === 'internal') {
|
|
@@ -47,7 +50,7 @@ function insertIntoTree(treeNodes, command, depth) {
|
|
|
47
50
|
currentSegment = {
|
|
48
51
|
type: 'internal',
|
|
49
52
|
segmentName: currentSegmentName,
|
|
50
|
-
children: []
|
|
53
|
+
children: [],
|
|
51
54
|
};
|
|
52
55
|
treeNodes.push(currentSegment);
|
|
53
56
|
}
|
|
@@ -85,7 +88,7 @@ export const createCommand = (treeNode) => {
|
|
|
85
88
|
},
|
|
86
89
|
handler: async () => {
|
|
87
90
|
// Internal nodes don't need handlers as they'll demand subcommands
|
|
88
|
-
}
|
|
91
|
+
},
|
|
89
92
|
};
|
|
90
93
|
return command;
|
|
91
94
|
};
|
|
@@ -97,3 +100,4 @@ export const logCommandTree = (commands, level = 0) => {
|
|
|
97
100
|
}
|
|
98
101
|
});
|
|
99
102
|
};
|
|
103
|
+
//# sourceMappingURL=buildSegmentTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildSegmentTree.js","sourceRoot":"","sources":["../../src/lib/buildSegmentTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
describe('buildSegmentTree', async () => {
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { buildSegmentTree, createCommand, logCommandTree } from './buildSegmentTree.js';
|
|
3
|
+
describe('buildSegmentTree', () => {
|
|
5
4
|
it('should build correct tree structure', () => {
|
|
6
5
|
const commands = [
|
|
7
6
|
{
|
|
@@ -12,8 +11,8 @@ describe('buildSegmentTree', async () => {
|
|
|
12
11
|
describe: 'Migration command',
|
|
13
12
|
handler: async () => {
|
|
14
13
|
// Test handler
|
|
15
|
-
}
|
|
16
|
-
}
|
|
14
|
+
},
|
|
15
|
+
},
|
|
17
16
|
},
|
|
18
17
|
{
|
|
19
18
|
fullPath: '/commands/db/health.js',
|
|
@@ -23,28 +22,29 @@ describe('buildSegmentTree', async () => {
|
|
|
23
22
|
describe: 'Health command',
|
|
24
23
|
handler: async () => {
|
|
25
24
|
// Test handler
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
29
28
|
];
|
|
30
29
|
const tree = buildSegmentTree(commands);
|
|
31
|
-
|
|
30
|
+
expect(tree.length).toBe(1);
|
|
32
31
|
const rootNode = tree[0];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
expect(rootNode).toBeDefined();
|
|
33
|
+
if (!rootNode) {
|
|
34
|
+
throw new Error('Root node should exist');
|
|
35
|
+
}
|
|
36
|
+
expect(rootNode.segmentName).toBe('db');
|
|
37
|
+
expect(rootNode.type).toBe('internal');
|
|
36
38
|
if (rootNode.type !== 'internal') {
|
|
37
39
|
throw new Error('Expected internal node');
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
const childSegments = rootNode.children
|
|
41
|
-
|
|
42
|
-
.sort();
|
|
43
|
-
assert.deepEqual(childSegments, ['health', 'migration'], 'Should have "health" and "migration" sub-commands');
|
|
41
|
+
expect(rootNode.children.length).toBe(2);
|
|
42
|
+
const childSegments = rootNode.children.map((child) => child.segmentName).sort();
|
|
43
|
+
expect(childSegments).toEqual(['health', 'migration']);
|
|
44
44
|
});
|
|
45
45
|
it('should handle empty input', () => {
|
|
46
46
|
const tree = buildSegmentTree([]);
|
|
47
|
-
|
|
47
|
+
expect(tree.length).toBe(0);
|
|
48
48
|
});
|
|
49
49
|
it('should handle single command', () => {
|
|
50
50
|
const commands = [
|
|
@@ -56,15 +56,268 @@ describe('buildSegmentTree', async () => {
|
|
|
56
56
|
describe: 'Test command',
|
|
57
57
|
handler: async () => {
|
|
58
58
|
// Test handler
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
62
|
];
|
|
63
63
|
const tree = buildSegmentTree(commands);
|
|
64
|
-
|
|
64
|
+
expect(tree.length).toBe(1);
|
|
65
65
|
const node = tree[0];
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
expect(node).toBeDefined();
|
|
67
|
+
if (!node) {
|
|
68
|
+
throw new Error('Node should exist');
|
|
69
|
+
}
|
|
70
|
+
expect(node.segmentName).toBe('test');
|
|
71
|
+
expect(node.type).toBe('leaf');
|
|
72
|
+
});
|
|
73
|
+
it('should throw error when directory conflicts with command name (directory first)', () => {
|
|
74
|
+
const commands = [
|
|
75
|
+
{
|
|
76
|
+
fullPath: '/commands/db/migration/command.js',
|
|
77
|
+
segments: ['db', 'migration'],
|
|
78
|
+
commandModule: {
|
|
79
|
+
command: 'migration',
|
|
80
|
+
describe: 'Migration command',
|
|
81
|
+
handler: async () => { },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
fullPath: '/commands/db.js',
|
|
86
|
+
segments: ['db'],
|
|
87
|
+
commandModule: {
|
|
88
|
+
command: 'db',
|
|
89
|
+
describe: 'DB command',
|
|
90
|
+
handler: async () => { },
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
expect(() => buildSegmentTree(commands)).toThrow(/Conflict: db is both a directory and a command/);
|
|
95
|
+
});
|
|
96
|
+
it('should throw error when directory conflicts with command name (command first)', () => {
|
|
97
|
+
const commands = [
|
|
98
|
+
{
|
|
99
|
+
fullPath: '/commands/db.js',
|
|
100
|
+
segments: ['db'],
|
|
101
|
+
commandModule: {
|
|
102
|
+
command: 'db',
|
|
103
|
+
describe: 'DB command',
|
|
104
|
+
handler: async () => { },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
fullPath: '/commands/db/migration/command.js',
|
|
109
|
+
segments: ['db', 'migration'],
|
|
110
|
+
commandModule: {
|
|
111
|
+
command: 'migration',
|
|
112
|
+
describe: 'Migration command',
|
|
113
|
+
handler: async () => { },
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
expect(() => buildSegmentTree(commands)).toThrow(/Conflict: db is both a directory and a command/);
|
|
118
|
+
});
|
|
119
|
+
it('should handle multiple root commands', () => {
|
|
120
|
+
const commands = [
|
|
121
|
+
{
|
|
122
|
+
fullPath: '/commands/hello.ts',
|
|
123
|
+
segments: ['hello'],
|
|
124
|
+
commandModule: {
|
|
125
|
+
command: 'hello',
|
|
126
|
+
describe: 'Hello command',
|
|
127
|
+
handler: async () => { },
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
fullPath: '/commands/world.ts',
|
|
132
|
+
segments: ['world'],
|
|
133
|
+
commandModule: {
|
|
134
|
+
command: 'world',
|
|
135
|
+
describe: 'World command',
|
|
136
|
+
handler: async () => { },
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
const tree = buildSegmentTree(commands);
|
|
141
|
+
expect(tree.length).toBe(2);
|
|
142
|
+
expect(tree.map((n) => n.segmentName).sort()).toEqual(['hello', 'world']);
|
|
143
|
+
});
|
|
144
|
+
it('should handle nested commands at different depths', () => {
|
|
145
|
+
const commands = [
|
|
146
|
+
{
|
|
147
|
+
fullPath: '/commands/a/b/c.ts',
|
|
148
|
+
segments: ['a', 'b', 'c'],
|
|
149
|
+
commandModule: {
|
|
150
|
+
command: 'c',
|
|
151
|
+
describe: 'C command',
|
|
152
|
+
handler: async () => { },
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
fullPath: '/commands/a/d.ts',
|
|
157
|
+
segments: ['a', 'd'],
|
|
158
|
+
commandModule: {
|
|
159
|
+
command: 'd',
|
|
160
|
+
describe: 'D command',
|
|
161
|
+
handler: async () => { },
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
const tree = buildSegmentTree(commands);
|
|
166
|
+
expect(tree.length).toBe(1);
|
|
167
|
+
expect(tree[0]?.segmentName).toBe('a');
|
|
168
|
+
if (tree[0]?.type === 'internal') {
|
|
169
|
+
expect(tree[0].children.length).toBe(2);
|
|
170
|
+
const childNames = tree[0].children.map((c) => c.segmentName).sort();
|
|
171
|
+
expect(childNames).toEqual(['b', 'd']);
|
|
172
|
+
const bNode = tree[0].children.find((c) => c.segmentName === 'b');
|
|
173
|
+
if (bNode?.type === 'internal') {
|
|
174
|
+
expect(bNode.children.length).toBe(1);
|
|
175
|
+
expect(bNode.children[0]?.segmentName).toBe('c');
|
|
176
|
+
expect(bNode.children[0]?.type).toBe('leaf');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe('createCommand', () => {
|
|
182
|
+
it('should create command module from leaf node', () => {
|
|
183
|
+
const command = {
|
|
184
|
+
fullPath: '/commands/test.ts',
|
|
185
|
+
segments: ['test'],
|
|
186
|
+
commandModule: {
|
|
187
|
+
command: 'test',
|
|
188
|
+
describe: 'Test command',
|
|
189
|
+
handler: async () => {
|
|
190
|
+
// Test handler
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
const treeNode = {
|
|
195
|
+
type: 'leaf',
|
|
196
|
+
segmentName: 'test',
|
|
197
|
+
command,
|
|
198
|
+
};
|
|
199
|
+
const commandModule = createCommand(treeNode);
|
|
200
|
+
expect(commandModule.command).toBe('test');
|
|
201
|
+
expect(commandModule.describe).toBe('Test command');
|
|
202
|
+
expect(commandModule.handler).toBe(command.commandModule.handler);
|
|
203
|
+
});
|
|
204
|
+
it('should create command module from internal node with children', () => {
|
|
205
|
+
const childCommand = {
|
|
206
|
+
fullPath: '/commands/db/health.ts',
|
|
207
|
+
segments: ['db', 'health'],
|
|
208
|
+
commandModule: {
|
|
209
|
+
command: 'health',
|
|
210
|
+
describe: 'Health check',
|
|
211
|
+
handler: async () => { },
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
const childTreeNode = {
|
|
215
|
+
type: 'leaf',
|
|
216
|
+
segmentName: 'health',
|
|
217
|
+
command: childCommand,
|
|
218
|
+
};
|
|
219
|
+
const internalTreeNode = {
|
|
220
|
+
type: 'internal',
|
|
221
|
+
segmentName: 'db',
|
|
222
|
+
children: [childTreeNode],
|
|
223
|
+
};
|
|
224
|
+
const commandModule = createCommand(internalTreeNode);
|
|
225
|
+
expect(commandModule.command).toBe('db');
|
|
226
|
+
expect(commandModule.describe).toBe('db commands');
|
|
227
|
+
expect(commandModule.builder).toBeDefined();
|
|
228
|
+
expect(commandModule.handler).toBeDefined();
|
|
229
|
+
});
|
|
230
|
+
it('should create nested command structure with builder', () => {
|
|
231
|
+
const healthCommand = {
|
|
232
|
+
fullPath: '/commands/db/health.ts',
|
|
233
|
+
segments: ['db', 'health'],
|
|
234
|
+
commandModule: {
|
|
235
|
+
command: 'health',
|
|
236
|
+
describe: 'Health check',
|
|
237
|
+
handler: async () => { },
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
const migrationCommand = {
|
|
241
|
+
fullPath: '/commands/db/migration.ts',
|
|
242
|
+
segments: ['db', 'migration'],
|
|
243
|
+
commandModule: {
|
|
244
|
+
command: 'migration',
|
|
245
|
+
describe: 'Migration',
|
|
246
|
+
handler: async () => { },
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
const tree = buildSegmentTree([healthCommand, migrationCommand]);
|
|
250
|
+
const dbNode = tree[0];
|
|
251
|
+
if (!dbNode || dbNode.type !== 'internal') {
|
|
252
|
+
throw new Error('Expected internal node');
|
|
253
|
+
}
|
|
254
|
+
const commandModule = createCommand(dbNode);
|
|
255
|
+
expect(commandModule.command).toBe('db');
|
|
256
|
+
expect(commandModule.builder).toBeDefined();
|
|
257
|
+
// Test the builder function
|
|
258
|
+
if (commandModule.builder && typeof commandModule.builder === 'function') {
|
|
259
|
+
const mockYargs = {
|
|
260
|
+
command: vi.fn().mockReturnThis(),
|
|
261
|
+
demandCommand: vi.fn().mockReturnThis(),
|
|
262
|
+
};
|
|
263
|
+
commandModule.builder(mockYargs);
|
|
264
|
+
expect(mockYargs.command).toHaveBeenCalledTimes(1);
|
|
265
|
+
expect(mockYargs.demandCommand).toHaveBeenCalledWith(1, 'You must specify a db subcommand');
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
describe('logCommandTree', () => {
|
|
270
|
+
it('should log command tree structure', () => {
|
|
271
|
+
const consoleSpy = vi.spyOn(console, 'debug').mockImplementation(() => { });
|
|
272
|
+
const commands = [
|
|
273
|
+
{
|
|
274
|
+
fullPath: '/commands/db/health.ts',
|
|
275
|
+
segments: ['db', 'health'],
|
|
276
|
+
commandModule: {
|
|
277
|
+
command: 'health',
|
|
278
|
+
describe: 'Health',
|
|
279
|
+
handler: async () => { },
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
fullPath: '/commands/hello.ts',
|
|
284
|
+
segments: ['hello'],
|
|
285
|
+
commandModule: {
|
|
286
|
+
command: 'hello',
|
|
287
|
+
describe: 'Hello',
|
|
288
|
+
handler: async () => { },
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
];
|
|
292
|
+
const tree = buildSegmentTree(commands);
|
|
293
|
+
logCommandTree(tree);
|
|
294
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
295
|
+
const calls = consoleSpy.mock.calls.map((call) => call[0]);
|
|
296
|
+
expect(calls.some((call) => call.includes('db'))).toBe(true);
|
|
297
|
+
expect(calls.some((call) => call.includes('health'))).toBe(true);
|
|
298
|
+
expect(calls.some((call) => call.includes('hello'))).toBe(true);
|
|
299
|
+
consoleSpy.mockRestore();
|
|
300
|
+
});
|
|
301
|
+
it('should log command tree with correct indentation levels', () => {
|
|
302
|
+
const consoleSpy = vi.spyOn(console, 'debug').mockImplementation(() => { });
|
|
303
|
+
const commands = [
|
|
304
|
+
{
|
|
305
|
+
fullPath: '/commands/a/b/c.ts',
|
|
306
|
+
segments: ['a', 'b', 'c'],
|
|
307
|
+
commandModule: {
|
|
308
|
+
command: 'c',
|
|
309
|
+
describe: 'C',
|
|
310
|
+
handler: async () => { },
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
];
|
|
314
|
+
const tree = buildSegmentTree(commands);
|
|
315
|
+
logCommandTree(tree, 2);
|
|
316
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
317
|
+
const calls = consoleSpy.mock.calls.map((call) => call[0]);
|
|
318
|
+
// Check for indentation (initial level 2 = 4 spaces, then children add more)
|
|
319
|
+
expect(calls.length).toBeGreaterThan(0);
|
|
320
|
+
consoleSpy.mockRestore();
|
|
69
321
|
});
|
|
70
322
|
});
|
|
323
|
+
//# sourceMappingURL=buildSegmentTree.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildSegmentTree.test.js","sourceRoot":"","sources":["../../src/lib/buildSegmentTree.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CommandModule } from 'yargs';
|
|
1
2
|
import { type ScanDirectoryOptions } from './scanDirectory.js';
|
|
2
3
|
/**
|
|
3
4
|
* Configuration options for file-based command generation
|
|
@@ -30,4 +31,4 @@ export declare const DefaultFileCommandsOptions: Required<FileCommandsOptions>;
|
|
|
30
31
|
* 3. Build a tree structure based on file paths
|
|
31
32
|
* 4. Convert the tree into a command hierarchy
|
|
32
33
|
*/
|
|
33
|
-
export declare const fileCommands: (options: FileCommandsOptions) => Promise<
|
|
34
|
+
export declare const fileCommands: (options: FileCommandsOptions) => Promise<CommandModule<{}, {}>[]>;
|
package/dist/lib/fileCommands.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import path from 'path';
|
|
1
|
+
import path from 'node:path';
|
|
2
2
|
import { buildSegmentTree, createCommand, logCommandTree } from './buildSegmentTree.js';
|
|
3
3
|
import { importCommandFromFile } from './importCommand.js';
|
|
4
4
|
import { scanDirectory } from './scanDirectory.js';
|
|
@@ -13,17 +13,19 @@ export const DefaultFileCommandsOptions = {
|
|
|
13
13
|
commandDirs: [],
|
|
14
14
|
/** Default file extensions to process */
|
|
15
15
|
extensions: ['.js', '.ts'],
|
|
16
|
-
/** Default patterns to ignore when scanning directories
|
|
16
|
+
/** Default patterns to ignore when scanning directories.
|
|
17
|
+
* Note: System files (files starting with '.') are ALWAYS ignored regardless of these patterns.
|
|
18
|
+
* These defaults can be overridden by providing your own ignorePatterns.
|
|
19
|
+
*/
|
|
17
20
|
ignorePatterns: [
|
|
18
|
-
/^[.|_].*/, // Hidden files and underscore files
|
|
19
21
|
/\.(?:test|spec)\.[jt]s$/, // Test files
|
|
20
22
|
/__(?:test|spec)__/, // Test directories
|
|
21
|
-
/\.d\.ts
|
|
23
|
+
/\.d\.ts$/, // TypeScript declaration files
|
|
22
24
|
],
|
|
23
25
|
/** Default logging level */
|
|
24
26
|
logLevel: 'info',
|
|
25
27
|
/** Default log prefix */
|
|
26
|
-
logPrefix: ' '
|
|
28
|
+
logPrefix: ' ',
|
|
27
29
|
};
|
|
28
30
|
/**
|
|
29
31
|
* Generates a command tree structure from files in specified directories
|
|
@@ -45,7 +47,7 @@ export const DefaultFileCommandsOptions = {
|
|
|
45
47
|
export const fileCommands = async (options) => {
|
|
46
48
|
const fullOptions = {
|
|
47
49
|
...DefaultFileCommandsOptions,
|
|
48
|
-
...options
|
|
50
|
+
...options,
|
|
49
51
|
};
|
|
50
52
|
// validate extensions have dots in them
|
|
51
53
|
if (fullOptions.extensions.some((ext) => !ext.startsWith('.'))) {
|
|
@@ -61,29 +63,44 @@ export const fileCommands = async (options) => {
|
|
|
61
63
|
throw new Error(`Command directories must be absolute paths: ${nonAbsoluteDirs.join(', ')}`);
|
|
62
64
|
}
|
|
63
65
|
const commands = [];
|
|
64
|
-
|
|
66
|
+
// Process all command directories in parallel
|
|
67
|
+
const directoryResults = await Promise.all(fullOptions.commandDirs.map(async (commandDir) => {
|
|
65
68
|
const fullPath = path.resolve(commandDir);
|
|
66
69
|
if (fullOptions.logLevel === 'debug') {
|
|
67
70
|
console.debug(`Scanning directory for commands: ${fullPath}`);
|
|
68
71
|
}
|
|
69
72
|
const filePaths = await scanDirectory(commandDir, commandDir, fullOptions);
|
|
73
|
+
return { commandDir, filePaths };
|
|
74
|
+
}));
|
|
75
|
+
if (fullOptions.logLevel === 'debug') {
|
|
76
|
+
console.debug(`Importing found commands:`);
|
|
77
|
+
}
|
|
78
|
+
// Process all files in parallel
|
|
79
|
+
const fileResults = await Promise.all(directoryResults.flatMap(({ commandDir, filePaths }) => filePaths.map(async (filePath) => {
|
|
80
|
+
const localPath = path.relative(commandDir, filePath);
|
|
81
|
+
const segments = segmentPath(filePath, commandDir);
|
|
82
|
+
// Remove extension (last segment) if there are multiple segments
|
|
83
|
+
// If there's only one segment, it means the file has no name (e.g., .js)
|
|
84
|
+
if (segments.length > 1) {
|
|
85
|
+
segments.pop(); // remove extension.
|
|
86
|
+
}
|
|
87
|
+
else if (segments.length === 0) {
|
|
88
|
+
throw new Error(`No segments found for file: ${filePath}`);
|
|
89
|
+
}
|
|
70
90
|
if (fullOptions.logLevel === 'debug') {
|
|
71
|
-
console.debug(`
|
|
91
|
+
console.debug(` ${localPath} - importing command module`);
|
|
72
92
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
segments.pop(); // remove extension.
|
|
77
|
-
if (fullOptions.logLevel === 'debug') {
|
|
78
|
-
console.debug(` ${localPath} - importing command module`);
|
|
79
|
-
}
|
|
80
|
-
commands.push({
|
|
81
|
-
fullPath: filePath,
|
|
82
|
-
segments,
|
|
83
|
-
commandModule: await importCommandFromFile(filePath, segments[segments.length - 1], fullOptions)
|
|
84
|
-
});
|
|
93
|
+
const lastSegment = segments[segments.length - 1];
|
|
94
|
+
if (lastSegment === undefined) {
|
|
95
|
+
throw new Error(`No segments found for file: ${filePath}`);
|
|
85
96
|
}
|
|
86
|
-
|
|
97
|
+
return {
|
|
98
|
+
fullPath: filePath,
|
|
99
|
+
segments,
|
|
100
|
+
commandModule: await importCommandFromFile(filePath, lastSegment, fullOptions),
|
|
101
|
+
};
|
|
102
|
+
})));
|
|
103
|
+
commands.push(...fileResults);
|
|
87
104
|
// check if no commands were found
|
|
88
105
|
if (commands.length === 0) {
|
|
89
106
|
throw new Error(`No commands found in specified directories: ${fullOptions.commandDirs.join(', ')}`);
|
|
@@ -96,3 +113,4 @@ export const fileCommands = async (options) => {
|
|
|
96
113
|
const rootCommands = commandRootNodes.map((node) => createCommand(node));
|
|
97
114
|
return rootCommands;
|
|
98
115
|
};
|
|
116
|
+
//# sourceMappingURL=fileCommands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileCommands.js","sourceRoot":"","sources":["../../src/lib/fileCommands.ts"],"names":[],"mappings":"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"}
|