@esslassi/electron-printer 0.0.6 → 0.0.8

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.
@@ -1,49 +1,15 @@
1
1
  #include "windows_printer.h"
2
+
2
3
  #include <vector>
4
+ #include <string>
5
+ #include <map>
6
+ #include <fstream>
7
+ #include <sstream>
8
+ #include <algorithm>
3
9
 
4
- std::string WindowsPrinter::GetPrinterStatus(DWORD status)
5
- {
6
- if (status & PRINTER_STATUS_OFFLINE)
7
- return "offline";
8
- if (status & PRINTER_STATUS_ERROR)
9
- return "error";
10
- if (status & PRINTER_STATUS_PAPER_JAM)
11
- return "paper-jam";
12
- if (status & PRINTER_STATUS_PAPER_OUT)
13
- return "paper-out";
14
- if (status & PRINTER_STATUS_MANUAL_FEED)
15
- return "manual-feed";
16
- if (status & PRINTER_STATUS_PAPER_PROBLEM)
17
- return "paper-problem";
18
- if (status & PRINTER_STATUS_BUSY)
19
- return "busy";
20
- if (status & PRINTER_STATUS_PRINTING)
21
- return "printing";
22
- if (status & PRINTER_STATUS_OUTPUT_BIN_FULL)
23
- return "output-bin-full";
24
- if (status & PRINTER_STATUS_NOT_AVAILABLE)
25
- return "not-available";
26
- if (status & PRINTER_STATUS_WAITING)
27
- return "waiting";
28
- if (status & PRINTER_STATUS_PROCESSING)
29
- return "processing";
30
- if (status & PRINTER_STATUS_INITIALIZING)
31
- return "initializing";
32
- if (status & PRINTER_STATUS_WARMING_UP)
33
- return "warming-up";
34
- if (status & PRINTER_STATUS_TONER_LOW)
35
- return "toner-low";
36
- if (status & PRINTER_STATUS_NO_TONER)
37
- return "no-toner";
38
- if (status & PRINTER_STATUS_PAGE_PUNT)
39
- return "page-punt";
40
- if (status & PRINTER_STATUS_USER_INTERVENTION)
41
- return "user-intervention";
42
- if (status & PRINTER_STATUS_OUT_OF_MEMORY)
43
- return "out-of-memory";
44
- if (status & PRINTER_STATUS_DOOR_OPEN)
45
- return "door-open";
46
- return "ready";
10
+ static std::string ToUpper(std::string s) {
11
+ std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return (char)std::toupper(c); });
12
+ return s;
47
13
  }
48
14
 
49
15
  std::wstring WindowsPrinter::Utf8ToWide(const std::string &str)
@@ -72,139 +38,310 @@ std::string WindowsPrinter::WideToUtf8(LPWSTR wstr)
72
38
  return std::string(buffer.data());
73
39
  }
74
40
 
75
- PrinterInfo WindowsPrinter::GetPrinterDetails(const std::string &printerName, bool isDefault)
41
+ static std::time_t SystemTimeToTimeT(const SYSTEMTIME &st)
76
42
  {
77
- PrinterInfo info;
78
- info.name = printerName;
79
- info.isDefault = isDefault;
43
+ FILETIME ft;
44
+ if (!SystemTimeToFileTime(&st, &ft)) return 0;
80
45
 
81
- HANDLE hPrinter;
82
- std::wstring wPrinterName = Utf8ToWide(printerName);
46
+ ULARGE_INTEGER ull;
47
+ ull.LowPart = ft.dwLowDateTime;
48
+ ull.HighPart = ft.dwHighDateTime;
83
49
 
84
- if (OpenPrinterW((LPWSTR)wPrinterName.c_str(), &hPrinter, NULL))
85
- {
86
- DWORD needed;
87
- GetPrinterW(hPrinter, 2, NULL, 0, &needed);
88
- if (needed > 0)
89
- {
90
- std::vector<BYTE> buffer(needed);
91
- if (GetPrinterW(hPrinter, 2, buffer.data(), needed, &needed))
92
- {
93
- PRINTER_INFO_2W *pInfo = (PRINTER_INFO_2W *)buffer.data();
94
- info.status = GetPrinterStatus(pInfo->Status);
95
-
96
- if (pInfo->pLocation)
97
- info.details["location"] = WideToUtf8(pInfo->pLocation);
98
- if (pInfo->pComment)
99
- info.details["comment"] = WideToUtf8(pInfo->pComment);
100
- if (pInfo->pDriverName)
101
- info.details["driver"] = WideToUtf8(pInfo->pDriverName);
102
- if (pInfo->pPortName)
103
- info.details["port"] = WideToUtf8(pInfo->pPortName);
104
- }
105
- }
106
- ClosePrinter(hPrinter);
107
- }
50
+ // Windows FILETIME is 100-ns since Jan 1, 1601 (UTC)
51
+ // Convert to Unix epoch (seconds since Jan 1, 1970)
52
+ const unsigned long long EPOCH_DIFFERENCE = 116444736000000000ULL; // 100ns
53
+ if (ull.QuadPart < EPOCH_DIFFERENCE) return 0;
108
54
 
109
- return info;
55
+ unsigned long long unix100ns = ull.QuadPart - EPOCH_DIFFERENCE;
56
+ return (std::time_t)(unix100ns / 10000000ULL);
110
57
  }
