0
# Single Line Input
1
2
Read individual lines from standard input with stream management, automatic cleanup, and singleton stream handling for optimal resource usage.
3
4
## Capabilities
5
6
### Main ReadLine Function
7
8
Reads a single line from input stream with automatic stream management and resource cleanup.
9
10
```typescript { .api }
11
/**
12
* Read a single line from input stream
13
* @param options - Configuration options for stream and cleanup behavior
14
* @returns Promise resolving to the line content as string
15
*/
16
function readLine(options?: ReadLineOptions): Promise<string>;
17
18
interface ReadLineOptions {
19
/** Input stream to read from (defaults to process.stdin) */
20
stream?: NodeJS.ReadableStream;
21
/** Whether to close the stream after reading (defaults to false) */
22
close?: boolean;
23
}
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import { readLine } from "stdio";
30
31
// Read single line from stdin
32
const userInput = await readLine();
33
console.log(`You entered: ${userInput}`);
34
35
// Read with explicit stream closure
36
const input = await readLine({ close: true });
37
console.log(`Final input: ${input}`);
38
39
// Read from custom stream
40
import { createReadStream } from 'fs';
41
42
const fileStream = createReadStream('input.txt');
43
const firstLine = await readLine({ stream: fileStream });
44
console.log(`First line from file: ${firstLine}`);
45
46
// Interactive input loop
47
console.log('Enter commands (type "quit" to exit):');
48
while (true) {
49
const command = await readLine();
50
if (command === 'quit') {
51
// Close stream on final read
52
await readLine({ close: true });
53
break;
54
}
55
console.log(`Processing command: ${command}`);
56
}
57
58
// Error handling
59
try {
60
const input = await readLine({ close: true });
61
const number = parseInt(input);
62
if (isNaN(number)) {
63
throw new Error('Invalid number format');
64
}
65
console.log(`Number: ${number}`);
66
} catch (error) {
67
console.error('Input error:', error.message);
68
}
69
```
70
71
### Stream Management
72
73
The readLine function uses efficient singleton stream management for optimal resource usage.
74
75
**Singleton Pattern:**
76
- Reuses the same `InputStream` instance across multiple calls
77
- Reduces resource overhead for multiple readline operations
78
- Automatically manages stream lifecycle
79
80
**Stream Lifecycle:**
81
- Stream is created on first use
82
- Remains open for subsequent reads (unless `close: true`)
83
- Properly cleans up resources when closed
84
85
### InputStream Class
86
87
Internal class that manages readline operations with buffering and event handling.
88
89
```typescript { .api }
90
class InputStream {
91
constructor(input?: NodeJS.ReadableStream);
92
93
/**
94
* Get the next line from the input stream
95
* @returns Promise resolving to line content or null on stream end
96
*/
97
getLine(): Promise<string>;
98
99
/**
100
* Close the input stream and clean up resources
101
*/
102
close(): void;
103
}
104
```
105
106
**Internal Implementation Details:**
107
108
The `InputStream` class provides:
109
- **Event-driven Processing**: Uses readline events for efficient line handling
110
- **Buffer Management**: Maintains internal buffer for immediate line availability
111
- **Promise Queue**: Handles multiple concurrent readLine calls correctly
112
- **Stream End Handling**: Properly resolves with `null` when stream closes
113
114
## Advanced Features
115
116
### Buffering and Queue Management
117
118
Handles multiple readline requests efficiently:
119
120
```typescript
121
// Multiple concurrent reads are properly queued
122
const promise1 = readLine();
123
const promise2 = readLine();
124
const promise3 = readLine();
125
126
// Lines are returned in order as they arrive
127
const [line1, line2, line3] = await Promise.all([promise1, promise2, promise3]);
128
```
129
130
### Stream End Detection
131
132
Properly handles stream closure and end-of-input:
133
134
```typescript
135
import { readLine } from "stdio";
136
137
try {
138
const line = await readLine();
139
if (line === null) {
140
console.log('Stream ended (Ctrl+D pressed or pipe closed)');
141
} else {
142
console.log(`Read: ${line}`);
143
}
144
} catch (error) {
145
console.error('Read error:', error);
146
}
147
```
148
149
### Resource Management
150
151
Efficient resource usage with proper cleanup:
152
153
```typescript
154
// Stream stays open for multiple reads (efficient)
155
const name = await readLine();
156
const age = await readLine();
157
const email = await readLine();
158
159
// Explicitly close when done
160
await readLine({ close: true });
161
162
// Or close in final operation
163
const confirmation = await readLine({ close: true });
164
```
165
166
### Integration Patterns
167
168
Common integration patterns for different use cases:
169
170
**Interactive CLI Applications:**
171
172
```typescript
173
import { readLine } from "stdio";
174
175
async function runCLI() {
176
console.log('Welcome to My CLI');
177
178
while (true) {
179
process.stdout.write('> ');
180
const command = await readLine();
181
182
if (command === 'exit') {
183
console.log('Goodbye!');
184
await readLine({ close: true });
185
break;
186
}
187
188
await processCommand(command);
189
}
190
}
191
```
192
193
**Configuration Input:**
194
195
```typescript
196
async function getConfiguration() {
197
const config = {};
198
199
console.log('Please enter configuration:');
200
config.host = await readLine();
201
config.port = parseInt(await readLine());
202
config.database = await readLine({ close: true });
203
204
return config;
205
}
206
```
207
208
**File Processing:**
209
210
```typescript
211
import { createReadStream } from 'fs';
212
213
async function processFileLines(filename: string) {
214
const stream = createReadStream(filename);
215
216
try {
217
while (true) {
218
const line = await readLine({ stream });
219
if (line === null) break; // End of file
220
221
await processLine(line);
222
}
223
} finally {
224
// Stream is automatically closed when file ends
225
}
226
}
227
```
228
229
## Error Handling
230
231
Comprehensive error handling for various failure scenarios:
232
233
```typescript
234
try {
235
const input = await readLine();
236
// Process input
237
} catch (error) {
238
if (error.code === 'ENOENT') {
239
console.error('Input stream not available');
240
} else if (error.code === 'EPERM') {
241
console.error('Permission denied reading input');
242
} else {
243
console.error('Unexpected error:', error.message);
244
}
245
}
246
```