@vibe-agent-toolkit/utils 0.1.9 → 0.1.11

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.
@@ -37,9 +37,32 @@ export declare function gitLsFiles(options: {
37
37
  *
38
38
  * Uses git check-ignore which respects .gitignore, .git/info/exclude, and global gitignore
39
39
  *
40
+ * **Performance warning**: This spawns a git subprocess for each file.
41
+ * For checking multiple files, use `gitCheckIgnoredBatch()` instead.
42
+ *
40
43
  * @param filePath - Absolute or relative path to check
41
44
  * @param cwd - Working directory (defaults to process.cwd())
42
45
  * @returns true if file is gitignored, false otherwise
43
46
  */
44
47
  export declare function isGitIgnored(filePath: string, cwd?: string): boolean;
48
+ /**
49
+ * Batch check if multiple file paths are ignored by git
50
+ *
51
+ * Much more efficient than calling `isGitIgnored()` in a loop - uses a single
52
+ * git subprocess with stdin instead of N subprocesses.
53
+ *
54
+ * @param filePaths - Array of absolute or relative paths to check
55
+ * @param cwd - Working directory (defaults to process.cwd())
56
+ * @returns Map of filePath -> isIgnored (true if gitignored, false otherwise)
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const files = ['src/foo.ts', 'dist/bar.js', 'node_modules/baz.js'];
61
+ * const ignoreMap = gitCheckIgnoredBatch(files, '/project');
62
+ * // ignoreMap.get('src/foo.ts') === false
63
+ * // ignoreMap.get('dist/bar.js') === true
64
+ * // ignoreMap.get('node_modules/baz.js') === true
65
+ * ```
66
+ */
67
+ export declare function gitCheckIgnoredBatch(filePaths: string[], cwd?: string): Map<string, boolean>;
45
68
  //# sourceMappingURL=git-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-utils.d.ts","sourceRoot":"","sources":["../src/git-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,MAAM,EAAE,GAAG,IAAI,CA0ClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAkBnF"}
1
+ {"version":3,"file":"git-utils.d.ts","sourceRoot":"","sources":["../src/git-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,MAAM,EAAE,GAAG,IAAI,CA0ClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAkBnF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EAAE,EACnB,GAAG,GAAE,MAAsB,GAC1B,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CA8DtB"}
package/dist/git-utils.js CHANGED
@@ -6,6 +6,7 @@ import { spawnSync } from 'node:child_process';
6
6
  import { existsSync } from 'node:fs';
7
7
  import { dirname, join, parse, resolve } from 'node:path';
8
8
  import which from 'which';
9
+ import { toForwardSlash } from './path-utils.js';
9
10
  /**
10
11
  * Find the git repository root by walking up from the given directory.
11
12
  *
@@ -85,6 +86,9 @@ export function gitLsFiles(options) {
85
86
  *
86
87
  * Uses git check-ignore which respects .gitignore, .git/info/exclude, and global gitignore
87
88
  *
89
+ * **Performance warning**: This spawns a git subprocess for each file.
90
+ * For checking multiple files, use `gitCheckIgnoredBatch()` instead.
91
+ *
88
92
  * @param filePath - Absolute or relative path to check
89
93
  * @param cwd - Working directory (defaults to process.cwd())
90
94
  * @returns true if file is gitignored, false otherwise
@@ -107,4 +111,78 @@ export function isGitIgnored(filePath, cwd = process.cwd()) {
107
111
  return false;
108
112
  }
109
113
  }
114
+ /**
115
+ * Batch check if multiple file paths are ignored by git
116
+ *
117
+ * Much more efficient than calling `isGitIgnored()` in a loop - uses a single
118
+ * git subprocess with stdin instead of N subprocesses.
119
+ *
120
+ * @param filePaths - Array of absolute or relative paths to check
121
+ * @param cwd - Working directory (defaults to process.cwd())
122
+ * @returns Map of filePath -> isIgnored (true if gitignored, false otherwise)
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const files = ['src/foo.ts', 'dist/bar.js', 'node_modules/baz.js'];
127
+ * const ignoreMap = gitCheckIgnoredBatch(files, '/project');
128
+ * // ignoreMap.get('src/foo.ts') === false
129
+ * // ignoreMap.get('dist/bar.js') === true
130
+ * // ignoreMap.get('node_modules/baz.js') === true
131
+ * ```
132
+ */
133
+ export function gitCheckIgnoredBatch(filePaths, cwd = process.cwd()) {
134
+ const result = new Map();
135
+ // No files to check
136
+ if (filePaths.length === 0) {
137
+ return result;
138
+ }
139
+ // Normalize paths to forward slashes for cross-platform consistency
140
+ // Git on Windows returns forward slashes, so we normalize input paths to match
141
+ const normalizedPaths = filePaths.map(p => toForwardSlash(p));
142
+ // Create map with normalized paths as keys
143
+ const pathMap = new Map(); // normalized -> original
144
+ for (const [index, normalizedPath] of normalizedPaths.entries()) {
145
+ const originalPath = filePaths[index];
146
+ if (originalPath !== undefined) {
147
+ pathMap.set(normalizedPath, originalPath);
148
+ }
149
+ }
150
+ // Initialize all as not ignored (using original paths as keys)
151
+ for (const filePath of filePaths) {
152
+ result.set(filePath, false);
153
+ }
154
+ try {
155
+ // Resolve git path using which for security (avoids PATH manipulation)
156
+ const gitPath = which.sync('git');
157
+ // git check-ignore --stdin reads paths from stdin and outputs ignored ones
158
+ // Send normalized paths to git
159
+ const gitResult = spawnSync(gitPath, ['check-ignore', '--stdin'], {
160
+ cwd,
161
+ encoding: 'utf-8',
162
+ input: normalizedPaths.join('\n'),
163
+ stdio: 'pipe',
164
+ shell: false, // No shell interpreter for security
165
+ });
166
+ // Exit code 0 = at least one file ignored, 1 = none ignored
167
+ // Parse stdout to get which files are ignored
168
+ if (gitResult.status === 0 && gitResult.stdout) {
169
+ const ignoredPaths = gitResult.stdout
170
+ .split('\n')
171
+ .map((line) => line.trim())
172
+ .filter((line) => line.length > 0);
173
+ // Mark ignored files (convert back to original paths)
174
+ for (const ignoredPath of ignoredPaths) {
175
+ const originalPath = pathMap.get(ignoredPath);
176
+ if (originalPath !== undefined) {
177
+ result.set(originalPath, true);
178
+ }
179
+ }
180
+ }
181
+ return result;
182
+ }
183
+ catch {
184
+ // If git is not available or other error, return all as not ignored
185
+ return result;
186
+ }
187
+ }
110
188
  //# sourceMappingURL=git-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-utils.js","sourceRoot":"","sources":["../src/git-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,IAAI,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAEpC,OAAO,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACxC,yGAAyG;QACzG,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,UAAU,CAAC,OAI1B;IACC,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAE1B,iDAAiD;QACjD,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAC1D,CAAC;QAED,2BAA2B;QAC3B,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;YACtC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,KAAK,EAAE,oCAAoC;SACnD,CAAC,CAAC;QAEH,qDAAqD;QACrD,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wCAAwC;QACxC,OAAO,MAAM,CAAC,MAAM;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACxE,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElC,oEAAoE;QACpE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE;YAClE,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,KAAK,EAAE,oCAAoC;SACnD,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"git-utils.js","sourceRoot":"","sources":["../src/git-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,IAAI,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;IAEpC,OAAO,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACxC,yGAAyG;QACzG,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,UAAU,CAAC,OAI1B;IACC,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAE1B,iDAAiD;QACjD,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAC1D,CAAC;QAED,2BAA2B;QAC3B,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;YACtC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,KAAK,EAAE,oCAAoC;SACnD,CAAC,CAAC;QAEH,qDAAqD;QACrD,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wCAAwC;QACxC,OAAO,MAAM,CAAC,MAAM;aACjB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACxE,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElC,oEAAoE;QACpE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE;YAClE,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,KAAK,EAAE,oCAAoC;SACnD,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAAmB,EACnB,MAAc,OAAO,CAAC,GAAG,EAAE;IAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmB,CAAC;IAE1C,oBAAoB;IACpB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,oEAAoE;IACpE,+EAA+E;IAC/E,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,2CAA2C;IAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,yBAAyB;IACpE,KAAK,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;QAChE,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC;QACH,uEAAuE;QACvE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElC,2EAA2E;QAC3E,+BAA+B;QAC/B,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC,EAAE;YAChE,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;YACjC,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,KAAK,EAAE,oCAAoC;SACnD,CAAC,CAAC;QAEH,4DAA4D;QAC5D,8CAA8C;QAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YAC/C,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM;iBAClC,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;iBAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAErC,sDAAsD;YACtD,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;gBACvC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBAC9C,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;oBAC/B,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -35,4 +35,68 @@ export declare function getTestOutputDir(packageName: string, testType: 'unit' |
35
35
  * ```
36
36
  */
37
37
  export declare function getTestOutputBase(packageName: string): string;
38
+ /**
39
+ * Per-suite temp directory pattern (async version)
40
+ * Creates a single temp directory for the entire test suite,
41
+ * with subdirectories for each test. This is 3-5x faster on Windows
42
+ * than creating a new mkdtemp for each test.
43
+ *
44
+ * @param prefix - Prefix for the suite temp directory name
45
+ * @returns Suite helper with beforeAll, afterAll, beforeEach, afterEach, and getTempDir
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const suite = setupAsyncTempDirSuite('my-test');
50
+ *
51
+ * describe('my tests', () => {
52
+ * beforeAll(suite.beforeAll);
53
+ * afterAll(suite.afterAll);
54
+ * beforeEach(suite.beforeEach);
55
+ *
56
+ * it('test 1', async () => {
57
+ * const tempDir = suite.getTempDir();
58
+ * // Use tempDir...
59
+ * });
60
+ * });
61
+ * ```
62
+ */
63
+ export declare function setupAsyncTempDirSuite(prefix: string): {
64
+ beforeAll: () => Promise<void>;
65
+ afterAll: () => Promise<void>;
66
+ beforeEach: () => Promise<void>;
67
+ afterEach: () => Promise<void>;
68
+ getTempDir: () => string;
69
+ };
70
+ /**
71
+ * Per-suite temp directory pattern (sync version)
72
+ * Creates a single temp directory for the entire test suite,
73
+ * with subdirectories for each test. This is 3-5x faster on Windows
74
+ * than creating a new mkdtemp for each test.
75
+ *
76
+ * @param prefix - Prefix for the suite temp directory name
77
+ * @returns Suite helper with beforeAll, afterAll, beforeEach, afterEach, and getTempDir
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const suite = setupSyncTempDirSuite('my-test');
82
+ *
83
+ * describe('my tests', () => {
84
+ * beforeAll(suite.beforeAll);
85
+ * afterAll(suite.afterAll);
86
+ * beforeEach(suite.beforeEach);
87
+ *
88
+ * it('test 1', () => {
89
+ * const tempDir = suite.getTempDir();
90
+ * // Use tempDir...
91
+ * });
92
+ * });
93
+ * ```
94
+ */
95
+ export declare function setupSyncTempDirSuite(prefix: string): {
96
+ beforeAll: () => void;
97
+ afterAll: () => void;
98
+ beforeEach: () => void;
99
+ afterEach: () => void;
100
+ getTempDir: () => string;
101
+ };
38
102
  //# sourceMappingURL=test-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,EAC3C,GAAG,OAAO,EAAE,MAAM,EAAE,GACnB,MAAM,CAuBR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAG7D"}
1
+ {"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,EAC3C,GAAG,OAAO,EAAE,MAAM,EAAE,GACnB,MAAM,CAuBR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG;IACtD,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,MAAM,CAAC;CAC1B,CAyBA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG;IACrD,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,MAAM,CAAC;CAC1B,CAwBA"}
@@ -1,6 +1,8 @@
1
1
  import { randomBytes } from 'node:crypto';
2
+ import { mkdtempSync, rmSync } from 'node:fs';
3
+ import fs from 'node:fs/promises';
2
4
  import { join, resolve } from 'node:path';
3
- import { mkdirSyncReal } from './path-utils.js';
5
+ import { mkdirSyncReal, normalizedTmpdir } from './path-utils.js';
4
6
  /**
5
7
  * Get isolated test output directory for current test run
6
8
  *
@@ -52,4 +54,103 @@ export function getTestOutputBase(packageName) {
52
54
  const projectRoot = resolve(process.cwd());
53
55
  return join(projectRoot, 'packages', packageName, '.test-output');
54
56
  }
57
+ /**
58
+ * Per-suite temp directory pattern (async version)
59
+ * Creates a single temp directory for the entire test suite,
60
+ * with subdirectories for each test. This is 3-5x faster on Windows
61
+ * than creating a new mkdtemp for each test.
62
+ *
63
+ * @param prefix - Prefix for the suite temp directory name
64
+ * @returns Suite helper with beforeAll, afterAll, beforeEach, afterEach, and getTempDir
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const suite = setupAsyncTempDirSuite('my-test');
69
+ *
70
+ * describe('my tests', () => {
71
+ * beforeAll(suite.beforeAll);
72
+ * afterAll(suite.afterAll);
73
+ * beforeEach(suite.beforeEach);
74
+ *
75
+ * it('test 1', async () => {
76
+ * const tempDir = suite.getTempDir();
77
+ * // Use tempDir...
78
+ * });
79
+ * });
80
+ * ```
81
+ */
82
+ export function setupAsyncTempDirSuite(prefix) {
83
+ let suiteDir = '';
84
+ let tempDir = '';
85
+ let testCounter = 0;
86
+ return {
87
+ beforeAll: async () => {
88
+ suiteDir = await fs.mkdtemp(join(normalizedTmpdir(), `${prefix}-suite-`));
89
+ },
90
+ afterAll: async () => {
91
+ if (suiteDir) {
92
+ await fs.rm(suiteDir, { recursive: true, force: true });
93
+ }
94
+ },
95
+ beforeEach: async () => {
96
+ testCounter++;
97
+ tempDir = join(suiteDir, `test-${testCounter}`);
98
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- tempDir is from mkdtemp
99
+ await fs.mkdir(tempDir, { recursive: true });
100
+ },
101
+ afterEach: async () => {
102
+ // Per-test cleanup handled by suite cleanup
103
+ },
104
+ getTempDir: () => tempDir,
105
+ };
106
+ }
107
+ /**
108
+ * Per-suite temp directory pattern (sync version)
109
+ * Creates a single temp directory for the entire test suite,
110
+ * with subdirectories for each test. This is 3-5x faster on Windows
111
+ * than creating a new mkdtemp for each test.
112
+ *
113
+ * @param prefix - Prefix for the suite temp directory name
114
+ * @returns Suite helper with beforeAll, afterAll, beforeEach, afterEach, and getTempDir
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const suite = setupSyncTempDirSuite('my-test');
119
+ *
120
+ * describe('my tests', () => {
121
+ * beforeAll(suite.beforeAll);
122
+ * afterAll(suite.afterAll);
123
+ * beforeEach(suite.beforeEach);
124
+ *
125
+ * it('test 1', () => {
126
+ * const tempDir = suite.getTempDir();
127
+ * // Use tempDir...
128
+ * });
129
+ * });
130
+ * ```
131
+ */
132
+ export function setupSyncTempDirSuite(prefix) {
133
+ let suiteDir = '';
134
+ let tempDir = '';
135
+ let testCounter = 0;
136
+ return {
137
+ beforeAll: () => {
138
+ suiteDir = mkdtempSync(join(normalizedTmpdir(), `${prefix}-suite-`));
139
+ },
140
+ afterAll: () => {
141
+ if (suiteDir) {
142
+ rmSync(suiteDir, { recursive: true, force: true });
143
+ }
144
+ },
145
+ beforeEach: () => {
146
+ testCounter++;
147
+ tempDir = join(suiteDir, `test-${testCounter}`);
148
+ mkdirSyncReal(tempDir);
149
+ },
150
+ afterEach: () => {
151
+ // Per-test cleanup handled by suite cleanup
152
+ },
153
+ getTempDir: () => tempDir,
154
+ };
155
+ }
55
156
  //# sourceMappingURL=test-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,QAA2C,EAC3C,GAAG,OAAiB;IAEpB,iDAAiD;IACjD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC;IAEzC,iEAAiE;IACjE,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAE3C,kFAAkF;IAClF,MAAM,aAAa,GAAG,IAAI,CACxB,WAAW,EACX,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,KAAK,EACL,GAAG,OAAO,CACX,CAAC;IAEF,wDAAwD;IAExD,OAAO,aAAa,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-agent-toolkit/utils",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "description": "Core utility functions with no external dependencies",
6
6
  "keywords": [