@holoscript/std 3.1.1 → 7.0.0
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.
- package/LICENSE +21 -0
- package/dist/__tests__/EconomicPrimitives.test.d.ts +2 -0
- package/dist/__tests__/EconomicTraits.test.d.ts +2 -0
- package/dist/__tests__/SimulationLabPrimitives.test.d.ts +2 -0
- package/dist/__tests__/collections.test.d.ts +2 -0
- package/dist/__tests__/events.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/materials.test.d.ts +2 -0
- package/dist/__tests__/math.test.d.ts +2 -0
- package/dist/__tests__/physics.test.d.ts +2 -0
- package/dist/__tests__/spatial.test.d.ts +2 -0
- package/dist/__tests__/standard-library-fundamentals.test.d.ts +2 -0
- package/dist/__tests__/standard-library-fundamentals.test.d.ts.map +1 -0
- package/dist/__tests__/string-and-time-utilities.test.d.ts +2 -0
- package/dist/__tests__/string-and-time-utilities.test.d.ts.map +1 -0
- package/dist/__tests__/string-decoupled.test.d.ts +2 -0
- package/dist/__tests__/string.test.d.ts +2 -0
- package/dist/__tests__/time.test.d.ts +2 -0
- package/dist/chunk-DZHAVOCH.js +686 -0
- package/dist/chunk-DZHAVOCH.js.map +1 -0
- package/dist/chunk-P4O3WNG2.js +287 -0
- package/dist/chunk-P4O3WNG2.js.map +1 -0
- package/dist/chunk-PFX2JM4X.js +683 -0
- package/dist/chunk-PFX2JM4X.js.map +1 -0
- package/dist/chunk-PR4QN5HX.js +43 -0
- package/dist/chunk-PR4QN5HX.js.map +1 -0
- package/dist/chunk-WS6W35YC.js +443 -0
- package/dist/chunk-WS6W35YC.js.map +1 -0
- package/dist/chunk-XBA4ARST.js +9313 -0
- package/dist/chunk-XBA4ARST.js.map +1 -0
- package/dist/chunk-XJIFG7G3.js +348 -0
- package/dist/chunk-XJIFG7G3.js.map +1 -0
- package/dist/chunk-ZXVZAQCZ.js +470 -0
- package/dist/chunk-ZXVZAQCZ.js.map +1 -0
- package/dist/collections.cjs +715 -0
- package/dist/collections.cjs.map +1 -0
- package/dist/collections.d.ts +177 -0
- package/dist/collections.js +18 -0
- package/dist/collections.js.map +1 -0
- package/dist/events.d.ts +32 -0
- package/dist/fs/__tests__/file-watch-system.test.d.ts +2 -0
- package/dist/fs/__tests__/file-watch-system.test.d.ts.map +1 -0
- package/dist/fs/__tests__/path-utilities.test.d.ts +2 -0
- package/dist/fs/__tests__/path-utilities.test.d.ts.map +1 -0
- package/dist/fs/__tests__/path.test.d.ts +2 -0
- package/dist/fs/__tests__/path.test.d.ts.map +1 -0
- package/dist/fs/fs.d.ts +288 -0
- package/dist/fs/fs.d.ts.map +1 -0
- package/dist/fs/index.cjs +9338 -0
- package/dist/fs/index.cjs.map +1 -0
- package/dist/fs/index.d.ts +51 -0
- package/dist/fs/index.d.ts.map +1 -0
- package/dist/fs/index.js +204 -0
- package/dist/fs/index.js.map +1 -0
- package/dist/fs/path.d.ts +135 -0
- package/dist/fs/path.d.ts.map +1 -0
- package/dist/fs/watch.d.ts +133 -0
- package/dist/fs/watch.d.ts.map +1 -0
- package/dist/index.cjs +13326 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1275 -190
- package/dist/index.js.map +1 -0
- package/dist/materials.d.ts +50 -0
- package/dist/math.cjs +595 -0
- package/dist/math.cjs.map +1 -0
- package/dist/math.d.ts +162 -0
- package/dist/math.js +54 -0
- package/dist/math.js.map +1 -0
- package/dist/physics.d.ts +59 -0
- package/dist/spatial.d.ts +82 -0
- package/dist/string.basic.test.d.ts +5 -0
- package/dist/string.basic.test.d.ts.map +1 -0
- package/dist/string.cjs +422 -0
- package/dist/string.cjs.map +1 -0
- package/dist/string.d.ts +212 -0
- package/dist/string.d.ts.map +1 -1
- package/dist/string.js +108 -0
- package/dist/string.js.map +1 -0
- package/dist/string.test.d.ts +5 -0
- package/dist/string.test.d.ts.map +1 -0
- package/dist/time.cjs +512 -0
- package/dist/time.cjs.map +1 -0
- package/dist/time.d.ts +215 -0
- package/dist/time.js +44 -0
- package/dist/time.js.map +1 -0
- package/dist/traits/ARTraits.d.ts +14 -0
- package/dist/traits/EconomicPrimitives.cjs +335 -0
- package/dist/traits/EconomicPrimitives.cjs.map +1 -0
- package/dist/traits/EconomicPrimitives.d.ts +345 -0
- package/dist/traits/EconomicPrimitives.js +56 -0
- package/dist/traits/EconomicPrimitives.js.map +1 -0
- package/dist/traits/EconomicTraits.cjs +471 -0
- package/dist/traits/EconomicTraits.cjs.map +1 -0
- package/dist/traits/EconomicTraits.d.ts +71 -0
- package/dist/traits/EconomicTraits.js +18 -0
- package/dist/traits/EconomicTraits.js.map +1 -0
- package/dist/traits/IoTTraits.d.ts +14 -0
- package/dist/traits/SimulationLabPrimitives.d.ts +187 -0
- package/dist/traits/SimulationLabTraits.d.ts +42 -0
- package/dist/traits/VRRTraits.d.ts +150 -0
- package/dist/traits/__tests__/ARTraits.test.d.ts +2 -0
- package/dist/traits/__tests__/ARTraits.test.d.ts.map +1 -0
- package/dist/traits/__tests__/EconomicPrimitives.test.d.ts +2 -0
- package/dist/traits/__tests__/EconomicPrimitives.test.d.ts.map +1 -0
- package/dist/traits/__tests__/EconomicTraits.test.d.ts +2 -0
- package/dist/traits/__tests__/EconomicTraits.test.d.ts.map +1 -0
- package/dist/types.d.ts +202 -0
- package/dist/types.d.ts.map +1 -1
- package/error-utf8.log +6 -0
- package/error.log +0 -0
- package/package.json +35 -18
- package/src/__tests__/index.test.ts +14 -0
- package/src/__tests__/{Sprint33.test.ts → standard-library-fundamentals.test.ts} +91 -74
- package/src/__tests__/{Sprint56.test.ts → string-and-time-utilities.test.ts} +64 -64
- package/src/__tests__/string-decoupled.test.ts +6 -9
- package/src/fs/__tests__/file-watch-system.test.ts +675 -0
- package/src/fs/__tests__/path-utilities.test.ts +375 -0
- package/src/fs/__tests__/path.test.ts +287 -0
- package/src/fs/fs.ts +692 -0
- package/src/fs/index.ts +194 -0
- package/src/fs/path.ts +310 -0
- package/src/fs/watch.ts +413 -0
- package/src/index.ts +3 -1
- package/src/math.ts +1 -1
- package/src/string.basic.test.ts +1 -1
- package/src/string.test.ts +4 -4
- package/src/string.ts +32 -17
- package/src/time.ts +1 -1
- package/src/traits/ARTraits.ts +2 -2
- package/src/traits/IoTTraits.ts +2 -2
- package/src/traits/VRRTraits.ts +2 -2
- package/src/traits/__tests__/ARTraits.test.ts +8 -0
- package/src/traits/__tests__/EconomicPrimitives.test.ts +14 -0
- package/src/traits/__tests__/EconomicTraits.test.ts +16 -0
- package/src/types.ts +10 -3
- package/std_error.log +5 -0
- package/tsup.config.ts +20 -0
- package/dist/__tests__/Sprint33.test.d.ts.map +0 -1
- package/dist/__tests__/Sprint56.test.d.ts.map +0 -1
package/src/fs/index.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/fs - File System Library for HoloScript Plus
|
|
3
|
+
*
|
|
4
|
+
* Provides file I/O, directory operations, path manipulation,
|
|
5
|
+
* and file watching for HoloScript Plus programs.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```hsplus
|
|
9
|
+
* import { readText, writeText, watch } from "@holoscript/fs";
|
|
10
|
+
* import { join } from "@holoscript/fs/path";
|
|
11
|
+
*
|
|
12
|
+
* async fn main() {
|
|
13
|
+
* // Read a config file
|
|
14
|
+
* let config = await readJson("config.json");
|
|
15
|
+
*
|
|
16
|
+
* // Watch for changes
|
|
17
|
+
* let watcher = watch("./src", { debounce: 100 });
|
|
18
|
+
* watcher.on("change", fn(event) {
|
|
19
|
+
* print("File changed:", event.path);
|
|
20
|
+
* });
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// File operations
|
|
26
|
+
export {
|
|
27
|
+
// Types
|
|
28
|
+
type Encoding,
|
|
29
|
+
type FileStats,
|
|
30
|
+
type DirEntry,
|
|
31
|
+
type ReadOptions,
|
|
32
|
+
type WriteOptions,
|
|
33
|
+
type CopyOptions,
|
|
34
|
+
|
|
35
|
+
// Reading
|
|
36
|
+
readText,
|
|
37
|
+
readTextSync,
|
|
38
|
+
readBytes,
|
|
39
|
+
readBytesSync,
|
|
40
|
+
readJson,
|
|
41
|
+
readJsonSync,
|
|
42
|
+
readLines,
|
|
43
|
+
readLinesSync,
|
|
44
|
+
|
|
45
|
+
// Writing
|
|
46
|
+
writeText,
|
|
47
|
+
writeTextSync,
|
|
48
|
+
writeBytes,
|
|
49
|
+
writeBytesSync,
|
|
50
|
+
writeJson,
|
|
51
|
+
writeJsonSync,
|
|
52
|
+
appendText,
|
|
53
|
+
appendTextSync,
|
|
54
|
+
appendLine,
|
|
55
|
+
appendLineSync,
|
|
56
|
+
|
|
57
|
+
// File/Directory operations
|
|
58
|
+
exists,
|
|
59
|
+
existsSync,
|
|
60
|
+
isFile,
|
|
61
|
+
isFileSync,
|
|
62
|
+
isDirectory,
|
|
63
|
+
isDirectorySync,
|
|
64
|
+
stat,
|
|
65
|
+
statSync,
|
|
66
|
+
mkdir,
|
|
67
|
+
mkdirSync,
|
|
68
|
+
ensureDir,
|
|
69
|
+
ensureDirSync,
|
|
70
|
+
ensureFile,
|
|
71
|
+
ensureFileSync,
|
|
72
|
+
remove,
|
|
73
|
+
removeSync,
|
|
74
|
+
copy,
|
|
75
|
+
copySync,
|
|
76
|
+
move,
|
|
77
|
+
moveSync,
|
|
78
|
+
|
|
79
|
+
// Directory reading
|
|
80
|
+
readDir,
|
|
81
|
+
readDirSync,
|
|
82
|
+
listFiles,
|
|
83
|
+
listFilesSync,
|
|
84
|
+
listDirs,
|
|
85
|
+
listDirsSync,
|
|
86
|
+
walk,
|
|
87
|
+
glob,
|
|
88
|
+
globSync,
|
|
89
|
+
|
|
90
|
+
// Temp files
|
|
91
|
+
tempDir,
|
|
92
|
+
createTempFile,
|
|
93
|
+
createTempDir,
|
|
94
|
+
|
|
95
|
+
// Size utilities
|
|
96
|
+
fileSize,
|
|
97
|
+
fileSizeSync,
|
|
98
|
+
dirSize,
|
|
99
|
+
formatSize,
|
|
100
|
+
} from './fs.js';
|
|
101
|
+
|
|
102
|
+
// Path utilities
|
|
103
|
+
export {
|
|
104
|
+
sep,
|
|
105
|
+
delimiter,
|
|
106
|
+
join,
|
|
107
|
+
resolve,
|
|
108
|
+
relative,
|
|
109
|
+
normalize,
|
|
110
|
+
isAbsolute,
|
|
111
|
+
dirname,
|
|
112
|
+
basename,
|
|
113
|
+
extname,
|
|
114
|
+
type ParsedPath,
|
|
115
|
+
parse,
|
|
116
|
+
format,
|
|
117
|
+
toPosix,
|
|
118
|
+
toWindows,
|
|
119
|
+
parent,
|
|
120
|
+
segments,
|
|
121
|
+
hasExtension,
|
|
122
|
+
changeExtension,
|
|
123
|
+
removeExtension,
|
|
124
|
+
addSuffix,
|
|
125
|
+
isChildOf,
|
|
126
|
+
commonBase,
|
|
127
|
+
expandHome,
|
|
128
|
+
sanitize,
|
|
129
|
+
matchesPattern,
|
|
130
|
+
PathBuilder,
|
|
131
|
+
path,
|
|
132
|
+
} from './path.js';
|
|
133
|
+
|
|
134
|
+
// Watch utilities
|
|
135
|
+
export {
|
|
136
|
+
type WatchEventType,
|
|
137
|
+
type WatchEvent,
|
|
138
|
+
type WatchOptions,
|
|
139
|
+
type WatchCallback,
|
|
140
|
+
FileWatcher,
|
|
141
|
+
watch,
|
|
142
|
+
watchCallback,
|
|
143
|
+
watchFileTypes,
|
|
144
|
+
watchFile,
|
|
145
|
+
watchDebounced,
|
|
146
|
+
watchOnce,
|
|
147
|
+
watchBatched,
|
|
148
|
+
watchFiltered,
|
|
149
|
+
watchEvents,
|
|
150
|
+
watchFiles,
|
|
151
|
+
watchDirs,
|
|
152
|
+
} from './watch.js';
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Convenience: Get current working directory
|
|
156
|
+
*/
|
|
157
|
+
export function cwd(): string {
|
|
158
|
+
return process.cwd();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Convenience: Change current working directory
|
|
163
|
+
*/
|
|
164
|
+
export function chdir(path: string): void {
|
|
165
|
+
process.chdir(path);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Convenience: Get home directory
|
|
170
|
+
*/
|
|
171
|
+
export function homeDir(): string {
|
|
172
|
+
return require('os').homedir();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Convenience: Check if running on Windows
|
|
177
|
+
*/
|
|
178
|
+
export function isWindows(): boolean {
|
|
179
|
+
return process.platform === 'win32';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Convenience: Check if running on macOS
|
|
184
|
+
*/
|
|
185
|
+
export function isMacOS(): boolean {
|
|
186
|
+
return process.platform === 'darwin';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Convenience: Check if running on Linux
|
|
191
|
+
*/
|
|
192
|
+
export function isLinux(): boolean {
|
|
193
|
+
return process.platform === 'linux';
|
|
194
|
+
}
|
package/src/fs/path.ts
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/fs - Path Module
|
|
3
|
+
*
|
|
4
|
+
* Cross-platform path manipulation utilities for HoloScript Plus.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as nodePath from 'path';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Path separator for the current platform
|
|
11
|
+
*/
|
|
12
|
+
export const sep = nodePath.sep;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Path delimiter for environment variables
|
|
16
|
+
*/
|
|
17
|
+
export const delimiter = nodePath.delimiter;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Join path segments
|
|
21
|
+
*/
|
|
22
|
+
export function join(...paths: string[]): string {
|
|
23
|
+
return nodePath.join(...paths);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve path segments to an absolute path
|
|
28
|
+
*/
|
|
29
|
+
export function resolve(...paths: string[]): string {
|
|
30
|
+
return nodePath.resolve(...paths);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get the relative path from one path to another
|
|
35
|
+
*/
|
|
36
|
+
export function relative(from: string, to: string): string {
|
|
37
|
+
return nodePath.relative(from, to);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Normalize a path (resolve . and .. segments)
|
|
42
|
+
*/
|
|
43
|
+
export function normalize(p: string): string {
|
|
44
|
+
return nodePath.normalize(p);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if a path is absolute
|
|
49
|
+
*/
|
|
50
|
+
export function isAbsolute(p: string): boolean {
|
|
51
|
+
return nodePath.isAbsolute(p);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get the directory name of a path
|
|
56
|
+
*/
|
|
57
|
+
export function dirname(p: string): string {
|
|
58
|
+
return nodePath.dirname(p);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get the base name of a path
|
|
63
|
+
*/
|
|
64
|
+
export function basename(p: string, ext?: string): string {
|
|
65
|
+
return nodePath.basename(p, ext);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get the extension of a path
|
|
70
|
+
*/
|
|
71
|
+
export function extname(p: string): string {
|
|
72
|
+
return nodePath.extname(p);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Parse a path into components
|
|
77
|
+
*/
|
|
78
|
+
export interface ParsedPath {
|
|
79
|
+
root: string;
|
|
80
|
+
dir: string;
|
|
81
|
+
base: string;
|
|
82
|
+
ext: string;
|
|
83
|
+
name: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function parse(p: string): ParsedPath {
|
|
87
|
+
return nodePath.parse(p);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Format a parsed path back into a string
|
|
92
|
+
*/
|
|
93
|
+
export function format(pathObject: Partial<ParsedPath>): string {
|
|
94
|
+
return nodePath.format(pathObject);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Convert path to POSIX format (forward slashes)
|
|
99
|
+
*/
|
|
100
|
+
export function toPosix(p: string): string {
|
|
101
|
+
return p.replace(/\\/g, '/');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Convert path to Windows format (backslashes)
|
|
106
|
+
*/
|
|
107
|
+
export function toWindows(p: string): string {
|
|
108
|
+
return p.replace(/\//g, '\\');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the parent directory
|
|
113
|
+
*/
|
|
114
|
+
export function parent(p: string): string {
|
|
115
|
+
return dirname(p);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get path segments as an array
|
|
120
|
+
*/
|
|
121
|
+
export function segments(p: string): string[] {
|
|
122
|
+
const normalized = normalize(p);
|
|
123
|
+
return normalized.split(sep).filter((s) => s.length > 0);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if a path has a specific extension
|
|
128
|
+
*/
|
|
129
|
+
export function hasExtension(p: string, ext: string): boolean {
|
|
130
|
+
const pathExt = extname(p).toLowerCase();
|
|
131
|
+
const checkExt = ext.startsWith('.') ? ext.toLowerCase() : `.${ext.toLowerCase()}`;
|
|
132
|
+
return pathExt === checkExt;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Change the extension of a path
|
|
137
|
+
*/
|
|
138
|
+
export function changeExtension(p: string, newExt: string): string {
|
|
139
|
+
const parsed = parse(p);
|
|
140
|
+
const ext = newExt.startsWith('.') ? newExt : `.${newExt}`;
|
|
141
|
+
return join(parsed.dir, `${parsed.name}${ext}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Remove the extension from a path
|
|
146
|
+
*/
|
|
147
|
+
export function removeExtension(p: string): string {
|
|
148
|
+
const parsed = parse(p);
|
|
149
|
+
return join(parsed.dir, parsed.name);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Add a suffix before the extension
|
|
154
|
+
*/
|
|
155
|
+
export function addSuffix(p: string, suffix: string): string {
|
|
156
|
+
const parsed = parse(p);
|
|
157
|
+
return join(parsed.dir, `${parsed.name}${suffix}${parsed.ext}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Check if a path is a child of another path
|
|
162
|
+
*/
|
|
163
|
+
export function isChildOf(child: string, parent: string): boolean {
|
|
164
|
+
const childResolved = resolve(child);
|
|
165
|
+
const parentResolved = resolve(parent);
|
|
166
|
+
const rel = relative(parentResolved, childResolved);
|
|
167
|
+
return !rel.startsWith('..') && !isAbsolute(rel);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get the common base path of multiple paths
|
|
172
|
+
*/
|
|
173
|
+
export function commonBase(...paths: string[]): string {
|
|
174
|
+
if (paths.length === 0) return '';
|
|
175
|
+
if (paths.length === 1) return dirname(paths[0]);
|
|
176
|
+
|
|
177
|
+
const resolvedPaths = paths.map((p) => resolve(p));
|
|
178
|
+
const segmentsList = resolvedPaths.map((p) => segments(p));
|
|
179
|
+
const minLength = Math.min(...segmentsList.map((s) => s.length));
|
|
180
|
+
|
|
181
|
+
const common: string[] = [];
|
|
182
|
+
for (let i = 0; i < minLength; i++) {
|
|
183
|
+
const segment = segmentsList[0][i];
|
|
184
|
+
if (segmentsList.every((s) => s[i] === segment)) {
|
|
185
|
+
common.push(segment);
|
|
186
|
+
} else {
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (common.length === 0) return '';
|
|
192
|
+
|
|
193
|
+
// Handle root on Unix vs Windows
|
|
194
|
+
if (resolvedPaths[0].startsWith('/')) {
|
|
195
|
+
return '/' + common.join('/');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return common.join(sep);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Expand tilde (~) to home directory
|
|
203
|
+
*/
|
|
204
|
+
export function expandHome(p: string): string {
|
|
205
|
+
if (p.startsWith('~')) {
|
|
206
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
207
|
+
return join(home, p.slice(1));
|
|
208
|
+
}
|
|
209
|
+
return p;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Make a path safe for use as a filename
|
|
214
|
+
*/
|
|
215
|
+
export function sanitize(filename: string): string {
|
|
216
|
+
return filename
|
|
217
|
+
.replace(/[<>:"/\\|?*\x00-\x1F]/g, '_')
|
|
218
|
+
.replace(/^\.+/, '_')
|
|
219
|
+
.replace(/\.+$/, '_')
|
|
220
|
+
.slice(0, 255);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if a filename matches a glob pattern
|
|
225
|
+
*/
|
|
226
|
+
export function matchesPattern(filename: string, pattern: string): boolean {
|
|
227
|
+
const regexPattern = pattern
|
|
228
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
229
|
+
.replace(/\*/g, '.*')
|
|
230
|
+
.replace(/\?/g, '.');
|
|
231
|
+
return new RegExp(`^${regexPattern}$`).test(filename);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Path builder for fluent API
|
|
236
|
+
*/
|
|
237
|
+
export class PathBuilder {
|
|
238
|
+
private path: string;
|
|
239
|
+
|
|
240
|
+
constructor(base: string = process.cwd()) {
|
|
241
|
+
this.path = resolve(base);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static from(base: string): PathBuilder {
|
|
245
|
+
return new PathBuilder(base);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static cwd(): PathBuilder {
|
|
249
|
+
return new PathBuilder(process.cwd());
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
join(...segments: string[]): PathBuilder {
|
|
253
|
+
this.path = join(this.path, ...segments);
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
parent(): PathBuilder {
|
|
258
|
+
this.path = dirname(this.path);
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
sibling(name: string): PathBuilder {
|
|
263
|
+
this.path = join(dirname(this.path), name);
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
withExtension(ext: string): PathBuilder {
|
|
268
|
+
this.path = changeExtension(this.path, ext);
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
withSuffix(suffix: string): PathBuilder {
|
|
273
|
+
this.path = addSuffix(this.path, suffix);
|
|
274
|
+
return this;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
normalize(): PathBuilder {
|
|
278
|
+
this.path = normalize(this.path);
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
toString(): string {
|
|
283
|
+
return this.path;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
get value(): string {
|
|
287
|
+
return this.path;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
get dirname(): string {
|
|
291
|
+
return dirname(this.path);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
get basename(): string {
|
|
295
|
+
return basename(this.path);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
get extname(): string {
|
|
299
|
+
return extname(this.path);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
get name(): string {
|
|
303
|
+
return parse(this.path).name;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Convenience function
|
|
308
|
+
export function path(base?: string): PathBuilder {
|
|
309
|
+
return new PathBuilder(base);
|
|
310
|
+
}
|