111
58
 
112
- std::vector<PrinterInfo> WindowsPrinter::GetPrinters()
59
+ std::vector<std::string> WindowsPrinter::MapJobStatus(DWORD status)
113
60
  {
114
- std::vector<PrinterInfo> printers;
115
- DWORD needed = 0, returned = 0;
61
+ std::vector<std::string> out;
62
+
63
+ if (status & JOB_STATUS_PAUSED) out.push_back("PAUSED");
64
+ if (status & JOB_STATUS_PRINTING) out.push_back("PRINTING");
65
+ if (status & JOB_STATUS_SPOOLING) out.push_back("PENDING");
66
+ if (status & JOB_STATUS_DELETING) out.push_back("CANCELLED");
67
+ if (status & JOB_STATUS_DELETED) out.push_back("CANCELLED");
68
+ if (status & JOB_STATUS_ERROR) out.push_back("ABORTED");
69
+ if (status & JOB_STATUS_OFFLINE) out.push_back("PENDING");
70
+ if (status & JOB_STATUS_PAPEROUT) out.push_back("PENDING");
71
+ if (status & JOB_STATUS_PRINTED) out.push_back("PRINTED");
116
72
 
73
+ if (out.empty()) out.push_back("PENDING");
74
+ return out;
75
+ }
76
+
77
+ static bool ReadAllBytes(const std::string &path, std::vector<uint8_t> &out)
78
+ {
79
+ std::ifstream f(path, std::ios::binary);
80
+ if (!f) return false;
81
+ f.seekg(0, std::ios::end);
82
+ std::streamsize size = f.tellg();
83
+ if (size < 0) return false;
84
+ f.seekg(0, std::ios::beg);
85
+
86
+ out.resize((size_t)size);
87
+ if (size > 0)
88
+ f.read((char*)out.data(), size);
89
+
90
+ return true;
91
+ }
92
+
93
+ std::vector<PrinterDetailsNative> WindowsPrinter::GetPrinters()
94
+ {
95
+ std::vector<PrinterDetailsNative> printers;
96
+
97
+ DWORD needed = 0, returned = 0;
117
98
  EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
118
- if (needed > 0)
99
+ if (needed == 0) return printers;
100
+
101
+ std::vector<BYTE> buffer(needed);
102
+ if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, buffer.data(), needed, &needed, &returned))
103
+ return printers;
104
+
105
+ wchar_t defaultPrinter[512];
106
+ DWORD defaultSize = (DWORD)(sizeof(defaultPrinter) / sizeof(defaultPrinter[0]));
107
+ std::string defaultName;
108
+ if (GetDefaultPrinterW(defaultPrinter, &defaultSize))
109
+ defaultName = WideToUtf8(defaultPrinter);
110
+
111
+ PRINTER_INFO_2W *pInfo = (PRINTER_INFO_2W *)buffer.data();
112
+
113
+ for (DWORD i = 0; i < returned; i++)
119
114
  {
120
- std::vector<BYTE> buffer(needed);
121
- if (EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, buffer.data(), needed, &needed, &returned))
122
- {
123
- PRINTER_INFO_2W *pInfo = (PRINTER_INFO_2W *)buffer.data();
124
- for (DWORD i = 0; i < returned; i++)
125
- {
126
- std::string name = WideToUtf8(pInfo[i].pPrinterName);
127
- bool isDefault = false;
128
-
129
- wchar_t defaultPrinter[256];
130
- DWORD size = sizeof(defaultPrinter) / sizeof(defaultPrinter[0]);
131
- if (GetDefaultPrinterW(defaultPrinter, &size))
132
- {
133
- isDefault = (wcscmp(pInfo[i].pPrinterName, defaultPrinter) == 0);
134
- }
135
-
136
- printers.push_back(GetPrinterDetails(name, isDefault));
137
- }
138
- }
115
+ PrinterDetailsNative p;
116
+ p.name = WideToUtf8(pInfo[i].pPrinterName);
117
+ p.isDefault = (!defaultName.empty() && p.name == defaultName);
118
+
119
+ // options: keep it clean and stable
120
+ if (pInfo[i].pLocation) p.options["location"] = WideToUtf8(pInfo[i].pLocation);
121
+ if (pInfo[i].pComment) p.options["comment"] = WideToUtf8(pInfo[i].pComment);
122
+ if (pInfo[i].pDriverName) p.options["driver"] = WideToUtf8(pInfo[i].pDriverName);
123
+ if (pInfo[i].pPortName) p.options["port"] = WideToUtf8(pInfo[i].pPortName);
124
+
125
+ printers.push_back(std::move(p));
139
126
  }
