@esslassi/electron-printer 0.0.7 → 0.0.9

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/src/print.cpp CHANGED
@@ -1,353 +1,353 @@
1
- #include <napi.h>
2
- #include <fstream>
3
- #include <vector>
4
- #include <memory>
5
- #include <functional>
6
-
7
- #include "printer_factory.h"
8
- #include "printer_interface.h"
9
-
10
- static std::unique_ptr<PrinterInterface> P()
11
- {
12
- return PrinterFactory::Create();
13
- }
14
-
15
- /* =========================================================
16
- JS Converters
17
- ========================================================= */
18
-
19
- static Napi::Object JsPrinterDetails(Napi::Env env, const PrinterDetailsNative &p)
20
- {
21
- Napi::Object o = Napi::Object::New(env);
22
- o.Set("name", p.name);
23
- o.Set("isDefault", p.isDefault);
24
-
25
- Napi::Object opts = Napi::Object::New(env);
26
- for (auto &kv : p.options)
27
- opts.Set(kv.first, kv.second);
28
-
29
- o.Set("options", opts);
30
- return o;
31
- }
32
-
33
- static Napi::Object JsDriverOptions(Napi::Env env, const DriverOptions &opts)
34
- {
35
- Napi::Object out = Napi::Object::New(env);
36
- for (auto &group : opts)
37
- {
38
- Napi::Object choices = Napi::Object::New(env);
39
- for (auto &choice : group.second)
40
- choices.Set(choice.first, Napi::Boolean::New(env, choice.second));
41
- out.Set(group.first, choices);
42
- }
43
- return out;
44
- }
45
-
46
- static Napi::Object JsJobDetails(Napi::Env env, const JobDetailsNative &j)
47
- {
48
- Napi::Object o = Napi::Object::New(env);
49
- o.Set("id", j.id);
50
- o.Set("name", j.name);
51
- o.Set("printerName", j.printerName);
52
- o.Set("user", j.user);
53
- o.Set("format", j.format);
54
- o.Set("priority", j.priority);
55
- o.Set("size", j.size);
56
-
57
- Napi::Array st = Napi::Array::New(env, j.status.size());
58
- for (size_t i = 0; i < j.status.size(); i++)
59
- st.Set((uint32_t)i, j.status[i]);
60
- o.Set("status", st);
61
-
62
- o.Set("completedTime", Napi::Date::New(env, (double)j.completedTime * 1000.0));
63
- o.Set("creationTime", Napi::Date::New(env, (double)j.creationTime * 1000.0));
64
- o.Set("processingTime", Napi::Date::New(env, (double)j.processingTime * 1000.0));
65
-
66
- return o;
67
- }
68
-
69
- /* =========================================================
70
- Sync Methods
71
- ========================================================= */
72
-
73
- Napi::Value getPrinters(const Napi::CallbackInfo &info)
74
- {
75
- auto env = info.Env();
76
- auto printer = P();
77
- auto list = printer->GetPrinters();
78
-
79
- Napi::Array arr = Napi::Array::New(env, list.size());
80
- for (size_t i = 0; i < list.size(); i++)
81
- arr.Set((uint32_t)i, JsPrinterDetails(env, list[i]));
82
-
83
- return arr;
84
- }
85
-
86
- Napi::Value getPrinter(const Napi::CallbackInfo &info)
87
- {
88
- auto env = info.Env();
89
- if (info.Length() < 1 || !info[0].IsString())
90
- Napi::TypeError::New(env, "printerName required").ThrowAsJavaScriptException();
91
-
92
- auto printer = P();
93
- auto p = printer->GetPrinter(info[0].As<Napi::String>().Utf8Value());
94
- return JsPrinterDetails(env, p);
95
- }
96
-
97
- Napi::Value getPrinterDriverOptions(const Napi::CallbackInfo &info)
98
- {
99
- auto env = info.Env();
100
- if (info.Length() < 1 || !info[0].IsString())
101
- Napi::TypeError::New(env, "printerName required").ThrowAsJavaScriptException();
102
-
103
- auto printer = P();
104
- auto opts = printer->GetPrinterDriverOptions(info[0].As<Napi::String>().Utf8Value());
105
- return JsDriverOptions(env, opts);
106
- }
107
-
108
- Napi::Value getSelectedPaperSize(const Napi::CallbackInfo &info)
109
- {
110
- auto env = info.Env();
111
- if (info.Length() < 1 || !info[0].IsString())
112
- Napi::TypeError::New(env, "printerName required").ThrowAsJavaScriptException();
113
-
114
- auto printer = P();
115
- auto ps = printer->GetSelectedPaperSize(info[0].As<Napi::String>().Utf8Value());
116
- return Napi::String::New(env, ps);
117
- }
118
-
119
- Napi::Value getDefaultPrinterName(const Napi::CallbackInfo &info)
120
- {
121
- auto env = info.Env();
122
- auto printer = P();
123
- auto name = printer->GetDefaultPrinterName();
124
- if (name.empty())
125
- return env.Undefined();
126
- return Napi::String::New(env, name);
127
- }
128
-
129
- Napi::Value getSupportedPrintFormats(const Napi::CallbackInfo &info)
130
- {
131
- auto env = info.Env();
132
- auto printer = P();
133
- auto formats = printer->GetSupportedPrintFormats();
134
-
135
- Napi::Array arr = Napi::Array::New(env, formats.size());
136
- for (size_t i = 0; i < formats.size(); i++)
137
- arr.Set((uint32_t)i, formats[i]);
138
-
139
- return arr;
140
- }
141
-
142
- Napi::Value getSupportedJobCommands(const Napi::CallbackInfo &info)
143
- {
144
- auto env = info.Env();
145
- auto printer = P();
146
- auto cmds = printer->GetSupportedJobCommands();
147
-
148
- Napi::Array arr = Napi::Array::New(env, cmds.size());
149
- for (size_t i = 0; i < cmds.size(); i++)
150
- arr.Set((uint32_t)i, cmds[i]);
151
-
152
- return arr;
153
- }
154
-
155
- Napi::Value getJob(const Napi::CallbackInfo &info)
156
- {
157
- auto env = info.Env();
158
- if (info.Length() < 2 || !info[0].IsString() || !info[1].IsNumber())
159
- Napi::TypeError::New(env, "getJob(printerName, jobId)").ThrowAsJavaScriptException();
160
-
161
- auto printer = P();
162
- auto job = printer->GetJob(
163
- info[0].As<Napi::String>().Utf8Value(),
164
- info[1].As<Napi::Number>().Int32Value());
165
-
166
- return JsJobDetails(env, job);
167
- }
168
-
169
- Napi::Value setJob(const Napi::CallbackInfo &info)
170
- {
171
- auto env = info.Env();
172
- if (info.Length() < 3 || !info[0].IsString() || !info[1].IsNumber() || !info[2].IsString())
173
- Napi::TypeError::New(env, "setJob(printerName, jobId, command)").ThrowAsJavaScriptException();
174
-
175
- auto printer = P();
176
- printer->SetJob(
177
- info[0].As<Napi::String>().Utf8Value(),
178
- info[1].As<Napi::Number>().Int32Value(),
179
- info[2].As<Napi::String>().Utf8Value());
180
-
181
- return env.Undefined();
182
- }
183
-
184
- /* =========================================================
185
- Async Print Worker
186
- ========================================================= */
187
-
188
- class PrintWorker : public Napi::AsyncWorker
189
- {
190
- public:
191
- PrintWorker(
192
- Napi::Function successCb,
193
- Napi::Function errorCb,
194
- std::function<int()> workFn)
195
- : Napi::AsyncWorker(successCb),
196
- successRef(Napi::Persistent(successCb)),
197
- errorRef(Napi::Persistent(errorCb)),
198
- work(workFn)
199
- {}
200
-
201
- void Execute() override
202
- {
203
- try
204
- {
205
- jobId = work();
206
- if (jobId <= 0)
207
- SetError("Print failed");
208
- }
209
- catch (...)
210
- {
211
- SetError("Print failed (exception)");
212
- }
213
- }
214
-
215
- void OnOK() override
216
- {
217
- Napi::HandleScope scope(Env());
218
- successRef.Call({ Napi::String::New(Env(), std::to_string(jobId)) });
219
- }
220
-
221
- void OnError(const Napi::Error &e) override
222
- {
223
- Napi::HandleScope scope(Env());
224
- errorRef.Call({ e.Value() });
225
- }
226
-
227
- private:
228
- Napi::FunctionReference successRef;
229
- Napi::FunctionReference errorRef;
230
- std::function<int()> work;
231
- int jobId = 0;
232
- };
233
-
234
- static Napi::Function SafeCb(Napi::Env env, Napi::Object opt, const char *key)
235
- {
236
- if (opt.Has(key) && opt.Get(key).IsFunction())
237
- return opt.Get(key).As<Napi::Function>();
238
-
239
- return Napi::Function::New(env, [](const Napi::CallbackInfo &) {});
240
- }
241
-
242
- /* =========================================================
243
- printDirect
244
- ========================================================= */
245
-
246
- Napi::Value printDirect(const Napi::CallbackInfo &info)
247
- {
248
- auto env = info.Env();
249
-
250
- if (info.Length() < 1 || !info[0].IsObject())
251
- Napi::TypeError::New(env, "options object required").ThrowAsJavaScriptException();
252
-
253
- Napi::Object opt = info[0].As<Napi::Object>();
254
-
255
- if (!opt.Has("data"))
256
- Napi::TypeError::New(env, "options.data required").ThrowAsJavaScriptException();
257
-
258
- std::string printerName;
259
- if (opt.Has("printer") && opt.Get("printer").IsString())
260
- printerName = opt.Get("printer").As<Napi::String>().Utf8Value();
261
-
262
- std::string type = "RAW";
263
- if (opt.Has("type") && opt.Get("type").IsString())
264
- type = opt.Get("type").As<Napi::String>().Utf8Value();
265
-
266
- StringMap driverOpts;
267
- if (opt.Has("options") && opt.Get("options").IsObject())
268
- {
269
- Napi::Object o = opt.Get("options").As<Napi::Object>();
270
- auto props = o.GetPropertyNames();
271
- for (uint32_t i = 0; i < props.Length(); i++)
272
- {
273
- auto k = props.Get(i).As<Napi::String>().Utf8Value();
274
- auto v = o.Get(k).ToString().Utf8Value();
275
- driverOpts[k] = v;
276
- }
277
- }
278
-
279
- std::vector<uint8_t> data;
280
- auto d = opt.Get("data");
281
-
282
- if (d.IsBuffer())
283
- {
284
- auto b = d.As<Napi::Buffer<uint8_t>>();
285
- data.assign(b.Data(), b.Data() + b.Length());
286
- }
287
- else
288
- {
289
- auto s = d.ToString().Utf8Value();
290
- data.assign(s.begin(), s.end());
291
- }
292
-
293
- auto successCb = SafeCb(env, opt, "success");
294
- auto errorCb = SafeCb(env, opt, "error");
295
-
296
- auto worker = new PrintWorker(
297
- successCb,
298
- errorCb,
299
- [printerName, data, type, driverOpts]() -> int
300
- {
301
- auto printer = P();
302
- std::string usePrinter = printerName.empty()
303
- ? printer->GetDefaultPrinterName()
304
- : printerName;
305
-
306
- return printer->PrintDirect(usePrinter, data, type, driverOpts);
307
- });
308
-
309
- worker->Queue();
310
- return env.Undefined();
311
- }
312
-
313
- /* =========================================================
314
- printFile
315
- ========================================================= */
316
-
317
- Napi::Value printFile(const Napi::CallbackInfo &info)
318
- {
319
- auto env = info.Env();
320
-
321
- if (info.Length() < 1 || !info[0].IsObject())
322
- Napi::TypeError::New(env, "options object required").ThrowAsJavaScriptException();
323
-
324
- Napi::Object opt = info[0].As<Napi::Object>();
325
-
326
- if (!opt.Has("filename") || !opt.Get("filename").IsString())
327
- Napi::TypeError::New(env, "options.filename required").ThrowAsJavaScriptException();
328
-
329
- std::string filename = opt.Get("filename").As<Napi::String>().Utf8Value();
330
-
331
- std::string printerName;
332
- if (opt.Has("printer") && opt.Get("printer").IsString())
333
- printerName = opt.Get("printer").As<Napi::String>().Utf8Value();
334
-
335
- auto successCb = SafeCb(env, opt, "success");
336
- auto errorCb = SafeCb(env, opt, "error");
337
-
338
- auto worker = new PrintWorker(
339
- successCb,
340
- errorCb,
341
- [printerName, filename]() -> int
342
- {
343
- auto printer = P();
344
- std::string usePrinter = printerName.empty()
345
- ? printer->GetDefaultPrinterName()
346
- : printerName;
347
-
348
- return printer->PrintFile(usePrinter, filename);
349
- });
350
-
351
- worker->Queue();
352
- return env.Undefined();
1
+ #include <napi.h>
2
+ #include <fstream>
3
+ #include <vector>
4
+ #include <memory>
5
+ #include <functional>
6
+
7
+ #include "printer_factory.h"
8
+ #include "printer_interface.h"
9
+
10
+ static std::unique_ptr<PrinterInterface> P()
11
+ {
12
+ return PrinterFactory::Create();
13
+ }
14
+
15
+ /* =========================================================
16
+ JS Converters
17
+ ========================================================= */
18
+
19
+ static Napi::Object JsPrinterDetails(Napi::Env env, const PrinterDetailsNative &p)
20
+ {
21
+ Napi::Object o = Napi::Object::New(env);
22
+ o.Set("name", p.name);
23
+ o.Set("isDefault", p.isDefault);
24
+
25
+ Napi::Object opts = Napi::Object::New(env);
26
+ for (auto &kv : p.options)
27
+ opts.Set(kv.first, kv.second);
28
+
29
+ o.Set("options", opts);
30
+ return o;
31
+ }
32
+
33
+ static Napi::Object JsDriverOptions(Napi::Env env, const DriverOptions &opts)
34
+ {
35
+ Napi::Object out = Napi::Object::New(env);
36
+ for (auto &group : opts)
37
+ {
38
+ Napi::Object choices = Napi::Object::New(env);
39
+ for (auto &choice : group.second)
40
+ choices.Set(choice.first, Napi::Boolean::New(env, choice.second));
41
+ out.Set(group.first, choices);
42
+ }
43
+ return out;
44
+ }
45
+
46
+ static Napi::Object JsJobDetails(Napi::Env env, const JobDetailsNative &j)
47
+ {
48
+ Napi::Object o = Napi::Object::New(env);
49
+ o.Set("id", j.id);
50
+ o.Set("name", j.name);
51
+ o.Set("printerName", j.printerName);
52
+ o.Set("user", j.user);
53
+ o.Set("format", j.format);
54
+ o.Set("priority", j.priority);
55
+ o.Set("size", j.size);
56
+
57
+ Napi::Array st = Napi::Array::New(env, j.status.size());
58
+ for (size_t i = 0; i < j.status.size(); i++)
59
+ st.Set((uint32_t)i, j.status[i]);
60
+ o.Set("status", st);
61
+
62
+ o.Set("completedTime", Napi::Date::New(env, (double)j.completedTime * 1000.0));
63
+ o.Set("creationTime", Napi::Date::New(env, (double)j.creationTime * 1000.0));
64
+ o.Set("processingTime", Napi::Date::New(env, (double)j.processingTime * 1000.0));
65
+
66
+ return o;
67
+ }
68
+
69
+ /* =========================================================
70
+ Sync Methods
71
+ ========================================================= */
72
+
73
+ Napi::Value getPrinters(const Napi::CallbackInfo &info)
74
+ {
75
+ auto env = info.Env();
76
+ auto printer = P();
77
+ auto list = printer->GetPrinters();
78
+
79
+ Napi::Array arr = Napi::Array::New(env, list.size());
80
+ for (size_t i = 0; i < list.size(); i++)
81
+ arr.Set((uint32_t)i, JsPrinterDetails(env, list[i]));
82
+
83
+ return arr;
84
+ }
85
+
86
+ Napi::Value getPrinter(const Napi::CallbackInfo &info)
87
+ {
88
+ auto env = info.Env();
89
+ if (info.Length() < 1 || !info[0].IsString())
90
+ Napi::TypeError::New(env, "printerName required").ThrowAsJavaScriptException();
91
+
92
+ auto printer = P();
93
+ auto p = printer->GetPrinter(info[0].As<Napi::String>().Utf8Value());
94
+ return JsPrinterDetails(env, p);
95
+ }
96
+
97
+ Napi::Value getPrinterDriverOptions(const Napi::CallbackInfo &info)
98
+ {
99
+ auto env = info.Env();
100
+ if (info.Length() < 1 || !info[0].IsString())
101
+ Napi::TypeError::New(env, "printerName required").ThrowAsJavaScriptException();
102
+
103
+ auto printer = P();
104
+ auto opts = printer->GetPrinterDriverOptions(info[0].As<Napi::String>().Utf8Value());
105
+ return JsDriverOptions(env, opts);
106
+ }
107
+
108
+ Napi::Value getSelectedPaperSize(const Napi::CallbackInfo &info)
109
+ {
110
+ auto env = info.Env();
111
+ if (info.Length() < 1 || !info[0].IsString())
112
+ Napi::TypeError::New(env, "printerName required").ThrowAsJavaScriptException();
113
+
114
+ auto printer = P();
115
+ auto ps = printer->GetSelectedPaperSize(info[0].As<Napi::String>().Utf8Value());
116
+ return Napi::String::New(env, ps);
117
+ }
118
+
119
+ Napi::Value getDefaultPrinterName(const Napi::CallbackInfo &info)
120
+ {
121
+ auto env = info.Env();
122
+ auto printer = P();
123
+ auto name = printer->GetDefaultPrinterName();
124
+ if (name.empty())
125
+ return env.Undefined();
126
+ return Napi::String::New(env, name);
127
+ }
128
+
129
+ Napi::Value getSupportedPrintFormats(const Napi::CallbackInfo &info)
130
+ {
131
+ auto env = info.Env();
132
+ auto printer = P();
133
+ auto formats = printer->GetSupportedPrintFormats();
134
+
135
+ Napi::Array arr = Napi::Array::New(env, formats.size());
136
+ for (size_t i = 0; i < formats.size(); i++)
137
+ arr.Set((uint32_t)i, formats[i]);
138
+
139
+ return arr;
140
+ }
141
+
142
+ Napi::Value getSupportedJobCommands(const Napi::CallbackInfo &info)
143
+ {
144
+ auto env = info.Env();
145
+ auto printer = P();
146
+ auto cmds = printer->GetSupportedJobCommands();
147
+
148
+ Napi::Array arr = Napi::Array::New(env, cmds.size());
149
+ for (size_t i = 0; i < cmds.size(); i++)
150
+ arr.Set((uint32_t)i, cmds[i]);
151
+
152
+ return arr;
153
+ }
154
+
155
+ Napi::Value getJob(const Napi::CallbackInfo &info)
156
+ {
157
+ auto env = info.Env();
158
+ if (info.Length() < 2 || !info[0].IsString() || !info[1].IsNumber())
159
+ Napi::TypeError::New(env, "getJob(printerName, jobId)").ThrowAsJavaScriptException();
160
+
161
+ auto printer = P();
162
+ auto job = printer->GetJob(
163
+ info[0].As<Napi::String>().Utf8Value(),
164
+ info[1].As<Napi::Number>().Int32Value());
165
+
166
+ return JsJobDetails(env, job);
167
+ }
168
+
169
+ Napi::Value setJob(const Napi::CallbackInfo &info)
170
+ {
171
+ auto env = info.Env();
172
+ if (info.Length() < 3 || !info[0].IsString() || !info[1].IsNumber() || !info[2].IsString())
173
+ Napi::TypeError::New(env, "setJob(printerName, jobId, command)").ThrowAsJavaScriptException();
174
+
175
+ auto printer = P();
176
+ printer->SetJob(
177
+ info[0].As<Napi::String>().Utf8Value(),
178
+ info[1].As<Napi::Number>().Int32Value(),
179
+ info[2].As<Napi::String>().Utf8Value());
180
+
181
+ return env.Undefined();
182
+ }
183
+
184
+ /* =========================================================
185
+ Async Print Worker
186
+ ========================================================= */
187
+
188
+ class PrintWorker : public Napi::AsyncWorker
189
+ {
190
+ public:
191
+ PrintWorker(
192
+ Napi::Function successCb,
193
+ Napi::Function errorCb,
194
+ std::function<int()> workFn)
195
+ : Napi::AsyncWorker(successCb),
196
+ successRef(Napi::Persistent(successCb)),
197
+ errorRef(Napi::Persistent(errorCb)),
198
+ work(workFn)
199
+ {}
200
+
201
+ void Execute() override
202
+ {
203
+ try
204
+ {
205
+ jobId = work();
206
+ if (jobId <= 0)
207
+ SetError("Print failed");
208
+ }
209
+ catch (...)
210
+ {
211
+ SetError("Print failed (exception)");
212
+ }
213
+ }
214
+
215
+ void OnOK() override
216
+ {
217
+ Napi::HandleScope scope(Env());
218
+ successRef.Call({ Napi::String::New(Env(), std::to_string(jobId)) });
219
+ }
220
+
221
+ void OnError(const Napi::Error &e) override
222
+ {
223
+ Napi::HandleScope scope(Env());
224
+ errorRef.Call({ e.Value() });
225
+ }
226
+
227
+ private:
228
+ Napi::FunctionReference successRef;
229
+ Napi::FunctionReference errorRef;
230
+ std::function<int()> work;
231
+ int jobId = 0;
232
+ };
233
+
234
+ static Napi::Function SafeCb(Napi::Env env, Napi::Object opt, const char *key)
235
+ {
236
+ if (opt.Has(key) && opt.Get(key).IsFunction())
237
+ return opt.Get(key).As<Napi::Function>();
238
+
239
+ return Napi::Function::New(env, [](const Napi::CallbackInfo &) {});
240
+ }
241
+
242
+ /* =========================================================
243
+ printDirect
244
+ ========================================================= */
245
+
246
+ Napi::Value printDirect(const Napi::CallbackInfo &info)
247
+ {
248
+ auto env = info.Env();
249
+
250
+ if (info.Length() < 1 || !info[0].IsObject())
251
+ Napi::TypeError::New(env, "options object required").ThrowAsJavaScriptException();
252
+
253
+ Napi::Object opt = info[0].As<Napi::Object>();
254
+
255
+ if (!opt.Has("data"))
256
+ Napi::TypeError::New(env, "options.data required").ThrowAsJavaScriptException();
257
+
258
+ std::string printerName;
259
+ if (opt.Has("printer") && opt.Get("printer").IsString())
260
+ printerName = opt.Get("printer").As<Napi::String>().Utf8Value();
261
+
262
+ std::string type = "RAW";
263
+ if (opt.Has("type") && opt.Get("type").IsString())
264
+ type = opt.Get("type").As<Napi::String>().Utf8Value();
265
+
266
+ StringMap driverOpts;
267
+ if (opt.Has("options") && opt.Get("options").IsObject())
268
+ {
269
+ Napi::Object o = opt.Get("options").As<Napi::Object>();
270
+ auto props = o.GetPropertyNames();
271
+ for (uint32_t i = 0; i < props.Length(); i++)
272
+ {
273
+ auto k = props.Get(i).As<Napi::String>().Utf8Value();
274
+ auto v = o.Get(k).ToString().Utf8Value();
275
+ driverOpts[k] = v;
276
+ }
277
+ }
278
+
279
+ std::vector<uint8_t> data;
280
+ auto d = opt.Get("data");
281
+
282
+ if (d.IsBuffer())
283
+ {
284
+ auto b = d.As<Napi::Buffer<uint8_t>>();
285
+ data.assign(b.Data(), b.Data() + b.Length());
286
+ }
287
+ else
288
+ {
289
+ auto s = d.ToString().Utf8Value();
290
+ data.assign(s.begin(), s.end());
291
+ }
292
+
293
+ auto successCb = SafeCb(env, opt, "success");
294
+ auto errorCb = SafeCb(env, opt, "error");
295
+
296
+ auto worker = new PrintWorker(
297
+ successCb,
298
+ errorCb,
299
+ [printerName, data, type, driverOpts]() -> int
300
+ {
301
+ auto printer = P();
302
+ std::string usePrinter = printerName.empty()
303
+ ? printer->GetDefaultPrinterName()
304
+ : printerName;
305
+
306
+ return printer->PrintDirect(usePrinter, data, type, driverOpts);
307
+ });
308
+
309
+ worker->Queue();
310
+ return env.Undefined();
311
+ }
312
+
313
+ /* =========================================================
314
+ printFile
315
+ ========================================================= */
316
+
317
+ Napi::Value printFile(const Napi::CallbackInfo &info)
318
+ {
319
+ auto env = info.Env();
320
+
321
+ if (info.Length() < 1 || !info[0].IsObject())
322
+ Napi::TypeError::New(env, "options object required").ThrowAsJavaScriptException();
323
+
324
+ Napi::Object opt = info[0].As<Napi::Object>();
325
+
326
+ if (!opt.Has("filename") || !opt.Get("filename").IsString())
327
+ Napi::TypeError::New(env, "options.filename required").ThrowAsJavaScriptException();
328
+
329
+ std::string filename = opt.Get("filename").As<Napi::String>().Utf8Value();
330
+
331
+ std::string printerName;
332
+ if (opt.Has("printer") && opt.Get("printer").IsString())
333
+ printerName = opt.Get("printer").As<Napi::String>().Utf8Value();
334
+
335
+ auto successCb = SafeCb(env, opt, "success");
336
+ auto errorCb = SafeCb(env, opt, "error");
337
+
338
+ auto worker = new PrintWorker(
339
+ successCb,
340
+ errorCb,
341
+ [printerName, filename]() -> int
342
+ {
343
+ auto printer = P();
344
+ std::string usePrinter = printerName.empty()
345
+ ? printer->GetDefaultPrinterName()
346
+ : printerName;
347
+
348
+ return printer->PrintFile(usePrinter, filename);
349
+ });
350
+
351
+ worker->Queue();
352
+ return env.Undefined();
353
353
  }