@vibe-agent-toolkit/utils 0.1.0 → 0.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore-checker.d.ts","sourceRoot":"","sources":["../src/gitignore-checker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAe,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE7C;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqCnF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAsBxE"}
1
+ {"version":3,"file":"gitignore-checker.d.ts","sourceRoot":"","sources":["../src/gitignore-checker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAe,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAI7C;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwCnF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAsBxE"}
@@ -5,6 +5,7 @@
5
5
  import fs from 'node:fs';
6
6
  import path from 'node:path';
7
7
  import ignore from 'ignore';
8
+ import { toForwardSlash } from './path-utils.js';
8
9
  /**
9
10
  * Find the git repository root by walking up from the given directory.
10
11
  *
@@ -42,7 +43,9 @@ export function loadGitignoreRules(gitRoot, baseDir) {
42
43
  const dirsToCheck = [];
43
44
  let currentDir = path.resolve(baseDir ?? gitRoot);
44
45
  const resolvedGitRoot = path.resolve(gitRoot);
45
- while (currentDir.startsWith(resolvedGitRoot)) {
46
+ // Normalize for cross-platform path comparison
47
+ const normalizedGitRoot = toForwardSlash(resolvedGitRoot);
48
+ while (toForwardSlash(currentDir).startsWith(normalizedGitRoot)) {
46
49
  dirsToCheck.unshift(currentDir);
47
50
  if (currentDir === resolvedGitRoot) {
48
51
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore-checker.js","sourceRoot":"","sources":["../src/gitignore-checker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gitignore-checker.js","sourceRoot":"","sources":["../src/gitignore-checker.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -10,4 +10,5 @@ export * from './fs-utils.js';
10
10
  export * from './file-crawler.js';
11
11
  export * from './gitignore-checker.js';
12
12
  export * from './git-utils.js';
13
+ export * from './test-helpers.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -16,4 +16,6 @@ export * from './file-crawler.js';
16
16
  export * from './gitignore-checker.js';
17
17
  // Git utilities (using git commands directly)
18
18
  export * from './git-utils.js';
19
+ // Test helpers for isolated test output directories
20
+ export * from './test-helpers.js';
19
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC;AAE/B,oDAAoD;AACpD,cAAc,mBAAmB,CAAC"}
@@ -1,20 +1,94 @@
1
+ import { mkdirSync } from 'node:fs';
1
2
  /**
2
- * Normalize a path for cross-platform comparison
3
+ * Normalize any path (resolve short names on Windows)
3
4
  *
4
- * - Converts to absolute path (if baseDir provided)
5
- * - Normalizes separators (/ vs \)
6
- * - Resolves . and ..
7
- * - Removes trailing slashes
5
+ * Resolves Windows 8.3 short names (e.g., RUNNER~1) and symlinks.
6
+ * Accepts multiple path segments like path.resolve() for convenience.
8
7
  *
9
- * @param p - Path to normalize
10
- * @param baseDir - Optional base directory for relative path resolution
11
- * @returns Normalized absolute path
8
+ * **Why this matters:**
9
+ * - Windows may create paths with short names (8.3 format)
10
+ * - Node.js operations may use long names while paths contain short names
11
+ * - This causes path comparison failures and existsSync() issues
12
+ * - realpathSync.native() resolves these to their actual filesystem paths
13
+ *
14
+ * @param paths - Path segments to join and normalize
15
+ * @returns Real (normalized) path, or resolved path if normalization fails
12
16
  *
13
17
  * @example
18
+ * ```typescript
19
+ * // Single path
20
+ * const shortPath = 'C:\\PROGRA~1\\nodejs';
21
+ * const longPath = normalizePath(shortPath);
22
+ * // Result: 'C:\\Program Files\\nodejs'
23
+ *
24
+ * // Multiple segments (like path.resolve)
25
+ * const cliPath = normalizePath(__dirname, '../../dist/bin.js');
26
+ * // Resolves to absolute path AND normalizes short names
27
+ *
28
+ * // Backward compatible with old signature
14
29
  * normalizePath('./docs/../README.md', '/project')
15
- * // Returns: '/project/README.md'
30
+ * // Returns: '/project/README.md' (normalized)
31
+ * ```
32
+ */
33
+ export declare function normalizePath(...paths: string[]): string;
34
+ /**
35
+ * Get normalized temp directory path
36
+ *
37
+ * On Windows, tmpdir() may return 8.3 short names like:
38
+ * - C:\Users\RUNNER~1\AppData\Local\Temp
39
+ *
40
+ * This function returns the real (long) path:
41
+ * - C:\Users\runneradmin\AppData\Local\Temp
42
+ *
43
+ * **Why this matters:**
44
+ * - Node.js operations create directories with LONG names
45
+ * - Tests using SHORT paths from tmpdir() will fail existsSync() checks
46
+ * - This is a "works on Mac, fails on Windows CI" bug pattern
47
+ *
48
+ * @returns Normalized temp directory path (resolves short names on Windows)
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // ❌ WRONG - May return short path on Windows
53
+ * const testDir = join(tmpdir(), 'test-dir');
54
+ *
55
+ * // ✅ RIGHT - Always returns real path
56
+ * const testDir = join(normalizedTmpdir(), 'test-dir');
57
+ * ```
58
+ */
59
+ export declare function normalizedTmpdir(): string;
60
+ /**
61
+ * Create directory and return normalized path
62
+ *
63
+ * Combines mkdirSync + realpathSync to ensure the returned path
64
+ * matches the actual filesystem path (resolves Windows short names).
65
+ *
66
+ * **Why this matters:**
67
+ * - After mkdirSync(), the path might not match what filesystem uses
68
+ * - On Windows, short path input creates long path output
69
+ * - Subsequent existsSync() checks with original path may fail
70
+ *
71
+ * @param path - Directory path to create
72
+ * @param options - Options for mkdirSync (e.g., recursive: true)
73
+ * @returns Real (normalized) path to the created directory
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * // ❌ WRONG - Path mismatch on Windows
78
+ * const testDir = join(tmpdir(), 'test-dir');
79
+ * mkdirSync(testDir, { recursive: true });
80
+ * // testDir might be: C:\Users\RUNNER~1\...\test-dir
81
+ * // But filesystem created: C:\Users\runneradmin\...\test-dir
82
+ *
83
+ * // ✅ RIGHT - Normalized path guaranteed
84
+ * const testDir = mkdirSyncReal(
85
+ * join(tmpdir(), 'test-dir'),
86
+ * { recursive: true }
87
+ * );
88
+ * // testDir is now: C:\Users\runneradmin\...\test-dir (real path)
89
+ * ```
16
90
  */
17
- export declare function normalizePath(p: string, baseDir?: string): string;
91
+ export declare function mkdirSyncReal(dirPath: string, options?: Parameters<typeof mkdirSync>[1]): string;
18
92
  /**
19
93
  * Check if a path is absolute
20
94
  *
@@ -67,21 +141,21 @@ export declare function toAbsolutePath(p: string, baseDir: string): string;
67
141
  */
68
142
  export declare function getRelativePath(from: string, to: string): string;
69
143
  /**
70
- * Convert a path to Unix-style forward slashes
144
+ * Convert a path to forward slashes
71
145
  *
72
- * Useful for glob pattern matching, which expects forward slashes.
73
- * On Windows, path.resolve() and path.normalize() return backslashes,
74
- * but glob matchers like picomatch expect forward slashes by default.
146
+ * Windows accepts both forward slashes and backslashes as path separators.
147
+ * This function normalizes all paths to use forward slashes for consistency.
148
+ * Useful for glob pattern matching, cross-platform comparisons, and string operations.
75
149
  *
76
150
  * @param p - Path to convert
77
151
  * @returns Path with forward slashes
78
152
  *
79
153
  * @example
80
- * toUnixPath('C:\\Users\\docs\\README.md')
154
+ * toForwardSlash('C:\\Users\\docs\\README.md')
81
155
  * // Returns: 'C:/Users/docs/README.md'
82
156
  *
83
- * toUnixPath('/project/docs/README.md')
84
- * // Returns: '/project/docs/README.md' (unchanged on Unix)
157
+ * toForwardSlash('/project/docs/README.md')
158
+ * // Returns: '/project/docs/README.md' (unchanged)
85
159
  */
86
- export declare function toUnixPath(p: string): string;
160
+ export declare function toForwardSlash(p: string): string;
87
161
  //# sourceMappingURL=path-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAWjE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C"}
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,MAAM,SAAS,CAAC;AAIlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CA+BxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAezC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,MAAM,CAiBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -1,30 +1,163 @@
1
+ import { mkdirSync, realpathSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
1
3
  import path from 'node:path';
2
4
  /**
3
- * Normalize a path for cross-platform comparison
5
+ * Normalize any path (resolve short names on Windows)
4
6
  *
5
- * - Converts to absolute path (if baseDir provided)
6
- * - Normalizes separators (/ vs \)
7
- * - Resolves . and ..
8
- * - Removes trailing slashes
7
+ * Resolves Windows 8.3 short names (e.g., RUNNER~1) and symlinks.
8
+ * Accepts multiple path segments like path.resolve() for convenience.
9
9
  *
10
- * @param p - Path to normalize
11
- * @param baseDir - Optional base directory for relative path resolution
12
- * @returns Normalized absolute path
10
+ * **Why this matters:**
11
+ * - Windows may create paths with short names (8.3 format)
12
+ * - Node.js operations may use long names while paths contain short names
13
+ * - This causes path comparison failures and existsSync() issues
14
+ * - realpathSync.native() resolves these to their actual filesystem paths
15
+ *
16
+ * @param paths - Path segments to join and normalize
17
+ * @returns Real (normalized) path, or resolved path if normalization fails
13
18
  *
14
19
  * @example
20
+ * ```typescript
21
+ * // Single path
22
+ * const shortPath = 'C:\\PROGRA~1\\nodejs';
23
+ * const longPath = normalizePath(shortPath);
24
+ * // Result: 'C:\\Program Files\\nodejs'
25
+ *
26
+ * // Multiple segments (like path.resolve)
27
+ * const cliPath = normalizePath(__dirname, '../../dist/bin.js');
28
+ * // Resolves to absolute path AND normalizes short names
29
+ *
30
+ * // Backward compatible with old signature
15
31
  * normalizePath('./docs/../README.md', '/project')
16
- * // Returns: '/project/README.md'
32
+ * // Returns: '/project/README.md' (normalized)
33
+ * ```
34
+ */
35
+ export function normalizePath(...paths) {
36
+ // Handle single relative path without filesystem resolution
37
+ if (paths.length === 1 && paths[0] && !path.isAbsolute(paths[0])) {
38
+ return path.normalize(paths[0]);
39
+ }
40
+ // Resolve to absolute path
41
+ // For 2 args: treat as (relativePath, baseDir) - reverse for path.resolve(baseDir, relativePath)
42
+ // For 3+ args or single absolute: use as-is
43
+ let resolved;
44
+ if (paths.length === 1) {
45
+ resolved = paths[0] ?? '';
46
+ }
47
+ else if (paths.length === 2) {
48
+ resolved = path.resolve(paths[1] ?? '', paths[0] ?? '');
49
+ }
50
+ else {
51
+ resolved = path.resolve(...paths);
52
+ }
53
+ try {
54
+ // Use native OS realpath for better Windows compatibility
55
+ return realpathSync.native(resolved);
56
+ }
57
+ catch {
58
+ // Fallback to regular realpathSync
59
+ try {
60
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- Safe: resolved is from path.resolve
61
+ return realpathSync(resolved);
62
+ }
63
+ catch {
64
+ // Last resort: return resolved path (better than original input)
65
+ return resolved;
66
+ }
67
+ }
68
+ }
69
+ /**
70
+ * Get normalized temp directory path
71
+ *
72
+ * On Windows, tmpdir() may return 8.3 short names like:
73
+ * - C:\Users\RUNNER~1\AppData\Local\Temp
74
+ *
75
+ * This function returns the real (long) path:
76
+ * - C:\Users\runneradmin\AppData\Local\Temp
77
+ *
78
+ * **Why this matters:**
79
+ * - Node.js operations create directories with LONG names
80
+ * - Tests using SHORT paths from tmpdir() will fail existsSync() checks
81
+ * - This is a "works on Mac, fails on Windows CI" bug pattern
82
+ *
83
+ * @returns Normalized temp directory path (resolves short names on Windows)
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // ❌ WRONG - May return short path on Windows
88
+ * const testDir = join(tmpdir(), 'test-dir');
89
+ *
90
+ * // ✅ RIGHT - Always returns real path
91
+ * const testDir = join(normalizedTmpdir(), 'test-dir');
92
+ * ```
17
93
  */
18
- export function normalizePath(p, baseDir) {
19
- // Resolve to absolute if baseDir provided, otherwise just normalize
20
- const resolved = baseDir ? path.resolve(baseDir, p) : path.normalize(p);
21
- // Normalize path separators and remove trailing slashes
22
- // Use simple non-backtracking pattern
23
- let normalized = resolved;
24
- while (normalized.endsWith('/') || normalized.endsWith('\\')) {
25
- normalized = normalized.slice(0, -1);
94
+ export function normalizedTmpdir() {
95
+ const temp = tmpdir();
96
+ try {
97
+ // Use native OS realpath for better Windows compatibility
98
+ return realpathSync.native(temp);
99
+ }
100
+ catch {
101
+ // Fallback to regular realpathSync
102
+ try {
103
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- Safe: temp is from tmpdir()
104
+ return realpathSync(temp);
105
+ }
106
+ catch {
107
+ // Last resort: return original
108
+ return temp;
109
+ }
110
+ }
111
+ }
112
+ /**
113
+ * Create directory and return normalized path
114
+ *
115
+ * Combines mkdirSync + realpathSync to ensure the returned path
116
+ * matches the actual filesystem path (resolves Windows short names).
117
+ *
118
+ * **Why this matters:**
119
+ * - After mkdirSync(), the path might not match what filesystem uses
120
+ * - On Windows, short path input creates long path output
121
+ * - Subsequent existsSync() checks with original path may fail
122
+ *
123
+ * @param path - Directory path to create
124
+ * @param options - Options for mkdirSync (e.g., recursive: true)
125
+ * @returns Real (normalized) path to the created directory
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // ❌ WRONG - Path mismatch on Windows
130
+ * const testDir = join(tmpdir(), 'test-dir');
131
+ * mkdirSync(testDir, { recursive: true });
132
+ * // testDir might be: C:\Users\RUNNER~1\...\test-dir
133
+ * // But filesystem created: C:\Users\runneradmin\...\test-dir
134
+ *
135
+ * // ✅ RIGHT - Normalized path guaranteed
136
+ * const testDir = mkdirSyncReal(
137
+ * join(tmpdir(), 'test-dir'),
138
+ * { recursive: true }
139
+ * );
140
+ * // testDir is now: C:\Users\runneradmin\...\test-dir (real path)
141
+ * ```
142
+ */
143
+ export function mkdirSyncReal(dirPath, options) {
144
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- This IS the mkdirSyncReal() implementation
145
+ mkdirSync(dirPath, options);
146
+ try {
147
+ // Use native OS realpath for better Windows compatibility
148
+ return realpathSync.native(dirPath);
149
+ }
150
+ catch {
151
+ // Fallback to regular realpathSync
152
+ try {
153
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- Safe: dirPath is function parameter
154
+ return realpathSync(dirPath);
155
+ }
156
+ catch {
157
+ // Last resort: return original
158
+ return dirPath;
159
+ }
26
160
  }
27
- return normalized;
28
161
  }
29
162
  /**
30
163
  * Check if a path is absolute
@@ -90,23 +223,23 @@ export function getRelativePath(from, to) {
90
223
  return path.relative(fromDir, to);
91
224
  }
92
225
  /**
93
- * Convert a path to Unix-style forward slashes
226
+ * Convert a path to forward slashes
94
227
  *
95
- * Useful for glob pattern matching, which expects forward slashes.
96
- * On Windows, path.resolve() and path.normalize() return backslashes,
97
- * but glob matchers like picomatch expect forward slashes by default.
228
+ * Windows accepts both forward slashes and backslashes as path separators.
229
+ * This function normalizes all paths to use forward slashes for consistency.
230
+ * Useful for glob pattern matching, cross-platform comparisons, and string operations.
98
231
  *
99
232
  * @param p - Path to convert
100
233
  * @returns Path with forward slashes
101
234
  *
102
235
  * @example
103
- * toUnixPath('C:\\Users\\docs\\README.md')
236
+ * toForwardSlash('C:\\Users\\docs\\README.md')
104
237
  * // Returns: 'C:/Users/docs/README.md'
105
238
  *
106
- * toUnixPath('/project/docs/README.md')
107
- * // Returns: '/project/docs/README.md' (unchanged on Unix)
239
+ * toForwardSlash('/project/docs/README.md')
240
+ * // Returns: '/project/docs/README.md' (unchanged)
108
241
  */
109
- export function toUnixPath(p) {
242
+ export function toForwardSlash(p) {
110
243
  return p.replaceAll('\\', '/');
111
244
  }
112
245
  //# sourceMappingURL=path-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,aAAa,CAAC,CAAS,EAAE,OAAgB;IACvD,oEAAoE;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAExE,wDAAwD;IACxD,sCAAsC;IACtC,IAAI,UAAU,GAAG,QAAQ,CAAC;IAC1B,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS,EAAE,OAAe;IACvD,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,EAAU;IACtD,qDAAqD;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,+DAA+D;IAC/D,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../src/path-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Get isolated test output directory for current test run
3
+ *
4
+ * Creates a unique directory under `packages/{packageName}/.test-output/{testType}/{runId}`
5
+ * where runId is `{timestamp}-{randomId}` to ensure isolation across parallel test runs.
6
+ *
7
+ * @param packageName - Name of package (e.g., 'rag-lancedb')
8
+ * @param testType - Type of test ('unit', 'integration', 'system')
9
+ * @param subdirs - Optional subdirectories to create within the test output directory
10
+ * @returns Absolute path to the created directory
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Create isolated database directory for system tests
15
+ * const dbPath = getTestOutputDir('rag-lancedb', 'system', 'databases', 'test-db');
16
+ * // Result: packages/rag-lancedb/.test-output/system/20260105-143022-abc123/databases/test-db
17
+ *
18
+ * // Create temporary file directory for integration tests
19
+ * const tempDir = getTestOutputDir('runtime-claude-skills', 'integration', 'temp-files');
20
+ * // Result: packages/runtime-claude-skills/.test-output/integration/20260105-143022-def456/temp-files
21
+ * ```
22
+ */
23
+ export declare function getTestOutputDir(packageName: string, testType: 'unit' | 'integration' | 'system', ...subdirs: string[]): string;
24
+ /**
25
+ * Get the base test output directory for a package
26
+ * Useful for cleanup operations that need to remove all test output
27
+ *
28
+ * @param packageName - Name of package (e.g., 'rag-lancedb')
29
+ * @returns Absolute path to packages/{packageName}/.test-output
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const baseDir = getTestOutputBase('rag-lancedb');
34
+ * // Result: packages/rag-lancedb/.test-output
35
+ * ```
36
+ */
37
+ export declare function getTestOutputBase(packageName: string): string;
38
+ //# sourceMappingURL=test-helpers.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,55 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { join, resolve } from 'node:path';
3
+ import { mkdirSyncReal } from './path-utils.js';
4
+ /**
5
+ * Get isolated test output directory for current test run
6
+ *
7
+ * Creates a unique directory under `packages/{packageName}/.test-output/{testType}/{runId}`
8
+ * where runId is `{timestamp}-{randomId}` to ensure isolation across parallel test runs.
9
+ *
10
+ * @param packageName - Name of package (e.g., 'rag-lancedb')
11
+ * @param testType - Type of test ('unit', 'integration', 'system')
12
+ * @param subdirs - Optional subdirectories to create within the test output directory
13
+ * @returns Absolute path to the created directory
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Create isolated database directory for system tests
18
+ * const dbPath = getTestOutputDir('rag-lancedb', 'system', 'databases', 'test-db');
19
+ * // Result: packages/rag-lancedb/.test-output/system/20260105-143022-abc123/databases/test-db
20
+ *
21
+ * // Create temporary file directory for integration tests
22
+ * const tempDir = getTestOutputDir('runtime-claude-skills', 'integration', 'temp-files');
23
+ * // Result: packages/runtime-claude-skills/.test-output/integration/20260105-143022-def456/temp-files
24
+ * ```
25
+ */
26
+ export function getTestOutputDir(packageName, testType, ...subdirs) {
27
+ // Generate unique run ID: timestamp + random hex
28
+ const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-').slice(0, 19);
29
+ const randomId = randomBytes(4).toString('hex');
30
+ const runId = `${timestamp}-${randomId}`;
31
+ // Find project root (assuming we're always in packages/*/test/*)
32
+ const projectRoot = resolve(process.cwd());
33
+ // Build path: packages/{packageName}/.test-output/{testType}/{runId}/{...subdirs}
34
+ const testOutputDir = join(projectRoot, 'packages', packageName, '.test-output', testType, runId, ...subdirs);
35
+ // Create directory structure and return normalized path
36
+ return mkdirSyncReal(testOutputDir, { recursive: true });
37
+ }
38
+ /**
39
+ * Get the base test output directory for a package
40
+ * Useful for cleanup operations that need to remove all test output
41
+ *
42
+ * @param packageName - Name of package (e.g., 'rag-lancedb')
43
+ * @returns Absolute path to packages/{packageName}/.test-output
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const baseDir = getTestOutputBase('rag-lancedb');
48
+ * // Result: packages/rag-lancedb/.test-output
49
+ * ```
50
+ */
51
+ export function getTestOutputBase(packageName) {
52
+ const projectRoot = resolve(process.cwd());
53
+ return join(projectRoot, 'packages', packageName, '.test-output');
54
+ }
55
+ //# sourceMappingURL=test-helpers.js.map
@@ -0,0 +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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-agent-toolkit/utils",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Core utility functions with no external dependencies",
6
6
  "keywords": [