140
127
 
141
128
  return printers;
142
129
  }
143
130
 
144
- PrinterInfo WindowsPrinter::GetSystemDefaultPrinter()
131
+ PrinterDetailsNative WindowsPrinter::GetPrinter(const std::string &printerName)
145
132
  {
146
- wchar_t printerName[256];
147
- DWORD size = sizeof(printerName) / sizeof(printerName[0]);
133
+ // Build from GetPrinters (stable + consistent)
134
+ auto list = GetPrinters();
135
+ for (auto &p : list)
136
+ {
137
+ if (p.name == printerName) return p;
138
+ }
148
139
 
140
+ PrinterDetailsNative p;
141
+ p.name = printerName;
142
+ p.isDefault = false;
143
+ return p;
144
+ }
145
+
146
+ std::string WindowsPrinter::GetDefaultPrinterName()
147
+ {
148
+ wchar_t printerName[512];
149
+ DWORD size = (DWORD)(sizeof(printerName) / sizeof(printerName[0]));
149
150
  if (GetDefaultPrinterW(printerName, &size))
151
+ return WideToUtf8(printerName);
152
+ return "";
153
+ }
154
+
155
+ DriverOptions WindowsPrinter::GetPrinterDriverOptions(const std::string &printerName)
156
+ {
157
+ // Windows driver option enumeration is complex (DEVMODE / DocumentProperties).
158
+ // For now: return empty, still satisfies your TS typing.
159
+ // You can enhance later with DEVMODE-driven options.
160
+ (void)printerName;
161
+ return DriverOptions{};
162
+ }
163
+
164
+ std::string WindowsPrinter::GetSelectedPaperSize(const std::string &printerName)
165
+ {
166
+ HANDLE hPrinter = NULL;
167
+ std::wstring wName = Utf8ToWide(printerName);
168
+
169
+ if (!OpenPrinterW((LPWSTR)wName.c_str(), &hPrinter, NULL))
170
+ return "";
171
+
172
+ // Query DEVMODE size
173
+ LONG dmSize = DocumentPropertiesW(NULL, hPrinter, (LPWSTR)wName.c_str(), NULL, NULL, 0);
174
+ if (dmSize <= 0)
175
+ {
176
+ ClosePrinter(hPrinter);
177
+ return "";
178
+ }
179
+
180
+ std::vector<BYTE> dmBuffer((size_t)dmSize);
181
+ DEVMODEW *dm = (DEVMODEW *)dmBuffer.data();
182
+
183
+ LONG res = DocumentPropertiesW(NULL, hPrinter, (LPWSTR)wName.c_str(), dm, NULL, DM_OUT_BUFFER);
184
+ if (res != IDOK)
185
+ {
186
+ ClosePrinter(hPrinter);
187
+ return "";
188
+ }
189
+
190
+ std::string paper;
191
+
192
+ if ((dm->dmFields & DM_FORMNAME) && dm->dmFormName[0] != L'\0')
193
+ {
194
+ paper = WideToUtf8(dm->dmFormName);
195
+ }
196
+ else if (dm->dmFields & DM_PAPERSIZE)
150
197
  {
151
- std::string name = WideToUtf8(printerName);
152
- return GetPrinterDetails(name, true);
198
+ // Fallback: return numeric code as string (still useful)
199
+ paper = std::to_string((int)dm->dmPaperSize);
153
200
  }
154
201
 
155
- return PrinterInfo();
202
+ ClosePrinter(hPrinter);
203
+ return paper;
156
204
  }
