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.
Files changed (57) hide show
  1. package/README.md +59 -13
  2. package/dist/index.js +1 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/lib/Command.js +1 -0
  5. package/dist/lib/Command.js.map +1 -0
  6. package/dist/lib/buildSegmentTree.d.ts +1 -1
  7. package/dist/lib/buildSegmentTree.js +7 -3
  8. package/dist/lib/buildSegmentTree.js.map +1 -0
  9. package/dist/lib/buildSegmentTree.test.js +279 -26
  10. package/dist/lib/buildSegmentTree.test.js.map +1 -0
  11. package/dist/lib/fileCommands.d.ts +2 -1
  12. package/dist/lib/fileCommands.js +39 -21
  13. package/dist/lib/fileCommands.js.map +1 -0
  14. package/dist/lib/fileCommands.test.js +107 -30
  15. package/dist/lib/fileCommands.test.js.map +1 -0
  16. package/dist/lib/fixtures/commands/$default.js +1 -0
  17. package/dist/lib/fixtures/commands/$default.js.map +1 -0
  18. package/dist/lib/fixtures/commands/create.js +1 -0
  19. package/dist/lib/fixtures/commands/create.js.map +1 -0
  20. package/dist/lib/fixtures/commands/db/health.d.ts +2 -1
  21. package/dist/lib/fixtures/commands/db/health.js +2 -3
  22. package/dist/lib/fixtures/commands/db/health.js.map +1 -0
  23. package/dist/lib/fixtures/commands/db/migration/command.d.ts +9 -2
  24. package/dist/lib/fixtures/commands/db/migration/command.js +6 -7
  25. package/dist/lib/fixtures/commands/db/migration/command.js.map +1 -0
  26. package/dist/lib/importCommand.d.ts +8 -4
  27. package/dist/lib/importCommand.js +66 -21
  28. package/dist/lib/importCommand.js.map +1 -0
  29. package/dist/lib/importCommand.test.js +157 -34
  30. package/dist/lib/importCommand.test.js.map +1 -0
  31. package/dist/lib/scanDirectory.js +54 -25
  32. package/dist/lib/scanDirectory.js.map +1 -0
  33. package/dist/lib/scanDirectory.test.js +148 -25
  34. package/dist/lib/scanDirectory.test.js.map +1 -0
  35. package/dist/lib/segmentPath.js +8 -6
  36. package/dist/lib/segmentPath.js.map +1 -0
  37. package/dist/lib/segmentPath.test.js +10 -38
  38. package/dist/lib/segmentPath.test.js.map +1 -0
  39. package/dist/tsconfig.tsbuildinfo +1 -0
  40. package/package.json +6 -9
  41. package/CHANGELOG.md +0 -56
  42. package/src/index.ts +0 -1
  43. package/src/lib/Command.ts +0 -16
  44. package/src/lib/buildSegmentTree.test.ts +0 -90
  45. package/src/lib/buildSegmentTree.ts +0 -149
  46. package/src/lib/fileCommands.test.ts +0 -55
  47. package/src/lib/fileCommands.ts +0 -149
  48. package/src/lib/fixtures/commands/$default.ts +0 -5
  49. package/src/lib/fixtures/commands/create.ts +0 -6
  50. package/src/lib/fixtures/commands/db/health.ts +0 -9
  51. package/src/lib/fixtures/commands/db/migration/command.ts +0 -12
  52. package/src/lib/importCommand.test.ts +0 -65
  53. package/src/lib/importCommand.ts +0 -148
  54. package/src/lib/scanDirectory.test.ts +0 -75
  55. package/src/lib/scanDirectory.ts +0 -109
  56. package/src/lib/segmentPath.test.ts +0 -71
  57. package/src/lib/segmentPath.ts +0 -38
