| 1 | /*
|
|---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
|---|
| 3 | Author Tobias Koppers @sokra
|
|---|
| 4 | */
|
|---|
| 5 |
|
|---|
| 6 | "use strict";
|
|---|
| 7 |
|
|---|
| 8 | const 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 | */
|
|---|
| 533 | const 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 | */
|
|---|
| 553 | const 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 | */
|
|---|
| 572 | const 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 | */
|
|---|
| 592 | const 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 | */
|
|---|
| 636 | const 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 | */
|
|---|
| 664 | const 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 | */
|
|---|
| 690 | const 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 | */
|
|---|
| 728 | const isAbsolute = (pathname) =>
|
|---|
| 729 | path.posix.isAbsolute(pathname) || path.win32.isAbsolute(pathname);
|
|---|
| 730 |
|
|---|
| 731 | module.exports.dirname = dirname;
|
|---|
| 732 | module.exports.isAbsolute = isAbsolute;
|
|---|
| 733 | module.exports.join = join;
|
|---|
| 734 | module.exports.lstatReadlinkAbsolute = lstatReadlinkAbsolute;
|
|---|
| 735 | module.exports.mkdirp = mkdirp;
|
|---|
| 736 | module.exports.mkdirpSync = mkdirpSync;
|
|---|
| 737 | module.exports.readJson = readJson;
|
|---|
| 738 | module.exports.relative = relative;
|
|---|