157
205
 
158
- bool WindowsPrinter::PrintDirect(const std::string &printerName, const std::vector<uint8_t> &data, const std::string &dataType)
206
+ std::vector<std::string> WindowsPrinter::GetSupportedPrintFormats()
159
207
  {
160
- HANDLE hPrinter;
208
+ // On Windows spooler, “RAW” is always safe. PDF/JPEG/PS conversion is not guaranteed without extra pipeline.
209
+ return { "RAW", "TEXT", "COMMAND" };
210
+ }
211
+
212
+ int WindowsPrinter::PrintDirect(const std::string &printerName,
213
+ const std::vector<uint8_t> &data,
214
+ const std::string &type,
215
+ const StringMap &options)
216
+ {
217
+ (void)options;
218
+
219
+ HANDLE hPrinter = NULL;
161
220
  std::wstring wPrinterName = Utf8ToWide(printerName);
162
- std::wstring wDataType = Utf8ToWide(dataType);
163
221
 
164
222
  if (!OpenPrinterW((LPWSTR)wPrinterName.c_str(), &hPrinter, NULL))
165
- {
166
- return false;
167
- }
223
+ return 0;
224
+
225
+ std::string t = ToUpper(type);
226
+ // Windows expects a spool datatype string. For our types:
227
+ // RAW/TEXT/COMMAND => use RAW to send bytes directly.
228
+ std::wstring wDataType = Utf8ToWide("RAW");
168
229
 
169
230
  DOC_INFO_1W docInfo;
170
- wchar_t docName[] = L"Node.js Print Job";
231
+ wchar_t docName[] = L"Node Print Job";
171
232
  docInfo.pDocName = docName;
172
233
  docInfo.pOutputFile = NULL;
173
- docInfo.pDatatype = const_cast<LPWSTR>(wDataType.c_str());
234
+ docInfo.pDatatype = (LPWSTR)wDataType.c_str();
235
+
236
+ DWORD jobId = StartDocPrinterW(hPrinter, 1, (LPBYTE)&docInfo);
237
+ if (jobId == 0)
238
+ {
239
+ ClosePrinter(hPrinter);
240
+ return 0;
241
+ }
174
242
 
175
- if (StartDocPrinterW(hPrinter, 1, (LPBYTE)&docInfo))
243
+ if (!StartPagePrinter(hPrinter))
176
244
  {
177
- if (StartPagePrinter(hPrinter))
178
- {
179
- DWORD bytesWritten;
180
- void *buffer = const_cast<void *>(static_cast<const void *>(data.data()));
181
- if (WritePrinter(hPrinter, buffer, static_cast<DWORD>(data.size()), &bytesWritten))
182
- {
183
- EndPagePrinter(hPrinter);
184
- EndDocPrinter(hPrinter);
185
- ClosePrinter(hPrinter);
186
- return true;
187
- }
188
- }
189
245
  EndDocPrinter(hPrinter);
246
+ ClosePrinter(hPrinter);
247
+ return 0;
248
+ }
249
+
250
+ DWORD bytesWritten = 0;
251
+ BOOL ok = WritePrinter(hPrinter, (LPVOID)data.data(), (DWORD)data.size(), &bytesWritten);
252
+
253
+ EndPagePrinter(hPrinter);
254
+ EndDocPrinter(hPrinter);
255
+ ClosePrinter(hPrinter);
256
+
257
+ if (!ok || bytesWritten != (DWORD)data.size())
258
+ return 0;
259
+
260
+ return (int)jobId;
261
+ }
262
+
263
+ int WindowsPrinter::PrintFile(const std::string &printerName,
264
+ const std::string &filename)
265
+ {
266
+ std::vector<uint8_t> data;
267
+ if (!ReadAllBytes(filename, data))
268
+ return 0;
269
+
270
+ // PrintFile typing does not include type, so we treat it as RAW bytes.
271
+ StringMap emptyOpts;
272
+ return PrintDirect(printerName, data, "RAW", emptyOpts);
273
+ }
274
+
275
+ JobDetailsNative WindowsPrinter::GetJob(const std::string &printerName, int jobId)
276
+ {
277
+ JobDetailsNative j;
278
+ j.id = jobId;
279
+ j.printerName = printerName;
280
+
281
+ HANDLE hPrinter = NULL;
282
+ std::wstring wPrinterName = Utf8ToWide(printerName);
283
+ if (!OpenPrinterW((LPWSTR)wPrinterName.c_str(), &hPrinter, NULL))
284
+ return j;
285
+
286
+ DWORD needed = 0;
287
+ GetJobW(hPrinter, (DWORD)jobId, 2, NULL, 0, &needed);
288
+ if (needed == 0)
289
+ {
290
+ ClosePrinter(hPrinter);
291
+ return j;
292
+ }
293
+
294
+ std::vector<BYTE> buffer(needed);
295
+ if (!GetJobW(hPrinter, (DWORD)jobId, 2, buffer.data(), needed, &needed))
296
+ {
297
+ ClosePrinter(hPrinter);
298
+ return j;
190
299
  }
191
300
 
301
+ JOB_INFO_2W *ji = (JOB_INFO_2W *)buffer.data();
302
+
303
+ j.name = ji->pDocument ? WideToUtf8(ji->pDocument) : "";
304
+ j.user = ji->pUserName ? WideToUtf8(ji->pUserName) : "";
305
+ j.format = "RAW";
306
+ j.priority = (int)ji->Priority;
307
+ j.size = (int)ji->Size;
308
+ j.status = MapJobStatus(ji->Status);
309
+
310
+ // Times
311
+ j.creationTime = SystemTimeToTimeT(ji->Submitted);
312
+ j.processingTime = j.creationTime;
313
+ j.completedTime = 0;
314
+
192
315
  ClosePrinter(hPrinter);
193
- return false;
316
+ return j;
194
317
  }
