@zpl-toolchain/print 0.1.2
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/dist/browser.d.ts +66 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +194 -0
- package/dist/browser.js.map +1 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +647 -0
- package/dist/index.js.map +1 -0
- package/dist/proxy.d.ts +57 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +404 -0
- package/dist/proxy.js.map +1 -0
- package/dist/status.d.ts +14 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +108 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +79 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
import { PrintError } from "./types.js";
|
|
3
|
+
import { parseHostStatus } from "./status.js";
|
|
4
|
+
export { parseHostStatus } from "./status.js";
|
|
5
|
+
export { PrintError, } from "./types.js";
|
|
6
|
+
// ─── Defaults ────────────────────────────────────────────────────────────────
|
|
7
|
+
const DEFAULT_PORT = 9100;
|
|
8
|
+
const DEFAULT_TIMEOUT = 5_000;
|
|
9
|
+
const DEFAULT_MAX_RETRIES = 2;
|
|
10
|
+
const DEFAULT_RETRY_DELAY = 500;
|
|
11
|
+
// ─── Error classification ────────────────────────────────────────────────────
|
|
12
|
+
function classifyError(err) {
|
|
13
|
+
switch (err.code) {
|
|
14
|
+
case "ECONNREFUSED":
|
|
15
|
+
return "CONNECTION_REFUSED";
|
|
16
|
+
case "ETIMEDOUT":
|
|
17
|
+
return "TIMEOUT";
|
|
18
|
+
case "ENOTFOUND":
|
|
19
|
+
return "HOST_NOT_FOUND";
|
|
20
|
+
case "EPIPE":
|
|
21
|
+
return "BROKEN_PIPE";
|
|
22
|
+
case "ECONNRESET":
|
|
23
|
+
return "CONNECTION_RESET";
|
|
24
|
+
default:
|
|
25
|
+
return "UNKNOWN";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function wrapError(err) {
|
|
29
|
+
if (err instanceof PrintError)
|
|
30
|
+
return err;
|
|
31
|
+
const nodeErr = err;
|
|
32
|
+
const code = classifyError(nodeErr);
|
|
33
|
+
const msg = nodeErr.message ?? String(err);
|
|
34
|
+
return new PrintError(msg, code, err);
|
|
35
|
+
}
|
|
36
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
37
|
+
function resolveConfig(cfg) {
|
|
38
|
+
if (!cfg.host || cfg.host.trim().length === 0) {
|
|
39
|
+
throw new PrintError("host is required", "UNKNOWN");
|
|
40
|
+
}
|
|
41
|
+
const port = cfg.port ?? DEFAULT_PORT;
|
|
42
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
43
|
+
throw new PrintError(`Invalid port: ${port} (must be 1–65535)`, "UNKNOWN");
|
|
44
|
+
}
|
|
45
|
+
const timeout = cfg.timeout ?? DEFAULT_TIMEOUT;
|
|
46
|
+
if (typeof timeout !== "number" || timeout < 0) {
|
|
47
|
+
throw new PrintError(`Invalid timeout: ${timeout}`, "UNKNOWN");
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
host: cfg.host,
|
|
51
|
+
port,
|
|
52
|
+
timeout,
|
|
53
|
+
maxRetries: cfg.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
54
|
+
retryDelay: cfg.retryDelay ?? DEFAULT_RETRY_DELAY,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Sleep for `ms` milliseconds. */
|
|
58
|
+
function sleep(ms) {
|
|
59
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
60
|
+
}
|
|
61
|
+
// ─── Low-level TCP helpers ───────────────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Open a TCP socket, write `data`, and close. Returns bytes written & timing.
|
|
64
|
+
*/
|
|
65
|
+
function tcpSend(host, port, data, timeout) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const start = performance.now();
|
|
68
|
+
const buf = Buffer.from(data, "utf-8");
|
|
69
|
+
let settled = false;
|
|
70
|
+
const fail = (err) => {
|
|
71
|
+
if (settled)
|
|
72
|
+
return;
|
|
73
|
+
settled = true;
|
|
74
|
+
socket.destroy();
|
|
75
|
+
reject(err);
|
|
76
|
+
};
|
|
77
|
+
const succeed = (result) => {
|
|
78
|
+
if (settled)
|
|
79
|
+
return;
|
|
80
|
+
settled = true;
|
|
81
|
+
resolve(result);
|
|
82
|
+
};
|
|
83
|
+
const socket = net.createConnection({ host, port }, () => {
|
|
84
|
+
socket.setNoDelay(true);
|
|
85
|
+
socket.write(buf, (writeErr) => {
|
|
86
|
+
if (writeErr) {
|
|
87
|
+
fail(wrapError(writeErr));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
socket.end(() => {
|
|
91
|
+
succeed({
|
|
92
|
+
success: true,
|
|
93
|
+
bytesWritten: buf.length,
|
|
94
|
+
duration: Math.round(performance.now() - start),
|
|
95
|
+
});
|
|
96
|
+
// Force-close after graceful FIN — ZPL printers won't send FIN back,
|
|
97
|
+
// which would leave the socket in FIN_WAIT_2 indefinitely.
|
|
98
|
+
setTimeout(() => {
|
|
99
|
+
if (!socket.destroyed)
|
|
100
|
+
socket.destroy();
|
|
101
|
+
}, 1000).unref();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
socket.setTimeout(timeout);
|
|
106
|
+
socket.on("timeout", () => {
|
|
107
|
+
fail(new PrintError(`Connection to ${host}:${port} timed out after ${timeout}ms`, "TIMEOUT"));
|
|
108
|
+
});
|
|
109
|
+
socket.on("error", (err) => fail(wrapError(err)));
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Open a TCP socket, write `command`, read the response until the socket is
|
|
114
|
+
* idle for a short period, then close and return the response.
|
|
115
|
+
*
|
|
116
|
+
* Exported so that `proxy.ts` can re-use it instead of duplicating the logic.
|
|
117
|
+
*/
|
|
118
|
+
export function tcpQuery(host, port, command, timeout) {
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
const chunks = [];
|
|
121
|
+
let idleTimer;
|
|
122
|
+
let settled = false;
|
|
123
|
+
const finish = (value) => {
|
|
124
|
+
if (settled)
|
|
125
|
+
return;
|
|
126
|
+
settled = true;
|
|
127
|
+
if (idleTimer)
|
|
128
|
+
clearTimeout(idleTimer);
|
|
129
|
+
socket.destroy();
|
|
130
|
+
resolve(value);
|
|
131
|
+
};
|
|
132
|
+
const fail = (err) => {
|
|
133
|
+
if (settled)
|
|
134
|
+
return;
|
|
135
|
+
settled = true;
|
|
136
|
+
if (idleTimer)
|
|
137
|
+
clearTimeout(idleTimer);
|
|
138
|
+
socket.destroy();
|
|
139
|
+
reject(err);
|
|
140
|
+
};
|
|
141
|
+
const socket = net.createConnection({ host, port }, () => {
|
|
142
|
+
socket.write(command, "utf-8");
|
|
143
|
+
});
|
|
144
|
+
socket.setTimeout(timeout);
|
|
145
|
+
socket.on("data", (chunk) => {
|
|
146
|
+
chunks.push(chunk);
|
|
147
|
+
// Reset idle timer — wait 250ms after last data before closing.
|
|
148
|
+
if (idleTimer)
|
|
149
|
+
clearTimeout(idleTimer);
|
|
150
|
+
idleTimer = setTimeout(() => {
|
|
151
|
+
socket.end();
|
|
152
|
+
}, 250);
|
|
153
|
+
});
|
|
154
|
+
socket.on("end", () => {
|
|
155
|
+
finish(Buffer.concat(chunks).toString("utf-8"));
|
|
156
|
+
});
|
|
157
|
+
socket.on("timeout", () => {
|
|
158
|
+
// If we have partial data, return it rather than failing.
|
|
159
|
+
if (chunks.length > 0) {
|
|
160
|
+
finish(Buffer.concat(chunks).toString("utf-8"));
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
fail(new PrintError(`Query to ${host}:${port} timed out after ${timeout}ms`, "TIMEOUT"));
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
socket.on("error", (err) => fail(wrapError(err)));
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
// ─── One-shot print function ─────────────────────────────────────────────────
|
|
170
|
+
/**
|
|
171
|
+
* Send ZPL to a printer and return the result.
|
|
172
|
+
*
|
|
173
|
+
* Automatically retries on transient network errors with exponential backoff.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import { print } from "@zpl-toolchain/print";
|
|
178
|
+
*
|
|
179
|
+
* const result = await print("^XA^FO50,50^A0N,50,50^FDHello^FS^XZ", {
|
|
180
|
+
* host: "192.168.1.100",
|
|
181
|
+
* });
|
|
182
|
+
* console.log(result); // { success: true, bytesWritten: 44, duration: 12 }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
export async function print(zpl, config) {
|
|
186
|
+
const cfg = resolveConfig(config);
|
|
187
|
+
let lastError;
|
|
188
|
+
for (let attempt = 0; attempt <= cfg.maxRetries; attempt++) {
|
|
189
|
+
try {
|
|
190
|
+
return await tcpSend(cfg.host, cfg.port, zpl, cfg.timeout);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
lastError = wrapError(err);
|
|
194
|
+
// Only retry on transient errors.
|
|
195
|
+
const retryable = [
|
|
196
|
+
"TIMEOUT",
|
|
197
|
+
"CONNECTION_RESET",
|
|
198
|
+
"BROKEN_PIPE",
|
|
199
|
+
];
|
|
200
|
+
if (!retryable.includes(lastError.code))
|
|
201
|
+
throw lastError;
|
|
202
|
+
if (attempt < cfg.maxRetries) {
|
|
203
|
+
const delay = cfg.retryDelay * Math.pow(2, attempt);
|
|
204
|
+
await sleep(delay);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
throw lastError;
|
|
209
|
+
}
|
|
210
|
+
// ─── Persistent connection (TcpPrinter) ─────────────────────────────────────
|
|
211
|
+
/**
|
|
212
|
+
* A persistent TCP connection to a ZPL printer.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* import { createPrinter } from "@zpl-toolchain/print";
|
|
217
|
+
*
|
|
218
|
+
* const printer = createPrinter({ host: "192.168.1.100" });
|
|
219
|
+
* await printer.print("^XA^FO50,50^A0N,50,50^FDHello^FS^XZ");
|
|
220
|
+
* const status = await printer.getStatus();
|
|
221
|
+
* console.log(status.ready);
|
|
222
|
+
* await printer.close();
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
export class TcpPrinter {
|
|
226
|
+
config;
|
|
227
|
+
socket = null;
|
|
228
|
+
connecting = null;
|
|
229
|
+
closed = false;
|
|
230
|
+
writeQueue = Promise.resolve();
|
|
231
|
+
constructor(config) {
|
|
232
|
+
this.config = resolveConfig(config);
|
|
233
|
+
}
|
|
234
|
+
// ── Internal helpers ───────────────────────────────────────────────────
|
|
235
|
+
/** Ensure a live connection exists, creating one if needed. */
|
|
236
|
+
async ensureConnected() {
|
|
237
|
+
if (this.closed) {
|
|
238
|
+
throw new PrintError("Printer connection has been closed", "UNKNOWN");
|
|
239
|
+
}
|
|
240
|
+
if (this.socket && !this.socket.destroyed) {
|
|
241
|
+
return this.socket;
|
|
242
|
+
}
|
|
243
|
+
if (this.connecting) {
|
|
244
|
+
await this.connecting;
|
|
245
|
+
return this.socket;
|
|
246
|
+
}
|
|
247
|
+
this.connecting = new Promise((resolve, reject) => {
|
|
248
|
+
const sock = net.createConnection({ host: this.config.host, port: this.config.port }, () => {
|
|
249
|
+
sock.setNoDelay(true);
|
|
250
|
+
sock.setKeepAlive(true, 60_000);
|
|
251
|
+
// Disable idle timeout — it was only needed for the connection phase.
|
|
252
|
+
// TCP keepalive (above) handles liveness detection for persistent connections.
|
|
253
|
+
sock.setTimeout(0);
|
|
254
|
+
sock.removeAllListeners("timeout");
|
|
255
|
+
sock.removeAllListeners("error");
|
|
256
|
+
sock.on("error", () => { this.socket = null; });
|
|
257
|
+
sock.on("close", () => { this.socket = null; });
|
|
258
|
+
this.socket = sock;
|
|
259
|
+
this.connecting = null;
|
|
260
|
+
resolve();
|
|
261
|
+
});
|
|
262
|
+
sock.setTimeout(this.config.timeout);
|
|
263
|
+
sock.on("timeout", () => {
|
|
264
|
+
sock.destroy();
|
|
265
|
+
this.socket = null;
|
|
266
|
+
this.connecting = null;
|
|
267
|
+
reject(new PrintError(`Connection to ${this.config.host}:${this.config.port} timed out`, "TIMEOUT"));
|
|
268
|
+
});
|
|
269
|
+
sock.on("error", (err) => {
|
|
270
|
+
this.socket = null;
|
|
271
|
+
this.connecting = null;
|
|
272
|
+
reject(wrapError(err));
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
await this.connecting;
|
|
276
|
+
return this.socket;
|
|
277
|
+
}
|
|
278
|
+
// ── Public API ─────────────────────────────────────────────────────────
|
|
279
|
+
/**
|
|
280
|
+
* Send ZPL to the printer over the persistent connection.
|
|
281
|
+
*
|
|
282
|
+
* Falls back to a fresh connection if the existing one is broken.
|
|
283
|
+
*/
|
|
284
|
+
print(zpl) {
|
|
285
|
+
const job = this.writeQueue.then(async () => {
|
|
286
|
+
const start = performance.now();
|
|
287
|
+
const buf = Buffer.from(zpl, "utf-8");
|
|
288
|
+
const sock = await this.ensureConnected();
|
|
289
|
+
return new Promise((resolve, reject) => {
|
|
290
|
+
sock.write(buf, (err) => {
|
|
291
|
+
if (err) {
|
|
292
|
+
this.socket = null;
|
|
293
|
+
reject(wrapError(err));
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
resolve({
|
|
297
|
+
success: true,
|
|
298
|
+
bytesWritten: buf.length,
|
|
299
|
+
duration: Math.round(performance.now() - start),
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
// Chain onto writeQueue so next print waits for this one.
|
|
305
|
+
// Eat errors in the queue chain — callers get their own rejection.
|
|
306
|
+
this.writeQueue = job.then(() => { }, () => { });
|
|
307
|
+
return job;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Query the printer's host status (~HS).
|
|
311
|
+
*
|
|
312
|
+
* Sends the `~HS` command and parses the response into a
|
|
313
|
+
* {@link PrinterStatus} object.
|
|
314
|
+
*
|
|
315
|
+
* **Note:** This opens a separate short-lived TCP connection for the query
|
|
316
|
+
* rather than using the persistent connection, because the ~HS response
|
|
317
|
+
* needs an idle-timeout-based read strategy that would interfere with the
|
|
318
|
+
* persistent socket's event handlers.
|
|
319
|
+
*/
|
|
320
|
+
async getStatus() {
|
|
321
|
+
const raw = await tcpQuery(this.config.host, this.config.port, "~HS", this.config.timeout);
|
|
322
|
+
return parseHostStatus(raw);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Send an arbitrary command and return the raw response string.
|
|
326
|
+
*
|
|
327
|
+
* Useful for querying ~HI (Host Identification), ~HM (Host Memory), etc.
|
|
328
|
+
*
|
|
329
|
+
* **Note:** This opens a separate short-lived TCP connection for each query
|
|
330
|
+
* rather than using the persistent connection, because reading a response
|
|
331
|
+
* requires an idle-timeout strategy that would interfere with the
|
|
332
|
+
* persistent socket's event handlers.
|
|
333
|
+
*/
|
|
334
|
+
async query(command) {
|
|
335
|
+
return tcpQuery(this.config.host, this.config.port, command, this.config.timeout);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Check whether the printer is reachable by attempting a TCP connection.
|
|
339
|
+
* Returns `true` if the connection succeeds, `false` otherwise.
|
|
340
|
+
*/
|
|
341
|
+
async isReachable() {
|
|
342
|
+
return new Promise((resolve) => {
|
|
343
|
+
let settled = false;
|
|
344
|
+
const done = (value) => {
|
|
345
|
+
if (settled)
|
|
346
|
+
return;
|
|
347
|
+
settled = true;
|
|
348
|
+
resolve(value);
|
|
349
|
+
};
|
|
350
|
+
const sock = net.createConnection({ host: this.config.host, port: this.config.port }, () => {
|
|
351
|
+
sock.end();
|
|
352
|
+
// Force-close after graceful FIN — printers won't send FIN back.
|
|
353
|
+
setTimeout(() => { if (!sock.destroyed)
|
|
354
|
+
sock.destroy(); }, 1000).unref();
|
|
355
|
+
done(true);
|
|
356
|
+
});
|
|
357
|
+
sock.setTimeout(this.config.timeout);
|
|
358
|
+
sock.on("timeout", () => {
|
|
359
|
+
sock.destroy();
|
|
360
|
+
done(false);
|
|
361
|
+
});
|
|
362
|
+
sock.on("error", () => {
|
|
363
|
+
sock.destroy();
|
|
364
|
+
done(false);
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Send multiple labels sequentially over the persistent connection.
|
|
370
|
+
*
|
|
371
|
+
* @param labels - Array of ZPL strings, one per label.
|
|
372
|
+
* @param opts - Optional batch options (e.g., status polling interval).
|
|
373
|
+
* @param onProgress - Optional callback after each label.
|
|
374
|
+
* Return `false` (strictly) to abort the batch early.
|
|
375
|
+
* Any other return value (including `undefined`/`true`) continues normally.
|
|
376
|
+
* @returns The number of labels sent and the total.
|
|
377
|
+
*
|
|
378
|
+
* @example
|
|
379
|
+
* ```ts
|
|
380
|
+
* // Simple batch
|
|
381
|
+
* await printer.printBatch(labels);
|
|
382
|
+
*
|
|
383
|
+
* // With progress tracking
|
|
384
|
+
* await printer.printBatch(labels, {}, (p) => {
|
|
385
|
+
* console.log(`${p.sent}/${p.total}`);
|
|
386
|
+
* });
|
|
387
|
+
*
|
|
388
|
+
* // With status polling every 5 labels
|
|
389
|
+
* await printer.printBatch(labels, { statusInterval: 5 }, (p) => {
|
|
390
|
+
* if (p.status) console.log(`Labels remaining: ${p.status.labelsRemaining}`);
|
|
391
|
+
* });
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
async printBatch(labels, opts, onProgress) {
|
|
395
|
+
const total = labels.length;
|
|
396
|
+
const interval = opts?.statusInterval ?? 0;
|
|
397
|
+
let sent = 0;
|
|
398
|
+
for (const label of labels) {
|
|
399
|
+
await this.print(label);
|
|
400
|
+
sent++;
|
|
401
|
+
let status;
|
|
402
|
+
if (interval > 0 && sent % interval === 0) {
|
|
403
|
+
try {
|
|
404
|
+
status = await this.getStatus();
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
// Status polling is best-effort — don't abort the batch on query failure.
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (onProgress) {
|
|
411
|
+
const shouldContinue = onProgress({ sent, total, status });
|
|
412
|
+
if (shouldContinue === false)
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return { sent, total };
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Poll the printer until all queued labels have been printed.
|
|
420
|
+
*
|
|
421
|
+
* Queries `~HS` at the specified interval and resolves when
|
|
422
|
+
* `formatsInBuffer === 0` and `labelsRemaining === 0`.
|
|
423
|
+
*
|
|
424
|
+
* @param pollInterval - Milliseconds between status polls (default: 500).
|
|
425
|
+
* @param timeout - Maximum wait time in milliseconds (default: 30000).
|
|
426
|
+
* @throws {PrintError} with code `TIMEOUT` if the timeout is exceeded.
|
|
427
|
+
*/
|
|
428
|
+
async waitForCompletion(pollInterval = 500, timeout = 30_000) {
|
|
429
|
+
const start = performance.now();
|
|
430
|
+
const deadline = start + timeout;
|
|
431
|
+
while (true) {
|
|
432
|
+
if (performance.now() >= deadline) {
|
|
433
|
+
throw new PrintError(`Printer did not finish within ${timeout}ms`, "TIMEOUT");
|
|
434
|
+
}
|
|
435
|
+
try {
|
|
436
|
+
const status = await this.getStatus();
|
|
437
|
+
if (status.formatsInBuffer === 0 && status.labelsRemaining === 0) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
// Transient status query failure — retry until deadline.
|
|
443
|
+
}
|
|
444
|
+
const remaining = deadline - performance.now();
|
|
445
|
+
if (remaining <= 0) {
|
|
446
|
+
throw new PrintError(`Printer did not finish within ${timeout}ms`, "TIMEOUT");
|
|
447
|
+
}
|
|
448
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(pollInterval, remaining)));
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
/** Close the persistent connection. Safe to call multiple times. */
|
|
452
|
+
async close() {
|
|
453
|
+
this.closed = true;
|
|
454
|
+
// Drain the write queue — let in-flight writes settle before teardown.
|
|
455
|
+
try {
|
|
456
|
+
await this.writeQueue;
|
|
457
|
+
}
|
|
458
|
+
catch {
|
|
459
|
+
// Errors are already consumed in the queue chain.
|
|
460
|
+
}
|
|
461
|
+
// Wait for any in-flight connection attempt to settle first.
|
|
462
|
+
if (this.connecting) {
|
|
463
|
+
try {
|
|
464
|
+
await this.connecting;
|
|
465
|
+
}
|
|
466
|
+
catch {
|
|
467
|
+
// Connection failed — nothing to close.
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
const sock = this.socket;
|
|
471
|
+
this.socket = null;
|
|
472
|
+
this.connecting = null;
|
|
473
|
+
if (!sock || sock.destroyed)
|
|
474
|
+
return;
|
|
475
|
+
return new Promise((resolve) => {
|
|
476
|
+
const forceTimer = setTimeout(() => {
|
|
477
|
+
if (!sock.destroyed)
|
|
478
|
+
sock.destroy();
|
|
479
|
+
resolve();
|
|
480
|
+
}, 2000);
|
|
481
|
+
forceTimer.unref();
|
|
482
|
+
sock.end(() => {
|
|
483
|
+
clearTimeout(forceTimer);
|
|
484
|
+
resolve();
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Create a {@link TcpPrinter} with a persistent TCP connection.
|
|
491
|
+
*
|
|
492
|
+
* @see {@link TcpPrinter}
|
|
493
|
+
*/
|
|
494
|
+
export function createPrinter(config) {
|
|
495
|
+
return new TcpPrinter(config);
|
|
496
|
+
}
|
|
497
|
+
// ─── Validation helper ──────────────────────────────────────────────────────
|
|
498
|
+
/** @internal */
|
|
499
|
+
function isDiagnosticError(d) {
|
|
500
|
+
return (typeof d === "object" &&
|
|
501
|
+
d !== null &&
|
|
502
|
+
d.severity === "error");
|
|
503
|
+
}
|
|
504
|
+
/** @internal */
|
|
505
|
+
function isDiagnosticWarning(d) {
|
|
506
|
+
return (typeof d === "object" &&
|
|
507
|
+
d !== null &&
|
|
508
|
+
d.severity === "warn");
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Process the result of a `validate()` call and throw a {@link PrintError} if
|
|
512
|
+
* validation fails.
|
|
513
|
+
*
|
|
514
|
+
* @remarks
|
|
515
|
+
* Exported for unit-testing purposes. Not part of the public API contract.
|
|
516
|
+
*
|
|
517
|
+
* @param result - Raw return value from `@zpl-toolchain/core`'s `validate()`.
|
|
518
|
+
* @param opts - Validation options (strict mode, etc.).
|
|
519
|
+
* @throws {PrintError} with code `VALIDATION_FAILED` when errors (or warnings
|
|
520
|
+
* in strict mode) are found.
|
|
521
|
+
*
|
|
522
|
+
* @internal
|
|
523
|
+
*/
|
|
524
|
+
export function _processValidationResult(result, opts) {
|
|
525
|
+
// The core validate() returns { ok, issues } — extract issues array.
|
|
526
|
+
let diagnostics;
|
|
527
|
+
if (typeof result === "object" &&
|
|
528
|
+
result !== null &&
|
|
529
|
+
Array.isArray(result.issues)) {
|
|
530
|
+
diagnostics = result.issues;
|
|
531
|
+
}
|
|
532
|
+
else if (Array.isArray(result)) {
|
|
533
|
+
diagnostics = result;
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
diagnostics = [];
|
|
537
|
+
}
|
|
538
|
+
const errors = diagnostics.filter(isDiagnosticError);
|
|
539
|
+
const warnings = diagnostics.filter(isDiagnosticWarning);
|
|
540
|
+
// In strict mode, warnings are also treated as errors.
|
|
541
|
+
const failures = opts?.strict
|
|
542
|
+
? [...errors, ...warnings]
|
|
543
|
+
: errors;
|
|
544
|
+
if (failures.length > 0) {
|
|
545
|
+
const msgs = failures
|
|
546
|
+
.map((e) => {
|
|
547
|
+
if (typeof e === "object" && e !== null) {
|
|
548
|
+
const msg = e.message;
|
|
549
|
+
return typeof msg === "string" && msg.length > 0 ? msg : "unknown error";
|
|
550
|
+
}
|
|
551
|
+
return "unknown error";
|
|
552
|
+
})
|
|
553
|
+
.join("; ");
|
|
554
|
+
const label = opts?.strict && errors.length === 0
|
|
555
|
+
? "ZPL validation warnings (strict mode)"
|
|
556
|
+
: "ZPL validation failed";
|
|
557
|
+
throw new PrintError(`${label}: ${msgs}`, "VALIDATION_FAILED");
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// ─── printValidated — convenience with optional @zpl-toolchain/core ──────────
|
|
561
|
+
/**
|
|
562
|
+
* Print ZPL after first validating it with `@zpl-toolchain/core` (if
|
|
563
|
+
* installed). Falls back to a plain print if the core package is not
|
|
564
|
+
* available.
|
|
565
|
+
*
|
|
566
|
+
* Supports optional printer-profile-aware validation and strict mode
|
|
567
|
+
* (treat warnings as errors).
|
|
568
|
+
*
|
|
569
|
+
* @param zpl - The ZPL source string to validate and send.
|
|
570
|
+
* @param config - Printer connection configuration.
|
|
571
|
+
* @param validateOpts - Optional validation settings (profile, strict mode).
|
|
572
|
+
*
|
|
573
|
+
* @throws {PrintError} with code `VALIDATION_FAILED` if validation finds errors
|
|
574
|
+
* (or warnings in strict mode).
|
|
575
|
+
* @throws {PrintError} with a network-related code if the print operation fails.
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
* ```ts
|
|
579
|
+
* import { printValidated } from "@zpl-toolchain/print";
|
|
580
|
+
* import { readFileSync } from "node:fs";
|
|
581
|
+
*
|
|
582
|
+
* // Basic: validate then print
|
|
583
|
+
* await printValidated("^XA^FDHello^FS^XZ", { host: "192.168.1.100" });
|
|
584
|
+
*
|
|
585
|
+
* // With printer profile for hardware-aware validation
|
|
586
|
+
* const profile = readFileSync("profiles/ZD421.json", "utf-8");
|
|
587
|
+
* await printValidated("^XA^FDHello^FS^XZ", { host: "192.168.1.100" }, {
|
|
588
|
+
* profileJson: profile,
|
|
589
|
+
* strict: true, // treat warnings as errors
|
|
590
|
+
* });
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
export async function printValidated(zpl, config, validateOpts) {
|
|
594
|
+
// Step 1: Try to load the optional peer dependency.
|
|
595
|
+
let core;
|
|
596
|
+
try {
|
|
597
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
598
|
+
core = await Function('return import("@zpl-toolchain/core")')();
|
|
599
|
+
}
|
|
600
|
+
catch {
|
|
601
|
+
// Module not installed — skip validation silently.
|
|
602
|
+
}
|
|
603
|
+
// Step 2: If loaded, validate (errors propagate naturally).
|
|
604
|
+
if (core) {
|
|
605
|
+
const validate = core.validate;
|
|
606
|
+
if (typeof validate === "function") {
|
|
607
|
+
const result = await validate(zpl, validateOpts?.profileJson);
|
|
608
|
+
_processValidationResult(result, validateOpts);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
return print(zpl, config);
|
|
612
|
+
}
|
|
613
|
+
// ─── Standalone batch print ──────────────────────────────────────────────────
|
|
614
|
+
/**
|
|
615
|
+
* Send multiple ZPL labels to a printer in a single session.
|
|
616
|
+
*
|
|
617
|
+
* Opens a persistent connection, sends all labels sequentially, and closes.
|
|
618
|
+
*
|
|
619
|
+
* @param labels - Array of ZPL strings, one per label.
|
|
620
|
+
* @param config - Printer connection configuration.
|
|
621
|
+
* @param opts - Optional batch options (e.g., status polling interval).
|
|
622
|
+
* @param onProgress - Optional callback after each label.
|
|
623
|
+
* Return `false` (strictly) to abort the batch early.
|
|
624
|
+
* @returns The number of labels sent and the total.
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```ts
|
|
628
|
+
* import { printBatch } from "@zpl-toolchain/print";
|
|
629
|
+
*
|
|
630
|
+
* const labels = [
|
|
631
|
+
* "^XA^FO50,50^A0N,50,50^FDLabel 1^FS^XZ",
|
|
632
|
+
* "^XA^FO50,50^A0N,50,50^FDLabel 2^FS^XZ",
|
|
633
|
+
* ];
|
|
634
|
+
* const result = await printBatch(labels, { host: "192.168.1.100" });
|
|
635
|
+
* console.log(`Sent ${result.sent}/${result.total} labels`);
|
|
636
|
+
* ```
|
|
637
|
+
*/
|
|
638
|
+
export async function printBatch(labels, config, opts, onProgress) {
|
|
639
|
+
const printer = new TcpPrinter(config);
|
|
640
|
+
try {
|
|
641
|
+
return await printer.printBatch(labels, opts, onProgress);
|
|
642
|
+
}
|
|
643
|
+
finally {
|
|
644
|
+
await printer.close();
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAW3B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,UAAU,GASX,MAAM,YAAY,CAAC;AAEpB,gFAAgF;AAEhF,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,gFAAgF;AAEhF,SAAS,aAAa,CAAC,GAA0B;IAC/C,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,cAAc;YACjB,OAAO,oBAAoB,CAAC;QAC9B,KAAK,WAAW;YACd,OAAO,SAAS,CAAC;QACnB,KAAK,WAAW;YACd,OAAO,gBAAgB,CAAC;QAC1B,KAAK,OAAO;YACV,OAAO,aAAa,CAAC;QACvB,KAAK,YAAY;YACf,OAAO,kBAAkB,CAAC;QAC5B;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,GAAG,YAAY,UAAU;QAAE,OAAO,GAAG,CAAC;IAC1C,MAAM,OAAO,GAAG,GAA4B,CAAC;IAC7C,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,IAAI,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,gFAAgF;AAEhF,SAAS,aAAa,CAAC,GAAkB;IACvC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,UAAU,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,YAAY,CAAC;IACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACxD,MAAM,IAAI,UAAU,CAAC,iBAAiB,IAAI,oBAAoB,EAAE,SAAS,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC;IAC/C,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,UAAU,CAAC,oBAAoB,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACjE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI;QACJ,OAAO;QACP,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,mBAAmB;QACjD,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,mBAAmB;KAClD,CAAC;AACJ,CAAC;AAED,mCAAmC;AACnC,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,gFAAgF;AAEhF;;GAEG;AACH,SAAS,OAAO,CACd,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,OAAe;IAEf,OAAO,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,MAAM,IAAI,GAAG,CAAC,GAAe,EAAE,EAAE;YAC/B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,MAAmB,EAAE,EAAE;YACtC,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE;YACvD,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE;gBAC7B,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAC1B,OAAO;gBACT,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;oBACd,OAAO,CAAC;wBACN,OAAO,EAAE,IAAI;wBACb,YAAY,EAAE,GAAG,CAAC,MAAM;wBACxB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;qBAChD,CAAC,CAAC;oBACH,qEAAqE;oBACrE,2DAA2D;oBAC3D,UAAU,CAAC,GAAG,EAAE;wBACd,IAAI,CAAC,MAAM,CAAC,SAAS;4BAAE,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC1C,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACxB,IAAI,CACF,IAAI,UAAU,CACZ,iBAAiB,IAAI,IAAI,IAAI,oBAAoB,OAAO,IAAI,EAC5D,SAAS,CACV,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAY,EACZ,IAAY,EACZ,OAAe,EACf,OAAe;IAEf,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,IAAI,SAAoD,CAAC;QACzD,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,CAAC,GAAe,EAAE,EAAE;YAC/B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE;YACvD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAE3B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,gEAAgE;YAChE,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC1B,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,CAAC,EAAE,GAAG,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACxB,0DAA0D;YAC1D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,IAAI,CACF,IAAI,UAAU,CACZ,YAAY,IAAI,IAAI,IAAI,oBAAoB,OAAO,IAAI,EACvD,SAAS,CACV,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,GAAW,EACX,MAAqB;IAErB,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,SAAiC,CAAC;IAEtC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QAC3D,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAE3B,kCAAkC;YAClC,MAAM,SAAS,GAAqB;gBAClC,SAAS;gBACT,kBAAkB;gBAClB,aAAa;aACd,CAAC;YACF,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;gBAAE,MAAM,SAAS,CAAC;YACzD,IAAI,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBACpD,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAU,CAAC;AACnB,CAAC;AAED,+EAA+E;AAE/E;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,UAAU;IACJ,MAAM,CAAmC;IAClD,MAAM,GAAsB,IAAI,CAAC;IACjC,UAAU,GAAyB,IAAI,CAAC;IACxC,MAAM,GAAG,KAAK,CAAC;IACf,UAAU,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEtD,YAAY,MAAqB;QAC/B,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,0EAA0E;IAE1E,+DAA+D;IACvD,KAAK,CAAC,eAAe;QAC3B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,UAAU,CAAC,oCAAoC,EAAE,SAAS,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,UAAU,CAAC;YACtB,OAAO,IAAI,CAAC,MAAO,CAAC;QACtB,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,GAAG,CAAC,gBAAgB,CAC/B,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAClD,GAAG,EAAE;gBACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBACtB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChC,sEAAsE;gBACtE,+EAA+E;gBAC/E,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBACnB,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;gBACnC,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;gBACvB,OAAO,EAAE,CAAC;YACZ,CAAC,CACF,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACtB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;gBACvB,MAAM,CACJ,IAAI,UAAU,CACZ,iBAAiB,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,YAAY,EACjE,SAAS,CACV,CACF,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;gBACvB,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,UAAU,CAAC;QACtB,OAAO,IAAI,CAAC,MAAO,CAAC;IACtB,CAAC;IAED,0EAA0E;IAE1E;;;;OAIG;IACH,KAAK,CAAC,GAAW;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAC1C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAEtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1C,OAAO,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAClD,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;oBACtB,IAAI,GAAG,EAAE,CAAC;wBACR,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;wBACnB,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;wBACvB,OAAO;oBACT,CAAC;oBACD,OAAO,CAAC;wBACN,OAAO,EAAE,IAAI;wBACb,YAAY,EAAE,GAAG,CAAC,MAAM;wBACxB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;qBAChD,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,0DAA0D;QAC1D,mEAAmE;QACnE,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,IAAI,CACxB,GAAG,EAAE,GAAE,CAAC,EACR,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;QACF,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,GAAG,GAAG,MAAM,QAAQ,CACxB,IAAI,CAAC,MAAM,CAAC,IAAI,EAChB,IAAI,CAAC,MAAM,CAAC,IAAI,EAChB,KAAK,EACL,IAAI,CAAC,MAAM,CAAC,OAAO,CACpB,CAAC;QACF,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,KAAK,CAAC,OAAe;QACzB,OAAO,QAAQ,CACb,IAAI,CAAC,MAAM,CAAC,IAAI,EAChB,IAAI,CAAC,MAAM,CAAC,IAAI,EAChB,OAAO,EACP,IAAI,CAAC,MAAM,CAAC,OAAO,CACpB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACtC,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE;gBAC9B,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,IAAI,GAAG,GAAG,CAAC,gBAAgB,CAC/B,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAClD,GAAG,EAAE;gBACH,IAAI,CAAC,GAAG,EAAE,CAAC;gBACX,iEAAiE;gBACjE,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS;oBAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACzE,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,CAAC,CACF,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACtB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACpB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAK,CAAC,UAAU,CACd,MAAgB,EAChB,IAAmB,EACnB,UAAwD;QAExD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,EAAE,cAAc,IAAI,CAAC,CAAC;QAC3C,IAAI,IAAI,GAAG,CAAC,CAAC;QAEb,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,EAAE,CAAC;YAEP,IAAI,MAAiC,CAAC;YACtC,IAAI,QAAQ,GAAG,CAAC,IAAI,IAAI,GAAG,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC;oBACH,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;gBAClC,CAAC;gBAAC,MAAM,CAAC;oBACP,0EAA0E;gBAC5E,CAAC;YACH,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,cAAc,GAAG,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC3D,IAAI,cAAc,KAAK,KAAK;oBAAE,MAAM;YACtC,CAAC;QACH,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,iBAAiB,CACrB,YAAY,GAAG,GAAG,EAClB,OAAO,GAAG,MAAM;QAEhB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;QAEjC,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAClC,MAAM,IAAI,UAAU,CAClB,iCAAiC,OAAO,IAAI,EAC5C,SAAS,CACV,CAAC;YACJ,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;gBACtC,IAAI,MAAM,CAAC,eAAe,KAAK,CAAC,IAAI,MAAM,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;oBACjE,OAAO;gBACT,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,yDAAyD;YAC3D,CAAC;YAED,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAC/C,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,MAAM,IAAI,UAAU,CAClB,iCAAiC,OAAO,IAAI,EAC5C,SAAS,CACV,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAC5B,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CACvD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,uEAAuE;QACvE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,UAAU,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QAED,6DAA6D;QAC7D,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,UAAU,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,wCAAwC;YAC1C,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QACpC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;gBACjC,IAAI,CAAC,IAAI,CAAC,SAAS;oBAAE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACpC,OAAO,EAAE,CAAC;YACZ,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;gBACZ,YAAY,CAAC,UAAU,CAAC,CAAC;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAqB;IACjD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,+EAA+E;AAE/E,gBAAgB;AAChB,SAAS,iBAAiB,CAAC,CAAU;IACnC,OAAO,CACL,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACT,CAA6B,CAAC,QAAQ,KAAK,OAAO,CACpD,CAAC;AACJ,CAAC;AAED,gBAAgB;AAChB,SAAS,mBAAmB,CAAC,CAAU;IACrC,OAAO,CACL,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACT,CAA6B,CAAC,QAAQ,KAAK,MAAM,CACnD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAAe,EACf,IAAsB;IAEtB,qEAAqE;IACrE,IAAI,WAAsB,CAAC;IAC3B,IACE,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,KAAK,CAAC,OAAO,CAAE,MAAkC,CAAC,MAAM,CAAC,EACzD,CAAC;QACD,WAAW,GAAI,MAAkC,CAAC,MAAmB,CAAC;IACxE,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,WAAW,GAAG,MAAM,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAEzD,uDAAuD;IACvD,MAAM,QAAQ,GAAG,IAAI,EAAE,MAAM;QAC3B,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC;QAC1B,CAAC,CAAC,MAAM,CAAC;IAEX,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,QAAQ;aAClB,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE;YAClB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACxC,MAAM,GAAG,GAAI,CAA6B,CAAC,OAAO,CAAC;gBACnD,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC;YAC3E,CAAC;YACD,OAAO,eAAe,CAAC;QACzB,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,KAAK,GAAG,IAAI,EAAE,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAC/C,CAAC,CAAC,uCAAuC;YACzC,CAAC,CAAC,uBAAuB,CAAC;QAC5B,MAAM,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,IAAI,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,MAAqB,EACrB,YAA8B;IAE9B,oDAAoD;IACpD,IAAI,IAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,mEAAmE;QACnE,IAAI,GAAG,MAAO,QAAQ,CACpB,sCAAsC,CACvC,EAAuC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;IACrD,CAAC;IAED,4DAA4D;IAC5D,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACnC,MAAM,MAAM,GAAY,MAAM,QAAQ,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YACvE,wBAAwB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAgB,EAChB,MAAqB,EACrB,IAAmB,EACnB,UAAwD;IAExD,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5D,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|