label-printer 0.5.4 → 0.7.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 +245 -25
- package/dist/index.d.mts +30 -55
- package/dist/index.d.ts +30 -55
- package/dist/index.js +538 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +534 -108
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -22,9 +22,9 @@ var __spreadValues = (a, b) => {
|
|
|
22
22
|
return a;
|
|
23
23
|
};
|
|
24
24
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
-
var __export = (
|
|
25
|
+
var __export = (target2, all) => {
|
|
26
26
|
for (var name in all)
|
|
27
|
-
__defProp(
|
|
27
|
+
__defProp(target2, name, { get: all[name], enumerable: true });
|
|
28
28
|
};
|
|
29
29
|
var __copyProps = (to, from, except, desc) => {
|
|
30
30
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -34,15 +34,15 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
34
34
|
}
|
|
35
35
|
return to;
|
|
36
36
|
};
|
|
37
|
-
var __toESM = (
|
|
37
|
+
var __toESM = (mod2, isNodeMode, target2) => (target2 = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
38
38
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
39
39
|
// file that has been converted to a CommonJS file using a Babel-
|
|
40
40
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
41
41
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
42
|
-
isNodeMode || !
|
|
43
|
-
|
|
42
|
+
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target2, "default", { value: mod2, enumerable: true }) : target2,
|
|
43
|
+
mod2
|
|
44
44
|
));
|
|
45
|
-
var __toCommonJS = (
|
|
45
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
46
46
|
var __async = (__this, __arguments, generator) => {
|
|
47
47
|
return new Promise((resolve, reject) => {
|
|
48
48
|
var fulfilled = (value) => {
|
|
@@ -87,10 +87,10 @@ var Command = class {
|
|
|
87
87
|
fn(this.commandString);
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
|
-
* Write the command data to a
|
|
90
|
+
* Write the command data to a device
|
|
91
91
|
* @param device Device to write to
|
|
92
92
|
*/
|
|
93
|
-
|
|
93
|
+
writeTo(device) {
|
|
94
94
|
return __async(this, null, function* () {
|
|
95
95
|
yield this.writeString(this.commandString, device);
|
|
96
96
|
yield this.terminateCommand(device);
|
|
@@ -144,10 +144,10 @@ var CommandGroup = class extends Command {
|
|
|
144
144
|
this.commands[commandIndex].print(fn);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
writeTo(device) {
|
|
148
148
|
return __async(this, null, function* () {
|
|
149
149
|
for (let commandIndex in this.commands) {
|
|
150
|
-
yield this.commands[commandIndex].
|
|
150
|
+
yield this.commands[commandIndex].writeTo(device);
|
|
151
151
|
}
|
|
152
152
|
});
|
|
153
153
|
}
|
|
@@ -424,14 +424,15 @@ var ImageProcessor = class {
|
|
|
424
424
|
/**
|
|
425
425
|
* Get pixel information about an image
|
|
426
426
|
* @param image Image to process (local file path, remote URL, data URL, or Blob)
|
|
427
|
+
* @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.
|
|
427
428
|
* @returns Promise with image data including width, height, pixel data, and bits per pixel
|
|
428
429
|
*/
|
|
429
|
-
static getImageData(image2) {
|
|
430
|
+
static getImageData(image2, target2) {
|
|
430
431
|
return __async(this, null, function* () {
|
|
431
432
|
if (typeof window !== "undefined") {
|
|
432
|
-
return this.getImageDataBrowser(image2);
|
|
433
|
+
return this.getImageDataBrowser(image2, target2);
|
|
433
434
|
} else {
|
|
434
|
-
return this.getImageDataNode(image2);
|
|
435
|
+
return this.getImageDataNode(image2, target2);
|
|
435
436
|
}
|
|
436
437
|
});
|
|
437
438
|
}
|
|
@@ -439,74 +440,76 @@ var ImageProcessor = class {
|
|
|
439
440
|
/**
|
|
440
441
|
* Get pixel information about an image in browser environment
|
|
441
442
|
* @param image Image to process
|
|
443
|
+
* @param target Optional target raster size.
|
|
442
444
|
* @returns Promise with image data
|
|
443
445
|
*/
|
|
444
|
-
static getImageDataBrowser(image2) {
|
|
446
|
+
static getImageDataBrowser(image2, target2) {
|
|
445
447
|
return __async(this, null, function* () {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
img.onerror = () => reject(new Error("Failed to load image"));
|
|
473
|
-
if (typeof image2 === "string") {
|
|
474
|
-
img.src = image2;
|
|
475
|
-
} else {
|
|
476
|
-
const url2 = URL.createObjectURL(image2);
|
|
477
|
-
img.onload = () => {
|
|
478
|
-
URL.revokeObjectURL(url2);
|
|
479
|
-
resolve({
|
|
480
|
-
data: new Uint8Array(0),
|
|
481
|
-
// Will be set by the actual onload
|
|
482
|
-
width: 0,
|
|
483
|
-
height: 0,
|
|
484
|
-
bitsPerPixel: 4
|
|
485
|
-
});
|
|
486
|
-
};
|
|
487
|
-
img.src = url2;
|
|
448
|
+
var _a, _b;
|
|
449
|
+
const loadImage = (src2) => {
|
|
450
|
+
return new Promise((resolve, reject) => {
|
|
451
|
+
const img = new Image();
|
|
452
|
+
img.crossOrigin = "anonymous";
|
|
453
|
+
img.onload = () => resolve(img);
|
|
454
|
+
img.onerror = () => reject(new Error("Failed to load image"));
|
|
455
|
+
img.src = src2;
|
|
456
|
+
});
|
|
457
|
+
};
|
|
458
|
+
let src;
|
|
459
|
+
let revokeUrl;
|
|
460
|
+
if (typeof image2 === "string") {
|
|
461
|
+
src = this.normalizePotentialSVGSource(image2);
|
|
462
|
+
} else {
|
|
463
|
+
revokeUrl = URL.createObjectURL(image2);
|
|
464
|
+
src = revokeUrl;
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
const img = yield loadImage(src);
|
|
468
|
+
const canvas = document.createElement("canvas");
|
|
469
|
+
const ctx = canvas.getContext("2d");
|
|
470
|
+
if (!ctx) {
|
|
471
|
+
throw new Error("Could not get canvas context");
|
|
488
472
|
}
|
|
489
|
-
|
|
473
|
+
const width = (_a = target2 == null ? void 0 : target2.width) != null ? _a : img.width;
|
|
474
|
+
const height = (_b = target2 == null ? void 0 : target2.height) != null ? _b : img.height;
|
|
475
|
+
canvas.width = width;
|
|
476
|
+
canvas.height = height;
|
|
477
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
478
|
+
const imageData2 = ctx.getImageData(0, 0, width, height);
|
|
479
|
+
return {
|
|
480
|
+
data: new Uint8Array(imageData2.data),
|
|
481
|
+
width,
|
|
482
|
+
height,
|
|
483
|
+
bitsPerPixel: 4
|
|
484
|
+
};
|
|
485
|
+
} finally {
|
|
486
|
+
if (revokeUrl) URL.revokeObjectURL(revokeUrl);
|
|
487
|
+
}
|
|
490
488
|
});
|
|
491
489
|
}
|
|
492
490
|
/******** NODEJS ********/
|
|
493
491
|
/**
|
|
494
492
|
* Get pixel information about an image in Node.js environment
|
|
495
493
|
* @param image Image to process
|
|
494
|
+
* @param target Optional target raster size.
|
|
496
495
|
* @returns Promise with image data
|
|
497
496
|
*/
|
|
498
|
-
static getImageDataNode(image2) {
|
|
497
|
+
static getImageDataNode(image2, _target) {
|
|
499
498
|
return __async(this, null, function* () {
|
|
500
499
|
console.log("Processing image in Node.js environment");
|
|
501
500
|
if (image2 instanceof Blob) {
|
|
502
501
|
throw new Error("Blob input not supported in Node.js environment. Use file path or data URL instead.");
|
|
503
502
|
}
|
|
503
|
+
const trimmed = image2.trim();
|
|
504
|
+
if (trimmed.startsWith("<svg")) {
|
|
505
|
+
return this.rasterizeSVGNode(trimmed, _target);
|
|
506
|
+
}
|
|
504
507
|
if (image2.startsWith("data:")) {
|
|
505
|
-
return this.getImageFromData(image2);
|
|
508
|
+
return this.getImageFromData(image2, _target);
|
|
506
509
|
} else if (image2.startsWith("http://") || image2.startsWith("https://")) {
|
|
507
|
-
return this.getImageFromUrl(image2);
|
|
510
|
+
return this.getImageFromUrl(image2, _target);
|
|
508
511
|
} else {
|
|
509
|
-
return this.getImageFromFile(image2);
|
|
512
|
+
return this.getImageFromFile(image2, _target);
|
|
510
513
|
}
|
|
511
514
|
});
|
|
512
515
|
}
|
|
@@ -515,7 +518,7 @@ var ImageProcessor = class {
|
|
|
515
518
|
* @param dataURL Data URL string
|
|
516
519
|
* @returns Promise with image data
|
|
517
520
|
*/
|
|
518
|
-
static getImageFromData(dataURL) {
|
|
521
|
+
static getImageFromData(dataURL, target2) {
|
|
519
522
|
return __async(this, null, function* () {
|
|
520
523
|
var _a;
|
|
521
524
|
const [header, data] = dataURL.split(",");
|
|
@@ -523,8 +526,13 @@ var ImageProcessor = class {
|
|
|
523
526
|
if (!(mimeType == null ? void 0 : mimeType.startsWith("image/"))) {
|
|
524
527
|
throw new Error("Invalid image data URL");
|
|
525
528
|
}
|
|
526
|
-
const buffer2 = Buffer.from(data, "base64");
|
|
527
529
|
const extension = mimeType.split("/")[1].toLowerCase();
|
|
530
|
+
if (extension === "svg+xml" || mimeType === "image/svg+xml") {
|
|
531
|
+
const isBase64 = header.includes(";base64");
|
|
532
|
+
const svgText = isBase64 ? Buffer.from(data, "base64").toString("utf8") : decodeURIComponent(data);
|
|
533
|
+
return this.rasterizeSVGNode(svgText, target2);
|
|
534
|
+
}
|
|
535
|
+
const buffer2 = Buffer.from(data, "base64");
|
|
528
536
|
return this.parse(buffer2, extension);
|
|
529
537
|
});
|
|
530
538
|
}
|
|
@@ -533,7 +541,7 @@ var ImageProcessor = class {
|
|
|
533
541
|
* @param image
|
|
534
542
|
* @returns
|
|
535
543
|
*/
|
|
536
|
-
static getImageFromFile(image) {
|
|
544
|
+
static getImageFromFile(image, target) {
|
|
537
545
|
return __async(this, null, function* () {
|
|
538
546
|
const fs = yield eval("require")("fs");
|
|
539
547
|
const path = yield eval("require")("path");
|
|
@@ -542,6 +550,10 @@ var ImageProcessor = class {
|
|
|
542
550
|
}
|
|
543
551
|
const buffer = fs.readFileSync(image);
|
|
544
552
|
const ext = path.extname(image).toLowerCase();
|
|
553
|
+
if (ext === ".svg") {
|
|
554
|
+
const svgText = buffer.toString("utf8");
|
|
555
|
+
return this.rasterizeSVGNode(svgText, target);
|
|
556
|
+
}
|
|
545
557
|
return this.parse(buffer, ext);
|
|
546
558
|
});
|
|
547
559
|
}
|
|
@@ -550,16 +562,16 @@ var ImageProcessor = class {
|
|
|
550
562
|
* @param url Remote image URL
|
|
551
563
|
* @returns Promise with image data
|
|
552
564
|
*/
|
|
553
|
-
static getImageFromUrl(url2) {
|
|
565
|
+
static getImageFromUrl(url2, target2) {
|
|
554
566
|
return __async(this, null, function* () {
|
|
555
567
|
let fetch;
|
|
556
568
|
try {
|
|
557
569
|
fetch = globalThis.fetch;
|
|
558
570
|
} catch (e) {
|
|
559
|
-
return this.fetchWithHttps(url2);
|
|
571
|
+
return this.fetchWithHttps(url2, target2);
|
|
560
572
|
}
|
|
561
573
|
if (!fetch) {
|
|
562
|
-
return this.fetchWithHttps(url2);
|
|
574
|
+
return this.fetchWithHttps(url2, target2);
|
|
563
575
|
}
|
|
564
576
|
const response = yield fetch(url2);
|
|
565
577
|
if (!response.ok) {
|
|
@@ -569,6 +581,10 @@ var ImageProcessor = class {
|
|
|
569
581
|
const buffer2 = Buffer.from(arrayBuffer);
|
|
570
582
|
const contentType = response.headers.get("content-type");
|
|
571
583
|
const imageType = this.getImageType(contentType || "", url2);
|
|
584
|
+
if (imageType === "svg") {
|
|
585
|
+
const svgText = buffer2.toString("utf8");
|
|
586
|
+
return this.rasterizeSVGNode(svgText, target2);
|
|
587
|
+
}
|
|
572
588
|
return this.parse(buffer2, imageType);
|
|
573
589
|
});
|
|
574
590
|
}
|
|
@@ -577,7 +593,7 @@ var ImageProcessor = class {
|
|
|
577
593
|
* @param url Remote image URL
|
|
578
594
|
* @returns Promise with image data
|
|
579
595
|
*/
|
|
580
|
-
static fetchWithHttps(url) {
|
|
596
|
+
static fetchWithHttps(url, target) {
|
|
581
597
|
return __async(this, null, function* () {
|
|
582
598
|
const https = yield eval("require")("https");
|
|
583
599
|
const http = yield eval("require")("http");
|
|
@@ -597,8 +613,12 @@ var ImageProcessor = class {
|
|
|
597
613
|
const buffer2 = Buffer.concat(chunks);
|
|
598
614
|
const contentType = response.headers["content-type"] || "";
|
|
599
615
|
const imageType = this.getImageType(contentType || "", url);
|
|
600
|
-
|
|
601
|
-
|
|
616
|
+
if (imageType === "svg") {
|
|
617
|
+
const svgText = buffer2.toString("utf8");
|
|
618
|
+
resolve(this.rasterizeSVGNode(svgText, target));
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
resolve(this.parse(buffer2, imageType));
|
|
602
622
|
} catch (error) {
|
|
603
623
|
reject(error);
|
|
604
624
|
}
|
|
@@ -626,6 +646,8 @@ var ImageProcessor = class {
|
|
|
626
646
|
return "png";
|
|
627
647
|
} else if (contentType.includes("jpeg") || contentType.includes("jpg")) {
|
|
628
648
|
return "jpeg";
|
|
649
|
+
} else if (contentType.includes("svg")) {
|
|
650
|
+
return "svg";
|
|
629
651
|
}
|
|
630
652
|
}
|
|
631
653
|
const urlLower = url2.toLowerCase();
|
|
@@ -633,32 +655,57 @@ var ImageProcessor = class {
|
|
|
633
655
|
return "png";
|
|
634
656
|
} else if (urlLower.includes(".jpg") || urlLower.includes(".jpeg")) {
|
|
635
657
|
return "jpeg";
|
|
658
|
+
} else if (urlLower.includes(".svg")) {
|
|
659
|
+
return "svg";
|
|
636
660
|
}
|
|
637
661
|
return "";
|
|
638
662
|
}
|
|
639
663
|
/**
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
* @param extension
|
|
643
|
-
* @returns
|
|
644
|
-
*/
|
|
664
|
+
* Parse image data by extension
|
|
665
|
+
*/
|
|
645
666
|
static parse(buffer2, extension) {
|
|
646
|
-
|
|
647
|
-
|
|
667
|
+
const normalizedExtension = extension.startsWith(".") ? extension.slice(1) : extension;
|
|
668
|
+
console.log(`Parsing image with extension: ${normalizedExtension}`);
|
|
669
|
+
if (normalizedExtension === "png") {
|
|
648
670
|
return parsePNG(buffer2);
|
|
649
|
-
} else if (
|
|
671
|
+
} else if (normalizedExtension === "jpeg" || normalizedExtension === "jpg") {
|
|
650
672
|
return this.parseJPEG(buffer2);
|
|
673
|
+
} else if (normalizedExtension === "svg") {
|
|
674
|
+
throw new Error("svg-not-supported-in-node");
|
|
651
675
|
} else {
|
|
652
|
-
throw new Error(`Unsupported image format: ${
|
|
676
|
+
throw new Error(`Unsupported image format: ${normalizedExtension}. Supported formats: PNG, JPEG`);
|
|
653
677
|
}
|
|
654
678
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
679
|
+
static rasterizeSVGNode(svg, target) {
|
|
680
|
+
let Resvg;
|
|
681
|
+
try {
|
|
682
|
+
Resvg = eval("require")("@resvg/resvg-js").Resvg;
|
|
683
|
+
} catch (_e) {
|
|
684
|
+
throw new Error("svg-rasterizer-missing");
|
|
685
|
+
}
|
|
686
|
+
const fitTo = target ? { mode: "width", value: target.width } : void 0;
|
|
687
|
+
const resvg = new Resvg(svg, {
|
|
688
|
+
fitTo
|
|
689
|
+
});
|
|
690
|
+
const pngData = resvg.render().asPng();
|
|
691
|
+
const pngBuffer = Buffer.from(pngData);
|
|
692
|
+
const imageData = parsePNG(pngBuffer);
|
|
693
|
+
if (target && (imageData.width !== target.width || imageData.height !== target.height)) {
|
|
694
|
+
return this.resize(imageData, target.width, target.height);
|
|
695
|
+
}
|
|
696
|
+
return imageData;
|
|
697
|
+
}
|
|
698
|
+
static normalizePotentialSVGSource(source) {
|
|
699
|
+
const trimmed = source.trim();
|
|
700
|
+
const isInlineSvg = trimmed.startsWith("<svg");
|
|
701
|
+
const isSvgDataUrl = trimmed.startsWith("data:image/svg+xml");
|
|
702
|
+
if (isInlineSvg) {
|
|
703
|
+
const encoded = encodeURIComponent(trimmed);
|
|
704
|
+
return `data:image/svg+xml;charset=utf-8,${encoded}`;
|
|
705
|
+
}
|
|
706
|
+
if (isSvgDataUrl) return source;
|
|
707
|
+
return source;
|
|
708
|
+
}
|
|
662
709
|
static parseJPEG(buffer2) {
|
|
663
710
|
if (buffer2[0] !== 255 || buffer2[1] !== 216) {
|
|
664
711
|
throw new Error("Invalid JPEG file");
|
|
@@ -725,8 +772,8 @@ var ImageProcessor = class {
|
|
|
725
772
|
* @param imageData Original image data
|
|
726
773
|
* @returns Grayscale image data
|
|
727
774
|
*/
|
|
728
|
-
static toGrayscale(
|
|
729
|
-
const { data, width, height } =
|
|
775
|
+
static toGrayscale(imageData2) {
|
|
776
|
+
const { data, width, height } = imageData2;
|
|
730
777
|
const grayscaleData = new Uint8Array(data.length);
|
|
731
778
|
for (let i = 0; i < data.length; i += 4) {
|
|
732
779
|
const r = data[i];
|
|
@@ -743,7 +790,7 @@ var ImageProcessor = class {
|
|
|
743
790
|
data: grayscaleData,
|
|
744
791
|
width,
|
|
745
792
|
height,
|
|
746
|
-
bitsPerPixel:
|
|
793
|
+
bitsPerPixel: imageData2.bitsPerPixel
|
|
747
794
|
};
|
|
748
795
|
}
|
|
749
796
|
/**
|
|
@@ -753,8 +800,8 @@ var ImageProcessor = class {
|
|
|
753
800
|
* @param newHeight Target height
|
|
754
801
|
* @returns Resized image data
|
|
755
802
|
*/
|
|
756
|
-
static resize(
|
|
757
|
-
const { data, width, height, bitsPerPixel } =
|
|
803
|
+
static resize(imageData2, newWidth, newHeight) {
|
|
804
|
+
const { data, width, height, bitsPerPixel } = imageData2;
|
|
758
805
|
const resizedData = new Uint8Array(newWidth * newHeight * bitsPerPixel);
|
|
759
806
|
const xRatio = width / newWidth;
|
|
760
807
|
const yRatio = height / newHeight;
|
|
@@ -782,15 +829,17 @@ var ImageProcessor_default = ImageProcessor;
|
|
|
782
829
|
// src/helpers/ImageUtils.ts
|
|
783
830
|
var BLACK_PIXEL = 0;
|
|
784
831
|
var WHITE_PIXEL = 1;
|
|
832
|
+
var DEFAULT_THRESHOLD = 200;
|
|
785
833
|
var ImageUtils = class {
|
|
786
834
|
/**
|
|
787
835
|
* Get pixel information about an image
|
|
788
836
|
* @param image Image to process
|
|
837
|
+
* @param target Optional target raster size. Useful for vector inputs (e.g. SVG) to rasterize at the final size.
|
|
789
838
|
* @returns
|
|
790
839
|
*/
|
|
791
|
-
static getPixels(image2) {
|
|
840
|
+
static getPixels(image2, target2) {
|
|
792
841
|
return __async(this, null, function* () {
|
|
793
|
-
return yield ImageProcessor_default.getImageData(image2);
|
|
842
|
+
return yield ImageProcessor_default.getImageData(image2, target2);
|
|
794
843
|
});
|
|
795
844
|
}
|
|
796
845
|
/**
|
|
@@ -810,7 +859,10 @@ var ImageUtils = class {
|
|
|
810
859
|
width,
|
|
811
860
|
height,
|
|
812
861
|
bitsPerPixel
|
|
813
|
-
} = yield this.getPixels(
|
|
862
|
+
} = yield this.getPixels(
|
|
863
|
+
image2,
|
|
864
|
+
destinationWidth != null && destinationHeight != null ? { width: destinationWidth, height: destinationHeight } : void 0
|
|
865
|
+
);
|
|
814
866
|
const dim = getSizePreserveAspect(width, height, destinationWidth, destinationHeight);
|
|
815
867
|
const dWidth = dim.width;
|
|
816
868
|
const dHeight = dim.height;
|
|
@@ -826,16 +878,16 @@ var ImageUtils = class {
|
|
|
826
878
|
const r = data[baseIndex];
|
|
827
879
|
const g = data[baseIndex + 1];
|
|
828
880
|
const b = data[baseIndex + 2];
|
|
829
|
-
const a = data[baseIndex + 3];
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
}
|
|
837
|
-
} else {
|
|
881
|
+
const a = bitsPerPixel > 3 ? data[baseIndex + 3] : 255;
|
|
882
|
+
const alpha = a / 255;
|
|
883
|
+
const rC = r * alpha + 255 * (1 - alpha);
|
|
884
|
+
const gC = g * alpha + 255 * (1 - alpha);
|
|
885
|
+
const bC = b * alpha + 255 * (1 - alpha);
|
|
886
|
+
const luminance = 0.299 * rC + 0.587 * gC + 0.114 * bC;
|
|
887
|
+
if (luminance > DEFAULT_THRESHOLD) {
|
|
838
888
|
bitmapData[destinationIndex] = WHITE_PIXEL;
|
|
889
|
+
} else {
|
|
890
|
+
bitmapData[destinationIndex] = BLACK_PIXEL;
|
|
839
891
|
}
|
|
840
892
|
destinationIndex += 1;
|
|
841
893
|
}
|
|
@@ -916,7 +968,7 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
|
|
|
916
968
|
return 2;
|
|
917
969
|
}
|
|
918
970
|
}
|
|
919
|
-
|
|
971
|
+
writeTo(device) {
|
|
920
972
|
return __async(this, null, function* () {
|
|
921
973
|
yield this.writeString(this.commandWithoutBytes, device);
|
|
922
974
|
yield this.writeBytes(this.bitmap.bytes, device);
|
|
@@ -1097,7 +1149,7 @@ var TSPLDownload = class extends TSPLCommand {
|
|
|
1097
1149
|
get commandString() {
|
|
1098
1150
|
return `DOWNLOAD "${this.fileName}", ${this.data.byteLength},`;
|
|
1099
1151
|
}
|
|
1100
|
-
|
|
1152
|
+
writeTo(device) {
|
|
1101
1153
|
return __async(this, null, function* () {
|
|
1102
1154
|
yield this.writeString(this.commandString, device);
|
|
1103
1155
|
yield this.writeBytes(this.data, device);
|
|
@@ -1281,14 +1333,14 @@ __export(printers_exports, {
|
|
|
1281
1333
|
// src/printers/Printer.ts
|
|
1282
1334
|
var Printer = class {
|
|
1283
1335
|
constructor(device) {
|
|
1284
|
-
this.
|
|
1336
|
+
this.device = device;
|
|
1285
1337
|
}
|
|
1286
1338
|
/**
|
|
1287
1339
|
* Close the printer USB
|
|
1288
1340
|
*/
|
|
1289
1341
|
close() {
|
|
1290
1342
|
return __async(this, null, function* () {
|
|
1291
|
-
yield this.
|
|
1343
|
+
yield this.device.close();
|
|
1292
1344
|
});
|
|
1293
1345
|
}
|
|
1294
1346
|
/**
|
|
@@ -1317,8 +1369,8 @@ var Printer = class {
|
|
|
1317
1369
|
*/
|
|
1318
1370
|
writeCommand(command) {
|
|
1319
1371
|
return __async(this, null, function* () {
|
|
1320
|
-
if (!this.
|
|
1321
|
-
yield command.
|
|
1372
|
+
if (!this.device.opened) yield this.device.openAndConfigure();
|
|
1373
|
+
yield command.writeTo(this.device);
|
|
1322
1374
|
});
|
|
1323
1375
|
}
|
|
1324
1376
|
/**
|
|
@@ -1486,8 +1538,214 @@ var UsbDevice = class {
|
|
|
1486
1538
|
}
|
|
1487
1539
|
};
|
|
1488
1540
|
|
|
1541
|
+
// src/helpers/NetworkDevice.ts
|
|
1542
|
+
var unsupportedNetworkError = "network-unsupported";
|
|
1543
|
+
var stringHelper2 = new StringUtils();
|
|
1544
|
+
var getNet = () => {
|
|
1545
|
+
if (typeof window !== "undefined") {
|
|
1546
|
+
throw unsupportedNetworkError;
|
|
1547
|
+
}
|
|
1548
|
+
return eval("require")("net");
|
|
1549
|
+
};
|
|
1550
|
+
var NetworkDevice = class {
|
|
1551
|
+
/**
|
|
1552
|
+
* Create a TCP-based device.
|
|
1553
|
+
*
|
|
1554
|
+
* This is intended for raw printing ports (typically 9100). It is Node-only.
|
|
1555
|
+
*
|
|
1556
|
+
* @param host Hostname or IP
|
|
1557
|
+
* @param port TCP port (defaults to 9100)
|
|
1558
|
+
* @param connectTimeoutMs Connection timeout
|
|
1559
|
+
* @param readTimeoutMs Read timeout used by `readData`/`readString`
|
|
1560
|
+
*/
|
|
1561
|
+
constructor(host, port = 9100, connectTimeoutMs = 2e3, readTimeoutMs = 500) {
|
|
1562
|
+
this.host = host;
|
|
1563
|
+
this.port = port;
|
|
1564
|
+
this.connectTimeoutMs = connectTimeoutMs;
|
|
1565
|
+
this.readTimeoutMs = readTimeoutMs;
|
|
1566
|
+
}
|
|
1567
|
+
get opened() {
|
|
1568
|
+
return !!this.socket;
|
|
1569
|
+
}
|
|
1570
|
+
openAndConfigure() {
|
|
1571
|
+
return __async(this, null, function* () {
|
|
1572
|
+
if (this.socket) return;
|
|
1573
|
+
const net = getNet();
|
|
1574
|
+
yield new Promise((resolve, reject) => {
|
|
1575
|
+
let settled = false;
|
|
1576
|
+
const timeout = setTimeout(() => {
|
|
1577
|
+
var _a;
|
|
1578
|
+
if (settled) return;
|
|
1579
|
+
settled = true;
|
|
1580
|
+
try {
|
|
1581
|
+
(_a = this.socket) == null ? void 0 : _a.destroy();
|
|
1582
|
+
} catch (_e) {
|
|
1583
|
+
}
|
|
1584
|
+
this.socket = void 0;
|
|
1585
|
+
reject(new Error("network-connect-timeout"));
|
|
1586
|
+
}, this.connectTimeoutMs);
|
|
1587
|
+
try {
|
|
1588
|
+
const socket = net.createConnection({ host: this.host, port: this.port }, () => {
|
|
1589
|
+
if (settled) return;
|
|
1590
|
+
settled = true;
|
|
1591
|
+
clearTimeout(timeout);
|
|
1592
|
+
resolve();
|
|
1593
|
+
});
|
|
1594
|
+
socket.once("error", (err) => {
|
|
1595
|
+
if (settled) return;
|
|
1596
|
+
settled = true;
|
|
1597
|
+
clearTimeout(timeout);
|
|
1598
|
+
this.socket = void 0;
|
|
1599
|
+
reject(err);
|
|
1600
|
+
});
|
|
1601
|
+
this.socket = socket;
|
|
1602
|
+
} catch (e) {
|
|
1603
|
+
if (settled) return;
|
|
1604
|
+
settled = true;
|
|
1605
|
+
clearTimeout(timeout);
|
|
1606
|
+
this.socket = void 0;
|
|
1607
|
+
reject(e);
|
|
1608
|
+
}
|
|
1609
|
+
});
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
close() {
|
|
1613
|
+
return __async(this, null, function* () {
|
|
1614
|
+
if (!this.socket) return;
|
|
1615
|
+
const socket = this.socket;
|
|
1616
|
+
this.socket = void 0;
|
|
1617
|
+
try {
|
|
1618
|
+
socket.end();
|
|
1619
|
+
} catch (_e) {
|
|
1620
|
+
try {
|
|
1621
|
+
socket.destroy();
|
|
1622
|
+
} catch (_e2) {
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
writeData(data) {
|
|
1628
|
+
return __async(this, null, function* () {
|
|
1629
|
+
if (!this.socket) {
|
|
1630
|
+
throw new Error("network-not-open");
|
|
1631
|
+
}
|
|
1632
|
+
yield new Promise((resolve, reject) => {
|
|
1633
|
+
try {
|
|
1634
|
+
this.socket.write(data, (err) => {
|
|
1635
|
+
if (err) reject(err);
|
|
1636
|
+
else resolve();
|
|
1637
|
+
});
|
|
1638
|
+
} catch (e) {
|
|
1639
|
+
reject(e);
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
writeString(text) {
|
|
1645
|
+
return __async(this, null, function* () {
|
|
1646
|
+
const bytes = stringHelper2.toUTF8Array(text);
|
|
1647
|
+
yield this.writeData(bytes);
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1650
|
+
readData(length) {
|
|
1651
|
+
return __async(this, null, function* () {
|
|
1652
|
+
if (!this.socket) {
|
|
1653
|
+
throw new Error("network-not-open");
|
|
1654
|
+
}
|
|
1655
|
+
const socket = this.socket;
|
|
1656
|
+
const buffer2 = yield new Promise((resolve, reject) => {
|
|
1657
|
+
let settled = false;
|
|
1658
|
+
const onData = (data) => {
|
|
1659
|
+
if (settled) return;
|
|
1660
|
+
settled = true;
|
|
1661
|
+
cleanup();
|
|
1662
|
+
resolve(data);
|
|
1663
|
+
};
|
|
1664
|
+
const onError = (err) => {
|
|
1665
|
+
if (settled) return;
|
|
1666
|
+
settled = true;
|
|
1667
|
+
cleanup();
|
|
1668
|
+
reject(err);
|
|
1669
|
+
};
|
|
1670
|
+
const cleanup = () => {
|
|
1671
|
+
clearTimeout(timeout);
|
|
1672
|
+
socket.removeListener("data", onData);
|
|
1673
|
+
socket.removeListener("error", onError);
|
|
1674
|
+
};
|
|
1675
|
+
const timeout = setTimeout(() => {
|
|
1676
|
+
if (settled) return;
|
|
1677
|
+
settled = true;
|
|
1678
|
+
cleanup();
|
|
1679
|
+
resolve(void 0);
|
|
1680
|
+
}, this.readTimeoutMs);
|
|
1681
|
+
socket.once("data", onData);
|
|
1682
|
+
socket.once("error", onError);
|
|
1683
|
+
});
|
|
1684
|
+
if (!buffer2) return void 0;
|
|
1685
|
+
if (buffer2.byteLength > length) return void 0;
|
|
1686
|
+
return new DataView(buffer2.buffer.slice(buffer2.byteOffset, buffer2.byteOffset + buffer2.byteLength));
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
readString(length) {
|
|
1690
|
+
return __async(this, null, function* () {
|
|
1691
|
+
const bytes = yield this.readData(length);
|
|
1692
|
+
if (bytes) return stringHelper2.toString(bytes);
|
|
1693
|
+
return void 0;
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
|
|
1698
|
+
// src/helpers/BonjourUtils.ts
|
|
1699
|
+
var unsupportedBonjourError = "bonjour-unsupported";
|
|
1700
|
+
var getBonjour = () => {
|
|
1701
|
+
var _a;
|
|
1702
|
+
if (typeof window !== "undefined") {
|
|
1703
|
+
throw unsupportedBonjourError;
|
|
1704
|
+
}
|
|
1705
|
+
const mod = eval("require")("bonjour");
|
|
1706
|
+
const factory = mod && ((_a = mod.default) != null ? _a : mod);
|
|
1707
|
+
if (typeof factory !== "function") {
|
|
1708
|
+
throw new Error("bonjour-invalid-module");
|
|
1709
|
+
}
|
|
1710
|
+
return factory;
|
|
1711
|
+
};
|
|
1712
|
+
var discoverBonjourServices = (types, timeoutMs = 1500) => __async(null, null, function* () {
|
|
1713
|
+
if (typeof window !== "undefined") return [];
|
|
1714
|
+
const factory2 = getBonjour();
|
|
1715
|
+
const bonjour = factory2();
|
|
1716
|
+
try {
|
|
1717
|
+
const results = [];
|
|
1718
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1719
|
+
const browsers = types.map((type) => {
|
|
1720
|
+
return bonjour.find({ type }, (service) => {
|
|
1721
|
+
var _a;
|
|
1722
|
+
const host = ((_a = service == null ? void 0 : service.referer) == null ? void 0 : _a.address) || (service == null ? void 0 : service.host);
|
|
1723
|
+
const port = service == null ? void 0 : service.port;
|
|
1724
|
+
if (!host || !port) return;
|
|
1725
|
+
const key = `${host}:${port}`;
|
|
1726
|
+
if (seen.has(key)) return;
|
|
1727
|
+
seen.add(key);
|
|
1728
|
+
results.push({ host, port, name: service == null ? void 0 : service.name, type });
|
|
1729
|
+
});
|
|
1730
|
+
});
|
|
1731
|
+
yield new Promise((resolve) => setTimeout(resolve, timeoutMs));
|
|
1732
|
+
for (const browser of browsers) {
|
|
1733
|
+
try {
|
|
1734
|
+
browser.stop();
|
|
1735
|
+
} catch (_e) {
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
return results;
|
|
1739
|
+
} finally {
|
|
1740
|
+
try {
|
|
1741
|
+
bonjour.destroy();
|
|
1742
|
+
} catch (_e) {
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
|
|
1489
1747
|
// src/printers/TSPLPrinter.ts
|
|
1490
|
-
var TSPLPrinter = class extends Printer {
|
|
1748
|
+
var TSPLPrinter = class _TSPLPrinter extends Printer {
|
|
1491
1749
|
get language() {
|
|
1492
1750
|
return "tspl";
|
|
1493
1751
|
}
|
|
@@ -1501,12 +1759,152 @@ var TSPLPrinter = class extends Printer {
|
|
|
1501
1759
|
return __async(this, null, function* () {
|
|
1502
1760
|
if (!device.opened) yield device.openAndConfigure();
|
|
1503
1761
|
const testCommand = new TSPLRawCommand("~!I");
|
|
1504
|
-
yield testCommand.
|
|
1762
|
+
yield testCommand.writeTo(device);
|
|
1505
1763
|
const response = yield device.readString(64);
|
|
1506
1764
|
yield device.close();
|
|
1507
1765
|
return !!response;
|
|
1508
1766
|
});
|
|
1509
1767
|
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Discover TSPL-capable printers on the local network.
|
|
1770
|
+
*
|
|
1771
|
+
* Strategy:
|
|
1772
|
+
* - Use Bonjour/mDNS to discover "printer-ish" services to obtain a set of candidate hosts.
|
|
1773
|
+
* - For each unique host, probe TCP/9100 by sending the TSPL identify command (~!I).
|
|
1774
|
+
* - Only return devices that respond to the TSPL probe.
|
|
1775
|
+
* - If Bonjour yields no candidates (e.g. mDNS is blocked), fall back to a conservative
|
|
1776
|
+
* subnet scan on local private /24 networks (still verified by the same TSPL probe).
|
|
1777
|
+
*/
|
|
1778
|
+
static discoverDevices() {
|
|
1779
|
+
return __async(this, null, function* () {
|
|
1780
|
+
if (typeof window !== "undefined") return [];
|
|
1781
|
+
const services = yield discoverBonjourServices([
|
|
1782
|
+
"pdl-datastream",
|
|
1783
|
+
"printer",
|
|
1784
|
+
"ipp",
|
|
1785
|
+
"ipps"
|
|
1786
|
+
]);
|
|
1787
|
+
let uniqueHosts = Array.from(new Set(services.map((s) => s.host).filter(Boolean)));
|
|
1788
|
+
if (uniqueHosts.length === 0) {
|
|
1789
|
+
uniqueHosts = yield _TSPLPrinter.discoverHostsBySubnetScan();
|
|
1790
|
+
}
|
|
1791
|
+
const candidates = uniqueHosts.map((host) => ({ host, port: 9100 }));
|
|
1792
|
+
const concurrency = 5;
|
|
1793
|
+
const verified = [];
|
|
1794
|
+
for (let i = 0; i < candidates.length; i += concurrency) {
|
|
1795
|
+
const batch = candidates.slice(i, i + concurrency);
|
|
1796
|
+
const results = yield Promise.all(batch.map((c) => __async(null, null, function* () {
|
|
1797
|
+
const device = new NetworkDevice(c.host, c.port, 4e3, 1e3);
|
|
1798
|
+
try {
|
|
1799
|
+
const ok = yield _TSPLPrinter.try(device);
|
|
1800
|
+
return ok ? device : void 0;
|
|
1801
|
+
} catch (_e) {
|
|
1802
|
+
try {
|
|
1803
|
+
yield device.close();
|
|
1804
|
+
} catch (_e2) {
|
|
1805
|
+
}
|
|
1806
|
+
return void 0;
|
|
1807
|
+
}
|
|
1808
|
+
})));
|
|
1809
|
+
verified.push(...results.filter(Boolean));
|
|
1810
|
+
}
|
|
1811
|
+
return verified;
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Fallback discovery mechanism used when Bonjour/mDNS returns no printer candidates.
|
|
1816
|
+
*
|
|
1817
|
+
* It derives local private IPv4 /24 prefixes from the current machine's network interfaces
|
|
1818
|
+
* and probes TCP/9100 using the TSPL identify command.
|
|
1819
|
+
*
|
|
1820
|
+
* The scan is intentionally conservative:
|
|
1821
|
+
* - Limited number of prefixes
|
|
1822
|
+
* - Concurrency limits
|
|
1823
|
+
* - Total time cap
|
|
1824
|
+
* - Early-exit when at least one printer is found
|
|
1825
|
+
*/
|
|
1826
|
+
static discoverHostsBySubnetScan() {
|
|
1827
|
+
return __async(this, null, function* () {
|
|
1828
|
+
var _a, _b, _c;
|
|
1829
|
+
if (typeof window !== "undefined") return [];
|
|
1830
|
+
const req = _TSPLPrinter.getNodeRequire();
|
|
1831
|
+
if (!req) return [];
|
|
1832
|
+
const os = req("os");
|
|
1833
|
+
const networkInterfaces = (_b = (_a = os.networkInterfaces) == null ? void 0 : _a.call(os)) != null ? _b : {};
|
|
1834
|
+
const privatePrefixes = /* @__PURE__ */ new Set();
|
|
1835
|
+
const isPrivateIpv4 = (ip) => {
|
|
1836
|
+
if (ip.startsWith("10.")) return true;
|
|
1837
|
+
if (ip.startsWith("192.168.")) return true;
|
|
1838
|
+
const m = ip.match(/^172\.(\d+)\./);
|
|
1839
|
+
if (m) {
|
|
1840
|
+
const n = Number(m[1]);
|
|
1841
|
+
return n >= 16 && n <= 31;
|
|
1842
|
+
}
|
|
1843
|
+
return false;
|
|
1844
|
+
};
|
|
1845
|
+
for (const key of Object.keys(networkInterfaces)) {
|
|
1846
|
+
const infos = (_c = networkInterfaces[key]) != null ? _c : [];
|
|
1847
|
+
for (const info of infos) {
|
|
1848
|
+
const family = info == null ? void 0 : info.family;
|
|
1849
|
+
const address = info == null ? void 0 : info.address;
|
|
1850
|
+
const internal = info == null ? void 0 : info.internal;
|
|
1851
|
+
if (internal) continue;
|
|
1852
|
+
if (family !== "IPv4") continue;
|
|
1853
|
+
if (typeof address !== "string") continue;
|
|
1854
|
+
if (!isPrivateIpv4(address)) continue;
|
|
1855
|
+
const parts = address.split(".");
|
|
1856
|
+
if (parts.length !== 4) continue;
|
|
1857
|
+
privatePrefixes.add(`${parts[0]}.${parts[1]}.${parts[2]}`);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
const prefixes = Array.from(privatePrefixes).slice(0, 2);
|
|
1861
|
+
if (prefixes.length === 0) return [];
|
|
1862
|
+
const hosts = [];
|
|
1863
|
+
for (const prefix of prefixes) {
|
|
1864
|
+
for (let i = 1; i <= 254; i++) {
|
|
1865
|
+
hosts.push(`${prefix}.${i}`);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
const concurrency = 30;
|
|
1869
|
+
const verifiedHosts = [];
|
|
1870
|
+
const startedAt = Date.now();
|
|
1871
|
+
const maxDurationMs = 15e3;
|
|
1872
|
+
for (let i = 0; i < hosts.length; i += concurrency) {
|
|
1873
|
+
if (Date.now() - startedAt > maxDurationMs) break;
|
|
1874
|
+
if (verifiedHosts.length > 0) break;
|
|
1875
|
+
const batch = hosts.slice(i, i + concurrency);
|
|
1876
|
+
const results = yield Promise.all(batch.map((host) => __async(null, null, function* () {
|
|
1877
|
+
const device = new NetworkDevice(host, 9100, 800, 800);
|
|
1878
|
+
try {
|
|
1879
|
+
const ok = yield _TSPLPrinter.try(device);
|
|
1880
|
+
return ok ? host : void 0;
|
|
1881
|
+
} catch (_e) {
|
|
1882
|
+
try {
|
|
1883
|
+
yield device.close();
|
|
1884
|
+
} catch (_e2) {
|
|
1885
|
+
}
|
|
1886
|
+
return void 0;
|
|
1887
|
+
}
|
|
1888
|
+
})));
|
|
1889
|
+
verifiedHosts.push(...results.filter(Boolean));
|
|
1890
|
+
}
|
|
1891
|
+
return verifiedHosts;
|
|
1892
|
+
});
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* Returns a Node-style `require` function.
|
|
1896
|
+
*
|
|
1897
|
+
* This is used to keep runtime dependencies Node-only while still allowing the library to
|
|
1898
|
+
* be imported/bundled in browser contexts.
|
|
1899
|
+
*
|
|
1900
|
+
* Tests may inject a custom require implementation via `globalThis.__label_printer_require`.
|
|
1901
|
+
*/
|
|
1902
|
+
static getNodeRequire() {
|
|
1903
|
+
if (typeof window !== "undefined") return void 0;
|
|
1904
|
+
const override = globalThis.__label_printer_require;
|
|
1905
|
+
if (typeof override === "function") return override;
|
|
1906
|
+
return eval("require");
|
|
1907
|
+
}
|
|
1510
1908
|
};
|
|
1511
1909
|
|
|
1512
1910
|
// src/printers/PrinterService.ts
|
|
@@ -1531,12 +1929,40 @@ var PrinterService = class _PrinterService {
|
|
|
1531
1929
|
return void 0;
|
|
1532
1930
|
});
|
|
1533
1931
|
}
|
|
1932
|
+
/**
|
|
1933
|
+
* Discover devices using printer-specific discovery hooks.
|
|
1934
|
+
*
|
|
1935
|
+
* Each printer class may optionally implement `static discoverDevices(): Promise<Device[]>`
|
|
1936
|
+
* to find candidates over non-USB transports.
|
|
1937
|
+
*
|
|
1938
|
+
* Candidates returned here are still verified by `printerForDevice` via the printer
|
|
1939
|
+
* class' `try(device)` method.
|
|
1940
|
+
*/
|
|
1941
|
+
static discoverDevices() {
|
|
1942
|
+
return __async(this, null, function* () {
|
|
1943
|
+
const classes = [TSPLPrinter];
|
|
1944
|
+
const discoveryResults = yield Promise.all(classes.map((cls) => __async(null, null, function* () {
|
|
1945
|
+
const discoverer = cls.discoverDevices;
|
|
1946
|
+
if (typeof discoverer === "function") {
|
|
1947
|
+
try {
|
|
1948
|
+
return yield discoverer.call(cls);
|
|
1949
|
+
} catch (_e) {
|
|
1950
|
+
return [];
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
return [];
|
|
1954
|
+
})));
|
|
1955
|
+
return discoveryResults.flat();
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1534
1958
|
/**
|
|
1535
1959
|
* @returns List of available printers
|
|
1536
1960
|
*/
|
|
1537
1961
|
static getPrinters() {
|
|
1538
1962
|
return __async(this, null, function* () {
|
|
1539
|
-
const
|
|
1963
|
+
const usbDevices = yield getDevices();
|
|
1964
|
+
const discoveredDevices = yield _PrinterService.discoverDevices();
|
|
1965
|
+
const devices = [...usbDevices, ...discoveredDevices];
|
|
1540
1966
|
const optionalPrinters = yield Promise.all(devices.map(_PrinterService.printerForDevice));
|
|
1541
1967
|
return optionalPrinters.filter((printer) => !!printer);
|
|
1542
1968
|
});
|