@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,692 @@
1
+ // readline polyfill -- createInterface, emitKeypressEvents, terminal helpers.
2
+ // tracks line/cursor on every keystroke because @clack reads rl.line directly.
3
+
4
+ import { EventEmitter } from "./events";
5
+ import { ref as _elRef, unref as _elUnref } from "../helpers/event-loop";
6
+
7
+ // child_process wait loop checks this to avoid exiting while waiting for user input
8
+ let _activeInterfaceCount = 0;
9
+
10
+ export function getActiveInterfaceCount(): number {
11
+ return _activeInterfaceCount;
12
+ }
13
+
14
+ export function setActiveInterfaceCount(n: number): void {
15
+ _activeInterfaceCount = n;
16
+ }
17
+
18
+ export function resetActiveInterfaceCount(): void {
19
+ _activeInterfaceCount = 0;
20
+ }
21
+
22
+
23
+ export interface InterfaceConfig {
24
+ input?: unknown;
25
+ output?: unknown;
26
+ terminal?: boolean;
27
+ prompt?: string;
28
+ historySize?: number;
29
+ completer?: (line: string) => [string[], string] | void;
30
+ crlfDelay?: number;
31
+ escapeCodeTimeout?: number;
32
+ tabSize?: number;
33
+ }
34
+
35
+ // emitKeypressEvents: parse data events into keypress events
36
+
37
+ const KEYPRESS_DECODER = Symbol("keypressDecoder");
38
+
39
+ // mirrors Node.js internal emitKeys generator
40
+ function parseAndEmitKeypress(
41
+ stream: any,
42
+ char: string,
43
+ escapeBuf: string[],
44
+ ): string[] {
45
+ if (escapeBuf.length > 0) {
46
+ escapeBuf.push(char);
47
+ const seq = escapeBuf.join("");
48
+
49
+ if (seq.length >= 3 && seq[1] === "[") {
50
+ // CSI sequence
51
+ const lastChar = seq[seq.length - 1];
52
+ if (/[A-Za-z~]/.test(lastChar)) {
53
+ let name = "";
54
+ if (lastChar === "A") name = "up";
55
+ else if (lastChar === "B") name = "down";
56
+ else if (lastChar === "C") name = "right";
57
+ else if (lastChar === "D") name = "left";
58
+ else if (lastChar === "H") name = "home";
59
+ else if (lastChar === "F") name = "end";
60
+ else if (seq === "\x1b[3~") name = "delete";
61
+ else if (seq === "\x1b[2~") name = "insert";
62
+ else if (seq === "\x1b[5~") name = "pageup";
63
+ else if (seq === "\x1b[6~") name = "pagedown";
64
+ else name = lastChar;
65
+
66
+ stream.emit("keypress", seq, {
67
+ sequence: seq,
68
+ name,
69
+ ctrl: false,
70
+ meta: false,
71
+ shift: false,
72
+ });
73
+ return [];
74
+ }
75
+ if (seq.length > 8) {
76
+ stream.emit("keypress", seq, {
77
+ sequence: seq,
78
+ name: "unknown",
79
+ ctrl: false,
80
+ meta: false,
81
+ shift: false,
82
+ });
83
+ return [];
84
+ }
85
+ return escapeBuf;
86
+ }
87
+
88
+ if (seq.length >= 3 && seq[1] === "O") {
89
+ const lastChar = seq[seq.length - 1];
90
+ let name = "";
91
+ if (lastChar === "A") name = "up";
92
+ else if (lastChar === "B") name = "down";
93
+ else if (lastChar === "C") name = "right";
94
+ else if (lastChar === "D") name = "left";
95
+ else if (lastChar === "H") name = "home";
96
+ else if (lastChar === "F") name = "end";
97
+ else name = lastChar;
98
+
99
+ stream.emit("keypress", seq, {
100
+ sequence: seq,
101
+ name,
102
+ ctrl: false,
103
+ meta: false,
104
+ shift: false,
105
+ });
106
+ return [];
107
+ }
108
+
109
+ if (seq.length >= 2 && seq[1] !== "[" && seq[1] !== "O") {
110
+ stream.emit("keypress", seq, {
111
+ sequence: seq,
112
+ name: "escape",
113
+ ctrl: false,
114
+ meta: true,
115
+ shift: false,
116
+ });
117
+ return [];
118
+ }
119
+
120
+ return escapeBuf;
121
+ }
122
+
123
+ if (char === "\x1b") {
124
+ return [char];
125
+ }
126
+
127
+ let name = char;
128
+ let ctrl = false;
129
+ if (char === "\r" || char === "\n") name = "return";
130
+ else if (char === "\x7f" || char === "\b") name = "backspace";
131
+ else if (char === "\t") name = "tab";
132
+ else if (char === " ") name = "space";
133
+ else if (char.charCodeAt(0) < 32) {
134
+ // Ctrl+letter
135
+ ctrl = true;
136
+ name = String.fromCharCode(char.charCodeAt(0) + 96);
137
+ }
138
+
139
+ stream.emit("keypress", char, {
140
+ sequence: char,
141
+ name,
142
+ ctrl,
143
+ meta: false,
144
+ shift: false,
145
+ });
146
+
147
+ return [];
148
+ }
149
+
150
+ export function emitKeypressEvents(stream: unknown, _iface?: Interface): void {
151
+ if (!stream || typeof (stream as any).on !== "function") return;
152
+ if ((stream as any)[KEYPRESS_DECODER]) return;
153
+ (stream as any)[KEYPRESS_DECODER] = true;
154
+
155
+ let escapeBuf: string[] = [];
156
+ let escapeTimeout: ReturnType<typeof setTimeout> | null = null;
157
+
158
+ (stream as any).on("data", (data: unknown) => {
159
+ if ((stream as any).listenerCount("keypress") <= 0) return;
160
+ const text = typeof data === "string" ? data : String(data);
161
+
162
+ for (const char of text) {
163
+ if (escapeTimeout) {
164
+ clearTimeout(escapeTimeout);
165
+ escapeTimeout = null;
166
+ }
167
+ escapeBuf = parseAndEmitKeypress(stream as any, char, escapeBuf);
168
+
169
+ // flush pending escape after timeout
170
+ if (escapeBuf.length > 0) {
171
+ escapeTimeout = setTimeout(() => {
172
+ if (escapeBuf.length > 0) {
173
+ const seq = escapeBuf.join("");
174
+ (stream as any).emit("keypress", seq, {
175
+ sequence: seq,
176
+ name: "escape",
177
+ ctrl: false,
178
+ meta: false,
179
+ shift: false,
180
+ });
181
+ escapeBuf = [];
182
+ }
183
+ }, 50);
184
+ }
185
+ }
186
+ });
187
+ }
188
+
189
+
190
+ export interface Interface extends EventEmitter {
191
+ _promptStr: string;
192
+ _input: unknown;
193
+ _output: unknown;
194
+ _closed: boolean;
195
+ _lineBuffer: string;
196
+ _pendingQuestions: Array<{
197
+ query: string;
198
+ handler: (answer: string) => void;
199
+ }>;
200
+ terminal: boolean;
201
+ line: string;
202
+ cursor: number;
203
+ _refreshLine(): void;
204
+ _onKeypress(char: string | undefined, key: any): void;
205
+ _onData(text: string): void;
206
+ prompt(preserveCursor?: boolean): void;
207
+ setPrompt(text: string): void;
208
+ getPrompt(): string;
209
+ question(query: string, optsOrHandler?: unknown, handler?: (answer: string) => void): void;
210
+ pause(): this;
211
+ resume(): this;
212
+ close(): void;
213
+ write(data: string | null, _key?: { ctrl?: boolean; name?: string; meta?: boolean; shift?: boolean; sequence?: string }): void;
214
+ getCursorPos(): { rows: number; cols: number };
215
+ [Symbol.asyncIterator](): AsyncGenerator<string, void, undefined>;
216
+ }
217
+
218
+ interface InterfaceConstructor {
219
+ new (cfg?: InterfaceConfig): Interface;
220
+ (this: any, cfg?: InterfaceConfig): void;
221
+ prototype: any;
222
+ }
223
+
224
+ export const Interface = function Interface(this: any, cfg?: InterfaceConfig) {
225
+ if (!this) return;
226
+ EventEmitter.call(this);
227
+ this._promptStr = cfg?.prompt ?? "> ";
228
+ this._input = cfg?.input;
229
+ this._output = cfg?.output;
230
+ this._closed = false;
231
+ this._lineBuffer = "";
232
+ this._pendingQuestions = [];
233
+ this.terminal = cfg?.terminal ?? false;
234
+ this.line = "";
235
+ this.cursor = 0;
236
+
237
+ if (this._input && typeof (this._input as any).on === "function") {
238
+ _activeInterfaceCount++;
239
+ _elRef();
240
+ const inputStream = this._input as EventEmitter;
241
+ const self = this;
242
+
243
+ if (this.terminal) {
244
+ emitKeypressEvents(this._input, this);
245
+
246
+ inputStream.on("keypress", (char: string | undefined, key: any) => {
247
+ if (self._closed) return;
248
+ self._onKeypress(char, key);
249
+ });
250
+ } else {
251
+ inputStream.on("data", (data: unknown) => {
252
+ if (self._closed) return;
253
+ const text = typeof data === "string" ? data : String(data);
254
+ self._onData(text);
255
+ });
256
+ }
257
+
258
+ inputStream.on("end", () => {
259
+ if (!self._closed) self.close();
260
+ });
261
+ }
262
+ } as unknown as InterfaceConstructor;
263
+
264
+ Object.setPrototypeOf(Interface.prototype, EventEmitter.prototype);
265
+
266
+ Interface.prototype._refreshLine = function _refreshLine(this: any): void {
267
+ if (this._output && typeof (this._output as any).write === "function") {
268
+ (this._output as any).write(this.line);
269
+ }
270
+ };
271
+
272
+ Interface.prototype._onKeypress = function _onKeypress(this: any, char: string | undefined, key: any): void {
273
+ if (!key) return;
274
+
275
+ if (key.ctrl && key.name === "c") {
276
+ this.close();
277
+ return;
278
+ }
279
+
280
+ if (key.name === "return") {
281
+ const line = this._lineBuffer;
282
+ this._lineBuffer = "";
283
+ this.line = line;
284
+
285
+ if (this._pendingQuestions.length > 0) {
286
+ const q = this._pendingQuestions.shift()!;
287
+ q.handler(line);
288
+ }
289
+
290
+ this.emit("line", line);
291
+ this.line = "";
292
+ this.cursor = 0;
293
+ return;
294
+ }
295
+
296
+ if (key.name === "backspace") {
297
+ if (this.cursor > 0) {
298
+ this._lineBuffer =
299
+ this._lineBuffer.slice(0, this.cursor - 1) +
300
+ this._lineBuffer.slice(this.cursor);
301
+ this.cursor--;
302
+ this.line = this._lineBuffer;
303
+ this._refreshLine();
304
+ }
305
+ return;
306
+ }
307
+
308
+ if (key.name === "delete") {
309
+ if (this.cursor < this._lineBuffer.length) {
310
+ this._lineBuffer =
311
+ this._lineBuffer.slice(0, this.cursor) +
312
+ this._lineBuffer.slice(this.cursor + 1);
313
+ this.line = this._lineBuffer;
314
+ this._refreshLine();
315
+ }
316
+ return;
317
+ }
318
+
319
+ if (key.name === "left") {
320
+ this.cursor = Math.max(0, this.cursor - 1);
321
+ this._refreshLine();
322
+ return;
323
+ }
324
+ if (key.name === "right") {
325
+ this.cursor = Math.min(this._lineBuffer.length, this.cursor + 1);
326
+ this._refreshLine();
327
+ return;
328
+ }
329
+ if (key.name === "home") {
330
+ this.cursor = 0;
331
+ this._refreshLine();
332
+ return;
333
+ }
334
+ if (key.name === "end") {
335
+ this.cursor = this._lineBuffer.length;
336
+ this._refreshLine();
337
+ return;
338
+ }
339
+
340
+ if (key.ctrl && key.name === "u") {
341
+ this._lineBuffer = this._lineBuffer.slice(this.cursor);
342
+ this.cursor = 0;
343
+ this.line = this._lineBuffer;
344
+ this._refreshLine();
345
+ return;
346
+ }
347
+
348
+ if (key.ctrl && key.name === "k") {
349
+ this._lineBuffer = this._lineBuffer.slice(0, this.cursor);
350
+ this.line = this._lineBuffer;
351
+ this._refreshLine();
352
+ return;
353
+ }
354
+
355
+ if (key.ctrl && key.name === "h") {
356
+ if (this.cursor > 0) {
357
+ this._lineBuffer =
358
+ this._lineBuffer.slice(0, this.cursor - 1) +
359
+ this._lineBuffer.slice(this.cursor);
360
+ this.cursor--;
361
+ this.line = this._lineBuffer;
362
+ this._refreshLine();
363
+ }
364
+ return;
365
+ }
366
+
367
+ if (
368
+ char &&
369
+ !key.ctrl &&
370
+ !key.meta &&
371
+ char.length === 1 &&
372
+ char.charCodeAt(0) >= 32
373
+ ) {
374
+ this._lineBuffer =
375
+ this._lineBuffer.slice(0, this.cursor) +
376
+ char +
377
+ this._lineBuffer.slice(this.cursor);
378
+ this.cursor++;
379
+ this.line = this._lineBuffer;
380
+ this._refreshLine();
381
+ return;
382
+ }
383
+
384
+ };
385
+
386
+ Interface.prototype._onData = function _onData(this: any, text: string): void {
387
+ for (const char of text) {
388
+ if (char === "\n" || char === "\r") {
389
+ const line = this._lineBuffer;
390
+ this._lineBuffer = "";
391
+ this.line = line;
392
+
393
+ if (this._pendingQuestions.length > 0) {
394
+ const q = this._pendingQuestions.shift()!;
395
+ q.handler(line);
396
+ }
397
+
398
+ this.emit("line", line);
399
+ this.line = "";
400
+ this.cursor = 0;
401
+ } else if (char === "\x7f" || char === "\b") {
402
+ if (this._lineBuffer.length > 0) {
403
+ this._lineBuffer =
404
+ this._lineBuffer.slice(0, this.cursor - 1) +
405
+ this._lineBuffer.slice(this.cursor);
406
+ this.cursor = Math.max(0, this.cursor - 1);
407
+ this.line = this._lineBuffer;
408
+ this._refreshLine();
409
+ }
410
+ } else if (char.charCodeAt(0) >= 32) {
411
+ this._lineBuffer =
412
+ this._lineBuffer.slice(0, this.cursor) +
413
+ char +
414
+ this._lineBuffer.slice(this.cursor);
415
+ this.cursor++;
416
+ this.line = this._lineBuffer;
417
+ this._refreshLine();
418
+ }
419
+ }
420
+ };
421
+
422
+ Interface.prototype.prompt = function prompt(this: any, preserveCursor?: boolean): void {
423
+ if (this._output && typeof (this._output as any).write === "function") {
424
+ (this._output as any).write(this._promptStr);
425
+ }
426
+ if (!preserveCursor) {
427
+ this.cursor = 0;
428
+ this.line = "";
429
+ this._lineBuffer = "";
430
+ }
431
+ };
432
+
433
+ Interface.prototype.setPrompt = function setPrompt(this: any, text: string): void {
434
+ this._promptStr = text;
435
+ };
436
+
437
+ Interface.prototype.getPrompt = function getPrompt(this: any): string {
438
+ return this._promptStr;
439
+ };
440
+
441
+ Interface.prototype.question = function question(
442
+ this: any,
443
+ query: string,
444
+ optsOrHandler?: unknown,
445
+ handler?: (answer: string) => void,
446
+ ): void {
447
+ const actualHandler =
448
+ typeof optsOrHandler === "function"
449
+ ? (optsOrHandler as (answer: string) => void)
450
+ : handler;
451
+ if (!actualHandler) return;
452
+
453
+ if (this._output && typeof (this._output as any).write === "function") {
454
+ (this._output as any).write(query);
455
+ }
456
+
457
+ if (this._input && typeof (this._input as any).on === "function") {
458
+ this._pendingQuestions.push({ query, handler: actualHandler });
459
+ } else {
460
+ setTimeout(() => actualHandler(""), 0);
461
+ }
462
+ };
463
+
464
+ Interface.prototype.pause = function pause(this: any): any {
465
+ if (this._input && typeof (this._input as any).pause === "function") {
466
+ (this._input as any).pause();
467
+ }
468
+ this.emit("pause");
469
+ return this;
470
+ };
471
+
472
+ Interface.prototype.resume = function resume(this: any): any {
473
+ if (this._input && typeof (this._input as any).resume === "function") {
474
+ (this._input as any).resume();
475
+ }
476
+ this.emit("resume");
477
+ return this;
478
+ };
479
+
480
+ Interface.prototype.close = function close(this: any): void {
481
+ if (this._closed) return;
482
+ this._closed = true;
483
+ if (this._input && typeof (this._input as any).on === "function") {
484
+ _activeInterfaceCount = Math.max(0, _activeInterfaceCount - 1);
485
+ _elUnref();
486
+ }
487
+ for (const q of this._pendingQuestions) {
488
+ q.handler("");
489
+ }
490
+ this._pendingQuestions.length = 0;
491
+ this.emit("close");
492
+ };
493
+
494
+ Interface.prototype.write = function write(
495
+ this: any,
496
+ data: string | null,
497
+ _key?: {
498
+ ctrl?: boolean;
499
+ name?: string;
500
+ meta?: boolean;
501
+ shift?: boolean;
502
+ sequence?: string;
503
+ },
504
+ ): void {
505
+ if (this._closed) return;
506
+
507
+ if (data === null || data === undefined) {
508
+ if (_key) {
509
+ // emit synthetic keypress on input so external listeners (e.g. @clack) see it
510
+ const emitOnInput =
511
+ this._input && typeof (this._input as any).emit === "function";
512
+
513
+ if (_key.ctrl && _key.name === "c") {
514
+ this.close();
515
+ return;
516
+ }
517
+ if (_key.ctrl && _key.name === "h") {
518
+ // Backspace
519
+ if (this.cursor > 0) {
520
+ this._lineBuffer =
521
+ this._lineBuffer.slice(0, this.cursor - 1) +
522
+ this._lineBuffer.slice(this.cursor);
523
+ this.cursor--;
524
+ this.line = this._lineBuffer;
525
+ }
526
+ if (emitOnInput) {
527
+ (this._input as any).emit("keypress", "\x7f", {
528
+ sequence: "\x7f",
529
+ name: "backspace",
530
+ ctrl: false,
531
+ meta: false,
532
+ shift: false,
533
+ });
534
+ }
535
+ return;
536
+ }
537
+ if (_key.ctrl && _key.name === "u") {
538
+ this._lineBuffer = this._lineBuffer.slice(this.cursor);
539
+ this.cursor = 0;
540
+ this.line = this._lineBuffer;
541
+ return;
542
+ }
543
+ if (_key.ctrl && _key.name === "k") {
544
+ this._lineBuffer = this._lineBuffer.slice(0, this.cursor);
545
+ this.line = this._lineBuffer;
546
+ return;
547
+ }
548
+ if (_key.name === "left") {
549
+ this.cursor = Math.max(0, this.cursor - 1);
550
+ return;
551
+ }
552
+ if (_key.name === "right") {
553
+ this.cursor = Math.min(this._lineBuffer.length, this.cursor + 1);
554
+ return;
555
+ }
556
+ if (_key.name === "home") {
557
+ this.cursor = 0;
558
+ return;
559
+ }
560
+ if (_key.name === "end") {
561
+ this.cursor = this._lineBuffer.length;
562
+ return;
563
+ }
564
+ }
565
+ return;
566
+ }
567
+
568
+ if (_key?.ctrl && _key?.name === "c") {
569
+ this.close();
570
+ return;
571
+ }
572
+
573
+ this._onData(data);
574
+ };
575
+
576
+ Interface.prototype.getCursorPos = function getCursorPos(this: any): { rows: number; cols: number } {
577
+ return { rows: 0, cols: this.cursor };
578
+ };
579
+
580
+ Interface.prototype[Symbol.asyncIterator] = async function*(this: any): AsyncGenerator<string, void, undefined> {
581
+ const self = this;
582
+ while (!self._closed) {
583
+ const line = await new Promise<string | null>((resolve) => {
584
+ if (self._closed) {
585
+ resolve(null);
586
+ return;
587
+ }
588
+ self.once("line", (l: string) => resolve(l));
589
+ self.once("close", () => resolve(null));
590
+ });
591
+ if (line === null) break;
592
+ yield line;
593
+ }
594
+ };
595
+
596
+
597
+ export function createInterface(
598
+ cfgOrInput?: InterfaceConfig | unknown,
599
+ output?: unknown,
600
+ ): Interface {
601
+ if (
602
+ cfgOrInput &&
603
+ typeof cfgOrInput === "object" &&
604
+ !("on" in (cfgOrInput as any)) &&
605
+ !("read" in (cfgOrInput as any))
606
+ ) {
607
+ return new Interface(cfgOrInput as InterfaceConfig);
608
+ }
609
+ return new Interface({ input: cfgOrInput, output });
610
+ }
611
+
612
+
613
+ export function clearLine(
614
+ stream: unknown,
615
+ dir: number,
616
+ done?: () => void,
617
+ ): boolean {
618
+ if (stream && typeof (stream as any).clearLine === "function") {
619
+ return (stream as any).clearLine(dir, done);
620
+ }
621
+ if (done) done();
622
+ return true;
623
+ }
624
+
625
+ export function clearScreenDown(stream: unknown, done?: () => void): boolean {
626
+ if (stream && typeof (stream as any).write === "function") {
627
+ (stream as any).write("\x1b[J");
628
+ }
629
+ if (done) done();
630
+ return true;
631
+ }
632
+
633
+ export function cursorTo(
634
+ stream: unknown,
635
+ x: number,
636
+ yOrDone?: number | (() => void),
637
+ done?: () => void,
638
+ ): boolean {
639
+ const cb = typeof yOrDone === "function" ? yOrDone : done;
640
+ if (stream && typeof (stream as any).cursorTo === "function") {
641
+ return (stream as any).cursorTo(
642
+ x,
643
+ typeof yOrDone === "number" ? yOrDone : undefined,
644
+ cb,
645
+ );
646
+ }
647
+ if (cb) cb();
648
+ return true;
649
+ }
650
+
651
+ export function moveCursor(
652
+ stream: unknown,
653
+ dx: number,
654
+ dy: number,
655
+ done?: () => void,
656
+ ): boolean {
657
+ if (stream && typeof (stream as any).moveCursor === "function") {
658
+ return (stream as any).moveCursor(dx, dy, done);
659
+ }
660
+ if (done) done();
661
+ return true;
662
+ }
663
+
664
+
665
+ export const promises = {
666
+ createInterface(cfg?: InterfaceConfig) {
667
+ const rl = createInterface(cfg);
668
+ return {
669
+ question(query: string): Promise<string> {
670
+ return new Promise((resolve) => rl.question(query, resolve));
671
+ },
672
+ close(): void {
673
+ rl.close();
674
+ },
675
+ async *[Symbol.asyncIterator](): AsyncGenerator<string, void, undefined> {
676
+ yield* rl;
677
+ },
678
+ };
679
+ },
680
+ };
681
+
682
+
683
+ export default {
684
+ Interface,
685
+ createInterface,
686
+ clearLine,
687
+ clearScreenDown,
688
+ cursorTo,
689
+ moveCursor,
690
+ emitKeypressEvents,
691
+ promises,
692
+ };