rrdir 13.1.1 → 13.2.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/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { Stats } from 'node:fs';
2
2
  import { Matcher } from 'picomatch';
3
-
4
- type Encoding = "utf8" | "buffer";
5
- type Dir = string | Uint8Array;
6
- type RRDirOpts = {
3
+ export type Encoding = "utf8" | "buffer";
4
+ export type Dir = string | Uint8Array;
5
+ export type DirNodeCompatible = string | Buffer;
6
+ export type RRDirOpts = {
7
7
  strict?: boolean;
8
8
  stats?: boolean;
9
9
  followSymlinks?: boolean;
@@ -16,7 +16,7 @@ type InternalOpts = {
16
16
  excludeMatcher?: Matcher;
17
17
  encoding?: Encoding;
18
18
  };
19
- type Entry = {
19
+ export type Entry = {
20
20
  /** The path to the entry, will be relative if `dir` is given relative. If `dir` is a `Uint8Array`, this will be too. Always present. */
21
21
  path: Dir;
22
22
  /** Boolean indicating whether the entry is a directory. `undefined` on error. */
@@ -32,3 +32,4 @@ export declare function rrdir(dir: Dir, opts?: RRDirOpts, { includeMatcher, excl
32
32
  export declare function rrdirAsync(dir: Dir, opts?: RRDirOpts, { includeMatcher, excludeMatcher, encoding }?: InternalOpts): Promise<Entry[]>;
33
33
  export declare function rrdirSync(dir: Dir, opts?: RRDirOpts, { includeMatcher, excludeMatcher, encoding }?: InternalOpts): Entry[];
34
34
  export {};
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,KAAK,EAAS,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAQvC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AACzC,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AACtC,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAA;AAED,KAAK,YAAY,GAAG;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,wIAAwI;IACxI,IAAI,EAAE,GAAG,CAAC;IACV,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0IAA0I;IAC1I,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,8EAA8E;IAC9E,GAAG,CAAC,EAAE,KAAK,CAAC;CACb,CAAA;AA6CD,wBAAuB,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,GAAE,SAAc,EAAE,EAAC,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAC,GAAE,YAAiB,GAAG,cAAc,CAAC,KAAK,CAAC,CAkDjJ;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,GAAE,SAAc,EAAE,EAAC,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAC,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAqDhJ;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,GAAE,SAAc,EAAE,EAAC,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAC,GAAE,YAAiB,GAAG,KAAK,EAAE,CAoDhI"}
package/dist/index.js CHANGED
@@ -1,164 +1,190 @@
1
- import { readdir as U, stat as b, lstat as g } from "node:fs/promises";
2
- import { readdirSync as I, statSync as $, lstatSync as E } from "node:fs";
3
- import { sep as F, resolve as A } from "node:path";
4
- import P from "picomatch";
5
- const T = new TextEncoder(), O = T.encode.bind(T), p = new TextDecoder(), h = p.decode.bind(p), j = O(F), S = (t) => t instanceof Uint8Array ? "buffer" : "utf8", k = {
6
- strict: !1,
7
- stats: !1,
8
- followSymlinks: !1,
1
+ import { readdir, stat, lstat } from "node:fs/promises";
2
+ import { readdirSync, statSync, lstatSync } from "node:fs";
3
+ import { sep, resolve } from "node:path";
4
+ import picomatch from "picomatch";
5
+ const encoder = new TextEncoder();
6
+ const toUint8Array = encoder.encode.bind(encoder);
7
+ const decoder = new TextDecoder();
8
+ const toString = decoder.decode.bind(decoder);
9
+ const sepUint8Array = toUint8Array(sep);
10
+ const getEncoding = (dir) => dir instanceof Uint8Array ? "buffer" : "utf8";
11
+ const defaultOpts = {
12
+ strict: false,
13
+ stats: false,
14
+ followSymlinks: false,
9
15
  exclude: void 0,
10
16
  include: void 0,
11
- insensitive: !1
17
+ insensitive: false
12
18
  };
13
- function v({ name: t }, i, s) {
14
- return s === "buffer" ? i === "." ? t : Uint8Array.from([...i, ...j, ...t]) : i === "." ? t : `${i}${F}${t}`;
19
+ function makePath({ name }, dir, encoding) {
20
+ if (encoding === "buffer") {
21
+ return dir === "." ? name : Uint8Array.from([...dir, ...sepUint8Array, ...name]);
22
+ } else {
23
+ return dir === "." ? name : `${dir}${sep}${name}`;
24
+ }
15
25
  }
16
- function D(t, i, s, l) {
26
+ function build(dirent, path, stats, opts) {
17
27
  return {
18
- path: i,
19
- directory: (s || t).isDirectory(),
20
- symlink: (s || t).isSymbolicLink(),
21
- ...l.stats ? { stats: s } : {}
28
+ path,
29
+ directory: (stats || dirent).isDirectory(),
30
+ symlink: (stats || dirent).isSymbolicLink(),
31
+ ...opts.stats ? { stats } : {}
22
32
  };
23
33
  }
24
- function L({ include: t, exclude: i, insensitive: s }) {
25
- const l = {
26
- dot: !0,
27
- flags: s ? "i" : void 0
34
+ function makeMatchers({ include, exclude, insensitive }) {
35
+ const opts = {
36
+ dot: true,
37
+ flags: insensitive ? "i" : void 0
28
38
  };
29
39
  return {
30
- includeMatcher: t?.length ? (f) => P(t, l)(A(f)) : null,
31
- excludeMatcher: i?.length ? (f) => P(i, l)(A(f)) : null
40
+ includeMatcher: include?.length ? (path) => picomatch(include, opts)(resolve(path)) : null,
41
+ excludeMatcher: exclude?.length ? (path) => picomatch(exclude, opts)(resolve(path)) : null
32
42
  };
33
43
  }
34
- async function* q(t, i = {}, { includeMatcher: s, excludeMatcher: l, encoding: f } = {}) {
35
- s === void 0 && (i = { ...k, ...i }, { includeMatcher: s, excludeMatcher: l } = L(i), typeof t == "string" && /[/\\]$/.test(t) && (t = t.substring(0, t.length - 1)), f = S(t));
36
- let n = [];
44
+ async function* rrdir(dir, opts = {}, { includeMatcher, excludeMatcher, encoding } = {}) {
45
+ if (includeMatcher === void 0) {
46
+ opts = { ...defaultOpts, ...opts };
47
+ ({ includeMatcher, excludeMatcher } = makeMatchers(opts));
48
+ if (typeof dir === "string" && /[/\\]$/.test(dir)) dir = dir.substring(0, dir.length - 1);
49
+ encoding = getEncoding(dir);
50
+ }
51
+ let dirents = [];
37
52
  try {
38
- n = await U(t, { encoding: f, withFileTypes: !0 });
39
- } catch (y) {
40
- if (i.strict)
41
- throw y;
42
- yield { path: t, err: y };
53
+ dirents = await readdir(dir, { encoding, withFileTypes: true });
54
+ } catch (err) {
55
+ if (opts.strict) throw err;
56
+ yield { path: dir, err };
43
57
  }
44
- if (n.length)
45
- for (const y of n) {
46
- const r = v(y, t, f);
47
- if (l?.(f === "buffer" ? h(r) : r))
48
- continue;
49
- const e = i.followSymlinks && y.isSymbolicLink(), u = f === "buffer" ? h(r) : r, m = !s || s(u);
50
- let c;
51
- if (m) {
52
- if (i.stats || e)
53
- try {
54
- c = await (i.followSymlinks ? b : g)(r);
55
- } catch (a) {
56
- if (i.strict)
57
- throw a;
58
- yield { path: r, err: a };
59
- }
60
- yield D(y, r, c, i);
58
+ if (!dirents.length) return;
59
+ for (const dirent of dirents) {
60
+ const path = makePath(dirent, dir, encoding);
61
+ if (excludeMatcher?.(encoding === "buffer" ? toString(path) : path)) continue;
62
+ const isSymbolicLink = opts.followSymlinks && dirent.isSymbolicLink();
63
+ const encodedPath = encoding === "buffer" ? toString(path) : path;
64
+ const isIncluded = !includeMatcher || includeMatcher(encodedPath);
65
+ let stats;
66
+ if (isIncluded) {
67
+ if (opts.stats || isSymbolicLink) {
68
+ try {
69
+ stats = await (opts.followSymlinks ? stat : lstat)(path);
70
+ } catch (err) {
71
+ if (opts.strict) throw err;
72
+ yield { path, err };
73
+ }
74
+ }
75
+ yield build(dirent, path, stats, opts);
76
+ }
77
+ let recurse = false;
78
+ if (isSymbolicLink) {
79
+ if (!stats) try {
80
+ stats = await stat(path);
81
+ } catch {
61
82
  }
62
- let o = !1;
63
- if (e) {
64
- if (!c)
65
- try {
66
- c = await b(r);
67
- } catch {
68
- }
69
- c && c.isDirectory() && (o = !0);
70
- } else
71
- y.isDirectory() && (o = !0);
72
- o && (yield* q(r, i, { includeMatcher: s, excludeMatcher: l, encoding: f }));
83
+ if (stats && stats.isDirectory()) recurse = true;
84
+ } else if (dirent.isDirectory()) {
85
+ recurse = true;
73
86
  }
87
+ if (recurse) yield* rrdir(path, opts, { includeMatcher, excludeMatcher, encoding });
88
+ }
74
89
  }
75
- async function z(t, i = {}, { includeMatcher: s, excludeMatcher: l, encoding: f } = {}) {
76
- s === void 0 && (i = { ...k, ...i }, { includeMatcher: s, excludeMatcher: l } = L(i), typeof t == "string" && /[/\\]$/.test(t) && (t = t.substring(0, t.length - 1)), f = S(t));
77
- const n = [];
78
- let y = [];
90
+ async function rrdirAsync(dir, opts = {}, { includeMatcher, excludeMatcher, encoding } = {}) {
91
+ if (includeMatcher === void 0) {
92
+ opts = { ...defaultOpts, ...opts };
93
+ ({ includeMatcher, excludeMatcher } = makeMatchers(opts));
94
+ if (typeof dir === "string" && /[/\\]$/.test(dir)) dir = dir.substring(0, dir.length - 1);
95
+ encoding = getEncoding(dir);
96
+ }
97
+ const results = [];
98
+ let dirents = [];
79
99
  try {
80
- y = await U(t, { encoding: f, withFileTypes: !0 });
81
- } catch (r) {
82
- if (i.strict)
83
- throw r;
84
- n.push({ path: t, err: r });
100
+ dirents = await readdir(dir, { encoding, withFileTypes: true });
101
+ } catch (err) {
102
+ if (opts.strict) throw err;
103
+ results.push({ path: dir, err });
85
104
  }
86
- return y.length && await Promise.all(y.map(async (r) => {
87
- const e = v(r, t, f);
88
- if (l?.(f === "buffer" ? h(e) : e))
89
- return;
90
- const u = i.followSymlinks && r.isSymbolicLink(), m = f === "buffer" ? h(e) : e, c = !s || s(m);
91
- let o;
92
- if (c) {
93
- if (i.stats || u)
105
+ if (!dirents.length) return results;
106
+ await Promise.all(dirents.map(async (dirent) => {
107
+ const path = makePath(dirent, dir, encoding);
108
+ if (excludeMatcher?.(encoding === "buffer" ? toString(path) : path)) return;
109
+ const isSymbolicLink = opts.followSymlinks && dirent.isSymbolicLink();
110
+ const encodedPath = encoding === "buffer" ? toString(path) : path;
111
+ const isIncluded = !includeMatcher || includeMatcher(encodedPath);
112
+ let stats;
113
+ if (isIncluded) {
114
+ if (opts.stats || isSymbolicLink) {
94
115
  try {
95
- o = await (i.followSymlinks ? b : g)(e);
96
- } catch (w) {
97
- if (i.strict)
98
- throw w;
99
- n.push({ path: e, err: w });
116
+ stats = await (opts.followSymlinks ? stat : lstat)(path);
117
+ } catch (err) {
118
+ if (opts.strict) throw err;
119
+ results.push({ path, err });
100
120
  }
101
- n.push(D(r, e, o, i));
121
+ }
122
+ results.push(build(dirent, path, stats, opts));
102
123
  }
103
- let a = !1;
104
- if (u) {
105
- if (!o)
106
- try {
107
- o = await b(e);
108
- } catch {
109
- }
110
- o && o.isDirectory() && (a = !0);
111
- } else
112
- r.isDirectory() && (a = !0);
113
- a && n.push(...await z(e, i, { includeMatcher: s, excludeMatcher: l, encoding: f }));
114
- })), n;
124
+ let recurse = false;
125
+ if (isSymbolicLink) {
126
+ if (!stats) try {
127
+ stats = await stat(path);
128
+ } catch {
129
+ }
130
+ if (stats && stats.isDirectory()) recurse = true;
131
+ } else if (dirent.isDirectory()) {
132
+ recurse = true;
133
+ }
134
+ if (recurse) results.push(...await rrdirAsync(path, opts, { includeMatcher, excludeMatcher, encoding }));
135
+ }));
136
+ return results;
115
137
  }
116
- function B(t, i = {}, { includeMatcher: s, excludeMatcher: l, encoding: f } = {}) {
117
- s === void 0 && (i = { ...k, ...i }, { includeMatcher: s, excludeMatcher: l } = L(i), typeof t == "string" && /[/\\]$/.test(t) && (t = t.substring(0, t.length - 1)), f = S(t));
118
- const n = [];
119
- let y = [];
138
+ function rrdirSync(dir, opts = {}, { includeMatcher, excludeMatcher, encoding } = {}) {
139
+ if (includeMatcher === void 0) {
140
+ opts = { ...defaultOpts, ...opts };
141
+ ({ includeMatcher, excludeMatcher } = makeMatchers(opts));
142
+ if (typeof dir === "string" && /[/\\]$/.test(dir)) dir = dir.substring(0, dir.length - 1);
143
+ encoding = getEncoding(dir);
144
+ }
145
+ const results = [];
146
+ let dirents = [];
120
147
  try {
121
- y = I(t, { encoding: f, withFileTypes: !0 });
122
- } catch (r) {
123
- if (i.strict)
124
- throw r;
125
- n.push({ path: t, err: r });
148
+ dirents = readdirSync(dir, { encoding, withFileTypes: true });
149
+ } catch (err) {
150
+ if (opts.strict) throw err;
151
+ results.push({ path: dir, err });
126
152
  }
127
- if (!y.length)
128
- return n;
129
- for (const r of y) {
130
- const e = v(r, t, f);
131
- if (l?.(f === "buffer" ? h(e) : e))
132
- continue;
133
- const u = i.followSymlinks && r.isSymbolicLink(), m = f === "buffer" ? h(e) : e, c = !s || s(m);
134
- let o;
135
- if (c) {
136
- if (i.stats || u)
153
+ if (!dirents.length) return results;
154
+ for (const dirent of dirents) {
155
+ const path = makePath(dirent, dir, encoding);
156
+ if (excludeMatcher?.(encoding === "buffer" ? toString(path) : path)) continue;
157
+ const isSymbolicLink = opts.followSymlinks && dirent.isSymbolicLink();
158
+ const encodedPath = encoding === "buffer" ? toString(path) : path;
159
+ const isIncluded = !includeMatcher || includeMatcher(encodedPath);
160
+ let stats;
161
+ if (isIncluded) {
162
+ if (opts.stats || isSymbolicLink) {
137
163
  try {
138
- o = (i.followSymlinks ? $ : E)(e);
139
- } catch (w) {
140
- if (i.strict)
141
- throw w;
142
- n.push({ path: e, err: w });
164
+ stats = (opts.followSymlinks ? statSync : lstatSync)(path);
165
+ } catch (err) {
166
+ if (opts.strict) throw err;
167
+ results.push({ path, err });
143
168
  }
144
- n.push(D(r, e, o, i));
169
+ }
170
+ results.push(build(dirent, path, stats, opts));
145
171
  }
146
- let a = !1;
147
- if (u) {
148
- if (!o)
149
- try {
150
- o = $(e);
151
- } catch {
152
- }
153
- o && o.isDirectory() && (a = !0);
154
- } else
155
- r.isDirectory() && (a = !0);
156
- a && n.push(...B(e, i, { includeMatcher: s, excludeMatcher: l, encoding: f }));
172
+ let recurse = false;
173
+ if (isSymbolicLink) {
174
+ if (!stats) try {
175
+ stats = statSync(path);
176
+ } catch {
177
+ }
178
+ if (stats && stats.isDirectory()) recurse = true;
179
+ } else if (dirent.isDirectory()) {
180
+ recurse = true;
181
+ }
182
+ if (recurse) results.push(...rrdirSync(path, opts, { includeMatcher, excludeMatcher, encoding }));
157
183
  }
158
- return n;
184
+ return results;
159
185
  }
160
186
  export {
161
- q as rrdir,
162
- z as rrdirAsync,
163
- B as rrdirSync
187
+ rrdir,
188
+ rrdirAsync,
189
+ rrdirSync
164
190
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrdir",
3
- "version": "13.1.1",
3
+ "version": "13.2.0",
4
4
  "description": "Recursive directory reader with a delightful API",
5
5
  "author": "silverwind <me@silverwind.io>",
6
6
  "repository": "silverwind/rrdir",
@@ -20,17 +20,17 @@
20
20
  "picomatch": "^4.0.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@types/node": "20.12.12",
24
- "@types/picomatch": "2.3.3",
23
+ "@types/node": "22.10.1",
24
+ "@types/picomatch": "3.0.1",
25
25
  "eslint": "8.57.0",
26
- "eslint-config-silverwind": "83.0.1",
27
- "eslint-config-silverwind-typescript": "3.2.5",
28
- "typescript-config-silverwind": "4.2.0",
29
- "updates": "16.0.1",
30
- "versions": "12.0.1",
31
- "vite": "5.2.11",
32
- "vite-config-silverwind": "2.0.3",
33
- "vitest": "1.5.0",
34
- "vitest-config-silverwind": "8.0.4"
26
+ "eslint-config-silverwind": "94.2.1",
27
+ "eslint-config-silverwind-typescript": "9.2.0",
28
+ "typescript-config-silverwind": "6.1.1",
29
+ "updates": "16.4.0",
30
+ "versions": "12.1.2",
31
+ "vite": "6.0.1",
32
+ "vite-config-silverwind": "3.1.0",
33
+ "vitest": "2.1.6",
34
+ "vitest-config-silverwind": "9.2.0"
35
35
  }
36
36
  }