taro-bluetooth-print 2.1.0 → 2.1.1
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/CHANGELOG.md +40 -6
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1678 -643
- package/dist/index.umd.js +1 -1
- package/dist/types/adapters/BaseAdapter.d.ts +4 -4
- package/dist/types/core/BluetoothPrinter.d.ts +16 -17
- package/dist/types/core/EventEmitter.d.ts +38 -1
- package/dist/types/services/CommandBuilder.d.ts +73 -0
- package/dist/types/services/ConnectionManager.d.ts +53 -0
- package/dist/types/services/PrintJobManager.d.ts +82 -0
- package/dist/types/services/interfaces/index.d.ts +161 -0
- package/dist/types/utils/encoding.d.ts +25 -1
- package/dist/types/utils/logger.d.ts +67 -10
- package/dist/types/utils/platform.d.ts +1 -1
- package/package.json +4 -2
- package/src/adapters/AdapterFactory.ts +4 -4
- package/src/adapters/AlipayAdapter.ts +76 -17
- package/src/adapters/BaiduAdapter.ts +74 -17
- package/src/adapters/BaseAdapter.ts +9 -15
- package/src/adapters/ByteDanceAdapter.ts +78 -17
- package/src/adapters/TaroAdapter.ts +69 -12
- package/src/core/BluetoothPrinter.ts +150 -158
- package/src/core/EventEmitter.ts +114 -8
- package/src/drivers/EscPos.ts +4 -4
- package/src/services/CommandBuilder.ts +135 -0
- package/src/services/ConnectionManager.ts +133 -0
- package/src/services/PrintJobManager.ts +300 -0
- package/src/services/interfaces/index.ts +188 -0
- package/src/types.ts +10 -10
- package/src/utils/encoding.ts +34 -4
- package/src/utils/image.ts +9 -7
- package/src/utils/logger.ts +143 -37
- package/src/utils/platform.ts +27 -13
package/dist/index.es.js
CHANGED
|
@@ -43,6 +43,196 @@ var PrinterState = /* @__PURE__ */ ((PrinterState2) => {
|
|
|
43
43
|
PrinterState2["PAUSED"] = "paused";
|
|
44
44
|
return PrinterState2;
|
|
45
45
|
})(PrinterState || {});
|
|
46
|
+
class EventEmitter {
|
|
47
|
+
constructor() {
|
|
48
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Subscribe to an event
|
|
52
|
+
*
|
|
53
|
+
* @param event - Event name
|
|
54
|
+
* @param handler - Event handler function
|
|
55
|
+
* @returns Unsubscribe function
|
|
56
|
+
*/
|
|
57
|
+
on(event, handler) {
|
|
58
|
+
if (!this.listeners.has(event)) {
|
|
59
|
+
this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
60
|
+
}
|
|
61
|
+
this.listeners.get(event).add(handler);
|
|
62
|
+
return () => this.off(event, handler);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Subscribe to an event, but only for the first occurrence
|
|
66
|
+
*
|
|
67
|
+
* @param event - Event name
|
|
68
|
+
* @param handler - Event handler function
|
|
69
|
+
* @returns Unsubscribe function
|
|
70
|
+
*/
|
|
71
|
+
once(event, handler) {
|
|
72
|
+
const wrappedHandler = (data) => {
|
|
73
|
+
handler(data);
|
|
74
|
+
this.off(event, wrappedHandler);
|
|
75
|
+
};
|
|
76
|
+
return this.on(event, wrappedHandler);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Adds a listener to the beginning of the listeners array for the specified event
|
|
80
|
+
*
|
|
81
|
+
* @param event - Event name
|
|
82
|
+
* @param handler - Event handler function
|
|
83
|
+
* @returns Unsubscribe function
|
|
84
|
+
*/
|
|
85
|
+
prepend(event, handler) {
|
|
86
|
+
if (!this.listeners.has(event)) {
|
|
87
|
+
this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
88
|
+
}
|
|
89
|
+
const existingHandlers = this.listeners.get(event);
|
|
90
|
+
const newHandlers = /* @__PURE__ */ new Set();
|
|
91
|
+
newHandlers.add(handler);
|
|
92
|
+
existingHandlers.forEach((h) => newHandlers.add(h));
|
|
93
|
+
this.listeners.set(event, newHandlers);
|
|
94
|
+
return () => this.off(event, handler);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Adds a one-time listener to the beginning of the listeners array for the specified event
|
|
98
|
+
*
|
|
99
|
+
* @param event - Event name
|
|
100
|
+
* @param handler - Event handler function
|
|
101
|
+
* @returns Unsubscribe function
|
|
102
|
+
*/
|
|
103
|
+
prependOnce(event, handler) {
|
|
104
|
+
const wrappedHandler = (data) => {
|
|
105
|
+
handler(data);
|
|
106
|
+
this.off(event, wrappedHandler);
|
|
107
|
+
};
|
|
108
|
+
return this.prepend(event, wrappedHandler);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Unsubscribe from an event
|
|
112
|
+
*
|
|
113
|
+
* @param event - Event name
|
|
114
|
+
* @param handler - Event handler function to remove
|
|
115
|
+
*/
|
|
116
|
+
off(event, handler) {
|
|
117
|
+
const handlers = this.listeners.get(event);
|
|
118
|
+
if (handlers) {
|
|
119
|
+
handlers.delete(handler);
|
|
120
|
+
if (handlers.size === 0) {
|
|
121
|
+
this.listeners.delete(event);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Emit an event to all subscribers
|
|
127
|
+
*
|
|
128
|
+
* @param event - Event name
|
|
129
|
+
* @param data - Event payload (optional for void events)
|
|
130
|
+
*/
|
|
131
|
+
emit(event, data) {
|
|
132
|
+
const handlers = this.listeners.get(event);
|
|
133
|
+
if (!handlers || handlers.size === 0) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const handlersCopy = new Set(handlers);
|
|
137
|
+
handlersCopy.forEach((handler) => {
|
|
138
|
+
try {
|
|
139
|
+
if (data === void 0 || data === null) {
|
|
140
|
+
handler();
|
|
141
|
+
} else {
|
|
142
|
+
handler(data);
|
|
143
|
+
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(`Error in event handler for "${String(event)}":`, error);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Asynchronously emit an event to all subscribers, waiting for all handlers to complete
|
|
151
|
+
*
|
|
152
|
+
* @param event - Event name
|
|
153
|
+
* @param data - Event payload (optional for void events)
|
|
154
|
+
* @returns Promise that resolves when all handlers have completed
|
|
155
|
+
*/
|
|
156
|
+
emitAsync(event, data) {
|
|
157
|
+
return __async(this, null, function* () {
|
|
158
|
+
const handlers = this.listeners.get(event);
|
|
159
|
+
if (!handlers || handlers.size === 0) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const handlersCopy = new Set(handlers);
|
|
163
|
+
const promises = [];
|
|
164
|
+
handlersCopy.forEach((handler) => {
|
|
165
|
+
promises.push(
|
|
166
|
+
new Promise((resolve) => {
|
|
167
|
+
try {
|
|
168
|
+
if (data === void 0 || data === null) {
|
|
169
|
+
handler();
|
|
170
|
+
} else {
|
|
171
|
+
handler(data);
|
|
172
|
+
}
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error(`Error in event handler for "${String(event)}":`, error);
|
|
175
|
+
} finally {
|
|
176
|
+
resolve();
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
yield Promise.all(promises);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Remove all event listeners
|
|
186
|
+
* @param event - Optional event name to remove all listeners for a specific event
|
|
187
|
+
*/
|
|
188
|
+
removeAllListeners(event) {
|
|
189
|
+
if (event) {
|
|
190
|
+
this.listeners.delete(event);
|
|
191
|
+
} else {
|
|
192
|
+
this.listeners.clear();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get the number of listeners for an event
|
|
197
|
+
*
|
|
198
|
+
* @param event - Event name
|
|
199
|
+
* @returns Number of listeners
|
|
200
|
+
*/
|
|
201
|
+
listenerCount(event) {
|
|
202
|
+
var _a, _b;
|
|
203
|
+
return (_b = (_a = this.listeners.get(event)) == null ? void 0 : _a.size) != null ? _b : 0;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Get all listeners for an event
|
|
207
|
+
*
|
|
208
|
+
* @param event - Event name
|
|
209
|
+
* @returns Array of event handlers
|
|
210
|
+
*/
|
|
211
|
+
getListeners(event) {
|
|
212
|
+
const handlers = this.listeners.get(event);
|
|
213
|
+
if (!handlers) {
|
|
214
|
+
return [];
|
|
215
|
+
}
|
|
216
|
+
return Array.from(handlers);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get all event names that have listeners
|
|
220
|
+
*
|
|
221
|
+
* @returns Array of event names
|
|
222
|
+
*/
|
|
223
|
+
eventNames() {
|
|
224
|
+
return Array.from(this.listeners.keys());
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Check if there are any listeners for an event
|
|
228
|
+
*
|
|
229
|
+
* @param event - Event name
|
|
230
|
+
* @returns True if there are listeners, false otherwise
|
|
231
|
+
*/
|
|
232
|
+
hasListeners(event) {
|
|
233
|
+
return this.listenerCount(event) > 0;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
46
236
|
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
47
237
|
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
48
238
|
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
@@ -52,19 +242,97 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
52
242
|
return LogLevel2;
|
|
53
243
|
})(LogLevel || {});
|
|
54
244
|
const _Logger = class _Logger {
|
|
245
|
+
/**
|
|
246
|
+
* Configures the logger
|
|
247
|
+
*
|
|
248
|
+
* @param config - Configuration options
|
|
249
|
+
*/
|
|
250
|
+
static configure(config) {
|
|
251
|
+
this.config = __spreadValues(__spreadValues({}, this.config), config);
|
|
252
|
+
}
|
|
55
253
|
/**
|
|
56
254
|
* Sets the global log level
|
|
57
255
|
*
|
|
58
256
|
* @param level - Minimum log level to output
|
|
59
257
|
*/
|
|
60
258
|
static setLevel(level) {
|
|
61
|
-
this.level = level;
|
|
259
|
+
this.config.level = level;
|
|
62
260
|
}
|
|
63
261
|
/**
|
|
64
262
|
* Gets the current log level
|
|
65
263
|
*/
|
|
66
264
|
static getLevel() {
|
|
67
|
-
return this.level;
|
|
265
|
+
return this.config.level;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Formats the log prefix
|
|
269
|
+
*/
|
|
270
|
+
static formatPrefix(level, scope) {
|
|
271
|
+
const levelNames = {
|
|
272
|
+
[
|
|
273
|
+
0
|
|
274
|
+
/* DEBUG */
|
|
275
|
+
]: "DEBUG",
|
|
276
|
+
[
|
|
277
|
+
1
|
|
278
|
+
/* INFO */
|
|
279
|
+
]: "INFO",
|
|
280
|
+
[
|
|
281
|
+
2
|
|
282
|
+
/* WARN */
|
|
283
|
+
]: "WARN",
|
|
284
|
+
[
|
|
285
|
+
3
|
|
286
|
+
/* ERROR */
|
|
287
|
+
]: "ERROR",
|
|
288
|
+
[
|
|
289
|
+
4
|
|
290
|
+
/* NONE */
|
|
291
|
+
]: "NONE"
|
|
292
|
+
};
|
|
293
|
+
const scopedPrefix = scope ? `${this.config.prefix}:${scope}` : this.config.prefix;
|
|
294
|
+
return `${scopedPrefix} [${levelNames[level]}]`;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Formats a complete log message for custom handlers
|
|
298
|
+
*/
|
|
299
|
+
static formatMessage(level, message, args, scope) {
|
|
300
|
+
const prefix = this.formatPrefix(level, scope);
|
|
301
|
+
return `${prefix} ${message}`;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Logs a message with the specified level
|
|
305
|
+
*/
|
|
306
|
+
static log(level, message, args, scope) {
|
|
307
|
+
if (this.config.level > level) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const prefix = this.formatPrefix(level, scope);
|
|
311
|
+
const formatted = this.formatMessage(level, message, args, scope);
|
|
312
|
+
const entry = {
|
|
313
|
+
level,
|
|
314
|
+
message,
|
|
315
|
+
args,
|
|
316
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
317
|
+
scope,
|
|
318
|
+
formatted
|
|
319
|
+
};
|
|
320
|
+
if (this.config.handler) {
|
|
321
|
+
this.config.handler(entry);
|
|
322
|
+
} else {
|
|
323
|
+
switch (level) {
|
|
324
|
+
case 0:
|
|
325
|
+
case 1:
|
|
326
|
+
console.log(prefix, message, ...args);
|
|
327
|
+
break;
|
|
328
|
+
case 2:
|
|
329
|
+
console.warn(prefix, message, ...args);
|
|
330
|
+
break;
|
|
331
|
+
case 3:
|
|
332
|
+
console.error(prefix, message, ...args);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
68
336
|
}
|
|
69
337
|
/**
|
|
70
338
|
* Logs a debug message (only in DEBUG level)
|
|
@@ -73,9 +341,7 @@ const _Logger = class _Logger {
|
|
|
73
341
|
* @param args - Additional arguments to log
|
|
74
342
|
*/
|
|
75
343
|
static debug(message, ...args) {
|
|
76
|
-
|
|
77
|
-
console.log(`${this.prefix} [DEBUG]`, message, ...args);
|
|
78
|
-
}
|
|
344
|
+
this.log(0, message, args);
|
|
79
345
|
}
|
|
80
346
|
/**
|
|
81
347
|
* Logs an info message (DEBUG and INFO levels)
|
|
@@ -84,9 +350,7 @@ const _Logger = class _Logger {
|
|
|
84
350
|
* @param args - Additional arguments to log
|
|
85
351
|
*/
|
|
86
352
|
static info(message, ...args) {
|
|
87
|
-
|
|
88
|
-
console.log(`${this.prefix} [INFO]`, message, ...args);
|
|
89
|
-
}
|
|
353
|
+
this.log(1, message, args);
|
|
90
354
|
}
|
|
91
355
|
/**
|
|
92
356
|
* Logs a warning message (DEBUG, INFO, and WARN levels)
|
|
@@ -95,9 +359,7 @@ const _Logger = class _Logger {
|
|
|
95
359
|
* @param args - Additional arguments to log
|
|
96
360
|
*/
|
|
97
361
|
static warn(message, ...args) {
|
|
98
|
-
|
|
99
|
-
console.warn(`${this.prefix} [WARN]`, message, ...args);
|
|
100
|
-
}
|
|
362
|
+
this.log(2, message, args);
|
|
101
363
|
}
|
|
102
364
|
/**
|
|
103
365
|
* Logs an error message (all levels except NONE)
|
|
@@ -106,9 +368,7 @@ const _Logger = class _Logger {
|
|
|
106
368
|
* @param args - Additional arguments to log
|
|
107
369
|
*/
|
|
108
370
|
static error(message, ...args) {
|
|
109
|
-
|
|
110
|
-
console.error(`${this.prefix} [ERROR]`, message, ...args);
|
|
111
|
-
}
|
|
371
|
+
this.log(3, message, args);
|
|
112
372
|
}
|
|
113
373
|
/**
|
|
114
374
|
* Creates a scoped logger with a specific prefix
|
|
@@ -117,408 +377,549 @@ const _Logger = class _Logger {
|
|
|
117
377
|
* @returns Scoped logger instance
|
|
118
378
|
*/
|
|
119
379
|
static scope(scope) {
|
|
120
|
-
const scopedPrefix = `${this.prefix}:${scope}`;
|
|
121
380
|
return {
|
|
122
381
|
debug: (message, ...args) => {
|
|
123
|
-
|
|
124
|
-
console.log(`${scopedPrefix} [DEBUG]`, message, ...args);
|
|
125
|
-
}
|
|
382
|
+
_Logger.log(0, message, args, scope);
|
|
126
383
|
},
|
|
127
384
|
info: (message, ...args) => {
|
|
128
|
-
|
|
129
|
-
console.log(`${scopedPrefix} [INFO]`, message, ...args);
|
|
130
|
-
}
|
|
385
|
+
_Logger.log(1, message, args, scope);
|
|
131
386
|
},
|
|
132
387
|
warn: (message, ...args) => {
|
|
133
|
-
|
|
134
|
-
console.warn(`${scopedPrefix} [WARN]`, message, ...args);
|
|
135
|
-
}
|
|
388
|
+
_Logger.log(2, message, args, scope);
|
|
136
389
|
},
|
|
137
390
|
error: (message, ...args) => {
|
|
138
|
-
|
|
139
|
-
console.error(`${scopedPrefix} [ERROR]`, message, ...args);
|
|
140
|
-
}
|
|
391
|
+
_Logger.log(3, message, args, scope);
|
|
141
392
|
}
|
|
142
393
|
};
|
|
143
394
|
}
|
|
144
395
|
};
|
|
145
|
-
_Logger.
|
|
146
|
-
|
|
396
|
+
_Logger.config = {
|
|
397
|
+
level: 2,
|
|
398
|
+
prefix: "[TaroBTPrint]"
|
|
399
|
+
};
|
|
147
400
|
let Logger = _Logger;
|
|
148
|
-
|
|
149
|
-
|
|
401
|
+
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
402
|
+
ErrorCode2["CONNECTION_FAILED"] = "CONNECTION_FAILED";
|
|
403
|
+
ErrorCode2["CONNECTION_TIMEOUT"] = "CONNECTION_TIMEOUT";
|
|
404
|
+
ErrorCode2["DEVICE_NOT_FOUND"] = "DEVICE_NOT_FOUND";
|
|
405
|
+
ErrorCode2["DEVICE_DISCONNECTED"] = "DEVICE_DISCONNECTED";
|
|
406
|
+
ErrorCode2["SERVICE_NOT_FOUND"] = "SERVICE_NOT_FOUND";
|
|
407
|
+
ErrorCode2["CHARACTERISTIC_NOT_FOUND"] = "CHARACTERISTIC_NOT_FOUND";
|
|
408
|
+
ErrorCode2["SERVICE_DISCOVERY_FAILED"] = "SERVICE_DISCOVERY_FAILED";
|
|
409
|
+
ErrorCode2["WRITE_FAILED"] = "WRITE_FAILED";
|
|
410
|
+
ErrorCode2["WRITE_TIMEOUT"] = "WRITE_TIMEOUT";
|
|
411
|
+
ErrorCode2["PRINT_JOB_IN_PROGRESS"] = "PRINT_JOB_IN_PROGRESS";
|
|
412
|
+
ErrorCode2["PRINT_JOB_CANCELLED"] = "PRINT_JOB_CANCELLED";
|
|
413
|
+
ErrorCode2["PRINT_JOB_FAILED"] = "PRINT_JOB_FAILED";
|
|
414
|
+
ErrorCode2["INVALID_CONFIGURATION"] = "INVALID_CONFIGURATION";
|
|
415
|
+
ErrorCode2["ENCODING_NOT_SUPPORTED"] = "ENCODING_NOT_SUPPORTED";
|
|
416
|
+
ErrorCode2["INVALID_IMAGE_DATA"] = "INVALID_IMAGE_DATA";
|
|
417
|
+
ErrorCode2["INVALID_QR_DATA"] = "INVALID_QR_DATA";
|
|
418
|
+
ErrorCode2["PLATFORM_NOT_SUPPORTED"] = "PLATFORM_NOT_SUPPORTED";
|
|
419
|
+
return ErrorCode2;
|
|
420
|
+
})(ErrorCode || {});
|
|
421
|
+
class BluetoothPrintError extends Error {
|
|
150
422
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* @param text - Text to encode
|
|
154
|
-
* @param encoding - Target encoding (default: 'GBK')
|
|
155
|
-
* @returns Encoded bytes
|
|
156
|
-
*
|
|
157
|
-
* @remarks
|
|
158
|
-
* Note: Native TextEncoder only supports UTF-8.
|
|
159
|
-
* For GBK encoding, a third-party library or polyfill is recommended.
|
|
160
|
-
* Currently falls back to UTF-8 with a warning.
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* ```typescript
|
|
164
|
-
* // UTF-8 encoding
|
|
165
|
-
* const utf8 = Encoding.encode('Hello', 'UTF-8');
|
|
423
|
+
* Creates a new BluetoothPrintError
|
|
166
424
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
425
|
+
* @param code - Error code from ErrorCode enum
|
|
426
|
+
* @param message - Human-readable error message
|
|
427
|
+
* @param originalError - Original error that caused this error (optional)
|
|
170
428
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
if (!this.warningShown) {
|
|
180
|
-
logger.warn(
|
|
181
|
-
`Encoding ${encoding} not yet fully implemented, falling back to UTF-8. This may cause display issues with some printers.`
|
|
182
|
-
);
|
|
183
|
-
this.warningShown = true;
|
|
429
|
+
constructor(code, message, originalError) {
|
|
430
|
+
super(message);
|
|
431
|
+
this.code = code;
|
|
432
|
+
this.originalError = originalError;
|
|
433
|
+
this.name = "BluetoothPrintError";
|
|
434
|
+
if (Error.captureStackTrace) {
|
|
435
|
+
Error.captureStackTrace(this, BluetoothPrintError);
|
|
184
436
|
}
|
|
185
|
-
return this.utf8Encoder.encode(text);
|
|
186
437
|
}
|
|
187
438
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* @param encoding - Encoding name to check
|
|
191
|
-
* @returns True if supported, false otherwise
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* ```typescript
|
|
195
|
-
* if (Encoding.isSupported('GBK')) {
|
|
196
|
-
* console.log('GBK is supported');
|
|
197
|
-
* }
|
|
198
|
-
* ```
|
|
439
|
+
* Returns a detailed error message including the error code
|
|
199
440
|
*/
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
441
|
+
toString() {
|
|
442
|
+
let result = `${this.name} [${this.code}]: ${this.message}`;
|
|
443
|
+
if (this.originalError) {
|
|
444
|
+
result += `
|
|
445
|
+
Caused by: ${this.originalError.message}`;
|
|
203
446
|
}
|
|
204
|
-
|
|
205
|
-
return normalizedEncoding === "UTF8" || normalizedEncoding === "UTF-8";
|
|
447
|
+
return result;
|
|
206
448
|
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
* Convert RGBA data to monochrome bitmap (1 bit per pixel)
|
|
214
|
-
* suitable for ESC/POS GS v 0 command.
|
|
215
|
-
* Uses Floyd-Steinberg dithering for better quality.
|
|
216
|
-
*
|
|
217
|
-
* @param data - RGBA pixel data as Uint8Array
|
|
218
|
-
* @param width - Image width in pixels
|
|
219
|
-
* @param height - Image height in pixels
|
|
220
|
-
* @returns Monochrome bitmap data as Uint8Array
|
|
221
|
-
*
|
|
222
|
-
* @example
|
|
223
|
-
* ```typescript
|
|
224
|
-
* const imageData = new Uint8Array(width * height * 4); // RGBA
|
|
225
|
-
* const bitmap = ImageProcessing.toBitmap(imageData, width, height);
|
|
226
|
-
* ```
|
|
227
|
-
*/
|
|
228
|
-
static toBitmap(data, width, height) {
|
|
229
|
-
if (!data || !(data instanceof Uint8Array) || width <= 0 || height <= 0) {
|
|
230
|
-
return new Uint8Array(0);
|
|
449
|
+
}
|
|
450
|
+
var Token = (
|
|
451
|
+
/** @class */
|
|
452
|
+
/* @__PURE__ */ function() {
|
|
453
|
+
function Token2(name) {
|
|
454
|
+
this.name = name;
|
|
231
455
|
}
|
|
232
|
-
|
|
233
|
-
|
|
456
|
+
return Token2;
|
|
457
|
+
}()
|
|
458
|
+
);
|
|
459
|
+
var __extends$1 = /* @__PURE__ */ function() {
|
|
460
|
+
var extendStatics = function(d, b) {
|
|
461
|
+
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
|
|
462
|
+
d2.__proto__ = b2;
|
|
463
|
+
} || function(d2, b2) {
|
|
464
|
+
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
|
|
465
|
+
};
|
|
466
|
+
return extendStatics(d, b);
|
|
467
|
+
};
|
|
468
|
+
return function(d, b) {
|
|
469
|
+
extendStatics(d, b);
|
|
470
|
+
function __() {
|
|
471
|
+
this.constructor = d;
|
|
234
472
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
473
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
474
|
+
};
|
|
475
|
+
}();
|
|
476
|
+
var ServiceNotFoundError = (
|
|
477
|
+
/** @class */
|
|
478
|
+
function(_super) {
|
|
479
|
+
__extends$1(ServiceNotFoundError2, _super);
|
|
480
|
+
function ServiceNotFoundError2(identifier) {
|
|
481
|
+
var _a, _b;
|
|
482
|
+
var _this = _super.call(this) || this;
|
|
483
|
+
_this.name = "ServiceNotFoundError";
|
|
484
|
+
_this.normalizedIdentifier = "<UNKNOWN_IDENTIFIER>";
|
|
485
|
+
if (typeof identifier === "string") {
|
|
486
|
+
_this.normalizedIdentifier = identifier;
|
|
487
|
+
} else if (identifier instanceof Token) {
|
|
488
|
+
_this.normalizedIdentifier = "Token<" + (identifier.name || "UNSET_NAME") + ">";
|
|
489
|
+
} else if (identifier && (identifier.name || ((_a = identifier.prototype) === null || _a === void 0 ? void 0 : _a.name))) {
|
|
490
|
+
_this.normalizedIdentifier = "MaybeConstructable<" + identifier.name + ">" || "MaybeConstructable<" + ((_b = identifier.prototype) === null || _b === void 0 ? void 0 : _b.name) + ">";
|
|
491
|
+
}
|
|
492
|
+
return _this;
|
|
244
493
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
494
|
+
Object.defineProperty(ServiceNotFoundError2.prototype, "message", {
|
|
495
|
+
get: function() {
|
|
496
|
+
return 'Service with "' + this.normalizedIdentifier + '" identifier was not found in the container. Register it before usage via explicitly calling the "Container.set" function or using the "@Service()" decorator.';
|
|
497
|
+
},
|
|
498
|
+
enumerable: false,
|
|
499
|
+
configurable: true
|
|
500
|
+
});
|
|
501
|
+
return ServiceNotFoundError2;
|
|
502
|
+
}(Error)
|
|
503
|
+
);
|
|
504
|
+
var __extends = /* @__PURE__ */ function() {
|
|
505
|
+
var extendStatics = function(d, b) {
|
|
506
|
+
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
|
|
507
|
+
d2.__proto__ = b2;
|
|
508
|
+
} || function(d2, b2) {
|
|
509
|
+
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
|
|
510
|
+
};
|
|
511
|
+
return extendStatics(d, b);
|
|
512
|
+
};
|
|
513
|
+
return function(d, b) {
|
|
514
|
+
extendStatics(d, b);
|
|
515
|
+
function __() {
|
|
516
|
+
this.constructor = d;
|
|
517
|
+
}
|
|
518
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
519
|
+
};
|
|
520
|
+
}();
|
|
521
|
+
var CannotInstantiateValueError = (
|
|
522
|
+
/** @class */
|
|
523
|
+
function(_super) {
|
|
524
|
+
__extends(CannotInstantiateValueError2, _super);
|
|
525
|
+
function CannotInstantiateValueError2(identifier) {
|
|
526
|
+
var _a, _b;
|
|
527
|
+
var _this = _super.call(this) || this;
|
|
528
|
+
_this.name = "CannotInstantiateValueError";
|
|
529
|
+
_this.normalizedIdentifier = "<UNKNOWN_IDENTIFIER>";
|
|
530
|
+
if (typeof identifier === "string") {
|
|
531
|
+
_this.normalizedIdentifier = identifier;
|
|
532
|
+
} else if (identifier instanceof Token) {
|
|
533
|
+
_this.normalizedIdentifier = "Token<" + (identifier.name || "UNSET_NAME") + ">";
|
|
534
|
+
} else if (identifier && (identifier.name || ((_a = identifier.prototype) === null || _a === void 0 ? void 0 : _a.name))) {
|
|
535
|
+
_this.normalizedIdentifier = "MaybeConstructable<" + identifier.name + ">" || "MaybeConstructable<" + ((_b = identifier.prototype) === null || _b === void 0 ? void 0 : _b.name) + ">";
|
|
536
|
+
}
|
|
537
|
+
return _this;
|
|
538
|
+
}
|
|
539
|
+
Object.defineProperty(CannotInstantiateValueError2.prototype, "message", {
|
|
540
|
+
get: function() {
|
|
541
|
+
return 'Cannot instantiate the requested value for the "' + this.normalizedIdentifier + `" identifier. The related metadata doesn't contain a factory or a type to instantiate.`;
|
|
542
|
+
},
|
|
543
|
+
enumerable: false,
|
|
544
|
+
configurable: true
|
|
545
|
+
});
|
|
546
|
+
return CannotInstantiateValueError2;
|
|
547
|
+
}(Error)
|
|
548
|
+
);
|
|
549
|
+
var EMPTY_VALUE = Symbol("EMPTY_VALUE");
|
|
550
|
+
var __assign = function() {
|
|
551
|
+
__assign = Object.assign || function(t) {
|
|
552
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
553
|
+
s = arguments[i];
|
|
554
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
555
|
+
t[p] = s[p];
|
|
556
|
+
}
|
|
557
|
+
return t;
|
|
558
|
+
};
|
|
559
|
+
return __assign.apply(this, arguments);
|
|
560
|
+
};
|
|
561
|
+
var __spreadArrays = function() {
|
|
562
|
+
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
563
|
+
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
564
|
+
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
565
|
+
r[k] = a[j];
|
|
566
|
+
return r;
|
|
567
|
+
};
|
|
568
|
+
var ContainerInstance = (
|
|
569
|
+
/** @class */
|
|
570
|
+
function() {
|
|
571
|
+
function ContainerInstance2(id) {
|
|
572
|
+
this.services = [];
|
|
573
|
+
this.id = id;
|
|
574
|
+
}
|
|
575
|
+
ContainerInstance2.prototype.has = function(identifier) {
|
|
576
|
+
return !!this.findService(identifier);
|
|
577
|
+
};
|
|
578
|
+
ContainerInstance2.prototype.get = function(identifier) {
|
|
579
|
+
var globalContainer = Container.of(void 0);
|
|
580
|
+
var globalService = globalContainer.findService(identifier);
|
|
581
|
+
var scopedService = this.findService(identifier);
|
|
582
|
+
if (globalService && globalService.global === true)
|
|
583
|
+
return this.getServiceValue(globalService);
|
|
584
|
+
if (scopedService)
|
|
585
|
+
return this.getServiceValue(scopedService);
|
|
586
|
+
if (globalService && this !== globalContainer) {
|
|
587
|
+
var clonedService = __assign({}, globalService);
|
|
588
|
+
clonedService.value = EMPTY_VALUE;
|
|
589
|
+
this.set(clonedService);
|
|
590
|
+
var value = this.getServiceValue(clonedService);
|
|
591
|
+
this.set(__assign(__assign({}, clonedService), { value }));
|
|
592
|
+
return value;
|
|
593
|
+
}
|
|
594
|
+
if (globalService)
|
|
595
|
+
return this.getServiceValue(globalService);
|
|
596
|
+
throw new ServiceNotFoundError(identifier);
|
|
597
|
+
};
|
|
598
|
+
ContainerInstance2.prototype.getMany = function(identifier) {
|
|
599
|
+
var _this = this;
|
|
600
|
+
return this.findAllServices(identifier).map(function(service) {
|
|
601
|
+
return _this.getServiceValue(service);
|
|
602
|
+
});
|
|
603
|
+
};
|
|
604
|
+
ContainerInstance2.prototype.set = function(identifierOrServiceMetadata, value) {
|
|
605
|
+
var _this = this;
|
|
606
|
+
if (identifierOrServiceMetadata instanceof Array) {
|
|
607
|
+
identifierOrServiceMetadata.forEach(function(data) {
|
|
608
|
+
return _this.set(data);
|
|
609
|
+
});
|
|
610
|
+
return this;
|
|
611
|
+
}
|
|
612
|
+
if (typeof identifierOrServiceMetadata === "string" || identifierOrServiceMetadata instanceof Token) {
|
|
613
|
+
return this.set({
|
|
614
|
+
id: identifierOrServiceMetadata,
|
|
615
|
+
type: null,
|
|
616
|
+
value,
|
|
617
|
+
factory: void 0,
|
|
618
|
+
global: false,
|
|
619
|
+
multiple: false,
|
|
620
|
+
eager: false,
|
|
621
|
+
transient: false
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
if (typeof identifierOrServiceMetadata === "function") {
|
|
625
|
+
return this.set({
|
|
626
|
+
id: identifierOrServiceMetadata,
|
|
627
|
+
// TODO: remove explicit casting
|
|
628
|
+
type: identifierOrServiceMetadata,
|
|
629
|
+
value,
|
|
630
|
+
factory: void 0,
|
|
631
|
+
global: false,
|
|
632
|
+
multiple: false,
|
|
633
|
+
eager: false,
|
|
634
|
+
transient: false
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
var newService = __assign({ id: new Token("UNREACHABLE"), type: null, factory: void 0, value: EMPTY_VALUE, global: false, multiple: false, eager: false, transient: false }, identifierOrServiceMetadata);
|
|
638
|
+
var service = this.findService(newService.id);
|
|
639
|
+
if (service && service.multiple !== true) {
|
|
640
|
+
Object.assign(service, newService);
|
|
641
|
+
} else {
|
|
642
|
+
this.services.push(newService);
|
|
643
|
+
}
|
|
644
|
+
if (newService.eager) {
|
|
645
|
+
this.get(newService.id);
|
|
646
|
+
}
|
|
647
|
+
return this;
|
|
648
|
+
};
|
|
649
|
+
ContainerInstance2.prototype.remove = function(identifierOrIdentifierArray) {
|
|
650
|
+
var _this = this;
|
|
651
|
+
if (Array.isArray(identifierOrIdentifierArray)) {
|
|
652
|
+
identifierOrIdentifierArray.forEach(function(id) {
|
|
653
|
+
return _this.remove(id);
|
|
654
|
+
});
|
|
655
|
+
} else {
|
|
656
|
+
this.services = this.services.filter(function(service) {
|
|
657
|
+
if (service.id === identifierOrIdentifierArray) {
|
|
658
|
+
_this.destroyServiceInstance(service);
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
return true;
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
return this;
|
|
665
|
+
};
|
|
666
|
+
ContainerInstance2.prototype.reset = function(options) {
|
|
667
|
+
var _this = this;
|
|
668
|
+
if (options === void 0) {
|
|
669
|
+
options = { strategy: "resetValue" };
|
|
670
|
+
}
|
|
671
|
+
switch (options.strategy) {
|
|
672
|
+
case "resetValue":
|
|
673
|
+
this.services.forEach(function(service) {
|
|
674
|
+
return _this.destroyServiceInstance(service);
|
|
675
|
+
});
|
|
676
|
+
break;
|
|
677
|
+
case "resetServices":
|
|
678
|
+
this.services.forEach(function(service) {
|
|
679
|
+
return _this.destroyServiceInstance(service);
|
|
680
|
+
});
|
|
681
|
+
this.services = [];
|
|
682
|
+
break;
|
|
683
|
+
default:
|
|
684
|
+
throw new Error("Received invalid reset strategy.");
|
|
685
|
+
}
|
|
686
|
+
return this;
|
|
687
|
+
};
|
|
688
|
+
ContainerInstance2.prototype.findAllServices = function(identifier) {
|
|
689
|
+
return this.services.filter(function(service) {
|
|
690
|
+
return service.id === identifier;
|
|
691
|
+
});
|
|
692
|
+
};
|
|
693
|
+
ContainerInstance2.prototype.findService = function(identifier) {
|
|
694
|
+
return this.services.find(function(service) {
|
|
695
|
+
return service.id === identifier;
|
|
696
|
+
});
|
|
697
|
+
};
|
|
698
|
+
ContainerInstance2.prototype.getServiceValue = function(serviceMetadata) {
|
|
699
|
+
var _a;
|
|
700
|
+
var value = EMPTY_VALUE;
|
|
701
|
+
if (serviceMetadata.value !== EMPTY_VALUE) {
|
|
702
|
+
return serviceMetadata.value;
|
|
703
|
+
}
|
|
704
|
+
if (!serviceMetadata.factory && !serviceMetadata.type) {
|
|
705
|
+
throw new CannotInstantiateValueError(serviceMetadata.id);
|
|
706
|
+
}
|
|
707
|
+
if (serviceMetadata.factory) {
|
|
708
|
+
if (serviceMetadata.factory instanceof Array) {
|
|
709
|
+
var factoryInstance = void 0;
|
|
710
|
+
try {
|
|
711
|
+
factoryInstance = this.get(serviceMetadata.factory[0]);
|
|
712
|
+
} catch (error) {
|
|
713
|
+
if (error instanceof ServiceNotFoundError) {
|
|
714
|
+
factoryInstance = new serviceMetadata.factory[0]();
|
|
715
|
+
} else {
|
|
716
|
+
throw error;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
value = factoryInstance[serviceMetadata.factory[1]](this, serviceMetadata.id);
|
|
720
|
+
} else {
|
|
721
|
+
value = serviceMetadata.factory(this, serviceMetadata.id);
|
|
254
722
|
}
|
|
255
|
-
const quantError = oldPixel - newPixel;
|
|
256
|
-
this.distributeError(grayscale, width, height, x, y, quantError);
|
|
257
723
|
}
|
|
724
|
+
if (!serviceMetadata.factory && serviceMetadata.type) {
|
|
725
|
+
var constructableTargetType = serviceMetadata.type;
|
|
726
|
+
var paramTypes = ((_a = Reflect) === null || _a === void 0 ? void 0 : _a.getMetadata("design:paramtypes", constructableTargetType)) || [];
|
|
727
|
+
var params = this.initializeParams(constructableTargetType, paramTypes);
|
|
728
|
+
params.push(this);
|
|
729
|
+
value = new (constructableTargetType.bind.apply(constructableTargetType, __spreadArrays([void 0], params)))();
|
|
730
|
+
}
|
|
731
|
+
if (!serviceMetadata.transient && value !== EMPTY_VALUE) {
|
|
732
|
+
serviceMetadata.value = value;
|
|
733
|
+
}
|
|
734
|
+
if (value === EMPTY_VALUE) {
|
|
735
|
+
throw new CannotInstantiateValueError(serviceMetadata.id);
|
|
736
|
+
}
|
|
737
|
+
if (serviceMetadata.type) {
|
|
738
|
+
this.applyPropertyHandlers(serviceMetadata.type, value);
|
|
739
|
+
}
|
|
740
|
+
return value;
|
|
741
|
+
};
|
|
742
|
+
ContainerInstance2.prototype.initializeParams = function(target, paramTypes) {
|
|
743
|
+
var _this = this;
|
|
744
|
+
return paramTypes.map(function(paramType, index) {
|
|
745
|
+
var paramHandler = Container.handlers.find(function(handler) {
|
|
746
|
+
return (handler.object === target || handler.object === Object.getPrototypeOf(target)) && handler.index === index;
|
|
747
|
+
});
|
|
748
|
+
if (paramHandler)
|
|
749
|
+
return paramHandler.value(_this);
|
|
750
|
+
if (paramType && paramType.name && !_this.isPrimitiveParamType(paramType.name)) {
|
|
751
|
+
return _this.get(paramType);
|
|
752
|
+
}
|
|
753
|
+
return void 0;
|
|
754
|
+
});
|
|
755
|
+
};
|
|
756
|
+
ContainerInstance2.prototype.isPrimitiveParamType = function(paramTypeName) {
|
|
757
|
+
return ["string", "boolean", "number", "object"].includes(paramTypeName.toLowerCase());
|
|
758
|
+
};
|
|
759
|
+
ContainerInstance2.prototype.applyPropertyHandlers = function(target, instance) {
|
|
760
|
+
var _this = this;
|
|
761
|
+
Container.handlers.forEach(function(handler) {
|
|
762
|
+
if (typeof handler.index === "number")
|
|
763
|
+
return;
|
|
764
|
+
if (handler.object.constructor !== target && !(target.prototype instanceof handler.object.constructor))
|
|
765
|
+
return;
|
|
766
|
+
if (handler.propertyName) {
|
|
767
|
+
instance[handler.propertyName] = handler.value(_this);
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
};
|
|
771
|
+
ContainerInstance2.prototype.destroyServiceInstance = function(serviceMetadata, force) {
|
|
772
|
+
if (force === void 0) {
|
|
773
|
+
force = false;
|
|
774
|
+
}
|
|
775
|
+
var shouldResetValue = force || !!serviceMetadata.type || !!serviceMetadata.factory;
|
|
776
|
+
if (shouldResetValue) {
|
|
777
|
+
if (typeof (serviceMetadata === null || serviceMetadata === void 0 ? void 0 : serviceMetadata.value)["destroy"] === "function") {
|
|
778
|
+
try {
|
|
779
|
+
serviceMetadata.value.destroy();
|
|
780
|
+
} catch (error) {
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
serviceMetadata.value = EMPTY_VALUE;
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
return ContainerInstance2;
|
|
787
|
+
}()
|
|
788
|
+
);
|
|
789
|
+
var Container = (
|
|
790
|
+
/** @class */
|
|
791
|
+
function() {
|
|
792
|
+
function Container2() {
|
|
258
793
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
static distributeError(grayscale, width, height, x, y, error) {
|
|
272
|
-
const distribute = (dx, dy, factor) => {
|
|
273
|
-
const nx = x + dx;
|
|
274
|
-
const ny = y + dy;
|
|
275
|
-
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
276
|
-
const index = ny * width + nx;
|
|
277
|
-
grayscale[index] = Math.max(0, Math.min(255, (grayscale[index] || 0) + error * factor));
|
|
794
|
+
Container2.of = function(containerId) {
|
|
795
|
+
if (containerId === void 0) {
|
|
796
|
+
containerId = "default";
|
|
797
|
+
}
|
|
798
|
+
if (containerId === "default")
|
|
799
|
+
return this.globalInstance;
|
|
800
|
+
var container = this.instances.find(function(instance) {
|
|
801
|
+
return instance.id === containerId;
|
|
802
|
+
});
|
|
803
|
+
if (!container) {
|
|
804
|
+
container = new ContainerInstance(containerId);
|
|
805
|
+
this.instances.push(container);
|
|
278
806
|
}
|
|
807
|
+
return container;
|
|
279
808
|
};
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
809
|
+
Container2.has = function(identifier) {
|
|
810
|
+
return this.globalInstance.has(identifier);
|
|
811
|
+
};
|
|
812
|
+
Container2.get = function(identifier) {
|
|
813
|
+
return this.globalInstance.get(identifier);
|
|
814
|
+
};
|
|
815
|
+
Container2.getMany = function(id) {
|
|
816
|
+
return this.globalInstance.getMany(id);
|
|
817
|
+
};
|
|
818
|
+
Container2.set = function(identifierOrServiceMetadata, value) {
|
|
819
|
+
this.globalInstance.set(identifierOrServiceMetadata, value);
|
|
820
|
+
return this;
|
|
821
|
+
};
|
|
822
|
+
Container2.remove = function(identifierOrIdentifierArray) {
|
|
823
|
+
this.globalInstance.remove(identifierOrIdentifierArray);
|
|
824
|
+
return this;
|
|
825
|
+
};
|
|
826
|
+
Container2.reset = function(containerId) {
|
|
827
|
+
if (containerId === void 0) {
|
|
828
|
+
containerId = "default";
|
|
829
|
+
}
|
|
830
|
+
if (containerId == "default") {
|
|
831
|
+
this.globalInstance.reset();
|
|
832
|
+
this.instances.forEach(function(instance2) {
|
|
833
|
+
return instance2.reset();
|
|
834
|
+
});
|
|
835
|
+
} else {
|
|
836
|
+
var instance = this.instances.find(function(instance2) {
|
|
837
|
+
return instance2.id === containerId;
|
|
838
|
+
});
|
|
839
|
+
if (instance) {
|
|
840
|
+
instance.reset();
|
|
841
|
+
this.instances.splice(this.instances.indexOf(instance), 1);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return this;
|
|
845
|
+
};
|
|
846
|
+
Container2.registerHandler = function(handler) {
|
|
847
|
+
this.handlers.push(handler);
|
|
848
|
+
return this;
|
|
849
|
+
};
|
|
850
|
+
Container2.import = function(services) {
|
|
851
|
+
return this;
|
|
852
|
+
};
|
|
853
|
+
Container2.handlers = [];
|
|
854
|
+
Container2.globalInstance = new ContainerInstance("default");
|
|
855
|
+
Container2.instances = [];
|
|
856
|
+
return Container2;
|
|
857
|
+
}()
|
|
858
|
+
);
|
|
859
|
+
function Service(optionsOrServiceIdentifier) {
|
|
860
|
+
return function(targetConstructor) {
|
|
861
|
+
var serviceMetadata = {
|
|
862
|
+
id: targetConstructor,
|
|
863
|
+
// TODO: Let's investigate why we receive Function type instead of a constructable.
|
|
864
|
+
type: targetConstructor,
|
|
865
|
+
factory: void 0,
|
|
866
|
+
multiple: false,
|
|
867
|
+
global: false,
|
|
868
|
+
eager: false,
|
|
869
|
+
transient: false,
|
|
870
|
+
value: EMPTY_VALUE
|
|
871
|
+
};
|
|
872
|
+
if (optionsOrServiceIdentifier instanceof Token || typeof optionsOrServiceIdentifier === "string") {
|
|
873
|
+
serviceMetadata.id = optionsOrServiceIdentifier;
|
|
874
|
+
}
|
|
875
|
+
Container.set(serviceMetadata);
|
|
876
|
+
};
|
|
285
877
|
}
|
|
286
|
-
class
|
|
878
|
+
class BaseAdapter {
|
|
287
879
|
constructor() {
|
|
288
|
-
this.
|
|
880
|
+
this.serviceCache = /* @__PURE__ */ new Map();
|
|
881
|
+
this.logger = Logger.scope("BaseAdapter");
|
|
289
882
|
}
|
|
290
883
|
/**
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
* @returns Array of command buffers
|
|
884
|
+
* Register a callback for connection state changes
|
|
885
|
+
* @param callback - Function to call when the state changes
|
|
295
886
|
*/
|
|
296
|
-
|
|
297
|
-
|
|
887
|
+
onStateChange(callback) {
|
|
888
|
+
this.stateCallback = callback;
|
|
298
889
|
}
|
|
299
890
|
/**
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
* @param content - Text content to print
|
|
303
|
-
* @param encoding - Text encoding (default: 'GBK')
|
|
304
|
-
* @returns Array of command buffers
|
|
305
|
-
*
|
|
306
|
-
* @example
|
|
307
|
-
* ```typescript
|
|
308
|
-
* driver.text('你好世界', 'GBK');
|
|
309
|
-
* ```
|
|
891
|
+
* Updates the internal state and notifies callbacks
|
|
892
|
+
* @param state - New printer state
|
|
310
893
|
*/
|
|
311
|
-
|
|
312
|
-
if (
|
|
313
|
-
|
|
894
|
+
updateState(state) {
|
|
895
|
+
if (this.stateCallback) {
|
|
896
|
+
this.stateCallback(state);
|
|
314
897
|
}
|
|
315
|
-
const encoded = Encoding.encode(content, encoding);
|
|
316
|
-
return [encoded];
|
|
317
898
|
}
|
|
318
899
|
/**
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
* @
|
|
322
|
-
* @returns Array of command buffers
|
|
323
|
-
*
|
|
324
|
-
* @example
|
|
325
|
-
* ```typescript
|
|
326
|
-
* driver.feed(3); // Feed 3 lines
|
|
327
|
-
* ```
|
|
900
|
+
* Validates device ID
|
|
901
|
+
* @param deviceId - Device ID to validate
|
|
902
|
+
* @throws BluetoothPrintError if device ID is invalid
|
|
328
903
|
*/
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
904
|
+
validateDeviceId(deviceId) {
|
|
905
|
+
if (!deviceId || typeof deviceId !== "string") {
|
|
906
|
+
throw new BluetoothPrintError(ErrorCode.DEVICE_NOT_FOUND, "Invalid device ID provided");
|
|
907
|
+
}
|
|
332
908
|
}
|
|
333
909
|
/**
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
* @
|
|
337
|
-
*
|
|
338
|
-
* @example
|
|
339
|
-
* ```typescript
|
|
340
|
-
* driver.cut();
|
|
341
|
-
* ```
|
|
910
|
+
* Validates buffer data
|
|
911
|
+
* @param buffer - Buffer to validate
|
|
912
|
+
* @throws BluetoothPrintError if buffer is invalid
|
|
342
913
|
*/
|
|
343
|
-
|
|
344
|
-
|
|
914
|
+
validateBuffer(buffer) {
|
|
915
|
+
if (!buffer || !(buffer instanceof ArrayBuffer)) {
|
|
916
|
+
throw new BluetoothPrintError(ErrorCode.PRINT_JOB_FAILED, "Invalid buffer data provided");
|
|
917
|
+
}
|
|
345
918
|
}
|
|
346
919
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* @param data - RGBA pixel data
|
|
351
|
-
* @param width - Image width in pixels
|
|
352
|
-
* @param height - Image height in pixels
|
|
353
|
-
* @returns Array of command buffers
|
|
354
|
-
*
|
|
355
|
-
* @example
|
|
356
|
-
* ```typescript
|
|
357
|
-
* const imageData = new Uint8Array(width * height * 4); // RGBA
|
|
358
|
-
* driver.image(imageData, 200, 100);
|
|
359
|
-
* ```
|
|
360
|
-
*/
|
|
361
|
-
image(data, width, height) {
|
|
362
|
-
if (!data || !(data instanceof Uint8Array) || width <= 0 || height <= 0) {
|
|
363
|
-
return [];
|
|
364
|
-
}
|
|
365
|
-
if (data.length !== width * height * 4) {
|
|
366
|
-
this.logger.warn(`Invalid image data length: expected ${width * height * 4}, got ${data.length}`);
|
|
367
|
-
return [];
|
|
368
|
-
}
|
|
369
|
-
const bitmap = ImageProcessing.toBitmap(data, width, height);
|
|
370
|
-
const bytesPerLine = Math.ceil(width / 8);
|
|
371
|
-
const xL = bytesPerLine % 256;
|
|
372
|
-
const xH = Math.floor(bytesPerLine / 256);
|
|
373
|
-
const yL = height % 256;
|
|
374
|
-
const yH = Math.floor(height / 256);
|
|
375
|
-
const header = new Uint8Array([29, 118, 48, 0, xL, xH, yL, yH]);
|
|
376
|
-
return [header, bitmap];
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Generates QR code print command
|
|
380
|
-
*
|
|
381
|
-
* @param content - QR code content (URL, text, etc.)
|
|
382
|
-
* @param options - QR code options
|
|
383
|
-
* @returns Array of command buffers
|
|
384
|
-
*
|
|
385
|
-
* @example
|
|
386
|
-
* ```typescript
|
|
387
|
-
* driver.qr('https://example.com', {
|
|
388
|
-
* model: 2,
|
|
389
|
-
* size: 8,
|
|
390
|
-
* errorCorrection: 'M'
|
|
391
|
-
* });
|
|
392
|
-
* ```
|
|
393
|
-
*/
|
|
394
|
-
qr(content, options) {
|
|
395
|
-
var _a, _b, _c, _d;
|
|
396
|
-
if (!content || typeof content !== "string") {
|
|
397
|
-
return [];
|
|
398
|
-
}
|
|
399
|
-
const model = (_a = options == null ? void 0 : options.model) != null ? _a : 2;
|
|
400
|
-
const size = Math.max(1, Math.min(16, (_b = options == null ? void 0 : options.size) != null ? _b : 6));
|
|
401
|
-
const errorCorrection = (_c = options == null ? void 0 : options.errorCorrection) != null ? _c : "M";
|
|
402
|
-
const commands = [];
|
|
403
|
-
commands.push(
|
|
404
|
-
new Uint8Array([29, 40, 107, 4, 0, 49, 65, model === 1 ? 49 : 50, 0])
|
|
405
|
-
);
|
|
406
|
-
commands.push(new Uint8Array([29, 40, 107, 3, 0, 49, 67, size]));
|
|
407
|
-
const ecMap = { L: 48, M: 49, Q: 50, H: 51 };
|
|
408
|
-
const ecValue = (_d = ecMap[errorCorrection]) != null ? _d : 49;
|
|
409
|
-
commands.push(
|
|
410
|
-
new Uint8Array([29, 40, 107, 3, 0, 49, 69, ecValue])
|
|
411
|
-
);
|
|
412
|
-
const data = Encoding.encode(content, "GBK");
|
|
413
|
-
const len = data.length + 3;
|
|
414
|
-
const pL = len % 256;
|
|
415
|
-
const pH = Math.floor(len / 256);
|
|
416
|
-
commands.push(new Uint8Array([29, 40, 107, pL, pH, 49, 80, 48]));
|
|
417
|
-
commands.push(data);
|
|
418
|
-
commands.push(new Uint8Array([29, 40, 107, 3, 0, 49, 81, 48]));
|
|
419
|
-
return commands;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
423
|
-
ErrorCode2["CONNECTION_FAILED"] = "CONNECTION_FAILED";
|
|
424
|
-
ErrorCode2["CONNECTION_TIMEOUT"] = "CONNECTION_TIMEOUT";
|
|
425
|
-
ErrorCode2["DEVICE_NOT_FOUND"] = "DEVICE_NOT_FOUND";
|
|
426
|
-
ErrorCode2["DEVICE_DISCONNECTED"] = "DEVICE_DISCONNECTED";
|
|
427
|
-
ErrorCode2["SERVICE_NOT_FOUND"] = "SERVICE_NOT_FOUND";
|
|
428
|
-
ErrorCode2["CHARACTERISTIC_NOT_FOUND"] = "CHARACTERISTIC_NOT_FOUND";
|
|
429
|
-
ErrorCode2["SERVICE_DISCOVERY_FAILED"] = "SERVICE_DISCOVERY_FAILED";
|
|
430
|
-
ErrorCode2["WRITE_FAILED"] = "WRITE_FAILED";
|
|
431
|
-
ErrorCode2["WRITE_TIMEOUT"] = "WRITE_TIMEOUT";
|
|
432
|
-
ErrorCode2["PRINT_JOB_IN_PROGRESS"] = "PRINT_JOB_IN_PROGRESS";
|
|
433
|
-
ErrorCode2["PRINT_JOB_CANCELLED"] = "PRINT_JOB_CANCELLED";
|
|
434
|
-
ErrorCode2["PRINT_JOB_FAILED"] = "PRINT_JOB_FAILED";
|
|
435
|
-
ErrorCode2["INVALID_CONFIGURATION"] = "INVALID_CONFIGURATION";
|
|
436
|
-
ErrorCode2["ENCODING_NOT_SUPPORTED"] = "ENCODING_NOT_SUPPORTED";
|
|
437
|
-
ErrorCode2["INVALID_IMAGE_DATA"] = "INVALID_IMAGE_DATA";
|
|
438
|
-
ErrorCode2["INVALID_QR_DATA"] = "INVALID_QR_DATA";
|
|
439
|
-
ErrorCode2["PLATFORM_NOT_SUPPORTED"] = "PLATFORM_NOT_SUPPORTED";
|
|
440
|
-
return ErrorCode2;
|
|
441
|
-
})(ErrorCode || {});
|
|
442
|
-
class BluetoothPrintError extends Error {
|
|
443
|
-
/**
|
|
444
|
-
* Creates a new BluetoothPrintError
|
|
445
|
-
*
|
|
446
|
-
* @param code - Error code from ErrorCode enum
|
|
447
|
-
* @param message - Human-readable error message
|
|
448
|
-
* @param originalError - Original error that caused this error (optional)
|
|
449
|
-
*/
|
|
450
|
-
constructor(code, message, originalError) {
|
|
451
|
-
super(message);
|
|
452
|
-
this.code = code;
|
|
453
|
-
this.originalError = originalError;
|
|
454
|
-
this.name = "BluetoothPrintError";
|
|
455
|
-
if (Error.captureStackTrace) {
|
|
456
|
-
Error.captureStackTrace(this, BluetoothPrintError);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Returns a detailed error message including the error code
|
|
461
|
-
*/
|
|
462
|
-
toString() {
|
|
463
|
-
let result = `${this.name} [${this.code}]: ${this.message}`;
|
|
464
|
-
if (this.originalError) {
|
|
465
|
-
result += `
|
|
466
|
-
Caused by: ${this.originalError.message}`;
|
|
467
|
-
}
|
|
468
|
-
return result;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
class BaseAdapter {
|
|
472
|
-
constructor() {
|
|
473
|
-
this.serviceCache = /* @__PURE__ */ new Map();
|
|
474
|
-
this.logger = Logger.scope("BaseAdapter");
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Register a callback for connection state changes
|
|
478
|
-
* @param callback - Function to call when the state changes
|
|
479
|
-
*/
|
|
480
|
-
onStateChange(callback) {
|
|
481
|
-
this.stateCallback = callback;
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* Updates the internal state and notifies callbacks
|
|
485
|
-
* @param state - New printer state
|
|
486
|
-
*/
|
|
487
|
-
updateState(state) {
|
|
488
|
-
if (this.stateCallback) {
|
|
489
|
-
this.stateCallback(state);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
/**
|
|
493
|
-
* Validates device ID
|
|
494
|
-
* @param deviceId - Device ID to validate
|
|
495
|
-
* @throws BluetoothPrintError if device ID is invalid
|
|
496
|
-
*/
|
|
497
|
-
validateDeviceId(deviceId) {
|
|
498
|
-
if (!deviceId || typeof deviceId !== "string") {
|
|
499
|
-
throw new BluetoothPrintError(
|
|
500
|
-
ErrorCode.DEVICE_NOT_FOUND,
|
|
501
|
-
"Invalid device ID provided"
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Validates buffer data
|
|
507
|
-
* @param buffer - Buffer to validate
|
|
508
|
-
* @throws BluetoothPrintError if buffer is invalid
|
|
509
|
-
*/
|
|
510
|
-
validateBuffer(buffer) {
|
|
511
|
-
if (!buffer || !(buffer instanceof ArrayBuffer)) {
|
|
512
|
-
throw new BluetoothPrintError(
|
|
513
|
-
ErrorCode.PRINT_JOB_FAILED,
|
|
514
|
-
"Invalid buffer data provided"
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
/**
|
|
519
|
-
* Validates adapter options
|
|
520
|
-
* @param options - Options to validate
|
|
521
|
-
* @returns Validated options with default values
|
|
920
|
+
* Validates adapter options
|
|
921
|
+
* @param options - Options to validate
|
|
922
|
+
* @returns Validated options with default values
|
|
522
923
|
*/
|
|
523
924
|
validateOptions(options) {
|
|
524
925
|
var _a, _b, _c;
|
|
@@ -578,13 +979,17 @@ class TaroAdapter extends BaseAdapter {
|
|
|
578
979
|
this.updateState(PrinterState.CONNECTING);
|
|
579
980
|
this.logger.debug("Connecting to device:", deviceId);
|
|
580
981
|
try {
|
|
982
|
+
let timeoutId;
|
|
581
983
|
const connectionPromise = Taro.createBLEConnection({ deviceId });
|
|
582
984
|
const timeoutPromise = new Promise((_, reject) => {
|
|
583
|
-
setTimeout(() => {
|
|
985
|
+
timeoutId = setTimeout(() => {
|
|
584
986
|
reject(new Error("Connection timeout after 10 seconds"));
|
|
585
987
|
}, 1e4);
|
|
586
988
|
});
|
|
587
989
|
yield Promise.race([connectionPromise, timeoutPromise]);
|
|
990
|
+
if (timeoutId) {
|
|
991
|
+
clearTimeout(timeoutId);
|
|
992
|
+
}
|
|
588
993
|
this.logger.info("BLE connection established");
|
|
589
994
|
yield this.discoverServices(deviceId);
|
|
590
995
|
this.updateState(PrinterState.CONNECTED);
|
|
@@ -661,10 +1066,7 @@ class TaroAdapter extends BaseAdapter {
|
|
|
661
1066
|
const state = yield Taro.getBLEConnectionState({ deviceId });
|
|
662
1067
|
if (!state.connected) {
|
|
663
1068
|
this.cleanupDevice(deviceId);
|
|
664
|
-
throw new BluetoothPrintError(
|
|
665
|
-
ErrorCode.DEVICE_DISCONNECTED,
|
|
666
|
-
"Device disconnected"
|
|
667
|
-
);
|
|
1069
|
+
throw new BluetoothPrintError(ErrorCode.DEVICE_DISCONNECTED, "Device disconnected");
|
|
668
1070
|
}
|
|
669
1071
|
} catch (error) {
|
|
670
1072
|
this.cleanupDevice(deviceId);
|
|
@@ -790,15 +1192,19 @@ class AlipayAdapter extends BaseAdapter {
|
|
|
790
1192
|
this.updateState(PrinterState.CONNECTING);
|
|
791
1193
|
this.logger.debug("Connecting to device:", deviceId);
|
|
792
1194
|
try {
|
|
1195
|
+
let timeoutId;
|
|
793
1196
|
const connectionPromise = my.createBLEConnection({
|
|
794
1197
|
deviceId
|
|
795
1198
|
});
|
|
796
1199
|
const timeoutPromise = new Promise((_, reject) => {
|
|
797
|
-
setTimeout(() => {
|
|
1200
|
+
timeoutId = setTimeout(() => {
|
|
798
1201
|
reject(new Error("Connection timeout after 10 seconds"));
|
|
799
1202
|
}, 1e4);
|
|
800
1203
|
});
|
|
801
1204
|
yield Promise.race([connectionPromise, timeoutPromise]);
|
|
1205
|
+
if (timeoutId) {
|
|
1206
|
+
clearTimeout(timeoutId);
|
|
1207
|
+
}
|
|
802
1208
|
this.logger.info("BLE connection established");
|
|
803
1209
|
yield this.discoverServices(deviceId);
|
|
804
1210
|
this.updateState(PrinterState.CONNECTED);
|
|
@@ -879,10 +1285,7 @@ class AlipayAdapter extends BaseAdapter {
|
|
|
879
1285
|
});
|
|
880
1286
|
if (!state.connected) {
|
|
881
1287
|
this.cleanupDevice(deviceId);
|
|
882
|
-
throw new BluetoothPrintError(
|
|
883
|
-
ErrorCode.DEVICE_DISCONNECTED,
|
|
884
|
-
"Device disconnected"
|
|
885
|
-
);
|
|
1288
|
+
throw new BluetoothPrintError(ErrorCode.DEVICE_DISCONNECTED, "Device disconnected");
|
|
886
1289
|
}
|
|
887
1290
|
} catch (error) {
|
|
888
1291
|
this.cleanupDevice(deviceId);
|
|
@@ -1010,15 +1413,19 @@ class BaiduAdapter extends BaseAdapter {
|
|
|
1010
1413
|
this.updateState(PrinterState.CONNECTING);
|
|
1011
1414
|
this.logger.debug("Connecting to device:", deviceId);
|
|
1012
1415
|
try {
|
|
1416
|
+
let timeoutId;
|
|
1013
1417
|
const connectionPromise = swan.createBLEConnection({
|
|
1014
1418
|
deviceId
|
|
1015
1419
|
});
|
|
1016
1420
|
const timeoutPromise = new Promise((_, reject) => {
|
|
1017
|
-
setTimeout(() => {
|
|
1421
|
+
timeoutId = setTimeout(() => {
|
|
1018
1422
|
reject(new Error("Connection timeout after 10 seconds"));
|
|
1019
1423
|
}, 1e4);
|
|
1020
1424
|
});
|
|
1021
1425
|
yield Promise.race([connectionPromise, timeoutPromise]);
|
|
1426
|
+
if (timeoutId) {
|
|
1427
|
+
clearTimeout(timeoutId);
|
|
1428
|
+
}
|
|
1022
1429
|
this.logger.info("BLE connection established");
|
|
1023
1430
|
yield this.discoverServices(deviceId);
|
|
1024
1431
|
this.updateState(PrinterState.CONNECTED);
|
|
@@ -1099,10 +1506,7 @@ class BaiduAdapter extends BaseAdapter {
|
|
|
1099
1506
|
});
|
|
1100
1507
|
if (!state.connected) {
|
|
1101
1508
|
this.cleanupDevice(deviceId);
|
|
1102
|
-
throw new BluetoothPrintError(
|
|
1103
|
-
ErrorCode.DEVICE_DISCONNECTED,
|
|
1104
|
-
"Device disconnected"
|
|
1105
|
-
);
|
|
1509
|
+
throw new BluetoothPrintError(ErrorCode.DEVICE_DISCONNECTED, "Device disconnected");
|
|
1106
1510
|
}
|
|
1107
1511
|
} catch (error) {
|
|
1108
1512
|
this.cleanupDevice(deviceId);
|
|
@@ -1230,15 +1634,19 @@ class ByteDanceAdapter extends BaseAdapter {
|
|
|
1230
1634
|
this.updateState(PrinterState.CONNECTING);
|
|
1231
1635
|
this.logger.debug("Connecting to device:", deviceId);
|
|
1232
1636
|
try {
|
|
1637
|
+
let timeoutId;
|
|
1233
1638
|
const connectionPromise = tt.createBLEConnection({
|
|
1234
1639
|
deviceId
|
|
1235
1640
|
});
|
|
1236
1641
|
const timeoutPromise = new Promise((_, reject) => {
|
|
1237
|
-
setTimeout(() => {
|
|
1642
|
+
timeoutId = setTimeout(() => {
|
|
1238
1643
|
reject(new Error("Connection timeout after 10 seconds"));
|
|
1239
1644
|
}, 1e4);
|
|
1240
1645
|
});
|
|
1241
1646
|
yield Promise.race([connectionPromise, timeoutPromise]);
|
|
1647
|
+
if (timeoutId) {
|
|
1648
|
+
clearTimeout(timeoutId);
|
|
1649
|
+
}
|
|
1242
1650
|
this.logger.info("BLE connection established");
|
|
1243
1651
|
yield this.discoverServices(deviceId);
|
|
1244
1652
|
this.updateState(PrinterState.CONNECTED);
|
|
@@ -1319,10 +1727,7 @@ class ByteDanceAdapter extends BaseAdapter {
|
|
|
1319
1727
|
});
|
|
1320
1728
|
if (!state.connected) {
|
|
1321
1729
|
this.cleanupDevice(deviceId);
|
|
1322
|
-
throw new BluetoothPrintError(
|
|
1323
|
-
ErrorCode.DEVICE_DISCONNECTED,
|
|
1324
|
-
"Device disconnected"
|
|
1325
|
-
);
|
|
1730
|
+
throw new BluetoothPrintError(ErrorCode.DEVICE_DISCONNECTED, "Device disconnected");
|
|
1326
1731
|
}
|
|
1327
1732
|
} catch (error) {
|
|
1328
1733
|
this.cleanupDevice(deviceId);
|
|
@@ -1441,201 +1846,902 @@ var PlatformType = /* @__PURE__ */ ((PlatformType2) => {
|
|
|
1441
1846
|
PlatformType2["UNKNOWN"] = "unknown";
|
|
1442
1847
|
return PlatformType2;
|
|
1443
1848
|
})(PlatformType || {});
|
|
1849
|
+
function hasRequestMethod(obj) {
|
|
1850
|
+
return typeof obj === "object" && obj !== null && "request" in obj;
|
|
1851
|
+
}
|
|
1852
|
+
function isWindowWithNavigator(obj) {
|
|
1853
|
+
return typeof obj === "object" && obj !== null && "navigator" in obj;
|
|
1854
|
+
}
|
|
1444
1855
|
function detectPlatform() {
|
|
1445
|
-
if (typeof wx !== "undefined" && wx
|
|
1856
|
+
if (typeof wx !== "undefined" && hasRequestMethod(wx)) {
|
|
1446
1857
|
return "wechat";
|
|
1447
1858
|
}
|
|
1448
|
-
if (typeof my !== "undefined" && my
|
|
1859
|
+
if (typeof my !== "undefined" && hasRequestMethod(my)) {
|
|
1449
1860
|
return "alipay";
|
|
1450
1861
|
}
|
|
1451
|
-
if (typeof swan !== "undefined" && swan
|
|
1862
|
+
if (typeof swan !== "undefined" && hasRequestMethod(swan)) {
|
|
1452
1863
|
return "baidu";
|
|
1453
1864
|
}
|
|
1454
|
-
if (typeof tt !== "undefined" && tt
|
|
1865
|
+
if (typeof tt !== "undefined" && hasRequestMethod(tt)) {
|
|
1455
1866
|
return "bytedance";
|
|
1456
1867
|
}
|
|
1457
|
-
if (typeof window !== "undefined" && window
|
|
1868
|
+
if (typeof window !== "undefined" && isWindowWithNavigator(window)) {
|
|
1458
1869
|
return "web";
|
|
1459
1870
|
}
|
|
1460
|
-
return "unknown";
|
|
1871
|
+
return "unknown";
|
|
1872
|
+
}
|
|
1873
|
+
class AdapterFactory {
|
|
1874
|
+
/**
|
|
1875
|
+
* Creates an adapter instance based on the detected platform
|
|
1876
|
+
*
|
|
1877
|
+
* @returns An instance of the appropriate adapter for the current platform
|
|
1878
|
+
* @throws BluetoothPrintError if the platform is not supported
|
|
1879
|
+
*/
|
|
1880
|
+
static create() {
|
|
1881
|
+
const platform = detectPlatform();
|
|
1882
|
+
switch (platform) {
|
|
1883
|
+
case PlatformType.WECHAT:
|
|
1884
|
+
return new TaroAdapter();
|
|
1885
|
+
case PlatformType.ALIPAY:
|
|
1886
|
+
return new AlipayAdapter();
|
|
1887
|
+
case PlatformType.BAIDU:
|
|
1888
|
+
return new BaiduAdapter();
|
|
1889
|
+
case PlatformType.BYTEDANCE:
|
|
1890
|
+
return new ByteDanceAdapter();
|
|
1891
|
+
default:
|
|
1892
|
+
throw new BluetoothPrintError(
|
|
1893
|
+
ErrorCode.PLATFORM_NOT_SUPPORTED,
|
|
1894
|
+
`Platform ${platform} is not supported. Please use a supported mini-program platform.`
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
/**
|
|
1899
|
+
* Creates an adapter instance for a specific platform
|
|
1900
|
+
*
|
|
1901
|
+
* @param platform - The platform type to create an adapter for
|
|
1902
|
+
* @returns An instance of the appropriate adapter for the specified platform
|
|
1903
|
+
* @throws BluetoothPrintError if the platform is not supported
|
|
1904
|
+
*/
|
|
1905
|
+
static createForPlatform(platform) {
|
|
1906
|
+
switch (platform) {
|
|
1907
|
+
case PlatformType.WECHAT:
|
|
1908
|
+
return new TaroAdapter();
|
|
1909
|
+
case PlatformType.ALIPAY:
|
|
1910
|
+
return new AlipayAdapter();
|
|
1911
|
+
case PlatformType.BAIDU:
|
|
1912
|
+
return new BaiduAdapter();
|
|
1913
|
+
case PlatformType.BYTEDANCE:
|
|
1914
|
+
return new ByteDanceAdapter();
|
|
1915
|
+
default:
|
|
1916
|
+
throw new BluetoothPrintError(
|
|
1917
|
+
ErrorCode.PLATFORM_NOT_SUPPORTED,
|
|
1918
|
+
`Platform ${platform} is not supported.`
|
|
1919
|
+
);
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
1924
|
+
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
1925
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
1926
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
1927
|
+
if (decorator = decorators[i])
|
|
1928
|
+
result = decorator(result) || result;
|
|
1929
|
+
return result;
|
|
1930
|
+
};
|
|
1931
|
+
let ConnectionManager = class {
|
|
1932
|
+
/**
|
|
1933
|
+
* Creates a new ConnectionManager instance
|
|
1934
|
+
*/
|
|
1935
|
+
constructor(adapter) {
|
|
1936
|
+
var _a, _b;
|
|
1937
|
+
this.deviceId = null;
|
|
1938
|
+
this.state = PrinterState.DISCONNECTED;
|
|
1939
|
+
this.logger = Logger.scope("ConnectionManager");
|
|
1940
|
+
this.adapter = adapter || AdapterFactory.create();
|
|
1941
|
+
(_b = (_a = this.adapter).onStateChange) == null ? void 0 : _b.call(_a, (state) => {
|
|
1942
|
+
this.state = state;
|
|
1943
|
+
this.logger.debug("State changed:", state);
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Connects to a Bluetooth device
|
|
1948
|
+
*
|
|
1949
|
+
* @param deviceId - Bluetooth device ID
|
|
1950
|
+
* @returns Promise<void>
|
|
1951
|
+
*/
|
|
1952
|
+
connect(deviceId) {
|
|
1953
|
+
return __async(this, null, function* () {
|
|
1954
|
+
this.logger.info("Connecting to device:", deviceId);
|
|
1955
|
+
try {
|
|
1956
|
+
this.deviceId = deviceId;
|
|
1957
|
+
yield this.adapter.connect(deviceId);
|
|
1958
|
+
this.state = PrinterState.CONNECTED;
|
|
1959
|
+
this.logger.info("Connected successfully");
|
|
1960
|
+
} catch (error) {
|
|
1961
|
+
this.deviceId = null;
|
|
1962
|
+
this.state = PrinterState.DISCONNECTED;
|
|
1963
|
+
const printError = error instanceof BluetoothPrintError ? error : new BluetoothPrintError(
|
|
1964
|
+
ErrorCode.CONNECTION_FAILED,
|
|
1965
|
+
"Connection failed",
|
|
1966
|
+
error
|
|
1967
|
+
);
|
|
1968
|
+
this.logger.error("Connection failed:", printError);
|
|
1969
|
+
throw printError;
|
|
1970
|
+
}
|
|
1971
|
+
});
|
|
1972
|
+
}
|
|
1973
|
+
/**
|
|
1974
|
+
* Disconnects from the current device
|
|
1975
|
+
*
|
|
1976
|
+
* @returns Promise<void>
|
|
1977
|
+
*/
|
|
1978
|
+
disconnect() {
|
|
1979
|
+
return __async(this, null, function* () {
|
|
1980
|
+
if (!this.deviceId) {
|
|
1981
|
+
this.logger.warn("Disconnect called but no device connected");
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
const deviceId = this.deviceId;
|
|
1985
|
+
this.logger.info("Disconnecting from device:", deviceId);
|
|
1986
|
+
try {
|
|
1987
|
+
yield this.adapter.disconnect(deviceId);
|
|
1988
|
+
this.deviceId = null;
|
|
1989
|
+
this.state = PrinterState.DISCONNECTED;
|
|
1990
|
+
this.logger.info("Disconnected successfully");
|
|
1991
|
+
} catch (error) {
|
|
1992
|
+
const printError = new BluetoothPrintError(
|
|
1993
|
+
ErrorCode.DEVICE_DISCONNECTED,
|
|
1994
|
+
"Disconnect failed",
|
|
1995
|
+
error
|
|
1996
|
+
);
|
|
1997
|
+
this.logger.error("Disconnect failed:", printError);
|
|
1998
|
+
throw printError;
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Checks if a device is connected
|
|
2004
|
+
*
|
|
2005
|
+
* @returns boolean - True if connected, false otherwise
|
|
2006
|
+
*/
|
|
2007
|
+
isConnected() {
|
|
2008
|
+
return this.state === PrinterState.CONNECTED;
|
|
2009
|
+
}
|
|
2010
|
+
/**
|
|
2011
|
+
* Gets the current device ID
|
|
2012
|
+
*
|
|
2013
|
+
* @returns string | null - Device ID or null if not connected
|
|
2014
|
+
*/
|
|
2015
|
+
getDeviceId() {
|
|
2016
|
+
return this.deviceId;
|
|
2017
|
+
}
|
|
2018
|
+
/**
|
|
2019
|
+
* Gets the current connection state
|
|
2020
|
+
*
|
|
2021
|
+
* @returns PrinterState - Current state
|
|
2022
|
+
*/
|
|
2023
|
+
getState() {
|
|
2024
|
+
return this.state;
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* Gets the printer adapter instance
|
|
2028
|
+
*
|
|
2029
|
+
* @returns IPrinterAdapter - Printer adapter
|
|
2030
|
+
*/
|
|
2031
|
+
getAdapter() {
|
|
2032
|
+
return this.adapter;
|
|
2033
|
+
}
|
|
2034
|
+
};
|
|
2035
|
+
ConnectionManager = __decorateClass$3([
|
|
2036
|
+
Service()
|
|
2037
|
+
], ConnectionManager);
|
|
2038
|
+
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
2039
|
+
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
2040
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
2041
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
2042
|
+
if (decorator = decorators[i])
|
|
2043
|
+
result = decorator(result) || result;
|
|
2044
|
+
return result;
|
|
2045
|
+
};
|
|
2046
|
+
let PrintJobManager = class {
|
|
2047
|
+
/**
|
|
2048
|
+
* Creates a new PrintJobManager instance
|
|
2049
|
+
*
|
|
2050
|
+
* @param connectionManagerOrAdapter - Connection manager instance or adapter instance (for backward compatibility)
|
|
2051
|
+
* @param adapter - Printer adapter instance (optional, will be taken from connectionManager if not provided)
|
|
2052
|
+
*/
|
|
2053
|
+
constructor(connectionManagerOrAdapter, adapter) {
|
|
2054
|
+
this.jobBuffer = null;
|
|
2055
|
+
this.jobOffset = 0;
|
|
2056
|
+
this._isPaused = false;
|
|
2057
|
+
this._isInProgress = false;
|
|
2058
|
+
this.adapterOptions = {};
|
|
2059
|
+
this.logger = Logger.scope("PrintJobManager");
|
|
2060
|
+
if (adapter) {
|
|
2061
|
+
this.connectionManager = connectionManagerOrAdapter;
|
|
2062
|
+
this.adapter = adapter;
|
|
2063
|
+
} else if (connectionManagerOrAdapter && typeof connectionManagerOrAdapter.connect === "function") {
|
|
2064
|
+
this.adapter = connectionManagerOrAdapter;
|
|
2065
|
+
this.connectionManager = {
|
|
2066
|
+
getDeviceId: () => "test-device",
|
|
2067
|
+
// Default device ID for backward compatibility
|
|
2068
|
+
isConnected: () => true,
|
|
2069
|
+
getState: () => PrinterState.CONNECTED,
|
|
2070
|
+
// Default to CONNECTED
|
|
2071
|
+
connect: () => Promise.resolve(),
|
|
2072
|
+
disconnect: () => Promise.resolve(),
|
|
2073
|
+
getAdapter: () => this.adapter
|
|
2074
|
+
};
|
|
2075
|
+
} else {
|
|
2076
|
+
this.connectionManager = connectionManagerOrAdapter;
|
|
2077
|
+
if (this.connectionManager && typeof this.connectionManager.getAdapter === "function") {
|
|
2078
|
+
this.adapter = this.connectionManager.getAdapter();
|
|
2079
|
+
} else {
|
|
2080
|
+
throw new Error(
|
|
2081
|
+
"Printer adapter not provided and could not be retrieved from connection manager"
|
|
2082
|
+
);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
/**
|
|
2087
|
+
* Starts a print job
|
|
2088
|
+
*
|
|
2089
|
+
* @param buffer - Print data buffer
|
|
2090
|
+
* @returns Promise<void>
|
|
2091
|
+
*/
|
|
2092
|
+
start(buffer) {
|
|
2093
|
+
return __async(this, null, function* () {
|
|
2094
|
+
if (this._isInProgress) {
|
|
2095
|
+
throw new BluetoothPrintError(
|
|
2096
|
+
ErrorCode.PRINT_JOB_IN_PROGRESS,
|
|
2097
|
+
"A print job is already in progress. Wait for completion or cancel it."
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
this.logger.info(`Starting print job: ${buffer.length} bytes`);
|
|
2101
|
+
this.jobBuffer = buffer;
|
|
2102
|
+
this.jobOffset = 0;
|
|
2103
|
+
this._isPaused = false;
|
|
2104
|
+
this._isInProgress = true;
|
|
2105
|
+
try {
|
|
2106
|
+
yield this.processJob();
|
|
2107
|
+
if (this._isPaused) {
|
|
2108
|
+
this.logger.info("Print job paused");
|
|
2109
|
+
} else {
|
|
2110
|
+
this.logger.info("Print job completed successfully");
|
|
2111
|
+
this._isInProgress = false;
|
|
2112
|
+
this.jobBuffer = null;
|
|
2113
|
+
this.jobOffset = 0;
|
|
2114
|
+
}
|
|
2115
|
+
} catch (error) {
|
|
2116
|
+
this.logger.error("Print job failed:", error);
|
|
2117
|
+
this._isInProgress = false;
|
|
2118
|
+
this.jobBuffer = null;
|
|
2119
|
+
this.jobOffset = 0;
|
|
2120
|
+
const printError = error instanceof BluetoothPrintError ? error : new BluetoothPrintError(ErrorCode.PRINT_JOB_FAILED, "Print job failed", error);
|
|
2121
|
+
throw printError;
|
|
2122
|
+
}
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Pauses the current print job
|
|
2127
|
+
*/
|
|
2128
|
+
pause() {
|
|
2129
|
+
if (!this._isInProgress) {
|
|
2130
|
+
this.logger.warn("Pause called but no print job in progress");
|
|
2131
|
+
return;
|
|
2132
|
+
}
|
|
2133
|
+
this._isPaused = true;
|
|
2134
|
+
this.logger.info("Print job paused");
|
|
2135
|
+
}
|
|
2136
|
+
/**
|
|
2137
|
+
* Resumes a paused print job
|
|
2138
|
+
*
|
|
2139
|
+
* @returns Promise<void>
|
|
2140
|
+
*/
|
|
2141
|
+
resume() {
|
|
2142
|
+
return __async(this, null, function* () {
|
|
2143
|
+
if (!this._isInProgress || !this._isPaused) {
|
|
2144
|
+
this.logger.warn("Resume called but no paused print job");
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
this._isPaused = false;
|
|
2148
|
+
this.logger.info("Print job resumed");
|
|
2149
|
+
try {
|
|
2150
|
+
yield this.processJob();
|
|
2151
|
+
if (!this._isPaused) {
|
|
2152
|
+
this.logger.info("Print job completed successfully");
|
|
2153
|
+
this._isInProgress = false;
|
|
2154
|
+
this.jobBuffer = null;
|
|
2155
|
+
this.jobOffset = 0;
|
|
2156
|
+
}
|
|
2157
|
+
} catch (error) {
|
|
2158
|
+
this.logger.error("Print job failed after resume:", error);
|
|
2159
|
+
this._isInProgress = false;
|
|
2160
|
+
this.jobBuffer = null;
|
|
2161
|
+
this.jobOffset = 0;
|
|
2162
|
+
const printError = error instanceof BluetoothPrintError ? error : new BluetoothPrintError(ErrorCode.PRINT_JOB_FAILED, "Print job failed", error);
|
|
2163
|
+
throw printError;
|
|
2164
|
+
}
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Cancels the current print job
|
|
2169
|
+
*/
|
|
2170
|
+
cancel() {
|
|
2171
|
+
if (!this._isInProgress) {
|
|
2172
|
+
this.logger.warn("Cancel called but no print job in progress");
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
this._isPaused = false;
|
|
2176
|
+
this._isInProgress = false;
|
|
2177
|
+
this.jobBuffer = null;
|
|
2178
|
+
this.jobOffset = 0;
|
|
2179
|
+
this.logger.info("Print job cancelled");
|
|
2180
|
+
}
|
|
2181
|
+
/**
|
|
2182
|
+
* Gets the number of bytes remaining to print
|
|
2183
|
+
*
|
|
2184
|
+
* @returns number - Bytes remaining
|
|
2185
|
+
*/
|
|
2186
|
+
remaining() {
|
|
2187
|
+
if (this.jobBuffer) {
|
|
2188
|
+
return this.jobBuffer.length - this.jobOffset;
|
|
2189
|
+
}
|
|
2190
|
+
return 0;
|
|
2191
|
+
}
|
|
2192
|
+
/**
|
|
2193
|
+
* Checks if the print job is paused
|
|
2194
|
+
*
|
|
2195
|
+
* @returns boolean - True if paused, false otherwise
|
|
2196
|
+
*/
|
|
2197
|
+
isPaused() {
|
|
2198
|
+
return this._isPaused;
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* Checks if a print job is in progress
|
|
2202
|
+
*
|
|
2203
|
+
* @returns boolean - True if in progress, false otherwise
|
|
2204
|
+
*/
|
|
2205
|
+
isInProgress() {
|
|
2206
|
+
return this._isInProgress;
|
|
2207
|
+
}
|
|
2208
|
+
/**
|
|
2209
|
+
* Sets adapter options for write operations
|
|
2210
|
+
*
|
|
2211
|
+
* @param options - Adapter options
|
|
2212
|
+
*/
|
|
2213
|
+
setOptions(options) {
|
|
2214
|
+
this.adapterOptions = __spreadValues(__spreadValues({}, this.adapterOptions), options);
|
|
2215
|
+
this.logger.debug("Adapter options updated:", this.adapterOptions);
|
|
2216
|
+
}
|
|
2217
|
+
/**
|
|
2218
|
+
* Processes the print job in chunks
|
|
2219
|
+
* Supports pause/resume functionality
|
|
2220
|
+
*
|
|
2221
|
+
* @returns Promise<void>
|
|
2222
|
+
*/
|
|
2223
|
+
processJob() {
|
|
2224
|
+
return __async(this, null, function* () {
|
|
2225
|
+
if (!this.jobBuffer) {
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
if (!this.adapter || typeof this.adapter.write !== "function") {
|
|
2229
|
+
throw new BluetoothPrintError(
|
|
2230
|
+
ErrorCode.INVALID_CONFIGURATION,
|
|
2231
|
+
"Printer adapter does not support write operation"
|
|
2232
|
+
);
|
|
2233
|
+
}
|
|
2234
|
+
const printerChunkSize = 512;
|
|
2235
|
+
const total = this.jobBuffer.length;
|
|
2236
|
+
const jobBuffer = this.jobBuffer;
|
|
2237
|
+
try {
|
|
2238
|
+
while (this.jobOffset < jobBuffer.length) {
|
|
2239
|
+
if (this._isPaused) {
|
|
2240
|
+
this.logger.debug("Job paused at offset:", this.jobOffset);
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2243
|
+
const end = Math.min(this.jobOffset + printerChunkSize, jobBuffer.length);
|
|
2244
|
+
const chunk = jobBuffer.slice(this.jobOffset, end);
|
|
2245
|
+
yield this.adapter.write(this.getDeviceId(), chunk.buffer, this.adapterOptions);
|
|
2246
|
+
this.jobOffset = end;
|
|
2247
|
+
this.logger.debug(`Processed ${this.jobOffset}/${total} bytes`);
|
|
2248
|
+
}
|
|
2249
|
+
} catch (error) {
|
|
2250
|
+
this.logger.error("Error processing job:", error);
|
|
2251
|
+
throw error;
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Gets the current device ID from the connection manager
|
|
2257
|
+
*
|
|
2258
|
+
* @returns string - Device ID
|
|
2259
|
+
* @throws BluetoothPrintError if no device is connected
|
|
2260
|
+
*/
|
|
2261
|
+
getDeviceId() {
|
|
2262
|
+
const deviceId = this.connectionManager.getDeviceId();
|
|
2263
|
+
if (!deviceId) {
|
|
2264
|
+
throw new BluetoothPrintError(ErrorCode.DEVICE_DISCONNECTED, "Device ID not available");
|
|
2265
|
+
}
|
|
2266
|
+
return deviceId;
|
|
2267
|
+
}
|
|
2268
|
+
};
|
|
2269
|
+
PrintJobManager = __decorateClass$2([
|
|
2270
|
+
Service()
|
|
2271
|
+
], PrintJobManager);
|
|
2272
|
+
const logger = Logger.scope("Encoding");
|
|
2273
|
+
const _Encoding = class _Encoding {
|
|
2274
|
+
/**
|
|
2275
|
+
* Configures the encoding utility
|
|
2276
|
+
*
|
|
2277
|
+
* @param config - Configuration options
|
|
2278
|
+
*
|
|
2279
|
+
* @example
|
|
2280
|
+
* ```typescript
|
|
2281
|
+
* Encoding.configure({
|
|
2282
|
+
* showWarnings: false
|
|
2283
|
+
* });
|
|
2284
|
+
* ```
|
|
2285
|
+
*/
|
|
2286
|
+
static configure(config) {
|
|
2287
|
+
this.config = __spreadValues(__spreadValues({}, this.config), config);
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Encodes a string to a Uint8Array using the specified encoding
|
|
2291
|
+
*
|
|
2292
|
+
* @param text - Text to encode
|
|
2293
|
+
* @param encoding - Target encoding (default: 'GBK')
|
|
2294
|
+
* @returns Encoded bytes
|
|
2295
|
+
*
|
|
2296
|
+
* @remarks
|
|
2297
|
+
* Note: Native TextEncoder only supports UTF-8.
|
|
2298
|
+
* For GBK encoding, a third-party library or polyfill is recommended.
|
|
2299
|
+
* Currently falls back to UTF-8 with a warning (configurable).
|
|
2300
|
+
*
|
|
2301
|
+
* @example
|
|
2302
|
+
* ```typescript
|
|
2303
|
+
* // UTF-8 encoding
|
|
2304
|
+
* const utf8 = Encoding.encode('Hello', 'UTF-8');
|
|
2305
|
+
*
|
|
2306
|
+
* // GBK encoding (currently falls back to UTF-8)
|
|
2307
|
+
* const gbk = Encoding.encode('你好', 'GBK');
|
|
2308
|
+
* ```
|
|
2309
|
+
*/
|
|
2310
|
+
static encode(text, encoding = "GBK") {
|
|
2311
|
+
if (!text || typeof text !== "string") {
|
|
2312
|
+
return new Uint8Array(0);
|
|
2313
|
+
}
|
|
2314
|
+
const normalizedEncoding = encoding.toUpperCase().replace("-", "");
|
|
2315
|
+
if (normalizedEncoding === "UTF8" || normalizedEncoding === "UTF-8") {
|
|
2316
|
+
return this.utf8Encoder.encode(text);
|
|
2317
|
+
}
|
|
2318
|
+
if (this.config.showWarnings && !this.warningShown) {
|
|
2319
|
+
logger.warn(
|
|
2320
|
+
`Encoding ${encoding} not yet fully implemented, falling back to UTF-8. This may cause display issues with some printers.`
|
|
2321
|
+
);
|
|
2322
|
+
this.warningShown = true;
|
|
2323
|
+
}
|
|
2324
|
+
return this.utf8Encoder.encode(text);
|
|
2325
|
+
}
|
|
2326
|
+
/**
|
|
2327
|
+
* Checks if an encoding is supported
|
|
2328
|
+
*
|
|
2329
|
+
* @param encoding - Encoding name to check
|
|
2330
|
+
* @returns True if supported, false otherwise
|
|
2331
|
+
*
|
|
2332
|
+
* @example
|
|
2333
|
+
* ```typescript
|
|
2334
|
+
* if (Encoding.isSupported('GBK')) {
|
|
2335
|
+
* console.log('GBK is supported');
|
|
2336
|
+
* }
|
|
2337
|
+
* ```
|
|
2338
|
+
*/
|
|
2339
|
+
static isSupported(encoding) {
|
|
2340
|
+
if (!encoding || typeof encoding !== "string") {
|
|
2341
|
+
return false;
|
|
2342
|
+
}
|
|
2343
|
+
const normalizedEncoding = encoding.toUpperCase().replace("-", "");
|
|
2344
|
+
return normalizedEncoding === "UTF8" || normalizedEncoding === "UTF-8";
|
|
2345
|
+
}
|
|
2346
|
+
};
|
|
2347
|
+
_Encoding.utf8Encoder = new TextEncoder();
|
|
2348
|
+
_Encoding.warningShown = false;
|
|
2349
|
+
_Encoding.config = {
|
|
2350
|
+
showWarnings: true
|
|
2351
|
+
};
|
|
2352
|
+
let Encoding = _Encoding;
|
|
2353
|
+
class ImageProcessing {
|
|
2354
|
+
/**
|
|
2355
|
+
* Convert RGBA data to monochrome bitmap (1 bit per pixel)
|
|
2356
|
+
* suitable for ESC/POS GS v 0 command.
|
|
2357
|
+
* Uses Floyd-Steinberg dithering for better quality.
|
|
2358
|
+
*
|
|
2359
|
+
* @param data - RGBA pixel data as Uint8Array
|
|
2360
|
+
* @param width - Image width in pixels
|
|
2361
|
+
* @param height - Image height in pixels
|
|
2362
|
+
* @returns Monochrome bitmap data as Uint8Array
|
|
2363
|
+
*
|
|
2364
|
+
* @example
|
|
2365
|
+
* ```typescript
|
|
2366
|
+
* const imageData = new Uint8Array(width * height * 4); // RGBA
|
|
2367
|
+
* const bitmap = ImageProcessing.toBitmap(imageData, width, height);
|
|
2368
|
+
* ```
|
|
2369
|
+
*/
|
|
2370
|
+
static toBitmap(data, width, height) {
|
|
2371
|
+
if (!data || !(data instanceof Uint8Array) || width <= 0 || height <= 0) {
|
|
2372
|
+
return new Uint8Array(0);
|
|
2373
|
+
}
|
|
2374
|
+
if (data.length !== width * height * 4) {
|
|
2375
|
+
throw new Error(
|
|
2376
|
+
`Invalid image data length: expected ${width * height * 4}, got ${data.length}`
|
|
2377
|
+
);
|
|
2378
|
+
}
|
|
2379
|
+
const bytesPerLine = Math.ceil(width / 8);
|
|
2380
|
+
const bitmap = new Uint8Array(bytesPerLine * height);
|
|
2381
|
+
const grayscale = new Float32Array(width * height);
|
|
2382
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
2383
|
+
const index = i / 4;
|
|
2384
|
+
const r = data[i] || 0;
|
|
2385
|
+
const g = data[i + 1] || 0;
|
|
2386
|
+
const b = data[i + 2] || 0;
|
|
2387
|
+
grayscale[index] = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
2388
|
+
}
|
|
2389
|
+
for (let y = 0; y < height; y++) {
|
|
2390
|
+
for (let x = 0; x < width; x++) {
|
|
2391
|
+
const index = y * width + x;
|
|
2392
|
+
const oldPixel = grayscale[index] || 0;
|
|
2393
|
+
const newPixel = oldPixel < 128 ? 0 : 255;
|
|
2394
|
+
if (newPixel === 0) {
|
|
2395
|
+
const byteIndex = y * bytesPerLine + Math.floor(x / 8);
|
|
2396
|
+
const bitIndex = 7 - x % 8;
|
|
2397
|
+
bitmap[byteIndex] = (bitmap[byteIndex] || 0) | 1 << bitIndex;
|
|
2398
|
+
}
|
|
2399
|
+
const quantError = oldPixel - newPixel;
|
|
2400
|
+
this.distributeError(grayscale, width, height, x, y, quantError);
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
return bitmap;
|
|
2404
|
+
}
|
|
2405
|
+
/**
|
|
2406
|
+
* Distribute quantization error to neighboring pixels using Floyd-Steinberg algorithm
|
|
2407
|
+
*
|
|
2408
|
+
* @param grayscale - Grayscale image data
|
|
2409
|
+
* @param width - Image width
|
|
2410
|
+
* @param height - Image height
|
|
2411
|
+
* @param x - Current x position
|
|
2412
|
+
* @param y - Current y position
|
|
2413
|
+
* @param error - Quantization error to distribute
|
|
2414
|
+
*/
|
|
2415
|
+
static distributeError(grayscale, width, height, x, y, error) {
|
|
2416
|
+
const distribute = (dx, dy, factor) => {
|
|
2417
|
+
const nx = x + dx;
|
|
2418
|
+
const ny = y + dy;
|
|
2419
|
+
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
2420
|
+
const index = ny * width + nx;
|
|
2421
|
+
grayscale[index] = Math.max(0, Math.min(255, (grayscale[index] || 0) + error * factor));
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
distribute(1, 0, 7 / 16);
|
|
2425
|
+
distribute(-1, 1, 3 / 16);
|
|
2426
|
+
distribute(0, 1, 5 / 16);
|
|
2427
|
+
distribute(1, 1, 1 / 16);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
class EscPos {
|
|
2431
|
+
constructor() {
|
|
2432
|
+
this.logger = Logger.scope("EscPos");
|
|
2433
|
+
}
|
|
2434
|
+
/**
|
|
2435
|
+
* Initializes the printer
|
|
2436
|
+
* Sends ESC @ command to reset printer to default state
|
|
2437
|
+
*
|
|
2438
|
+
* @returns Array of command buffers
|
|
2439
|
+
*/
|
|
2440
|
+
init() {
|
|
2441
|
+
return [new Uint8Array([27, 64])];
|
|
2442
|
+
}
|
|
2443
|
+
/**
|
|
2444
|
+
* Generates text print command
|
|
2445
|
+
*
|
|
2446
|
+
* @param content - Text content to print
|
|
2447
|
+
* @param encoding - Text encoding (default: 'GBK')
|
|
2448
|
+
* @returns Array of command buffers
|
|
2449
|
+
*
|
|
2450
|
+
* @example
|
|
2451
|
+
* ```typescript
|
|
2452
|
+
* driver.text('你好世界', 'GBK');
|
|
2453
|
+
* ```
|
|
2454
|
+
*/
|
|
2455
|
+
text(content, encoding = "GBK") {
|
|
2456
|
+
if (!content || typeof content !== "string") {
|
|
2457
|
+
return [];
|
|
2458
|
+
}
|
|
2459
|
+
const encoded = Encoding.encode(content, encoding);
|
|
2460
|
+
return [encoded];
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Generates line feed command
|
|
2464
|
+
*
|
|
2465
|
+
* @param lines - Number of lines to feed (default: 1)
|
|
2466
|
+
* @returns Array of command buffers
|
|
2467
|
+
*
|
|
2468
|
+
* @example
|
|
2469
|
+
* ```typescript
|
|
2470
|
+
* driver.feed(3); // Feed 3 lines
|
|
2471
|
+
* ```
|
|
2472
|
+
*/
|
|
2473
|
+
feed(lines = 1) {
|
|
2474
|
+
const safeLines = Math.max(1, Math.min(255, Math.floor(lines)));
|
|
2475
|
+
return [new Uint8Array([27, 100, safeLines])];
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
* Generates paper cut command
|
|
2479
|
+
*
|
|
2480
|
+
* @returns Array of command buffers
|
|
2481
|
+
*
|
|
2482
|
+
* @example
|
|
2483
|
+
* ```typescript
|
|
2484
|
+
* driver.cut();
|
|
2485
|
+
* ```
|
|
2486
|
+
*/
|
|
2487
|
+
cut() {
|
|
2488
|
+
return [new Uint8Array([29, 86, 0])];
|
|
2489
|
+
}
|
|
2490
|
+
/**
|
|
2491
|
+
* Generates image print command
|
|
2492
|
+
* Uses Floyd-Steinberg dithering for better quality
|
|
2493
|
+
*
|
|
2494
|
+
* @param data - RGBA pixel data
|
|
2495
|
+
* @param width - Image width in pixels
|
|
2496
|
+
* @param height - Image height in pixels
|
|
2497
|
+
* @returns Array of command buffers
|
|
2498
|
+
*
|
|
2499
|
+
* @example
|
|
2500
|
+
* ```typescript
|
|
2501
|
+
* const imageData = new Uint8Array(width * height * 4); // RGBA
|
|
2502
|
+
* driver.image(imageData, 200, 100);
|
|
2503
|
+
* ```
|
|
2504
|
+
*/
|
|
2505
|
+
image(data, width, height) {
|
|
2506
|
+
if (!data || !(data instanceof Uint8Array) || width <= 0 || height <= 0) {
|
|
2507
|
+
return [];
|
|
2508
|
+
}
|
|
2509
|
+
if (data.length !== width * height * 4) {
|
|
2510
|
+
this.logger.warn(
|
|
2511
|
+
`Invalid image data length: expected ${width * height * 4}, got ${data.length}`
|
|
2512
|
+
);
|
|
2513
|
+
return [];
|
|
2514
|
+
}
|
|
2515
|
+
const bitmap = ImageProcessing.toBitmap(data, width, height);
|
|
2516
|
+
const bytesPerLine = Math.ceil(width / 8);
|
|
2517
|
+
const xL = bytesPerLine % 256;
|
|
2518
|
+
const xH = Math.floor(bytesPerLine / 256);
|
|
2519
|
+
const yL = height % 256;
|
|
2520
|
+
const yH = Math.floor(height / 256);
|
|
2521
|
+
const header = new Uint8Array([29, 118, 48, 0, xL, xH, yL, yH]);
|
|
2522
|
+
return [header, bitmap];
|
|
2523
|
+
}
|
|
2524
|
+
/**
|
|
2525
|
+
* Generates QR code print command
|
|
2526
|
+
*
|
|
2527
|
+
* @param content - QR code content (URL, text, etc.)
|
|
2528
|
+
* @param options - QR code options
|
|
2529
|
+
* @returns Array of command buffers
|
|
2530
|
+
*
|
|
2531
|
+
* @example
|
|
2532
|
+
* ```typescript
|
|
2533
|
+
* driver.qr('https://example.com', {
|
|
2534
|
+
* model: 2,
|
|
2535
|
+
* size: 8,
|
|
2536
|
+
* errorCorrection: 'M'
|
|
2537
|
+
* });
|
|
2538
|
+
* ```
|
|
2539
|
+
*/
|
|
2540
|
+
qr(content, options) {
|
|
2541
|
+
var _a, _b, _c, _d;
|
|
2542
|
+
if (!content || typeof content !== "string") {
|
|
2543
|
+
return [];
|
|
2544
|
+
}
|
|
2545
|
+
const model = (_a = options == null ? void 0 : options.model) != null ? _a : 2;
|
|
2546
|
+
const size = Math.max(1, Math.min(16, (_b = options == null ? void 0 : options.size) != null ? _b : 6));
|
|
2547
|
+
const errorCorrection = (_c = options == null ? void 0 : options.errorCorrection) != null ? _c : "M";
|
|
2548
|
+
const commands = [];
|
|
2549
|
+
commands.push(
|
|
2550
|
+
new Uint8Array([29, 40, 107, 4, 0, 49, 65, model === 1 ? 49 : 50, 0])
|
|
2551
|
+
);
|
|
2552
|
+
commands.push(new Uint8Array([29, 40, 107, 3, 0, 49, 67, size]));
|
|
2553
|
+
const ecMap = { L: 48, M: 49, Q: 50, H: 51 };
|
|
2554
|
+
const ecValue = (_d = ecMap[errorCorrection]) != null ? _d : 49;
|
|
2555
|
+
commands.push(new Uint8Array([29, 40, 107, 3, 0, 49, 69, ecValue]));
|
|
2556
|
+
const data = Encoding.encode(content, "GBK");
|
|
2557
|
+
const len = data.length + 3;
|
|
2558
|
+
const pL = len % 256;
|
|
2559
|
+
const pH = Math.floor(len / 256);
|
|
2560
|
+
commands.push(new Uint8Array([29, 40, 107, pL, pH, 49, 80, 48]));
|
|
2561
|
+
commands.push(data);
|
|
2562
|
+
commands.push(new Uint8Array([29, 40, 107, 3, 0, 49, 81, 48]));
|
|
2563
|
+
return commands;
|
|
2564
|
+
}
|
|
1461
2565
|
}
|
|
1462
|
-
|
|
2566
|
+
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
2567
|
+
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
2568
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
2569
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
2570
|
+
if (decorator = decorators[i])
|
|
2571
|
+
result = decorator(result) || result;
|
|
2572
|
+
return result;
|
|
2573
|
+
};
|
|
2574
|
+
let CommandBuilder = class {
|
|
1463
2575
|
/**
|
|
1464
|
-
* Creates
|
|
1465
|
-
*
|
|
1466
|
-
* @
|
|
1467
|
-
* @throws BluetoothPrintError if the platform is not supported
|
|
2576
|
+
* Creates a new CommandBuilder instance
|
|
2577
|
+
*
|
|
2578
|
+
* @param driver - Printer driver instance
|
|
1468
2579
|
*/
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
case PlatformType.ALIPAY:
|
|
1475
|
-
return new AlipayAdapter();
|
|
1476
|
-
case PlatformType.BAIDU:
|
|
1477
|
-
return new BaiduAdapter();
|
|
1478
|
-
case PlatformType.BYTEDANCE:
|
|
1479
|
-
return new ByteDanceAdapter();
|
|
1480
|
-
default:
|
|
1481
|
-
throw new BluetoothPrintError(
|
|
1482
|
-
ErrorCode.PLATFORM_NOT_SUPPORTED,
|
|
1483
|
-
`Platform ${platform} is not supported. Please use a supported mini-program platform.`
|
|
1484
|
-
);
|
|
1485
|
-
}
|
|
2580
|
+
constructor(driver) {
|
|
2581
|
+
this.buffer = [];
|
|
2582
|
+
this.logger = Logger.scope("CommandBuilder");
|
|
2583
|
+
this.driver = driver || new EscPos();
|
|
2584
|
+
this.buffer.push(...this.driver.init());
|
|
1486
2585
|
}
|
|
1487
2586
|
/**
|
|
1488
|
-
*
|
|
1489
|
-
*
|
|
1490
|
-
* @param
|
|
1491
|
-
* @
|
|
1492
|
-
* @
|
|
2587
|
+
* Adds text to the print queue
|
|
2588
|
+
*
|
|
2589
|
+
* @param content - Text content
|
|
2590
|
+
* @param encoding - Text encoding
|
|
2591
|
+
* @returns this - For method chaining
|
|
1493
2592
|
*/
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
case PlatformType.ALIPAY:
|
|
1499
|
-
return new AlipayAdapter();
|
|
1500
|
-
case PlatformType.BAIDU:
|
|
1501
|
-
return new BaiduAdapter();
|
|
1502
|
-
case PlatformType.BYTEDANCE:
|
|
1503
|
-
return new ByteDanceAdapter();
|
|
1504
|
-
default:
|
|
1505
|
-
throw new BluetoothPrintError(
|
|
1506
|
-
ErrorCode.PLATFORM_NOT_SUPPORTED,
|
|
1507
|
-
`Platform ${platform} is not supported.`
|
|
1508
|
-
);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
class EventEmitter {
|
|
1513
|
-
constructor() {
|
|
1514
|
-
this.listeners = /* @__PURE__ */ new Map();
|
|
2593
|
+
text(content, encoding) {
|
|
2594
|
+
this.logger.debug("Adding text:", content.substring(0, 50));
|
|
2595
|
+
this.buffer.push(...this.driver.text(content, encoding));
|
|
2596
|
+
return this;
|
|
1515
2597
|
}
|
|
1516
2598
|
/**
|
|
1517
|
-
*
|
|
2599
|
+
* Adds line feeds to the print queue
|
|
1518
2600
|
*
|
|
1519
|
-
* @param
|
|
1520
|
-
* @
|
|
1521
|
-
* @returns Unsubscribe function
|
|
2601
|
+
* @param lines - Number of lines to feed
|
|
2602
|
+
* @returns this - For method chaining
|
|
1522
2603
|
*/
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
this.listeners.get(event).add(handler);
|
|
1528
|
-
return () => this.off(event, handler);
|
|
2604
|
+
feed(lines = 1) {
|
|
2605
|
+
this.logger.debug("Adding feed:", lines);
|
|
2606
|
+
this.buffer.push(...this.driver.feed(lines));
|
|
2607
|
+
return this;
|
|
1529
2608
|
}
|
|
1530
2609
|
/**
|
|
1531
|
-
*
|
|
2610
|
+
* Adds a paper cut command to the print queue
|
|
1532
2611
|
*
|
|
1533
|
-
* @
|
|
1534
|
-
* @param handler - Event handler function
|
|
1535
|
-
* @returns Unsubscribe function
|
|
2612
|
+
* @returns this - For method chaining
|
|
1536
2613
|
*/
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
};
|
|
1542
|
-
return this.on(event, wrappedHandler);
|
|
2614
|
+
cut() {
|
|
2615
|
+
this.logger.debug("Adding cut command");
|
|
2616
|
+
this.buffer.push(...this.driver.cut());
|
|
2617
|
+
return this;
|
|
1543
2618
|
}
|
|
1544
2619
|
/**
|
|
1545
|
-
*
|
|
2620
|
+
* Adds an image to the print queue
|
|
1546
2621
|
*
|
|
1547
|
-
* @param
|
|
1548
|
-
* @param
|
|
2622
|
+
* @param data - Image data as Uint8Array
|
|
2623
|
+
* @param width - Image width
|
|
2624
|
+
* @param height - Image height
|
|
2625
|
+
* @returns this - For method chaining
|
|
1549
2626
|
*/
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
if (handlers.size === 0) {
|
|
1555
|
-
this.listeners.delete(event);
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
2627
|
+
image(data, width, height) {
|
|
2628
|
+
this.logger.debug(`Adding image: ${width}x${height}`);
|
|
2629
|
+
this.buffer.push(...this.driver.image(data, width, height));
|
|
2630
|
+
return this;
|
|
1558
2631
|
}
|
|
1559
2632
|
/**
|
|
1560
|
-
*
|
|
2633
|
+
* Adds a QR code to the print queue
|
|
1561
2634
|
*
|
|
1562
|
-
* @param
|
|
1563
|
-
* @param
|
|
2635
|
+
* @param content - QR code content
|
|
2636
|
+
* @param options - QR code options
|
|
2637
|
+
* @returns this - For method chaining
|
|
1564
2638
|
*/
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
}
|
|
1570
|
-
const handlersCopy = new Set(handlers);
|
|
1571
|
-
handlersCopy.forEach((handler) => {
|
|
1572
|
-
try {
|
|
1573
|
-
if (data === void 0 && data === null) {
|
|
1574
|
-
handler("");
|
|
1575
|
-
} else {
|
|
1576
|
-
handler(data);
|
|
1577
|
-
}
|
|
1578
|
-
} catch (error) {
|
|
1579
|
-
console.error(`Error in event handler for "${String(event)}":`, error);
|
|
1580
|
-
}
|
|
1581
|
-
});
|
|
2639
|
+
qr(content, options) {
|
|
2640
|
+
this.logger.debug("Adding QR code:", content.substring(0, 50));
|
|
2641
|
+
this.buffer.push(...this.driver.qr(content, options));
|
|
2642
|
+
return this;
|
|
1582
2643
|
}
|
|
1583
2644
|
/**
|
|
1584
|
-
*
|
|
1585
|
-
*
|
|
2645
|
+
* Clears the print queue
|
|
2646
|
+
*
|
|
2647
|
+
* @returns this - For method chaining
|
|
1586
2648
|
*/
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
}
|
|
2649
|
+
clear() {
|
|
2650
|
+
this.logger.debug("Clearing buffer");
|
|
2651
|
+
this.buffer = [];
|
|
2652
|
+
this.buffer.push(...this.driver.init());
|
|
2653
|
+
return this;
|
|
1593
2654
|
}
|
|
1594
2655
|
/**
|
|
1595
|
-
*
|
|
2656
|
+
* Gets the current buffer
|
|
1596
2657
|
*
|
|
1597
|
-
* @
|
|
1598
|
-
* @returns Number of listeners
|
|
2658
|
+
* @returns Uint8Array - Current print buffer
|
|
1599
2659
|
*/
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
2660
|
+
getBuffer() {
|
|
2661
|
+
const totalLength = this.buffer.reduce((acc, b) => acc + b.length, 0);
|
|
2662
|
+
const combined = new Uint8Array(totalLength);
|
|
2663
|
+
let offset = 0;
|
|
2664
|
+
for (const b of this.buffer) {
|
|
2665
|
+
combined.set(b, offset);
|
|
2666
|
+
offset += b.length;
|
|
2667
|
+
}
|
|
2668
|
+
return combined;
|
|
1603
2669
|
}
|
|
1604
2670
|
/**
|
|
1605
|
-
*
|
|
2671
|
+
* Gets the total number of bytes in the buffer
|
|
1606
2672
|
*
|
|
1607
|
-
* @
|
|
1608
|
-
* @returns True if there are listeners, false otherwise
|
|
2673
|
+
* @returns number - Total bytes
|
|
1609
2674
|
*/
|
|
1610
|
-
|
|
1611
|
-
return this.
|
|
2675
|
+
getTotalBytes() {
|
|
2676
|
+
return this.buffer.reduce((acc, b) => acc + b.length, 0);
|
|
1612
2677
|
}
|
|
1613
|
-
}
|
|
1614
|
-
|
|
2678
|
+
};
|
|
2679
|
+
CommandBuilder = __decorateClass$1([
|
|
2680
|
+
Service()
|
|
2681
|
+
], CommandBuilder);
|
|
2682
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
2683
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
2684
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
2685
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
2686
|
+
if (decorator = decorators[i])
|
|
2687
|
+
result = decorator(result) || result;
|
|
2688
|
+
return result;
|
|
2689
|
+
};
|
|
2690
|
+
let BluetoothPrinter = class extends EventEmitter {
|
|
1615
2691
|
/**
|
|
1616
2692
|
* Creates a new BluetoothPrinter instance
|
|
1617
2693
|
*
|
|
1618
|
-
* @param
|
|
1619
|
-
* @param
|
|
2694
|
+
* @param connectionManagerOrAdapter - Connection manager instance or printer adapter instance (for backward compatibility)
|
|
2695
|
+
* @param printJobManagerOrDriver - Print job manager instance or printer driver instance (for backward compatibility)
|
|
2696
|
+
* @param commandBuilder - Command builder instance (optional)
|
|
1620
2697
|
*/
|
|
1621
|
-
constructor(
|
|
1622
|
-
var _a, _b;
|
|
2698
|
+
constructor(connectionManagerOrAdapter, printJobManagerOrDriver, commandBuilder) {
|
|
1623
2699
|
super();
|
|
1624
|
-
this.deviceId = null;
|
|
1625
|
-
this.buffer = [];
|
|
1626
|
-
this.adapterOptions = {};
|
|
1627
|
-
this.isPaused = false;
|
|
1628
|
-
this.jobBuffer = null;
|
|
1629
|
-
this.jobOffset = 0;
|
|
1630
2700
|
this.logger = Logger.scope("BluetoothPrinter");
|
|
1631
2701
|
this.state = PrinterState.DISCONNECTED;
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
this.
|
|
1636
|
-
this.
|
|
1637
|
-
this.
|
|
1638
|
-
}
|
|
2702
|
+
if (connectionManagerOrAdapter && typeof connectionManagerOrAdapter.connect === "function") {
|
|
2703
|
+
const adapter = connectionManagerOrAdapter;
|
|
2704
|
+
const driver = printJobManagerOrDriver;
|
|
2705
|
+
this.connectionManager = new ConnectionManager(adapter);
|
|
2706
|
+
this.printJobManager = new PrintJobManager(this.connectionManager, adapter);
|
|
2707
|
+
this.commandBuilder = new CommandBuilder(driver);
|
|
2708
|
+
} else {
|
|
2709
|
+
this.connectionManager = connectionManagerOrAdapter;
|
|
2710
|
+
this.printJobManager = printJobManagerOrDriver;
|
|
2711
|
+
this.commandBuilder = commandBuilder;
|
|
2712
|
+
if (!this.connectionManager) {
|
|
2713
|
+
this.connectionManager = new ConnectionManager();
|
|
2714
|
+
this.printJobManager = new PrintJobManager(this.connectionManager);
|
|
2715
|
+
this.commandBuilder = new CommandBuilder();
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
this.updateState();
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Updates the current state based on the connection manager and print job manager states
|
|
2722
|
+
*/
|
|
2723
|
+
updateState() {
|
|
2724
|
+
let connectionState;
|
|
2725
|
+
if (this.connectionManager && typeof this.connectionManager.getState === "function") {
|
|
2726
|
+
connectionState = this.connectionManager.getState();
|
|
2727
|
+
} else {
|
|
2728
|
+
connectionState = PrinterState.CONNECTED;
|
|
2729
|
+
}
|
|
2730
|
+
let isPrinting = false;
|
|
2731
|
+
let isPaused = false;
|
|
2732
|
+
if (this.printJobManager) {
|
|
2733
|
+
isPrinting = typeof this.printJobManager.isInProgress === "function" ? this.printJobManager.isInProgress() : false;
|
|
2734
|
+
isPaused = typeof this.printJobManager.isPaused === "function" ? this.printJobManager.isPaused() : false;
|
|
2735
|
+
}
|
|
2736
|
+
if (isPaused) {
|
|
2737
|
+
this.state = PrinterState.PAUSED;
|
|
2738
|
+
} else if (isPrinting) {
|
|
2739
|
+
this.state = PrinterState.PRINTING;
|
|
2740
|
+
} else {
|
|
2741
|
+
this.state = connectionState;
|
|
2742
|
+
}
|
|
2743
|
+
this.emit("state-change", this.state);
|
|
2744
|
+
this.logger.debug("State updated:", this.state);
|
|
1639
2745
|
}
|
|
1640
2746
|
/**
|
|
1641
2747
|
* Connects to a Bluetooth device
|
|
@@ -1653,20 +2759,19 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1653
2759
|
return __async(this, null, function* () {
|
|
1654
2760
|
this.logger.info("Connecting to device:", deviceId);
|
|
1655
2761
|
try {
|
|
1656
|
-
this.deviceId
|
|
1657
|
-
|
|
1658
|
-
this.buffer.push(...this.driver.init());
|
|
2762
|
+
yield this.connectionManager.connect(deviceId);
|
|
2763
|
+
this.updateState();
|
|
1659
2764
|
this.emit("connected", deviceId);
|
|
1660
2765
|
this.logger.info("Connected successfully");
|
|
1661
2766
|
return this;
|
|
1662
2767
|
} catch (error) {
|
|
1663
|
-
this.deviceId = null;
|
|
1664
2768
|
const printError = error instanceof BluetoothPrintError ? error : new BluetoothPrintError(
|
|
1665
2769
|
ErrorCode.CONNECTION_FAILED,
|
|
1666
2770
|
"Connection failed",
|
|
1667
2771
|
error
|
|
1668
2772
|
);
|
|
1669
2773
|
this.emit("error", printError);
|
|
2774
|
+
this.updateState();
|
|
1670
2775
|
throw printError;
|
|
1671
2776
|
}
|
|
1672
2777
|
});
|
|
@@ -1683,18 +2788,16 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1683
2788
|
*/
|
|
1684
2789
|
disconnect() {
|
|
1685
2790
|
return __async(this, null, function* () {
|
|
1686
|
-
|
|
2791
|
+
const deviceId = this.connectionManager.getDeviceId();
|
|
2792
|
+
if (!deviceId) {
|
|
1687
2793
|
this.logger.warn("Disconnect called but no device connected");
|
|
1688
2794
|
return;
|
|
1689
2795
|
}
|
|
1690
|
-
const deviceId = this.deviceId;
|
|
1691
2796
|
this.logger.info("Disconnecting from device:", deviceId);
|
|
1692
2797
|
try {
|
|
1693
|
-
yield this.
|
|
1694
|
-
this.
|
|
1695
|
-
this.
|
|
1696
|
-
this.jobBuffer = null;
|
|
1697
|
-
this.jobOffset = 0;
|
|
2798
|
+
yield this.connectionManager.disconnect();
|
|
2799
|
+
this.printJobManager.cancel();
|
|
2800
|
+
this.updateState();
|
|
1698
2801
|
this.emit("disconnected", deviceId);
|
|
1699
2802
|
this.logger.info("Disconnected successfully");
|
|
1700
2803
|
} catch (error) {
|
|
@@ -1704,6 +2807,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1704
2807
|
error
|
|
1705
2808
|
);
|
|
1706
2809
|
this.emit("error", printError);
|
|
2810
|
+
this.updateState();
|
|
1707
2811
|
throw printError;
|
|
1708
2812
|
}
|
|
1709
2813
|
});
|
|
@@ -1721,8 +2825,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1721
2825
|
* ```
|
|
1722
2826
|
*/
|
|
1723
2827
|
text(content, encoding) {
|
|
1724
|
-
this.
|
|
1725
|
-
this.buffer.push(...this.driver.text(content, encoding));
|
|
2828
|
+
this.commandBuilder.text(content, encoding);
|
|
1726
2829
|
return this;
|
|
1727
2830
|
}
|
|
1728
2831
|
/**
|
|
@@ -1737,8 +2840,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1737
2840
|
* ```
|
|
1738
2841
|
*/
|
|
1739
2842
|
feed(lines = 1) {
|
|
1740
|
-
this.
|
|
1741
|
-
this.buffer.push(...this.driver.feed(lines));
|
|
2843
|
+
this.commandBuilder.feed(lines);
|
|
1742
2844
|
return this;
|
|
1743
2845
|
}
|
|
1744
2846
|
/**
|
|
@@ -1752,8 +2854,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1752
2854
|
* ```
|
|
1753
2855
|
*/
|
|
1754
2856
|
cut() {
|
|
1755
|
-
this.
|
|
1756
|
-
this.buffer.push(...this.driver.cut());
|
|
2857
|
+
this.commandBuilder.cut();
|
|
1757
2858
|
return this;
|
|
1758
2859
|
}
|
|
1759
2860
|
/**
|
|
@@ -1771,8 +2872,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1771
2872
|
* ```
|
|
1772
2873
|
*/
|
|
1773
2874
|
image(data, width, height) {
|
|
1774
|
-
this.
|
|
1775
|
-
this.buffer.push(...this.driver.image(data, width, height));
|
|
2875
|
+
this.commandBuilder.image(data, width, height);
|
|
1776
2876
|
return this;
|
|
1777
2877
|
}
|
|
1778
2878
|
/**
|
|
@@ -1788,8 +2888,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1788
2888
|
* ```
|
|
1789
2889
|
*/
|
|
1790
2890
|
qr(content, options) {
|
|
1791
|
-
this.
|
|
1792
|
-
this.buffer.push(...this.driver.qr(content, options));
|
|
2891
|
+
this.commandBuilder.qr(content, options);
|
|
1793
2892
|
return this;
|
|
1794
2893
|
}
|
|
1795
2894
|
/**
|
|
@@ -1804,8 +2903,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1804
2903
|
* ```
|
|
1805
2904
|
*/
|
|
1806
2905
|
setOptions(options) {
|
|
1807
|
-
this.
|
|
1808
|
-
this.logger.debug("Adapter options updated:", this.adapterOptions);
|
|
2906
|
+
this.printJobManager.setOptions(options);
|
|
1809
2907
|
return this;
|
|
1810
2908
|
}
|
|
1811
2909
|
/**
|
|
@@ -1820,9 +2918,8 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1820
2918
|
* ```
|
|
1821
2919
|
*/
|
|
1822
2920
|
pause() {
|
|
1823
|
-
this.
|
|
1824
|
-
this.
|
|
1825
|
-
this.emit("state-change", PrinterState.PAUSED);
|
|
2921
|
+
this.printJobManager.pause();
|
|
2922
|
+
this.updateState();
|
|
1826
2923
|
this.logger.info("Print job paused");
|
|
1827
2924
|
}
|
|
1828
2925
|
/**
|
|
@@ -1837,16 +2934,11 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1837
2934
|
*/
|
|
1838
2935
|
resume() {
|
|
1839
2936
|
return __async(this, null, function* () {
|
|
1840
|
-
|
|
1841
|
-
this.logger.warn("Resume called but job not paused or no job buffer");
|
|
1842
|
-
return;
|
|
1843
|
-
}
|
|
1844
|
-
this.isPaused = false;
|
|
1845
|
-
this.state = PrinterState.PRINTING;
|
|
1846
|
-
this.emit("state-change", PrinterState.PRINTING);
|
|
1847
|
-
this.logger.info("Print job resumed");
|
|
2937
|
+
this.logger.info("Resuming print job");
|
|
1848
2938
|
try {
|
|
1849
|
-
yield this.
|
|
2939
|
+
yield this.printJobManager.resume();
|
|
2940
|
+
this.updateState();
|
|
2941
|
+
this.logger.info("Print job resumed");
|
|
1850
2942
|
} catch (error) {
|
|
1851
2943
|
const printError = new BluetoothPrintError(
|
|
1852
2944
|
ErrorCode.PRINT_JOB_FAILED,
|
|
@@ -1854,6 +2946,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1854
2946
|
error
|
|
1855
2947
|
);
|
|
1856
2948
|
this.emit("error", printError);
|
|
2949
|
+
this.updateState();
|
|
1857
2950
|
throw printError;
|
|
1858
2951
|
}
|
|
1859
2952
|
});
|
|
@@ -1867,12 +2960,9 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1867
2960
|
* ```
|
|
1868
2961
|
*/
|
|
1869
2962
|
cancel() {
|
|
1870
|
-
this.
|
|
1871
|
-
this.
|
|
1872
|
-
this.
|
|
1873
|
-
this.buffer = [];
|
|
1874
|
-
this.state = this.deviceId ? PrinterState.CONNECTED : PrinterState.DISCONNECTED;
|
|
1875
|
-
this.emit("state-change", this.state);
|
|
2963
|
+
this.printJobManager.cancel();
|
|
2964
|
+
this.commandBuilder.clear();
|
|
2965
|
+
this.updateState();
|
|
1876
2966
|
this.logger.info("Print job cancelled");
|
|
1877
2967
|
}
|
|
1878
2968
|
/**
|
|
@@ -1886,10 +2976,7 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1886
2976
|
* ```
|
|
1887
2977
|
*/
|
|
1888
2978
|
remaining() {
|
|
1889
|
-
|
|
1890
|
-
return this.jobBuffer.length - this.jobOffset;
|
|
1891
|
-
}
|
|
1892
|
-
return this.buffer.reduce((acc, b) => acc + b.length, 0);
|
|
2979
|
+
return this.printJobManager.remaining();
|
|
1893
2980
|
}
|
|
1894
2981
|
/**
|
|
1895
2982
|
* Sends all queued commands to the printer
|
|
@@ -1907,91 +2994,39 @@ class BluetoothPrinter extends EventEmitter {
|
|
|
1907
2994
|
*/
|
|
1908
2995
|
print() {
|
|
1909
2996
|
return __async(this, null, function* () {
|
|
1910
|
-
if (!this.
|
|
2997
|
+
if (!this.connectionManager.isConnected()) {
|
|
1911
2998
|
throw new BluetoothPrintError(
|
|
1912
2999
|
ErrorCode.CONNECTION_FAILED,
|
|
1913
3000
|
"Printer not connected. Call connect() first."
|
|
1914
3001
|
);
|
|
1915
3002
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
);
|
|
1921
|
-
}
|
|
1922
|
-
const totalLength = this.buffer.reduce((acc, b) => acc + b.length, 0);
|
|
1923
|
-
this.logger.info(`Starting print job: ${totalLength} bytes`);
|
|
1924
|
-
const combined = new Uint8Array(totalLength);
|
|
1925
|
-
let offset = 0;
|
|
1926
|
-
for (const b of this.buffer) {
|
|
1927
|
-
combined.set(b, offset);
|
|
1928
|
-
offset += b.length;
|
|
1929
|
-
}
|
|
1930
|
-
this.jobBuffer = combined;
|
|
1931
|
-
this.jobOffset = 0;
|
|
1932
|
-
this.buffer = [];
|
|
1933
|
-
this.isPaused = false;
|
|
1934
|
-
this.state = PrinterState.PRINTING;
|
|
1935
|
-
this.emit("state-change", this.state);
|
|
3003
|
+
const buffer = this.commandBuilder.getBuffer();
|
|
3004
|
+
this.logger.info(`Starting print job: ${buffer.length} bytes`);
|
|
3005
|
+
this.commandBuilder.clear();
|
|
3006
|
+
this.updateState();
|
|
1936
3007
|
try {
|
|
1937
|
-
yield this.
|
|
1938
|
-
|
|
3008
|
+
yield this.printJobManager.start(buffer);
|
|
3009
|
+
const isPaused = typeof this.printJobManager.isPaused === "function" ? this.printJobManager.isPaused() : false;
|
|
3010
|
+
if (isPaused) {
|
|
1939
3011
|
this.logger.info("Print job paused");
|
|
1940
3012
|
} else {
|
|
1941
3013
|
this.emit("print-complete");
|
|
1942
3014
|
this.logger.info("Print job completed successfully");
|
|
1943
|
-
this.state = PrinterState.CONNECTED;
|
|
1944
|
-
this.emit("state-change", this.state);
|
|
1945
3015
|
}
|
|
1946
3016
|
} catch (error) {
|
|
3017
|
+
this.logger.error("Print job failed with error:", error);
|
|
1947
3018
|
const printError = error instanceof BluetoothPrintError ? error : new BluetoothPrintError(ErrorCode.PRINT_JOB_FAILED, "Print job failed", error);
|
|
1948
3019
|
this.emit("error", printError);
|
|
1949
|
-
this.state = PrinterState.CONNECTED;
|
|
1950
|
-
this.emit("state-change", this.state);
|
|
1951
3020
|
throw printError;
|
|
1952
|
-
}
|
|
1953
|
-
});
|
|
1954
|
-
}
|
|
1955
|
-
/**
|
|
1956
|
-
* Processes the print job in chunks
|
|
1957
|
-
* Supports pause/resume and emits progress events
|
|
1958
|
-
*/
|
|
1959
|
-
processJob() {
|
|
1960
|
-
return __async(this, null, function* () {
|
|
1961
|
-
if (!this.jobBuffer || !this.deviceId) return;
|
|
1962
|
-
const printerChunkSize = 512;
|
|
1963
|
-
const total = this.jobBuffer.length;
|
|
1964
|
-
const deviceId = this.deviceId;
|
|
1965
|
-
const jobBuffer = this.jobBuffer;
|
|
1966
|
-
try {
|
|
1967
|
-
while (this.jobOffset < jobBuffer.length) {
|
|
1968
|
-
if (this.isPaused) {
|
|
1969
|
-
this.logger.debug("Job paused at offset:", this.jobOffset);
|
|
1970
|
-
return;
|
|
1971
|
-
}
|
|
1972
|
-
if (this.state !== PrinterState.CONNECTED && this.state !== PrinterState.PRINTING && this.state !== PrinterState.PAUSED) {
|
|
1973
|
-
throw new BluetoothPrintError(
|
|
1974
|
-
ErrorCode.DEVICE_DISCONNECTED,
|
|
1975
|
-
"Device disconnected during print job"
|
|
1976
|
-
);
|
|
1977
|
-
}
|
|
1978
|
-
const end = Math.min(this.jobOffset + printerChunkSize, jobBuffer.length);
|
|
1979
|
-
const chunk = jobBuffer.slice(this.jobOffset, end);
|
|
1980
|
-
yield this.adapter.write(deviceId, chunk.buffer, this.adapterOptions);
|
|
1981
|
-
this.jobOffset = end;
|
|
1982
|
-
if (this.hasListeners("progress")) {
|
|
1983
|
-
this.emit("progress", { sent: this.jobOffset, total });
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
3021
|
} finally {
|
|
1987
|
-
|
|
1988
|
-
this.jobBuffer = null;
|
|
1989
|
-
this.jobOffset = 0;
|
|
1990
|
-
}
|
|
3022
|
+
this.updateState();
|
|
1991
3023
|
}
|
|
1992
3024
|
});
|
|
1993
3025
|
}
|
|
1994
|
-
}
|
|
3026
|
+
};
|
|
3027
|
+
BluetoothPrinter = __decorateClass([
|
|
3028
|
+
Service()
|
|
3029
|
+
], BluetoothPrinter);
|
|
1995
3030
|
const DEFAULT_CONFIG = {
|
|
1996
3031
|
adapter: {
|
|
1997
3032
|
chunkSize: 20,
|