@hubblecommerce/overmind-core 0.1.7 → 0.1.8
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.
|
@@ -17,6 +17,12 @@ interface SearchOptions {
|
|
|
17
17
|
ignoreCase?: boolean;
|
|
18
18
|
contextLines?: number;
|
|
19
19
|
}
|
|
20
|
+
interface DirectoryStructureOptions {
|
|
21
|
+
/** Subtree root path to start from (e.g. "app/components"). Default: root */
|
|
22
|
+
path?: string;
|
|
23
|
+
/** How many levels deep to return. Default: 1 (top-level only) */
|
|
24
|
+
depth?: number;
|
|
25
|
+
}
|
|
20
26
|
/**
|
|
21
27
|
* Search a repomix XML string for lines matching a pattern.
|
|
22
28
|
* Returns matching lines with optional context.
|
|
@@ -28,5 +34,10 @@ export declare function searchRepomix(xml: string, pattern: string, options?: Se
|
|
|
28
34
|
* Returns null if the file is not found.
|
|
29
35
|
*/
|
|
30
36
|
export declare function getRepomixFile(xml: string, filePath: string): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Extract the directory structure from repomix XML.
|
|
39
|
+
* Returns an indented tree filtered by optional path and depth.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getRepomixDirectoryStructure(xml: string, options?: DirectoryStructureOptions): string | null;
|
|
31
42
|
export {};
|
|
32
43
|
//# sourceMappingURL=repomix-search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repomix-search.d.ts","sourceRoot":"","sources":["../../../src/utils/repomix-search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,UAAU,WAAW;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,UAAU,aAAa;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAmGD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,YAAY,CASjG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3E"}
|
|
1
|
+
{"version":3,"file":"repomix-search.d.ts","sourceRoot":"","sources":["../../../src/utils/repomix-search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,UAAU,WAAW;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,UAAU,aAAa;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,yBAAyB;IAC/B,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAmGD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,YAAY,CASjG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3E;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,MAAM,GAAG,IAAI,CA0D5G"}
|
|
@@ -105,3 +105,57 @@ export function getRepomixFile(xml, filePath) {
|
|
|
105
105
|
return null;
|
|
106
106
|
return match[1];
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Extract the directory structure from repomix XML.
|
|
110
|
+
* Returns an indented tree filtered by optional path and depth.
|
|
111
|
+
*/
|
|
112
|
+
export function getRepomixDirectoryStructure(xml, options) {
|
|
113
|
+
const match = xml.match(/<directory_structure>\n?([\s\S]*?)\n?<\/directory_structure>/);
|
|
114
|
+
if (!match?.[1])
|
|
115
|
+
return null;
|
|
116
|
+
const fullTree = match[1];
|
|
117
|
+
const lines = fullTree.split('\n');
|
|
118
|
+
const targetPath = options?.path?.replace(/\/$/, '') ?? '';
|
|
119
|
+
const maxDepth = options?.depth ?? 1;
|
|
120
|
+
const getDepth = (line) => {
|
|
121
|
+
const leadingSpaces = line.match(/^( *)/)?.[1].length ?? 0;
|
|
122
|
+
return leadingSpaces / 2;
|
|
123
|
+
};
|
|
124
|
+
// Build full paths from indented tree using a stack
|
|
125
|
+
const pathStack = [];
|
|
126
|
+
if (!targetPath) {
|
|
127
|
+
return lines
|
|
128
|
+
.filter(line => line.trim() && getDepth(line) < maxDepth)
|
|
129
|
+
.join('\n');
|
|
130
|
+
}
|
|
131
|
+
// Find the subtree starting at targetPath
|
|
132
|
+
let inSubtree = false;
|
|
133
|
+
let subtreeBaseDepth = 0;
|
|
134
|
+
const result = [];
|
|
135
|
+
for (const line of lines) {
|
|
136
|
+
const trimmed = line.trim();
|
|
137
|
+
if (!trimmed)
|
|
138
|
+
continue;
|
|
139
|
+
const depth = getDepth(line);
|
|
140
|
+
// Maintain path stack: trim to current depth, then push
|
|
141
|
+
pathStack.length = depth;
|
|
142
|
+
pathStack.push(trimmed.replace(/\/$/, ''));
|
|
143
|
+
const fullPath = pathStack.join('/');
|
|
144
|
+
if (!inSubtree) {
|
|
145
|
+
if (fullPath === targetPath) {
|
|
146
|
+
inSubtree = true;
|
|
147
|
+
subtreeBaseDepth = depth + 1;
|
|
148
|
+
result.push(trimmed);
|
|
149
|
+
}
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (depth < subtreeBaseDepth) {
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
const relativeDepth = depth - subtreeBaseDepth;
|
|
156
|
+
if (relativeDepth < maxDepth) {
|
|
157
|
+
result.push(' '.repeat(relativeDepth) + trimmed);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return result.length > 0 ? result.join('\n') : null;
|
|
161
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { searchRepomix, getRepomixFile } from './repomix-search.js';
|
|
2
|
+
import { searchRepomix, getRepomixFile, getRepomixDirectoryStructure } from './repomix-search.js';
|
|
3
3
|
const SAMPLE_XML = `<file path="src/index.ts">
|
|
4
4
|
import { App } from './app';
|
|
5
5
|
|
|
@@ -25,6 +25,27 @@ export function login(username: string, password: string) {
|
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
</file>`;
|
|
28
|
+
const SAMPLE_XML_WITH_STRUCTURE = `<directory_structure>
|
|
29
|
+
app/
|
|
30
|
+
components/
|
|
31
|
+
Header.vue
|
|
32
|
+
Footer.vue
|
|
33
|
+
pages/
|
|
34
|
+
index.vue
|
|
35
|
+
about.vue
|
|
36
|
+
middleware/
|
|
37
|
+
auth.ts
|
|
38
|
+
config/
|
|
39
|
+
app.config.ts
|
|
40
|
+
package.json
|
|
41
|
+
README.md
|
|
42
|
+
</directory_structure>
|
|
43
|
+
|
|
44
|
+
<files>
|
|
45
|
+
<file path="app/components/Header.vue">
|
|
46
|
+
<template><header></header></template>
|
|
47
|
+
</file>
|
|
48
|
+
</files>`;
|
|
28
49
|
describe('searchRepomix', () => {
|
|
29
50
|
it('returns matching lines with file context', () => {
|
|
30
51
|
const results = searchRepomix(SAMPLE_XML, 'auth');
|
|
@@ -86,3 +107,36 @@ describe('getRepomixFile', () => {
|
|
|
86
107
|
expect(content).toContain("import { App }");
|
|
87
108
|
});
|
|
88
109
|
});
|
|
110
|
+
describe('getRepomixDirectoryStructure', () => {
|
|
111
|
+
it('returns top-level entries by default (depth 1)', () => {
|
|
112
|
+
const result = getRepomixDirectoryStructure(SAMPLE_XML_WITH_STRUCTURE);
|
|
113
|
+
expect(result).toContain('app/');
|
|
114
|
+
expect(result).toContain('config/');
|
|
115
|
+
expect(result).toContain('package.json');
|
|
116
|
+
expect(result).not.toContain('Header.vue');
|
|
117
|
+
expect(result).not.toContain('pages/');
|
|
118
|
+
});
|
|
119
|
+
it('returns deeper entries when depth is increased', () => {
|
|
120
|
+
const result = getRepomixDirectoryStructure(SAMPLE_XML_WITH_STRUCTURE, { depth: 2 });
|
|
121
|
+
expect(result).toContain('app/');
|
|
122
|
+
expect(result).toContain('components/');
|
|
123
|
+
expect(result).toContain('pages/');
|
|
124
|
+
expect(result).not.toContain('Header.vue');
|
|
125
|
+
});
|
|
126
|
+
it('returns a subtree when path is specified', () => {
|
|
127
|
+
const result = getRepomixDirectoryStructure(SAMPLE_XML_WITH_STRUCTURE, { path: 'app/components', depth: 1 });
|
|
128
|
+
expect(result).toContain('components/');
|
|
129
|
+
expect(result).toContain('Header.vue');
|
|
130
|
+
expect(result).toContain('Footer.vue');
|
|
131
|
+
expect(result).not.toContain('pages/');
|
|
132
|
+
expect(result).not.toContain('config/');
|
|
133
|
+
});
|
|
134
|
+
it('returns null when directory_structure section is missing', () => {
|
|
135
|
+
const result = getRepomixDirectoryStructure('<file path="test.ts">code</file>');
|
|
136
|
+
expect(result).toBeNull();
|
|
137
|
+
});
|
|
138
|
+
it('returns null when path does not exist in tree', () => {
|
|
139
|
+
const result = getRepomixDirectoryStructure(SAMPLE_XML_WITH_STRUCTURE, { path: 'nonexistent' });
|
|
140
|
+
expect(result).toBeNull();
|
|
141
|
+
});
|
|
142
|
+
});
|