yargs-file-commands 0.0.20 → 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 +13 -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 +3 -3
- package/dist/lib/importCommand.js +39 -27
- package/dist/lib/importCommand.js.map +1 -0
- package/dist/lib/importCommand.test.js +157 -33
- 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 -62
- 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 -60
- package/src/lib/importCommand.ts +0 -196
- 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
|
@@ -1,36 +1,113 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
4
5
|
import { fileCommands } from './fileCommands.js';
|
|
5
6
|
// get __dirname in ESM style
|
|
6
7
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
describe('fileCommands', () => {
|
|
9
|
+
it('should load commands from directory structure', async () => {
|
|
10
|
+
const commands = await fileCommands({
|
|
11
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
12
|
+
logLevel: 'debug',
|
|
13
|
+
});
|
|
14
|
+
expect(commands.length).toBeGreaterThan(0);
|
|
11
15
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
it('should respect ignore patterns', async () => {
|
|
17
|
+
const commands = await fileCommands({
|
|
18
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
19
|
+
ignorePatterns: [/health/, /.d.ts/],
|
|
20
|
+
logLevel: 'debug',
|
|
21
|
+
});
|
|
22
|
+
expect(commands.length).toBeGreaterThan(0);
|
|
23
|
+
});
|
|
24
|
+
it('should handle explicit commands and default command', async () => {
|
|
25
|
+
const commands = await fileCommands({
|
|
26
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
27
|
+
logLevel: 'debug',
|
|
28
|
+
});
|
|
29
|
+
console.log('commands', JSON.stringify(commands.map((c) => c.command), null, 2));
|
|
30
|
+
// Find the explicit command
|
|
31
|
+
const explicitCommand = commands.find((cmd) => cmd.command?.toString().includes('create [name]'));
|
|
32
|
+
expect(explicitCommand).toBeDefined();
|
|
33
|
+
expect(explicitCommand?.describe).toBe('Create something with a name');
|
|
34
|
+
// Find the default command
|
|
35
|
+
const defaultCommand = commands.find((cmd) => cmd.command === '$0');
|
|
36
|
+
expect(defaultCommand).toBeDefined();
|
|
37
|
+
expect(defaultCommand?.describe).toBe('Default command');
|
|
38
|
+
});
|
|
39
|
+
it('should throw error for invalid extensions (missing dot)', async () => {
|
|
40
|
+
await expect(fileCommands({
|
|
41
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
42
|
+
extensions: ['js', 'ts'], // Missing dots
|
|
43
|
+
})).rejects.toThrow(/Invalid extensions provided, must start with a dot/);
|
|
44
|
+
});
|
|
45
|
+
it('should throw error for empty command directories', async () => {
|
|
46
|
+
await expect(fileCommands({
|
|
47
|
+
commandDirs: [],
|
|
48
|
+
})).rejects.toThrow(/No command directories provided/);
|
|
49
|
+
});
|
|
50
|
+
it('should throw error for non-absolute directory paths', async () => {
|
|
51
|
+
await expect(fileCommands({
|
|
52
|
+
commandDirs: ['relative/path'], // Relative path
|
|
53
|
+
})).rejects.toThrow(/Command directories must be absolute paths/);
|
|
54
|
+
});
|
|
55
|
+
it('should throw error for non-absolute directory paths (multiple)', async () => {
|
|
56
|
+
await expect(fileCommands({
|
|
57
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands'), 'relative/path', 'another/relative'],
|
|
58
|
+
})).rejects.toThrow(/Command directories must be absolute paths/);
|
|
59
|
+
await expect(fileCommands({
|
|
60
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands'), 'relative/path', 'another/relative'],
|
|
61
|
+
})).rejects.toThrow(/relative\/path, another\/relative/);
|
|
62
|
+
});
|
|
63
|
+
it('should throw error when no commands found', async () => {
|
|
64
|
+
// Create a temporary empty directory
|
|
65
|
+
// Use a unique timestamp to avoid collisions with other tests
|
|
66
|
+
const tempDir = path.join(tmpdir(), `yargs-empty-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
67
|
+
await mkdir(tempDir, { recursive: true });
|
|
68
|
+
try {
|
|
69
|
+
// Ensure directory is truly empty (system files like .DS_Store are automatically ignored)
|
|
70
|
+
await expect(fileCommands({
|
|
71
|
+
commandDirs: [tempDir],
|
|
72
|
+
extensions: ['.js', '.ts'], // Only look for JS/TS files
|
|
73
|
+
})).rejects.toThrow(/No commands found in specified directories/);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
it('should handle multiple command directories', async () => {
|
|
80
|
+
const tempDir1 = path.join(tmpdir(), `yargs-test-1-${Date.now()}`);
|
|
81
|
+
const tempDir2 = path.join(tmpdir(), `yargs-test-2-${Date.now()}`);
|
|
82
|
+
await mkdir(tempDir1, { recursive: true });
|
|
83
|
+
await mkdir(tempDir2, { recursive: true });
|
|
84
|
+
try {
|
|
85
|
+
// Create a command file in each directory
|
|
86
|
+
await writeFile(path.join(tempDir1, 'cmd1.ts'), "export const describe = 'Command 1';\nexport const handler = async () => {};");
|
|
87
|
+
await writeFile(path.join(tempDir2, 'cmd2.ts'), "export const describe = 'Command 2';\nexport const handler = async () => {};");
|
|
88
|
+
const commands = await fileCommands({
|
|
89
|
+
commandDirs: [tempDir1, tempDir2],
|
|
90
|
+
});
|
|
91
|
+
expect(commands.length).toBeGreaterThanOrEqual(2);
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
await rm(tempDir1, { recursive: true, force: true });
|
|
95
|
+
await rm(tempDir2, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
it('should use default options when not provided', async () => {
|
|
99
|
+
const commands = await fileCommands({
|
|
100
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
101
|
+
// No other options provided - should use defaults
|
|
102
|
+
});
|
|
103
|
+
expect(commands.length).toBeGreaterThan(0);
|
|
104
|
+
});
|
|
105
|
+
it('should handle custom extensions', async () => {
|
|
106
|
+
const commands = await fileCommands({
|
|
107
|
+
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
108
|
+
extensions: ['.ts'], // Only TypeScript files
|
|
109
|
+
});
|
|
110
|
+
expect(commands.length).toBeGreaterThan(0);
|
|
19
111
|
});
|
|
20
|
-
assert.ok(commands.length > 0);
|
|
21
|
-
});
|
|
22
|
-
test('should handle explicit commands and default command', async () => {
|
|
23
|
-
const commands = await fileCommands({
|
|
24
|
-
commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
|
|
25
|
-
logLevel: 'debug'
|
|
26
|
-
});
|
|
27
|
-
console.log('commands', JSON.stringify(commands.map((c) => c.command), null, 2));
|
|
28
|
-
// Find the explicit command
|
|
29
|
-
const explicitCommand = commands.find((cmd) => cmd.command?.toString().includes('create [name]'));
|
|
30
|
-
assert.ok(explicitCommand, 'Should find explicit command');
|
|
31
|
-
assert.equal(explicitCommand?.describe, 'Create something with a name');
|
|
32
|
-
// Find the default command
|
|
33
|
-
const defaultCommand = commands.find((cmd) => cmd.command === '$0');
|
|
34
|
-
assert.ok(defaultCommand, 'Should find default command');
|
|
35
|
-
assert.equal(defaultCommand?.describe, 'Default command');
|
|
36
112
|
});
|
|
113
|
+
//# sourceMappingURL=fileCommands.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileCommands.test.js","sourceRoot":"","sources":["../../src/lib/fileCommands.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"$default.js","sourceRoot":"","sources":["../../../../src/lib/fixtures/commands/$default.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAE1C,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;IACjC,iCAAiC;AADC,CAEnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/lib/fixtures/commands/create.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC;AACvC,MAAM,CAAC,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAEvD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;IACjC,gCAAgC;AADE,CAEnC,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export const describe = 'Database health check';
|
|
2
|
-
export const builder = (yargs) =>
|
|
3
|
-
return yargs;
|
|
4
|
-
};
|
|
2
|
+
export const builder = (yargs) => yargs;
|
|
5
3
|
export const handler = async () => {
|
|
6
4
|
console.log('Health check handler called');
|
|
7
5
|
};
|
|
6
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../../../src/lib/fixtures/commands/db/health.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AAEhD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAW,EAAE,EAAE,CAAC,KAAK,CAAC;AAE9C,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAAA,CAC5C,CAAC"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import type { ArgumentsCamelCase, Argv } from 'yargs';
|
|
1
2
|
export declare const describe = "Database migration command";
|
|
2
|
-
export declare const builder: (yargs:
|
|
3
|
-
|
|
3
|
+
export declare const builder: (yargs: Argv<{}>) => Argv<{
|
|
4
|
+
force: boolean | undefined;
|
|
5
|
+
}>;
|
|
6
|
+
type Options = {
|
|
7
|
+
force?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const handler: (_argv: ArgumentsCamelCase<Options>) => Promise<void>;
|
|
10
|
+
export {};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export const describe = 'Database migration command';
|
|
2
|
-
export const builder = (yargs) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
export const handler = async (argv) => {
|
|
2
|
+
export const builder = (yargs) => yargs.option('force', {
|
|
3
|
+
type: 'boolean',
|
|
4
|
+
describe: 'Force migration',
|
|
5
|
+
});
|
|
6
|
+
export const handler = async (_argv) => {
|
|
9
7
|
console.log('Migration handler called');
|
|
10
8
|
};
|
|
9
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../../src/lib/fixtures/commands/db/migration/command.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AAErD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAW,EAAE,EAAE,CACrC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;IACpB,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,iBAAiB;CAC5B,CAAC,CAAC;AAML,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,KAAkC,EAAE,EAAE,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAAA,CACzC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ArgumentsCamelCase, CommandBuilder, CommandModule } from 'yargs';
|
|
2
2
|
/**
|
|
3
3
|
* Represents command alias configuration
|
|
4
4
|
* @type {readonly string[] | string | undefined}
|
|
@@ -23,7 +23,7 @@ export type CommandDescribe = string | false | undefined;
|
|
|
23
23
|
* Command handler function type
|
|
24
24
|
* @type {Function}
|
|
25
25
|
*/
|
|
26
|
-
export type CommandHandler = (args: ArgumentsCamelCase<
|
|
26
|
+
export type CommandHandler = (args: ArgumentsCamelCase<Record<string, unknown>>) => undefined | Promise<unknown>;
|
|
27
27
|
/**
|
|
28
28
|
* Parameters for file commands configuration
|
|
29
29
|
* @interface FileCommandsParams
|
|
@@ -68,4 +68,4 @@ export interface ImportCommandOptions {
|
|
|
68
68
|
* 2. Individual exports of command parts (command, describe, alias, etc.)
|
|
69
69
|
* If no handler is provided, creates a null implementation.
|
|
70
70
|
*/
|
|
71
|
-
export declare const importCommandFromFile: (filePath: string, name: string, options: ImportCommandOptions) => Promise<CommandModule
|
|
71
|
+
export declare const importCommandFromFile: (filePath: string, name: string, options: ImportCommandOptions) => Promise<CommandModule<{}, {}>>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
3
4
|
/**
|
|
4
5
|
* Imports a command module from a file
|
|
5
6
|
* @async
|
|
@@ -16,21 +17,38 @@ import {} from 'yargs';
|
|
|
16
17
|
* If no handler is provided, creates a null implementation.
|
|
17
18
|
*/
|
|
18
19
|
export const importCommandFromFile = async (filePath, name, options) => {
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// Resolve to absolute path first
|
|
21
|
+
const resolvedPath = path.resolve(filePath);
|
|
22
|
+
// Ensure file exists using fs node library
|
|
23
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
24
|
+
const originalPath = filePath !== resolvedPath ? ` (original: ${filePath})` : '';
|
|
25
|
+
throw new Error(`Cannot import command from non-existent file path: ${resolvedPath}${originalPath}. ` +
|
|
26
|
+
`Ensure the file exists and the path is correct. If using a relative path, consider using an absolute path or path.resolve().`);
|
|
22
27
|
}
|
|
23
|
-
|
|
28
|
+
// Get the real (canonical) path to handle symlinks consistently
|
|
29
|
+
// This ensures the path matches what pathToFileURL will resolve to
|
|
30
|
+
const realPath = fs.realpathSync.native(resolvedPath);
|
|
31
|
+
// Construct file URL using Node.js's pathToFileURL which properly handles
|
|
32
|
+
// path normalization, special characters, and cross-platform compatibility
|
|
33
|
+
// Use the real path to avoid symlink resolution mismatches
|
|
34
|
+
const url = pathToFileURL(realPath).href;
|
|
24
35
|
const { logLevel = 'info' } = options;
|
|
25
36
|
// Import the module
|
|
26
|
-
|
|
37
|
+
let imported;
|
|
38
|
+
try {
|
|
39
|
+
imported = await import(url);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
43
|
+
throw new Error(`Failed to import command module from ${realPath}: ${errorMessage}. ` +
|
|
44
|
+
`Ensure the file is a valid JavaScript/TypeScript module and the path is correct.`);
|
|
45
|
+
}
|
|
27
46
|
// Check if this is the default command
|
|
28
47
|
const isDefault = name === '$default';
|
|
29
48
|
// First try to use the CommandModule export if it exists
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const commandModule = imported.command;
|
|
49
|
+
const importedRecord = imported;
|
|
50
|
+
if ('command' in importedRecord && typeof importedRecord.command === 'object' && importedRecord.command !== null) {
|
|
51
|
+
const commandModule = importedRecord.command;
|
|
34
52
|
// Ensure the command property exists or use the filename
|
|
35
53
|
if (!commandModule.command && !isDefault) {
|
|
36
54
|
commandModule.command = name;
|
|
@@ -39,7 +57,7 @@ export const importCommandFromFile = async (filePath, name, options) => {
|
|
|
39
57
|
commandModule.command = '$0';
|
|
40
58
|
}
|
|
41
59
|
if (logLevel === 'debug') {
|
|
42
|
-
console.debug('Importing CommandModule from',
|
|
60
|
+
console.debug('Importing CommandModule from', realPath, 'as', name, 'with description', commandModule.describe);
|
|
43
61
|
}
|
|
44
62
|
// Return the command module directly without wrapping
|
|
45
63
|
return {
|
|
@@ -48,11 +66,11 @@ export const importCommandFromFile = async (filePath, name, options) => {
|
|
|
48
66
|
builder: commandModule.builder,
|
|
49
67
|
handler: commandModule.handler,
|
|
50
68
|
deprecated: commandModule.deprecated,
|
|
51
|
-
aliases: commandModule.aliases
|
|
69
|
+
aliases: commandModule.aliases,
|
|
52
70
|
};
|
|
53
71
|
}
|
|
54
72
|
// Fall back to individual exports
|
|
55
|
-
const handlerModule =
|
|
73
|
+
const handlerModule = importedRecord;
|
|
56
74
|
const command = {
|
|
57
75
|
command: handlerModule.command ?? (isDefault ? '$0' : name),
|
|
58
76
|
describe: handlerModule.describe,
|
|
@@ -60,26 +78,20 @@ export const importCommandFromFile = async (filePath, name, options) => {
|
|
|
60
78
|
builder: handlerModule.builder,
|
|
61
79
|
deprecated: handlerModule.deprecated,
|
|
62
80
|
handler: handlerModule.handler ??
|
|
63
|
-
(async (
|
|
81
|
+
(async (_args) => {
|
|
64
82
|
// null implementation
|
|
65
|
-
})
|
|
83
|
+
}),
|
|
66
84
|
};
|
|
67
85
|
// Validate exports
|
|
68
|
-
const supportedNames = [
|
|
69
|
-
|
|
70
|
-
'describe',
|
|
71
|
-
'alias',
|
|
72
|
-
'builder',
|
|
73
|
-
'deprecated',
|
|
74
|
-
'handler'
|
|
75
|
-
];
|
|
76
|
-
const module = imported;
|
|
86
|
+
const supportedNames = ['command', 'describe', 'alias', 'builder', 'deprecated', 'handler'];
|
|
87
|
+
const module = importedRecord;
|
|
77
88
|
const unsupportedExports = Object.keys(module).filter((key) => !supportedNames.includes(key));
|
|
78
89
|
if (unsupportedExports.length > 0) {
|
|
79
|
-
throw new Error(`Command module ${name} in ${
|
|
90
|
+
throw new Error(`Command module ${name} in ${realPath} has some unsupported exports, probably a misspelling: ${unsupportedExports.join(', ')}. Supported exports are: ${supportedNames.join(', ')}.`);
|
|
80
91
|
}
|
|
81
92
|
if (logLevel === 'debug') {
|
|
82
|
-
console.debug('Importing individual exports from',
|
|
93
|
+
console.debug('Importing individual exports from', realPath, 'as', name, 'with description', command.describe);
|
|
83
94
|
}
|
|
84
95
|
return command;
|
|
85
96
|
};
|
|
97
|
+
//# sourceMappingURL=importCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importCommand.js","sourceRoot":"","sources":["../../src/lib/importCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +1,165 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
5
|
import { importCommandFromFile } from './importCommand.js';
|
|
5
6
|
// get __dirname in ESM style
|
|
6
7
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
describe('importCommandFromFile', () => {
|
|
9
|
+
it('should import command module correctly', async () => {
|
|
10
|
+
const filePath = path.join(__dirname, 'fixtures', 'commands', 'db', 'health.ts');
|
|
11
|
+
const command = await importCommandFromFile(filePath, 'health', {
|
|
12
|
+
logLevel: 'info',
|
|
13
|
+
});
|
|
14
|
+
expect(command.describe).toBe('Database health check');
|
|
11
15
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
it('should handle non-existent files', async () => {
|
|
17
|
+
const filePath = path.join(__dirname, 'fixtures', 'commands', 'non-existent.ts');
|
|
18
|
+
await expect(importCommandFromFile(filePath, 'non-existent', {
|
|
19
|
+
logLevel: 'info',
|
|
20
|
+
})).rejects.toThrow(/Cannot import command from non-existent file path/);
|
|
21
|
+
});
|
|
22
|
+
it('should handle explicit command names', async () => {
|
|
23
|
+
const filePath = path.join(__dirname, 'fixtures', 'commands', 'create.ts');
|
|
24
|
+
const command = await importCommandFromFile(filePath, 'create', {
|
|
25
|
+
logLevel: 'info',
|
|
19
26
|
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
catch (error) {
|
|
23
|
-
assert.ok(error instanceof Error);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
test('should handle explicit command names', async () => {
|
|
27
|
-
const filePath = path.join(__dirname, 'fixtures', 'commands', 'create.js');
|
|
28
|
-
const command = await importCommandFromFile(filePath, 'create', {
|
|
29
|
-
logLevel: 'info'
|
|
27
|
+
expect(command.command).toBe('create [name]');
|
|
28
|
+
expect(command.describe).toBe('Create something with a name');
|
|
30
29
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
it('should handle default commands', async () => {
|
|
31
|
+
const filePath = path.join(__dirname, 'fixtures', 'commands', '$default.ts');
|
|
32
|
+
const command = await importCommandFromFile(filePath, '$default', {
|
|
33
|
+
logLevel: 'info',
|
|
34
|
+
});
|
|
35
|
+
expect(command.command).toBe('$0');
|
|
36
|
+
expect(command.describe).toBe('Default command');
|
|
37
|
+
});
|
|
38
|
+
it('should handle CommandModule export style', async () => {
|
|
39
|
+
// Create a temporary command file with CommandModule export
|
|
40
|
+
const tempDir = path.join(tmpdir(), `yargs-test-${Date.now()}`);
|
|
41
|
+
await mkdir(tempDir, { recursive: true });
|
|
42
|
+
const filePath = path.resolve(path.join(tempDir, 'cmd.js')); // Use .js and ensure absolute path
|
|
43
|
+
try {
|
|
44
|
+
await writeFile(filePath, `export const command = {
|
|
45
|
+
command: 'testcmd',
|
|
46
|
+
describe: 'Test command',
|
|
47
|
+
handler: async () => {}
|
|
48
|
+
};`);
|
|
49
|
+
const command = await importCommandFromFile(filePath, 'testcmd', {
|
|
50
|
+
logLevel: 'info',
|
|
51
|
+
});
|
|
52
|
+
expect(command.command).toBe('testcmd');
|
|
53
|
+
expect(command.describe).toBe('Test command');
|
|
54
|
+
expect(command.handler).toBeDefined();
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
it('should handle CommandModule export with default command name', async () => {
|
|
61
|
+
// Create a temporary command file with CommandModule export for default
|
|
62
|
+
// Note: Using a simpler filename to avoid potential issues with $ character in file URLs
|
|
63
|
+
const tempDir = path.join(tmpdir(), `yargs-test-${Date.now()}`);
|
|
64
|
+
await mkdir(tempDir, { recursive: true });
|
|
65
|
+
const filePath = path.resolve(path.join(tempDir, 'default-cmd.js')); // Use simpler name
|
|
66
|
+
try {
|
|
67
|
+
await writeFile(filePath, `export const command = {
|
|
68
|
+
command: '$0',
|
|
69
|
+
describe: 'Default test',
|
|
70
|
+
handler: async () => {}
|
|
71
|
+
};`);
|
|
72
|
+
// Verify file exists
|
|
73
|
+
const fs = await import('node:fs');
|
|
74
|
+
if (!fs.existsSync(filePath)) {
|
|
75
|
+
throw new Error(`File was not created at ${filePath}`);
|
|
76
|
+
}
|
|
77
|
+
const command = await importCommandFromFile(filePath, '$default', {
|
|
78
|
+
logLevel: 'info',
|
|
79
|
+
});
|
|
80
|
+
expect(command.command).toBe('$0');
|
|
81
|
+
expect(command.describe).toBe('Default test');
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
it('should throw error for unsupported exports', async () => {
|
|
88
|
+
// Create a temporary command file with unsupported exports
|
|
89
|
+
const tempDir = path.join(tmpdir(), `yargs-test-${Date.now()}`);
|
|
90
|
+
await mkdir(tempDir, { recursive: true });
|
|
91
|
+
const filePath = path.resolve(path.join(tempDir, 'cmd.js')); // Use .js and ensure absolute path
|
|
92
|
+
try {
|
|
93
|
+
await writeFile(filePath, `export const describe = 'Test';
|
|
94
|
+
export const handler = async () => {};
|
|
95
|
+
export const unsupportedExport = 'should error';
|
|
96
|
+
export const anotherBadExport = 123;`);
|
|
97
|
+
// Verify file was written
|
|
98
|
+
const fs = await import('node:fs');
|
|
99
|
+
if (!fs.existsSync(filePath)) {
|
|
100
|
+
throw new Error(`File was not created at ${filePath}`);
|
|
101
|
+
}
|
|
102
|
+
await expect(importCommandFromFile(filePath, 'cmd', {
|
|
103
|
+
logLevel: 'info',
|
|
104
|
+
})).rejects.toThrow(/has some unsupported exports, probably a misspelling/);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
it('should create null handler when handler is not provided', async () => {
|
|
111
|
+
// Create a temporary command file without handler
|
|
112
|
+
const tempDir = path.join(tmpdir(), `yargs-test-${Date.now()}`);
|
|
113
|
+
await mkdir(tempDir, { recursive: true });
|
|
114
|
+
const filePath = path.resolve(path.join(tempDir, 'cmd.js')); // Use .js and ensure absolute path
|
|
115
|
+
try {
|
|
116
|
+
await writeFile(filePath, `export const describe = 'Test without handler';
|
|
117
|
+
export const command = 'test';`);
|
|
118
|
+
const command = await importCommandFromFile(filePath, 'cmd', {
|
|
119
|
+
logLevel: 'info',
|
|
120
|
+
});
|
|
121
|
+
expect(command.handler).toBeDefined();
|
|
122
|
+
expect(typeof command.handler).toBe('function');
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
it('should handle command with aliases', async () => {
|
|
129
|
+
const filePath = path.join(__dirname, 'fixtures', 'commands', 'db', 'health.ts');
|
|
130
|
+
const command = await importCommandFromFile(filePath, 'health', {
|
|
131
|
+
logLevel: 'info',
|
|
132
|
+
});
|
|
133
|
+
// Health command doesn't have aliases, but let's verify the structure supports it
|
|
134
|
+
expect(command).toBeDefined();
|
|
135
|
+
expect(command.describe).toBe('Database health check');
|
|
136
|
+
});
|
|
137
|
+
it('should use filename as command name when not provided', async () => {
|
|
138
|
+
// Create a temporary command file without explicit command name
|
|
139
|
+
const tempDir = path.join(tmpdir(), `yargs-test-${Date.now()}`);
|
|
140
|
+
await mkdir(tempDir, { recursive: true });
|
|
141
|
+
const filePath = path.resolve(path.join(tempDir, 'mycommand.js')); // Use .js and ensure absolute path
|
|
142
|
+
try {
|
|
143
|
+
await writeFile(filePath, `export const describe = 'My command';
|
|
144
|
+
export const handler = async () => {};`);
|
|
145
|
+
const command = await importCommandFromFile(filePath, 'mycommand', {
|
|
146
|
+
logLevel: 'info',
|
|
147
|
+
});
|
|
148
|
+
expect(command.command).toBe('mycommand');
|
|
149
|
+
expect(command.describe).toBe('My command');
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
it('should handle debug log level', async () => {
|
|
156
|
+
const consoleSpy = vi.spyOn(console, 'debug').mockImplementation(() => { });
|
|
157
|
+
const filePath = path.join(__dirname, 'fixtures', 'commands', 'create.ts');
|
|
158
|
+
await importCommandFromFile(filePath, 'create', {
|
|
159
|
+
logLevel: 'debug',
|
|
160
|
+
});
|
|
161
|
+
expect(consoleSpy).toHaveBeenCalled();
|
|
162
|
+
consoleSpy.mockRestore();
|
|
38
163
|
});
|
|
39
|
-
assert.equal(command.command, '$0');
|
|
40
|
-
assert.equal(command.describe, 'Default command');
|
|
41
164
|
});
|
|
165
|
+
//# sourceMappingURL=importCommand.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importCommand.test.js","sourceRoot":"","sources":["../../src/lib/importCommand.test.ts"],"names":[],"mappings":"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"}
|