195
318
 
196
- PrinterInfo WindowsPrinter::GetStatusPrinter(const std::string &printerName)
319
+ void WindowsPrinter::SetJob(const std::string &printerName, int jobId, const std::string &command)
197
320
  {
198
- wchar_t defaultPrinter[256];
199
- DWORD size = sizeof(defaultPrinter) / sizeof(defaultPrinter[0]);
200
- bool isDefault = false;
321
+ HANDLE hPrinter = NULL;
322
+ std::wstring wPrinterName = Utf8ToWide(printerName);
323
+ if (!OpenPrinterW((LPWSTR)wPrinterName.c_str(), &hPrinter, NULL))
324
+ return;
325
+
326
+ std::string cmd = ToUpper(command);
201
327
 
202
- if (GetDefaultPrinterW(defaultPrinter, &size))
328
+ if (cmd == "CANCEL")
329
+ {
330
+ SetJobW(hPrinter, (DWORD)jobId, 0, NULL, JOB_CONTROL_CANCEL);
331
+ }
332
+ else if (cmd == "PAUSE")
333
+ {
334
+ SetJobW(hPrinter, (DWORD)jobId, 0, NULL, JOB_CONTROL_PAUSE);
335
+ }
336
+ else if (cmd == "RESUME")
203
337
  {
204
- std::string defaultPrinterName = WideToUtf8(defaultPrinter);
205
- isDefault = (printerName == defaultPrinterName);
338
+ SetJobW(hPrinter, (DWORD)jobId, 0, NULL, JOB_CONTROL_RESUME);
206
339
  }
207
340
 
208
- PrinterInfo printer = GetPrinterDetails(printerName, isDefault);
209
- return printer;
341
+ ClosePrinter(hPrinter);
210
342
  }
