yargs-file-commands 0.0.4 → 0.0.6

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.
@@ -39,4 +39,5 @@ export declare const buildSegmentTree: (commands: Command[]) => CommandTreeNode[
39
39
  * For internal nodes, creates a parent command that manages subcommands.
40
40
  */
41
41
  export declare const createCommand: (treeNode: CommandTreeNode) => CommandModule;
42
+ export declare const logCommandTree: (commands: CommandTreeNode[], level?: number) => void;
42
43
  export {};
@@ -89,3 +89,11 @@ export const createCommand = (treeNode) => {
89
89
  };
90
90
  return command;
91
91
  };
92
+ export const logCommandTree = (commands, level = 0) => {
93
+ commands.forEach((command) => {
94
+ console.debug(`${' '.repeat(level) + command.segmentName}`);
95
+ if (command.type === 'internal') {
96
+ logCommandTree(command.children, level + 1);
97
+ }
98
+ });
99
+ };
@@ -1,4 +1,4 @@
1
- import { buildSegmentTree, createCommand } from './buildSegmentTree.js';
1
+ import { buildSegmentTree, createCommand, logCommandTree } from './buildSegmentTree.js';
2
2
  import { importCommandFromFile } from './importCommand.js';
3
3
  import { scanDirectory } from './scanDirectory.js';
4
4
  import { segmentPath } from './segmentPath.js';
@@ -47,12 +47,15 @@ export const fileCommands = async (options) => {
47
47
  return {
48
48
  fullPath: filePath,
49
49
  segments: segmentPath(filePath, commandDir),
50
- commandModule: await importCommandFromFile(filePath, segments[segments.length - 1])
50
+ commandModule: await importCommandFromFile(filePath, segments[segments.length - 1], fullOptions)
51
51
  };
52
52
  }));
53
53
  commands.push(...rootDirCommands);
54
54
  }));
55
55
  const commandRootNodes = buildSegmentTree(commands);
56
+ if (fullOptions.logLevel === 'debug') {
57
+ logCommandTree(commandRootNodes);
58
+ }
56
59
  const rootCommands = commandRootNodes.map((node) => createCommand(node));
57
60
  return rootCommands;
58
61
  };
@@ -50,6 +50,9 @@ export interface CommandImportModule {
50
50
  /** Command handler function */
51
51
  handler?: CommandHandler;
52
52
  }
53
+ export interface ImportCommandOptions {
54
+ logLevel?: 'info' | 'debug';
55
+ }
53
56
  /**
54
57
  * Imports a command module from a file
55
58
  * @async
@@ -61,4 +64,4 @@ export interface CommandImportModule {
61
64
  * Dynamically imports a command file and constructs a Yargs command module.
62
65
  * If no handler is provided, creates a null implementation.
63
66
  */
64
- export declare const importCommandFromFile: (filePath: string, name: string) => Promise<CommandModule<{}, {}>>;
67
+ export declare const importCommandFromFile: (filePath: string, name: string, options: ImportCommandOptions) => Promise<CommandModule<{}, {}>>;
@@ -10,9 +10,10 @@ import {} from 'yargs';
10
10
  * Dynamically imports a command file and constructs a Yargs command module.
11
11
  * If no handler is provided, creates a null implementation.
12
12
  */
