Skip to content
File

Blob: src/node/internal/internal_readline.ts

typescript109 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4//
5// Copyright Joyent, Inc. and other Node contributors.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a
8// copy of this software and associated documentation files (the
9// "Software"), to deal in the Software without restriction, including
10// without limitation the rights to use, copy, modify, merge, publish,
11// distribute, sublicense, and/or sell copies of the Software, and to permit
12// persons to whom the Software is furnished to do so, subject to the
13// following conditions:
14//
15// The above copyright notice and this permission notice shall be included
16// in all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24// USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26import { EventEmitter } from 'node-internal:events';
27import type { Abortable } from 'node:events';
28import type Readline from 'node:readline';
29 
30// This class provides a no-op stub implementation that matches unenv's behavior.
31// See: https://github.com/unjs/unenv/blob/main/src/runtime/node/internal/readline/interface.ts
32// Methods are no-ops or return sensible defaults rather than throwing errors,
33// which allows code that depends on readline to work without crashing.
34export class Interface extends EventEmitter implements Readline.Interface {
35 terminal = false;
36 line = '';
37 cursor = 0;
38 
39 getPrompt(): string {
40 return '';
41 }
42 
43 setPrompt(_prompt: string): void {
44 // No-op
45 }
46 
47 prompt(_preserveCursor?: boolean): void {
48 // No-op
49 }
50 
51 question(query: string, callback: (answer: string) => void): void;
52 question(
53 query: string,
54 options: Abortable,
55 callback: (answer: string) => void
56 ): void;
57 question(
58 _query: string,
59 _optionsOrCallback: Abortable | ((answer: string) => void),
60 _callback?: (answer: string) => void
61 ): void {
62 // If callback is the second argument (no options)
63 if (typeof _optionsOrCallback === 'function') {
64 _optionsOrCallback('');
65 } else if (typeof _callback === 'function') {
66 _callback('');
67 }
68 }
69 
70 pause(): this {
71 return this;
72 }
73 
74 resume(): this {
75 return this;
76 }
77 
78 close(): void {
79 // No-op
80 }
81 
82 write(_data: unknown, _key?: unknown): void {
83 // No-op
84 }
85 
86 getCursorPos(): Readline.CursorPos {
87 return {
88 rows: 0,
89 cols: 0,
90 };
91 }
92 
93 [Symbol.dispose](): void {
94 this.close();
95 }
96 
97 // eslint-disable-next-line @typescript-eslint/require-await
98 async [Symbol.asyncDispose](): Promise<void> {
99 this.close();
100 }
101 
102 // Yield a single empty string so that `for await...of` loops complete
103 // immediately without blocking, consistent with no-op stub behavior.
104 // eslint-disable-next-line @typescript-eslint/require-await
105 async *[Symbol.asyncIterator](): NodeJS.AsyncIterator<string> {
106 yield '';
107 }
108}