343
+
344
+ std::vector<std::string> WindowsPrinter::GetSupportedJobCommands()
345
+ {
346
+ return { "CANCEL", "PAUSE", "RESUME" };
347
+ }
@@ -1,14 +1,16 @@
1
1
  #ifndef WINDOWS_PRINTER_H
2
2
  #define WINDOWS_PRINTER_H
3
3
 
4
- #define NOMINMAX
4
+ #include "printer_interface.h"
5
+
5
6
  #include <windows.h>
6
7
  #include <winspool.h>
7
- #include <cstdint>
8
- #include "printer_interface.h"
9
- #include <vector>
10
8
 
11
- // Desabilita todas as macros do Windows que podem interferir
9
+ /* Now remove macro pollution */
10
+ #ifdef GetDefaultPrinter
11
+ #undef GetDefaultPrinter
12
+ #endif
13
+
12
14
  #ifdef GetDefaultPrinter
13
15
  #undef GetDefaultPrinter
14
16
  #endif
@@ -17,19 +19,46 @@
17
19
  #undef GetPrinter
18
20
  #endif
19
21
 
22
+ #ifdef GetJob
23
+ #undef GetJob
24
+ #endif
25
+
26
+ #ifdef SetJob
27
+ #undef SetJob
28
+ #endif
29
+
30
+ #include <vector>
31
+ #include <string>
32
+ #include <cstdint>
33
+
20
34
  class WindowsPrinter : public PrinterInterface
21
35
  {
22
36
  private:
23
- std::string GetPrinterStatus(DWORD status);
24
37
  std::wstring Utf8ToWide(const std::string &str);
25
38
  std::string WideToUtf8(LPWSTR wstr);
39
+ std::vector<std::string> MapJobStatus(DWORD status);
26
40
 
27
41
  public:
28
- virtual PrinterInfo GetPrinterDetails(const std::string &printerName, bool isDefault = false) override;
29
- virtual std::vector<PrinterInfo> GetPrinters() override;
30
- virtual PrinterInfo GetSystemDefaultPrinter() override;
31
- virtual bool PrintDirect(const std::string &printerName, const std::vector<uint8_t> &data, const std::string &dataType) override;
32
- virtual PrinterInfo GetStatusPrinter(const std::string &printerName) override;
42
+ std::vector<PrinterDetailsNative> GetPrinters() override;
43
+ PrinterDetailsNative GetPrinter(const std::string &printerName) override;
44
+ std::string GetDefaultPrinterName() override;
45
+
46
+ DriverOptions GetPrinterDriverOptions(const std::string &printerName) override;
47
+ std::string GetSelectedPaperSize(const std::string &printerName) override;
48
+
49
+ int PrintDirect(const std::string &printerName,
50
+ const std::vector<uint8_t> &data,
51
+ const std::string &type,
52
+ const StringMap &options) override;
53
+
54
+ int PrintFile(const std::string &printerName,
55
+ const std::string &filename) override;
56
+
57
+ std::vector<std::string> GetSupportedPrintFormats() override;
58
+
59
+ JobDetailsNative GetJob(const std::string &printerName, int jobId) override;
60
+ void SetJob(const std::string &printerName, int jobId, const std::string &command) override;
61
+ std::vector<std::string> GetSupportedJobCommands() override;
33
62
  };
34
63
 
35
64
  #endif
