sandbox-fs 1.0.0 → 1.1.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/README.md +16 -0
- package/dist/FSModule.d.ts.map +1 -1
- package/dist/FSModule.js +81 -18
- package/dist/FSModule.js.map +1 -1
- package/dist/PathMapper.d.ts.map +1 -1
- package/dist/PathMapper.js +147 -41
- package/dist/PathMapper.js.map +1 -1
- package/dist/VirtualFileSystem.d.ts.map +1 -1
- package/dist/VirtualFileSystem.js +27 -1
- package/dist/VirtualFileSystem.js.map +1 -1
- package/dist/operations/newer.d.ts.map +1 -1
- package/dist/operations/newer.js +32 -3
- package/dist/operations/newer.js.map +1 -1
- package/dist/operations/read.d.ts.map +1 -1
- package/dist/operations/read.js +100 -14
- package/dist/operations/read.js.map +1 -1
- package/dist/utils/ErrorFilter.d.ts.map +1 -1
- package/dist/utils/ErrorFilter.js +21 -24
- package/dist/utils/ErrorFilter.js.map +1 -1
- package/dist/wrappers/VirtualDir.d.ts.map +1 -1
- package/dist/wrappers/VirtualDir.js +36 -35
- package/dist/wrappers/VirtualDir.js.map +1 -1
- package/dist/wrappers/VirtualDirent.d.ts.map +1 -1
- package/dist/wrappers/VirtualDirent.js +28 -9
- package/dist/wrappers/VirtualDirent.js.map +1 -1
- package/package.json +8 -4
- package/dist/FSModule.d.ts +0 -153
- package/dist/PathMapper.d.ts +0 -30
- package/dist/PathModule.d.ts +0 -69
- package/dist/ResourceTracker.d.ts +0 -74
- package/dist/VirtualFileSystem.d.ts +0 -145
- package/dist/index.d.ts +0 -9
- package/dist/operations/newer.d.ts +0 -36
- package/dist/operations/read.d.ts +0 -24
- package/dist/operations/symlink.d.ts +0 -8
- package/dist/operations/write.d.ts +0 -29
- package/dist/utils/ErrorFilter.d.ts +0 -6
- package/dist/utils/callbackify.d.ts +0 -9
- package/dist/wrappers/VirtualDir.d.ts +0 -34
- package/dist/wrappers/VirtualDirent.d.ts +0 -21
- package/example.js +0 -95
- package/example.ts +0 -32
- package/src/FSModule.ts +0 -546
- package/src/PathMapper.ts +0 -102
- package/src/PathModule.ts +0 -142
- package/src/ResourceTracker.ts +0 -162
- package/src/VirtualFileSystem.ts +0 -172
- package/src/index.ts +0 -9
- package/src/operations/newer.ts +0 -223
- package/src/operations/read.ts +0 -319
- package/src/operations/symlink.ts +0 -31
- package/src/operations/write.ts +0 -189
- package/src/utils/ErrorFilter.ts +0 -57
- package/src/utils/callbackify.ts +0 -54
- package/src/wrappers/VirtualDir.ts +0 -84
- package/src/wrappers/VirtualDirent.ts +0 -60
- package/test-data/example.txt +0 -1
- package/test-data/subdir/nested.txt +0 -1
- package/tsconfig.example.json +0 -8
- package/tsconfig.json +0 -21
package/src/operations/read.ts
DELETED
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import type { PathMapper } from '../PathMapper';
|
|
3
|
-
import type { ResourceTracker } from '../ResourceTracker';
|
|
4
|
-
import { filterError } from '../utils/ErrorFilter';
|
|
5
|
-
import { VirtualDir } from '../wrappers/VirtualDir';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Create access denied error for write operations
|
|
9
|
-
*/
|
|
10
|
-
function createEACCESError(syscall: string, path: string): NodeJS.ErrnoException {
|
|
11
|
-
const error = new Error(`${syscall}: operation not permitted, ${syscall} '${path}'`) as NodeJS.ErrnoException;
|
|
12
|
-
error.code = 'EACCES';
|
|
13
|
-
error.errno = -13;
|
|
14
|
-
error.syscall = syscall;
|
|
15
|
-
error.path = path;
|
|
16
|
-
return error;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Wrap an async operation with error filtering and closed check
|
|
21
|
-
*/
|
|
22
|
-
async function wrapOperation<T>(
|
|
23
|
-
operation: () => Promise<T>,
|
|
24
|
-
pathMapper: PathMapper,
|
|
25
|
-
resourceTracker: ResourceTracker
|
|
26
|
-
): Promise<T> {
|
|
27
|
-
resourceTracker.assertNotClosed();
|
|
28
|
-
try {
|
|
29
|
-
return await operation();
|
|
30
|
-
} catch (error) {
|
|
31
|
-
throw filterError(error as Error, pathMapper);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Read file operations
|
|
37
|
-
*/
|
|
38
|
-
export function createReadFileOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
39
|
-
return async (virtualPath: string, options?: any): Promise<Buffer | string> => {
|
|
40
|
-
return wrapOperation(async () => {
|
|
41
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
42
|
-
|
|
43
|
-
// Handle AbortSignal if present
|
|
44
|
-
if (options?.signal) {
|
|
45
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return fs.promises.readFile(realPath, options);
|
|
49
|
-
}, pathMapper, resourceTracker);
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function createReaddirOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
54
|
-
return async (virtualPath: string, options?: any): Promise<string[] | Buffer[] | fs.Dirent[]> => {
|
|
55
|
-
return wrapOperation(async () => {
|
|
56
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
57
|
-
|
|
58
|
-
if (options?.signal) {
|
|
59
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return fs.promises.readdir(realPath, options);
|
|
63
|
-
}, pathMapper, resourceTracker);
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function createStatOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
68
|
-
return async (virtualPath: string, options?: any): Promise<fs.Stats> => {
|
|
69
|
-
return wrapOperation(async () => {
|
|
70
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
71
|
-
|
|
72
|
-
if (options?.signal) {
|
|
73
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const stats = await fs.promises.stat(realPath, options);
|
|
77
|
-
|
|
78
|
-
// Return EACCES for symlinks
|
|
79
|
-
if (stats.isSymbolicLink()) {
|
|
80
|
-
throw createEACCESError('stat', virtualPath);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return stats;
|
|
84
|
-
}, pathMapper, resourceTracker);
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function createLstatOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
89
|
-
return async (virtualPath: string, options?: any): Promise<fs.Stats> => {
|
|
90
|
-
return wrapOperation(async () => {
|
|
91
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
92
|
-
|
|
93
|
-
if (options?.signal) {
|
|
94
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const stats = await fs.promises.lstat(realPath, options);
|
|
98
|
-
|
|
99
|
-
// Return EACCES for symlinks
|
|
100
|
-
if (stats.isSymbolicLink()) {
|
|
101
|
-
throw createEACCESError('lstat', virtualPath);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return stats;
|
|
105
|
-
}, pathMapper, resourceTracker);
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function createAccessOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
110
|
-
return async (virtualPath: string, mode?: number): Promise<void> => {
|
|
111
|
-
return wrapOperation(async () => {
|
|
112
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
113
|
-
return fs.promises.access(realPath, mode);
|
|
114
|
-
}, pathMapper, resourceTracker);
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function createRealpathOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
119
|
-
return async (virtualPath: string, options?: any): Promise<string | Buffer> => {
|
|
120
|
-
return wrapOperation(async () => {
|
|
121
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
122
|
-
|
|
123
|
-
if (options?.signal) {
|
|
124
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const resolvedRealPath = await fs.promises.realpath(realPath, options);
|
|
128
|
-
|
|
129
|
-
// Convert back to virtual path
|
|
130
|
-
const resolvedStr = Buffer.isBuffer(resolvedRealPath) ? resolvedRealPath.toString() : resolvedRealPath;
|
|
131
|
-
const resolvedVirtualPath = pathMapper.toVirtualPath(resolvedStr);
|
|
132
|
-
|
|
133
|
-
// Return as buffer if encoding option is 'buffer'
|
|
134
|
-
if (options && typeof options === 'object' && options.encoding === 'buffer') {
|
|
135
|
-
return Buffer.from(resolvedVirtualPath) as any;
|
|
136
|
-
}
|
|
137
|
-
return resolvedVirtualPath as any;
|
|
138
|
-
}, pathMapper, resourceTracker);
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export function createOpenOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
143
|
-
return async (virtualPath: string, flags?: string | number, mode?: number): Promise<number> => {
|
|
144
|
-
return wrapOperation(async () => {
|
|
145
|
-
// Check if flags indicate write mode
|
|
146
|
-
const flagsStr = typeof flags === 'number' ? flags.toString() : (flags || 'r');
|
|
147
|
-
const isWriteMode = /w|a|\+/.test(flagsStr.toString());
|
|
148
|
-
|
|
149
|
-
if (isWriteMode) {
|
|
150
|
-
throw createEACCESError('open', virtualPath);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
154
|
-
const fd = await fs.promises.open(realPath, flags, mode);
|
|
155
|
-
|
|
156
|
-
// Track the file descriptor
|
|
157
|
-
resourceTracker.trackFD(fd.fd, {
|
|
158
|
-
virtualPath,
|
|
159
|
-
realPath,
|
|
160
|
-
flags: flags || 'r',
|
|
161
|
-
mode,
|
|
162
|
-
isStream: false,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
return fd.fd;
|
|
166
|
-
}, pathMapper, resourceTracker);
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export function createReadOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
171
|
-
return async (
|
|
172
|
-
fd: number,
|
|
173
|
-
buffer: NodeJS.ArrayBufferView,
|
|
174
|
-
offset: number,
|
|
175
|
-
length: number,
|
|
176
|
-
position: number | null
|
|
177
|
-
): Promise<{ bytesRead: number; buffer: NodeJS.ArrayBufferView }> => {
|
|
178
|
-
return wrapOperation(async () => {
|
|
179
|
-
// Verify FD is tracked
|
|
180
|
-
if (!resourceTracker.isTracked(fd)) {
|
|
181
|
-
const error = new Error('bad file descriptor') as NodeJS.ErrnoException;
|
|
182
|
-
error.code = 'EBADF';
|
|
183
|
-
error.errno = -9;
|
|
184
|
-
error.syscall = 'read';
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Use fs.read with callback wrapped in promise
|
|
189
|
-
return new Promise<{ bytesRead: number; buffer: NodeJS.ArrayBufferView }>((resolve, reject) => {
|
|
190
|
-
fs.read(fd, buffer, offset, length, position, (err, bytesRead) => {
|
|
191
|
-
if (err) reject(err);
|
|
192
|
-
else resolve({ bytesRead, buffer });
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
}, pathMapper, resourceTracker);
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export function createCloseOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
200
|
-
return async (fd: number): Promise<void> => {
|
|
201
|
-
return wrapOperation(async () => {
|
|
202
|
-
// Untrack before closing
|
|
203
|
-
resourceTracker.untrackFD(fd);
|
|
204
|
-
return new Promise<void>((resolve, reject) => {
|
|
205
|
-
fs.close(fd, (err) => {
|
|
206
|
-
if (err) reject(err);
|
|
207
|
-
else resolve();
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
}, pathMapper, resourceTracker);
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export function createFstatOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
215
|
-
return async (fd: number, options?: any): Promise<fs.Stats> => {
|
|
216
|
-
return wrapOperation(async () => {
|
|
217
|
-
if (!resourceTracker.isTracked(fd)) {
|
|
218
|
-
const error = new Error('bad file descriptor') as NodeJS.ErrnoException;
|
|
219
|
-
error.code = 'EBADF';
|
|
220
|
-
error.errno = -9;
|
|
221
|
-
error.syscall = 'fstat';
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (options?.signal) {
|
|
226
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// @ts-ignore - fstat exists but types may not match perfectly
|
|
230
|
-
return fs.promises.fstat(fd, options);
|
|
231
|
-
}, pathMapper, resourceTracker);
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
export function createOpendirOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
236
|
-
return async (virtualPath: string, options?: any): Promise<VirtualDir> => {
|
|
237
|
-
return wrapOperation(async () => {
|
|
238
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
239
|
-
|
|
240
|
-
if (options?.signal) {
|
|
241
|
-
resourceTracker.registerAbortListener(options.signal, () => {});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const realDir = await fs.promises.opendir(realPath, options);
|
|
245
|
-
return new VirtualDir(realDir, virtualPath, pathMapper);
|
|
246
|
-
}, pathMapper, resourceTracker);
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export function createExistsOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
251
|
-
return async (virtualPath: string): Promise<boolean> => {
|
|
252
|
-
resourceTracker.assertNotClosed();
|
|
253
|
-
try {
|
|
254
|
-
const realPath = pathMapper.toRealPath(virtualPath);
|
|
255
|
-
await fs.promises.access(realPath);
|
|
256
|
-
return true;
|
|
257
|
-
} catch {
|
|
258
|
-
return false;
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export function createCreateReadStreamOperation(pathMapper: PathMapper, resourceTracker: ResourceTracker) {
|
|
264
|
-
return (virtualPath: string, options?: any): fs.ReadStream => {
|
|
265
|
-
resourceTracker.assertNotClosed();
|
|
266
|
-
|
|
267
|
-
let realPath: string;
|
|
268
|
-
try {
|
|
269
|
-
realPath = pathMapper.toRealPath(virtualPath);
|
|
270
|
-
} catch (error) {
|
|
271
|
-
// Create a dummy stream that will emit an error
|
|
272
|
-
const stream = new (require('stream').Readable)({
|
|
273
|
-
read() {}
|
|
274
|
-
}) as fs.ReadStream;
|
|
275
|
-
|
|
276
|
-
process.nextTick(() => {
|
|
277
|
-
stream.destroy(filterError(error as Error, pathMapper));
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
return stream;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const realStream = fs.createReadStream(realPath, options);
|
|
284
|
-
|
|
285
|
-
// Track the stream
|
|
286
|
-
resourceTracker.trackStream(realStream);
|
|
287
|
-
|
|
288
|
-
// Untrack when closed
|
|
289
|
-
realStream.on('close', () => {
|
|
290
|
-
resourceTracker.untrackStream(realStream);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// Create a proxy to override the path property and filter errors
|
|
294
|
-
const streamProxy = new Proxy(realStream, {
|
|
295
|
-
get(target, prop) {
|
|
296
|
-
if (prop === 'path') {
|
|
297
|
-
return virtualPath;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (prop === 'on' || prop === 'once') {
|
|
301
|
-
return function(event: string, listener: any) {
|
|
302
|
-
if (event === 'error') {
|
|
303
|
-
// Wrap error listener to filter errors
|
|
304
|
-
const wrappedListener = (error: Error) => {
|
|
305
|
-
listener(filterError(error, pathMapper));
|
|
306
|
-
};
|
|
307
|
-
return target[prop as 'on'](event, wrappedListener);
|
|
308
|
-
}
|
|
309
|
-
return target[prop as 'on'](event, listener);
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return target[prop as keyof fs.ReadStream];
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
return streamProxy;
|
|
318
|
-
};
|
|
319
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* All symlink operations return EACCES (access denied)
|
|
3
|
-
* This module provides all symlink-related fs operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
function createEACCESError(syscall: string, path: string): NodeJS.ErrnoException {
|
|
7
|
-
const error = new Error(`${syscall}: operation not permitted, ${syscall} '${path}'`) as NodeJS.ErrnoException;
|
|
8
|
-
error.code = 'EACCES';
|
|
9
|
-
error.errno = -13;
|
|
10
|
-
error.syscall = syscall;
|
|
11
|
-
error.path = path;
|
|
12
|
-
return error;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createSymlinkOperation() {
|
|
16
|
-
return async (target: string, path: string, type?: string): Promise<void> => {
|
|
17
|
-
throw createEACCESError('symlink', path);
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createLinkOperation() {
|
|
22
|
-
return async (existingPath: string, newPath: string): Promise<void> => {
|
|
23
|
-
throw createEACCESError('link', newPath);
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function createReadlinkOperation() {
|
|
28
|
-
return async (path: string, options?: any): Promise<string | Buffer> => {
|
|
29
|
-
throw createEACCESError('readlink', path);
|
|
30
|
-
};
|
|
31
|
-
}
|
package/src/operations/write.ts
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* All write operations return EACCES (access denied)
|
|
3
|
-
* This module provides all write-related fs operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
function createEACCESError(syscall: string, path: string): NodeJS.ErrnoException {
|
|
7
|
-
const error = new Error(`${syscall}: operation not permitted, ${syscall} '${path}'`) as NodeJS.ErrnoException;
|
|
8
|
-
error.code = 'EACCES';
|
|
9
|
-
error.errno = -13;
|
|
10
|
-
error.syscall = syscall;
|
|
11
|
-
error.path = path;
|
|
12
|
-
return error;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createWriteFileOperation() {
|
|
16
|
-
return async (path: string, data: any, options?: any): Promise<void> => {
|
|
17
|
-
throw createEACCESError('open', path);
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createAppendFileOperation() {
|
|
22
|
-
return async (path: string, data: any, options?: any): Promise<void> => {
|
|
23
|
-
throw createEACCESError('open', path);
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function createMkdirOperation() {
|
|
28
|
-
return async (path: string, options?: any): Promise<void | string> => {
|
|
29
|
-
throw createEACCESError('mkdir', path);
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function createRmdirOperation() {
|
|
34
|
-
return async (path: string, options?: any): Promise<void> => {
|
|
35
|
-
throw createEACCESError('rmdir', path);
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function createRmOperation() {
|
|
40
|
-
return async (path: string, options?: any): Promise<void> => {
|
|
41
|
-
throw createEACCESError('rm', path);
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function createUnlinkOperation() {
|
|
46
|
-
return async (path: string): Promise<void> => {
|
|
47
|
-
throw createEACCESError('unlink', path);
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function createRenameOperation() {
|
|
52
|
-
return async (oldPath: string, newPath: string): Promise<void> => {
|
|
53
|
-
throw createEACCESError('rename', oldPath);
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function createCopyFileOperation() {
|
|
58
|
-
return async (src: string, dest: string, mode?: number): Promise<void> => {
|
|
59
|
-
throw createEACCESError('copyfile', dest);
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function createTruncateOperation() {
|
|
64
|
-
return async (path: string, len?: number): Promise<void> => {
|
|
65
|
-
throw createEACCESError('open', path);
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function createFtruncateOperation() {
|
|
70
|
-
return async (fd: number, len?: number): Promise<void> => {
|
|
71
|
-
const error = new Error('ftruncate: operation not permitted') as NodeJS.ErrnoException;
|
|
72
|
-
error.code = 'EACCES';
|
|
73
|
-
error.errno = -13;
|
|
74
|
-
error.syscall = 'ftruncate';
|
|
75
|
-
throw error;
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function createChmodOperation() {
|
|
80
|
-
return async (path: string, mode: string | number): Promise<void> => {
|
|
81
|
-
throw createEACCESError('chmod', path);
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function createFchmodOperation() {
|
|
86
|
-
return async (fd: number, mode: string | number): Promise<void> => {
|
|
87
|
-
const error = new Error('fchmod: operation not permitted') as NodeJS.ErrnoException;
|
|
88
|
-
error.code = 'EACCES';
|
|
89
|
-
error.errno = -13;
|
|
90
|
-
error.syscall = 'fchmod';
|
|
91
|
-
throw error;
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function createLchmodOperation() {
|
|
96
|
-
return async (path: string, mode: string | number): Promise<void> => {
|
|
97
|
-
throw createEACCESError('lchmod', path);
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function createChownOperation() {
|
|
102
|
-
return async (path: string, uid: number, gid: number): Promise<void> => {
|
|
103
|
-
throw createEACCESError('chown', path);
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function createFchownOperation() {
|
|
108
|
-
return async (fd: number, uid: number, gid: number): Promise<void> => {
|
|
109
|
-
const error = new Error('fchown: operation not permitted') as NodeJS.ErrnoException;
|
|
110
|
-
error.code = 'EACCES';
|
|
111
|
-
error.errno = -13;
|
|
112
|
-
error.syscall = 'fchown';
|
|
113
|
-
throw error;
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function createLchownOperation() {
|
|
118
|
-
return async (path: string, uid: number, gid: number): Promise<void> => {
|
|
119
|
-
throw createEACCESError('lchown', path);
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function createUtimesOperation() {
|
|
124
|
-
return async (path: string, atime: string | number | Date, mtime: string | number | Date): Promise<void> => {
|
|
125
|
-
throw createEACCESError('utime', path);
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function createFutimesOperation() {
|
|
130
|
-
return async (fd: number, atime: string | number | Date, mtime: string | number | Date): Promise<void> => {
|
|
131
|
-
const error = new Error('futime: operation not permitted') as NodeJS.ErrnoException;
|
|
132
|
-
error.code = 'EACCES';
|
|
133
|
-
error.errno = -13;
|
|
134
|
-
error.syscall = 'futime';
|
|
135
|
-
throw error;
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function createLutimesOperation() {
|
|
140
|
-
return async (path: string, atime: string | number | Date, mtime: string | number | Date): Promise<void> => {
|
|
141
|
-
throw createEACCESError('lutime', path);
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function createWriteOperation() {
|
|
146
|
-
return async (fd: number, buffer: any, offset?: any, length?: any, position?: any): Promise<any> => {
|
|
147
|
-
const error = new Error('write: operation not permitted') as NodeJS.ErrnoException;
|
|
148
|
-
error.code = 'EACCES';
|
|
149
|
-
error.errno = -13;
|
|
150
|
-
error.syscall = 'write';
|
|
151
|
-
throw error;
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export function createWritevOperation() {
|
|
156
|
-
return async (fd: number, buffers: NodeJS.ArrayBufferView[], position?: number): Promise<any> => {
|
|
157
|
-
const error = new Error('writev: operation not permitted') as NodeJS.ErrnoException;
|
|
158
|
-
error.code = 'EACCES';
|
|
159
|
-
error.errno = -13;
|
|
160
|
-
error.syscall = 'writev';
|
|
161
|
-
throw error;
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function createCreateWriteStreamOperation() {
|
|
166
|
-
return (path: string, options?: any): never => {
|
|
167
|
-
throw createEACCESError('open', path);
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export function createFsyncOperation() {
|
|
172
|
-
return async (fd: number): Promise<void> => {
|
|
173
|
-
const error = new Error('fsync: operation not permitted') as NodeJS.ErrnoException;
|
|
174
|
-
error.code = 'EACCES';
|
|
175
|
-
error.errno = -13;
|
|
176
|
-
error.syscall = 'fsync';
|
|
177
|
-
throw error;
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function createFdatasyncOperation() {
|
|
182
|
-
return async (fd: number): Promise<void> => {
|
|
183
|
-
const error = new Error('fdatasync: operation not permitted') as NodeJS.ErrnoException;
|
|
184
|
-
error.code = 'EACCES';
|
|
185
|
-
error.errno = -13;
|
|
186
|
-
error.syscall = 'fdatasync';
|
|
187
|
-
throw error;
|
|
188
|
-
};
|
|
189
|
-
}
|
package/src/utils/ErrorFilter.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { PathMapper } from "../PathMapper";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Filter error messages to replace real paths with virtual paths
|
|
5
|
-
*/
|
|
6
|
-
export function filterError(error: Error, pathMapper: PathMapper): Error {
|
|
7
|
-
const realRoot = pathMapper.getRoot();
|
|
8
|
-
|
|
9
|
-
// Create a regex to match the real root path
|
|
10
|
-
// Escape special regex characters and handle both forward and back slashes
|
|
11
|
-
const escapedRoot = realRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12
|
-
const rootPattern = new RegExp(escapedRoot.replace(/\\/g, "\\\\"), "g");
|
|
13
|
-
|
|
14
|
-
// Filter the error message
|
|
15
|
-
if (error.message) {
|
|
16
|
-
error.message = error.message.replace(rootPattern, "");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Filter the stack trace
|
|
20
|
-
if (error.stack) {
|
|
21
|
-
error.stack = error.stack.replace(rootPattern, "");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Filter the path property if it exists
|
|
25
|
-
const errWithPath = error as NodeJS.ErrnoException;
|
|
26
|
-
if (errWithPath.path && typeof errWithPath.path === "string") {
|
|
27
|
-
try {
|
|
28
|
-
// Try to convert real path to virtual path
|
|
29
|
-
if (pathMapper.isWithinRoot(errWithPath.path)) {
|
|
30
|
-
errWithPath.path = pathMapper.toVirtualPath(errWithPath.path);
|
|
31
|
-
} else {
|
|
32
|
-
// If outside root, just strip the root prefix
|
|
33
|
-
errWithPath.path = errWithPath.path.replace(rootPattern, "");
|
|
34
|
-
}
|
|
35
|
-
} catch {
|
|
36
|
-
// If conversion fails, just strip the root prefix
|
|
37
|
-
errWithPath.path = errWithPath.path.replace(rootPattern, "");
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Filter the dest property if it exists (for copy operations)
|
|
42
|
-
if ("dest" in errWithPath && typeof errWithPath.dest === "string") {
|
|
43
|
-
try {
|
|
44
|
-
const destStr = errWithPath.dest as string;
|
|
45
|
-
if (pathMapper.isWithinRoot(destStr)) {
|
|
46
|
-
(errWithPath as any).dest = pathMapper.toVirtualPath(destStr);
|
|
47
|
-
} else {
|
|
48
|
-
(errWithPath as any).dest = destStr.replace(rootPattern, "");
|
|
49
|
-
}
|
|
50
|
-
} catch {
|
|
51
|
-
const destStr = errWithPath.dest as string;
|
|
52
|
-
(errWithPath as any).dest = destStr.replace(rootPattern, "");
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return error;
|
|
57
|
-
}
|
package/src/utils/callbackify.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Convert a promise-based function to a callback-based function
|
|
3
|
-
*/
|
|
4
|
-
export function callbackify<T extends any[], R>(
|
|
5
|
-
fn: (...args: T) => Promise<R>
|
|
6
|
-
): (...args: [...T, (err: Error | null, result?: R) => void]) => void {
|
|
7
|
-
return function (this: any, ...args: any[]) {
|
|
8
|
-
// Extract callback from arguments
|
|
9
|
-
const callback = args[args.length - 1];
|
|
10
|
-
|
|
11
|
-
if (typeof callback !== 'function') {
|
|
12
|
-
throw new TypeError('The last argument must be a callback function');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Get the actual arguments (without callback)
|
|
16
|
-
const actualArgs = args.slice(0, -1) as T;
|
|
17
|
-
|
|
18
|
-
// Call the promise function
|
|
19
|
-
fn.apply(this, actualArgs)
|
|
20
|
-
.then((result) => {
|
|
21
|
-
// Call callback with no error
|
|
22
|
-
callback(null, result);
|
|
23
|
-
})
|
|
24
|
-
.catch((err) => {
|
|
25
|
-
// Call callback with error
|
|
26
|
-
callback(err);
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Callbackify for void-returning promises
|
|
33
|
-
*/
|
|
34
|
-
export function callbackifyVoid<T extends any[]>(
|
|
35
|
-
fn: (...args: T) => Promise<void>
|
|
36
|
-
): (...args: [...T, (err: Error | null) => void]) => void {
|
|
37
|
-
return function (this: any, ...args: any[]) {
|
|
38
|
-
const callback = args[args.length - 1];
|
|
39
|
-
|
|
40
|
-
if (typeof callback !== 'function') {
|
|
41
|
-
throw new TypeError('The last argument must be a callback function');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const actualArgs = args.slice(0, -1) as T;
|
|
45
|
-
|
|
46
|
-
fn.apply(this, actualArgs)
|
|
47
|
-
.then(() => {
|
|
48
|
-
callback(null);
|
|
49
|
-
})
|
|
50
|
-
.catch((err) => {
|
|
51
|
-
callback(err);
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
}
|