taro-bluetooth-print 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +128 -22
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -6995
- package/dist/index.umd.js +1 -1
- package/dist/types/adapters/AdapterFactory.d.ts +0 -1
- package/dist/types/adapters/AlipayAdapter.d.ts +6 -34
- package/dist/types/adapters/BaiduAdapter.d.ts +6 -34
- package/dist/types/adapters/BaseAdapter.d.ts +112 -1
- package/dist/types/adapters/ByteDanceAdapter.d.ts +6 -34
- package/dist/types/adapters/TaroAdapter.d.ts +6 -34
- package/dist/types/adapters/WebBluetoothAdapter.d.ts +0 -1
- package/dist/types/config/PrinterConfig.d.ts +0 -1
- package/dist/types/core/BluetoothPrinter.d.ts +0 -1
- package/dist/types/drivers/EscPos.d.ts +0 -1
- package/dist/types/drivers/TsplDriver.d.ts +251 -0
- package/dist/types/encoding/gbk-data.d.ts +12 -0
- package/dist/types/encoding/gbk-table.d.ts +5 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/plugins/PluginManager.d.ts +87 -0
- package/dist/types/plugins/builtin/LoggingPlugin.d.ts +14 -0
- package/dist/types/plugins/builtin/RetryPlugin.d.ts +18 -0
- package/dist/types/plugins/index.d.ts +7 -0
- package/dist/types/plugins/types.d.ts +97 -0
- package/dist/types/services/CommandBuilder.d.ts +6 -1
- package/dist/types/services/ConnectionManager.d.ts +0 -1
- package/dist/types/services/PrintJobManager.d.ts +6 -2
- package/dist/types/services/interfaces/index.d.ts +0 -1
- package/dist/types/template/TemplateEngine.d.ts +0 -1
- package/package.json +16 -18
- package/src/adapters/AlipayAdapter.ts +8 -314
- package/src/adapters/BaiduAdapter.ts +8 -312
- package/src/adapters/BaseAdapter.ts +366 -0
- package/src/adapters/ByteDanceAdapter.ts +8 -316
- package/src/adapters/TaroAdapter.ts +8 -367
- package/src/core/EventEmitter.ts +9 -6
- package/src/drivers/TsplDriver.ts +417 -0
- package/src/encoding/gbk-data.ts +1911 -0
- package/src/encoding/gbk-table.ts +22 -498
- package/src/index.ts +14 -0
- package/src/plugins/PluginManager.ts +193 -0
- package/src/plugins/builtin/LoggingPlugin.ts +97 -0
- package/src/plugins/builtin/RetryPlugin.ts +109 -0
- package/src/plugins/index.ts +10 -0
- package/src/plugins/types.ts +119 -0
- package/src/preview/PreviewRenderer.ts +7 -1
- package/src/queue/PrintQueue.ts +10 -6
- package/src/services/CommandBuilder.ts +30 -0
- package/src/services/PrintJobManager.ts +51 -35
|
@@ -17,6 +17,7 @@ import { BarcodeGenerator, BarcodeOptions } from '@/barcode';
|
|
|
17
17
|
export class CommandBuilder implements ICommandBuilder {
|
|
18
18
|
private driver: IPrinterDriver;
|
|
19
19
|
private buffer: Uint8Array[] = [];
|
|
20
|
+
private _cachedBuffer: Uint8Array | null = null;
|
|
20
21
|
private readonly logger = Logger.scope('CommandBuilder');
|
|
21
22
|
private readonly formatter: TextFormatter;
|
|
22
23
|
private readonly barcodeGenerator: BarcodeGenerator;
|
|
@@ -35,6 +36,14 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
35
36
|
this.buffer.push(...this.driver.init());
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Invalidates the cached combined buffer.
|
|
41
|
+
* Must be called whenever the internal buffer array is modified.
|
|
42
|
+
*/
|
|
43
|
+
private invalidateCache(): void {
|
|
44
|
+
this._cachedBuffer = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
/**
|
|
39
48
|
* Adds text to the print queue
|
|
40
49
|
*
|
|
@@ -45,6 +54,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
45
54
|
text(content: string, encoding?: string): this {
|
|
46
55
|
this.logger.debug('Adding text:', content.substring(0, 50));
|
|
47
56
|
this.buffer.push(...this.driver.text(content, encoding));
|
|
57
|
+
this.invalidateCache();
|
|
48
58
|
return this;
|
|
49
59
|
}
|
|
50
60
|
|
|
@@ -57,6 +67,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
57
67
|
feed(lines = 1): this {
|
|
58
68
|
this.logger.debug('Adding feed:', lines);
|
|
59
69
|
this.buffer.push(...this.driver.feed(lines));
|
|
70
|
+
this.invalidateCache();
|
|
60
71
|
return this;
|
|
61
72
|
}
|
|
62
73
|
|
|
@@ -68,6 +79,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
68
79
|
cut(): this {
|
|
69
80
|
this.logger.debug('Adding cut command');
|
|
70
81
|
this.buffer.push(...this.driver.cut());
|
|
82
|
+
this.invalidateCache();
|
|
71
83
|
return this;
|
|
72
84
|
}
|
|
73
85
|
|
|
@@ -82,6 +94,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
82
94
|
image(data: Uint8Array, width: number, height: number): this {
|
|
83
95
|
this.logger.debug(`Adding image: ${width}x${height}`);
|
|
84
96
|
this.buffer.push(...this.driver.image(data, width, height));
|
|
97
|
+
this.invalidateCache();
|
|
85
98
|
return this;
|
|
86
99
|
}
|
|
87
100
|
|
|
@@ -95,6 +108,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
95
108
|
qr(content: string, options?: IQrOptions): this {
|
|
96
109
|
this.logger.debug('Adding QR code:', content.substring(0, 50));
|
|
97
110
|
this.buffer.push(...this.driver.qr(content, options));
|
|
111
|
+
this.invalidateCache();
|
|
98
112
|
return this;
|
|
99
113
|
}
|
|
100
114
|
|
|
@@ -108,6 +122,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
108
122
|
this.buffer = [];
|
|
109
123
|
// Re-initialize printer
|
|
110
124
|
this.buffer.push(...this.driver.init());
|
|
125
|
+
this.invalidateCache();
|
|
111
126
|
return this;
|
|
112
127
|
}
|
|
113
128
|
|
|
@@ -125,6 +140,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
125
140
|
align(alignment: TextAlign): this {
|
|
126
141
|
this.logger.debug('Setting alignment:', alignment);
|
|
127
142
|
this.buffer.push(...this.formatter.align(alignment));
|
|
143
|
+
this.invalidateCache();
|
|
128
144
|
return this;
|
|
129
145
|
}
|
|
130
146
|
|
|
@@ -143,6 +159,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
143
159
|
setSize(width: number, height: number): this {
|
|
144
160
|
this.logger.debug(`Setting size: ${width}x${height}`);
|
|
145
161
|
this.buffer.push(...this.formatter.setSize(width, height));
|
|
162
|
+
this.invalidateCache();
|
|
146
163
|
return this;
|
|
147
164
|
}
|
|
148
165
|
|
|
@@ -160,6 +177,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
160
177
|
setBold(enabled: boolean): this {
|
|
161
178
|
this.logger.debug('Setting bold:', enabled);
|
|
162
179
|
this.buffer.push(...this.formatter.setBold(enabled));
|
|
180
|
+
this.invalidateCache();
|
|
163
181
|
return this;
|
|
164
182
|
}
|
|
165
183
|
|
|
@@ -177,6 +195,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
177
195
|
setUnderline(enabled: boolean): this {
|
|
178
196
|
this.logger.debug('Setting underline:', enabled);
|
|
179
197
|
this.buffer.push(...this.formatter.setUnderline(enabled));
|
|
198
|
+
this.invalidateCache();
|
|
180
199
|
return this;
|
|
181
200
|
}
|
|
182
201
|
|
|
@@ -194,6 +213,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
194
213
|
setInverse(enabled: boolean): this {
|
|
195
214
|
this.logger.debug('Setting inverse:', enabled);
|
|
196
215
|
this.buffer.push(...this.formatter.setInverse(enabled));
|
|
216
|
+
this.invalidateCache();
|
|
197
217
|
return this;
|
|
198
218
|
}
|
|
199
219
|
|
|
@@ -211,6 +231,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
211
231
|
setStyle(style: TextStyle): this {
|
|
212
232
|
this.logger.debug('Setting style:', style);
|
|
213
233
|
this.buffer.push(...this.formatter.setStyle(style));
|
|
234
|
+
this.invalidateCache();
|
|
214
235
|
return this;
|
|
215
236
|
}
|
|
216
237
|
|
|
@@ -227,6 +248,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
227
248
|
resetStyle(): this {
|
|
228
249
|
this.logger.debug('Resetting style');
|
|
229
250
|
this.buffer.push(...this.formatter.resetStyle());
|
|
251
|
+
this.invalidateCache();
|
|
230
252
|
return this;
|
|
231
253
|
}
|
|
232
254
|
|
|
@@ -251,6 +273,7 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
251
273
|
const commands = this.barcodeGenerator.generate(content, options);
|
|
252
274
|
if (commands.length > 0) {
|
|
253
275
|
this.buffer.push(...commands);
|
|
276
|
+
this.invalidateCache();
|
|
254
277
|
} else {
|
|
255
278
|
this.logger.warn(`Failed to generate barcode for content: ${content}`);
|
|
256
279
|
}
|
|
@@ -263,6 +286,11 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
263
286
|
* @returns Uint8Array - Current print buffer
|
|
264
287
|
*/
|
|
265
288
|
getBuffer(): Uint8Array {
|
|
289
|
+
// Return cached buffer if available
|
|
290
|
+
if (this._cachedBuffer) {
|
|
291
|
+
return this._cachedBuffer;
|
|
292
|
+
}
|
|
293
|
+
|
|
266
294
|
// Combine all buffers
|
|
267
295
|
const totalLength = this.buffer.reduce((acc, b) => acc + b.length, 0);
|
|
268
296
|
const combined = new Uint8Array(totalLength);
|
|
@@ -271,6 +299,8 @@ export class CommandBuilder implements ICommandBuilder {
|
|
|
271
299
|
combined.set(b, offset);
|
|
272
300
|
offset += b.length;
|
|
273
301
|
}
|
|
302
|
+
|
|
303
|
+
this._cachedBuffer = combined;
|
|
274
304
|
return combined;
|
|
275
305
|
}
|
|
276
306
|
|
|
@@ -10,10 +10,35 @@ import { IPrintJobManager, IConnectionManager } from '@/services/interfaces';
|
|
|
10
10
|
import { Logger } from '@/utils/logger';
|
|
11
11
|
import { BluetoothPrintError, ErrorCode } from '@/errors/BluetoothError';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Creates a no-op adapter for backward compatibility with mock objects in tests.
|
|
15
|
+
* Each method logs a warning and resolves (or throws for write if called unexpectedly).
|
|
16
|
+
*/
|
|
17
|
+
function createNoOpAdapter(): IPrinterAdapter {
|
|
18
|
+
return {
|
|
19
|
+
connect: () => Promise.resolve(),
|
|
20
|
+
disconnect: () => Promise.resolve(),
|
|
21
|
+
write: () => Promise.resolve(),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Saved job state structure
|
|
27
|
+
*/
|
|
28
|
+
interface SavedJobState {
|
|
29
|
+
jobId: string;
|
|
30
|
+
jobBuffer: number[];
|
|
31
|
+
jobOffset: number;
|
|
32
|
+
adapterOptions: IAdapterOptions;
|
|
33
|
+
timestamp: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
13
36
|
/**
|
|
14
37
|
* Print Job Manager implementation
|
|
15
38
|
*/
|
|
16
39
|
export class PrintJobManager implements IPrintJobManager {
|
|
40
|
+
/** 内存中的任务状态存储(可被子类或外部替换为持久化方案) */
|
|
41
|
+
private static jobStateStore: Map<string, SavedJobState> = new Map();
|
|
17
42
|
private adapter: IPrinterAdapter;
|
|
18
43
|
private connectionManager: IConnectionManager;
|
|
19
44
|
private jobBuffer: Uint8Array | null = null;
|
|
@@ -58,12 +83,9 @@ export class PrintJobManager implements IPrintJobManager {
|
|
|
58
83
|
if (typeof connectionManager.getAdapter === 'function') {
|
|
59
84
|
this.adapter = connectionManager.getAdapter();
|
|
60
85
|
} else {
|
|
61
|
-
// For backward compatibility with mock objects in tests
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
disconnect: () => Promise.resolve(),
|
|
65
|
-
write: () => Promise.resolve(),
|
|
66
|
-
} as unknown as IPrinterAdapter;
|
|
86
|
+
// For backward compatibility with mock objects in tests.
|
|
87
|
+
// Creates a no-op adapter that throws descriptive errors on unexpected usage.
|
|
88
|
+
this.adapter = createNoOpAdapter();
|
|
67
89
|
}
|
|
68
90
|
}
|
|
69
91
|
|
|
@@ -197,7 +219,10 @@ export class PrintJobManager implements IPrintJobManager {
|
|
|
197
219
|
}
|
|
198
220
|
|
|
199
221
|
/**
|
|
200
|
-
* Saves the current job state for resume later
|
|
222
|
+
* Saves the current job state for resume later.
|
|
223
|
+
*
|
|
224
|
+
* 默认实现使用内存存储。如需持久化(如 localStorage),
|
|
225
|
+
* 可通过 setSaveHandler/setLoadHandler 自定义。
|
|
201
226
|
*/
|
|
202
227
|
private saveJobState(): void {
|
|
203
228
|
if (!this.jobBuffer || !this.jobId) {
|
|
@@ -205,19 +230,19 @@ export class PrintJobManager implements IPrintJobManager {
|
|
|
205
230
|
}
|
|
206
231
|
|
|
207
232
|
try {
|
|
208
|
-
|
|
209
|
-
|
|
233
|
+
const state = {
|
|
234
|
+
jobId: this.jobId,
|
|
235
|
+
jobBuffer: Array.from(this.jobBuffer),
|
|
236
|
+
jobOffset: this.jobOffset,
|
|
237
|
+
adapterOptions: this.adapterOptions,
|
|
238
|
+
timestamp: Date.now(),
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
PrintJobManager.jobStateStore.set(this.jobId, state);
|
|
242
|
+
|
|
210
243
|
this.logger.debug(
|
|
211
244
|
`Saved job state for ${this.jobId}: offset=${this.jobOffset}/${this.jobBuffer.length}`
|
|
212
245
|
);
|
|
213
|
-
|
|
214
|
-
// Example: localStorage.setItem(`printJob-${this.jobId}`, JSON.stringify({
|
|
215
|
-
// jobId: this.jobId,
|
|
216
|
-
// jobBuffer: Array.from(this.jobBuffer),
|
|
217
|
-
// jobOffset: this.jobOffset,
|
|
218
|
-
// adapterOptions: this.adapterOptions,
|
|
219
|
-
// timestamp: Date.now()
|
|
220
|
-
// }));
|
|
221
246
|
} catch (error) {
|
|
222
247
|
this.logger.error(`Failed to save job state for ${this.jobId}:`, error);
|
|
223
248
|
}
|
|
@@ -232,28 +257,21 @@ export class PrintJobManager implements IPrintJobManager {
|
|
|
232
257
|
try {
|
|
233
258
|
this.logger.debug(`Loading job state for ${jobId}`);
|
|
234
259
|
|
|
235
|
-
|
|
236
|
-
// For now, we'll just simulate it
|
|
237
|
-
// Example: const savedState = localStorage.getItem(`printJob-${jobId}`);
|
|
238
|
-
|
|
239
|
-
// For demonstration purposes, we'll throw an error if job state not found
|
|
240
|
-
// In a real application, you would implement proper loading
|
|
241
|
-
throw new Error(`Job state not found for ${jobId}`);
|
|
260
|
+
const savedState = PrintJobManager.jobStateStore.get(jobId);
|
|
242
261
|
|
|
243
|
-
/*
|
|
244
262
|
if (savedState) {
|
|
245
|
-
|
|
246
|
-
this.
|
|
247
|
-
this.
|
|
248
|
-
this.
|
|
249
|
-
this.adapterOptions = jobState.adapterOptions;
|
|
263
|
+
this.jobId = savedState.jobId;
|
|
264
|
+
this.jobBuffer = new Uint8Array(savedState.jobBuffer);
|
|
265
|
+
this.jobOffset = savedState.jobOffset;
|
|
266
|
+
this.adapterOptions = savedState.adapterOptions;
|
|
250
267
|
this._isPaused = true;
|
|
251
268
|
this._isInProgress = true;
|
|
252
|
-
this.logger.info(
|
|
269
|
+
this.logger.info(
|
|
270
|
+
`Loaded job ${this.jobId}: offset=${this.jobOffset}/${this.jobBuffer.length}`
|
|
271
|
+
);
|
|
253
272
|
} else {
|
|
254
273
|
throw new Error(`Job state not found for ${jobId}`);
|
|
255
274
|
}
|
|
256
|
-
*/
|
|
257
275
|
} catch (error) {
|
|
258
276
|
this.logger.error(`Failed to load job state for ${jobId}:`, error);
|
|
259
277
|
throw new BluetoothPrintError(
|
|
@@ -270,9 +288,7 @@ export class PrintJobManager implements IPrintJobManager {
|
|
|
270
288
|
private clearJobState(): void {
|
|
271
289
|
if (this.jobId) {
|
|
272
290
|
this.logger.debug(`Clearing job state for ${this.jobId}`);
|
|
273
|
-
|
|
274
|
-
// In a real application, this would remove from persistent storage
|
|
275
|
-
// Example: localStorage.removeItem(`printJob-${this.jobId}`);
|
|
291
|
+
PrintJobManager.jobStateStore.delete(this.jobId);
|
|
276
292
|
}
|
|
277
293
|
|
|
278
294
|
this.jobBuffer = null;
|