tnz3270-node 0.1.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/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/index.cjs +5489 -0
- package/dist/index.d.cts +1305 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +1305 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5384 -0
- package/package.json +61 -0
- package/src/automation/ati.ts +1057 -0
- package/src/automation/file-transfer.ts +305 -0
- package/src/core/base.ts +59 -0
- package/src/core/buffer.ts +228 -0
- package/src/core/keyboard.ts +396 -0
- package/src/core/parser.ts +422 -0
- package/src/core/screen.ts +110 -0
- package/src/core/telnet.ts +213 -0
- package/src/core/tnz-state.ts +4 -0
- package/src/core/tnz.ts +2403 -0
- package/src/index.ts +113 -0
- package/src/types.ts +348 -0
- package/src/utils/codepage.ts +281 -0
- package/src/utils/session-utils.ts +94 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tnz-node: TypeScript library for IBM mainframe TN3270 terminal automation.
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* @module tnz-node
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type {
|
|
9
|
+
TnzOptions,
|
|
10
|
+
ConnectionState,
|
|
11
|
+
FieldAttribute,
|
|
12
|
+
ScreenSize,
|
|
13
|
+
CodecEntry,
|
|
14
|
+
FileTransferOptions,
|
|
15
|
+
AidCode,
|
|
16
|
+
CommandCode,
|
|
17
|
+
OrderCode,
|
|
18
|
+
ExtendedHighlightValue,
|
|
19
|
+
ColorValue,
|
|
20
|
+
} from './types';
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
AID,
|
|
24
|
+
CMD,
|
|
25
|
+
ORDER,
|
|
26
|
+
TELNET,
|
|
27
|
+
Color,
|
|
28
|
+
ExtendedHighlight,
|
|
29
|
+
FA,
|
|
30
|
+
SF_ID,
|
|
31
|
+
QR_TYPE,
|
|
32
|
+
ATTR_TYPE,
|
|
33
|
+
} from './types';
|
|
34
|
+
|
|
35
|
+
export { sessionPsSize, sessionPs14bit } from './utils/session-utils';
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
getCodec,
|
|
39
|
+
isEncodingSupported,
|
|
40
|
+
registerCodePage,
|
|
41
|
+
translateDataToDisplay,
|
|
42
|
+
getSpecialDisplayChar,
|
|
43
|
+
} from './utils/codepage';
|
|
44
|
+
|
|
45
|
+
// Core
|
|
46
|
+
export { Tnz, TnzError, TnzTerminalError, TnzTransferError, ReadState, bit6 } from './core/tnz';
|
|
47
|
+
|
|
48
|
+
// Automation
|
|
49
|
+
export {
|
|
50
|
+
Ati,
|
|
51
|
+
AtiError,
|
|
52
|
+
CASI,
|
|
53
|
+
EOL,
|
|
54
|
+
FIRST,
|
|
55
|
+
LAST,
|
|
56
|
+
enter,
|
|
57
|
+
clear,
|
|
58
|
+
pa1,
|
|
59
|
+
pa2,
|
|
60
|
+
pa3,
|
|
61
|
+
pf1,
|
|
62
|
+
pf2,
|
|
63
|
+
pf3,
|
|
64
|
+
pf4,
|
|
65
|
+
pf5,
|
|
66
|
+
pf6,
|
|
67
|
+
pf7,
|
|
68
|
+
pf8,
|
|
69
|
+
pf9,
|
|
70
|
+
pf10,
|
|
71
|
+
pf11,
|
|
72
|
+
pf12,
|
|
73
|
+
pf13,
|
|
74
|
+
pf14,
|
|
75
|
+
pf15,
|
|
76
|
+
pf16,
|
|
77
|
+
pf17,
|
|
78
|
+
pf18,
|
|
79
|
+
pf19,
|
|
80
|
+
pf20,
|
|
81
|
+
pf21,
|
|
82
|
+
pf22,
|
|
83
|
+
pf23,
|
|
84
|
+
pf24,
|
|
85
|
+
tab,
|
|
86
|
+
backtab,
|
|
87
|
+
home,
|
|
88
|
+
newline,
|
|
89
|
+
curdown,
|
|
90
|
+
curleft,
|
|
91
|
+
curright,
|
|
92
|
+
curup,
|
|
93
|
+
del,
|
|
94
|
+
eraseeof,
|
|
95
|
+
insert,
|
|
96
|
+
reset,
|
|
97
|
+
attn,
|
|
98
|
+
} from './automation/ati';
|
|
99
|
+
|
|
100
|
+
export type { IacMatch } from './core/telnet';
|
|
101
|
+
export {
|
|
102
|
+
findIacSequences,
|
|
103
|
+
escapeIac,
|
|
104
|
+
unescapeIac,
|
|
105
|
+
buildWill,
|
|
106
|
+
buildWont,
|
|
107
|
+
buildDo,
|
|
108
|
+
buildDont,
|
|
109
|
+
buildSub,
|
|
110
|
+
buildEor,
|
|
111
|
+
buildCommand,
|
|
112
|
+
optionName,
|
|
113
|
+
} from './core/telnet';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types, constants, and interfaces for TN3270 terminal emulation.
|
|
3
|
+
*
|
|
4
|
+
*
|
|
5
|
+
* @module types
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// 3270 AID (Attention Identifier) codes
|
|
10
|
+
// Sent from terminal to host to identify the key pressed.
|
|
11
|
+
// Reference: tnz.py line 192, and 3270 Data Stream Architecture Reference
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
export const AID = {
|
|
15
|
+
NONE: 0x60,
|
|
16
|
+
ENTER: 0x7d,
|
|
17
|
+
PF1: 0xf1,
|
|
18
|
+
PF2: 0xf2,
|
|
19
|
+
PF3: 0xf3,
|
|
20
|
+
PF4: 0xf4,
|
|
21
|
+
PF5: 0xf5,
|
|
22
|
+
PF6: 0xf6,
|
|
23
|
+
PF7: 0xf7,
|
|
24
|
+
PF8: 0xf8,
|
|
25
|
+
PF9: 0xf9,
|
|
26
|
+
PF10: 0x7a,
|
|
27
|
+
PF11: 0x7b,
|
|
28
|
+
PF12: 0x7c,
|
|
29
|
+
PF13: 0xc1,
|
|
30
|
+
PF14: 0xc2,
|
|
31
|
+
PF15: 0xc3,
|
|
32
|
+
PF16: 0xc4,
|
|
33
|
+
PF17: 0xc5,
|
|
34
|
+
PF18: 0xc6,
|
|
35
|
+
PF19: 0xc7,
|
|
36
|
+
PF20: 0xc8,
|
|
37
|
+
PF21: 0xc9,
|
|
38
|
+
PF22: 0x4a,
|
|
39
|
+
PF23: 0x4b,
|
|
40
|
+
PF24: 0x4c,
|
|
41
|
+
PA1: 0x6c,
|
|
42
|
+
PA2: 0x6e,
|
|
43
|
+
PA3: 0x6b,
|
|
44
|
+
CLEAR: 0x6d,
|
|
45
|
+
CLEAR_PARTITION: 0x6a,
|
|
46
|
+
SYSREQ: 0xf0,
|
|
47
|
+
STRUCTURED_FIELD: 0x88,
|
|
48
|
+
READ_PARTITION: 0x61,
|
|
49
|
+
TRIGGER: 0x7e,
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
export type AidCode = (typeof AID)[keyof typeof AID];
|
|
53
|
+
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// 3270 Command codes
|
|
56
|
+
// Sent from host to terminal.
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
export const CMD = {
|
|
60
|
+
WRITE: 0xf1,
|
|
61
|
+
ERASE_WRITE: 0xf5,
|
|
62
|
+
ERASE_WRITE_ALTERNATE: 0x7e,
|
|
63
|
+
READ_BUFFER: 0xf2,
|
|
64
|
+
READ_MODIFIED: 0xf6,
|
|
65
|
+
READ_MODIFIED_ALL: 0x6e,
|
|
66
|
+
ERASE_ALL_UNPROTECTED: 0x6f,
|
|
67
|
+
WRITE_STRUCTURED_FIELD: 0xf3,
|
|
68
|
+
} as const;
|
|
69
|
+
|
|
70
|
+
export type CommandCode = (typeof CMD)[keyof typeof CMD];
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// 3270 Order codes
|
|
74
|
+
// Embedded in data stream to control buffer positioning and field creation.
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
export const ORDER = {
|
|
78
|
+
/** Start Field */
|
|
79
|
+
SF: 0x1d,
|
|
80
|
+
/** Set Buffer Address */
|
|
81
|
+
SBA: 0x11,
|
|
82
|
+
/** Insert Cursor */
|
|
83
|
+
IC: 0x13,
|
|
84
|
+
/** Program Tab */
|
|
85
|
+
PT: 0x05,
|
|
86
|
+
/** Repeat to Address */
|
|
87
|
+
RA: 0x3c,
|
|
88
|
+
/** Erase Unprotected to Address */
|
|
89
|
+
EUA: 0x12,
|
|
90
|
+
/** Set Attribute */
|
|
91
|
+
SA: 0x28,
|
|
92
|
+
/** Start Field Extended */
|
|
93
|
+
SFE: 0x29,
|
|
94
|
+
/** Modify Field */
|
|
95
|
+
MF: 0x2c,
|
|
96
|
+
/** Graphic Escape */
|
|
97
|
+
GE: 0x08,
|
|
98
|
+
} as const;
|
|
99
|
+
|
|
100
|
+
export type OrderCode = (typeof ORDER)[keyof typeof ORDER];
|
|
101
|
+
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// Telnet protocol constants
|
|
104
|
+
// Reference: RFC 854, RFC 855, RFC 1576 (TN3270), RFC 2355 (TN3270E)
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
export const TELNET = {
|
|
108
|
+
// Telnet commands
|
|
109
|
+
IAC: 0xff,
|
|
110
|
+
DONT: 0xfe,
|
|
111
|
+
DO: 0xfd,
|
|
112
|
+
WONT: 0xfc,
|
|
113
|
+
WILL: 0xfb,
|
|
114
|
+
SB: 0xfa,
|
|
115
|
+
GA: 0xf9,
|
|
116
|
+
EL: 0xf8,
|
|
117
|
+
EC: 0xf7,
|
|
118
|
+
AYT: 0xf6,
|
|
119
|
+
AO: 0xf5,
|
|
120
|
+
IP: 0xf4,
|
|
121
|
+
BREAK: 0xf3,
|
|
122
|
+
NOP: 0xf1,
|
|
123
|
+
SE: 0xf0,
|
|
124
|
+
EOR: 0xef,
|
|
125
|
+
|
|
126
|
+
// Telnet options
|
|
127
|
+
OPT_BINARY: 0x00,
|
|
128
|
+
OPT_TERMINAL_TYPE: 0x18,
|
|
129
|
+
OPT_EOR: 0x19,
|
|
130
|
+
OPT_TN3270E: 0x28,
|
|
131
|
+
OPT_START_TLS: 0x2e,
|
|
132
|
+
|
|
133
|
+
// Terminal-type subnegotiation
|
|
134
|
+
TERMINAL_TYPE_IS: 0x00,
|
|
135
|
+
TERMINAL_TYPE_SEND: 0x01,
|
|
136
|
+
|
|
137
|
+
// TN3270E subnegotiation
|
|
138
|
+
TN3270E_SEND: 0x09,
|
|
139
|
+
TN3270E_DEVICE_TYPE: 0x02,
|
|
140
|
+
TN3270E_IS: 0x04,
|
|
141
|
+
TN3270E_REQUEST: 0x07,
|
|
142
|
+
TN3270E_FUNCTIONS: 0x03,
|
|
143
|
+
TN3270E_RESPONSES: 0x02,
|
|
144
|
+
|
|
145
|
+
// START_TLS subnegotiation
|
|
146
|
+
START_TLS_FOLLOWS: 0x01,
|
|
147
|
+
} as const;
|
|
148
|
+
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
// 3270 Extended Attribute types
|
|
151
|
+
// Used in SA (Set Attribute), SFE (Start Field Extended), MF (Modify Field)
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
export const ATTR_TYPE = {
|
|
155
|
+
ALL: 0x00,
|
|
156
|
+
FIELD_ATTRIBUTE: 0xc0,
|
|
157
|
+
EXTENDED_HIGHLIGHTING: 0x41,
|
|
158
|
+
FOREGROUND_COLOR: 0x42,
|
|
159
|
+
BACKGROUND_COLOR: 0x43,
|
|
160
|
+
CHARACTER_SET: 0x43,
|
|
161
|
+
} as const;
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Extended Highlighting values
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
export const ExtendedHighlight = {
|
|
168
|
+
DEFAULT: 0x00,
|
|
169
|
+
NORMAL: 0xf0,
|
|
170
|
+
BLINK: 0xf1,
|
|
171
|
+
REVERSE_VIDEO: 0xf2,
|
|
172
|
+
UNDERSCORE: 0xf4,
|
|
173
|
+
INTENSIFY: 0xf8,
|
|
174
|
+
} as const;
|
|
175
|
+
|
|
176
|
+
export type ExtendedHighlightValue =
|
|
177
|
+
(typeof ExtendedHighlight)[keyof typeof ExtendedHighlight];
|
|
178
|
+
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// 3270 Color values
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
export const Color = {
|
|
184
|
+
DEFAULT: 0x00,
|
|
185
|
+
NEUTRAL_BLACK: 0xf0,
|
|
186
|
+
BLUE: 0xf1,
|
|
187
|
+
RED: 0xf2,
|
|
188
|
+
PINK: 0xf3,
|
|
189
|
+
GREEN: 0xf4,
|
|
190
|
+
TURQUOISE: 0xf5,
|
|
191
|
+
YELLOW: 0xf6,
|
|
192
|
+
NEUTRAL_WHITE: 0xf7,
|
|
193
|
+
} as const;
|
|
194
|
+
|
|
195
|
+
export type ColorValue = (typeof Color)[keyof typeof Color];
|
|
196
|
+
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// Field attribute bit flags
|
|
199
|
+
// Reference: 3270 Data Stream Architecture, Chapter 4
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
|
|
202
|
+
export const FA = {
|
|
203
|
+
/** Protected field */
|
|
204
|
+
PROTECTED: 0x20,
|
|
205
|
+
/** Numeric-only field */
|
|
206
|
+
NUMERIC: 0x10,
|
|
207
|
+
/** Modified Data Tag */
|
|
208
|
+
MDT: 0x01,
|
|
209
|
+
|
|
210
|
+
// Display/intensity combinations (bits 3-4)
|
|
211
|
+
DISPLAY_NOT_PEN: 0x00,
|
|
212
|
+
DISPLAY_PEN: 0x04,
|
|
213
|
+
INTENSIFIED_PEN: 0x08,
|
|
214
|
+
NON_DISPLAY: 0x0c,
|
|
215
|
+
} as const;
|
|
216
|
+
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// Structured Field identifiers
|
|
219
|
+
// Reference: tnz.py query reply and WSF processing
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
|
|
222
|
+
export const SF_ID = {
|
|
223
|
+
READ_PARTITION: 0x01,
|
|
224
|
+
QUERY_REPLY: 0x81,
|
|
225
|
+
DDM: 0xd0,
|
|
226
|
+
} as const;
|
|
227
|
+
|
|
228
|
+
// Query Reply types
|
|
229
|
+
export const QR_TYPE = {
|
|
230
|
+
USABLE_AREA: 0x81,
|
|
231
|
+
HIGHLIGHT: 0x87,
|
|
232
|
+
COLOR: 0x86,
|
|
233
|
+
REPLY_MODES: 0x88,
|
|
234
|
+
IMPLICIT_PARTITION: 0xa6,
|
|
235
|
+
CHARACTER_SETS: 0x85,
|
|
236
|
+
DDM: 0x95,
|
|
237
|
+
RPQ_NAMES: 0xa1,
|
|
238
|
+
} as const;
|
|
239
|
+
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// Interfaces
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
|
|
244
|
+
/** Options for creating a Tnz connection. */
|
|
245
|
+
export interface TnzOptions {
|
|
246
|
+
/** Use TLS/SSL for the connection (default: false) */
|
|
247
|
+
secure?: boolean;
|
|
248
|
+
/** Verify the server certificate (default: true) */
|
|
249
|
+
verifyCert?: boolean;
|
|
250
|
+
/** EBCDIC encoding to use (default: 'cp037') */
|
|
251
|
+
encoding?: string;
|
|
252
|
+
/** Terminal type string sent during negotiation */
|
|
253
|
+
terminalType?: string;
|
|
254
|
+
/** Enable TN3270E protocol negotiation */
|
|
255
|
+
useTn3270e?: boolean;
|
|
256
|
+
/** Logical unit name for TN3270E */
|
|
257
|
+
luName?: string;
|
|
258
|
+
/** Alternate screen rows */
|
|
259
|
+
amaxRow?: number;
|
|
260
|
+
/** Alternate screen columns */
|
|
261
|
+
amaxCol?: number;
|
|
262
|
+
/** Maximum TLS security level */
|
|
263
|
+
secLevel?: number;
|
|
264
|
+
/** Minimum TLS version */
|
|
265
|
+
sslMinimumTls?: string;
|
|
266
|
+
/** SSL verification mode */
|
|
267
|
+
sslVerify?: string;
|
|
268
|
+
/** Optional callback fired when the screen is updated by the host. */
|
|
269
|
+
onScreenUpdate?: () => void;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Snapshot of connection security state. */
|
|
273
|
+
export interface ConnectionState {
|
|
274
|
+
/** Whether the connection uses TLS */
|
|
275
|
+
secure: boolean;
|
|
276
|
+
/** Whether the server certificate was verified as trusted */
|
|
277
|
+
certVerified: boolean;
|
|
278
|
+
/** Whether the server hostname was verified */
|
|
279
|
+
hostVerified: boolean;
|
|
280
|
+
/** Whether 3270 data stream mode is active (vs NVT) */
|
|
281
|
+
tn3270: boolean;
|
|
282
|
+
/** Whether TN3270E protocol is in use */
|
|
283
|
+
tn3270e: boolean;
|
|
284
|
+
/** Whether STARTTLS upgrade completed */
|
|
285
|
+
startTlsCompleted: boolean;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Describes a field on the 3270 screen. */
|
|
289
|
+
export interface FieldAttribute {
|
|
290
|
+
/** Buffer address of the field attribute byte */
|
|
291
|
+
address: number;
|
|
292
|
+
/** Raw attribute byte value */
|
|
293
|
+
attribute: number;
|
|
294
|
+
/** Whether the field is protected from input */
|
|
295
|
+
isProtected: boolean;
|
|
296
|
+
/** Whether the field accepts only numeric input */
|
|
297
|
+
isNumeric: boolean;
|
|
298
|
+
/** Whether the field has been modified */
|
|
299
|
+
isModified: boolean;
|
|
300
|
+
/** Whether the field is visible */
|
|
301
|
+
isDisplay: boolean;
|
|
302
|
+
/** Whether the field is intensified (bright) */
|
|
303
|
+
isIntensified: boolean;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Session presentation space size (rows x columns). */
|
|
307
|
+
export interface ScreenSize {
|
|
308
|
+
rows: number;
|
|
309
|
+
cols: number;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Codec entry for EBCDIC encoding/decoding.
|
|
314
|
+
* Maps an EBCDIC code page to encode/decode functions.
|
|
315
|
+
*/
|
|
316
|
+
export interface CodecEntry {
|
|
317
|
+
/** Code page name (e.g. 'cp037') */
|
|
318
|
+
name: string;
|
|
319
|
+
/** Numeric code page ID extracted from name */
|
|
320
|
+
codePageNumber: number;
|
|
321
|
+
/** Encode Unicode string to EBCDIC bytes */
|
|
322
|
+
encode: (str: string) => Buffer;
|
|
323
|
+
/** Decode EBCDIC bytes to Unicode string */
|
|
324
|
+
decode: (buf: Buffer) => string;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* DDM (Distributed Data Management) file transfer options.
|
|
329
|
+
* Used by IND$FILE GET/PUT operations.
|
|
330
|
+
*/
|
|
331
|
+
export interface FileTransferOptions {
|
|
332
|
+
/** Transfer mode */
|
|
333
|
+
mode?: 'ascii' | 'binary';
|
|
334
|
+
/** Record format */
|
|
335
|
+
recfm?: 'F' | 'V' | 'U';
|
|
336
|
+
/** Logical record length */
|
|
337
|
+
lrecl?: number;
|
|
338
|
+
/** Block size */
|
|
339
|
+
blksize?: number;
|
|
340
|
+
/** Append to existing file on download */
|
|
341
|
+
append?: boolean;
|
|
342
|
+
/** Space allocation for upload */
|
|
343
|
+
space?: {
|
|
344
|
+
primary: number;
|
|
345
|
+
secondary: number;
|
|
346
|
+
unit: 'tracks' | 'cylinders' | 'avblock';
|
|
347
|
+
};
|
|
348
|
+
}
|