Skip to content

Commit 98fafdd

Browse files
committed
feat: add directory scoping options to index command
- Add maxDepth, noTraverseUp, and boundary options to IndexOptions interface - Update CLI options interface to support new directory scoping parameters - Implement boundary-aware file discovery in discoverMarkdownFiles function - Fix TypeScript Path/string compatibility issues Addresses #12: index command now respects directory boundaries instead of scanning entire project tree
1 parent 639b730 commit 98fafdd

File tree

1 file changed

+61
-3
lines changed

1 file changed

+61
-3
lines changed

src/commands/index.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ export interface IndexOptions {
3030
dryRun: boolean;
3131
/** Enable verbose output with detailed progress information */
3232
verbose: boolean;
33+
/** Maximum depth to traverse subdirectories */
34+
maxDepth?: number;
35+
/** Prevent traversing up from the specified directory */
36+
noTraverseUp: boolean;
37+
/** Explicit boundary path to limit scanning scope */
38+
boundary?: string;
3339
}
3440

3541
/**
@@ -93,6 +99,9 @@ interface IndexCliOptions {
9399
template?: string;
94100
dryRun?: boolean;
95101
verbose?: boolean;
102+
maxDepth?: number;
103+
noTraverseUp?: boolean;
104+
boundary?: string;
96105
}
97106

98107
export async function indexCommand(
@@ -107,7 +116,10 @@ export async function indexCommand(
107116
embedStyle: cliOptions.embedStyle || 'obsidian',
108117
dryRun: cliOptions.dryRun || false,
109118
verbose: cliOptions.verbose || false,
119+
noTraverseUp: cliOptions.noTraverseUp || false,
110120
...(cliOptions.template && { template: cliOptions.template }),
121+
...(cliOptions.maxDepth !== undefined && { maxDepth: cliOptions.maxDepth }),
122+
...(cliOptions.boundary && { boundary: cliOptions.boundary }),
111123
};
112124

113125
return generateIndexFiles(options, directory || '.');
@@ -170,12 +182,58 @@ async function discoverMarkdownFiles(
170182
targetDir: string,
171183
options: IndexOptions
172184
): Promise<IndexableFile[]> {
173-
const pattern = join(targetDir, '**/*.md');
174-
const filePaths = await glob(pattern, { ignore: ['**/node_modules/**'] });
185+
// Determine the effective boundary for file scanning
186+
const effectiveBoundary = options.boundary ? resolve(options.boundary) : targetDir;
187+
188+
// Build glob pattern based on maxDepth option
189+
let globPattern: string;
190+
if (options.maxDepth !== undefined) {
191+
// Create depth-limited pattern
192+
const depthPattern = Array.from({ length: options.maxDepth }, () => '*').join('/');
193+
globPattern = join(targetDir, depthPattern, '*.md');
194+
} else {
195+
globPattern = join(targetDir, '**/*.md');
196+
}
197+
198+
const globOptions: Parameters<typeof glob>[1] = {
199+
ignore: ['**/node_modules/**'],
200+
};
201+
202+
// Only set cwd if noTraverseUp is enabled
203+
if (options.noTraverseUp) {
204+
globOptions.cwd = targetDir;
205+
}
206+
207+
const filePaths = await glob(globPattern, globOptions);
208+
209+
// Filter files to respect boundary constraints and convert Path objects to strings
210+
const boundaryFilePaths = filePaths
211+
.map(filePath => typeof filePath === 'string' ? filePath : filePath.toString())
212+
.filter(filePath => {
213+
const resolvedPath = resolve(filePath);
214+
215+
// Ensure file is within the boundary directory
216+
if (options.boundary) {
217+
const relativeToBoundary = relative(effectiveBoundary, resolvedPath);
218+
if (relativeToBoundary.startsWith('..')) {
219+
return false; // File is outside boundary
220+
}
221+
}
222+
223+
// Ensure file is within or below target directory when noTraverseUp is enabled
224+
if (options.noTraverseUp) {
225+
const relativeToTarget = relative(targetDir, resolvedPath);
226+
if (relativeToTarget.startsWith('..')) {
227+
return false; // File is above target directory
228+
}
229+
}
230+
231+
return true;
232+
});
175233

176234
const files: IndexableFile[] = [];
177235

178-
for (const filePath of filePaths) {
236+
for (const filePath of boundaryFilePaths) {
179237
// Skip existing index files if they match our naming pattern
180238
const fileName = filePath.split('/').pop() || '';
181239
if (fileName === options.name) {

0 commit comments

Comments
 (0)