@ubercode/dcmtk 0.1.4 → 0.3.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/README.md +20 -15
- package/dist/DicomInstance-D9plqHp5.d.ts +625 -0
- package/dist/DicomInstance-DNHPkkzl.d.cts +625 -0
- package/dist/{dcmodify-CTXBWKU9.d.cts → dcmodify-B-_uUIKB.d.ts} +4 -2
- package/dist/{dcmodify-Daeafqrm.d.ts → dcmodify-Gds9u5Vj.d.cts} +4 -2
- package/dist/dicom.cjs +329 -51
- package/dist/dicom.cjs.map +1 -1
- package/dist/dicom.d.cts +368 -3
- package/dist/dicom.d.ts +368 -3
- package/dist/dicom.js +329 -51
- package/dist/dicom.js.map +1 -1
- package/dist/index.cjs +1993 -423
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +324 -10
- package/dist/index.d.ts +324 -10
- package/dist/index.js +1962 -417
- package/dist/index.js.map +1 -1
- package/dist/servers.cjs +2380 -197
- package/dist/servers.cjs.map +1 -1
- package/dist/servers.d.cts +1654 -3
- package/dist/servers.d.ts +1654 -3
- package/dist/servers.js +2306 -146
- package/dist/servers.js.map +1 -1
- package/dist/tools.cjs +98 -51
- package/dist/tools.cjs.map +1 -1
- package/dist/tools.d.cts +21 -4
- package/dist/tools.d.ts +21 -4
- package/dist/tools.js +98 -52
- package/dist/tools.js.map +1 -1
- package/dist/{types-zHhxS7d2.d.cts → types-Cgumy1N4.d.cts} +1 -24
- package/dist/{types-zHhxS7d2.d.ts → types-Cgumy1N4.d.ts} +1 -24
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +8 -8
- package/dist/index-BZxi4104.d.ts +0 -826
- package/dist/index-CapkWqxy.d.ts +0 -1295
- package/dist/index-DX4C3zbo.d.cts +0 -826
- package/dist/index-r7AvpkCE.d.cts +0 -1295
package/dist/servers.d.cts
CHANGED
|
@@ -1,3 +1,1654 @@
|
|
|
1
|
-
|
|
2
|
-
import '
|
|
3
|
-
import '
|
|
1
|
+
import { L as LineSource, R as Result } from './types-Cgumy1N4.cjs';
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { d as DicomInstance } from './DicomInstance-DNHPkkzl.cjs';
|
|
4
|
+
import './dcmodify-Gds9u5Vj.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base class for long-lived DCMTK processes (servers).
|
|
8
|
+
*
|
|
9
|
+
* Manages spawning, line-by-line output buffering, typed event emission,
|
|
10
|
+
* lifecycle (start/stop), mandatory timeouts, and graceful shutdown.
|
|
11
|
+
*
|
|
12
|
+
* Implements `Disposable` for deterministic cleanup (Rule 5.1).
|
|
13
|
+
*
|
|
14
|
+
* @module DcmtkProcess
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Events emitted by a DcmtkProcess. */
|
|
18
|
+
interface DcmtkProcessEventMap {
|
|
19
|
+
started: [];
|
|
20
|
+
stopped: [{
|
|
21
|
+
readonly reason: string;
|
|
22
|
+
}];
|
|
23
|
+
error: [{
|
|
24
|
+
readonly error: Error;
|
|
25
|
+
readonly fatal: boolean;
|
|
26
|
+
}];
|
|
27
|
+
line: [{
|
|
28
|
+
readonly source: LineSource;
|
|
29
|
+
readonly text: string;
|
|
30
|
+
}];
|
|
31
|
+
}
|
|
32
|
+
/** Configuration for a DcmtkProcess instance. */
|
|
33
|
+
interface DcmtkProcessConfig {
|
|
34
|
+
/** Full path to the DCMTK binary. */
|
|
35
|
+
readonly binary: string;
|
|
36
|
+
/** Command-line arguments. */
|
|
37
|
+
readonly args: readonly string[];
|
|
38
|
+
/** Working directory. */
|
|
39
|
+
readonly cwd?: string | undefined;
|
|
40
|
+
/** Timeout for start() to resolve, in milliseconds. */
|
|
41
|
+
readonly startTimeoutMs?: number | undefined;
|
|
42
|
+
/** Timeout for graceful drain during stop(), in milliseconds. */
|
|
43
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* A function that inspects each output line and returns `true` when
|
|
46
|
+
* the process is considered "started" (e.g., "listening on port X").
|
|
47
|
+
* If not provided, start() resolves immediately after spawn.
|
|
48
|
+
*/
|
|
49
|
+
readonly isStartedPredicate?: ((line: string) => boolean) | undefined;
|
|
50
|
+
}
|
|
51
|
+
declare const ProcessState: {
|
|
52
|
+
readonly IDLE: "IDLE";
|
|
53
|
+
readonly STARTING: "STARTING";
|
|
54
|
+
readonly RUNNING: "RUNNING";
|
|
55
|
+
readonly STOPPING: "STOPPING";
|
|
56
|
+
readonly STOPPED: "STOPPED";
|
|
57
|
+
};
|
|
58
|
+
type ProcessStateValue = (typeof ProcessState)[keyof typeof ProcessState];
|
|
59
|
+
/**
|
|
60
|
+
* Base class for persistent DCMTK processes (e.g., dcmrecv, storescp).
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const proc = new DcmtkProcess({
|
|
65
|
+
* binary: '/usr/local/bin/dcmrecv',
|
|
66
|
+
* args: ['--config', 'storescp.cfg', '11112'],
|
|
67
|
+
* isStartedPredicate: line => line.includes('listening'),
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* const result = await proc.start();
|
|
71
|
+
* if (result.ok) {
|
|
72
|
+
* // Process is running
|
|
73
|
+
* proc.on('line', ({ source, text }) => console.log(`[${source}] ${text}`));
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* await proc.stop();
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare class DcmtkProcess extends EventEmitter<DcmtkProcessEventMap> {
|
|
80
|
+
private state;
|
|
81
|
+
private child;
|
|
82
|
+
private stdoutBuffer;
|
|
83
|
+
private stderrBuffer;
|
|
84
|
+
private readonly config;
|
|
85
|
+
constructor(config: DcmtkProcessConfig);
|
|
86
|
+
/** Whether the process is currently running. */
|
|
87
|
+
get isRunning(): boolean;
|
|
88
|
+
/** Current process state. */
|
|
89
|
+
get currentState(): ProcessStateValue;
|
|
90
|
+
/**
|
|
91
|
+
* Starts the DCMTK process.
|
|
92
|
+
*
|
|
93
|
+
* Single-use enforcement: returns an error if called more than once.
|
|
94
|
+
* Waits for the `isStartedPredicate` to match an output line, or resolves
|
|
95
|
+
* immediately after spawn if no predicate is configured.
|
|
96
|
+
*
|
|
97
|
+
* @returns A Result indicating success or failure
|
|
98
|
+
*/
|
|
99
|
+
start(): Promise<Result<void>>;
|
|
100
|
+
/**
|
|
101
|
+
* Stops the process gracefully.
|
|
102
|
+
*
|
|
103
|
+
* Waits up to `drainTimeoutMs` for the process to exit, then force-kills.
|
|
104
|
+
*/
|
|
105
|
+
stop(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Implements Disposable for deterministic cleanup (Rule 5.1).
|
|
108
|
+
*/
|
|
109
|
+
[Symbol.dispose](): void;
|
|
110
|
+
private killChild;
|
|
111
|
+
/**
|
|
112
|
+
* Wires all child process event handlers for startup.
|
|
113
|
+
*/
|
|
114
|
+
private wireChildEvents;
|
|
115
|
+
/**
|
|
116
|
+
* Wires a line listener that resolves start() when the predicate matches.
|
|
117
|
+
*/
|
|
118
|
+
private wireStartedPredicate;
|
|
119
|
+
private handleData;
|
|
120
|
+
private processLines;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Event pattern definitions for DCMTK output parsing.
|
|
125
|
+
*
|
|
126
|
+
* An EventPattern describes a regex that matches a specific DCMTK output pattern,
|
|
127
|
+
* along with a processor function that extracts structured data from the match.
|
|
128
|
+
*
|
|
129
|
+
* Supports both single-line and multi-line block matching.
|
|
130
|
+
*
|
|
131
|
+
* @module parsers/EventPattern
|
|
132
|
+
*/
|
|
133
|
+
/**
|
|
134
|
+
* Configuration for multi-line block matching.
|
|
135
|
+
*
|
|
136
|
+
* When a line matches the header, the parser accumulates subsequent lines
|
|
137
|
+
* until the footer is matched or limits are reached.
|
|
138
|
+
*/
|
|
139
|
+
interface MultiLineConfig {
|
|
140
|
+
/** Regex that identifies the start of a multi-line block. */
|
|
141
|
+
readonly header: RegExp;
|
|
142
|
+
/** Regex that identifies the end of a multi-line block. */
|
|
143
|
+
readonly footer: RegExp;
|
|
144
|
+
/** Maximum lines to accumulate (Rule 8.1: bounded). */
|
|
145
|
+
readonly maxLines: number;
|
|
146
|
+
/** Timeout in ms for block completion (Rule 4.2: mandatory timeout). */
|
|
147
|
+
readonly timeoutMs: number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Defines a pattern that can be matched against DCMTK process output lines.
|
|
151
|
+
*
|
|
152
|
+
* @typeParam T - The type of data extracted by the processor function
|
|
153
|
+
*/
|
|
154
|
+
interface EventPattern<T = unknown> {
|
|
155
|
+
/** The event name emitted when this pattern matches. */
|
|
156
|
+
readonly event: string;
|
|
157
|
+
/** The regex pattern to match against individual lines. */
|
|
158
|
+
readonly pattern: RegExp;
|
|
159
|
+
/** Extracts structured data from the regex match. */
|
|
160
|
+
readonly processor: (match: RegExpMatchArray) => T;
|
|
161
|
+
/** Optional multi-line block configuration. */
|
|
162
|
+
readonly multiLine?: MultiLineConfig | undefined;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Line-by-line parser for DCMTK process output.
|
|
167
|
+
*
|
|
168
|
+
* Matches output lines against registered EventPattern objects and emits
|
|
169
|
+
* structured events. Supports both single-line and multi-line block matching.
|
|
170
|
+
*
|
|
171
|
+
* All algorithms are iterative (Rule 8.2: no recursion).
|
|
172
|
+
* All buffers are bounded (Rule 8.1).
|
|
173
|
+
*
|
|
174
|
+
* @module parsers/LineParser
|
|
175
|
+
*/
|
|
176
|
+
|
|
177
|
+
/** Events emitted by the LineParser. */
|
|
178
|
+
interface LineParserEventMap {
|
|
179
|
+
/** Emitted when a pattern matches. Carries the event name and extracted data. */
|
|
180
|
+
match: [{
|
|
181
|
+
readonly event: string;
|
|
182
|
+
readonly data: unknown;
|
|
183
|
+
}];
|
|
184
|
+
/** Emitted when a multi-line block times out before the footer is matched. Consumers should listen for this event to detect and handle incomplete blocks. */
|
|
185
|
+
blockTimeout: [{
|
|
186
|
+
readonly event: string;
|
|
187
|
+
readonly lines: readonly string[];
|
|
188
|
+
}];
|
|
189
|
+
/** Emitted when a pattern processor throws. */
|
|
190
|
+
error: [Error];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Parses DCMTK output lines against registered event patterns.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* const parser = new LineParser();
|
|
198
|
+
* parser.addPattern({
|
|
199
|
+
* event: 'LISTENING',
|
|
200
|
+
* pattern: /listening on port (\d+)/i,
|
|
201
|
+
* processor: match => ({ port: Number(match[1]) }),
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* parser.on('match', ({ event, data }) => {
|
|
205
|
+
* console.log(`${event}:`, data);
|
|
206
|
+
* });
|
|
207
|
+
*
|
|
208
|
+
* parser.feed('I: listening on port 11112');
|
|
209
|
+
* // Emits: match { event: 'LISTENING', data: { port: 11112 } }
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
declare class LineParser extends EventEmitter<LineParserEventMap> {
|
|
213
|
+
private readonly patterns;
|
|
214
|
+
private activeBlock;
|
|
215
|
+
constructor();
|
|
216
|
+
/**
|
|
217
|
+
* Registers an event pattern.
|
|
218
|
+
*
|
|
219
|
+
* @param pattern - The pattern to register
|
|
220
|
+
* @returns Result indicating success or failure if pattern limit exceeded
|
|
221
|
+
*/
|
|
222
|
+
addPattern(pattern: EventPattern): Result<void>;
|
|
223
|
+
/**
|
|
224
|
+
* Feeds a single line of output to the parser.
|
|
225
|
+
*
|
|
226
|
+
* The line is matched against all registered patterns (iteratively, Rule 8.2).
|
|
227
|
+
* If a multi-line block is active, the line is accumulated until the footer matches.
|
|
228
|
+
*
|
|
229
|
+
* @param line - A single line of DCMTK output (without trailing newline)
|
|
230
|
+
*/
|
|
231
|
+
feed(line: string): void;
|
|
232
|
+
/**
|
|
233
|
+
* Feeds multiple lines of output (e.g., from a chunk split by newlines).
|
|
234
|
+
*
|
|
235
|
+
* @param lines - Array of lines to process
|
|
236
|
+
*/
|
|
237
|
+
feedLines(lines: readonly string[]): void;
|
|
238
|
+
/**
|
|
239
|
+
* Resets the parser state, clearing any active multi-line block.
|
|
240
|
+
*/
|
|
241
|
+
reset(): void;
|
|
242
|
+
/**
|
|
243
|
+
* Implements Disposable for cleanup (Rule 5.1).
|
|
244
|
+
*/
|
|
245
|
+
[Symbol.dispose](): void;
|
|
246
|
+
private matchSingleLine;
|
|
247
|
+
private startBlock;
|
|
248
|
+
private feedToBlock;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Event patterns and types for dcmrecv output parsing.
|
|
253
|
+
*
|
|
254
|
+
* Defines regex patterns that match DCMTK dcmrecv verbose output,
|
|
255
|
+
* along with typed event data interfaces for each event.
|
|
256
|
+
*
|
|
257
|
+
* @module events/dcmrecv
|
|
258
|
+
*/
|
|
259
|
+
|
|
260
|
+
/** Events emitted by dcmrecv process output. */
|
|
261
|
+
declare const DcmrecvEvent: {
|
|
262
|
+
readonly LISTENING: "LISTENING";
|
|
263
|
+
readonly ASSOCIATION_RECEIVED: "ASSOCIATION_RECEIVED";
|
|
264
|
+
readonly ASSOCIATION_ACKNOWLEDGED: "ASSOCIATION_ACKNOWLEDGED";
|
|
265
|
+
readonly C_STORE_REQUEST: "C_STORE_REQUEST";
|
|
266
|
+
readonly STORED_FILE: "STORED_FILE";
|
|
267
|
+
readonly ASSOCIATION_RELEASE: "ASSOCIATION_RELEASE";
|
|
268
|
+
readonly ASSOCIATION_ABORTED: "ASSOCIATION_ABORTED";
|
|
269
|
+
readonly ECHO_REQUEST: "ECHO_REQUEST";
|
|
270
|
+
readonly CANNOT_START_LISTENER: "CANNOT_START_LISTENER";
|
|
271
|
+
readonly REFUSING_ASSOCIATION: "REFUSING_ASSOCIATION";
|
|
272
|
+
/** Synthetic: STORED_FILE enriched with association context. */
|
|
273
|
+
readonly FILE_RECEIVED: "FILE_RECEIVED";
|
|
274
|
+
/** Synthetic: emitted on association release/abort with summary. */
|
|
275
|
+
readonly ASSOCIATION_COMPLETE: "ASSOCIATION_COMPLETE";
|
|
276
|
+
};
|
|
277
|
+
type DcmrecvEventValue = (typeof DcmrecvEvent)[keyof typeof DcmrecvEvent];
|
|
278
|
+
/** Data for ASSOCIATION_RECEIVED event. */
|
|
279
|
+
interface AssociationReceivedData {
|
|
280
|
+
readonly source: string;
|
|
281
|
+
readonly callingAE: string;
|
|
282
|
+
readonly calledAE: string;
|
|
283
|
+
}
|
|
284
|
+
/** Data for ASSOCIATION_ACKNOWLEDGED event. */
|
|
285
|
+
interface AssociationAcknowledgedData {
|
|
286
|
+
readonly maxSendPDV: number;
|
|
287
|
+
}
|
|
288
|
+
/** Data for C_STORE_REQUEST event. */
|
|
289
|
+
interface CStoreRequestData {
|
|
290
|
+
readonly raw: string;
|
|
291
|
+
}
|
|
292
|
+
/** Data for STORED_FILE event. */
|
|
293
|
+
interface StoredFileData {
|
|
294
|
+
readonly filePath: string;
|
|
295
|
+
}
|
|
296
|
+
/** Data for REFUSING_ASSOCIATION event. */
|
|
297
|
+
interface RefusingAssociationData {
|
|
298
|
+
readonly reason: string;
|
|
299
|
+
}
|
|
300
|
+
/** Data for CANNOT_START_LISTENER event. */
|
|
301
|
+
interface CannotStartListenerData {
|
|
302
|
+
readonly message: string;
|
|
303
|
+
}
|
|
304
|
+
/** Data for FILE_RECEIVED synthetic event. */
|
|
305
|
+
interface FileReceivedData {
|
|
306
|
+
readonly filePath: string;
|
|
307
|
+
readonly associationId: string;
|
|
308
|
+
readonly callingAE: string;
|
|
309
|
+
readonly calledAE: string;
|
|
310
|
+
readonly source: string;
|
|
311
|
+
}
|
|
312
|
+
/** Data for ASSOCIATION_COMPLETE synthetic event. */
|
|
313
|
+
interface AssociationCompleteData {
|
|
314
|
+
readonly associationId: string;
|
|
315
|
+
readonly callingAE: string;
|
|
316
|
+
readonly calledAE: string;
|
|
317
|
+
readonly source: string;
|
|
318
|
+
readonly files: readonly string[];
|
|
319
|
+
readonly durationMs: number;
|
|
320
|
+
readonly endReason: 'release' | 'abort';
|
|
321
|
+
}
|
|
322
|
+
/** Event patterns for parsing dcmrecv verbose output. */
|
|
323
|
+
declare const DCMRECV_PATTERNS: readonly EventPattern[];
|
|
324
|
+
/** Events that indicate fatal errors (process should be stopped). */
|
|
325
|
+
declare const DCMRECV_FATAL_EVENTS: ReadonlySet<string>;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Event patterns and types for storescp output parsing.
|
|
329
|
+
*
|
|
330
|
+
* Extends dcmrecv patterns with storescp-specific events like
|
|
331
|
+
* file storage progress and subdirectory creation.
|
|
332
|
+
*
|
|
333
|
+
* @module events/storescp
|
|
334
|
+
*/
|
|
335
|
+
|
|
336
|
+
/** Events emitted by storescp process output. */
|
|
337
|
+
declare const StorescpEvent: {
|
|
338
|
+
readonly STORING_FILE: "STORING_FILE";
|
|
339
|
+
readonly SUBDIRECTORY_CREATED: "SUBDIRECTORY_CREATED";
|
|
340
|
+
readonly LISTENING: "LISTENING";
|
|
341
|
+
readonly ASSOCIATION_RECEIVED: "ASSOCIATION_RECEIVED";
|
|
342
|
+
readonly ASSOCIATION_ACKNOWLEDGED: "ASSOCIATION_ACKNOWLEDGED";
|
|
343
|
+
readonly C_STORE_REQUEST: "C_STORE_REQUEST";
|
|
344
|
+
readonly STORED_FILE: "STORED_FILE";
|
|
345
|
+
readonly ASSOCIATION_RELEASE: "ASSOCIATION_RELEASE";
|
|
346
|
+
readonly ASSOCIATION_ABORTED: "ASSOCIATION_ABORTED";
|
|
347
|
+
readonly ECHO_REQUEST: "ECHO_REQUEST";
|
|
348
|
+
readonly CANNOT_START_LISTENER: "CANNOT_START_LISTENER";
|
|
349
|
+
readonly REFUSING_ASSOCIATION: "REFUSING_ASSOCIATION";
|
|
350
|
+
readonly FILE_RECEIVED: "FILE_RECEIVED";
|
|
351
|
+
readonly ASSOCIATION_COMPLETE: "ASSOCIATION_COMPLETE";
|
|
352
|
+
};
|
|
353
|
+
type StorescpEventValue = (typeof StorescpEvent)[keyof typeof StorescpEvent];
|
|
354
|
+
/** Data for STORING_FILE event. */
|
|
355
|
+
interface StoringFileData {
|
|
356
|
+
readonly filePath: string;
|
|
357
|
+
}
|
|
358
|
+
/** Data for SUBDIRECTORY_CREATED event. */
|
|
359
|
+
interface SubdirectoryCreatedData {
|
|
360
|
+
readonly directory: string;
|
|
361
|
+
}
|
|
362
|
+
/** Combined event patterns for parsing storescp verbose output. */
|
|
363
|
+
declare const STORESCP_PATTERNS: readonly EventPattern[];
|
|
364
|
+
/** Events that indicate fatal errors (process should be stopped). */
|
|
365
|
+
declare const STORESCP_FATAL_EVENTS: ReadonlySet<string>;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Event patterns and types for dcmprscp output parsing.
|
|
369
|
+
*
|
|
370
|
+
* Defines regex patterns that match DCMTK dcmprscp (print management SCP)
|
|
371
|
+
* verbose output, along with typed event data interfaces for each event.
|
|
372
|
+
*
|
|
373
|
+
* @module events/dcmprscp
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
/** Events emitted by dcmprscp process output. */
|
|
377
|
+
declare const DcmprscpEvent: {
|
|
378
|
+
readonly DATABASE_READY: "DATABASE_READY";
|
|
379
|
+
readonly ASSOCIATION_RECEIVED: "ASSOCIATION_RECEIVED";
|
|
380
|
+
readonly ASSOCIATION_ACKNOWLEDGED: "ASSOCIATION_ACKNOWLEDGED";
|
|
381
|
+
readonly ASSOCIATION_RELEASE: "ASSOCIATION_RELEASE";
|
|
382
|
+
readonly ASSOCIATION_ABORTED: "ASSOCIATION_ABORTED";
|
|
383
|
+
readonly CANNOT_START_LISTENER: "CANNOT_START_LISTENER";
|
|
384
|
+
readonly CONFIG_ERROR: "CONFIG_ERROR";
|
|
385
|
+
};
|
|
386
|
+
type DcmprscpEventValue = (typeof DcmprscpEvent)[keyof typeof DcmprscpEvent];
|
|
387
|
+
/** Data for DATABASE_READY event. */
|
|
388
|
+
interface DatabaseReadyData {
|
|
389
|
+
readonly directory: string;
|
|
390
|
+
}
|
|
391
|
+
/** Data for ASSOCIATION_RECEIVED event. */
|
|
392
|
+
interface PrintAssociationReceivedData {
|
|
393
|
+
readonly peerInfo: string;
|
|
394
|
+
}
|
|
395
|
+
/** Data for ASSOCIATION_ACKNOWLEDGED event. */
|
|
396
|
+
interface PrintAssociationAcknowledgedData {
|
|
397
|
+
readonly maxSendPDV: number;
|
|
398
|
+
}
|
|
399
|
+
/** Data for CANNOT_START_LISTENER event. */
|
|
400
|
+
interface PrintCannotStartListenerData {
|
|
401
|
+
readonly message: string;
|
|
402
|
+
}
|
|
403
|
+
/** Data for CONFIG_ERROR event. */
|
|
404
|
+
interface ConfigErrorData {
|
|
405
|
+
readonly message: string;
|
|
406
|
+
}
|
|
407
|
+
/** Event patterns for parsing dcmprscp verbose output. */
|
|
408
|
+
declare const DCMPRSCP_PATTERNS: readonly EventPattern[];
|
|
409
|
+
/** Events that indicate fatal errors (process should be stopped). */
|
|
410
|
+
declare const DCMPRSCP_FATAL_EVENTS: ReadonlySet<string>;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Event patterns and types for dcmpsrcv output parsing.
|
|
414
|
+
*
|
|
415
|
+
* Defines regex patterns that match DCMTK dcmpsrcv (viewer network receiver)
|
|
416
|
+
* verbose output. Shares several patterns with dcmrecv/storescp since
|
|
417
|
+
* dcmpsrcv handles incoming DICOM associations and C-STORE operations.
|
|
418
|
+
*
|
|
419
|
+
* @module events/dcmpsrcv
|
|
420
|
+
*/
|
|
421
|
+
|
|
422
|
+
/** Events emitted by dcmpsrcv process output. */
|
|
423
|
+
declare const DcmpsrcvEvent: {
|
|
424
|
+
readonly LISTENING: "LISTENING";
|
|
425
|
+
readonly DATABASE_READY: "DATABASE_READY";
|
|
426
|
+
readonly ASSOCIATION_RECEIVED: "ASSOCIATION_RECEIVED";
|
|
427
|
+
readonly ASSOCIATION_ACKNOWLEDGED: "ASSOCIATION_ACKNOWLEDGED";
|
|
428
|
+
readonly ECHO_REQUEST: "ECHO_REQUEST";
|
|
429
|
+
readonly C_STORE_REQUEST: "C_STORE_REQUEST";
|
|
430
|
+
readonly FILE_DELETED: "FILE_DELETED";
|
|
431
|
+
readonly ASSOCIATION_RELEASE: "ASSOCIATION_RELEASE";
|
|
432
|
+
readonly ASSOCIATION_ABORTED: "ASSOCIATION_ABORTED";
|
|
433
|
+
readonly CANNOT_START_LISTENER: "CANNOT_START_LISTENER";
|
|
434
|
+
readonly CONFIG_ERROR: "CONFIG_ERROR";
|
|
435
|
+
readonly TERMINATING: "TERMINATING";
|
|
436
|
+
};
|
|
437
|
+
type DcmpsrcvEventValue = (typeof DcmpsrcvEvent)[keyof typeof DcmpsrcvEvent];
|
|
438
|
+
/** Data for LISTENING event. */
|
|
439
|
+
interface ReceiverListeningData {
|
|
440
|
+
readonly receiverId: string;
|
|
441
|
+
readonly port: number;
|
|
442
|
+
}
|
|
443
|
+
/** Data for DATABASE_READY event. */
|
|
444
|
+
interface ReceiverDatabaseReadyData {
|
|
445
|
+
readonly directory: string;
|
|
446
|
+
}
|
|
447
|
+
/** Data for ASSOCIATION_RECEIVED event. */
|
|
448
|
+
interface ReceiverAssociationReceivedData {
|
|
449
|
+
readonly peerInfo: string;
|
|
450
|
+
}
|
|
451
|
+
/** Data for ASSOCIATION_ACKNOWLEDGED event. */
|
|
452
|
+
interface ReceiverAssociationAcknowledgedData {
|
|
453
|
+
readonly maxSendPDV: number;
|
|
454
|
+
}
|
|
455
|
+
/** Data for ECHO_REQUEST event. */
|
|
456
|
+
interface ReceiverEchoRequestData {
|
|
457
|
+
readonly messageId: number;
|
|
458
|
+
}
|
|
459
|
+
/** Data for C_STORE_REQUEST event. */
|
|
460
|
+
interface ReceiverCStoreRequestData {
|
|
461
|
+
readonly raw: string;
|
|
462
|
+
}
|
|
463
|
+
/** Data for FILE_DELETED event. */
|
|
464
|
+
interface FileDeletedData {
|
|
465
|
+
readonly filePath: string;
|
|
466
|
+
}
|
|
467
|
+
/** Data for CANNOT_START_LISTENER event. */
|
|
468
|
+
interface ReceiverCannotStartListenerData {
|
|
469
|
+
readonly message: string;
|
|
470
|
+
}
|
|
471
|
+
/** Data for CONFIG_ERROR event. */
|
|
472
|
+
interface ReceiverConfigErrorData {
|
|
473
|
+
readonly message: string;
|
|
474
|
+
}
|
|
475
|
+
/** Event patterns for parsing dcmpsrcv verbose output. */
|
|
476
|
+
declare const DCMPSRCV_PATTERNS: readonly EventPattern[];
|
|
477
|
+
/** Events that indicate fatal errors (process should be stopped). */
|
|
478
|
+
declare const DCMPSRCV_FATAL_EVENTS: ReadonlySet<string>;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Event patterns and types for dcmqrscp output parsing.
|
|
482
|
+
*
|
|
483
|
+
* Defines regex patterns that match DCMTK dcmqrscp (Query/Retrieve SCP)
|
|
484
|
+
* verbose output, along with typed event data interfaces for each event.
|
|
485
|
+
*
|
|
486
|
+
* @module events/dcmqrscp
|
|
487
|
+
*/
|
|
488
|
+
|
|
489
|
+
/** Events emitted by dcmqrscp process output. */
|
|
490
|
+
declare const DcmqrscpEvent: {
|
|
491
|
+
readonly LISTENING: "LISTENING";
|
|
492
|
+
readonly ASSOCIATION_RECEIVED: "ASSOCIATION_RECEIVED";
|
|
493
|
+
readonly ASSOCIATION_ACKNOWLEDGED: "ASSOCIATION_ACKNOWLEDGED";
|
|
494
|
+
readonly C_FIND_REQUEST: "C_FIND_REQUEST";
|
|
495
|
+
readonly C_MOVE_REQUEST: "C_MOVE_REQUEST";
|
|
496
|
+
readonly C_GET_REQUEST: "C_GET_REQUEST";
|
|
497
|
+
readonly C_STORE_REQUEST: "C_STORE_REQUEST";
|
|
498
|
+
readonly ASSOCIATION_RELEASE: "ASSOCIATION_RELEASE";
|
|
499
|
+
readonly ASSOCIATION_ABORTED: "ASSOCIATION_ABORTED";
|
|
500
|
+
readonly CANNOT_START_LISTENER: "CANNOT_START_LISTENER";
|
|
501
|
+
};
|
|
502
|
+
type DcmqrscpEventValue = (typeof DcmqrscpEvent)[keyof typeof DcmqrscpEvent];
|
|
503
|
+
/** Data for LISTENING event. */
|
|
504
|
+
interface QRListeningData {
|
|
505
|
+
readonly port: number;
|
|
506
|
+
}
|
|
507
|
+
/** Data for ASSOCIATION_RECEIVED event. */
|
|
508
|
+
interface QRAssociationReceivedData {
|
|
509
|
+
readonly peerInfo: string;
|
|
510
|
+
}
|
|
511
|
+
/** Data for ASSOCIATION_ACKNOWLEDGED event. */
|
|
512
|
+
interface QRAssociationAcknowledgedData {
|
|
513
|
+
readonly maxSendPDV: number;
|
|
514
|
+
}
|
|
515
|
+
/** Data for C_FIND_REQUEST event. */
|
|
516
|
+
interface QRCFindRequestData {
|
|
517
|
+
readonly raw: string;
|
|
518
|
+
}
|
|
519
|
+
/** Data for C_MOVE_REQUEST event. */
|
|
520
|
+
interface QRCMoveRequestData {
|
|
521
|
+
readonly raw: string;
|
|
522
|
+
}
|
|
523
|
+
/** Data for C_GET_REQUEST event. */
|
|
524
|
+
interface QRCGetRequestData {
|
|
525
|
+
readonly raw: string;
|
|
526
|
+
}
|
|
527
|
+
/** Data for C_STORE_REQUEST event. */
|
|
528
|
+
interface QRCStoreRequestData {
|
|
529
|
+
readonly raw: string;
|
|
530
|
+
}
|
|
531
|
+
/** Data for CANNOT_START_LISTENER event. */
|
|
532
|
+
interface QRCannotStartListenerData {
|
|
533
|
+
readonly message: string;
|
|
534
|
+
}
|
|
535
|
+
/** Event patterns for parsing dcmqrscp verbose output. */
|
|
536
|
+
declare const DCMQRSCP_PATTERNS: readonly EventPattern[];
|
|
537
|
+
/** Events that indicate fatal errors (process should be stopped). */
|
|
538
|
+
declare const DCMQRSCP_FATAL_EVENTS: ReadonlySet<string>;
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Event patterns and types for wlmscpfs output parsing.
|
|
542
|
+
*
|
|
543
|
+
* Defines regex patterns that match DCMTK wlmscpfs (Worklist Management SCP)
|
|
544
|
+
* verbose output, along with typed event data interfaces for each event.
|
|
545
|
+
*
|
|
546
|
+
* @module events/wlmscpfs
|
|
547
|
+
*/
|
|
548
|
+
|
|
549
|
+
/** Events emitted by wlmscpfs process output. */
|
|
550
|
+
declare const WlmscpfsEvent: {
|
|
551
|
+
readonly LISTENING: "LISTENING";
|
|
552
|
+
readonly ASSOCIATION_RECEIVED: "ASSOCIATION_RECEIVED";
|
|
553
|
+
readonly ASSOCIATION_ACKNOWLEDGED: "ASSOCIATION_ACKNOWLEDGED";
|
|
554
|
+
readonly C_FIND_REQUEST: "C_FIND_REQUEST";
|
|
555
|
+
readonly ASSOCIATION_RELEASE: "ASSOCIATION_RELEASE";
|
|
556
|
+
readonly ASSOCIATION_ABORTED: "ASSOCIATION_ABORTED";
|
|
557
|
+
readonly ECHO_REQUEST: "ECHO_REQUEST";
|
|
558
|
+
readonly CANNOT_START_LISTENER: "CANNOT_START_LISTENER";
|
|
559
|
+
};
|
|
560
|
+
type WlmscpfsEventValue = (typeof WlmscpfsEvent)[keyof typeof WlmscpfsEvent];
|
|
561
|
+
/** Data for LISTENING event. */
|
|
562
|
+
interface WlmListeningData {
|
|
563
|
+
readonly port: number;
|
|
564
|
+
}
|
|
565
|
+
/** Data for ASSOCIATION_RECEIVED event. */
|
|
566
|
+
interface WlmAssociationReceivedData {
|
|
567
|
+
readonly peerInfo: string;
|
|
568
|
+
}
|
|
569
|
+
/** Data for ASSOCIATION_ACKNOWLEDGED event. */
|
|
570
|
+
interface WlmAssociationAcknowledgedData {
|
|
571
|
+
readonly maxSendPDV: number;
|
|
572
|
+
}
|
|
573
|
+
/** Data for C_FIND_REQUEST event. */
|
|
574
|
+
interface WlmCFindRequestData {
|
|
575
|
+
readonly raw: string;
|
|
576
|
+
}
|
|
577
|
+
/** Data for CANNOT_START_LISTENER event. */
|
|
578
|
+
interface WlmCannotStartListenerData {
|
|
579
|
+
readonly message: string;
|
|
580
|
+
}
|
|
581
|
+
/** Event patterns for parsing wlmscpfs verbose output. */
|
|
582
|
+
declare const WLMSCPFS_PATTERNS: readonly EventPattern[];
|
|
583
|
+
/** Events that indicate fatal errors (process should be stopped). */
|
|
584
|
+
declare const WLMSCPFS_FATAL_EVENTS: ReadonlySet<string>;
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* DICOM receiver server wrapping the dcmrecv binary.
|
|
588
|
+
*
|
|
589
|
+
* Provides a type-safe, event-driven API for receiving DICOM objects
|
|
590
|
+
* via C-STORE. Uses a static factory pattern because binary resolution
|
|
591
|
+
* must happen before the constructor call.
|
|
592
|
+
*
|
|
593
|
+
* @module servers/Dcmrecv
|
|
594
|
+
*/
|
|
595
|
+
|
|
596
|
+
/** Typed event map for the Dcmrecv server. */
|
|
597
|
+
interface DcmrecvEventMap {
|
|
598
|
+
LISTENING: [];
|
|
599
|
+
ASSOCIATION_RECEIVED: [AssociationReceivedData];
|
|
600
|
+
ASSOCIATION_ACKNOWLEDGED: [AssociationAcknowledgedData];
|
|
601
|
+
C_STORE_REQUEST: [CStoreRequestData];
|
|
602
|
+
STORED_FILE: [StoredFileData];
|
|
603
|
+
ASSOCIATION_RELEASE: [];
|
|
604
|
+
ASSOCIATION_ABORTED: [];
|
|
605
|
+
ECHO_REQUEST: [];
|
|
606
|
+
CANNOT_START_LISTENER: [CannotStartListenerData];
|
|
607
|
+
REFUSING_ASSOCIATION: [RefusingAssociationData];
|
|
608
|
+
FILE_RECEIVED: [FileReceivedData];
|
|
609
|
+
ASSOCIATION_COMPLETE: [AssociationCompleteData];
|
|
610
|
+
}
|
|
611
|
+
/** Subdirectory generation mode for received files. */
|
|
612
|
+
declare const SubdirectoryMode: {
|
|
613
|
+
readonly NONE: "none";
|
|
614
|
+
readonly SERIES_DATE: "series-date";
|
|
615
|
+
};
|
|
616
|
+
type SubdirectoryModeValue = (typeof SubdirectoryMode)[keyof typeof SubdirectoryMode];
|
|
617
|
+
/** Filename generation mode for received files. */
|
|
618
|
+
declare const FilenameMode: {
|
|
619
|
+
readonly DEFAULT: "default";
|
|
620
|
+
readonly UNIQUE: "unique";
|
|
621
|
+
readonly SHORT_UNIQUE: "short-unique";
|
|
622
|
+
readonly SYSTEM_TIME: "system-time";
|
|
623
|
+
};
|
|
624
|
+
type FilenameModeValue = (typeof FilenameMode)[keyof typeof FilenameMode];
|
|
625
|
+
/** Storage mode for received DICOM objects. */
|
|
626
|
+
declare const StorageMode: {
|
|
627
|
+
readonly NORMAL: "normal";
|
|
628
|
+
readonly BIT_PRESERVING: "bit-preserving";
|
|
629
|
+
readonly IGNORE: "ignore";
|
|
630
|
+
};
|
|
631
|
+
type StorageModeValue = (typeof StorageMode)[keyof typeof StorageMode];
|
|
632
|
+
/** Options for creating a Dcmrecv server instance. */
|
|
633
|
+
interface DcmrecvOptions {
|
|
634
|
+
/** Port to listen on (required). */
|
|
635
|
+
readonly port: number;
|
|
636
|
+
/** Application Entity Title. */
|
|
637
|
+
readonly aeTitle?: string | undefined;
|
|
638
|
+
/** Output directory for received files. */
|
|
639
|
+
readonly outputDirectory?: string | undefined;
|
|
640
|
+
/** Path to an association negotiation configuration file. */
|
|
641
|
+
readonly configFile?: string | undefined;
|
|
642
|
+
/** Profile name within the configuration file. */
|
|
643
|
+
readonly configProfile?: string | undefined;
|
|
644
|
+
/** Subdirectory generation mode. */
|
|
645
|
+
readonly subdirectory?: SubdirectoryModeValue | undefined;
|
|
646
|
+
/** Filename generation mode. */
|
|
647
|
+
readonly filenameMode?: FilenameModeValue | undefined;
|
|
648
|
+
/** File extension for received files. */
|
|
649
|
+
readonly filenameExtension?: string | undefined;
|
|
650
|
+
/** Storage mode for received DICOM objects. */
|
|
651
|
+
readonly storageMode?: StorageModeValue | undefined;
|
|
652
|
+
/** ACSE timeout in seconds (passed to DCMTK as-is). */
|
|
653
|
+
readonly acseTimeout?: number | undefined;
|
|
654
|
+
/** DIMSE timeout in seconds (passed to DCMTK as-is). */
|
|
655
|
+
readonly dimseTimeout?: number | undefined;
|
|
656
|
+
/** Maximum PDU receive size. */
|
|
657
|
+
readonly maxPdu?: number | undefined;
|
|
658
|
+
/** Timeout for start() to resolve (milliseconds). */
|
|
659
|
+
readonly startTimeoutMs?: number | undefined;
|
|
660
|
+
/** Timeout for graceful drain during stop() (milliseconds). */
|
|
661
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
662
|
+
/** AbortSignal for external cancellation. */
|
|
663
|
+
readonly signal?: AbortSignal | undefined;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* DICOM receiver server wrapping the dcmrecv binary.
|
|
667
|
+
*
|
|
668
|
+
* Uses a static `create()` factory because binary resolution is fallible
|
|
669
|
+
* and must complete before the constructor runs.
|
|
670
|
+
*
|
|
671
|
+
* Server-specific events (LISTENING, STORED_FILE, etc.) are emitted dynamically
|
|
672
|
+
* via the LineParser. Use `onEvent()` for typed listeners on server events.
|
|
673
|
+
*
|
|
674
|
+
* @example
|
|
675
|
+
* ```ts
|
|
676
|
+
* const result = Dcmrecv.create({ port: 11112, outputDirectory: '/tmp/received' });
|
|
677
|
+
* if (result.ok) {
|
|
678
|
+
* const server = result.value;
|
|
679
|
+
* server.onEvent('STORED_FILE', (data) => console.log('Stored:', data.filePath));
|
|
680
|
+
* const startResult = await server.start();
|
|
681
|
+
* }
|
|
682
|
+
* ```
|
|
683
|
+
*/
|
|
684
|
+
declare class Dcmrecv extends DcmtkProcess {
|
|
685
|
+
private readonly parser;
|
|
686
|
+
private readonly tracker;
|
|
687
|
+
private abortSignal;
|
|
688
|
+
private abortHandler;
|
|
689
|
+
private constructor();
|
|
690
|
+
/**
|
|
691
|
+
* Registers a typed listener for a dcmrecv-specific event.
|
|
692
|
+
*
|
|
693
|
+
* @param event - The event name from DcmrecvEventMap
|
|
694
|
+
* @param listener - Callback receiving typed event data
|
|
695
|
+
* @returns this for chaining
|
|
696
|
+
*/
|
|
697
|
+
/** Disposes the server and its parser, preventing listener leaks. */
|
|
698
|
+
[Symbol.dispose](): void;
|
|
699
|
+
onEvent<K extends keyof DcmrecvEventMap>(event: K, listener: (...args: DcmrecvEventMap[K]) => void): this;
|
|
700
|
+
/**
|
|
701
|
+
* Registers a listener for incoming associations.
|
|
702
|
+
*
|
|
703
|
+
* @param listener - Callback receiving association data
|
|
704
|
+
* @returns this for chaining
|
|
705
|
+
*/
|
|
706
|
+
onAssociationReceived(listener: (...args: DcmrecvEventMap['ASSOCIATION_RECEIVED']) => void): this;
|
|
707
|
+
/**
|
|
708
|
+
* Registers a listener for stored files.
|
|
709
|
+
*
|
|
710
|
+
* @param listener - Callback receiving stored file data
|
|
711
|
+
* @returns this for chaining
|
|
712
|
+
*/
|
|
713
|
+
onStoredFile(listener: (...args: DcmrecvEventMap['STORED_FILE']) => void): this;
|
|
714
|
+
/**
|
|
715
|
+
* Registers a listener for received files enriched with association context.
|
|
716
|
+
*
|
|
717
|
+
* @param listener - Callback receiving tracked file data
|
|
718
|
+
* @returns this for chaining
|
|
719
|
+
*/
|
|
720
|
+
onFileReceived(listener: (...args: DcmrecvEventMap['FILE_RECEIVED']) => void): this;
|
|
721
|
+
/**
|
|
722
|
+
* Registers a listener for completed associations.
|
|
723
|
+
*
|
|
724
|
+
* @param listener - Callback receiving association summary
|
|
725
|
+
* @returns this for chaining
|
|
726
|
+
*/
|
|
727
|
+
onAssociationComplete(listener: (...args: DcmrecvEventMap['ASSOCIATION_COMPLETE']) => void): this;
|
|
728
|
+
/**
|
|
729
|
+
* Creates a new Dcmrecv server instance.
|
|
730
|
+
*
|
|
731
|
+
* @param options - Configuration options for the dcmrecv server
|
|
732
|
+
* @returns A Result containing the server instance or a validation/resolution error
|
|
733
|
+
*/
|
|
734
|
+
static create(options: DcmrecvOptions): Result<Dcmrecv>;
|
|
735
|
+
/** Wires the line parser to the process output. */
|
|
736
|
+
private wireParser;
|
|
737
|
+
/** Wires the AssociationTracker to server events. */
|
|
738
|
+
private wireTracker;
|
|
739
|
+
/** Wires an AbortSignal to stop the server. */
|
|
740
|
+
private wireAbortSignal;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* DICOM Storage SCP server wrapping the storescp binary.
|
|
745
|
+
*
|
|
746
|
+
* Provides a type-safe, event-driven API for receiving DICOM objects
|
|
747
|
+
* via the storescp command-line tool. Supports sorting, exec hooks,
|
|
748
|
+
* custom transfer syntaxes, and all standard storescp options.
|
|
749
|
+
*
|
|
750
|
+
* @module servers/StoreSCP
|
|
751
|
+
*/
|
|
752
|
+
|
|
753
|
+
/** Typed event map for the StoreSCP server. */
|
|
754
|
+
interface StoreSCPEventMap {
|
|
755
|
+
LISTENING: [];
|
|
756
|
+
ASSOCIATION_RECEIVED: [AssociationReceivedData];
|
|
757
|
+
ASSOCIATION_ACKNOWLEDGED: [AssociationAcknowledgedData];
|
|
758
|
+
C_STORE_REQUEST: [CStoreRequestData];
|
|
759
|
+
STORED_FILE: [StoredFileData];
|
|
760
|
+
ASSOCIATION_RELEASE: [];
|
|
761
|
+
ASSOCIATION_ABORTED: [];
|
|
762
|
+
ECHO_REQUEST: [];
|
|
763
|
+
CANNOT_START_LISTENER: [CannotStartListenerData];
|
|
764
|
+
REFUSING_ASSOCIATION: [RefusingAssociationData];
|
|
765
|
+
STORING_FILE: [StoringFileData];
|
|
766
|
+
SUBDIRECTORY_CREATED: [SubdirectoryCreatedData];
|
|
767
|
+
FILE_RECEIVED: [FileReceivedData];
|
|
768
|
+
ASSOCIATION_COMPLETE: [AssociationCompleteData];
|
|
769
|
+
}
|
|
770
|
+
/** Preferred transfer syntax for incoming associations. */
|
|
771
|
+
declare const PreferredTransferSyntax: {
|
|
772
|
+
readonly LITTLE_ENDIAN: "little-endian";
|
|
773
|
+
readonly BIG_ENDIAN: "big-endian";
|
|
774
|
+
readonly IMPLICIT: "implicit";
|
|
775
|
+
readonly ACCEPT_ALL: "accept-all";
|
|
776
|
+
};
|
|
777
|
+
type PreferredTransferSyntaxValue = (typeof PreferredTransferSyntax)[keyof typeof PreferredTransferSyntax];
|
|
778
|
+
/** Options for creating a StoreSCP server instance. */
|
|
779
|
+
interface StoreSCPOptions {
|
|
780
|
+
/** Port to listen on (required). */
|
|
781
|
+
readonly port: number;
|
|
782
|
+
/** Application Entity Title. */
|
|
783
|
+
readonly aeTitle?: string | undefined;
|
|
784
|
+
/** Output directory for received files. */
|
|
785
|
+
readonly outputDirectory?: string | undefined;
|
|
786
|
+
/** Path to an association negotiation configuration file. */
|
|
787
|
+
readonly configFile?: string | undefined;
|
|
788
|
+
/** Profile name within the configuration file. */
|
|
789
|
+
readonly configProfile?: string | undefined;
|
|
790
|
+
/** Preferred transfer syntax (not valid with configFile). */
|
|
791
|
+
readonly preferredTransferSyntax?: PreferredTransferSyntaxValue | undefined;
|
|
792
|
+
/** Sort studies into subdirectories. */
|
|
793
|
+
readonly sortByStudy?: boolean | undefined;
|
|
794
|
+
/** Sort by Study Instance UID. */
|
|
795
|
+
readonly sortByStudyUID?: boolean | undefined;
|
|
796
|
+
/** Sort by patient name. */
|
|
797
|
+
readonly sortByPatientName?: boolean | undefined;
|
|
798
|
+
/** Generate unique filenames. */
|
|
799
|
+
readonly uniqueFilenames?: boolean | undefined;
|
|
800
|
+
/** Use bit-preserving mode. */
|
|
801
|
+
readonly bitPreserving?: boolean | undefined;
|
|
802
|
+
/** Execute command on each received file. */
|
|
803
|
+
readonly execOnReception?: string | undefined;
|
|
804
|
+
/** Execute command at end of study. */
|
|
805
|
+
readonly execOnEndOfStudy?: string | undefined;
|
|
806
|
+
/** Timeout for end-of-study detection in seconds (passed to DCMTK as-is). */
|
|
807
|
+
readonly endOfStudyTimeout?: number | undefined;
|
|
808
|
+
/** Rename files at end of study. */
|
|
809
|
+
readonly renameOnEndOfStudy?: boolean | undefined;
|
|
810
|
+
/** Socket timeout in seconds (passed to DCMTK as-is). */
|
|
811
|
+
readonly socketTimeout?: number | undefined;
|
|
812
|
+
/** ACSE timeout in seconds (passed to DCMTK as-is). */
|
|
813
|
+
readonly acseTimeout?: number | undefined;
|
|
814
|
+
/** DIMSE timeout in seconds (passed to DCMTK as-is). */
|
|
815
|
+
readonly dimseTimeout?: number | undefined;
|
|
816
|
+
/** Maximum PDU receive size. */
|
|
817
|
+
readonly maxPdu?: number | undefined;
|
|
818
|
+
/** Filename extension for received files. */
|
|
819
|
+
readonly filenameExtension?: string | undefined;
|
|
820
|
+
/** Timeout for start() to resolve (milliseconds). */
|
|
821
|
+
readonly startTimeoutMs?: number | undefined;
|
|
822
|
+
/** Timeout for graceful drain during stop() (milliseconds). */
|
|
823
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
824
|
+
/** AbortSignal for external cancellation. */
|
|
825
|
+
readonly signal?: AbortSignal | undefined;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Pre-configured option sets for common StoreSCP deployment patterns.
|
|
829
|
+
* Spread a preset into your options to avoid specifying boilerplate.
|
|
830
|
+
*
|
|
831
|
+
* @example
|
|
832
|
+
* ```ts
|
|
833
|
+
* StoreSCP.create({ ...StoreSCPPreset.PRODUCTION, port: 11112, outputDirectory: '/data' });
|
|
834
|
+
* ```
|
|
835
|
+
*/
|
|
836
|
+
declare const StoreSCPPreset: {
|
|
837
|
+
/** Basic storage: unique filenames to avoid collisions. */
|
|
838
|
+
readonly BASIC_STORAGE: {
|
|
839
|
+
readonly uniqueFilenames: true;
|
|
840
|
+
};
|
|
841
|
+
/** Testing: unique filenames, preserving raw transfer syntax. */
|
|
842
|
+
readonly TESTING: {
|
|
843
|
+
readonly uniqueFilenames: true;
|
|
844
|
+
readonly bitPreserving: true;
|
|
845
|
+
};
|
|
846
|
+
/** Production: unique filenames with reasonable timeouts. */
|
|
847
|
+
readonly PRODUCTION: {
|
|
848
|
+
readonly uniqueFilenames: true;
|
|
849
|
+
readonly acseTimeout: 30;
|
|
850
|
+
readonly dimseTimeout: 60;
|
|
851
|
+
};
|
|
852
|
+
};
|
|
853
|
+
/** Names of the available StoreSCP configuration presets. */
|
|
854
|
+
type StoreSCPPresetName = keyof typeof StoreSCPPreset;
|
|
855
|
+
/**
|
|
856
|
+
* DICOM Storage SCP server wrapping the storescp binary.
|
|
857
|
+
*
|
|
858
|
+
* Uses a static `create()` factory because binary resolution is fallible
|
|
859
|
+
* and must complete before the constructor runs.
|
|
860
|
+
*
|
|
861
|
+
* Note: storescp does not print a "listening" message, so `start()` resolves
|
|
862
|
+
* on spawn. If the port is busy, storescp exits immediately and `start()`
|
|
863
|
+
* returns an error via the close handler.
|
|
864
|
+
*
|
|
865
|
+
* Server-specific events are emitted dynamically via the LineParser.
|
|
866
|
+
* Use `onEvent()` for typed listeners on server events.
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```ts
|
|
870
|
+
* const result = StoreSCP.create({ port: 11112, outputDirectory: '/tmp/received' });
|
|
871
|
+
* if (result.ok) {
|
|
872
|
+
* const server = result.value;
|
|
873
|
+
* server.onEvent('STORED_FILE', (data) => console.log('Stored:', data.filePath));
|
|
874
|
+
* const startResult = await server.start();
|
|
875
|
+
* }
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
declare class StoreSCP extends DcmtkProcess {
|
|
879
|
+
private readonly parser;
|
|
880
|
+
private readonly tracker;
|
|
881
|
+
private abortSignal;
|
|
882
|
+
private abortHandler;
|
|
883
|
+
private constructor();
|
|
884
|
+
/** Disposes the server and its parser, preventing listener leaks. */
|
|
885
|
+
[Symbol.dispose](): void;
|
|
886
|
+
/**
|
|
887
|
+
* Registers a typed listener for a storescp-specific event.
|
|
888
|
+
*
|
|
889
|
+
* @param event - The event name from StoreSCPEventMap
|
|
890
|
+
* @param listener - Callback receiving typed event data
|
|
891
|
+
* @returns this for chaining
|
|
892
|
+
*/
|
|
893
|
+
onEvent<K extends keyof StoreSCPEventMap>(event: K, listener: (...args: StoreSCPEventMap[K]) => void): this;
|
|
894
|
+
/**
|
|
895
|
+
* Registers a listener for incoming associations.
|
|
896
|
+
*
|
|
897
|
+
* @param listener - Callback receiving association data
|
|
898
|
+
* @returns this for chaining
|
|
899
|
+
*/
|
|
900
|
+
onAssociationReceived(listener: (...args: StoreSCPEventMap['ASSOCIATION_RECEIVED']) => void): this;
|
|
901
|
+
/**
|
|
902
|
+
* Registers a listener for files being stored to disk.
|
|
903
|
+
*
|
|
904
|
+
* @param listener - Callback receiving storing file data
|
|
905
|
+
* @returns this for chaining
|
|
906
|
+
*/
|
|
907
|
+
onStoringFile(listener: (...args: StoreSCPEventMap['STORING_FILE']) => void): this;
|
|
908
|
+
/**
|
|
909
|
+
* Registers a listener for received files enriched with association context.
|
|
910
|
+
*
|
|
911
|
+
* @param listener - Callback receiving tracked file data
|
|
912
|
+
* @returns this for chaining
|
|
913
|
+
*/
|
|
914
|
+
onFileReceived(listener: (...args: StoreSCPEventMap['FILE_RECEIVED']) => void): this;
|
|
915
|
+
/**
|
|
916
|
+
* Registers a listener for completed associations.
|
|
917
|
+
*
|
|
918
|
+
* @param listener - Callback receiving association summary
|
|
919
|
+
* @returns this for chaining
|
|
920
|
+
*/
|
|
921
|
+
onAssociationComplete(listener: (...args: StoreSCPEventMap['ASSOCIATION_COMPLETE']) => void): this;
|
|
922
|
+
/**
|
|
923
|
+
* Creates a new StoreSCP server instance.
|
|
924
|
+
*
|
|
925
|
+
* @param options - Configuration options for the storescp server
|
|
926
|
+
* @returns A Result containing the server instance or a validation/resolution error
|
|
927
|
+
*/
|
|
928
|
+
static create(options: StoreSCPOptions): Result<StoreSCP>;
|
|
929
|
+
/** Wires the line parser to the process output. */
|
|
930
|
+
private wireParser;
|
|
931
|
+
/** Wires the AssociationTracker to server events. */
|
|
932
|
+
private wireTracker;
|
|
933
|
+
/** Wires an AbortSignal to stop the server. */
|
|
934
|
+
private wireAbortSignal;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* DICOM Print Management SCP server wrapping the dcmprscp binary.
|
|
939
|
+
*
|
|
940
|
+
* Provides a type-safe, event-driven API for the Basic Grayscale Print
|
|
941
|
+
* Management SCP. Uses a static factory pattern because binary resolution
|
|
942
|
+
* and validation must happen before the constructor call.
|
|
943
|
+
*
|
|
944
|
+
* @module servers/DcmprsCP
|
|
945
|
+
*/
|
|
946
|
+
|
|
947
|
+
/** Typed event map for the DcmprsCP server. */
|
|
948
|
+
interface DcmprsCPEventMap {
|
|
949
|
+
DATABASE_READY: [DatabaseReadyData];
|
|
950
|
+
ASSOCIATION_RECEIVED: [PrintAssociationReceivedData];
|
|
951
|
+
ASSOCIATION_ACKNOWLEDGED: [PrintAssociationAcknowledgedData];
|
|
952
|
+
ASSOCIATION_RELEASE: [];
|
|
953
|
+
ASSOCIATION_ABORTED: [];
|
|
954
|
+
CANNOT_START_LISTENER: [PrintCannotStartListenerData];
|
|
955
|
+
CONFIG_ERROR: [ConfigErrorData];
|
|
956
|
+
}
|
|
957
|
+
/** Options for creating a DcmprsCP server instance. */
|
|
958
|
+
interface DcmprsCPOptions {
|
|
959
|
+
/** Path to the dcmpstat configuration file (required). */
|
|
960
|
+
readonly configFile: string;
|
|
961
|
+
/** Printer identifier from the config file (optional, defaults to first printer). */
|
|
962
|
+
readonly printer?: string | undefined;
|
|
963
|
+
/** Enable DIMSE message dumping. */
|
|
964
|
+
readonly dump?: boolean | undefined;
|
|
965
|
+
/** Log level override. */
|
|
966
|
+
readonly logLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | undefined;
|
|
967
|
+
/** Path to a log configuration file. */
|
|
968
|
+
readonly logConfig?: string | undefined;
|
|
969
|
+
/** Timeout for start() to resolve (milliseconds). */
|
|
970
|
+
readonly startTimeoutMs?: number | undefined;
|
|
971
|
+
/** Timeout for graceful drain during stop() (milliseconds). */
|
|
972
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
973
|
+
/** AbortSignal for external cancellation. */
|
|
974
|
+
readonly signal?: AbortSignal | undefined;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* DICOM Print Management SCP server wrapping the dcmprscp binary.
|
|
978
|
+
*
|
|
979
|
+
* Uses a static `create()` factory because binary resolution is fallible
|
|
980
|
+
* and must complete before the constructor runs.
|
|
981
|
+
*
|
|
982
|
+
* Note: dcmprscp does not print a "listening" message. The `start()` method
|
|
983
|
+
* resolves either when the DATABASE_READY event is detected or on spawn.
|
|
984
|
+
*
|
|
985
|
+
* @example
|
|
986
|
+
* ```ts
|
|
987
|
+
* const result = DcmprsCP.create({ configFile: '/etc/dcmpstat.cfg' });
|
|
988
|
+
* if (result.ok) {
|
|
989
|
+
* const server = result.value;
|
|
990
|
+
* server.onEvent('DATABASE_READY', (data) => console.log('DB:', data.directory));
|
|
991
|
+
* const startResult = await server.start();
|
|
992
|
+
* }
|
|
993
|
+
* ```
|
|
994
|
+
*/
|
|
995
|
+
declare class DcmprsCP extends DcmtkProcess {
|
|
996
|
+
private readonly parser;
|
|
997
|
+
private abortSignal;
|
|
998
|
+
private abortHandler;
|
|
999
|
+
private constructor();
|
|
1000
|
+
/**
|
|
1001
|
+
* Registers a typed listener for a dcmprscp-specific event.
|
|
1002
|
+
*
|
|
1003
|
+
* @param event - The event name from DcmprsCPEventMap
|
|
1004
|
+
* @param listener - Callback receiving typed event data
|
|
1005
|
+
* @returns this for chaining
|
|
1006
|
+
*/
|
|
1007
|
+
/** Disposes the server and its parser, preventing listener leaks. */
|
|
1008
|
+
[Symbol.dispose](): void;
|
|
1009
|
+
onEvent<K extends keyof DcmprsCPEventMap>(event: K, listener: (...args: DcmprsCPEventMap[K]) => void): this;
|
|
1010
|
+
/**
|
|
1011
|
+
* Registers a listener for when the database is ready.
|
|
1012
|
+
*
|
|
1013
|
+
* @param listener - Callback receiving database ready data
|
|
1014
|
+
* @returns this for chaining
|
|
1015
|
+
*/
|
|
1016
|
+
onDatabaseReady(listener: (...args: DcmprsCPEventMap['DATABASE_READY']) => void): this;
|
|
1017
|
+
/**
|
|
1018
|
+
* Registers a listener for incoming associations.
|
|
1019
|
+
*
|
|
1020
|
+
* @param listener - Callback receiving association data
|
|
1021
|
+
* @returns this for chaining
|
|
1022
|
+
*/
|
|
1023
|
+
onAssociationReceived(listener: (...args: DcmprsCPEventMap['ASSOCIATION_RECEIVED']) => void): this;
|
|
1024
|
+
/**
|
|
1025
|
+
* Creates a new DcmprsCP server instance.
|
|
1026
|
+
*
|
|
1027
|
+
* @param options - Configuration options for the dcmprscp server
|
|
1028
|
+
* @returns A Result containing the server instance or a validation/resolution error
|
|
1029
|
+
*/
|
|
1030
|
+
static create(options: DcmprsCPOptions): Result<DcmprsCP>;
|
|
1031
|
+
/** Wires the line parser to the process output. */
|
|
1032
|
+
private wireParser;
|
|
1033
|
+
/** Wires an AbortSignal to stop the server. */
|
|
1034
|
+
private wireAbortSignal;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* DICOM Viewer Network Receiver wrapping the dcmpsrcv binary.
|
|
1039
|
+
*
|
|
1040
|
+
* Provides a type-safe, event-driven API for the DICOMscope network
|
|
1041
|
+
* receiver component. Accepts incoming DICOM associations for storage
|
|
1042
|
+
* and C-ECHO verification.
|
|
1043
|
+
*
|
|
1044
|
+
* @module servers/Dcmpsrcv
|
|
1045
|
+
*/
|
|
1046
|
+
|
|
1047
|
+
/** Typed event map for the Dcmpsrcv server. */
|
|
1048
|
+
interface DcmpsrcvEventMap {
|
|
1049
|
+
LISTENING: [ReceiverListeningData];
|
|
1050
|
+
DATABASE_READY: [ReceiverDatabaseReadyData];
|
|
1051
|
+
ASSOCIATION_RECEIVED: [ReceiverAssociationReceivedData];
|
|
1052
|
+
ASSOCIATION_ACKNOWLEDGED: [ReceiverAssociationAcknowledgedData];
|
|
1053
|
+
ECHO_REQUEST: [ReceiverEchoRequestData];
|
|
1054
|
+
C_STORE_REQUEST: [ReceiverCStoreRequestData];
|
|
1055
|
+
FILE_DELETED: [FileDeletedData];
|
|
1056
|
+
ASSOCIATION_RELEASE: [];
|
|
1057
|
+
ASSOCIATION_ABORTED: [];
|
|
1058
|
+
CANNOT_START_LISTENER: [ReceiverCannotStartListenerData];
|
|
1059
|
+
CONFIG_ERROR: [ReceiverConfigErrorData];
|
|
1060
|
+
TERMINATING: [];
|
|
1061
|
+
}
|
|
1062
|
+
/** Options for creating a Dcmpsrcv server instance. */
|
|
1063
|
+
interface DcmpsrcvOptions {
|
|
1064
|
+
/** Path to the dcmpstat configuration file (required). */
|
|
1065
|
+
readonly configFile: string;
|
|
1066
|
+
/** Receiver identifier from the config file (optional, defaults to first receiver). */
|
|
1067
|
+
readonly receiverId?: string | undefined;
|
|
1068
|
+
/** Log level override. */
|
|
1069
|
+
readonly logLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | undefined;
|
|
1070
|
+
/** Path to a log configuration file. */
|
|
1071
|
+
readonly logConfig?: string | undefined;
|
|
1072
|
+
/** Timeout for start() to resolve (milliseconds). */
|
|
1073
|
+
readonly startTimeoutMs?: number | undefined;
|
|
1074
|
+
/** Timeout for graceful drain during stop() (milliseconds). */
|
|
1075
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
1076
|
+
/** AbortSignal for external cancellation. */
|
|
1077
|
+
readonly signal?: AbortSignal | undefined;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* DICOM Viewer Network Receiver wrapping the dcmpsrcv binary.
|
|
1081
|
+
*
|
|
1082
|
+
* Uses a static `create()` factory because binary resolution is fallible
|
|
1083
|
+
* and must complete before the constructor runs.
|
|
1084
|
+
*
|
|
1085
|
+
* The `start()` method resolves when the LISTENING event is detected
|
|
1086
|
+
* (i.e., "Receiver <id> on port <port>").
|
|
1087
|
+
*
|
|
1088
|
+
* @example
|
|
1089
|
+
* ```ts
|
|
1090
|
+
* const result = Dcmpsrcv.create({ configFile: '/etc/dcmpstat.cfg', receiverId: 'RECEIVE_1' });
|
|
1091
|
+
* if (result.ok) {
|
|
1092
|
+
* const server = result.value;
|
|
1093
|
+
* server.onEvent('LISTENING', (data) => console.log(`Listening on port ${data.port}`));
|
|
1094
|
+
* const startResult = await server.start();
|
|
1095
|
+
* }
|
|
1096
|
+
* ```
|
|
1097
|
+
*/
|
|
1098
|
+
declare class Dcmpsrcv extends DcmtkProcess {
|
|
1099
|
+
private readonly parser;
|
|
1100
|
+
private abortSignal;
|
|
1101
|
+
private abortHandler;
|
|
1102
|
+
private constructor();
|
|
1103
|
+
/**
|
|
1104
|
+
* Registers a typed listener for a dcmpsrcv-specific event.
|
|
1105
|
+
*
|
|
1106
|
+
* @param event - The event name from DcmpsrcvEventMap
|
|
1107
|
+
* @param listener - Callback receiving typed event data
|
|
1108
|
+
* @returns this for chaining
|
|
1109
|
+
*/
|
|
1110
|
+
/** Disposes the server and its parser, preventing listener leaks. */
|
|
1111
|
+
[Symbol.dispose](): void;
|
|
1112
|
+
onEvent<K extends keyof DcmpsrcvEventMap>(event: K, listener: (...args: DcmpsrcvEventMap[K]) => void): this;
|
|
1113
|
+
/**
|
|
1114
|
+
* Registers a listener for when the receiver starts listening.
|
|
1115
|
+
*
|
|
1116
|
+
* @param listener - Callback receiving listening data (receiver ID and port)
|
|
1117
|
+
* @returns this for chaining
|
|
1118
|
+
*/
|
|
1119
|
+
onListening(listener: (...args: DcmpsrcvEventMap['LISTENING']) => void): this;
|
|
1120
|
+
/**
|
|
1121
|
+
* Registers a listener for incoming C-STORE requests.
|
|
1122
|
+
*
|
|
1123
|
+
* @param listener - Callback receiving C-STORE request data
|
|
1124
|
+
* @returns this for chaining
|
|
1125
|
+
*/
|
|
1126
|
+
onCStoreRequest(listener: (...args: DcmpsrcvEventMap['C_STORE_REQUEST']) => void): this;
|
|
1127
|
+
/**
|
|
1128
|
+
* Creates a new Dcmpsrcv server instance.
|
|
1129
|
+
*
|
|
1130
|
+
* @param options - Configuration options for the dcmpsrcv server
|
|
1131
|
+
* @returns A Result containing the server instance or a validation/resolution error
|
|
1132
|
+
*/
|
|
1133
|
+
static create(options: DcmpsrcvOptions): Result<Dcmpsrcv>;
|
|
1134
|
+
/** Wires the line parser to the process output. */
|
|
1135
|
+
private wireParser;
|
|
1136
|
+
/** Wires an AbortSignal to stop the server. */
|
|
1137
|
+
private wireAbortSignal;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* DICOM Query/Retrieve SCP server wrapping the dcmqrscp binary.
|
|
1142
|
+
*
|
|
1143
|
+
* Provides a type-safe, event-driven API for the Q/R SCP that supports
|
|
1144
|
+
* C-FIND, C-MOVE, C-GET, and C-STORE operations. Uses a static factory
|
|
1145
|
+
* pattern because binary resolution and validation must happen before
|
|
1146
|
+
* the constructor call.
|
|
1147
|
+
*
|
|
1148
|
+
* @module servers/DcmQRSCP
|
|
1149
|
+
*/
|
|
1150
|
+
|
|
1151
|
+
/** Typed event map for the DcmQRSCP server. */
|
|
1152
|
+
interface DcmQRSCPEventMap {
|
|
1153
|
+
LISTENING: [QRListeningData];
|
|
1154
|
+
ASSOCIATION_RECEIVED: [QRAssociationReceivedData];
|
|
1155
|
+
ASSOCIATION_ACKNOWLEDGED: [QRAssociationAcknowledgedData];
|
|
1156
|
+
C_FIND_REQUEST: [QRCFindRequestData];
|
|
1157
|
+
C_MOVE_REQUEST: [QRCMoveRequestData];
|
|
1158
|
+
C_GET_REQUEST: [QRCGetRequestData];
|
|
1159
|
+
C_STORE_REQUEST: [QRCStoreRequestData];
|
|
1160
|
+
ASSOCIATION_RELEASE: [];
|
|
1161
|
+
ASSOCIATION_ABORTED: [];
|
|
1162
|
+
CANNOT_START_LISTENER: [QRCannotStartListenerData];
|
|
1163
|
+
}
|
|
1164
|
+
/** Options for creating a DcmQRSCP server instance. */
|
|
1165
|
+
interface DcmQRSCPOptions {
|
|
1166
|
+
/** Path to the dcmqrscp configuration file (required). */
|
|
1167
|
+
readonly configFile: string;
|
|
1168
|
+
/** Override port from config (positional arg). */
|
|
1169
|
+
readonly port?: number | undefined;
|
|
1170
|
+
/** Single-process mode (-s flag, recommended on Windows). */
|
|
1171
|
+
readonly singleProcess?: boolean | undefined;
|
|
1172
|
+
/** Check Find responses (-XF). */
|
|
1173
|
+
readonly checkFind?: boolean | undefined;
|
|
1174
|
+
/** Check Move responses (-XM). */
|
|
1175
|
+
readonly checkMove?: boolean | undefined;
|
|
1176
|
+
/** Disable C-GET support (--disable-get). */
|
|
1177
|
+
readonly disableGet?: boolean | undefined;
|
|
1178
|
+
/** Maximum PDU receive size. */
|
|
1179
|
+
readonly maxPdu?: number | undefined;
|
|
1180
|
+
/** ACSE timeout in seconds (passed to DCMTK as-is). */
|
|
1181
|
+
readonly acseTimeout?: number | undefined;
|
|
1182
|
+
/** DIMSE timeout in seconds (passed to DCMTK as-is). */
|
|
1183
|
+
readonly dimseTimeout?: number | undefined;
|
|
1184
|
+
/** Enable verbose mode (default true for event detection). */
|
|
1185
|
+
readonly verbose?: boolean | undefined;
|
|
1186
|
+
/** Timeout for start() to resolve (milliseconds). */
|
|
1187
|
+
readonly startTimeoutMs?: number | undefined;
|
|
1188
|
+
/** Timeout for graceful drain during stop() (milliseconds). */
|
|
1189
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
1190
|
+
/** AbortSignal for external cancellation. */
|
|
1191
|
+
readonly signal?: AbortSignal | undefined;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* DICOM Query/Retrieve SCP server wrapping the dcmqrscp binary.
|
|
1195
|
+
*
|
|
1196
|
+
* Uses a static `create()` factory because binary resolution is fallible
|
|
1197
|
+
* and must complete before the constructor runs.
|
|
1198
|
+
*
|
|
1199
|
+
* @example
|
|
1200
|
+
* ```ts
|
|
1201
|
+
* const result = DcmQRSCP.create({ configFile: '/etc/dcmqrscp.cfg', port: 11112 });
|
|
1202
|
+
* if (result.ok) {
|
|
1203
|
+
* const server = result.value;
|
|
1204
|
+
* server.onEvent('C_FIND_REQUEST', (data) => console.log('Find:', data.raw));
|
|
1205
|
+
* const startResult = await server.start();
|
|
1206
|
+
* }
|
|
1207
|
+
* ```
|
|
1208
|
+
*/
|
|
1209
|
+
declare class DcmQRSCP extends DcmtkProcess {
|
|
1210
|
+
private readonly parser;
|
|
1211
|
+
private abortSignal;
|
|
1212
|
+
private abortHandler;
|
|
1213
|
+
private constructor();
|
|
1214
|
+
/** Disposes the server and its parser, preventing listener leaks. */
|
|
1215
|
+
[Symbol.dispose](): void;
|
|
1216
|
+
/**
|
|
1217
|
+
* Registers a typed listener for a dcmqrscp-specific event.
|
|
1218
|
+
*
|
|
1219
|
+
* @param event - The event name from DcmQRSCPEventMap
|
|
1220
|
+
* @param listener - Callback receiving typed event data
|
|
1221
|
+
* @returns this for chaining
|
|
1222
|
+
*/
|
|
1223
|
+
onEvent<K extends keyof DcmQRSCPEventMap>(event: K, listener: (...args: DcmQRSCPEventMap[K]) => void): this;
|
|
1224
|
+
/**
|
|
1225
|
+
* Registers a listener for incoming C-FIND requests.
|
|
1226
|
+
*
|
|
1227
|
+
* @param listener - Callback receiving C-FIND request data
|
|
1228
|
+
* @returns this for chaining
|
|
1229
|
+
*/
|
|
1230
|
+
onCFindRequest(listener: (...args: DcmQRSCPEventMap['C_FIND_REQUEST']) => void): this;
|
|
1231
|
+
/**
|
|
1232
|
+
* Registers a listener for incoming C-MOVE requests.
|
|
1233
|
+
*
|
|
1234
|
+
* @param listener - Callback receiving C-MOVE request data
|
|
1235
|
+
* @returns this for chaining
|
|
1236
|
+
*/
|
|
1237
|
+
onCMoveRequest(listener: (...args: DcmQRSCPEventMap['C_MOVE_REQUEST']) => void): this;
|
|
1238
|
+
/**
|
|
1239
|
+
* Creates a new DcmQRSCP server instance.
|
|
1240
|
+
*
|
|
1241
|
+
* @param options - Configuration options for the dcmqrscp server
|
|
1242
|
+
* @returns A Result containing the server instance or a validation/resolution error
|
|
1243
|
+
*/
|
|
1244
|
+
static create(options: DcmQRSCPOptions): Result<DcmQRSCP>;
|
|
1245
|
+
/** Wires the line parser to the process output. */
|
|
1246
|
+
private wireParser;
|
|
1247
|
+
/** Wires an AbortSignal to stop the server. */
|
|
1248
|
+
private wireAbortSignal;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* DICOM Worklist Management SCP server wrapping the wlmscpfs binary.
|
|
1253
|
+
*
|
|
1254
|
+
* Provides a type-safe, event-driven API for serving worklist data
|
|
1255
|
+
* from a file-system based database. Uses a static factory pattern
|
|
1256
|
+
* because binary resolution and validation must happen before the
|
|
1257
|
+
* constructor call.
|
|
1258
|
+
*
|
|
1259
|
+
* @module servers/Wlmscpfs
|
|
1260
|
+
*/
|
|
1261
|
+
|
|
1262
|
+
/** Typed event map for the Wlmscpfs server. */
|
|
1263
|
+
interface WlmscpfsEventMap {
|
|
1264
|
+
LISTENING: [WlmListeningData];
|
|
1265
|
+
ASSOCIATION_RECEIVED: [WlmAssociationReceivedData];
|
|
1266
|
+
ASSOCIATION_ACKNOWLEDGED: [WlmAssociationAcknowledgedData];
|
|
1267
|
+
C_FIND_REQUEST: [WlmCFindRequestData];
|
|
1268
|
+
ASSOCIATION_RELEASE: [];
|
|
1269
|
+
ASSOCIATION_ABORTED: [];
|
|
1270
|
+
ECHO_REQUEST: [];
|
|
1271
|
+
CANNOT_START_LISTENER: [WlmCannotStartListenerData];
|
|
1272
|
+
}
|
|
1273
|
+
/** Options for creating a Wlmscpfs server instance. */
|
|
1274
|
+
interface WlmscpfsOptions {
|
|
1275
|
+
/** Port to listen on (required, positional arg). */
|
|
1276
|
+
readonly port: number;
|
|
1277
|
+
/** Worklist data directory (required, -dfp flag). */
|
|
1278
|
+
readonly worklistDirectory: string;
|
|
1279
|
+
/** Enable file rejection (default true). Maps to -efr / -dfr. */
|
|
1280
|
+
readonly enableFileRejection?: boolean | undefined;
|
|
1281
|
+
/** Maximum PDU receive size. */
|
|
1282
|
+
readonly maxPdu?: number | undefined;
|
|
1283
|
+
/** ACSE timeout in seconds (passed to DCMTK as-is). */
|
|
1284
|
+
readonly acseTimeout?: number | undefined;
|
|
1285
|
+
/** DIMSE timeout in seconds (passed to DCMTK as-is). */
|
|
1286
|
+
readonly dimseTimeout?: number | undefined;
|
|
1287
|
+
/** Maximum simultaneous associations. */
|
|
1288
|
+
readonly maxAssociations?: number | undefined;
|
|
1289
|
+
/** Enable verbose mode (default true for event detection). */
|
|
1290
|
+
readonly verbose?: boolean | undefined;
|
|
1291
|
+
/** Timeout for start() to resolve (milliseconds). */
|
|
1292
|
+
readonly startTimeoutMs?: number | undefined;
|
|
1293
|
+
/** Timeout for graceful drain during stop() (milliseconds). */
|
|
1294
|
+
readonly drainTimeoutMs?: number | undefined;
|
|
1295
|
+
/** AbortSignal for external cancellation. */
|
|
1296
|
+
readonly signal?: AbortSignal | undefined;
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* DICOM Worklist Management SCP server wrapping the wlmscpfs binary.
|
|
1300
|
+
*
|
|
1301
|
+
* Uses a static `create()` factory because binary resolution is fallible
|
|
1302
|
+
* and must complete before the constructor runs.
|
|
1303
|
+
*
|
|
1304
|
+
* Note: wlmscpfs does not print a reliable "listening" message in all
|
|
1305
|
+
* DCMTK versions, so `start()` resolves on spawn (like StoreSCP).
|
|
1306
|
+
*
|
|
1307
|
+
* @example
|
|
1308
|
+
* ```ts
|
|
1309
|
+
* const result = Wlmscpfs.create({ port: 2005, worklistDirectory: '/var/worklists' });
|
|
1310
|
+
* if (result.ok) {
|
|
1311
|
+
* const server = result.value;
|
|
1312
|
+
* server.onEvent('C_FIND_REQUEST', (data) => console.log('Find:', data.raw));
|
|
1313
|
+
* const startResult = await server.start();
|
|
1314
|
+
* }
|
|
1315
|
+
* ```
|
|
1316
|
+
*/
|
|
1317
|
+
declare class Wlmscpfs extends DcmtkProcess {
|
|
1318
|
+
private readonly parser;
|
|
1319
|
+
private abortSignal;
|
|
1320
|
+
private abortHandler;
|
|
1321
|
+
private constructor();
|
|
1322
|
+
/** Disposes the server and its parser, preventing listener leaks. */
|
|
1323
|
+
[Symbol.dispose](): void;
|
|
1324
|
+
/**
|
|
1325
|
+
* Registers a typed listener for a wlmscpfs-specific event.
|
|
1326
|
+
*
|
|
1327
|
+
* @param event - The event name from WlmscpfsEventMap
|
|
1328
|
+
* @param listener - Callback receiving typed event data
|
|
1329
|
+
* @returns this for chaining
|
|
1330
|
+
*/
|
|
1331
|
+
onEvent<K extends keyof WlmscpfsEventMap>(event: K, listener: (...args: WlmscpfsEventMap[K]) => void): this;
|
|
1332
|
+
/**
|
|
1333
|
+
* Registers a listener for incoming C-FIND requests.
|
|
1334
|
+
*
|
|
1335
|
+
* @param listener - Callback receiving C-FIND request data
|
|
1336
|
+
* @returns this for chaining
|
|
1337
|
+
*/
|
|
1338
|
+
onCFindRequest(listener: (...args: WlmscpfsEventMap['C_FIND_REQUEST']) => void): this;
|
|
1339
|
+
/**
|
|
1340
|
+
* Registers a listener for when the server starts listening.
|
|
1341
|
+
*
|
|
1342
|
+
* @param listener - Callback receiving listening data (port)
|
|
1343
|
+
* @returns this for chaining
|
|
1344
|
+
*/
|
|
1345
|
+
onListening(listener: (...args: WlmscpfsEventMap['LISTENING']) => void): this;
|
|
1346
|
+
/**
|
|
1347
|
+
* Creates a new Wlmscpfs server instance.
|
|
1348
|
+
*
|
|
1349
|
+
* @param options - Configuration options for the wlmscpfs server
|
|
1350
|
+
* @returns A Result containing the server instance or a validation/resolution error
|
|
1351
|
+
*/
|
|
1352
|
+
static create(options: WlmscpfsOptions): Result<Wlmscpfs>;
|
|
1353
|
+
/** Wires the line parser to the process output. */
|
|
1354
|
+
private wireParser;
|
|
1355
|
+
/** Wires an AbortSignal to stop the server. */
|
|
1356
|
+
private wireAbortSignal;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
/**
|
|
1360
|
+
* Pure state machine tracking DICOM association lifecycle.
|
|
1361
|
+
*
|
|
1362
|
+
* No I/O, no async, no EventEmitter — just state transitions.
|
|
1363
|
+
* Used by Dcmrecv and StoreSCP to correlate files to associations.
|
|
1364
|
+
*
|
|
1365
|
+
* State machine:
|
|
1366
|
+
* ```
|
|
1367
|
+
* IDLE -> [beginAssociation] -> ACTIVE -> [trackFile]* -> [endAssociation] -> IDLE
|
|
1368
|
+
* ```
|
|
1369
|
+
*
|
|
1370
|
+
* This single-slot design is safe because all DCMTK server binaries
|
|
1371
|
+
* (dcmrecv, storescp, etc.) are single-threaded and handle one
|
|
1372
|
+
* association at a time. Concurrent connections queue at the TCP level,
|
|
1373
|
+
* so associations never interleave in the output stream.
|
|
1374
|
+
*
|
|
1375
|
+
* @module servers/AssociationTracker
|
|
1376
|
+
*/
|
|
1377
|
+
/** Context for the currently active association. */
|
|
1378
|
+
interface AssociationContext {
|
|
1379
|
+
readonly associationId: string;
|
|
1380
|
+
readonly callingAE: string;
|
|
1381
|
+
readonly calledAE: string;
|
|
1382
|
+
readonly source: string;
|
|
1383
|
+
readonly startTime: number;
|
|
1384
|
+
readonly files: string[];
|
|
1385
|
+
}
|
|
1386
|
+
/** A file enriched with association context. */
|
|
1387
|
+
interface TrackedFile {
|
|
1388
|
+
readonly filePath: string;
|
|
1389
|
+
readonly associationId: string;
|
|
1390
|
+
readonly callingAE: string;
|
|
1391
|
+
readonly calledAE: string;
|
|
1392
|
+
readonly source: string;
|
|
1393
|
+
}
|
|
1394
|
+
/** Summary emitted when an association completes. */
|
|
1395
|
+
interface AssociationSummary {
|
|
1396
|
+
readonly associationId: string;
|
|
1397
|
+
readonly callingAE: string;
|
|
1398
|
+
readonly calledAE: string;
|
|
1399
|
+
readonly source: string;
|
|
1400
|
+
readonly files: readonly string[];
|
|
1401
|
+
readonly durationMs: number;
|
|
1402
|
+
readonly endReason: 'release' | 'abort';
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Tracks DICOM association lifecycle for file-to-source correlation.
|
|
1406
|
+
*
|
|
1407
|
+
* Maintains a simple IDLE/ACTIVE state machine. While active, all tracked
|
|
1408
|
+
* files are enriched with the current association context. Only one
|
|
1409
|
+
* association can be active at a time — this is safe because DCMTK
|
|
1410
|
+
* servers are single-threaded and process associations sequentially.
|
|
1411
|
+
*
|
|
1412
|
+
* @example
|
|
1413
|
+
* ```ts
|
|
1414
|
+
* const tracker = new AssociationTracker();
|
|
1415
|
+
* const id = tracker.beginAssociation({ callingAE: 'SCU', calledAE: 'SCP', source: 'db' });
|
|
1416
|
+
* const file = tracker.trackFile('/path/to/received.dcm');
|
|
1417
|
+
* const summary = tracker.endAssociation('release');
|
|
1418
|
+
* ```
|
|
1419
|
+
*/
|
|
1420
|
+
declare class AssociationTracker {
|
|
1421
|
+
private association;
|
|
1422
|
+
private counter;
|
|
1423
|
+
/**
|
|
1424
|
+
* Begins a new association, transitioning from IDLE to ACTIVE.
|
|
1425
|
+
*
|
|
1426
|
+
* If an association is already active, it is silently ended (abort)
|
|
1427
|
+
* and the new one begins.
|
|
1428
|
+
*
|
|
1429
|
+
* @param data - Association metadata
|
|
1430
|
+
* @returns The unique association ID
|
|
1431
|
+
*/
|
|
1432
|
+
beginAssociation(data: {
|
|
1433
|
+
readonly callingAE: string;
|
|
1434
|
+
readonly calledAE: string;
|
|
1435
|
+
readonly source: string;
|
|
1436
|
+
}): string;
|
|
1437
|
+
/**
|
|
1438
|
+
* Tracks a file received during the current association.
|
|
1439
|
+
*
|
|
1440
|
+
* If no association is active, returns a TrackedFile with empty context.
|
|
1441
|
+
*
|
|
1442
|
+
* @param filePath - Path to the received file
|
|
1443
|
+
* @returns A TrackedFile enriched with association context
|
|
1444
|
+
*/
|
|
1445
|
+
trackFile(filePath: string): TrackedFile;
|
|
1446
|
+
/**
|
|
1447
|
+
* Ends the current association, transitioning from ACTIVE to IDLE.
|
|
1448
|
+
*
|
|
1449
|
+
* @param reason - Why the association ended
|
|
1450
|
+
* @returns An AssociationSummary, or undefined if no association was active
|
|
1451
|
+
*/
|
|
1452
|
+
endAssociation(reason: 'release' | 'abort'): AssociationSummary | undefined;
|
|
1453
|
+
/** The currently active association context, or undefined. */
|
|
1454
|
+
get current(): AssociationContext | undefined;
|
|
1455
|
+
/** Whether an association is currently active. */
|
|
1456
|
+
get isActive(): boolean;
|
|
1457
|
+
/** Resets the tracker to IDLE, discarding any active association. */
|
|
1458
|
+
reset(): void;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* Pooled DICOM receiver with auto-scaling.
|
|
1463
|
+
*
|
|
1464
|
+
* Manages a pool of long-lived `Dcmrecv` workers behind a TCP proxy,
|
|
1465
|
+
* routing incoming connections to idle workers. Workers are reused
|
|
1466
|
+
* across associations — they are only stopped during scale-down or
|
|
1467
|
+
* shutdown.
|
|
1468
|
+
*
|
|
1469
|
+
* @module servers/DicomReceiver
|
|
1470
|
+
*/
|
|
1471
|
+
|
|
1472
|
+
/** Snapshot of the worker pool state. */
|
|
1473
|
+
interface PoolStatus {
|
|
1474
|
+
/** Number of idle workers ready for connections. */
|
|
1475
|
+
readonly idle: number;
|
|
1476
|
+
/** Number of workers currently handling associations. */
|
|
1477
|
+
readonly busy: number;
|
|
1478
|
+
/** Total number of workers (idle + busy). */
|
|
1479
|
+
readonly total: number;
|
|
1480
|
+
}
|
|
1481
|
+
/** Data emitted with FILE_RECEIVED events. */
|
|
1482
|
+
interface ReceiverFileData {
|
|
1483
|
+
readonly filePath: string;
|
|
1484
|
+
readonly associationId: string;
|
|
1485
|
+
readonly associationDir: string;
|
|
1486
|
+
readonly callingAE: string;
|
|
1487
|
+
readonly calledAE: string;
|
|
1488
|
+
readonly source: string;
|
|
1489
|
+
readonly instance: DicomInstance;
|
|
1490
|
+
}
|
|
1491
|
+
/** Data emitted with ASSOCIATION_COMPLETE events. */
|
|
1492
|
+
interface ReceiverAssociationData {
|
|
1493
|
+
readonly associationId: string;
|
|
1494
|
+
readonly associationDir: string;
|
|
1495
|
+
readonly callingAE: string;
|
|
1496
|
+
readonly calledAE: string;
|
|
1497
|
+
readonly source: string;
|
|
1498
|
+
readonly files: readonly string[];
|
|
1499
|
+
readonly durationMs: number;
|
|
1500
|
+
readonly endReason: 'release' | 'abort';
|
|
1501
|
+
readonly totalBytes: number;
|
|
1502
|
+
readonly bytesPerSecond: number;
|
|
1503
|
+
readonly startAt: number;
|
|
1504
|
+
readonly endAt: number;
|
|
1505
|
+
}
|
|
1506
|
+
/** Data emitted with error events. */
|
|
1507
|
+
interface ReceiverErrorData {
|
|
1508
|
+
readonly error: Error;
|
|
1509
|
+
readonly filePath?: string;
|
|
1510
|
+
readonly associationId?: string;
|
|
1511
|
+
readonly associationDir?: string;
|
|
1512
|
+
readonly callingAE?: string;
|
|
1513
|
+
readonly calledAE?: string;
|
|
1514
|
+
readonly source?: string;
|
|
1515
|
+
}
|
|
1516
|
+
/** Typed event map for DicomReceiver. */
|
|
1517
|
+
interface DicomReceiverEventMap {
|
|
1518
|
+
FILE_RECEIVED: [ReceiverFileData];
|
|
1519
|
+
ASSOCIATION_COMPLETE: [ReceiverAssociationData];
|
|
1520
|
+
error: [ReceiverErrorData];
|
|
1521
|
+
}
|
|
1522
|
+
/** Options for creating a DicomReceiver instance. */
|
|
1523
|
+
interface DicomReceiverOptions {
|
|
1524
|
+
/** External port to listen on (required). */
|
|
1525
|
+
readonly port: number;
|
|
1526
|
+
/** Root directory for association subdirectories (required). */
|
|
1527
|
+
readonly storageDir: string;
|
|
1528
|
+
/** Application Entity Title for workers. */
|
|
1529
|
+
readonly aeTitle?: string | undefined;
|
|
1530
|
+
/** Minimum number of idle workers to maintain. */
|
|
1531
|
+
readonly minPoolSize?: number | undefined;
|
|
1532
|
+
/** Maximum total workers allowed. */
|
|
1533
|
+
readonly maxPoolSize?: number | undefined;
|
|
1534
|
+
/** Timeout for waiting for an idle worker (milliseconds). */
|
|
1535
|
+
readonly connectionTimeoutMs?: number | undefined;
|
|
1536
|
+
/** Path to a dcmrecv association negotiation configuration file. */
|
|
1537
|
+
readonly configFile?: string | undefined;
|
|
1538
|
+
/** Profile name within the configuration file. */
|
|
1539
|
+
readonly configProfile?: string | undefined;
|
|
1540
|
+
/** AbortSignal for external cancellation. */
|
|
1541
|
+
readonly signal?: AbortSignal | undefined;
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* Pooled DICOM receiver with auto-scaling.
|
|
1545
|
+
*
|
|
1546
|
+
* Manages a pool of long-lived `Dcmrecv` workers behind a TCP proxy.
|
|
1547
|
+
* Incoming connections are routed to idle workers. Workers are reused
|
|
1548
|
+
* across associations and only stopped during scale-down or shutdown.
|
|
1549
|
+
*
|
|
1550
|
+
* @example
|
|
1551
|
+
* ```ts
|
|
1552
|
+
* const result = DicomReceiver.create({
|
|
1553
|
+
* port: 4242,
|
|
1554
|
+
* storageDir: '/data/received',
|
|
1555
|
+
* minPoolSize: 2,
|
|
1556
|
+
* maxPoolSize: 8,
|
|
1557
|
+
* });
|
|
1558
|
+
* if (!result.ok) { console.error(result.error.message); return; }
|
|
1559
|
+
* const receiver = result.value;
|
|
1560
|
+
*
|
|
1561
|
+
* receiver.onFileReceived(data => console.log('File:', data.filePath));
|
|
1562
|
+
* receiver.onAssociationComplete(data => console.log('Done:', data.associationDir));
|
|
1563
|
+
*
|
|
1564
|
+
* await receiver.start();
|
|
1565
|
+
* ```
|
|
1566
|
+
*/
|
|
1567
|
+
declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
|
|
1568
|
+
private readonly options;
|
|
1569
|
+
private readonly minPoolSize;
|
|
1570
|
+
private readonly maxPoolSize;
|
|
1571
|
+
private readonly connectionTimeoutMs;
|
|
1572
|
+
private readonly workers;
|
|
1573
|
+
private tcpServer;
|
|
1574
|
+
private associationCounter;
|
|
1575
|
+
private started;
|
|
1576
|
+
private stopping;
|
|
1577
|
+
private abortHandler;
|
|
1578
|
+
private constructor();
|
|
1579
|
+
/**
|
|
1580
|
+
* Creates a new DicomReceiver instance.
|
|
1581
|
+
*
|
|
1582
|
+
* @param options - Configuration options
|
|
1583
|
+
* @returns A Result containing the instance or a validation error
|
|
1584
|
+
*/
|
|
1585
|
+
static create(options: DicomReceiverOptions): Result<DicomReceiver>;
|
|
1586
|
+
/**
|
|
1587
|
+
* Starts the TCP proxy and spawns the initial worker pool.
|
|
1588
|
+
*
|
|
1589
|
+
* @returns A Result indicating success or failure
|
|
1590
|
+
*/
|
|
1591
|
+
start(): Promise<Result<void>>;
|
|
1592
|
+
/**
|
|
1593
|
+
* Stops the TCP proxy and all workers.
|
|
1594
|
+
*/
|
|
1595
|
+
stop(): Promise<void>;
|
|
1596
|
+
/**
|
|
1597
|
+
* Registers a typed listener for a DicomReceiver-specific event.
|
|
1598
|
+
*
|
|
1599
|
+
* @param event - The event name from DicomReceiverEventMap
|
|
1600
|
+
* @param listener - Callback receiving typed event data
|
|
1601
|
+
* @returns this for chaining
|
|
1602
|
+
*/
|
|
1603
|
+
onEvent<K extends keyof DicomReceiverEventMap>(event: K, listener: (...args: DicomReceiverEventMap[K]) => void): this;
|
|
1604
|
+
/**
|
|
1605
|
+
* Registers a listener for received files.
|
|
1606
|
+
*
|
|
1607
|
+
* @param listener - Callback receiving file data
|
|
1608
|
+
* @returns this for chaining
|
|
1609
|
+
*/
|
|
1610
|
+
onFileReceived(listener: (data: ReceiverFileData) => void): this;
|
|
1611
|
+
/**
|
|
1612
|
+
* Registers a listener for completed associations.
|
|
1613
|
+
*
|
|
1614
|
+
* @param listener - Callback receiving association data
|
|
1615
|
+
* @returns this for chaining
|
|
1616
|
+
*/
|
|
1617
|
+
onAssociationComplete(listener: (data: ReceiverAssociationData) => void): this;
|
|
1618
|
+
/** Current pool status. */
|
|
1619
|
+
get poolStatus(): PoolStatus;
|
|
1620
|
+
/** Starts the TCP proxy on the configured port. */
|
|
1621
|
+
private startTcpProxy;
|
|
1622
|
+
/** Closes the TCP proxy server. */
|
|
1623
|
+
private closeTcpProxy;
|
|
1624
|
+
/** Routes an incoming connection to an idle worker. */
|
|
1625
|
+
private handleConnection;
|
|
1626
|
+
/** Finds an idle worker, retrying up to connectionTimeoutMs. */
|
|
1627
|
+
private findIdleWorker;
|
|
1628
|
+
/** Returns the first idle worker, or undefined. */
|
|
1629
|
+
private getIdleWorker;
|
|
1630
|
+
/** Pipes remote socket bidirectionally to the worker's port. */
|
|
1631
|
+
private pipeConnection;
|
|
1632
|
+
/** Spawns `count` new workers and adds them to the pool. */
|
|
1633
|
+
private spawnWorkers;
|
|
1634
|
+
/** Spawns a single Dcmrecv worker with an ephemeral port. */
|
|
1635
|
+
private spawnWorker;
|
|
1636
|
+
/** Stops a single worker: stop process, clean temp dir, remove from pool. */
|
|
1637
|
+
private stopWorker;
|
|
1638
|
+
/** Pre-emptively spawns workers to keep idle count >= minPoolSize. */
|
|
1639
|
+
private replenishPool;
|
|
1640
|
+
/** Stops excess idle workers when idle count > minPoolSize + 2. */
|
|
1641
|
+
private scaleDown;
|
|
1642
|
+
/** Wires FILE_RECEIVED and ASSOCIATION_COMPLETE events on a worker. */
|
|
1643
|
+
private wireWorkerEvents;
|
|
1644
|
+
/** Wires FILE_RECEIVED from dcmrecv worker to handleFileReceived. */
|
|
1645
|
+
private wireFileReceived;
|
|
1646
|
+
/** Moves a received file, opens it as DicomInstance, and emits FILE_RECEIVED. */
|
|
1647
|
+
private handleFileReceived;
|
|
1648
|
+
/** Returns worker to idle pool on association complete, emits summary. */
|
|
1649
|
+
private wireAssociationComplete;
|
|
1650
|
+
/** Wires an AbortSignal to stop the receiver. */
|
|
1651
|
+
private wireAbortSignal;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
export { type AssociationAcknowledgedData, type AssociationCompleteData, type AssociationContext, type AssociationReceivedData, type AssociationSummary, AssociationTracker, type CStoreRequestData, type CannotStartListenerData, type ConfigErrorData, DCMPRSCP_FATAL_EVENTS, DCMPRSCP_PATTERNS, DCMPSRCV_FATAL_EVENTS, DCMPSRCV_PATTERNS, DCMQRSCP_FATAL_EVENTS, DCMQRSCP_PATTERNS, DCMRECV_FATAL_EVENTS, DCMRECV_PATTERNS, type DatabaseReadyData, DcmQRSCP, type DcmQRSCPEventMap, type DcmQRSCPOptions, DcmprsCP, type DcmprsCPEventMap, type DcmprsCPOptions, DcmprscpEvent, type DcmprscpEventValue, Dcmpsrcv, DcmpsrcvEvent, type DcmpsrcvEventMap, type DcmpsrcvEventValue, type DcmpsrcvOptions, DcmqrscpEvent, type DcmqrscpEventValue, Dcmrecv, DcmrecvEvent, type DcmrecvEventMap, type DcmrecvEventValue, type DcmrecvOptions, DcmtkProcess, type DcmtkProcessConfig, type DcmtkProcessEventMap, DicomReceiver, type DicomReceiverEventMap, type DicomReceiverOptions, type EventPattern, type FileDeletedData, type FileReceivedData, FilenameMode, type FilenameModeValue, LineParser, type LineParserEventMap, type MultiLineConfig, type PoolStatus, PreferredTransferSyntax, type PreferredTransferSyntaxValue, type PrintAssociationAcknowledgedData, type PrintAssociationReceivedData, type PrintCannotStartListenerData, ProcessState, type ProcessStateValue, type QRAssociationAcknowledgedData, type QRAssociationReceivedData, type QRCFindRequestData, type QRCGetRequestData, type QRCMoveRequestData, type QRCStoreRequestData, type QRCannotStartListenerData, type QRListeningData, type ReceiverAssociationAcknowledgedData, type ReceiverAssociationData, type ReceiverAssociationReceivedData, type ReceiverCStoreRequestData, type ReceiverCannotStartListenerData, type ReceiverConfigErrorData, type ReceiverDatabaseReadyData, type ReceiverEchoRequestData, type ReceiverErrorData, type ReceiverFileData, type ReceiverListeningData, type RefusingAssociationData, STORESCP_FATAL_EVENTS, STORESCP_PATTERNS, StorageMode, type StorageModeValue, StoreSCP, type StoreSCPEventMap, type StoreSCPOptions, StoreSCPPreset, type StoreSCPPresetName, type StoredFileData, StorescpEvent, type StorescpEventValue, type StoringFileData, type SubdirectoryCreatedData, SubdirectoryMode, type SubdirectoryModeValue, type TrackedFile, WLMSCPFS_FATAL_EVENTS, WLMSCPFS_PATTERNS, type WlmAssociationAcknowledgedData, type WlmAssociationReceivedData, type WlmCFindRequestData, type WlmCannotStartListenerData, type WlmListeningData, Wlmscpfs, WlmscpfsEvent, type WlmscpfsEventMap, type WlmscpfsEventValue, type WlmscpfsOptions };
|