@scelar/nodepod 1.0.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.
Files changed (134) hide show
  1. package/LICENSE +43 -0
  2. package/README.md +240 -0
  3. package/dist/child_process-BJOMsZje.js +8233 -0
  4. package/dist/child_process-BJOMsZje.js.map +1 -0
  5. package/dist/child_process-Cj8vOcuc.cjs +7434 -0
  6. package/dist/child_process-Cj8vOcuc.cjs.map +1 -0
  7. package/dist/index-Cb1Cgdnd.js +35308 -0
  8. package/dist/index-Cb1Cgdnd.js.map +1 -0
  9. package/dist/index-DsMGS-xc.cjs +37195 -0
  10. package/dist/index-DsMGS-xc.cjs.map +1 -0
  11. package/dist/index.cjs +65 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.mjs +59 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/package.json +95 -0
  16. package/src/__tests__/smoke.test.ts +11 -0
  17. package/src/constants/cdn-urls.ts +18 -0
  18. package/src/constants/config.ts +236 -0
  19. package/src/cross-origin.ts +26 -0
  20. package/src/engine-factory.ts +176 -0
  21. package/src/engine-types.ts +56 -0
  22. package/src/helpers/byte-encoding.ts +39 -0
  23. package/src/helpers/digest.ts +9 -0
  24. package/src/helpers/event-loop.ts +96 -0
  25. package/src/helpers/wasm-cache.ts +133 -0
  26. package/src/iframe-sandbox.ts +141 -0
  27. package/src/index.ts +192 -0
  28. package/src/isolation-helpers.ts +148 -0
  29. package/src/memory-volume.ts +941 -0
  30. package/src/module-transformer.ts +368 -0
  31. package/src/packages/archive-extractor.ts +248 -0
  32. package/src/packages/browser-bundler.ts +284 -0
  33. package/src/packages/installer.ts +396 -0
  34. package/src/packages/registry-client.ts +131 -0
  35. package/src/packages/version-resolver.ts +411 -0
  36. package/src/polyfills/assert.ts +384 -0
  37. package/src/polyfills/async_hooks.ts +144 -0
  38. package/src/polyfills/buffer.ts +628 -0
  39. package/src/polyfills/child_process.ts +2288 -0
  40. package/src/polyfills/chokidar.ts +336 -0
  41. package/src/polyfills/cluster.ts +106 -0
  42. package/src/polyfills/console.ts +136 -0
  43. package/src/polyfills/constants.ts +123 -0
  44. package/src/polyfills/crypto.ts +885 -0
  45. package/src/polyfills/dgram.ts +87 -0
  46. package/src/polyfills/diagnostics_channel.ts +76 -0
  47. package/src/polyfills/dns.ts +134 -0
  48. package/src/polyfills/domain.ts +68 -0
  49. package/src/polyfills/esbuild.ts +854 -0
  50. package/src/polyfills/events.ts +276 -0
  51. package/src/polyfills/fs.ts +2888 -0
  52. package/src/polyfills/fsevents.ts +79 -0
  53. package/src/polyfills/http.ts +1449 -0
  54. package/src/polyfills/http2.ts +199 -0
  55. package/src/polyfills/https.ts +76 -0
  56. package/src/polyfills/inspector.ts +62 -0
  57. package/src/polyfills/lightningcss.ts +105 -0
  58. package/src/polyfills/module.ts +191 -0
  59. package/src/polyfills/net.ts +353 -0
  60. package/src/polyfills/os.ts +238 -0
  61. package/src/polyfills/path.ts +206 -0
  62. package/src/polyfills/perf_hooks.ts +102 -0
  63. package/src/polyfills/process.ts +690 -0
  64. package/src/polyfills/punycode.ts +159 -0
  65. package/src/polyfills/querystring.ts +93 -0
  66. package/src/polyfills/quic.ts +118 -0
  67. package/src/polyfills/readdirp.ts +229 -0
  68. package/src/polyfills/readline.ts +692 -0
  69. package/src/polyfills/repl.ts +134 -0
  70. package/src/polyfills/rollup.ts +119 -0
  71. package/src/polyfills/sea.ts +33 -0
  72. package/src/polyfills/sqlite.ts +78 -0
  73. package/src/polyfills/stream.ts +1620 -0
  74. package/src/polyfills/string_decoder.ts +25 -0
  75. package/src/polyfills/tailwindcss-oxide.ts +309 -0
  76. package/src/polyfills/test.ts +197 -0
  77. package/src/polyfills/timers.ts +32 -0
  78. package/src/polyfills/tls.ts +105 -0
  79. package/src/polyfills/trace_events.ts +50 -0
  80. package/src/polyfills/tty.ts +71 -0
  81. package/src/polyfills/url.ts +174 -0
  82. package/src/polyfills/util.ts +559 -0
  83. package/src/polyfills/v8.ts +126 -0
  84. package/src/polyfills/vm.ts +132 -0
  85. package/src/polyfills/volume-registry.ts +15 -0
  86. package/src/polyfills/wasi.ts +44 -0
  87. package/src/polyfills/worker_threads.ts +326 -0
  88. package/src/polyfills/ws.ts +595 -0
  89. package/src/polyfills/zlib.ts +881 -0
  90. package/src/request-proxy.ts +716 -0
  91. package/src/script-engine.ts +3375 -0
  92. package/src/sdk/nodepod-fs.ts +93 -0
  93. package/src/sdk/nodepod-process.ts +86 -0
  94. package/src/sdk/nodepod-terminal.ts +350 -0
  95. package/src/sdk/nodepod.ts +509 -0
  96. package/src/sdk/types.ts +70 -0
  97. package/src/shell/commands/bun.ts +121 -0
  98. package/src/shell/commands/directory.ts +297 -0
  99. package/src/shell/commands/file-ops.ts +525 -0
  100. package/src/shell/commands/git.ts +2142 -0
  101. package/src/shell/commands/node.ts +80 -0
  102. package/src/shell/commands/npm.ts +198 -0
  103. package/src/shell/commands/pm-types.ts +45 -0
  104. package/src/shell/commands/pnpm.ts +82 -0
  105. package/src/shell/commands/search.ts +264 -0
  106. package/src/shell/commands/shell-env.ts +352 -0
  107. package/src/shell/commands/text-processing.ts +1152 -0
  108. package/src/shell/commands/yarn.ts +84 -0
  109. package/src/shell/shell-builtins.ts +19 -0
  110. package/src/shell/shell-helpers.ts +250 -0
  111. package/src/shell/shell-interpreter.ts +514 -0
  112. package/src/shell/shell-parser.ts +429 -0
  113. package/src/shell/shell-types.ts +85 -0
  114. package/src/syntax-transforms.ts +561 -0
  115. package/src/threading/engine-worker.ts +64 -0
  116. package/src/threading/inline-worker.ts +372 -0
  117. package/src/threading/offload-types.ts +112 -0
  118. package/src/threading/offload-worker.ts +383 -0
  119. package/src/threading/offload.ts +271 -0
  120. package/src/threading/process-context.ts +92 -0
  121. package/src/threading/process-handle.ts +275 -0
  122. package/src/threading/process-manager.ts +956 -0
  123. package/src/threading/process-worker-entry.ts +854 -0
  124. package/src/threading/shared-vfs.ts +352 -0
  125. package/src/threading/sync-channel.ts +135 -0
  126. package/src/threading/task-queue.ts +177 -0
  127. package/src/threading/vfs-bridge.ts +231 -0
  128. package/src/threading/worker-pool.ts +233 -0
  129. package/src/threading/worker-protocol.ts +358 -0
  130. package/src/threading/worker-vfs.ts +218 -0
  131. package/src/types/externals.d.ts +38 -0
  132. package/src/types/fs-streams.ts +142 -0
  133. package/src/types/manifest.ts +17 -0
  134. package/src/worker-sandbox.ts +90 -0