@@ -1,36 +1,113 @@
1
- import path from 'path';
2
- import { test } from 'node:test';
3
- import assert from 'node:assert';
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
- test('should load commands from directory structure', async () => {
8
- const commands = await fileCommands({
9
- commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
10
- logLevel: 'debug'
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
- assert.ok(commands.length > 0);
13
- });
14
- test('should respect ignore patterns', async () => {
15
- const commands = await fileCommands({
16
- commandDirs: [path.join(__dirname, 'fixtures', 'commands')],
17
- ignorePatterns: [/health/, /.d.ts/],
18
- logLevel: 'debug'
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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"}
@@ -2,3 +2,4 @@ export const describe = 'Default command';
2
2
  export const handler = async () => {
3
3
  // Default command implementation
4
4
  };
5
+ //# sourceMappingURL=$default.js.map
@@ -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"}
@@ -3,3 +3,4 @@ export const describe = 'Create something with a name';
3
3
  export const handler = async () => {
4
4
  // Create command implementation
5
5
  };
6
+ //# sourceMappingURL=create.js.map
@@ -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,3 +1,4 @@
1
+ import type { Argv } from 'yargs';
1
2
  export declare const describe = "Database health check";
2
- export declare const builder: (yargs: any) => any;
3
+ export declare const builder: (yargs: Argv<{}>) => Argv<{}>;
3
4
  export declare const handler: () => Promise<void>;
@@ -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: any) => any;
3
- export declare const handler: (argv: any) => Promise<void>;
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
- return yargs.option('force', {
4
- type: 'boolean',
5
- describe: 'Force migration'
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 { type ArgumentsCamelCase, type CommandBuilder, type CommandModule } from 'yargs';
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<any>) => void | Promise<any>;
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
@@ -33,12 +33,12 @@ export interface FileCommandsParams {
33
33
  rootDir: string;
34
34
  }
35
35
  /**
36
- * Structure of a command module import
36
+ * Structure of a command module import with individual exports
37
37
  * @interface CommandImportModule
38
38
  */
39
39
  export interface CommandImportModule {
40
40
  /** Command aliases */
41
- alias?: CommandAlias;
41
+ aliases?: CommandAlias;
42
42
  /** Command builder function */
43
43
  builder?: CommandBuilder;
44
44
  /** Command name */
@@ -58,10 +58,14 @@ export interface ImportCommandOptions {
58
58
  * @async
59
59
  * @param {string} filePath - Path to the command file
60
60
  * @param {string} name - Command name
61
+ * @param {ImportCommandOptions} options - Import options
61
62
  * @returns {Promise<CommandModule>} Imported command module
62
63
  *
63
64
  * @description
64
65
  * Dynamically imports a command file and constructs a Yargs command module.
66
+ * Supports two styles of command declaration:
67
+ * 1. Single export of CommandModule named 'command'
68
+ * 2. Individual exports of command parts (command, describe, alias, etc.)
65
69
  * If no handler is provided, creates a null implementation.
66
70
  */
67
71
  export declare const importCommandFromFile: (filePath: string, name: string, options: ImportCommandOptions) => Promise<CommandModule<{}, {}>>;
@@ -1,52 +1,97 @@
1
- import fs from 'fs';
2
- import {} from 'yargs';
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
6
7
  * @param {string} filePath - Path to the command file
7
8
  * @param {string} name - Command name
9
+ * @param {ImportCommandOptions} options - Import options
8
10
  * @returns {Promise<CommandModule>} Imported command module
9
11
  *
10
12
  * @description
11
13
  * Dynamically imports a command file and constructs a Yargs command module.
14
+ * Supports two styles of command declaration:
15
+ * 1. Single export of CommandModule named 'command'
16
+ * 2. Individual exports of command parts (command, describe, alias, etc.)
12
17
  * If no handler is provided, creates a null implementation.
13
18
  */
14
19
  export const importCommandFromFile = async (filePath, name, options) => {
15
- // ensure file exists using fs node library
16
- if (fs.existsSync(filePath) === false) {
17
- throw new Error(`Can not import command from non-existence file path: ${filePath}`);
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().`);
18
27
  }
19
- const url = 'file://' + filePath;
20
- const handlerModule = (await import(url));
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;
21
35
  const { logLevel = 'info' } = options;
36
+ // Import the module
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
+ }
22
46
  // Check if this is the default command
23
47
  const isDefault = name === '$default';
48
+ // First try to use the CommandModule export if it exists
49
+ const importedRecord = imported;
50
+ if ('command' in importedRecord && typeof importedRecord.command === 'object' && importedRecord.command !== null) {
51
+ const commandModule = importedRecord.command;
52
+ // Ensure the command property exists or use the filename
53
+ if (!commandModule.command && !isDefault) {
54
+ commandModule.command = name;
55
+ }
56
+ else if (isDefault && !commandModule.command) {
57
+ commandModule.command = '$0';
58
+ }
59
+ if (logLevel === 'debug') {
60
+ console.debug('Importing CommandModule from', realPath, 'as', name, 'with description', commandModule.describe);
61
+ }
62
+ // Return the command module directly without wrapping
63
+ return {
64
+ command: commandModule.command,
65
+ describe: commandModule.describe,
66
+ builder: commandModule.builder,
67
+ handler: commandModule.handler,
68
+ deprecated: commandModule.deprecated,
69
+ aliases: commandModule.aliases,
70
+ };
71
+ }
72
+ // Fall back to individual exports
73
+ const handlerModule = importedRecord;
24
74
  const command = {
25
75
  command: handlerModule.command ?? (isDefault ? '$0' : name),
26
76
  describe: handlerModule.describe,
27
- alias: handlerModule.alias,
77
+ aliases: handlerModule.aliases,
28
78
  builder: handlerModule.builder,
29
79
  deprecated: handlerModule.deprecated,
30
80
  handler: handlerModule.handler ??
31
- (async (args) => {
81
+ (async (_args) => {
32
82
  // null implementation
33
- })
83
+ }),
34
84
  };
35
- const supportedNames = [
36
- 'command',
37
- 'describe',
38
- 'alias',
39
- 'builder',
40
- 'deprecated',
41
- 'handler'
42
- ];
43
- const module = handlerModule;
85
+ // Validate exports
86
+ const supportedNames = ['command', 'describe', 'alias', 'builder', 'deprecated', 'handler'];
87
+ const module = importedRecord;
44
88
  const unsupportedExports = Object.keys(module).filter((key) => !supportedNames.includes(key));
45
89
  if (unsupportedExports.length > 0) {
46
- throw new Error(`Command module ${name} in ${filePath} has some unsupported exports, probably a misspelling: ${unsupportedExports.join(', ')}`);
90
+ throw new Error(`Command module ${name} in ${realPath} has some unsupported exports, probably a misspelling: ${unsupportedExports.join(', ')}. Supported exports are: ${supportedNames.join(', ')}.`);
47
91
  }
48
92
  if (logLevel === 'debug') {
49
- console.debug('Importing command from', filePath, 'as', name, 'with description', command.describe);
93
+ console.debug('Importing individual exports from', realPath, 'as', name, 'with description', command.describe);
50
94
  }
51
95
  return command;
52
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,42 +1,165 @@
1
- import path from 'path';
2
- import { test } from 'node:test';
3
- import assert from 'node:assert';
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
- test('should import command module correctly', async () => {
8
- const filePath = path.join(__dirname, 'fixtures', 'commands', 'db', 'health.js');
9
- const command = await importCommandFromFile(filePath, 'health', {
10
- logLevel: 'info'
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
- assert.equal(command.describe, 'Database health check');
13
- });
14
- test('should handle non-existent files', async () => {
15
- const filePath = path.join(__dirname, 'fixtures', 'commands', 'non-existent.js');
16
- try {
17
- await importCommandFromFile(filePath, 'non-existent', {
18
- logLevel: 'info'
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
- assert.fail('Should have thrown an error');
21
- }
22
- catch (error) {
23
- assert.ok(error instanceof Error);
24
- assert.ok(error.message.includes('Can not import command from non-existence'));
25
- }
26
- });
27
- test('should handle explicit command names', async () => {
28
- const filePath = path.join(__dirname, 'fixtures', 'commands', 'create.js');
29
- const command = await importCommandFromFile(filePath, 'create', {
30
- logLevel: 'info'
27
+ expect(command.command).toBe('create [name]');
28
+ expect(command.describe).toBe('Create something with a name');
31
29
  });
32
- assert.equal(command.command, 'create [name]');
33
- assert.equal(command.describe, 'Create something with a name');
34
- });
35
- test('should handle default commands', async () => {
36
- const filePath = path.join(__dirname, 'fixtures', 'commands', '$default.js');
37
- const command = await importCommandFromFile(filePath, '$default', {
38
- logLevel: 'info'
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();
39
163
  });
40
- assert.equal(command.command, '$0');
41
- assert.equal(command.describe, 'Default command');
42
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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"}