package/test.js ADDED
@@ -0,0 +1,120 @@
1
+ const printer = require('./lib');
2
+
3
+ async function run() {
4
+ console.log("===== TEST START =====");
5
+
6
+ // -------------------------------------------------
7
+ // 1️⃣ Get printers (sync)
8
+ // -------------------------------------------------
9
+ const printers = printer.getPrinters();
10
+ console.log("Printers:", printers);
11
+
12
+ if (!printers.length) {
13
+ console.log("No printers found. Exiting.");
14
+ return;
15
+ }
16
+
17
+ const defaultPrinter = printer.getDefaultPrinterName();
18
+ console.log("Default printer:", defaultPrinter);
19
+
20
+ const selectedPrinter = defaultPrinter || printers[0].name;
21
+ console.log("Using printer:", selectedPrinter);
22
+
23
+ // -------------------------------------------------
24
+ // 2️⃣ Get single printer
25
+ // -------------------------------------------------
26
+ const printerDetails = printer.getPrinter(selectedPrinter);
27
+ console.log("Printer details:", printerDetails);
28
+
29
+ // -------------------------------------------------
30
+ // 3️⃣ Driver options
31
+ // -------------------------------------------------
32
+ const driverOptions = printer.getPrinterDriverOptions(selectedPrinter);
33
+ console.log("Driver options:", driverOptions);
34
+
35
+ // -------------------------------------------------
36
+ // 4️⃣ Paper size
37
+ // -------------------------------------------------
38
+ const paper = printer.getSelectedPaperSize(selectedPrinter);
39
+ console.log("Selected paper size:", paper);
40
+
41
+ // -------------------------------------------------
42
+ // 5️⃣ Supported formats
43
+ // -------------------------------------------------
44
+ console.log("Supported formats:", printer.getSupportedPrintFormats());
45
+
46
+ // -------------------------------------------------
47
+ // 6️⃣ Supported job commands
48
+ // -------------------------------------------------
49
+ console.log("Supported job commands:", printer.getSupportedJobCommands());
50
+
51
+ // -------------------------------------------------
52
+ // 7️⃣ printDirect (callback version)
53
+ // -------------------------------------------------
54
+ printer.printDirect({
55
+ data: "TEST PRINT FROM CALLBACK\n\n",
56
+ printer: selectedPrinter,
57
+ type: "RAW",
58
+ success: (jobId) => {
59
+ console.log("printDirect success jobId:", jobId);
60
+
61
+ const job = printer.getJob(selectedPrinter, parseInt(jobId));
62
+ console.log("Job details (sync):", job);
63
+
64
+ // Try cancel test (optional)
65
+ // printer.setJob(selectedPrinter, parseInt(jobId), "CANCEL");
66
+ },
67
+ error: (err) => {
68
+ console.error("printDirect error:", err);
69
+ }
70
+ });
71
+
72
+ // -------------------------------------------------
73
+ // 8️⃣ printDirectAsync
74
+ // -------------------------------------------------
75
+ try {
76
+ const jobId = await printer.printDirectAsync({
77
+ data: Buffer.from("TEST PRINT FROM ASYNC\n\n"),
78
+ printer: selectedPrinter,
79
+ type: "RAW"
80
+ });
81
+
82
+ console.log("printDirectAsync jobId:", jobId);
83
+
84
+ const jobAsync = await printer.getJobAsync(selectedPrinter, parseInt(jobId));
85
+ console.log("Job details (async):", jobAsync);
86
+
87
+ } catch (err) {
88
+ console.error("printDirectAsync error:", err);
89
+ }
90
+
91
+ // -------------------------------------------------
92
+ // 9️⃣ printFileAsync
93
+ // -------------------------------------------------
94
+ try {
95
+ const jobId = await printer.printFileAsync({
96
+ filename: "./sample.txt", // make sure this exists
97
+ printer: selectedPrinter
98
+ });
99
+
100
+ console.log("printFileAsync jobId:", jobId);
101
+ } catch (err) {
102
+ console.error("printFileAsync error:", err);
103
+ }
104
+
105
+ // -------------------------------------------------
106
+ // 🔟 getPrintersAsync
107
+ // -------------------------------------------------
108
+ const printersAsync = await printer.getPrintersAsync();
109
+ console.log("Printers (async):", printersAsync);
110
+
111
+ // -------------------------------------------------
112
+ // 11️⃣ getPrinterAsync
113
+ // -------------------------------------------------
114
+ const singlePrinterAsync = await printer.getPrinterAsync(selectedPrinter);
115
+ console.log("Single printer (async):", singlePrinterAsync);
116
+
117
+ console.log("===== TEST END =====");
118
+ }
119
+
120
+ run().catch(console.error);