@@ -0,0 +1,159 @@
1
+ // Punycode/IDNA encoding for internationalized domain names (deprecated but still required by some packages)
2
+
3
+
4
+ const BASE = 36;
5
+ const TMIN = 1;
6
+ const TMAX = 26;
7
+ const SKEW = 38;
8
+ const DAMP = 700;
9
+ const INITIAL_BIAS = 72;
10
+ const INITIAL_N = 128;
11
+ const DELIMITER = "-";
12
+
13
+ function adapt(delta: number, numPoints: number, firstTime: boolean): number {
14
+ let d = firstTime ? Math.floor(delta / DAMP) : delta >> 1;
15
+ d += Math.floor(d / numPoints);
16
+ let k = 0;
17
+ while (d > ((BASE - TMIN) * TMAX) >> 1) {
18
+ d = Math.floor(d / (BASE - TMIN));
19
+ k += BASE;
20
+ }
21
+ return Math.floor(k + ((BASE - TMIN + 1) * d) / (d + SKEW));
22
+ }
23
+
24
+ function basicToDigit(cp: number): number {
25
+ if (cp - 48 < 10) return cp - 22;
26
+ if (cp - 65 < 26) return cp - 65;
27
+ if (cp - 97 < 26) return cp - 97;
28
+ return BASE;
29
+ }
30
+
31
+ function digitToBasic(digit: number, flag: boolean): number {
32
+ return digit + 22 + 75 * (digit < 26 ? 1 : 0) - ((flag ? 1 : 0) << 5);
33
+ }
34
+
35
+ export function decode(input: string): string {
36
+ const output: number[] = [];
37
+ let i = 0;
38
+ let n = INITIAL_N;
39
+ let bias = INITIAL_BIAS;
40
+
41
+ let basic = input.lastIndexOf(DELIMITER);
42
+ if (basic < 0) basic = 0;
43
+
44
+ for (let j = 0; j < basic; ++j) {
45
+ output.push(input.charCodeAt(j));
46
+ }
47
+
48
+ let index = basic > 0 ? basic + 1 : 0;
49
+
50
+ while (index < input.length) {
51
+ const oldi = i;
52
+ let w = 1;
53
+ let k = BASE;
54
+
55
+ while (true) {
56
+ if (index >= input.length) throw new RangeError("Invalid input");
57
+ const digit = basicToDigit(input.charCodeAt(index++));
58
+ if (digit >= BASE) throw new RangeError("Invalid input");
59
+ if (digit > Math.floor((0x7fffffff - i) / w)) throw new RangeError("Overflow");
60
+ i += digit * w;
61
+ const t = k <= bias ? TMIN : k >= bias + TMAX ? TMAX : k - bias;
62
+ if (digit < t) break;
63
+ if (w > Math.floor(0x7fffffff / (BASE - t))) throw new RangeError("Overflow");
64
+ w *= BASE - t;
65
+ k += BASE;
66
+ }
67
+
68
+ const out = output.length + 1;
69
+ bias = adapt(i - oldi, out, oldi === 0);
70
+ if (Math.floor(i / out) > 0x7fffffff - n) throw new RangeError("Overflow");
71
+ n += Math.floor(i / out);
72
+ i %= out;
73
+ output.splice(i++, 0, n);
74
+ }
75
+
76
+ return String.fromCodePoint(...output);
77
+ }
78
+
79
+ export function encode(input: string): string {
80
+ const output: string[] = [];
81
+ const inputCodes = Array.from(input).map((c) => c.codePointAt(0)!);
82
+ let n = INITIAL_N;
83
+ let delta = 0;
84
+ let bias = INITIAL_BIAS;
85
+
86
+ for (const cp of inputCodes) {
87
+ if (cp < 0x80) output.push(String.fromCharCode(cp));
88
+ }
89
+
90
+ let h = output.length;
91
+ const b = h;
92
+ if (b > 0) output.push(DELIMITER);
93
+
94
+ while (h < inputCodes.length) {
95
+ let m = 0x7fffffff;
96
+ for (const cp of inputCodes) {
97
+ if (cp >= n && cp < m) m = cp;
98
+ }
99
+
100
+ if (m - n > Math.floor((0x7fffffff - delta) / (h + 1)))
101
+ throw new RangeError("Overflow");
102
+ delta += (m - n) * (h + 1);
103
+ n = m;
104
+
105
+ for (const cp of inputCodes) {
106
+ if (cp < n && ++delta > 0x7fffffff) throw new RangeError("Overflow");
107
+ if (cp === n) {
108
+ let q = delta;
109
+ let k = BASE;
110
+ while (true) {
111
+ const t = k <= bias ? TMIN : k >= bias + TMAX ? TMAX : k - bias;
112
+ if (q < t) break;
113
+ output.push(String.fromCharCode(digitToBasic(t + ((q - t) % (BASE - t)), false)));
114
+ q = Math.floor((q - t) / (BASE - t));
115
+ k += BASE;
116
+ }
117
+ output.push(String.fromCharCode(digitToBasic(q, false)));
118
+ bias = adapt(delta, h + 1, h === b);
119
+ delta = 0;
120
+ ++h;
121
+ }
122
+ }
123
+
124
+ ++delta;
125
+ ++n;
126
+ }
127
+
128
+ return output.join("");
129
+ }
130
+
131
+ export function toUnicode(domain: string): string {
132
+ return domain
133
+ .split(".")
134
+ .map((label) =>
135
+ label.startsWith("xn--") ? decode(label.slice(4)) : label,
136
+ )
137
+ .join(".");
138
+ }
139
+
140
+ export function toASCII(domain: string): string {
141
+ return domain
142
+ .split(".")
143
+ .map((label) => {
144
+ if (/[^\x00-\x7E]/.test(label)) {
145
+ return "xn--" + encode(label);
146
+ }
147
+ return label;
148
+ })
149
+ .join(".");
150
+ }
151
+
152
+ export const ucs2 = {
153
+ decode: (str: string): number[] => Array.from(str).map((c) => c.codePointAt(0)!),
154
+ encode: (codePoints: number[]): string => String.fromCodePoint(...codePoints),
155
+ };
156
+
157
+ export const version = "2.3.1";
158
+
159
+ export default { decode, encode, toUnicode, toASCII, ucs2, version };
@@ -0,0 +1,93 @@
1
+ // Querystring parse/stringify/escape/unescape
2
+
3
+
4
+ export type ParsedQuery = Record<string, string | string[]>;
5
+
6
+ // supports duplicate keys (values become arrays) and custom separators
7
+ export function parse(
8
+ input: string,
9
+ pairSep: string = '&',
10
+ kvSep: string = '=',
11
+ options?: { maxKeys?: number }
12
+ ): ParsedQuery {
13
+ const output: ParsedQuery = {};
14
+ if (!input || typeof input !== 'string') return output;
15
+
16
+ const ceiling = options?.maxKeys || 1000;
17
+ const segments = input.split(pairSep);
18
+ const limit = ceiling > 0 ? Math.min(segments.length, ceiling) : segments.length;
19
+
20
+ for (let i = 0; i < limit; i++) {
21
+ const segment = segments[i];
22
+ const eqPos = segment.indexOf(kvSep);
23
+ let k: string;
24
+ let v: string;
25
+
26
+ if (eqPos >= 0) {
27
+ k = decodeURIComponent(segment.substring(0, eqPos).replace(/\+/g, ' '));
28
+ v = decodeURIComponent(segment.substring(eqPos + 1).replace(/\+/g, ' '));
29
+ } else {
30
+ k = decodeURIComponent(segment.replace(/\+/g, ' '));
31
+ v = '';
32
+ }
33
+
34
+ if (k in output) {
35
+ const prev = output[k];
36
+ if (Array.isArray(prev)) {
37
+ prev.push(v);
38
+ } else {
39
+ output[k] = [prev, v];
40
+ }
41
+ } else {
42
+ output[k] = v;
43
+ }
44
+ }
45
+
46
+ return output;
47
+ }
48
+
49
+ export function stringify(
50
+ obj: Record<string, string | string[] | number | boolean | undefined>,
51
+ pairSep: string = '&',
52
+ kvSep: string = '='
53
+ ): string {
54
+ if (!obj || typeof obj !== 'object') return '';
55
+
56
+ const parts: string[] = [];
57
+
58
+ for (const [key, val] of Object.entries(obj)) {
59
+ if (val === undefined) continue;
60
+ const encodedKey = encodeURIComponent(key);
61
+
62
+ if (Array.isArray(val)) {
63
+ for (const item of val) {
64
+ parts.push(`${encodedKey}${kvSep}${encodeURIComponent(String(item))}`);
65
+ }
66
+ } else {
67
+ parts.push(`${encodedKey}${kvSep}${encodeURIComponent(String(val))}`);
68
+ }
69
+ }
70
+
71
+ return parts.join(pairSep);
72
+ }
73
+
74
+ export function escape(text: string): string {
75
+ return encodeURIComponent(text);
76
+ }
77
+
78
+ export function unescape(text: string): string {
79
+ return decodeURIComponent(text.replace(/\+/g, ' '));
80
+ }
81
+
82
+ // Node.js compatibility aliases
83
+ export const encode = stringify;
84
+ export const decode = parse;
85
+
86
+ export default {
87
+ parse,
88
+ stringify,
89
+ escape,
90
+ unescape,
91
+ encode,
92
+ decode,
93
+ };
@@ -0,0 +1,118 @@
1
+ // stub - not available in browser
2
+
3
+
4
+ import { EventEmitter } from "./events";
5
+
6
+ /* ------------------------------------------------------------------ */
7
+ /* QuicEndpoint */
8
+ /* ------------------------------------------------------------------ */
9
+
10
+ export interface QuicEndpoint extends EventEmitter {
11
+ close(): void;
12
+ destroy(_err?: Error): void;
13
+ readonly address: { address: string; family: string; port: number };
14
+ }
15
+
16
+ interface QuicEndpointConstructor {
17
+ new (_opts?: object): QuicEndpoint;
18
+ (this: any, _opts?: object): void;
19
+ prototype: any;
20
+ }
21
+
22
+ export const QuicEndpoint = function QuicEndpoint(this: any, _opts?: object) {
23
+ if (!this) return;
24
+ EventEmitter.call(this);
25
+ } as unknown as QuicEndpointConstructor;
26
+
27
+ Object.setPrototypeOf(QuicEndpoint.prototype, EventEmitter.prototype);
28
+
29
+ QuicEndpoint.prototype.close = function close(this: any): void {
30
+ this.emit("close");
31
+ };
32
+
33
+ QuicEndpoint.prototype.destroy = function destroy(this: any, _err?: Error): void {
34
+ this.emit("close");
35
+ };
36
+
37
+ Object.defineProperty(QuicEndpoint.prototype, "address", {
38
+ get: function(this: any): { address: string; family: string; port: number } {
39
+ return { address: "0.0.0.0", family: "IPv4", port: 0 };
40
+ },
41
+ configurable: true,
42
+ });
43
+
44
+ /* ------------------------------------------------------------------ */
45
+ /* QuicSession */
46
+ /* ------------------------------------------------------------------ */
47
+
48
+ export interface QuicSession extends EventEmitter {
49
+ close(): void;
50
+ destroy(_err?: Error): void;
51
+ readonly destroyed: boolean;
52
+ }
53
+
54
+ interface QuicSessionConstructor {
55
+ new (): QuicSession;
56
+ (this: any): void;
57
+ prototype: any;
58
+ }
59
+
60
+ export const QuicSession = function QuicSession(this: any) {
61
+ if (!this) return;
62
+ EventEmitter.call(this);
63
+ } as unknown as QuicSessionConstructor;
64
+
65
+ Object.setPrototypeOf(QuicSession.prototype, EventEmitter.prototype);
66
+
67
+ QuicSession.prototype.close = function close(this: any): void {
68
+ this.emit("close");
69
+ };
70
+
71
+ QuicSession.prototype.destroy = function destroy(this: any, _err?: Error): void {
72
+ this.emit("close");
73
+ };
74
+
75
+ Object.defineProperty(QuicSession.prototype, "destroyed", {
76
+ get: function(this: any): boolean {
77
+ return false;
78
+ },
79
+ configurable: true,
80
+ });
81
+
82
+ /* ------------------------------------------------------------------ */
83
+ /* QuicStream */
84
+ /* ------------------------------------------------------------------ */
85
+
86
+ export interface QuicStream extends EventEmitter {
87
+ readonly id: number;
88
+ }
89
+
90
+ interface QuicStreamConstructor {
91
+ new (): QuicStream;
92
+ (this: any): void;
93
+ prototype: any;
94
+ }
95
+
96
+ export const QuicStream = function QuicStream(this: any) {
97
+ if (!this) return;
98
+ EventEmitter.call(this);
99
+ } as unknown as QuicStreamConstructor;
100
+
101
+ Object.setPrototypeOf(QuicStream.prototype, EventEmitter.prototype);
102
+
103
+ Object.defineProperty(QuicStream.prototype, "id", {
104
+ get: function(this: any): number {
105
+ return 0;
106
+ },
107
+ configurable: true,
108
+ });
109
+
110
+ /* ------------------------------------------------------------------ */
111
+ /* Default export */
112
+ /* ------------------------------------------------------------------ */
113
+
114
+ export default {
115
+ QuicEndpoint,
116
+ QuicSession,
117
+ QuicStream,
118
+ };
@@ -0,0 +1,229 @@
1
+ // Recursive directory listing polyfill (readdirp-compatible) on MemoryVolume
2
+
3
+
4
+ import type { MemoryVolume, FileStat } from "../memory-volume";
5
+ import { setSharedVolume, getSharedVolume } from "./volume-registry";
6
+
7
+
8
+ export function setVolume(vol: MemoryVolume): void {
9
+ setSharedVolume(vol);
10
+ }
11
+
12
+
13
+ export interface ScanOptions {
14
+ root?: string;
15
+ fileFilter?: string | string[] | ((entry: ScanEntry) => boolean);
16
+ directoryFilter?: string | string[] | ((entry: ScanEntry) => boolean);
17
+ depth?: number;
18
+ type?: "files" | "directories" | "files_directories" | "all";
19
+ lstat?: boolean;
20
+ alwaysStat?: boolean;
21
+ }
22
+
23
+ export interface ScanEntry {
24
+ path: string;
25
+ fullPath: string;
26
+ basename: string;
27
+ stats?: FileStat;
28
+ dirent?: {
29
+ isFile(): boolean;
30
+ isDirectory(): boolean;
31
+ name: string;
32
+ };
33
+ }
34
+
35
+ // collects entries synchronously, yields asynchronously
36
+
37
+ interface DirectoryScanner {
38
+ cfg: ScanOptions;
39
+ rootDir: string;
40
+ results: ScanEntry[];
41
+ scanned: boolean;
42
+ handlerMap: Map<string, Array<(...args: unknown[]) => void>>;
43
+ [Symbol.asyncIterator](): AsyncIterableIterator<ScanEntry>;
44
+ toArray(): Promise<ScanEntry[]>;
45
+ on(event: string, handler: (...args: unknown[]) => void): this;
46
+ once(event: string, handler: (...args: unknown[]) => void): this;
47
+ off(event: string, handler: (...args: unknown[]) => void): this;
48
+ fireEvent(event: string, ...args: unknown[]): void;
49
+ runScan(): void;
50
+ crawl(dir: string, level: number, relative: string): void;
51
+ applyFilter(entry: ScanEntry, filter?: string | string[] | ((e: ScanEntry) => boolean)): boolean;
52
+ globMatch(filename: string, pattern: string): boolean;
53
+ }
54
+
55
+ interface DirectoryScannerConstructor {
56
+ new (root: string, cfg?: ScanOptions): DirectoryScanner;
57
+ (this: any, root: string, cfg?: ScanOptions): void;
58
+ prototype: any;
59
+ }
60
+
61
+ const DirectoryScanner = function DirectoryScanner(this: any, root: string, cfg: ScanOptions = {}) {
62
+ if (!this) return;
63
+ this.rootDir = root;
64
+ this.cfg = cfg;
65
+ this.results = [];
66
+ this.scanned = false;
67
+ this.handlerMap = new Map<string, Array<(...args: unknown[]) => void>>();
68
+ } as unknown as DirectoryScannerConstructor;
69
+
70
+ DirectoryScanner.prototype[Symbol.asyncIterator] = async function*(this: any): AsyncIterableIterator<ScanEntry> {
71
+ this.runScan();
72
+ for (const entry of this.results) yield entry;
73
+ };
74
+
75
+ DirectoryScanner.prototype.toArray = async function toArray(this: any): Promise<ScanEntry[]> {
76
+ this.runScan();
77
+ return [...this.results];
78
+ };
79
+
80
+ DirectoryScanner.prototype.on = function on(this: any, event: string, handler: (...args: unknown[]) => void): any {
81
+ if (event === "data") {
82
+ setTimeout(() => {
83
+ this.runScan();
84
+ for (const entry of this.results) handler(entry);
85
+ this.fireEvent("end");
86
+ }, 0);
87
+ } else {
88
+ if (!this.handlerMap.has(event)) this.handlerMap.set(event, []);
89
+ this.handlerMap.get(event)!.push(handler);
90
+ }
91
+ return this;
92
+ };
93
+
94
+ DirectoryScanner.prototype.once = function once(this: any, event: string, handler: (...args: unknown[]) => void): any {
95
+ const self = this;
96
+ const wrapped = (...args: unknown[]) => {
97
+ handler(...args);
98
+ self.off(event, wrapped);
99
+ };
100
+ return this.on(event, wrapped);
101
+ };
102
+
103
+ DirectoryScanner.prototype.off = function off(this: any, event: string, handler: (...args: unknown[]) => void): any {
104
+ const arr = this.handlerMap.get(event);
105
+ if (arr) {
106
+ const idx = arr.indexOf(handler);
107
+ if (idx !== -1) arr.splice(idx, 1);
108
+ }
109
+ return this;
110
+ };
111
+
112
+ DirectoryScanner.prototype.fireEvent = function fireEvent(this: any, event: string, ...args: unknown[]): void {
113
+ const arr = this.handlerMap.get(event);
114
+ if (arr) for (const fn of arr) fn(...args);
115
+ };
116
+
117
+ DirectoryScanner.prototype.runScan = function runScan(this: any): void {
118
+ if (this.scanned) return;
119
+ this.scanned = true;
120
+ this.crawl(this.rootDir, 0, "");
121
+ };
122
+
123
+ DirectoryScanner.prototype.crawl = function crawl(this: any, dir: string, level: number, relative: string): void {
124
+ const vol = getSharedVolume();
125
+ if (!vol) return;
126
+ if (this.cfg.depth !== undefined && level > this.cfg.depth) return;
127
+
128
+ let children: string[];
129
+ try {
130
+ children = vol.readdirSync(dir);
131
+ } catch {
132
+ return;
133
+ }
134
+
135
+ for (const name of children) {
136
+ const absolute = dir === "/" ? "/" + name : dir + "/" + name;
137
+ const rel = relative ? relative + "/" + name : name;
138
+
139
+ let st: FileStat;
140
+ try {
141
+ st = vol.statSync(absolute);
142
+ } catch {
143
+ continue;
144
+ }
145
+
146
+ const isDir = st.isDirectory();
147
+
148
+ const entry: ScanEntry = {
149
+ path: rel,
150
+ fullPath: absolute,
151
+ basename: name,
152
+ stats: this.cfg.alwaysStat ? st : undefined,
153
+ dirent: {
154
+ isFile: () => !isDir,
155
+ isDirectory: () => isDir,
156
+ name,
157
+ },
158
+ };
159
+
160
+ const category = this.cfg.type || "files";
161
+
162
+ if (isDir) {
163
+ if (!this.applyFilter(entry, this.cfg.directoryFilter)) continue;
164
+
165
+ if (
166
+ category === "directories" ||
167
+ category === "files_directories" ||
168
+ category === "all"
169
+ ) {
170
+ this.results.push(entry);
171
+ }
172
+ this.crawl(absolute, level + 1, rel);
173
+ } else {
174
+ if (
175
+ category === "files" ||
176
+ category === "files_directories" ||
177
+ category === "all"
178
+ ) {
179
+ if (this.applyFilter(entry, this.cfg.fileFilter)) {
180
+ this.results.push(entry);
181
+ }
182
+ }
183
+ }
184
+ }
185
+ };
186
+
187
+ DirectoryScanner.prototype.applyFilter = function applyFilter(
188
+ this: any,
189
+ entry: ScanEntry,
190
+ filter?: string | string[] | ((e: ScanEntry) => boolean),
191
+ ): boolean {
192
+ if (!filter) return true;
193
+
194
+ if (typeof filter === "function") return filter(entry);
195
+
196
+ const patterns = Array.isArray(filter) ? filter : [filter];
197
+ for (const pat of patterns) {
198
+ if (pat.startsWith("!")) {
199
+ if (this.globMatch(entry.basename, pat.slice(1))) return false;
200
+ } else if (this.globMatch(entry.basename, pat)) {
201
+ return true;
202
+ }
203
+ }
204
+ // If every pattern was a negation and none matched, the entry is allowed
205
+ return patterns.length === 0 || patterns.every((p: string) => p.startsWith("!"));
206
+ };
207
+
208
+ DirectoryScanner.prototype.globMatch = function globMatch(filename: string, pattern: string): boolean {
209
+ if (pattern === "*") return true;
210
+ if (pattern.startsWith("*.")) return filename.endsWith(pattern.slice(1));
211
+ if (pattern.endsWith("*")) return filename.startsWith(pattern.slice(0, -1));
212
+ return filename === pattern;
213
+ };
214
+
215
+ export default function readdirp(
216
+ root: string,
217
+ options?: ScanOptions,
218
+ ): DirectoryScanner {
219
+ return new DirectoryScanner(root, options);
220
+ }
221
+
222
+ export async function readdirpPromise(
223
+ root: string,
224
+ options?: ScanOptions,
225
+ ): Promise<ScanEntry[]> {
226
+ return new DirectoryScanner(root, options).toArray();
227
+ }
228
+
229
+ export { readdirp, DirectoryScanner };