@xdxsoftlogger/pdf-to-printer 1.0.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 artiebits
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,194 @@
1
+ # PDF to Printer
2
+
3
+ [![codecov](https://codecov.io/gh/artiebits/pdf-to-printer/branch/master/graph/badge.svg)](https://codecov.io/gh/artiebits/pdf-to-printer)
4
+ ![npm](https://img.shields.io/npm/dw/pdf-to-printer)
5
+
6
+ Print PDF files and images directly to Windows printers from Node.js or Electron. Works with office printers, label printers (Zebra, Rollo), and network printers alike.
7
+
8
+ ## Features
9
+
10
+ - **Print PDFs and images** to any Windows printer
11
+ - **Precise control** over printing options (pages, orientation, paper size, etc.)
12
+ - **Label printer support** (Rollo, Zebra, and more)
13
+ - **Printer discovery** - list all available printers
14
+ - **Fast and reliable** using SumatraPDF engine
15
+ - **TypeScript support** with full type definitions
16
+ - **Windows only** - for Unix-like systems, see [unix-print](https://github.com/artiebits/unix-print)
17
+
18
+ ## Requirements
19
+
20
+ - **Windows** — for macOS and Linux, use [unix-print](https://github.com/artiebits/unix-print) (same API, same author)
21
+ - Node.js 14 or later
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install pdf-to-printer
27
+ # or
28
+ yarn add pdf-to-printer
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```typescript
34
+ import { print, getPrinters, getDefaultPrinter } from "pdf-to-printer";
35
+
36
+ // Print to default printer
37
+ await print("document.pdf");
38
+
39
+ // Print with options
40
+ await print("document.pdf", {
41
+ printer: "HP LaserJet",
42
+ pages: "1-3",
43
+ copies: 2,
44
+ paperSize: "A4",
45
+ });
46
+
47
+ // List available printers
48
+ const printers = await getPrinters();
49
+ console.log(printers);
50
+
51
+ // Get default printer
52
+ const defaultPrinter = await getDefaultPrinter();
53
+ console.log(defaultPrinter?.name);
54
+ ```
55
+
56
+ ## Common Use Cases
57
+
58
+ **Shipping label printing** — send generated labels directly to a Zebra or Rollo printer in an order fulfillment backend:
59
+
60
+ ```typescript
61
+ await print("label.pdf", {
62
+ printer: "Zebra ZTC ZPL",
63
+ paperSize: "4x6",
64
+ scale: "noscale",
65
+ });
66
+ ```
67
+
68
+ **Invoice and receipt printing** — print from a Node.js server without any user interaction:
69
+
70
+ ```typescript
71
+ await print("invoice.pdf", {
72
+ printer: "Office HP LaserJet",
73
+ silent: true,
74
+ copies: 2,
75
+ side: "duplex",
76
+ });
77
+ ```
78
+
79
+ **Electron desktop app** — paths inside `.asar` archives are handled automatically:
80
+
81
+ ```typescript
82
+ import path from "path";
83
+ import { print } from "pdf-to-printer";
84
+
85
+ await print(path.join(__dirname, "report.pdf"), {
86
+ printer: "Microsoft Print to PDF",
87
+ orientation: "landscape",
88
+ paperSize: "A4",
89
+ });
90
+ ```
91
+
92
+ **Print specific pages only:**
93
+
94
+ ```typescript
95
+ await print("document.pdf", { pages: "1-3,5", subset: "odd" });
96
+ ```
97
+
98
+ ## Support This Project
99
+
100
+ If you rely on this package, please consider supporting it. Maintaining an open source project takes time and your support would be greatly appreciated.
101
+
102
+ <a href="https://www.buymeacoffee.com/artiebits" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 50px !important;width: 207px !important;" ></a>
103
+
104
+ ## API Reference
105
+
106
+ ### `print(pdf, options?)`
107
+
108
+ Prints a PDF file to a printer.
109
+
110
+ **Parameters:**
111
+
112
+ - `pdf` (string): Path to the PDF file to print
113
+ - `options` (PrintOptions, optional): Printing configuration options
114
+
115
+ **Returns:** `Promise<void>`
116
+
117
+ **Throws:** `Error` if the PDF file doesn't exist, the operating system is not supported, or printing fails
118
+
119
+ #### PrintOptions
120
+
121
+ | Option | Type | Description |
122
+ | ---------------- | -------------------------------------------------------- | ------------------------------------------------------------ |
123
+ | `printer` | `string` | Name of the printer to use (default: system default printer) |
124
+ | `pages` | `string` | Pages to print (e.g., "1-3,5" or "1,3,5") |
125
+ | `subset` | `"odd" \| "even"` | Print only odd or even pages |
126
+ | `orientation` | `"portrait" \| "landscape"` | Page orientation |
127
+ | `scale` | `"noscale" \| "shrink" \| "fit"` | Content scaling |
128
+ | `monochrome` | `boolean` | Print in black and white |
129
+ | `side` | `"duplex" \| "duplexshort" \| "duplexlong" \| "simplex"` | Duplex printing mode |
130
+ | `bin` | `string` | Paper tray/bin to use (number or name) |
131
+ | `paperSize` | `string` | Paper size (e.g., "A4", "letter", "legal") |
132
+ | `silent` | `boolean` | Suppress error messages |
133
+ | `printDialog` | `boolean` | Show print dialog instead of printing directly |
134
+ | `sumatraPdfPath` | `string` | Custom path to SumatraPDF executable |
135
+ | `copies` | `number` | Number of copies to print (default: 1) |
136
+ | `paperkind` | `number` | Allow to choose custom paper size by kind |
137
+
138
+ ### `getPrinters()`
139
+
140
+ Gets a list of all available printers on the system.
141
+
142
+ **Returns:** `Promise<Printer[]>`
143
+
144
+ **Throws:** `Error` if the operating system is not supported or if the command fails
145
+
146
+ **Example:**
147
+
148
+ ```typescript
149
+ import { getPrinters } from "pdf-to-printer";
150
+
151
+ const printers = await getPrinters();
152
+ console.log(printers);
153
+ // [
154
+ // { deviceId: "HP_LaserJet", name: "HP LaserJet Pro", paperSizes: ["A4", "Letter"] },
155
+ // { deviceId: "Canon_Pixma", name: "Canon PIXMA", paperSizes: ["A4", "A3"] }
156
+ // ]
157
+ ```
158
+
159
+ ### `getDefaultPrinter()`
160
+
161
+ Gets the default printer information.
162
+
163
+ **Returns:** `Promise<Printer | null>`
164
+
165
+ **Throws:** `Error` if the operating system is not supported or if the command fails
166
+
167
+ **Example:**
168
+
169
+ ```typescript
170
+ import { getDefaultPrinter } from "pdf-to-printer";
171
+
172
+ const defaultPrinter = await getDefaultPrinter();
173
+ if (defaultPrinter) {
174
+ console.log(`Default printer: ${defaultPrinter.name}`);
175
+ console.log(`Device ID: ${defaultPrinter.deviceId}`);
176
+ console.log(`Paper sizes: ${defaultPrinter.paperSizes.join(", ")}`);
177
+ } else {
178
+ console.log("No default printer set");
179
+ }
180
+ ```
181
+
182
+ ### `Printer` Type
183
+
184
+ ```typescript
185
+ type Printer = {
186
+ deviceId: string; // Unique identifier for the printer device
187
+ name: string; // Human-readable name of the printer
188
+ paperSizes: string[]; // Array of supported paper sizes
189
+ };
190
+ ```
191
+
192
+ ## License
193
+
194
+ [MIT](LICENSE)
Binary file
package/dist/bundle.js ADDED
@@ -0,0 +1,2 @@
1
+ !function(e,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var t=n();for(var r in t)("object"==typeof exports?exports:e)[r]=t[r]}}(global,()=>(()=>{"use strict";var e={n:n=>{var t=n&&n.__esModule?()=>n.default:()=>n;return e.d(t,{a:t}),t},d:(n,t)=>{for(var r in t)e.o(t,r)&&!e.o(n,r)&&Object.defineProperty(n,r,{enumerable:!0,get:t[r]})},o:(e,n)=>Object.prototype.hasOwnProperty.call(e,n),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},n={};e.r(n),e.d(n,{getDefaultPrinter:()=>D,getPrinters:()=>b,print:()=>P});const t=require("path");var r=e.n(t);const i=require("fs");var o=e.n(i);const a=require("child_process"),s=require("util"),c=e.n(s)().promisify(a.execFile),u="electron"in process.versions&&process.mainModule&&process.mainModule.filename.includes("app.asar"),p=function(e){return u?e.replace("app.asar","app.asar.unpacked"):e},l=require("os");var d=e.n(l);function f(){if("win32"!==d().platform())throw"Operating System not supported"}var h=function(e,n,t,r){return new(t||(t=Promise))(function(i,o){function a(e){try{c(r.next(e))}catch(e){o(e)}}function s(e){try{c(r.throw(e))}catch(e){o(e)}}function c(e){var n;e.done?i(e.value):(n=e.value,n instanceof t?n:new t(function(e){e(n)})).then(a,s)}c((r=r.apply(e,n||[])).next())})};const m=["odd","even"],v=["portrait","landscape"],y=["noscale","shrink","fit"],w=["duplex","duplexshort","duplexlong","simplex"];function P(e){return h(this,arguments,void 0,function*(e,n={}){if(f(),!e)throw new Error("No PDF specified");if(!o().existsSync(e))throw new Error("No such file");let t=n.sumatraPdfPath||r().join(__dirname,"SumatraPDF-3.4.6-32.exe");n.sumatraPdfPath||(t=p(t));const i=[],{printer:a,silent:s,printDialog:u}=n;u?i.push("-print-dialog"):(a?i.push("-print-to",a):i.push("-print-to-default"),!1!==s&&i.push("-silent"));const l=function(e){const{pages:n,subset:t,orientation:r,scale:i,monochrome:o,side:a,bin:s,paperSize:c,copies:u,paperKind:p}=e,l=[];if(n&&l.push(n),t){if(!m.includes(t))throw new Error(`Invalid subset provided. Valid names: ${m.join(", ")}`);l.push(t)}if(r){if(!v.includes(r))throw new Error(`Invalid orientation provided. Valid names: ${v.join(", ")}`);l.push(r)}if(i){if(!y.includes(i))throw new Error(`Invalid scale provided. Valid names: ${y.join(", ")}`);l.push(i)}if(o?l.push("monochrome"):!1===o&&l.push("color"),a){if(!w.includes(a))throw new Error(`Invalid side provided. Valid names: ${w.join(", ")}`);l.push(a)}return s&&l.push(`bin=${s}`),c&&l.push(`paper=${c}`),p&&l.push(`paperkind=${p}`),u&&l.push(`${u}x`),l}(n);l.length&&i.push("-print-settings",l.join(",")),i.push(e);try{yield c(t,i)}catch(e){throw e}})}const x={DeviceID:"deviceId",Name:"name",PrinterPaperNames:"paperSizes"};function g(e){const n={deviceId:"",name:"",paperSizes:[]};return e.split(/\r?\n/).forEach(e=>{let[t,r]=e.split(":").map(e=>e.trim());r.match(/^{(.*)(\.{3})}$/)&&(r=r.replace("...}","}"));const i=r.match(/^{(.*)}$/);i&&i[1]&&(r=i[1].split(", "));const o=x[t];void 0!==o&&(n[o]=r)}),{isValid:!(!n.deviceId||!n.name),printerData:n}}const b=function(){return e=this,n=void 0,r=function*(){try{f();const{stdout:e}=yield c("Powershell.exe",["-Command","[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-CimInstance Win32_Printer -Property DeviceID,Name,PrinterPaperNames"]);return function(e){const n=[];return e.split(/(\r?\n){2,}/).map(e=>e.trim()).filter(e=>!!e).forEach(e=>{const{isValid:t,printerData:r}=g(e);t&&n.push(r)}),n}(e)}catch(e){throw e}},new((t=void 0)||(t=Promise))(function(i,o){function a(e){try{c(r.next(e))}catch(e){o(e)}}function s(e){try{c(r.throw(e))}catch(e){o(e)}}function c(e){var n;e.done?i(e.value):(n=e.value,n instanceof t?n:new t(function(e){e(n)})).then(a,s)}c((r=r.apply(e,n||[])).next())});var e,n,t,r};const D=function(){return e=this,n=void 0,r=function*(){try{f();const{stdout:e}=yield c("Powershell.exe",["-Command","Get-CimInstance Win32_Printer -Property DeviceID,Name,PrinterPaperNames -Filter Default=true"]),n=e.trim();if(!e)return null;const{isValid:t,printerData:r}=g(n);return t?r:null}catch(e){throw e}},new((t=void 0)||(t=Promise))(function(i,o){function a(e){try{c(r.next(e))}catch(e){o(e)}}function s(e){try{c(r.throw(e))}catch(e){o(e)}}function c(e){var n;e.done?i(e.value):(n=e.value,n instanceof t?n:new t(function(e){e(n)})).then(a,s)}c((r=r.apply(e,n||[])).next())});var e,n,t,r};return n})());
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUFLRixNQUFNLEtBQUtJLElBQUtDLEdBQU9BLEVBQUdDLFFBR2hEMUQsRUFBTTJELE1BQU0scUJBQ2QzRCxFQUFRQSxFQUFNVSxRQUFRLE9BQVEsTUFJaEMsTUFBTWtELEVBQVU1RCxFQUFNMkQsTUFBTSxZQUV4QkMsR0FBV0EsRUFBUSxLQUVyQjVELEVBQVE0RCxFQUFRLEdBQUdSLE1BQU0sT0FHM0IsTUFBTWpFLEVBQU13RCxFQUFXWSxRQUVYTSxJQUFSMUUsSUFHSjZELEVBQVk3RCxHQUFPYSxLQUtkLENBQ0w4RCxXQUhpQmQsRUFBWUMsV0FBWUQsRUFBWUUsTUFJckRGLGNBRUosQ0NHQSxRQS9CQSxXLHFDQW1CRSxJQUNFLElBQ0EsTUFBTSxPQUFFZSxTQUFpQixFQUFjLGlCQUFrQixDQUN2RCxXQUNBLHNJQUVGLE9BeEJGLFNBQXVCQSxHQUNyQixNQUFNQyxFQUFzQixHQWM1QixPQVpBRCxFQUNHWCxNQUFNLGVBQ05JLElBQUtoQyxHQUFZQSxFQUFRa0MsUUFDekJPLE9BQVF6QyxLQUFjQSxHQUN0QjZCLFFBQVM3QixJQUNSLE1BQU0sUUFBRXNDLEVBQU8sWUFBRWQsR0FBZ0JELEVBQWV2QixHQUUzQ3NDLEdBRUxFLEVBQVNyQyxLQUFLcUIsS0FHWGdCLENBQ1QsQ0FRU0UsQ0FBY0gsRUFDdkIsQ0FBRSxNQUFPckIsR0FDUCxNQUFNQSxDQUNSLENBQ0YsRSw0UkNGQSxRQXpCQSxXLHFDQUNFLElBQ0UsSUFFQSxNQUFNLE9BQUVxQixTQUFpQixFQUFjLGlCQUFrQixDQUN2RCxXQUNBLGlHQUdJdkMsRUFBVXVDLEVBQU9MLE9BR3ZCLElBQUtLLEVBQVEsT0FBTyxLQUVwQixNQUFNLFFBQUVELEVBQU8sWUFBRWQsR0FBZ0JELEVBQWV2QixHQUdoRCxPQUFLc0MsRUFFRWQsRUFGYyxJQUd2QixDQUFFLE1BQU9OLEdBQ1AsTUFBTUEsQ0FDUixDQUNGLEUiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci93ZWJwYWNrL3VuaXZlcnNhbE1vZHVsZURlZmluaXRpb24iLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvd2VicGFjay9ydW50aW1lL2NvbXBhdCBnZXQgZGVmYXVsdCBleHBvcnQiLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL0B4ZHhzb2Z0bG9nZ2VyL3BkZi10by1wcmludGVyL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci9leHRlcm5hbCBub2RlLWNvbW1vbmpzIFwicGF0aFwiIiwid2VicGFjazovL0B4ZHhzb2Z0bG9nZ2VyL3BkZi10by1wcmludGVyL2V4dGVybmFsIG5vZGUtY29tbW9uanMgXCJmc1wiIiwid2VicGFjazovL0B4ZHhzb2Z0bG9nZ2VyL3BkZi10by1wcmludGVyL2V4dGVybmFsIG5vZGUtY29tbW9uanMgXCJjaGlsZF9wcm9jZXNzXCIiLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvZXh0ZXJuYWwgbm9kZS1jb21tb25qcyBcInV0aWxcIiIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci8uL3NyYy91dGlscy9leGVjLWZpbGUtYXN5bmMudHMiLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvLi9zcmMvdXRpbHMvZWxlY3Ryb24tdXRpbC50cyIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci9leHRlcm5hbCBub2RlLWNvbW1vbmpzIFwib3NcIiIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci8uL3NyYy91dGlscy90aHJvdy1pZi11bnN1cHBvcnRlZC1vcy50cyIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci8uL3NyYy9wcmludC9wcmludC50cyIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci8uL3NyYy91dGlscy93aW5kb3dzLXByaW50ZXItdmFsaWQudHMiLCJ3ZWJwYWNrOi8vQHhkeHNvZnRsb2dnZXIvcGRmLXRvLXByaW50ZXIvLi9zcmMvZ2V0LXByaW50ZXJzL2dldC1wcmludGVycy50cyIsIndlYnBhY2s6Ly9AeGR4c29mdGxvZ2dlci9wZGYtdG8tcHJpbnRlci8uL3NyYy9nZXQtZGVmYXVsdC1wcmludGVyL2dldC1kZWZhdWx0LXByaW50ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoW10sIGZhY3RvcnkpO1xuXHRlbHNlIHtcblx0XHR2YXIgYSA9IGZhY3RvcnkoKTtcblx0XHRmb3IodmFyIGkgaW4gYSkgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyA/IGV4cG9ydHMgOiByb290KVtpXSA9IGFbaV07XG5cdH1cbn0pKGdsb2JhbCwgKCkgPT4ge1xucmV0dXJuICIsIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJjb25zdCBfX1dFQlBBQ0tfTkFNRVNQQUNFX09CSkVDVF9fID0gcmVxdWlyZShcInBhdGhcIik7IiwiY29uc3QgX19XRUJQQUNLX05BTUVTUEFDRV9PQkpFQ1RfXyA9IHJlcXVpcmUoXCJmc1wiKTsiLCJjb25zdCBfX1dFQlBBQ0tfTkFNRVNQQUNFX09CSkVDVF9fID0gcmVxdWlyZShcImNoaWxkX3Byb2Nlc3NcIik7IiwiY29uc3QgX19XRUJQQUNLX05BTUVTUEFDRV9PQkpFQ1RfXyA9IHJlcXVpcmUoXCJ1dGlsXCIpOyIsImltcG9ydCB7IGV4ZWNGaWxlIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB1dGlsIGZyb20gXCJ1dGlsXCI7XG5cbmNvbnN0IGV4ZWNGaWxlQXN5bmMgPSB1dGlsLnByb21pc2lmeShleGVjRmlsZSk7XG5cbmV4cG9ydCBkZWZhdWx0IGV4ZWNGaWxlQXN5bmM7XG4iLCIvLyBUYWtlbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9zaW5kcmVzb3JodXMvZWxlY3Ryb24tdXRpbC9ibG9iL21hc3Rlci9ub2RlLmpzXG5cbmNvbnN0IGlzRWxlY3Ryb24gPSBcImVsZWN0cm9uXCIgaW4gcHJvY2Vzcy52ZXJzaW9ucztcblxuY29uc3QgaXNVc2luZ0FzYXIgPVxuICBpc0VsZWN0cm9uICYmXG4gIHByb2Nlc3MubWFpbk1vZHVsZSAmJlxuICBwcm9jZXNzLm1haW5Nb2R1bGUuZmlsZW5hbWUuaW5jbHVkZXMoXCJhcHAuYXNhclwiKTtcblxuZnVuY3Rpb24gZml4UGF0aEZvckFzYXJVbnBhY2socGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGlzVXNpbmdBc2FyID8gcGF0aC5yZXBsYWNlKFwiYXBwLmFzYXJcIiwgXCJhcHAuYXNhci51bnBhY2tlZFwiKSA6IHBhdGg7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGZpeFBhdGhGb3JBc2FyVW5wYWNrO1xuIiwiY29uc3QgX19XRUJQQUNLX05BTUVTUEFDRV9PQkpFQ1RfXyA9IHJlcXVpcmUoXCJvc1wiKTsiLCJpbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIHRocm93SWZVbnN1cHBvcnRlZE9zKCkge1xuICBpZiAob3MucGxhdGZvcm0oKSAhPT0gXCJ3aW4zMlwiKSB7XG4gICAgdGhyb3cgXCJPcGVyYXRpbmcgU3lzdGVtIG5vdCBzdXBwb3J0ZWRcIjtcbiAgfVxufVxuIiwiaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBleGVjQXN5bmMgZnJvbSBcIi4uL3V0aWxzL2V4ZWMtZmlsZS1hc3luY1wiO1xuaW1wb3J0IGZpeFBhdGhGb3JBc2FyVW5wYWNrIGZyb20gXCIuLi91dGlscy9lbGVjdHJvbi11dGlsXCI7XG5pbXBvcnQgdGhyb3dJZlVuc3VwcG9ydGVkT3BlcmF0aW5nU3lzdGVtIGZyb20gXCIuLi91dGlscy90aHJvdy1pZi11bnN1cHBvcnRlZC1vc1wiO1xuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgcHJpbnRpbmcgUERGc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFByaW50T3B0aW9ucyB7XG4gIHByaW50ZXI/OiBzdHJpbmc7XG4gIHBhZ2VzPzogc3RyaW5nO1xuICBzdWJzZXQ/OiBcIm9kZFwiIHwgXCJldmVuXCI7XG4gIG9yaWVudGF0aW9uPzogXCJwb3J0cmFpdFwiIHwgXCJsYW5kc2NhcGVcIjtcbiAgc2NhbGU/OiBcIm5vc2NhbGVcIiB8IFwic2hyaW5rXCIgfCBcImZpdFwiO1xuICBtb25vY2hyb21lPzogYm9vbGVhbjtcbiAgc2lkZT86IFwiZHVwbGV4XCIgfCBcImR1cGxleHNob3J0XCIgfCBcImR1cGxleGxvbmdcIiB8IFwic2ltcGxleFwiO1xuICBiaW4/OiBzdHJpbmc7XG4gIHBhcGVyU2l6ZT86IHN0cmluZztcbiAgcGFwZXJLaW5kPzogbnVtYmVyO1xuICBzaWxlbnQ/OiBib29sZWFuO1xuICBwcmludERpYWxvZz86IGJvb2xlYW47XG4gIHN1bWF0cmFQZGZQYXRoPzogc3RyaW5nO1xuICBjb3BpZXM/OiBudW1iZXI7XG59XG5cbmNvbnN0IHZhbGlkU3Vic2V0cyA9IFtcIm9kZFwiLCBcImV2ZW5cIl07XG5jb25zdCB2YWxpZE9yaWVudGF0aW9ucyA9IFtcInBvcnRyYWl0XCIsIFwibGFuZHNjYXBlXCJdO1xuY29uc3QgdmFsaWRTY2FsZXMgPSBbXCJub3NjYWxlXCIsIFwic2hyaW5rXCIsIFwiZml0XCJdO1xuY29uc3QgdmFsaWRTaWRlcyA9IFtcImR1cGxleFwiLCBcImR1cGxleHNob3J0XCIsIFwiZHVwbGV4bG9uZ1wiLCBcInNpbXBsZXhcIl07XG5cbi8qKlxuICogUHJpbnRzIGEgUERGIGZpbGUgdG8gYSBwcmludGVyXG4gKlxuICogQHBhcmFtIHBkZiAtIFBhdGggdG8gdGhlIFBERiBmaWxlIHRvIHByaW50XG4gKiBAcGFyYW0gb3B0aW9ucyAtIFByaW50aW5nIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICogQHJldHVybnMgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gcHJpbnRpbmcgaXMgY29tcGxldGVcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgUERGIGZpbGUgZG9lc24ndCBleGlzdCBvciBwcmludGluZyBmYWlsc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBQcmludCB0byBkZWZhdWx0IHByaW50ZXJcbiAqIGF3YWl0IHByaW50KFwiZG9jdW1lbnQucGRmXCIpO1xuICpcbiAqIC8vIFByaW50IHRvIHNwZWNpZmljIHByaW50ZXIgd2l0aCBvcHRpb25zXG4gKiBhd2FpdCBwcmludChcImRvY3VtZW50LnBkZlwiLCB7XG4gKiAgIHByaW50ZXI6IFwiSFAgTGFzZXJKZXRcIixcbiAqICAgcGFnZXM6IFwiMS0zXCIsXG4gKiAgIGNvcGllczogMixcbiAqICAgcGFwZXJTaXplOiBcIkE0XCJcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHByaW50KFxuICBwZGY6IHN0cmluZyxcbiAgb3B0aW9uczogUHJpbnRPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdGhyb3dJZlVuc3VwcG9ydGVkT3BlcmF0aW5nU3lzdGVtKCk7XG4gIGlmICghcGRmKSB0aHJvdyBuZXcgRXJyb3IoXCJObyBQREYgc3BlY2lmaWVkXCIpO1xuICBpZiAoIWZzLmV4aXN0c1N5bmMocGRmKSkgdGhyb3cgbmV3IEVycm9yKFwiTm8gc3VjaCBmaWxlXCIpO1xuXG4gIGxldCBzdW1hdHJhUGRmID1cbiAgICBvcHRpb25zLnN1bWF0cmFQZGZQYXRoIHx8IHBhdGguam9pbihfX2Rpcm5hbWUsIFwiU3VtYXRyYVBERi0zLjQuNi0zMi5leGVcIik7XG4gIGlmICghb3B0aW9ucy5zdW1hdHJhUGRmUGF0aCkgc3VtYXRyYVBkZiA9IGZpeFBhdGhGb3JBc2FyVW5wYWNrKHN1bWF0cmFQZGYpO1xuXG4gIGNvbnN0IGFyZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3QgeyBwcmludGVyLCBzaWxlbnQsIHByaW50RGlhbG9nIH0gPSBvcHRpb25zO1xuXG4gIGlmIChwcmludERpYWxvZykge1xuICAgIGFyZ3MucHVzaChcIi1wcmludC1kaWFsb2dcIik7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHByaW50ZXIpIHtcbiAgICAgIGFyZ3MucHVzaChcIi1wcmludC10b1wiLCBwcmludGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXJncy5wdXNoKFwiLXByaW50LXRvLWRlZmF1bHRcIik7XG4gICAgfVxuICAgIGlmIChzaWxlbnQgIT09IGZhbHNlKSB7XG4gICAgICBhcmdzLnB1c2goXCItc2lsZW50XCIpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHByaW50U2V0dGluZ3MgPSBnZXRQcmludFNldHRpbmdzKG9wdGlvbnMpO1xuXG4gIGlmIChwcmludFNldHRpbmdzLmxlbmd0aCkge1xuICAgIGFyZ3MucHVzaChcIi1wcmludC1zZXR0aW5nc1wiLCBwcmludFNldHRpbmdzLmpvaW4oXCIsXCIpKTtcbiAgfVxuXG4gIGFyZ3MucHVzaChwZGYpO1xuXG4gIHRyeSB7XG4gICAgYXdhaXQgZXhlY0FzeW5jKHN1bWF0cmFQZGYsIGFyZ3MpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFByaW50U2V0dGluZ3Mob3B0aW9uczogUHJpbnRPcHRpb25zKTogc3RyaW5nW10ge1xuICBjb25zdCB7XG4gICAgcGFnZXMsXG4gICAgc3Vic2V0LFxuICAgIG9yaWVudGF0aW9uLFxuICAgIHNjYWxlLFxuICAgIG1vbm9jaHJvbWUsXG4gICAgc2lkZSxcbiAgICBiaW4sXG4gICAgcGFwZXJTaXplLFxuICAgIGNvcGllcyxcbiAgICBwYXBlcktpbmQsXG4gIH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IHByaW50U2V0dGluZ3MgPSBbXTtcblxuICBpZiAocGFnZXMpIHtcbiAgICBwcmludFNldHRpbmdzLnB1c2gocGFnZXMpO1xuICB9XG5cbiAgaWYgKHN1YnNldCkge1xuICAgIGlmICh2YWxpZFN1YnNldHMuaW5jbHVkZXMoc3Vic2V0KSkge1xuICAgICAgcHJpbnRTZXR0aW5ncy5wdXNoKHN1YnNldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEludmFsaWQgc3Vic2V0IHByb3ZpZGVkLiBWYWxpZCBuYW1lczogJHt2YWxpZFN1YnNldHMuam9pbihcIiwgXCIpfWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChvcmllbnRhdGlvbikge1xuICAgIGlmICh2YWxpZE9yaWVudGF0aW9ucy5pbmNsdWRlcyhvcmllbnRhdGlvbikpIHtcbiAgICAgIHByaW50U2V0dGluZ3MucHVzaChvcmllbnRhdGlvbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEludmFsaWQgb3JpZW50YXRpb24gcHJvdmlkZWQuIFZhbGlkIG5hbWVzOiAke3ZhbGlkT3JpZW50YXRpb25zLmpvaW4oXCIsIFwiKX1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc2NhbGUpIHtcbiAgICBpZiAodmFsaWRTY2FsZXMuaW5jbHVkZXMoc2NhbGUpKSB7XG4gICAgICBwcmludFNldHRpbmdzLnB1c2goc2NhbGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIHNjYWxlIHByb3ZpZGVkLiBWYWxpZCBuYW1lczogJHt2YWxpZFNjYWxlcy5qb2luKFwiLCBcIil9YCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG1vbm9jaHJvbWUpIHtcbiAgICBwcmludFNldHRpbmdzLnB1c2goXCJtb25vY2hyb21lXCIpO1xuICB9IGVsc2UgaWYgKG1vbm9jaHJvbWUgPT09IGZhbHNlKSB7XG4gICAgcHJpbnRTZXR0aW5ncy5wdXNoKFwiY29sb3JcIik7XG4gIH1cblxuICBpZiAoc2lkZSkge1xuICAgIGlmICh2YWxpZFNpZGVzLmluY2x1ZGVzKHNpZGUpKSB7XG4gICAgICBwcmludFNldHRpbmdzLnB1c2goc2lkZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEludmFsaWQgc2lkZSBwcm92aWRlZC4gVmFsaWQgbmFtZXM6ICR7dmFsaWRTaWRlcy5qb2luKFwiLCBcIil9YCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGJpbikge1xuICAgIHByaW50U2V0dGluZ3MucHVzaChgYmluPSR7YmlufWApO1xuICB9XG5cbiAgaWYgKHBhcGVyU2l6ZSkge1xuICAgIHByaW50U2V0dGluZ3MucHVzaChgcGFwZXI9JHtwYXBlclNpemV9YCk7XG4gIH1cblxuICBpZiAocGFwZXJLaW5kKSB7XG4gICAgcHJpbnRTZXR0aW5ncy5wdXNoKGBwYXBlcmtpbmQ9JHtwYXBlcktpbmR9YCk7XG4gIH1cblxuICBpZiAoY29waWVzKSB7XG4gICAgcHJpbnRTZXR0aW5ncy5wdXNoKGAke2NvcGllc314YCk7XG4gIH1cblxuICByZXR1cm4gcHJpbnRTZXR0aW5ncztcbn1cbiIsImltcG9ydCB7IFByaW50ZXIgfSBmcm9tIFwiLi4vaW5kZXhcIjtcblxuLy8gbWFwIHdpbmRvd3MtcHJpbnRlciBrZXkgdG8gZmluYWwgcHJpbnRlckRhdGEga2V5XG5jb25zdCBwcm9wZXJ0aWVzOiB7IFtrZXk6IHN0cmluZ106IGtleW9mIFByaW50ZXIgfSA9IHtcbiAgRGV2aWNlSUQ6IFwiZGV2aWNlSWRcIixcbiAgTmFtZTogXCJuYW1lXCIsXG4gIFByaW50ZXJQYXBlck5hbWVzOiBcInBhcGVyU2l6ZXNcIixcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGlzVmFsaWRQcmludGVyKHByaW50ZXI6IHN0cmluZyk6IHtcbiAgaXNWYWxpZDogYm9vbGVhbjtcbiAgcHJpbnRlckRhdGE6IFByaW50ZXI7XG59IHtcbiAgY29uc3QgcHJpbnRlckRhdGE6IFByaW50ZXIgPSB7XG4gICAgZGV2aWNlSWQ6IFwiXCIsXG4gICAgbmFtZTogXCJcIixcbiAgICBwYXBlclNpemVzOiBbXSxcbiAgfTtcblxuICBwcmludGVyLnNwbGl0KC9cXHI/XFxuLykuZm9yRWFjaCgobGluZSkgPT4ge1xuICAgIGxldCBbbGFiZWwsIHZhbHVlXSA9IGxpbmUuc3BsaXQoXCI6XCIpLm1hcCgoZWwpID0+IGVsLnRyaW0oKSk7XG5cbiAgICAvLyBoYW5kbGUgYXJyYXkgZG90c1xuICAgIGlmICh2YWx1ZS5tYXRjaCgvXnsoLiopKFxcLnszfSl9JC8pKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoXCIuLi59XCIsIFwifVwiKTtcbiAgICB9XG5cbiAgICAvLyBoYW5kbGUgYXJyYXkgcmV0dXJuc1xuICAgIGNvbnN0IG1hdGNoZXMgPSB2YWx1ZS5tYXRjaCgvXnsoLiopfSQvKTtcblxuICAgIGlmIChtYXRjaGVzICYmIG1hdGNoZXNbMV0pIHtcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIHZhbHVlID0gbWF0Y2hlc1sxXS5zcGxpdChcIiwgXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGtleSA9IHByb3BlcnRpZXNbbGFiZWxdO1xuXG4gICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICAvLyBAdHMtaWdub3JlXG4gICAgcHJpbnRlckRhdGFba2V5XSA9IHZhbHVlO1xuICB9KTtcblxuICBjb25zdCBpc1ZhbGlkID0gISEocHJpbnRlckRhdGEuZGV2aWNlSWQgJiYgcHJpbnRlckRhdGEubmFtZSk7XG5cbiAgcmV0dXJuIHtcbiAgICBpc1ZhbGlkLFxuICAgIHByaW50ZXJEYXRhLFxuICB9O1xufVxuIiwiaW1wb3J0IGV4ZWNGaWxlQXN5bmMgZnJvbSBcIi4uL3V0aWxzL2V4ZWMtZmlsZS1hc3luY1wiO1xuaW1wb3J0IGlzVmFsaWRQcmludGVyIGZyb20gXCIuLi91dGlscy93aW5kb3dzLXByaW50ZXItdmFsaWRcIjtcbmltcG9ydCB0aHJvd0lmVW5zdXBwb3J0ZWRPcGVyYXRpbmdTeXN0ZW0gZnJvbSBcIi4uL3V0aWxzL3Rocm93LWlmLXVuc3VwcG9ydGVkLW9zXCI7XG5pbXBvcnQgeyBQcmludGVyIH0gZnJvbSBcIi4uXCI7XG5cbi8qKlxuICogR2V0cyBhIGxpc3Qgb2YgYWxsIGF2YWlsYWJsZSBwcmludGVycyBvbiB0aGUgc3lzdGVtXG4gKlxuICogQHJldHVybnMgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIHByaW50ZXIgb2JqZWN0c1xuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIG5vdCBzdXBwb3J0ZWQgb3IgaWYgdGhlIGNvbW1hbmQgZmFpbHNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcHJpbnRlcnMgPSBhd2FpdCBnZXRQcmludGVycygpO1xuICogY29uc29sZS5sb2cocHJpbnRlcnMpO1xuICogLy8gW1xuICogLy8gICB7IGRldmljZUlkOiBcIkhQX0xhc2VySmV0XCIsIG5hbWU6IFwiSFAgTGFzZXJKZXQgUHJvXCIsIHBhcGVyU2l6ZXM6IFtcIkE0XCIsIFwiTGV0dGVyXCJdIH0sXG4gKiAvLyAgIHsgZGV2aWNlSWQ6IFwiQ2Fub25fUGl4bWFcIiwgbmFtZTogXCJDYW5vbiBQSVhNQVwiLCBwYXBlclNpemVzOiBbXCJBNFwiLCBcIkEzXCJdIH1cbiAqIC8vIF1cbiAqIGBgYFxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRQcmludGVycygpOiBQcm9taXNlPFByaW50ZXJbXT4ge1xuICBmdW5jdGlvbiBzdGRvdXRIYW5kbGVyKHN0ZG91dDogc3RyaW5nKSB7XG4gICAgY29uc3QgcHJpbnRlcnM6IFByaW50ZXJbXSA9IFtdO1xuXG4gICAgc3Rkb3V0XG4gICAgICAuc3BsaXQoLyhcXHI/XFxuKXsyLH0vKVxuICAgICAgLm1hcCgocHJpbnRlcikgPT4gcHJpbnRlci50cmltKCkpXG4gICAgICAuZmlsdGVyKChwcmludGVyKSA9PiAhIXByaW50ZXIpXG4gICAgICAuZm9yRWFjaCgocHJpbnRlcikgPT4ge1xuICAgICAgICBjb25zdCB7IGlzVmFsaWQsIHByaW50ZXJEYXRhIH0gPSBpc1ZhbGlkUHJpbnRlcihwcmludGVyKTtcblxuICAgICAgICBpZiAoIWlzVmFsaWQpIHJldHVybjtcblxuICAgICAgICBwcmludGVycy5wdXNoKHByaW50ZXJEYXRhKTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHByaW50ZXJzO1xuICB9XG5cbiAgdHJ5IHtcbiAgICB0aHJvd0lmVW5zdXBwb3J0ZWRPcGVyYXRpbmdTeXN0ZW0oKTtcbiAgICBjb25zdCB7IHN0ZG91dCB9ID0gYXdhaXQgZXhlY0ZpbGVBc3luYyhcIlBvd2Vyc2hlbGwuZXhlXCIsIFtcbiAgICAgIFwiLUNvbW1hbmRcIixcbiAgICAgIGBbQ29uc29sZV06Ok91dHB1dEVuY29kaW5nID0gW1N5c3RlbS5UZXh0LkVuY29kaW5nXTo6VVRGODsgR2V0LUNpbUluc3RhbmNlIFdpbjMyX1ByaW50ZXIgLVByb3BlcnR5IERldmljZUlELE5hbWUsUHJpbnRlclBhcGVyTmFtZXNgLFxuICAgIF0pO1xuICAgIHJldHVybiBzdGRvdXRIYW5kbGVyKHN0ZG91dCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgZ2V0UHJpbnRlcnM7XG4iLCJpbXBvcnQgZXhlY0ZpbGVBc3luYyBmcm9tIFwiLi4vdXRpbHMvZXhlYy1maWxlLWFzeW5jXCI7XG5pbXBvcnQgdGhyb3dJZlVuc3VwcG9ydGVkT3BlcmF0aW5nU3lzdGVtIGZyb20gXCIuLi91dGlscy90aHJvdy1pZi11bnN1cHBvcnRlZC1vc1wiO1xuaW1wb3J0IGlzVmFsaWRQcmludGVyIGZyb20gXCIuLi91dGlscy93aW5kb3dzLXByaW50ZXItdmFsaWRcIjtcbmltcG9ydCB7IFByaW50ZXIgfSBmcm9tIFwiLi5cIjtcblxuLyoqXG4gKiBHZXRzIHRoZSBkZWZhdWx0IHByaW50ZXIgaW5mb3JtYXRpb25cbiAqXG4gKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGRlZmF1bHQgcHJpbnRlciBvYmplY3QsIG9yIG51bGwgaWYgbm8gZGVmYXVsdCBwcmludGVyIGlzIHNldFxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIG5vdCBzdXBwb3J0ZWQgb3IgaWYgdGhlIGNvbW1hbmQgZmFpbHNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgZGVmYXVsdFByaW50ZXIgPSBhd2FpdCBnZXREZWZhdWx0UHJpbnRlcigpO1xuICogaWYgKGRlZmF1bHRQcmludGVyKSB7XG4gKiAgIGNvbnNvbGUubG9nKGBEZWZhdWx0IHByaW50ZXI6ICR7ZGVmYXVsdFByaW50ZXIubmFtZX1gKTtcbiAqICAgY29uc29sZS5sb2coYERldmljZSBJRDogJHtkZWZhdWx0UHJpbnRlci5kZXZpY2VJZH1gKTtcbiAqICAgY29uc29sZS5sb2coYFBhcGVyIHNpemVzOiAke2RlZmF1bHRQcmludGVyLnBhcGVyU2l6ZXMuam9pbihcIiwgXCIpfWApO1xuICogfSBlbHNlIHtcbiAqICAgY29uc29sZS5sb2coXCJObyBkZWZhdWx0IHByaW50ZXIgc2V0XCIpO1xuICogfVxuICogYGBgXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldERlZmF1bHRQcmludGVyKCk6IFByb21pc2U8UHJpbnRlciB8IG51bGw+IHtcbiAgdHJ5IHtcbiAgICB0aHJvd0lmVW5zdXBwb3J0ZWRPcGVyYXRpbmdTeXN0ZW0oKTtcblxuICAgIGNvbnN0IHsgc3Rkb3V0IH0gPSBhd2FpdCBleGVjRmlsZUFzeW5jKFwiUG93ZXJzaGVsbC5leGVcIiwgW1xuICAgICAgXCItQ29tbWFuZFwiLFxuICAgICAgYEdldC1DaW1JbnN0YW5jZSBXaW4zMl9QcmludGVyIC1Qcm9wZXJ0eSBEZXZpY2VJRCxOYW1lLFByaW50ZXJQYXBlck5hbWVzIC1GaWx0ZXIgRGVmYXVsdD10cnVlYCxcbiAgICBdKTtcblxuICAgIGNvbnN0IHByaW50ZXIgPSBzdGRvdXQudHJpbSgpO1xuXG4gICAgLy8gSWYgc3Rkb3V0IGlzIGVtcHR5LCB0aGVyZSBpcyBubyBkZWZhdWx0IHByaW50ZXJcbiAgICBpZiAoIXN0ZG91dCkgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCB7IGlzVmFsaWQsIHByaW50ZXJEYXRhIH0gPSBpc1ZhbGlkUHJpbnRlcihwcmludGVyKTtcblxuICAgIC8vIERldmljZUlEIG9yIE5hbWUgbm90IGZvdW5kXG4gICAgaWYgKCFpc1ZhbGlkKSByZXR1cm4gbnVsbDtcblxuICAgIHJldHVybiBwcmludGVyRGF0YTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBnZXREZWZhdWx0UHJpbnRlcjtcbiJdLCJuYW1lcyI6WyJyb290IiwiZmFjdG9yeSIsImV4cG9ydHMiLCJtb2R1bGUiLCJkZWZpbmUiLCJhbWQiLCJhIiwiaSIsImdsb2JhbCIsIl9fd2VicGFja19yZXF1aXJlX18iLCJnZXR0ZXIiLCJfX2VzTW9kdWxlIiwiZCIsImRlZmluaXRpb24iLCJrZXkiLCJvIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwiZ2V0Iiwib2JqIiwicHJvcCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIlN5bWJvbCIsInRvU3RyaW5nVGFnIiwidmFsdWUiLCJyZXF1aXJlIiwiZXhlY0ZpbGUiLCJpc1VzaW5nQXNhciIsInByb2Nlc3MiLCJ2ZXJzaW9ucyIsIm1haW5Nb2R1bGUiLCJmaWxlbmFtZSIsImluY2x1ZGVzIiwicGF0aCIsInJlcGxhY2UiLCJ0aHJvd0lmVW5zdXBwb3J0ZWRPcyIsInZhbGlkU3Vic2V0cyIsInZhbGlkT3JpZW50YXRpb25zIiwidmFsaWRTY2FsZXMiLCJ2YWxpZFNpZGVzIiwicHJpbnQiLCJwZGYiLCJvcHRpb25zIiwiRXJyb3IiLCJzdW1hdHJhUGRmIiwic3VtYXRyYVBkZlBhdGgiLCJfX2Rpcm5hbWUiLCJhcmdzIiwicHJpbnRlciIsInNpbGVudCIsInByaW50RGlhbG9nIiwicHVzaCIsInByaW50U2V0dGluZ3MiLCJwYWdlcyIsInN1YnNldCIsIm9yaWVudGF0aW9uIiwic2NhbGUiLCJtb25vY2hyb21lIiwic2lkZSIsImJpbiIsInBhcGVyU2l6ZSIsImNvcGllcyIsInBhcGVyS2luZCIsImpvaW4iLCJnZXRQcmludFNldHRpbmdzIiwibGVuZ3RoIiwiZXJyb3IiLCJwcm9wZXJ0aWVzIiwiRGV2aWNlSUQiLCJOYW1lIiwiUHJpbnRlclBhcGVyTmFtZXMiLCJpc1ZhbGlkUHJpbnRlciIsInByaW50ZXJEYXRhIiwiZGV2aWNlSWQiLCJuYW1lIiwicGFwZXJTaXplcyIsInNwbGl0IiwiZm9yRWFjaCIsImxpbmUiLCJsYWJlbCIsIm1hcCIsImVsIiwidHJpbSIsIm1hdGNoIiwibWF0Y2hlcyIsInVuZGVmaW5lZCIsImlzVmFsaWQiLCJzdGRvdXQiLCJwcmludGVycyIsImZpbHRlciIsInN0ZG91dEhhbmRsZXIiXSwic291cmNlUm9vdCI6IiJ9
@@ -0,0 +1,21 @@
1
+ import { Printer } from "..";
2
+ /**
3
+ * Gets the default printer information
4
+ *
5
+ * @returns Promise that resolves to the default printer object, or null if no default printer is set
6
+ * @throws {Error} If the operating system is not supported or if the command fails
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const defaultPrinter = await getDefaultPrinter();
11
+ * if (defaultPrinter) {
12
+ * console.log(`Default printer: ${defaultPrinter.name}`);
13
+ * console.log(`Device ID: ${defaultPrinter.deviceId}`);
14
+ * console.log(`Paper sizes: ${defaultPrinter.paperSizes.join(", ")}`);
15
+ * } else {
16
+ * console.log("No default printer set");
17
+ * }
18
+ * ```
19
+ */
20
+ declare function getDefaultPrinter(): Promise<Printer | null>;
21
+ export default getDefaultPrinter;
@@ -0,0 +1,19 @@
1
+ import { Printer } from "..";
2
+ /**
3
+ * Gets a list of all available printers on the system
4
+ *
5
+ * @returns Promise that resolves to an array of printer objects
6
+ * @throws {Error} If the operating system is not supported or if the command fails
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const printers = await getPrinters();
11
+ * console.log(printers);
12
+ * // [
13
+ * // { deviceId: "HP_LaserJet", name: "HP LaserJet Pro", paperSizes: ["A4", "Letter"] },
14
+ * // { deviceId: "Canon_Pixma", name: "Canon PIXMA", paperSizes: ["A4", "A3"] }
15
+ * // ]
16
+ * ```
17
+ */
18
+ declare function getPrinters(): Promise<Printer[]>;
19
+ export default getPrinters;
@@ -0,0 +1,15 @@
1
+ export { default as print } from "./print/print";
2
+ export { default as getPrinters } from "./get-printers/get-printers";
3
+ export { default as getDefaultPrinter } from "./get-default-printer/get-default-printer";
4
+ export { PrintOptions } from "./print/print";
5
+ /**
6
+ * Represents a printer device
7
+ */
8
+ export type Printer = {
9
+ /** Unique identifier for the printer device */
10
+ deviceId: string;
11
+ /** Human-readable name of the printer */
12
+ name: string;
13
+ /** Array of supported paper sizes */
14
+ paperSizes: string[];
15
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Configuration options for printing PDFs
3
+ */
4
+ export interface PrintOptions {
5
+ printer?: string;
6
+ pages?: string;
7
+ subset?: "odd" | "even";
8
+ orientation?: "portrait" | "landscape";
9
+ scale?: "noscale" | "shrink" | "fit";
10
+ monochrome?: boolean;
11
+ side?: "duplex" | "duplexshort" | "duplexlong" | "simplex";
12
+ bin?: string;
13
+ paperSize?: string;
14
+ paperKind?: number;
15
+ silent?: boolean;
16
+ printDialog?: boolean;
17
+ sumatraPdfPath?: string;
18
+ copies?: number;
19
+ }
20
+ /**
21
+ * Prints a PDF file to a printer
22
+ *
23
+ * @param pdf - Path to the PDF file to print
24
+ * @param options - Printing configuration options
25
+ * @returns Promise that resolves when printing is complete
26
+ * @throws {Error} If the PDF file doesn't exist or printing fails
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Print to default printer
31
+ * await print("document.pdf");
32
+ *
33
+ * // Print to specific printer with options
34
+ * await print("document.pdf", {
35
+ * printer: "HP LaserJet",
36
+ * pages: "1-3",
37
+ * copies: 2,
38
+ * paperSize: "A4"
39
+ * });
40
+ * ```
41
+ */
42
+ export default function print(pdf: string, options?: PrintOptions): Promise<void>;
@@ -0,0 +1,2 @@
1
+ declare function fixPathForAsarUnpack(path: string): string;
2
+ export default fixPathForAsarUnpack;
@@ -0,0 +1,3 @@
1
+ import { execFile } from "child_process";
2
+ declare const execFileAsync: typeof execFile.__promisify__;
3
+ export default execFileAsync;
@@ -0,0 +1 @@
1
+ export default function throwIfUnsupportedOs(): void;
@@ -0,0 +1,5 @@
1
+ import { Printer } from "../index";
2
+ export default function isValidPrinter(printer: string): {
3
+ isValid: boolean;
4
+ printerData: Printer;
5
+ };
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@xdxsoftlogger/pdf-to-printer",
3
+ "version": "1.0.0",
4
+ "description": "Print PDF files and images to Windows printers from Node.js and Electron. Supports Zebra, Rollo, and other label printers with duplex, paper size, tray selection, and silent printing.",
5
+ "license": "MIT",
6
+ "author": "xdxsoftlogger",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/1logger1/pdf-to-printer"
10
+ },
11
+ "main": "dist/bundle.js",
12
+ "types": "dist/index.d.ts",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "test": "jest",
18
+ "lint": "prettier --write .",
19
+ "build": "webpack --config webpack.production.config.js",
20
+ "prepare": "npm run lint && npm run test && npm run build"
21
+ },
22
+ "husky": {
23
+ "hooks": {
24
+ "pre-commit": "lint-staged"
25
+ }
26
+ },
27
+ "lint-staged": {
28
+ "src/**/*.{js,ts,json,md}": [
29
+ "prettier --write"
30
+ ]
31
+ },
32
+ "devDependencies": {
33
+ "@babel/cli": "^7.28.3",
34
+ "@babel/core": "^7.28.4",
35
+ "@babel/preset-env": "^7.28.3",
36
+ "@babel/preset-typescript": "^7.27.1",
37
+ "@types/jest": "^30.0.0",
38
+ "@types/node": "^25.0.3",
39
+ "babel-jest": "^30.2.0",
40
+ "clean-webpack-plugin": "^4.0.0",
41
+ "copy-webpack-plugin": "^13.0.1",
42
+ "husky": "^9.1.7",
43
+ "jest": "^30.2.0",
44
+ "jest-mock": "^30.2.0",
45
+ "lint-staged": "^16.2.3",
46
+ "prettier": "^3.6.2",
47
+ "ts-jest": "^29.4.4",
48
+ "ts-loader": "^9.5.1",
49
+ "typescript": "^5.9.2",
50
+ "webpack": "^5.97.1",
51
+ "webpack-cli": "^6.0.1"
52
+ },
53
+ "keywords": [
54
+ "pdf",
55
+ "printer",
56
+ "pdf-printer",
57
+ "print-pdf",
58
+ "zebra-printer",
59
+ "rollo-printer",
60
+ "label-printer",
61
+ "thermal-printer",
62
+ "shipping-label",
63
+ "silent-print",
64
+ "node.js",
65
+ "nodejs-printer",
66
+ "electron",
67
+ "electron-print",
68
+ "windows",
69
+ "win32",
70
+ "invoice-printing",
71
+ "sumatra"
72
+ ]
73
+ }