source: frontend/node_modules/webpack/lib/util/fs.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 27.8 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const path = require("path");
9
10/** @typedef {import("../../declarations/WebpackOptions").WatchOptions} WatchOptions */
11/** @typedef {import("watchpack").Entry} Entry */
12/** @typedef {import("watchpack").OnlySafeTimeEntry} OnlySafeTimeEntry */
13/** @typedef {import("watchpack").ExistenceOnlyTimeEntry} ExistenceOnlyTimeEntry */
14
15/**
16 * Defines the i stats base type used by this module.
17 * @template T
18 * @typedef {object} IStatsBase
19 * @property {() => boolean} isFile
20 * @property {() => boolean} isDirectory
21 * @property {() => boolean} isBlockDevice
22 * @property {() => boolean} isCharacterDevice
23 * @property {() => boolean} isSymbolicLink
24 * @property {() => boolean} isFIFO
25 * @property {() => boolean} isSocket
26 * @property {T} dev
27 * @property {T} ino
28 * @property {T} mode
29 * @property {T} nlink
30 * @property {T} uid
31 * @property {T} gid
32 * @property {T} rdev
33 * @property {T} size
34 * @property {T} blksize
35 * @property {T} blocks
36 * @property {T} atimeMs
37 * @property {T} mtimeMs
38 * @property {T} ctimeMs
39 * @property {T} birthtimeMs
40 * @property {Date} atime
41 * @property {Date} mtime
42 * @property {Date} ctime
43 * @property {Date} birthtime
44 */
45
46/**
47 * Defines the i stats type used by this module.
48 * @typedef {IStatsBase<number>} IStats
49 */
50
51/**
52 * Defines the i big int stats type used by this module.
53 * @typedef {IStatsBase<bigint> & { atimeNs: bigint, mtimeNs: bigint, ctimeNs: bigint, birthtimeNs: bigint }} IBigIntStats
54 */
55
56/**
57 * Defines the dirent type used by this module.
58 * @template {string | Buffer} [T=string]
59 * @typedef {object} Dirent
60 * @property {() => boolean} isFile true when is file, otherwise false
61 * @property {() => boolean} isDirectory true when is directory, otherwise false
62 * @property {() => boolean} isBlockDevice true when is block device, otherwise false
63 * @property {() => boolean} isCharacterDevice true when is character device, otherwise false
64 * @property {() => boolean} isSymbolicLink true when is symbolic link, otherwise false
65 * @property {() => boolean} isFIFO true when is FIFO, otherwise false
66 * @property {() => boolean} isSocket true when is socket, otherwise false
67 * @property {T} name name
68 * @property {string} parentPath path
69 * @property {string=} path path
70 */
71
72/** @typedef {string | number | boolean | null} JsonPrimitive */
73/** @typedef {JsonValue[]} JsonArray */
74/** @typedef {{ [Key in string]?: JsonValue }} JsonObject */
75/** @typedef {JsonPrimitive | JsonObject | JsonArray} JsonValue */
76
77/** @typedef {(err: NodeJS.ErrnoException | null) => void} NoParamCallback */
78/** @typedef {(err: NodeJS.ErrnoException | null, result?: string) => void} StringCallback */
79/** @typedef {(err: NodeJS.ErrnoException | null, result?: Buffer) => void} BufferCallback */
80/** @typedef {(err: NodeJS.ErrnoException | null, result?: string | Buffer) => void} StringOrBufferCallback */
81/** @typedef {(err: NodeJS.ErrnoException | null, result?: string[]) => void} ReaddirStringCallback */
82/** @typedef {(err: NodeJS.ErrnoException | null, result?: Buffer[]) => void} ReaddirBufferCallback */
83/** @typedef {(err: NodeJS.ErrnoException | null, result?: string[] | Buffer[]) => void} ReaddirStringOrBufferCallback */
84/** @typedef {(err: NodeJS.ErrnoException | null, result?: Dirent[]) => void} ReaddirDirentCallback */
85/** @typedef {(err: NodeJS.ErrnoException | null, result?: Dirent<Buffer>[]) => void} ReaddirDirentBufferCallback */
86/** @typedef {(err: NodeJS.ErrnoException | null, result?: IStats) => void} StatsCallback */
87/** @typedef {(err: NodeJS.ErrnoException | null, result?: IBigIntStats) => void} BigIntStatsCallback */
88/** @typedef {(err: NodeJS.ErrnoException | null, result?: IStats | IBigIntStats) => void} StatsOrBigIntStatsCallback */
89/** @typedef {(err: NodeJS.ErrnoException | null, result?: number) => void} NumberCallback */
90/** @typedef {(err: NodeJS.ErrnoException | Error | null, result?: JsonObject) => void} ReadJsonCallback */
91
92/** @typedef {Map<string, Entry | OnlySafeTimeEntry | ExistenceOnlyTimeEntry | null | "ignore">} TimeInfoEntries */
93
94/** @typedef {Set<string>} Changes */
95/** @typedef {Set<string>} Removals */
96
97/**
98 * Defines the watcher info type used by this module.
99 * @typedef {object} WatcherInfo
100 * @property {Changes | null} changes get current aggregated changes that have not yet send to callback
101 * @property {Removals | null} removals get current aggregated removals that have not yet send to callback
102 * @property {TimeInfoEntries} fileTimeInfoEntries get info about files
103 * @property {TimeInfoEntries} contextTimeInfoEntries get info about directories
104 */
105
106// TODO webpack 6 deprecate missing getInfo
107/**
108 * Defines the watcher type used by this module.
109 * @typedef {object} Watcher
110 * @property {() => void} close closes the watcher and all underlying file watchers
111 * @property {() => void} pause closes the watcher, but keeps underlying file watchers alive until the next watch call
112 * @property {(() => Changes | null)=} getAggregatedChanges get current aggregated changes that have not yet send to callback
113 * @property {(() => Removals | null)=} getAggregatedRemovals get current aggregated removals that have not yet send to callback
114 * @property {() => TimeInfoEntries} getFileTimeInfoEntries get info about files
115 * @property {() => TimeInfoEntries} getContextTimeInfoEntries get info about directories
116 * @property {() => WatcherInfo=} getInfo get info about timestamps and changes
117 */
118
119/**
120 * Defines the watch method callback.
121 * @callback WatchMethod
122 * @param {Iterable<string>} files watched files
123 * @param {Iterable<string>} directories watched directories
124 * @param {Iterable<string>} missing watched existence entries
125 * @param {number} startTime timestamp of start time
126 * @param {WatchOptions} options options object
127 * @param {(err: Error | null, timeInfoEntries1?: TimeInfoEntries, timeInfoEntries2?: TimeInfoEntries, changes?: Changes, removals?: Removals) => void} callback aggregated callback
128 * @param {(value: string, num: number) => void} callbackUndelayed callback when the first change was detected
129 * @returns {Watcher} a watcher
130 */
131
132// TODO webpack 6 make optional methods required and avoid using non standard methods like `join`, `relative`, `dirname`, move IntermediateFileSystemExtras methods to InputFilesystem or OutputFilesystem
133
134/**
135 * Defines the path like type used by this module.
136 * @typedef {string | Buffer | URL} PathLike
137 */
138
139/**
140 * Defines the path or file descriptor type used by this module.
141 * @typedef {PathLike | number} PathOrFileDescriptor
142 */
143
144/**
145 * Defines the object encoding options type used by this module.
146 * @typedef {object} ObjectEncodingOptions
147 * @property {BufferEncoding | null | undefined=} encoding
148 */
149
150/**
151 * Describes the read file shape.
152 * @typedef {{
153 * (path: PathOrFileDescriptor, options: ({ encoding?: null | undefined, flag?: string | undefined } & import("events").Abortable) | undefined | null, callback: BufferCallback): void,
154 * (path: PathOrFileDescriptor, options: ({ encoding: BufferEncoding, flag?: string | undefined } & import("events").Abortable) | BufferEncoding, callback: StringCallback): void,
155 * (path: PathOrFileDescriptor, options: (ObjectEncodingOptions & { flag?: string | undefined } & import("events").Abortable) | BufferEncoding | undefined | null, callback: StringOrBufferCallback): void,
156 * (path: PathOrFileDescriptor, callback: BufferCallback): void,
157 * }} ReadFile
158 */
159
160/**
161 * Describes the read file sync shape.
162 * @typedef {{
163 * (path: PathOrFileDescriptor, options?: { encoding?: null | undefined, flag?: string | undefined } | null): Buffer,
164 * (path: PathOrFileDescriptor, options: { encoding: BufferEncoding, flag?: string | undefined } | BufferEncoding): string,
165 * (path: PathOrFileDescriptor, options?: (ObjectEncodingOptions & { flag?: string | undefined }) | BufferEncoding | null): string | Buffer,
166 * }} ReadFileSync
167 */
168
169/**
170 * Defines the encoding option type used by this module.
171 * @typedef {ObjectEncodingOptions | BufferEncoding | undefined | null} EncodingOption
172 */
173
174/**
175 * Defines the buffer encoding option type used by this module.
176 * @typedef {"buffer" | { encoding: "buffer" }} BufferEncodingOption
177 */
178
179/**
180 * Defines the stat options type used by this module.
181 * @typedef {object} StatOptions
182 * @property {(boolean | undefined)=} bigint
183 */
184
185/**
186 * Defines the stat sync options type used by this module.
187 * @typedef {object} StatSyncOptions
188 * @property {(boolean | undefined)=} bigint
189 * @property {(boolean | undefined)=} throwIfNoEntry
190 */
191
192/**
193 * Describes the readlink shape.
194 * @typedef {{
195 * (path: PathLike, options: EncodingOption, callback: StringCallback): void,
196 * (path: PathLike, options: BufferEncodingOption, callback: BufferCallback): void,
197 * (path: PathLike, options: EncodingOption, callback: StringOrBufferCallback): void,
198 * (path: PathLike, callback: StringCallback): void,
199 * }} Readlink
200 */
201
202/**
203 * Describes the readlink sync shape.
204 * @typedef {{
205 * (path: PathLike, options?: EncodingOption): string,
206 * (path: PathLike, options: BufferEncodingOption): Buffer,
207 * (path: PathLike, options?: EncodingOption): string | Buffer,
208 * }} ReadlinkSync
209 */
210
211/**
212 * Describes the readdir shape.
213 * @typedef {{
214 * (path: PathLike, options: { encoding: BufferEncoding | null, withFileTypes?: false | undefined, recursive?: boolean | undefined } | BufferEncoding | undefined | null, callback: (err: NodeJS.ErrnoException | null, files?: string[]) => void): void,
215 * (path: PathLike, options: { encoding: "buffer", withFileTypes?: false | undefined, recursive?: boolean | undefined } | "buffer", callback: (err: NodeJS.ErrnoException | null, files?: Buffer[]) => void): void,
216 * (path: PathLike, options: (ObjectEncodingOptions & { withFileTypes?: false | undefined, recursive?: boolean | undefined }) | BufferEncoding | undefined | null, callback: (err: NodeJS.ErrnoException | null, files?: string[] | Buffer[]) => void): void,
217 * (path: PathLike, callback: (err: NodeJS.ErrnoException | null, files?: string[]) => void): void,
218 * (path: PathLike, options: ObjectEncodingOptions & { withFileTypes: true, recursive?: boolean | undefined }, callback: (err: NodeJS.ErrnoException | null, files?: Dirent<string>[]) => void): void,
219 * (path: PathLike, options: { encoding: "buffer", withFileTypes: true, recursive?: boolean | undefined }, callback: (err: NodeJS.ErrnoException | null, files: Dirent<Buffer>[]) => void): void,
220 * }} Readdir
221 */
222
223/**
224 * Describes the readdir sync shape.
225 * @typedef {{
226 * (path: PathLike, options?: { encoding: BufferEncoding | null, withFileTypes?: false | undefined, recursive?: boolean | undefined } | BufferEncoding | null): string[],
227 * (path: PathLike, options: { encoding: "buffer", withFileTypes?: false | undefined, recursive?: boolean | undefined } | "buffer"): Buffer[],
228 * (path: PathLike, options?: (ObjectEncodingOptions & { withFileTypes?: false | undefined, recursive?: boolean | undefined }) | BufferEncoding | null): string[] | Buffer[],
229 * (path: PathLike, options: ObjectEncodingOptions & { withFileTypes: true, recursive?: boolean | undefined }): Dirent[],
230 * (path: PathLike, options: { encoding: "buffer", withFileTypes: true, recursive?: boolean | undefined }): Dirent<Buffer>[],
231 * }} ReaddirSync
232 */
233
234/**
235 * Describes the stat shape.
236 * @typedef {{
237 * (path: PathLike, callback: StatsCallback): void,
238 * (path: PathLike, options: (StatOptions & { bigint?: false | undefined }) | undefined, callback: StatsCallback): void,
239 * (path: PathLike, options: StatOptions & { bigint: true }, callback: BigIntStatsCallback): void,
240 * (path: PathLike, options: StatOptions | undefined, callback: StatsOrBigIntStatsCallback): void,
241 * }} Stat
242 */
243
244/**
245 * Describes the stat sync shape.
246 * @typedef {{
247 * (path: PathLike): IStats,
248 * (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined, throwIfNoEntry?: true | undefined }): IStats,
249 * (path: PathLike, options: StatSyncOptions & { bigint: true, throwIfNoEntry?: true | undefined }): IBigIntStats,
250 * (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined, throwIfNoEntry: false }): IStats | undefined,
251 * (path: PathLike, options: StatSyncOptions & { bigint: true, throwIfNoEntry: false }): IBigIntStats | undefined,
252 * (path: PathLike, options: StatSyncOptions & { bigint: boolean, throwIfNoEntry?: true | undefined }): IStats | IBigIntStats,
253 * (path: PathLike, options?: StatSyncOptions): IStats | IBigIntStats | undefined,
254 * }} StatSync
255 */
256
257/**
258 * Describes the l stat shape.
259 * @typedef {{
260 * (path: PathLike, callback: StatsCallback): void,
261 * (path: PathLike, options: (StatOptions & { bigint?: false | undefined }) | undefined, callback: StatsCallback): void,
262 * (path: PathLike, options: StatOptions & { bigint: true }, callback: BigIntStatsCallback): void,
263 * (path: PathLike, options: StatOptions | undefined, callback: StatsOrBigIntStatsCallback): void,
264 * }} LStat
265 */
266
267/**
268 * Describes the l stat sync shape.
269 * @typedef {{
270 * (path: PathLike): IStats,
271 * (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined, throwIfNoEntry?: true | undefined }): IStats,
272 * (path: PathLike, options: StatSyncOptions & { bigint: true, throwIfNoEntry?: true | undefined }): IBigIntStats,
273 * (path: PathLike, options?: StatSyncOptions & { bigint?: false | undefined, throwIfNoEntry: false }): IStats | undefined,
274 * (path: PathLike, options: StatSyncOptions & { bigint: true, throwIfNoEntry: false }): IBigIntStats | undefined,
275 * (path: PathLike, options: StatSyncOptions & { bigint: boolean, throwIfNoEntry?: true | undefined }): IStats | IBigIntStats,
276 * (path: PathLike, options?: StatSyncOptions): IStats | IBigIntStats | undefined,
277 * }} LStatSync
278 */
279
280/**
281 * Describes the real path shape.
282 * @typedef {{
283 * (path: PathLike, options: EncodingOption, callback: StringCallback): void,
284 * (path: PathLike, options: BufferEncodingOption, callback: BufferCallback): void,
285 * (path: PathLike, options: EncodingOption, callback: StringOrBufferCallback): void,
286 * (path: PathLike, callback: StringCallback): void,
287 * }} RealPath
288 */
289
290/**
291 * Describes the real path sync shape.
292 * @typedef {{
293 * (path: PathLike, options?: EncodingOption): string,
294 * (path: PathLike, options: BufferEncodingOption): Buffer,
295 * (path: PathLike, options?: EncodingOption): string | Buffer,
296 * }} RealPathSync
297 */
298
299/**
300 * Defines the read json type used by this module.
301 * @typedef {(pathOrFileDescriptor: PathOrFileDescriptor, callback: ReadJsonCallback) => void} ReadJson
302 */
303
304/**
305 * Defines the read json sync type used by this module.
306 * @typedef {(pathOrFileDescriptor: PathOrFileDescriptor) => JsonObject} ReadJsonSync
307 */
308
309/**
310 * Defines the purge type used by this module.
311 * @typedef {(value?: string | string[] | Set<string>) => void} Purge
312 */
313
314/**
315 * Defines the input file system type used by this module.
316 * @typedef {object} InputFileSystem
317 * @property {ReadFile} readFile
318 * @property {ReadFileSync=} readFileSync
319 * @property {Readlink} readlink
320 * @property {ReadlinkSync=} readlinkSync
321 * @property {Readdir} readdir
322 * @property {ReaddirSync=} readdirSync
323 * @property {Stat} stat
324 * @property {StatSync=} statSync
325 * @property {LStat=} lstat
326 * @property {LStatSync=} lstatSync
327 * @property {RealPath=} realpath
328 * @property {RealPathSync=} realpathSync
329 * @property {ReadJson=} readJson
330 * @property {ReadJsonSync=} readJsonSync
331 * @property {Purge=} purge
332 * @property {((path1: string, path2: string) => string)=} join
333 * @property {((from: string, to: string) => string)=} relative
334 * @property {((dirname: string) => string)=} dirname
335 */
336
337/**
338 * Defines the mode type used by this module.
339 * @typedef {number | string} Mode
340 */
341
342/**
343 * Defines the write file options type used by this module.
344 * @typedef {(ObjectEncodingOptions & import("events").Abortable & { mode?: Mode | undefined, flag?: string | undefined, flush?: boolean | undefined }) | BufferEncoding | null} WriteFileOptions
345 */
346
347/**
348 * Describes the write file shape.
349 * @typedef {{
350 * (file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, options: WriteFileOptions, callback: NoParamCallback): void,
351 * (file: PathOrFileDescriptor, data: string | NodeJS.ArrayBufferView, callback: NoParamCallback): void,
352 * }} WriteFile
353 */
354
355/**
356 * Defines the make directory options type used by this module.
357 * @typedef {{ recursive?: boolean | undefined, mode?: Mode | undefined }} MakeDirectoryOptions
358 */
359
360/**
361 * Describes the mkdir shape.
362 * @typedef {{
363 * (file: PathLike, options: MakeDirectoryOptions & { recursive: true }, callback: StringCallback): void,
364 * (file: PathLike, options: Mode | (MakeDirectoryOptions & { recursive?: false | undefined }) | null | undefined, callback: NoParamCallback): void,
365 * (file: PathLike, options: Mode | MakeDirectoryOptions | null | undefined, callback: StringCallback): void,
366 * (file: PathLike, callback: NoParamCallback): void,
367 * }} Mkdir
368 */
369
370/**
371 * Defines the rmdir type used by this module.
372 * @typedef {{ (file: PathLike, callback: NoParamCallback): void }} Rmdir
373 */
374
375/**
376 * Defines the unlink type used by this module.
377 * @typedef {(pathLike: PathLike, callback: NoParamCallback) => void} Unlink
378 */
379
380/**
381 * Defines the create read stream fs implementation type used by this module.
382 * @typedef {FSImplementation & { read: (...args: EXPECTED_ANY[]) => EXPECTED_ANY }} CreateReadStreamFSImplementation
383 */
384
385/**
386 * Defines the read stream options type used by this module.
387 * @typedef {StreamOptions & { fs?: CreateReadStreamFSImplementation | null | undefined, end?: number | undefined }} ReadStreamOptions
388 */
389
390/**
391 * Defines the create read stream type used by this module.
392 * @typedef {(path: PathLike, options?: BufferEncoding | ReadStreamOptions) => NodeJS.ReadableStream} CreateReadStream
393 */
394
395/**
396 * Defines the output file system type used by this module.
397 * @typedef {object} OutputFileSystem
398 * @property {Mkdir} mkdir
399 * @property {Readdir=} readdir
400 * @property {Rmdir=} rmdir
401 * @property {WriteFile} writeFile
402 * @property {Unlink=} unlink
403 * @property {Stat} stat
404 * @property {LStat=} lstat
405 * @property {ReadFile} readFile
406 * @property {CreateReadStream=} createReadStream
407 * @property {((path1: string, path2: string) => string)=} join
408 * @property {((from: string, to: string) => string)=} relative
409 * @property {((dirname: string) => string)=} dirname
410 */
411
412/**
413 * Defines the watch file system type used by this module.
414 * @typedef {object} WatchFileSystem
415 * @property {WatchMethod} watch
416 */
417
418/**
419 * Describes the mkdir sync shape.
420 * @typedef {{
421 * (path: PathLike, options: MakeDirectoryOptions & { recursive: true }): string | undefined,
422 * (path: PathLike, options?: Mode | (MakeDirectoryOptions & { recursive?: false | undefined }) | null): void,
423 * (path: PathLike, options?: Mode | MakeDirectoryOptions | null): string | undefined,
424 * }} MkdirSync
425 */
426
427/**
428 * Defines the stream options type used by this module.
429 * @typedef {object} StreamOptions
430 * @property {(string | undefined)=} flags
431 * @property {(BufferEncoding | undefined)} encoding
432 * @property {(number | EXPECTED_ANY | undefined)=} fd
433 * @property {(number | undefined)=} mode
434 * @property {(boolean | undefined)=} autoClose
435 * @property {(boolean | undefined)=} emitClose
436 * @property {(number | undefined)=} start
437 * @property {(AbortSignal | null | undefined)=} signal
438 */
439
440/**
441 * Defines the fs implementation type used by this module.
442 * @typedef {object} FSImplementation
443 * @property {((...args: EXPECTED_ANY[]) => EXPECTED_ANY)=} open
444 * @property {((...args: EXPECTED_ANY[]) => EXPECTED_ANY)=} close
445 */
446
447/**
448 * Defines the create write stream fs implementation type used by this module.
449 * @typedef {FSImplementation & { write: (...args: EXPECTED_ANY[]) => EXPECTED_ANY, close?: (...args: EXPECTED_ANY[]) => EXPECTED_ANY }} CreateWriteStreamFSImplementation
450 */
451
452/**
453 * Defines the write stream options type used by this module.
454 * @typedef {StreamOptions & { fs?: CreateWriteStreamFSImplementation | null | undefined, flush?: boolean | undefined }} WriteStreamOptions
455 */
456
457/**
458 * Defines the create write stream type used by this module.
459 * @typedef {(pathLike: PathLike, result?: BufferEncoding | WriteStreamOptions) => NodeJS.WritableStream} CreateWriteStream
460 */
461
462/**
463 * Defines the open mode type used by this module.
464 * @typedef {number | string} OpenMode
465 */
466
467/**
468 * Describes the open shape.
469 * @typedef {{
470 * (file: PathLike, flags: OpenMode | undefined, mode: Mode | undefined | null, callback: NumberCallback): void,
471 * (file: PathLike, flags: OpenMode | undefined, callback: NumberCallback): void,
472 * (file: PathLike, callback: NumberCallback): void,
473 * }} Open
474 */
475
476/**
477 * Defines the read position type used by this module.
478 * @typedef {number | bigint} ReadPosition
479 */
480
481/**
482 * Defines the read sync options type used by this module.
483 * @typedef {object} ReadSyncOptions
484 * @property {(number | undefined)=} offset
485 * @property {(number | undefined)=} length
486 * @property {(ReadPosition | null | undefined)=} position
487 */
488
489/**
490 * Defines the read async options type used by this module.
491 * @template {NodeJS.ArrayBufferView} TBuffer
492 * @typedef {object} ReadAsyncOptions
493 * @property {(number | undefined)=} offset
494 * @property {(number | undefined)=} length
495 * @property {(ReadPosition | null | undefined)=} position
496 * @property {TBuffer=} buffer
497 */
498
499/**
500 * Defines the shared type used by this module.
501 * @template {NodeJS.ArrayBufferView} [TBuffer=NodeJS.ArrayBufferView]
502 * @typedef {{
503 * (fd: number, buffer: TBuffer, offset: number, length: number, position: ReadPosition | null, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void): void,
504 * (fd: number, options: ReadAsyncOptions<TBuffer>, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void): void,
505 * (fd: number, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: NodeJS.ArrayBufferView) => void): void,
506 * }} Read
507 */
508
509/** @typedef {(df: number, callback: NoParamCallback) => void} Close */
510
511/** @typedef {(a: PathLike, b: PathLike, callback: NoParamCallback) => void} Rename */
512
513/**
514 * Defines the intermediate file system extras type used by this module.
515 * @typedef {object} IntermediateFileSystemExtras
516 * @property {MkdirSync} mkdirSync
517 * @property {CreateWriteStream} createWriteStream
518 * @property {Open} open
519 * @property {Read} read
520 * @property {Close} close
521 * @property {Rename} rename
522 */
523
524/** @typedef {InputFileSystem & OutputFileSystem & IntermediateFileSystemExtras} IntermediateFileSystem */
525
526/**
527 * Returns location of targetPath relative to rootPath.
528 * @param {InputFileSystem | OutputFileSystem | undefined} fs a file system
529 * @param {string} rootPath the root path
530 * @param {string} targetPath the target path
531 * @returns {string} location of targetPath relative to rootPath
532 */
533const relative = (fs, rootPath, targetPath) => {
534 if (fs && fs.relative) {
535 return fs.relative(rootPath, targetPath);
536 } else if (path.posix.isAbsolute(rootPath)) {
537 return path.posix.relative(rootPath, targetPath);
538 } else if (path.win32.isAbsolute(rootPath)) {
539 return path.win32.relative(rootPath, targetPath);
540 }
541 throw new Error(
542 `${rootPath} is neither a posix nor a windows path, and there is no 'relative' method defined in the file system`
543 );
544};
545
546/**
547 * Returns the joined path.
548 * @param {InputFileSystem | OutputFileSystem | undefined} fs a file system
549 * @param {string} rootPath a path
550 * @param {string} filename a filename
551 * @returns {string} the joined path
552 */
553const join = (fs, rootPath, filename) => {
554 if (fs && fs.join) {
555 return fs.join(rootPath, filename);
556 } else if (path.posix.isAbsolute(rootPath)) {
557 return path.posix.join(rootPath, filename);
558 } else if (path.win32.isAbsolute(rootPath)) {
559 return path.win32.join(rootPath, filename);
560 }
561 throw new Error(
562 `${rootPath} is neither a posix nor a windows path, and there is no 'join' method defined in the file system`
563 );
564};
565
566/**
567 * Returns the parent directory of the absolute path.
568 * @param {InputFileSystem | OutputFileSystem | undefined} fs a file system
569 * @param {string} absPath an absolute path
570 * @returns {string} the parent directory of the absolute path
571 */
572const dirname = (fs, absPath) => {
573 if (fs && fs.dirname) {
574 return fs.dirname(absPath);
575 } else if (path.posix.isAbsolute(absPath)) {
576 return path.posix.dirname(absPath);
577 } else if (path.win32.isAbsolute(absPath)) {
578 return path.win32.dirname(absPath);
579 }
580 throw new Error(
581 `${absPath} is neither a posix nor a windows path, and there is no 'dirname' method defined in the file system`
582 );
583};
584
585/**
586 * Processes the provided f.
587 * @param {OutputFileSystem} fs a file system
588 * @param {string} p an absolute path
589 * @param {(err?: Error) => void} callback callback function for the error
590 * @returns {void}
591 */
592const mkdirp = (fs, p, callback) => {
593 fs.mkdir(p, (err) => {
594 if (err) {
595 if (err.code === "ENOENT") {
596 const dir = dirname(fs, p);
597 if (dir === p) {
598 callback(err);
599 return;
600 }
601 mkdirp(fs, dir, (err) => {
602 if (err) {
603 callback(err);
604 return;
605 }
606 fs.mkdir(p, (err) => {
607 if (err) {
608 if (err.code === "EEXIST") {
609 callback();
610 return;
611 }
612 callback(err);
613 return;
614 }
615 callback();
616 });
617 });
618 return;
619 } else if (err.code === "EEXIST") {
620 callback();
621 return;
622 }
623 callback(err);
624 return;
625 }
626 callback();
627 });
628};
629
630/**
631 * Processes the provided f.
632 * @param {IntermediateFileSystem} fs a file system
633 * @param {string} p an absolute path
634 * @returns {void}
635 */
636const mkdirpSync = (fs, p) => {
637 try {
638 fs.mkdirSync(p);
639 } catch (err) {
640 if (err) {
641 if (/** @type {NodeJS.ErrnoException} */ (err).code === "ENOENT") {
642 const dir = dirname(fs, p);
643 if (dir === p) {
644 throw err;
645 }
646 mkdirpSync(fs, dir);
647 fs.mkdirSync(p);
648 return;
649 } else if (/** @type {NodeJS.ErrnoException} */ (err).code === "EEXIST") {
650 return;
651 }
652 throw err;
653 }
654 }
655};
656
657/**
658 * Processes the provided f.
659 * @param {InputFileSystem} fs a file system
660 * @param {string} p an absolute path
661 * @param {ReadJsonCallback} callback callback
662 * @returns {void}
663 */
664const readJson = (fs, p, callback) => {
665 if ("readJson" in fs) {
666 return /** @type {NonNullable<InputFileSystem["readJson"]>} */ (
667 fs.readJson
668 )(p, callback);
669 }
670 fs.readFile(p, (err, buf) => {
671 if (err) return callback(err);
672 /** @type {JsonObject} */
673 let data;
674 try {
675 data = JSON.parse(/** @type {Buffer} */ (buf).toString("utf8"));
676 } catch (err1) {
677 return callback(/** @type {Error} */ (err1));
678 }
679 return callback(null, data);
680 });
681};
682
683/**
684 * Lstat readlink absolute.
685 * @param {InputFileSystem} fs a file system
686 * @param {string} p an absolute path
687 * @param {(err: NodeJS.ErrnoException | Error | null, stats?: IStats | string) => void} callback callback
688 * @returns {void}
689 */
690const lstatReadlinkAbsolute = (fs, p, callback) => {
691 let i = 3;
692 const doReadLink = () => {
693 fs.readlink(p, (err, target) => {
694 if (err && --i > 0) {
695 // It might was just changed from symlink to file
696 // we retry 2 times to catch this case before throwing the error
697 return doStat();
698 }
699 if (err) return callback(err);
700 const value = /** @type {string} */ (target).toString();
701 callback(null, join(fs, dirname(fs, p), value));
702 });
703 };
704 const doStat = () => {
705 if ("lstat" in fs) {
706 return /** @type {NonNullable<InputFileSystem["lstat"]>} */ (fs.lstat)(
707 p,
708 (err, stats) => {
709 if (err) return callback(err);
710 if (/** @type {IStats} */ (stats).isSymbolicLink()) {
711 return doReadLink();
712 }
713 callback(null, stats);
714 }
715 );
716 }
717 return fs.stat(p, callback);
718 };
719 if ("lstat" in fs) return doStat();
720 doReadLink();
721};
722
723/**
724 * Checks whether this object is absolute.
725 * @param {string} pathname a path
726 * @returns {boolean} is absolute
727 */
728const isAbsolute = (pathname) =>
729 path.posix.isAbsolute(pathname) || path.win32.isAbsolute(pathname);
730
731module.exports.dirname = dirname;
732module.exports.isAbsolute = isAbsolute;
733module.exports.join = join;
734module.exports.lstatReadlinkAbsolute = lstatReadlinkAbsolute;
735module.exports.mkdirp = mkdirp;
736module.exports.mkdirpSync = mkdirpSync;
737module.exports.readJson = readJson;
738module.exports.relative = relative;
Note: See TracBrowser for help on using the repository browser.