13
- export const importCommandFromFile = async (filePath, name) => {
13
+ export const importCommandFromFile = async (filePath, name, options) => {
14
14
  const handlerModule = (await import(filePath));
15
- return {
15
+ const { logLevel = 'info' } = options;
16
+ const command = {
16
17
  command: name,
17
18
  describe: handlerModule.describe,
18
19
  alias: handlerModule.alias,
@@ -23,4 +24,8 @@ export const importCommandFromFile = async (filePath, name) => {
23
24
  // null implementation
24
25
  })
25
26
  };
27
+ if (logLevel === 'debug') {
28
+ console.debug('Importing command from', filePath, 'as', name, 'with description', command.describe);
29
+ }
30
+ return command;
26
31
  };
@@ -7,6 +7,7 @@ export interface ScanDirectoryOptions {
7
7
  ignorePatterns?: RegExp[];
8
8
  /** File extensions to include in the scan */
9
9
  extensions?: string[];
10
+ logLevel?: 'info' | 'debug';
10
11
  }
11
12
  /**
12
13
  * Recursively scans a directory for command files
@@ -14,7 +14,11 @@ import path, { join } from 'path';
14
14
  * The scan is performed in parallel for better performance.
15
15
  */
16
16
  export const scanDirectory = async (dirPath, options = {}) => {
17
- const { ignorePatterns = [], extensions = [] } = options;
17
+ const { ignorePatterns = [], extensions = [], logLevel = 'info' } = options;
18
+ const rootedDirPath = path.resolve(dirPath);
19
+ if (logLevel === 'debug') {
20
+ console.debug(`Inspecting directory for possible commands: ${rootedDirPath}`);
21
+ }
18
22
  // Check if path should be ignored
19
23
  const shouldIgnore = ignorePatterns.some((pattern) => pattern.test(dirPath));
20
24
  if (shouldIgnore) {
@@ -23,12 +27,15 @@ export const scanDirectory = async (dirPath, options = {}) => {
23
27
  try {
24
28
  const entries = await readdir(dirPath);
25
29
  const nestedFilesPromises = entries.map(async (entry) => {
30
+ const fullPath = join(dirPath, entry);
26
31
  // apply ignore pattern and early return if matched
27
32
  const shouldIgnore = ignorePatterns.some((pattern) => pattern.test(entry));
28
33
  if (shouldIgnore) {
34
+ if (logLevel === 'debug') {
35
+ console.debug(`Ignoring file because of ignorePatterns match: ${path.resolve(fullPath)}`);
36
+ }
29
37
  return [];
30
38
  }
31
- const fullPath = join(dirPath, entry);
32
39
  const stats = await stat(fullPath);
33
40
  if (stats.isDirectory()) {
34
41
  return scanDirectory(fullPath, options);
@@ -37,6 +44,9 @@ export const scanDirectory = async (dirPath, options = {}) => {
37
44
  if (!extensions.includes(extension)) {
38
45
  return [];
39
46
  }
47
+ if (logLevel === 'debug') {
48
+ console.debug(`Inspecting file as possible command: ${fullPath}`);
49
+ }
40
50
  return [fullPath];
41
51
  });
42
52
  const nestedFiles = await Promise.all(nestedFilesPromises);
@@ -7,7 +7,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
7
  describe('importCommandFromFile', async () => {
8
8
  it('should import command module correctly', async () => {
9
9
  const commandPath = path.join(__dirname, 'fixtures', 'commands', 'db', 'health.js');
10
- const command = await importCommandFromFile(commandPath, 'health');
10
+ const command = await importCommandFromFile(commandPath, 'health', {});
11
11
  assert(command.describe, 'Should have describe property');
12
12
  assert(typeof command.builder === 'function', 'Should have builder function');
13
13
  assert(typeof command.handler === 'function', 'Should have handler function');
@@ -15,7 +15,7 @@ describe('importCommandFromFile', async () => {
15
15
  it('should handle non-existent files', async () => {
16
16
  const nonExistentPath = path.join(__dirname, 'fixtures', 'commands', 'non-existent.ts');
17
17
  await assert.rejects(async () => {
18
- await importCommandFromFile(nonExistentPath, 'non-existent');
18
+ await importCommandFromFile(nonExistentPath, 'non-existent', {});
19
19
  }, Error, 'Should throw error for non-existent file');
20
20
  });
21
21
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "yargs-file-commands",
3
3
  "description": "A yargs helper function that lets you define your commands structure via directory and file naming conventions.",
4
- "version": "0.0.4",
4
+ "version": "0.0.6",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",