source: imaps-frontend/node_modules/readdirp/index.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 9.8 KB
Line 
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ReaddirpStream = exports.EntryTypes = void 0;
4exports.readdirp = readdirp;
5exports.readdirpPromise = readdirpPromise;
6const promises_1 = require("node:fs/promises");
7const node_stream_1 = require("node:stream");
8const node_path_1 = require("node:path");
9exports.EntryTypes = {
10 FILE_TYPE: 'files',
11 DIR_TYPE: 'directories',
12 FILE_DIR_TYPE: 'files_directories',
13 EVERYTHING_TYPE: 'all',
14};
15const defaultOptions = {
16 root: '.',
17 fileFilter: (_entryInfo) => true,
18 directoryFilter: (_entryInfo) => true,
19 type: exports.EntryTypes.FILE_TYPE,
20 lstat: false,
21 depth: 2147483648,
22 alwaysStat: false,
23 highWaterMark: 4096,
24};
25Object.freeze(defaultOptions);
26const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';
27const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);
28const ALL_TYPES = [
29 exports.EntryTypes.DIR_TYPE,
30 exports.EntryTypes.EVERYTHING_TYPE,
31 exports.EntryTypes.FILE_DIR_TYPE,
32 exports.EntryTypes.FILE_TYPE,
33];
34const DIR_TYPES = new Set([
35 exports.EntryTypes.DIR_TYPE,
36 exports.EntryTypes.EVERYTHING_TYPE,
37 exports.EntryTypes.FILE_DIR_TYPE,
38]);
39const FILE_TYPES = new Set([
40 exports.EntryTypes.EVERYTHING_TYPE,
41 exports.EntryTypes.FILE_DIR_TYPE,
42 exports.EntryTypes.FILE_TYPE,
43]);
44const isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);
45const wantBigintFsStats = process.platform === 'win32';
46const emptyFn = (_entryInfo) => true;
47const normalizeFilter = (filter) => {
48 if (filter === undefined)
49 return emptyFn;
50 if (typeof filter === 'function')
51 return filter;
52 if (typeof filter === 'string') {
53 const fl = filter.trim();
54 return (entry) => entry.basename === fl;
55 }
56 if (Array.isArray(filter)) {
57 const trItems = filter.map((item) => item.trim());
58 return (entry) => trItems.some((f) => entry.basename === f);
59 }
60 return emptyFn;
61};
62/** Readable readdir stream, emitting new files as they're being listed. */
63class ReaddirpStream extends node_stream_1.Readable {
64 constructor(options = {}) {
65 super({
66 objectMode: true,
67 autoDestroy: true,
68 highWaterMark: options.highWaterMark,
69 });
70 const opts = { ...defaultOptions, ...options };
71 const { root, type } = opts;
72 this._fileFilter = normalizeFilter(opts.fileFilter);
73 this._directoryFilter = normalizeFilter(opts.directoryFilter);
74 const statMethod = opts.lstat ? promises_1.lstat : promises_1.stat;
75 // Use bigint stats if it's windows and stat() supports options (node 10+).
76 if (wantBigintFsStats) {
77 this._stat = (path) => statMethod(path, { bigint: true });
78 }
79 else {
80 this._stat = statMethod;
81 }
82 this._maxDepth = opts.depth ?? defaultOptions.depth;
83 this._wantsDir = type ? DIR_TYPES.has(type) : false;
84 this._wantsFile = type ? FILE_TYPES.has(type) : false;
85 this._wantsEverything = type === exports.EntryTypes.EVERYTHING_TYPE;
86 this._root = (0, node_path_1.resolve)(root);
87 this._isDirent = !opts.alwaysStat;
88 this._statsProp = this._isDirent ? 'dirent' : 'stats';
89 this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
90 // Launch stream with one parent, the root dir.
91 this.parents = [this._exploreDir(root, 1)];
92 this.reading = false;
93 this.parent = undefined;
94 }
95 async _read(batch) {
96 if (this.reading)
97 return;
98 this.reading = true;
99 try {
100 while (!this.destroyed && batch > 0) {
101 const par = this.parent;
102 const fil = par && par.files;
103 if (fil && fil.length > 0) {
104 const { path, depth } = par;
105 const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));
106 const awaited = await Promise.all(slice);
107 for (const entry of awaited) {
108 if (!entry) {
109 batch--;
110 return;
111 }
112 if (this.destroyed)
113 return;
114 const entryType = await this._getEntryType(entry);
115 if (entryType === 'directory' && this._directoryFilter(entry)) {
116 if (depth <= this._maxDepth) {
117 this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
118 }
119 if (this._wantsDir) {
120 this.push(entry);
121 batch--;
122 }
123 }
124 else if ((entryType === 'file' || this._includeAsFile(entry)) &&
125 this._fileFilter(entry)) {
126 if (this._wantsFile) {
127 this.push(entry);
128 batch--;
129 }
130 }
131 }
132 }
133 else {
134 const parent = this.parents.pop();
135 if (!parent) {
136 this.push(null);
137 break;
138 }
139 this.parent = await parent;
140 if (this.destroyed)
141 return;
142 }
143 }
144 }
145 catch (error) {
146 this.destroy(error);
147 }
148 finally {
149 this.reading = false;
150 }
151 }
152 async _exploreDir(path, depth) {
153 let files;
154 try {
155 files = await (0, promises_1.readdir)(path, this._rdOptions);
156 }
157 catch (error) {
158 this._onError(error);
159 }
160 return { files, depth, path };
161 }
162 async _formatEntry(dirent, path) {
163 let entry;
164 const basename = this._isDirent ? dirent.name : dirent;
165 try {
166 const fullPath = (0, node_path_1.resolve)((0, node_path_1.join)(path, basename));
167 entry = { path: (0, node_path_1.relative)(this._root, fullPath), fullPath, basename };
168 entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
169 }
170 catch (err) {
171 this._onError(err);
172 return;
173 }
174 return entry;
175 }
176 _onError(err) {
177 if (isNormalFlowError(err) && !this.destroyed) {
178 this.emit('warn', err);
179 }
180 else {
181 this.destroy(err);
182 }
183 }
184 async _getEntryType(entry) {
185 // entry may be undefined, because a warning or an error were emitted
186 // and the statsProp is undefined
187 if (!entry && this._statsProp in entry) {
188 return '';
189 }
190 const stats = entry[this._statsProp];
191 if (stats.isFile())
192 return 'file';
193 if (stats.isDirectory())
194 return 'directory';
195 if (stats && stats.isSymbolicLink()) {
196 const full = entry.fullPath;
197 try {
198 const entryRealPath = await (0, promises_1.realpath)(full);
199 const entryRealPathStats = await (0, promises_1.lstat)(entryRealPath);
200 if (entryRealPathStats.isFile()) {
201 return 'file';
202 }
203 if (entryRealPathStats.isDirectory()) {
204 const len = entryRealPath.length;
205 if (full.startsWith(entryRealPath) && full.substr(len, 1) === node_path_1.sep) {
206 const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
207 // @ts-ignore
208 recursiveError.code = RECURSIVE_ERROR_CODE;
209 return this._onError(recursiveError);
210 }
211 return 'directory';
212 }
213 }
214 catch (error) {
215 this._onError(error);
216 return '';
217 }
218 }
219 }
220 _includeAsFile(entry) {
221 const stats = entry && entry[this._statsProp];
222 return stats && this._wantsEverything && !stats.isDirectory();
223 }
224}
225exports.ReaddirpStream = ReaddirpStream;
226/**
227 * Streaming version: Reads all files and directories in given root recursively.
228 * Consumes ~constant small amount of RAM.
229 * @param root Root directory
230 * @param options Options to specify root (start directory), filters and recursion depth
231 */
232function readdirp(root, options = {}) {
233 // @ts-ignore
234 let type = options.entryType || options.type;
235 if (type === 'both')
236 type = exports.EntryTypes.FILE_DIR_TYPE; // backwards-compatibility
237 if (type)
238 options.type = type;
239 if (!root) {
240 throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
241 }
242 else if (typeof root !== 'string') {
243 throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
244 }
245 else if (type && !ALL_TYPES.includes(type)) {
246 throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
247 }
248 options.root = root;
249 return new ReaddirpStream(options);
250}
251/**
252 * Promise version: Reads all files and directories in given root recursively.
253 * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.
254 * @returns array of paths and their entry infos
255 */
256function readdirpPromise(root, options = {}) {
257 return new Promise((resolve, reject) => {
258 const files = [];
259 readdirp(root, options)
260 .on('data', (entry) => files.push(entry))
261 .on('end', () => resolve(files))
262 .on('error', (error) => reject(error));
263 });
264}
265exports.default = readdirp;
Note: See TracBrowser for help on using the repository browser.