label-printer 0.2.2 → 0.2.4

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/dist/index.d.mts CHANGED
@@ -179,7 +179,6 @@ declare class TSPLBitmapCommand extends TSPLVisualCommand {
179
179
  private readonly bitmap;
180
180
  private readonly mode;
181
181
  /**
182
- *
183
182
  * @param bitmap Bitmap to present.
184
183
  * @param x X coordinates in dots
185
184
  * @param y Y Coordinates in dots
@@ -191,6 +190,17 @@ declare class TSPLBitmapCommand extends TSPLVisualCommand {
191
190
  private get commandWithoutBytes();
192
191
  private get modeValue();
193
192
  write(device: UsbDevice): Promise<void>;
193
+ /**
194
+ * Create a new bitmap command for the given image url
195
+ * @param image Image to create command for
196
+ * @param x X coordinate of the image
197
+ * @param y Y coordinate of the image
198
+ * @param imageWidth Desired width of the image
199
+ * @param imageHeight Desired height of the image
200
+ * @param mode Graphics mode
201
+ * @returns
202
+ */
203
+ static forImageUrl(image: string, x: number, y: number, imageWidth?: number, imageHeight?: number, mode?: GraphicMode): Promise<TSPLBitmapCommand>;
194
204
  }
195
205
 
196
206
  /**
@@ -425,7 +435,7 @@ declare abstract class Printer {
425
435
  * Writes a command to the printers usb
426
436
  * @param command Command to send to the usb
427
437
  */
428
- protected writeCommand(command: Command): Promise<void>;
438
+ writeCommand(command: Command): Promise<void>;
429
439
  /**
430
440
  * Check if the device is indeed a printer
431
441
  * @param device
@@ -444,6 +454,14 @@ declare class PrinterService {
444
454
  * @returns List of available printers
445
455
  */
446
456
  static getPrinters(): Promise<Printer[]>;
457
+ /**
458
+ * This is intended to be used in the browser although it also works in node
459
+ * In the browser, it provides a UI for the user to choose a USB device and if it is a
460
+ * printer, it returns a new printer instance. In Node however, this will try to create
461
+ * a printer for the first available device and returns it. This means that even if there is a
462
+ * printer, it may return undefined. In node, use `getPrinters` instead
463
+ */
464
+ static requestPrinter(): Promise<Printer | undefined>;
447
465
  }
448
466
 
449
467
  type index_Printer = Printer;
package/dist/index.d.ts CHANGED
@@ -179,7 +179,6 @@ declare class TSPLBitmapCommand extends TSPLVisualCommand {
179
179
  private readonly bitmap;
180
180
  private readonly mode;
181
181
  /**
182
- *
183
182
  * @param bitmap Bitmap to present.
184
183
  * @param x X coordinates in dots
185
184
  * @param y Y Coordinates in dots
@@ -191,6 +190,17 @@ declare class TSPLBitmapCommand extends TSPLVisualCommand {
191
190
  private get commandWithoutBytes();
192
191
  private get modeValue();
193
192
  write(device: UsbDevice): Promise<void>;
193
+ /**
194
+ * Create a new bitmap command for the given image url
195
+ * @param image Image to create command for
196
+ * @param x X coordinate of the image
197
+ * @param y Y coordinate of the image
198
+ * @param imageWidth Desired width of the image
199
+ * @param imageHeight Desired height of the image
200
+ * @param mode Graphics mode
201
+ * @returns
202
+ */
203
+ static forImageUrl(image: string, x: number, y: number, imageWidth?: number, imageHeight?: number, mode?: GraphicMode): Promise<TSPLBitmapCommand>;
194
204
  }
195
205
 
196
206
  /**
@@ -425,7 +435,7 @@ declare abstract class Printer {
425
435
  * Writes a command to the printers usb
426
436
  * @param command Command to send to the usb
427
437
  */
428
- protected writeCommand(command: Command): Promise<void>;
438
+ writeCommand(command: Command): Promise<void>;
429
439
  /**
430
440
  * Check if the device is indeed a printer
431
441
  * @param device
@@ -444,6 +454,14 @@ declare class PrinterService {
444
454
  * @returns List of available printers
445
455
  */
446
456
  static getPrinters(): Promise<Printer[]>;
457
+ /**
458
+ * This is intended to be used in the browser although it also works in node
459
+ * In the browser, it provides a UI for the user to choose a USB device and if it is a
460
+ * printer, it returns a new printer instance. In Node however, this will try to create
461
+ * a printer for the first available device and returns it. This means that even if there is a
462
+ * printer, it may return undefined. In node, use `getPrinters` instead
463
+ */
464
+ static requestPrinter(): Promise<Printer | undefined>;
447
465
  }
448
466
 
449
467
  type index_Printer = Printer;
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var __async = (__this, __arguments, generator) => {
20
30
  return new Promise((resolve, reject) => {
@@ -172,10 +182,120 @@ var TSPLVisualCommand = class extends TSPLCommand {
172
182
  }
173
183
  };
174
184
 
175
- // src/commands/tspl/commands/basic/TSPLBitmapCommand.ts
176
- var TSPLBitmapCommand = class extends TSPLVisualCommand {
185
+ // src/helpers/ImageUtils.ts
186
+ var import_image_pixels = __toESM(require("image-pixels"));
187
+ var BLACK_PIXEL = 0;
188
+ var WHITE_PIXEL = 1;
189
+ var ImageUtils = class {
177
190
  /**
191
+ * Get pixel information about an image
192
+ * @param image Image to process
193
+ * @returns
194
+ */
195
+ static getPixels(image) {
196
+ return __async(this, null, function* () {
197
+ const { width, height, data } = yield (0, import_image_pixels.default)(image);
198
+ const bitsPerPixel = data.length / height / width;
199
+ return {
200
+ data,
201
+ width,
202
+ height,
203
+ bitsPerPixel
204
+ };
205
+ });
206
+ }
207
+ /**
208
+ * Return a bitmap in which all pixels are represented with one bit of either 1 or 0 representing white and black
209
+ * pixels respectively. `destinationWidth` and `destinationHeight` have to be smaller or equal to the
210
+ * input size as only downscaling is performed
178
211
  *
212
+ * @param image Image to process
213
+ * @param destinationWidth Width of the ouput bitmap
214
+ * @param destinationHeight Height of the output bitmap
215
+ * @returns
216
+ */
217
+ static getBWBitmap(image, destinationWidth, destinationHeight) {
218
+ return __async(this, null, function* () {
219
+ const {
220
+ data,
221
+ width,
222
+ height,
223
+ bitsPerPixel
224
+ } = yield this.getPixels(image);
225
+ const dWidth = destinationWidth != null ? destinationWidth : width;
226
+ const dHeight = destinationHeight != null ? destinationHeight : height;
227
+ const differenceToDividable = dWidth % 8 == 0 ? 0 : 8 - dWidth % 8;
228
+ const dividableDWidth = dWidth + differenceToDividable;
229
+ const bitmapData = new Uint8Array(dividableDWidth * dHeight);
230
+ let destinationIndex = 0;
231
+ for (let h = 0; h < dHeight; h++) {
232
+ const originalHeight = Math.round(h * (height - 1) / (dHeight - 1));
233
+ for (let w = 0; w < dWidth; w++) {
234
+ const originalWidth = Math.round(w * (width - 1) / (dWidth - 1));
235
+ const baseIndex = originalHeight * width * bitsPerPixel + originalWidth * bitsPerPixel;
236
+ const r = data[baseIndex];
237
+ const g = data[baseIndex + 1];
238
+ const b = data[baseIndex + 2];
239
+ const a = data[baseIndex + 3];
240
+ if (a > 128) {
241
+ const avg = (r + g + b) / 3;
242
+ if (avg > 128) {
243
+ bitmapData[destinationIndex] = WHITE_PIXEL;
244
+ } else {
245
+ bitmapData[destinationIndex] = BLACK_PIXEL;
246
+ }
247
+ } else {
248
+ bitmapData[destinationIndex] = WHITE_PIXEL;
249
+ }
250
+ destinationIndex += 1;
251
+ }
252
+ for (let i = 0; i < differenceToDividable; i++) {
253
+ bitmapData[destinationIndex] = WHITE_PIXEL;
254
+ destinationIndex += 1;
255
+ }
256
+ }
257
+ const byteArrays = this.chunk(bitmapData, 8);
258
+ const widthInBytes = dividableDWidth / 8;
259
+ const bytes = byteArrays.map(this.bitsToByte);
260
+ const finalBytes = new Uint8Array(bytes);
261
+ return {
262
+ width: widthInBytes,
263
+ height: dHeight,
264
+ bytes: finalBytes
265
+ };
266
+ });
267
+ }
268
+ /**
269
+ * Splits an array into chunks.
270
+ * @param originalArray
271
+ * @param chunkSize
272
+ * @returns
273
+ */
274
+ static chunk(originalArray, chunkSize) {
275
+ const resultArray = [];
276
+ for (let i = 0; i < originalArray.length; i += chunkSize) {
277
+ const chunk = originalArray.slice(i, i + chunkSize);
278
+ resultArray.push(chunk);
279
+ }
280
+ return resultArray;
281
+ }
282
+ /**
283
+ * Converts an array of bits to a byte
284
+ * @param bits
285
+ * @returns
286
+ */
287
+ static bitsToByte(bits) {
288
+ let byteValue = 0;
289
+ for (let i = 0; i < bits.length; i++) {
290
+ byteValue = byteValue << 1 | bits[i];
291
+ }
292
+ return byteValue;
293
+ }
294
+ };
295
+
296
+ // src/commands/tspl/commands/basic/TSPLBitmapCommand.ts
297
+ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
298
+ /**
179
299
  * @param bitmap Bitmap to present.
180
300
  * @param x X coordinates in dots
181
301
  * @param y Y Coordinates in dots
@@ -213,6 +333,22 @@ var TSPLBitmapCommand = class extends TSPLVisualCommand {
213
333
  yield this.terminateCommand(device);
214
334
  });
215
335
  }
336
+ /**
337
+ * Create a new bitmap command for the given image url
338
+ * @param image Image to create command for
339
+ * @param x X coordinate of the image
340
+ * @param y Y coordinate of the image
341
+ * @param imageWidth Desired width of the image
342
+ * @param imageHeight Desired height of the image
343
+ * @param mode Graphics mode
344
+ * @returns
345
+ */
346
+ static forImageUrl(image, x, y, imageWidth, imageHeight, mode) {
347
+ return __async(this, null, function* () {
348
+ const bitmap = yield ImageUtils.getBWBitmap(image, imageWidth, imageHeight);
349
+ return new _TSPLBitmapCommand(bitmap, x, y, mode);
350
+ });
351
+ }
216
352
  };
217
353
 
218
354
  // src/commands/tspl/types.ts
@@ -459,6 +595,14 @@ var getDevices = () => __async(void 0, null, function* () {
459
595
  const devices = yield usbAgent.getDevices();
460
596
  return devices.map((device) => new UsbDevice(device));
461
597
  });
598
+ var requestDevice = () => __async(void 0, null, function* () {
599
+ const device = yield usbAgent.requestDevice();
600
+ if (device) {
601
+ return new UsbDevice(device);
602
+ } else {
603
+ return void 0;
604
+ }
605
+ });
462
606
  var UsbDevice = class {
463
607
  get opened() {
464
608
  return this.device.opened;
@@ -608,6 +752,21 @@ var PrinterService = class _PrinterService {
608
752
  return optionalPrinters.filter((printer) => !!printer);
609
753
  });
610
754
  }
755
+ /**
756
+ * This is intended to be used in the browser although it also works in node
757
+ * In the browser, it provides a UI for the user to choose a USB device and if it is a
758
+ * printer, it returns a new printer instance. In Node however, this will try to create
759
+ * a printer for the first available device and returns it. This means that even if there is a
760
+ * printer, it may return undefined. In node, use `getPrinters` instead
761
+ */
762
+ static requestPrinter() {
763
+ return __async(this, null, function* () {
764
+ const device = yield requestDevice();
765
+ if (device) {
766
+ return _PrinterService.printerForDevice(device);
767
+ }
768
+ });
769
+ }
611
770
  };
612
771
  // Annotate the CommonJS export names for ESM import in node:
613
772
  0 && (module.exports = {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/index.ts","../src/commands/Command.ts","../src/commands/CommandGroup.ts","../src/commands/tspl/index.ts","../src/commands/tspl/TSPLCommand.ts","../src/commands/tspl/commands/TSPLRawCommand.ts","../src/commands/tspl/commands/TSPLCommandGroup.ts","../src/commands/tspl/commands/TSPLVisualCommand.ts","../src/commands/tspl/commands/basic/TSPLBitmapCommand.ts","../src/commands/tspl/types.ts","../src/commands/tspl/commands/basic/TSPLTextCommand.ts","../src/commands/tspl/commands/basic/TSPLGapCommand.ts","../src/commands/tspl/commands/basic/TSPLSizeCommand.ts","../src/commands/tspl/commands/basic/TSPLCLSCommand.ts","../src/commands/tspl/commands/basic/TSPLDirectionCommand.ts","../src/commands/tspl/commands/basic/TSPLPrintCommand.ts","../src/commands/tspl/commands/basic/TSPLBarCommand.ts","../src/commands/tspl/commands/basic/TSPLQRCommand.ts","../src/commands/tspl/commands/basic/TSPLBlockCommand.ts","../src/printers/index.ts","../src/printers/Printer.ts","../src/helpers/USBUtils.ts","../src/helpers/StringUtils.ts","../src/printers/TSPLPrinter.ts","../src/printers/PrinterService.ts"],"sourcesContent":["export * as commands from \"./commands\"\nexport * as printers from \"./printers\"","export { default as Command } from \"./Command\"\nexport { default as CommandGroup } from \"./CommandGroup\"\n\nexport type PrinterLanguage = \"tspl\"\n\nexport * as tspl from \"./tspl\"","import { UsbDevice } from \"@/helpers/USBUtils\"\n\n/**\n * Base implementation for all types of command\n * Represents a command to be send to the printer to execute, such as print\n */\nexport default abstract class Command {\n /**\n * Returns a string representation of the command\n */\n abstract get commandString(): string\n\n /**\n * Write the command data to a USB device\n * @param device Device to write to\n */\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Byte representation of a newline\n */\n protected get commandTerminatorBytes(): Uint8Array {\n return new Uint8Array([10])\n }\n\n /**\n * Writes a string to a device\n * @param data String representation of data\n * @param device Device to write to\n */\n protected async writeString(data: string, device: UsbDevice): Promise<void> {\n await device.writeString(data)\n }\n\n /**\n * Writes bytes to a device. It will automatically end a command with @see{commandTerminatorBytes}\n * @param data Byte array to send\n * @param device Device to write to\n */\n protected async writeBytes(data: Uint8Array, device: UsbDevice): Promise<void> {\n await device.writeData(data)\n }\n\n /**\n * Write the command terminator to the device\n * @param device \n */\n protected async terminateCommand(device: UsbDevice): Promise<void> {\n await this.writeBytes(this.commandTerminatorBytes, device)\n }\n}","import { UsbDevice } from \"@/helpers/USBUtils\";\nimport Command from \"./Command\";\n\n/**\n * A utility class that helps groupping commands together\n * Should be implemnted with a specific command type to ensure only commands for the same lagnuage are\n * groupped together\n */\nexport default abstract class CommandGroup<T extends Command> extends Command {\n private commands: T[]\n\n constructor(commands: T[]) {\n super()\n this.commands = commands\n }\n\n async write(device: UsbDevice): Promise<void> {\n for (let commandIndex in this.commands) {\n await this.commands[commandIndex].write(device)\n }\n }\n\n get commandString(): string {\n return \"\"\n }\n}","export { default as TSPLCommand } from \"./TSPLCommand\"\n\nexport * from \"./commands\"\nexport * from \"./types\"","import Command from \"@/commands/Command\";\n\n/**\n * Base for TSPL specific commands\n */\nexport default abstract class TSPLCommand extends Command {\n}","import TSPLCommand from \"../TSPLCommand\"\n\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLRawCommand extends TSPLCommand {\n /**\n * Raw command string\n */\n private readonly commandBody: string\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(body: string) {\n super()\n this.commandBody = body\n }\n\n get commandString(): string {\n return this.commandBody;\n }\n}\n","import CommandGroup from \"@/commands/CommandGroup\";\nimport TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Command group for tspl commands\n */\nexport default class TSPLCommandGroup extends CommandGroup<TSPLCommand> {}","import TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Base for all TSPL commands that have a visual effect on the final label\n */\nexport default abstract class TSPLVisualCommand extends TSPLCommand {\n protected readonly x: number\n protected readonly y: number\n\n constructor(x: number, y: number) {\n super()\n this.x = x\n this.y = y\n }\n}","import { BWBitmap } from \"@/helpers/ImageUtils\";\nimport { GraphicMode } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Represents a bitmap command. Can be used to draw an image to the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBitmapCommand extends TSPLVisualCommand {\n /**\n * Bitmap to present. \n * TSPL only supports black and write printing so this bitmap contains a matrix of 1 (White pixel)\n * and 0 (Black pixel) values\n */\n private readonly bitmap: BWBitmap\n private readonly mode: GraphicMode\n \n /**\n * \n * @param bitmap Bitmap to present. \n * @param x X coordinates in dots\n * @param y Y Coordinates in dots\n * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values\n */\n constructor(bitmap: BWBitmap, x: number, y: number, mode?: GraphicMode) {\n super(x, y);\n this.bitmap = bitmap;\n this.mode = mode ?? \"overwrite\"\n }\n\n get commandString(): string {\n const textDecoder = new TextDecoder('utf-8')\n const bytesString = textDecoder.decode(this.bitmap.bytes)\n\n return `${this.commandWithoutBytes}${bytesString.slice(0,5)}...\\n`;\n }\n\n private get commandWithoutBytes(): string {\n return `BITMAP ${this.x}, ${this.y},${this.bitmap.width},${this.bitmap.height},${this.modeValue},`\n }\n\n private get modeValue(): 0|1|2 {\n switch (this.mode) {\n case \"overwrite\": return 0\n case \"or\": return 1\n case \"xor\": return 2\n }\n }\n\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandWithoutBytes, device)\n await this.writeBytes(this.bitmap.bytes, device)\n await this.terminateCommand(device)\n }\n}","export type Rotation = 0|90|180|270\nexport type Alignment = undefined|\"left\"|\"center\"|\"right\"\n\n/**\n * Convert an alignemnt string to its number value\n * @param alignment \n * @returns \n */\nexport const alignmentToNumber = (alignment: Alignment): 0|1|2|3 => {\n switch(alignment) {\n case undefined: return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n}\n\n/**\n * Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation\n * on the values\n */\nexport type GraphicMode = \"overwrite\"|\"or\"|\"xor\"\nexport type UnitSystem = \"imperial\"|\"metric\"|\"dot\"\nexport type ECCLevel = \"L\"|\"M\"|\"Q\"|\"H\"\nexport type AutoManual = \"A\"|\"M\"\nexport type QRModel = \"M1\"|\"M2\"\nexport type BarcodeType = \"CODE128\"|\"EAN13\"|\"EAN8\"|\"EAN5\"|\"EAN2\"|\"UPC\"|\"CODE39\"|\"ITF14\"|\"MSI10\"|\"MSI11\"|\"MSI1010\"|\"MSI1110\"|\"pharmacode\"|\"codabar\"\nexport type BarcodeHumanReable = \"none\"|\"left\"|\"right\"|\"center\"","import { Alignment, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a single line text on the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLTextCommand extends TSPLVisualCommand {\n /**\n * Name of the font to use. Consult documentation for more info\n */\n protected readonly font: string\n /**\n * Angle of rotation of the text. 0, 90, 180 or 270\n */\n protected readonly rotatation: Rotation\n /**\n * Multiplication of the font size in x axis\n */\n protected readonly xMultiplication: number\n /**\n * Multiplication of the font size in y axis\n */\n protected readonly yMultiplication: number\n /**\n * Text alignment. Left, Center or Right. The default alignmnet is left\n */\n protected readonly alignment: number\n /**\n * Text to print\n */\n protected readonly content: string\n\n constructor(content: string, x: number, y: number, font: string, rotation?: Rotation, xMultiplication?: number, yMultiplication?: number, alignment?: Alignment) {\n super(x, y)\n this.font = font\n this.rotatation = rotation ?? 0\n this.xMultiplication = xMultiplication ?? 1\n this.yMultiplication = yMultiplication ?? 1\n this.alignment = alignmentToNumber(alignment)\n this.content = content\n }\n\n get commandString(): string {\n return `TEXT ${this.x},${this.y},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the gap between two labels\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLGapCommand extends TSPLCommand {\n private readonly gap: number\n private readonly offset: number\n\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(gap: number, offset: number, unitSystem: UnitSystem) {\n super()\n this.gap = gap\n this.offset = offset\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `GAP ${this.valueWithUnit(this.gap)}, ${this.valueWithUnit(this.offset)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the size of the label to rpint\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLSizeCommand extends TSPLCommand {\n private readonly width: number\n private readonly height: number\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(width: number, height: number, unitSystem: UnitSystem) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `SIZE ${this.valueWithUnit(this.width)}, ${this.valueWithUnit(this.height)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Clear the image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLCLSCommand extends TSPLCommand {\n get commandString(): string {\n return \"CLS\"\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * This command defines in which direction will the label be printed and wether or not to mirror the image\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDirectionCommand extends TSPLCommand {\n private readonly direction: 0|1\n private readonly mirror: 0|1\n\n /**\n * @param direction Controls the orientation of the resulting label compared to the printer\n * @param mirror Controls mirroring relative to the center line of the label perpendicular to the printhead. See the documentsion for examples\n */\n constructor(direction: \"normal\"|\"inverse\", mirror?: boolean) {\n super()\n this.direction = direction == \"normal\" ? 1 : 0\n this.mirror = mirror ? 1 : 0\n }\n\n get commandString(): string {\n return `DIRECTION ${this.direction}, ${this.mirror}`\n }\n}\n","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Prints the current image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLPrintCommand extends TSPLCommand {\n /**\n * The number of set to print.\n */\n private readonly sets: number\n /**\n * The number of copies to print of each set.\n * The difference between a set and a copy is that if you have a counter for example,\n * the counter will be incremented for each set but not for each copy\n */\n private readonly copies: number\n\n constructor(sets: number, copies: number = 1) {\n super()\n this.sets = sets\n this.copies = copies\n }\n\n get commandString(): string {\n return `PRINT ${this.sets}, ${this.copies}`\n }\n}","import TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Draws a black bar\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBarCommand extends TSPLVisualCommand {\n private readonly width: number\n private readonly height: number\n\n /**\n * @param x X coordinates in dots\n * @param y Y coordinates in dots\n * @param width Width of tha bar in dots\n * @param height Height of the bar in dots\n */\n constructor(x: number, y: number, width: number, height: number) {\n super(x,y)\n this.width = width\n this.height = height\n }\n\n get commandString(): string {\n return `BAR ${this.x}, ${this.y}, ${this.width}, ${this.height}`\n }\n}","import { ECCLevel, AutoManual, Rotation, QRModel } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a QR code\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLQRCommand extends TSPLVisualCommand {\n private readonly ecc: ECCLevel\n private readonly cellWidth: number\n private readonly mode: AutoManual\n private readonly rotation: Rotation\n private readonly model: QRModel\n /**\n * Should be between 0 and 7\n */\n private readonly mask: number\n private readonly content: string\n\n constructor(content: string, \n x: number, \n y: number, \n cellWidth: number, \n ecc: ECCLevel = \"H\", \n mode: AutoManual = \"A\", \n rotation: Rotation = 0, \n model: QRModel = \"M2\", \n mask: number = 7) {\n super(x,y)\n this.content = content\n this.cellWidth = cellWidth\n this.ecc = ecc\n this.mode = mode\n this.rotation = rotation\n this.model = model\n this.mask = mask\n\n if (mask < 0 || mask > 8) {\n throw new Error(`Invalid mask provided: ${mask}`)\n }\n }\n\n get commandString(): string {\n return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, ${this.mask}, \\\"${this.content}\\\"`\n }\n}","import { Alignment, Rotation } from \"../../types\";\nimport TSPLTextCommand from \"./TSPLTextCommand\";\n\nexport default class TSPLBlockCommand extends TSPLTextCommand {\n private readonly width: number\n private readonly height: number\n private readonly lineSpacing: number\n\n constructor(content: string, \n x: number, \n y: number, \n width: number,\n height: number,\n font: string, \n rotation?: Rotation, \n xMultiplication?: number, \n yMultiplication?: number, \n lineSpacing: number = 0,\n alignment?: Alignment) {\n super(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment)\n this.width = width\n this.height = height\n this.lineSpacing = lineSpacing\n }\n\n get commandString(): string {\n return `BLOCK ${this.x},${this.y},${this.width}, ${this.height},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.lineSpacing},${this.alignment},\\\"${this.content}\\\"`\n }\n}","export { default as Printer } from \"./Printer\"\nexport { PrinterService } from \"./PrinterService\"","import { Command, PrinterLanguage } from \"@/commands\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Base class that encapsulates functionality of all printers\n */\nexport default abstract class Printer {\n private readonly usbDevice: UsbDevice\n\n /**\n * Printer language used by the type of printer the subclass represents\n */\n abstract get language(): PrinterLanguage\n\n /**\n * When called, it will feed the labels to the beginig of the next label\n */\n abstract feedLabel(): Promise<void>\n\n constructor(device: UsbDevice) {\n this.usbDevice = device\n }\n\n /**\n * Close the printer USB\n */\n async close() {\n await this.usbDevice.close()\n }\n\n /**\n * Writes a command to the printers usb\n * @param command Command to send to the usb\n */\n protected async writeCommand(command: Command): Promise<void> {\n if(!this.usbDevice.opened) await this.usbDevice.openAndConfigure()\n await command.write(this.usbDevice)\n }\n\n /**\n * Check if the device is indeed a printer\n * @param device \n */\n static try(_device: UsbDevice): Promise<boolean> {\n throw new Error(\"try(device:) should be implemented\")\n }\n}","import { InEndpoint, WebUSB } from \"usb\";\nimport StringUtils from \"./StringUtils\";\n\nconst unsupportedUsbError = \"usb-unsupported\"\nconst stringHelper = new StringUtils()\n\n/**\n * @returns The appropiate USB agent based on the environment\n */\nconst getUSB = (): USB => {\n if(typeof navigator !== \"undefined\") {\n if(navigator.usb) {\n return navigator.usb\n } else {\n throw unsupportedUsbError\n }\n }\n\n return new WebUSB({allowAllDevices: true})\n}\n\nexport const usbAgent = getUSB()\n\n/**\n * @returns A list of available devices\n */\nexport const getDevices = async (): Promise<UsbDevice[]> => {\n const devices = await usbAgent.getDevices()\n return devices.map(device => new UsbDevice(device) )\n}\n\n/**\n * Convenience wrapper for a web usb device\n * Its main purpose is to hide the details of the usb library from client code so in case\n * it needs to be switched, compatibility can be retained\n */\nexport class UsbDevice {\n private readonly device: USBDevice\n\n get opened() {\n return this.device.opened\n }\n\n /**\n * All available endpoints\n */\n private get endpoints() {\n return this.device.configuration?.interfaces[0].alternate.endpoints ?? []\n }\n\n /**\n * Endpoint for writing\n */\n private get outEndpoint() {\n return this.endpoints.find(e => e.direction == \"out\")?.endpointNumber\n }\n\n /**\n * Endpoint for reading\n */\n private get inEndpoint() {\n return this.endpoints.find(e => e.direction == \"in\")?.endpointNumber\n }\n\n constructor(device: USBDevice) {\n this.device = device\n }\n\n /**\n * Open the device and claim its interface\n */\n async openAndConfigure() {\n await this.device.open();\n await this.device.selectConfiguration(1);\n await this.device.claimInterface(0);\n }\n\n /**\n * Closes the device\n */\n async close() {\n await this.device.releaseInterface(0)\n await this.device.close()\n }\n\n /**\n * Write data to an USB device\n * @param data Data to write\n */\n async writeData(data: Uint8Array): Promise<void> {\n const endpointNumber = this.outEndpoint\n await this.device.transferOut(endpointNumber!, data)\n }\n\n /**\n * Writes a text to a device\n * @param text Text to write\n */\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n /**\n * Reads bytes from the usb device\n * @param length The max length of the incoming data. \n * @returns Bytes received as a DataView or undefined. If data is longer then `length`, undefined will be returned\n */\n async readData(length: number): Promise<DataView|undefined> {\n const endpointNumber = this.inEndpoint\n const result = await this.device.transferIn(endpointNumber!, length)\n\n if(result.status == \"ok\" && result.data) {\n return result.data\n } else {\n return undefined\n }\n }\n\n /**\n * Reads data from the usb device and converts it to string\n * {@see readData}\n */\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","/**\n * Collection of helpers to work with strings\n */\nexport default class StringUtils {\n /**\n * Convert string to utf8 array\n * @param str Convert string to byte array\n */\n toUTF8Array(str: string) {\n let utf8Encode = new TextEncoder();\n return utf8Encode.encode(str)\n }\n\n /**\n * Convert bytes to utf8 encoded string\n * @param bytes Bytes to decode\n * @returns A string\n */\n toString(bytes: Uint8Array|DataView) {\n let decoder = new TextDecoder()\n return decoder.decode(bytes)\n }\n}","import { TSPLRawCommand } from \"@/commands/tspl\";\nimport { PrinterLanguage } from \"@/commands\"\nimport Printer from \"./Printer\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\nexport default class TSPLPrinter extends Printer {\n get language(): PrinterLanguage {\n return \"tspl\"\n }\n\n async feedLabel(): Promise<void> {\n const feedCommand = new TSPLRawCommand(\"FORMFEED\")\n await this.writeCommand(feedCommand)\n }\n\n static async try(device: UsbDevice): Promise<boolean> {\n if(!device.opened) await device.openAndConfigure()\n const testCommand = new TSPLRawCommand(\"~!I\")\n await testCommand.write(device)\n\n const response = await device.readString(64)\n await device.close()\n // If there is a response, we have a TSPL printer\n return !!response\n }\n}","import { UsbDevice, getDevices } from \"@/helpers/USBUtils\"\nimport TSPLPrinter from \"./TSPLPrinter\"\nimport Printer from \"./Printer\"\n\nexport class PrinterService {\n /**\n * Try each type of printer and return the one that mathces the usb device\n * @param device \n * @returns \n */\n static async printerForDevice(device: UsbDevice): Promise<Printer|undefined> {\n const classes = [TSPLPrinter]\n\n for (const key in classes) {\n if(await classes[key].try(device)) {\n return new classes[key](device)\n }\n }\n\n return undefined\n }\n\n /**\n * @returns List of available printers\n */\n static async getPrinters(): Promise<Printer[]> {\n const devices = await getDevices()\n const optionalPrinters = await Promise.all(devices.map(PrinterService.printerForDevice))\n return optionalPrinters.filter(printer => !!printer) as Printer[]\n }\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/index.ts","../src/commands/Command.ts","../src/commands/CommandGroup.ts","../src/commands/tspl/index.ts","../src/commands/tspl/TSPLCommand.ts","../src/commands/tspl/commands/TSPLRawCommand.ts","../src/commands/tspl/commands/TSPLCommandGroup.ts","../src/commands/tspl/commands/TSPLVisualCommand.ts","../src/helpers/ImageUtils.ts","../src/commands/tspl/commands/basic/TSPLBitmapCommand.ts","../src/commands/tspl/types.ts","../src/commands/tspl/commands/basic/TSPLTextCommand.ts","../src/commands/tspl/commands/basic/TSPLGapCommand.ts","../src/commands/tspl/commands/basic/TSPLSizeCommand.ts","../src/commands/tspl/commands/basic/TSPLCLSCommand.ts","../src/commands/tspl/commands/basic/TSPLDirectionCommand.ts","../src/commands/tspl/commands/basic/TSPLPrintCommand.ts","../src/commands/tspl/commands/basic/TSPLBarCommand.ts","../src/commands/tspl/commands/basic/TSPLQRCommand.ts","../src/commands/tspl/commands/basic/TSPLBlockCommand.ts","../src/printers/index.ts","../src/printers/Printer.ts","../src/helpers/USBUtils.ts","../src/helpers/StringUtils.ts","../src/printers/TSPLPrinter.ts","../src/printers/PrinterService.ts"],"sourcesContent":["export * as commands from \"./commands\"\nexport * as printers from \"./printers\"","export { default as Command } from \"./Command\"\nexport { default as CommandGroup } from \"./CommandGroup\"\n\nexport type PrinterLanguage = \"tspl\"\n\nexport * as tspl from \"./tspl\"","import { UsbDevice } from \"@/helpers/USBUtils\"\n\n/**\n * Base implementation for all types of command\n * Represents a command to be send to the printer to execute, such as print\n */\nexport default abstract class Command {\n /**\n * Returns a string representation of the command\n */\n abstract get commandString(): string\n\n /**\n * Write the command data to a USB device\n * @param device Device to write to\n */\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Byte representation of a newline\n */\n protected get commandTerminatorBytes(): Uint8Array {\n return new Uint8Array([10])\n }\n\n /**\n * Writes a string to a device\n * @param data String representation of data\n * @param device Device to write to\n */\n protected async writeString(data: string, device: UsbDevice): Promise<void> {\n await device.writeString(data)\n }\n\n /**\n * Writes bytes to a device. It will automatically end a command with @see{commandTerminatorBytes}\n * @param data Byte array to send\n * @param device Device to write to\n */\n protected async writeBytes(data: Uint8Array, device: UsbDevice): Promise<void> {\n await device.writeData(data)\n }\n\n /**\n * Write the command terminator to the device\n * @param device \n */\n protected async terminateCommand(device: UsbDevice): Promise<void> {\n await this.writeBytes(this.commandTerminatorBytes, device)\n }\n}","import { UsbDevice } from \"@/helpers/USBUtils\";\nimport Command from \"./Command\";\n\n/**\n * A utility class that helps groupping commands together\n * Should be implemnted with a specific command type to ensure only commands for the same lagnuage are\n * groupped together\n */\nexport default abstract class CommandGroup<T extends Command> extends Command {\n private commands: T[]\n\n constructor(commands: T[]) {\n super()\n this.commands = commands\n }\n\n async write(device: UsbDevice): Promise<void> {\n for (let commandIndex in this.commands) {\n await this.commands[commandIndex].write(device)\n }\n }\n\n get commandString(): string {\n return \"\"\n }\n}","export { default as TSPLCommand } from \"./TSPLCommand\"\n\nexport * from \"./commands\"\nexport * from \"./types\"","import Command from \"@/commands/Command\";\n\n/**\n * Base for TSPL specific commands\n */\nexport default abstract class TSPLCommand extends Command {\n}","import TSPLCommand from \"../TSPLCommand\"\n\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLRawCommand extends TSPLCommand {\n /**\n * Raw command string\n */\n private readonly commandBody: string\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(body: string) {\n super()\n this.commandBody = body\n }\n\n get commandString(): string {\n return this.commandBody;\n }\n}\n","import CommandGroup from \"@/commands/CommandGroup\";\nimport TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Command group for tspl commands\n */\nexport default class TSPLCommandGroup extends CommandGroup<TSPLCommand> {}","import TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Base for all TSPL commands that have a visual effect on the final label\n */\nexport default abstract class TSPLVisualCommand extends TSPLCommand {\n protected readonly x: number\n protected readonly y: number\n\n constructor(x: number, y: number) {\n super()\n this.x = x\n this.y = y\n }\n}","// @ts-ignore\nimport pixels from \"image-pixels\"\n\n/**\n * Helper type to transmit image bitmap data\n */\nexport type Pixels = {\n data: Uint8Array, \n width: number,\n height: number, \n bitsPerPixel: number\n}\n\n/**\n * Helper type to transmit black and white bitmap data\n */\nexport type BWBitmap = {\n width: number,\n height: number,\n bytes: Uint8Array\n}\n\nconst BLACK_PIXEL = 0\nconst WHITE_PIXEL = 1\n\n/**\n * Set of image utility\n */\nexport default class ImageUtils {\n /**\n * Get pixel information about an image\n * @param image Image to process\n * @returns \n */\n static async getPixels(image: string|Blob): Promise<Pixels> {\n const {width, height, data} = await pixels(image) as Omit<Pixels, \"bitsPerPixel\">\n const bitsPerPixel = data.length / height / width\n\n return {\n data, width, height, bitsPerPixel\n }\n }\n\n /**\n * Return a bitmap in which all pixels are represented with one bit of either 1 or 0 representing white and black\n * pixels respectively. `destinationWidth` and `destinationHeight` have to be smaller or equal to the\n * input size as only downscaling is performed\n * \n * @param image Image to process \n * @param destinationWidth Width of the ouput bitmap\n * @param destinationHeight Height of the output bitmap\n * @returns \n */\n static async getBWBitmap(image: string, destinationWidth?: number, destinationHeight?: number): Promise<BWBitmap> {\n const {\n data,\n width,\n height,\n bitsPerPixel\n } = await this.getPixels(image)\n \n // Number of pixels width and height => number of bits for each row and number of rows\n const dWidth = destinationWidth ?? width\n const dHeight = destinationHeight ?? height\n \n const differenceToDividable = dWidth % 8 == 0 ? 0 : (8 - (dWidth % 8))\n const dividableDWidth = dWidth + differenceToDividable\n \n // Size of the array has to be with * height but width has to be extended to be dividable by 8\n const bitmapData = new Uint8Array(dividableDWidth * dHeight)\n \n let destinationIndex = 0\n for (let h=0; h < dHeight; h++) {\n const originalHeight = Math.round((h * (height - 1)) / (dHeight - 1))\n \n for(let w=0; w < dWidth; w++) {\n const originalWidth = Math.round((w * (width - 1)) / (dWidth - 1))\n \n const baseIndex = (originalHeight * width * bitsPerPixel) + (originalWidth * bitsPerPixel)\n \n const r = data[baseIndex]\n const g = data[baseIndex + 1]\n const b = data[baseIndex + 2]\n const a = data[baseIndex + 3]\n \n if(a > 128) {\n const avg = (r + g + b) / 3\n \n if(avg > 128) {\n bitmapData[destinationIndex] = WHITE_PIXEL\n } else {\n bitmapData[destinationIndex] = BLACK_PIXEL\n }\n } else {\n bitmapData[destinationIndex] = WHITE_PIXEL\n }\n destinationIndex += 1\n }\n \n for(let i=0; i < differenceToDividable; i++) {\n bitmapData[destinationIndex] = WHITE_PIXEL\n destinationIndex += 1\n }\n }\n \n const byteArrays = this.chunk(bitmapData,8)\n const widthInBytes = dividableDWidth / 8\n \n const bytes = byteArrays.map(this.bitsToByte)\n const finalBytes = new Uint8Array(bytes)\n \n return {\n width: widthInBytes,\n height: dHeight,\n bytes: finalBytes\n }\n }\n\n /**\n * Splits an array into chunks.\n * @param originalArray\n * @param chunkSize\n * @returns\n */\n private static chunk(originalArray: Uint8Array, chunkSize: number): Uint8Array[] {\n const resultArray = [];\n\n for (let i = 0; i < originalArray.length; i += chunkSize) {\n const chunk = originalArray.slice(i, i + chunkSize);\n resultArray.push(chunk);\n }\n\n return resultArray;\n }\n\n /**\n * Converts an array of bits to a byte\n * @param bits\n * @returns\n */\n private static bitsToByte(bits: Uint8Array) {\n let byteValue = 0;\n for (let i = 0; i < bits.length; i++) {\n byteValue = (byteValue << 1) | bits[i];\n }\n return byteValue;\n }\n}","import ImageUtils, { BWBitmap } from \"@/helpers/ImageUtils\";\nimport { GraphicMode } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Represents a bitmap command. Can be used to draw an image to the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBitmapCommand extends TSPLVisualCommand {\n /**\n * Bitmap to present. \n * TSPL only supports black and write printing so this bitmap contains a matrix of 1 (White pixel)\n * and 0 (Black pixel) values\n */\n private readonly bitmap: BWBitmap\n private readonly mode: GraphicMode\n\n /**\n * @param bitmap Bitmap to present. \n * @param x X coordinates in dots\n * @param y Y Coordinates in dots\n * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values\n */\n constructor(bitmap: BWBitmap, x: number, y: number, mode?: GraphicMode) {\n super(x, y);\n this.bitmap = bitmap;\n this.mode = mode ?? \"overwrite\"\n }\n\n get commandString(): string {\n const textDecoder = new TextDecoder('utf-8')\n const bytesString = textDecoder.decode(this.bitmap.bytes)\n\n return `${this.commandWithoutBytes}${bytesString.slice(0,5)}...\\n`;\n }\n\n private get commandWithoutBytes(): string {\n return `BITMAP ${this.x}, ${this.y},${this.bitmap.width},${this.bitmap.height},${this.modeValue},`\n }\n\n private get modeValue(): 0|1|2 {\n switch (this.mode) {\n case \"overwrite\": return 0\n case \"or\": return 1\n case \"xor\": return 2\n }\n }\n\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandWithoutBytes, device)\n await this.writeBytes(this.bitmap.bytes, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Create a new bitmap command for the given image url\n * @param image Image to create command for \n * @param x X coordinate of the image\n * @param y Y coordinate of the image\n * @param imageWidth Desired width of the image\n * @param imageHeight Desired height of the image\n * @param mode Graphics mode\n * @returns \n */\n static async forImageUrl(image: string, x: number, y: number, imageWidth?: number, imageHeight?: number, mode?: GraphicMode) {\n const bitmap = await ImageUtils.getBWBitmap(image, imageWidth, imageHeight)\n return new TSPLBitmapCommand(bitmap, x, y, mode)\n }\n}","export type Rotation = 0|90|180|270\nexport type Alignment = undefined|\"left\"|\"center\"|\"right\"\n\n/**\n * Convert an alignemnt string to its number value\n * @param alignment \n * @returns \n */\nexport const alignmentToNumber = (alignment: Alignment): 0|1|2|3 => {\n switch(alignment) {\n case undefined: return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n}\n\n/**\n * Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation\n * on the values\n */\nexport type GraphicMode = \"overwrite\"|\"or\"|\"xor\"\nexport type UnitSystem = \"imperial\"|\"metric\"|\"dot\"\nexport type ECCLevel = \"L\"|\"M\"|\"Q\"|\"H\"\nexport type AutoManual = \"A\"|\"M\"\nexport type QRModel = \"M1\"|\"M2\"\nexport type BarcodeType = \"CODE128\"|\"EAN13\"|\"EAN8\"|\"EAN5\"|\"EAN2\"|\"UPC\"|\"CODE39\"|\"ITF14\"|\"MSI10\"|\"MSI11\"|\"MSI1010\"|\"MSI1110\"|\"pharmacode\"|\"codabar\"\nexport type BarcodeHumanReable = \"none\"|\"left\"|\"right\"|\"center\"","import { Alignment, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a single line text on the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLTextCommand extends TSPLVisualCommand {\n /**\n * Name of the font to use. Consult documentation for more info\n */\n protected readonly font: string\n /**\n * Angle of rotation of the text. 0, 90, 180 or 270\n */\n protected readonly rotatation: Rotation\n /**\n * Multiplication of the font size in x axis\n */\n protected readonly xMultiplication: number\n /**\n * Multiplication of the font size in y axis\n */\n protected readonly yMultiplication: number\n /**\n * Text alignment. Left, Center or Right. The default alignmnet is left\n */\n protected readonly alignment: number\n /**\n * Text to print\n */\n protected readonly content: string\n\n constructor(content: string, x: number, y: number, font: string, rotation?: Rotation, xMultiplication?: number, yMultiplication?: number, alignment?: Alignment) {\n super(x, y)\n this.font = font\n this.rotatation = rotation ?? 0\n this.xMultiplication = xMultiplication ?? 1\n this.yMultiplication = yMultiplication ?? 1\n this.alignment = alignmentToNumber(alignment)\n this.content = content\n }\n\n get commandString(): string {\n return `TEXT ${this.x},${this.y},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the gap between two labels\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLGapCommand extends TSPLCommand {\n private readonly gap: number\n private readonly offset: number\n\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(gap: number, offset: number, unitSystem: UnitSystem) {\n super()\n this.gap = gap\n this.offset = offset\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `GAP ${this.valueWithUnit(this.gap)}, ${this.valueWithUnit(this.offset)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the size of the label to rpint\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLSizeCommand extends TSPLCommand {\n private readonly width: number\n private readonly height: number\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(width: number, height: number, unitSystem: UnitSystem) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `SIZE ${this.valueWithUnit(this.width)}, ${this.valueWithUnit(this.height)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Clear the image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLCLSCommand extends TSPLCommand {\n get commandString(): string {\n return \"CLS\"\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * This command defines in which direction will the label be printed and wether or not to mirror the image\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDirectionCommand extends TSPLCommand {\n private readonly direction: 0|1\n private readonly mirror: 0|1\n\n /**\n * @param direction Controls the orientation of the resulting label compared to the printer\n * @param mirror Controls mirroring relative to the center line of the label perpendicular to the printhead. See the documentsion for examples\n */\n constructor(direction: \"normal\"|\"inverse\", mirror?: boolean) {\n super()\n this.direction = direction == \"normal\" ? 1 : 0\n this.mirror = mirror ? 1 : 0\n }\n\n get commandString(): string {\n return `DIRECTION ${this.direction}, ${this.mirror}`\n }\n}\n","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Prints the current image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLPrintCommand extends TSPLCommand {\n /**\n * The number of set to print.\n */\n private readonly sets: number\n /**\n * The number of copies to print of each set.\n * The difference between a set and a copy is that if you have a counter for example,\n * the counter will be incremented for each set but not for each copy\n */\n private readonly copies: number\n\n constructor(sets: number, copies: number = 1) {\n super()\n this.sets = sets\n this.copies = copies\n }\n\n get commandString(): string {\n return `PRINT ${this.sets}, ${this.copies}`\n }\n}","import TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Draws a black bar\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBarCommand extends TSPLVisualCommand {\n private readonly width: number\n private readonly height: number\n\n /**\n * @param x X coordinates in dots\n * @param y Y coordinates in dots\n * @param width Width of tha bar in dots\n * @param height Height of the bar in dots\n */\n constructor(x: number, y: number, width: number, height: number) {\n super(x,y)\n this.width = width\n this.height = height\n }\n\n get commandString(): string {\n return `BAR ${this.x}, ${this.y}, ${this.width}, ${this.height}`\n }\n}","import { ECCLevel, AutoManual, Rotation, QRModel } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a QR code\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLQRCommand extends TSPLVisualCommand {\n private readonly ecc: ECCLevel\n private readonly cellWidth: number\n private readonly mode: AutoManual\n private readonly rotation: Rotation\n private readonly model: QRModel\n /**\n * Should be between 0 and 7\n */\n private readonly mask: number\n private readonly content: string\n\n constructor(content: string, \n x: number, \n y: number, \n cellWidth: number, \n ecc: ECCLevel = \"H\", \n mode: AutoManual = \"A\", \n rotation: Rotation = 0, \n model: QRModel = \"M2\", \n mask: number = 7) {\n super(x,y)\n this.content = content\n this.cellWidth = cellWidth\n this.ecc = ecc\n this.mode = mode\n this.rotation = rotation\n this.model = model\n this.mask = mask\n\n if (mask < 0 || mask > 8) {\n throw new Error(`Invalid mask provided: ${mask}`)\n }\n }\n\n get commandString(): string {\n return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, ${this.mask}, \\\"${this.content}\\\"`\n }\n}","import { Alignment, Rotation } from \"../../types\";\nimport TSPLTextCommand from \"./TSPLTextCommand\";\n\nexport default class TSPLBlockCommand extends TSPLTextCommand {\n private readonly width: number\n private readonly height: number\n private readonly lineSpacing: number\n\n constructor(content: string, \n x: number, \n y: number, \n width: number,\n height: number,\n font: string, \n rotation?: Rotation, \n xMultiplication?: number, \n yMultiplication?: number, \n lineSpacing: number = 0,\n alignment?: Alignment) {\n super(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment)\n this.width = width\n this.height = height\n this.lineSpacing = lineSpacing\n }\n\n get commandString(): string {\n return `BLOCK ${this.x},${this.y},${this.width}, ${this.height},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.lineSpacing},${this.alignment},\\\"${this.content}\\\"`\n }\n}","export { default as Printer } from \"./Printer\"\nexport { PrinterService } from \"./PrinterService\"","import { Command, PrinterLanguage } from \"@/commands\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Base class that encapsulates functionality of all printers\n */\nexport default abstract class Printer {\n private readonly usbDevice: UsbDevice\n\n /**\n * Printer language used by the type of printer the subclass represents\n */\n abstract get language(): PrinterLanguage\n\n /**\n * When called, it will feed the labels to the beginig of the next label\n */\n abstract feedLabel(): Promise<void>\n\n constructor(device: UsbDevice) {\n this.usbDevice = device\n }\n\n /**\n * Close the printer USB\n */\n async close() {\n await this.usbDevice.close()\n }\n\n /**\n * Writes a command to the printers usb\n * @param command Command to send to the usb\n */\n async writeCommand(command: Command): Promise<void> {\n if(!this.usbDevice.opened) await this.usbDevice.openAndConfigure()\n await command.write(this.usbDevice)\n }\n\n /**\n * Check if the device is indeed a printer\n * @param device \n */\n static try(_device: UsbDevice): Promise<boolean> {\n throw new Error(\"try(device:) should be implemented\")\n }\n}","import { WebUSB } from \"usb\";\nimport StringUtils from \"./StringUtils\";\n\nconst unsupportedUsbError = \"usb-unsupported\"\nconst stringHelper = new StringUtils()\n\n/**\n * @returns The appropiate USB agent based on the environment\n */\nconst getUSB = (): USB => {\n if(typeof navigator !== \"undefined\") {\n if(navigator.usb) {\n return navigator.usb\n } else {\n throw unsupportedUsbError\n }\n }\n\n return new WebUSB({allowAllDevices: true})\n}\n\nexport const usbAgent = getUSB()\n\n/**\n * Returns the list of available devices\n * In node this returns all the connected devices but in the browser it will only return devices \n * that the user already gave permission to\n * @returns A list of available devices\n */\nexport const getDevices = async (): Promise<UsbDevice[]> => {\n const devices = await usbAgent.getDevices()\n return devices.map(device => new UsbDevice(device) )\n}\n\n/**\n * In node, it returns the first available device, in the browser (supported browsers only) it shows \n * a UI for the user to choose a device\n * @returns The first available device\n */\nexport const requestDevice = async (): Promise<UsbDevice|undefined> => {\n const device = await usbAgent.requestDevice()\n if(device) {\n return new UsbDevice(device)\n } else {\n return undefined\n }\n}\n\n/**\n * Convenience wrapper for a web usb device\n * Its main purpose is to hide the details of the usb library from client code so in case\n * it needs to be switched, compatibility can be retained\n */\nexport class UsbDevice {\n private readonly device: USBDevice\n\n get opened() {\n return this.device.opened\n }\n\n /**\n * All available endpoints\n */\n private get endpoints() {\n return this.device.configuration?.interfaces[0].alternate.endpoints ?? []\n }\n\n /**\n * Endpoint for writing\n */\n private get outEndpoint() {\n return this.endpoints.find(e => e.direction == \"out\")?.endpointNumber\n }\n\n /**\n * Endpoint for reading\n */\n private get inEndpoint() {\n return this.endpoints.find(e => e.direction == \"in\")?.endpointNumber\n }\n\n constructor(device: USBDevice) {\n this.device = device\n }\n\n /**\n * Open the device and claim its interface\n */\n async openAndConfigure() {\n await this.device.open();\n await this.device.selectConfiguration(1);\n await this.device.claimInterface(0);\n }\n\n /**\n * Closes the device\n */\n async close() {\n await this.device.releaseInterface(0)\n await this.device.close()\n }\n\n /**\n * Write data to an USB device\n * @param data Data to write\n */\n async writeData(data: Uint8Array): Promise<void> {\n const endpointNumber = this.outEndpoint\n await this.device.transferOut(endpointNumber!, data)\n }\n\n /**\n * Writes a text to a device\n * @param text Text to write\n */\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n /**\n * Reads bytes from the usb device\n * @param length The max length of the incoming data. \n * @returns Bytes received as a DataView or undefined. If data is longer then `length`, undefined will be returned\n */\n async readData(length: number): Promise<DataView|undefined> {\n const endpointNumber = this.inEndpoint\n const result = await this.device.transferIn(endpointNumber!, length)\n\n if(result.status == \"ok\" && result.data) {\n return result.data\n } else {\n return undefined\n }\n }\n\n /**\n * Reads data from the usb device and converts it to string\n * {@see readData}\n */\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","/**\n * Collection of helpers to work with strings\n */\nexport default class StringUtils {\n /**\n * Convert string to utf8 array\n * @param str Convert string to byte array\n */\n toUTF8Array(str: string) {\n let utf8Encode = new TextEncoder();\n return utf8Encode.encode(str)\n }\n\n /**\n * Convert bytes to utf8 encoded string\n * @param bytes Bytes to decode\n * @returns A string\n */\n toString(bytes: Uint8Array|DataView) {\n let decoder = new TextDecoder()\n return decoder.decode(bytes)\n }\n}","import { TSPLRawCommand } from \"@/commands/tspl\";\nimport { PrinterLanguage } from \"@/commands\"\nimport Printer from \"./Printer\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\nexport default class TSPLPrinter extends Printer {\n get language(): PrinterLanguage {\n return \"tspl\"\n }\n\n async feedLabel(): Promise<void> {\n const feedCommand = new TSPLRawCommand(\"FORMFEED\")\n await this.writeCommand(feedCommand)\n }\n\n static async try(device: UsbDevice): Promise<boolean> {\n if(!device.opened) await device.openAndConfigure()\n const testCommand = new TSPLRawCommand(\"~!I\")\n await testCommand.write(device)\n\n const response = await device.readString(64)\n await device.close()\n // If there is a response, we have a TSPL printer\n return !!response\n }\n}","import { UsbDevice, getDevices, requestDevice } from \"@/helpers/USBUtils\"\nimport TSPLPrinter from \"./TSPLPrinter\"\nimport Printer from \"./Printer\"\n\nexport class PrinterService {\n /**\n * Try each type of printer and return the one that mathces the usb device\n * @param device \n * @returns \n */\n static async printerForDevice(device: UsbDevice): Promise<Printer|undefined> {\n const classes = [TSPLPrinter]\n\n for (const key in classes) {\n if(await classes[key].try(device)) {\n return new classes[key](device)\n }\n }\n\n return undefined\n }\n\n /**\n * @returns List of available printers\n */\n static async getPrinters(): Promise<Printer[]> {\n const devices = await getDevices()\n const optionalPrinters = await Promise.all(devices.map(PrinterService.printerForDevice))\n return optionalPrinters.filter(printer => !!printer) as Printer[]\n }\n\n /**\n * This is intended to be used in the browser although it also works in node\n * In the browser, it provides a UI for the user to choose a USB device and if it is a\n * printer, it returns a new printer instance. In Node however, this will try to create\n * a printer for the first available device and returns it. This means that even if there is a \n * printer, it may return undefined. In node, use `getPrinters` instead\n */\n static async requestPrinter(): Promise<Printer|undefined> {\n const device = await requestDevice()\n if(device) {\n return PrinterService.printerForDevice(device)\n }\n }\n}"],"mappings":"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","names":["pixels"]}
package/dist/index.mjs CHANGED
@@ -151,10 +151,120 @@ var TSPLVisualCommand = class extends TSPLCommand {
151
151
  }
152
152
  };
153
153
 
154
- // src/commands/tspl/commands/basic/TSPLBitmapCommand.ts
155
- var TSPLBitmapCommand = class extends TSPLVisualCommand {
154
+ // src/helpers/ImageUtils.ts
155
+ import pixels from "image-pixels";
156
+ var BLACK_PIXEL = 0;
157
+ var WHITE_PIXEL = 1;
158
+ var ImageUtils = class {
156
159
  /**
160
+ * Get pixel information about an image
161
+ * @param image Image to process
162
+ * @returns
163
+ */
164
+ static getPixels(image) {
165
+ return __async(this, null, function* () {
166
+ const { width, height, data } = yield pixels(image);
167
+ const bitsPerPixel = data.length / height / width;
168
+ return {
169
+ data,
170
+ width,
171
+ height,
172
+ bitsPerPixel
173
+ };
174
+ });
175
+ }
176
+ /**
177
+ * Return a bitmap in which all pixels are represented with one bit of either 1 or 0 representing white and black
178
+ * pixels respectively. `destinationWidth` and `destinationHeight` have to be smaller or equal to the
179
+ * input size as only downscaling is performed
157
180
  *
181
+ * @param image Image to process
182
+ * @param destinationWidth Width of the ouput bitmap
183
+ * @param destinationHeight Height of the output bitmap
184
+ * @returns
185
+ */
186
+ static getBWBitmap(image, destinationWidth, destinationHeight) {
187
+ return __async(this, null, function* () {
188
+ const {
189
+ data,
190
+ width,
191
+ height,
192
+ bitsPerPixel
193
+ } = yield this.getPixels(image);
194
+ const dWidth = destinationWidth != null ? destinationWidth : width;
195
+ const dHeight = destinationHeight != null ? destinationHeight : height;
196
+ const differenceToDividable = dWidth % 8 == 0 ? 0 : 8 - dWidth % 8;
197
+ const dividableDWidth = dWidth + differenceToDividable;
198
+ const bitmapData = new Uint8Array(dividableDWidth * dHeight);
199
+ let destinationIndex = 0;
200
+ for (let h = 0; h < dHeight; h++) {
201
+ const originalHeight = Math.round(h * (height - 1) / (dHeight - 1));
202
+ for (let w = 0; w < dWidth; w++) {
203
+ const originalWidth = Math.round(w * (width - 1) / (dWidth - 1));
204
+ const baseIndex = originalHeight * width * bitsPerPixel + originalWidth * bitsPerPixel;
205
+ const r = data[baseIndex];
206
+ const g = data[baseIndex + 1];
207
+ const b = data[baseIndex + 2];
208
+ const a = data[baseIndex + 3];
209
+ if (a > 128) {
210
+ const avg = (r + g + b) / 3;
211
+ if (avg > 128) {
212
+ bitmapData[destinationIndex] = WHITE_PIXEL;
213
+ } else {
214
+ bitmapData[destinationIndex] = BLACK_PIXEL;
215
+ }
216
+ } else {
217
+ bitmapData[destinationIndex] = WHITE_PIXEL;
218
+ }
219
+ destinationIndex += 1;
220
+ }
221
+ for (let i = 0; i < differenceToDividable; i++) {
222
+ bitmapData[destinationIndex] = WHITE_PIXEL;
223
+ destinationIndex += 1;
224
+ }
225
+ }
226
+ const byteArrays = this.chunk(bitmapData, 8);
227
+ const widthInBytes = dividableDWidth / 8;
228
+ const bytes = byteArrays.map(this.bitsToByte);
229
+ const finalBytes = new Uint8Array(bytes);
230
+ return {
231
+ width: widthInBytes,
232
+ height: dHeight,
233
+ bytes: finalBytes
234
+ };
235
+ });
236
+ }
237
+ /**
238
+ * Splits an array into chunks.
239
+ * @param originalArray
240
+ * @param chunkSize
241
+ * @returns
242
+ */
243
+ static chunk(originalArray, chunkSize) {
244
+ const resultArray = [];
245
+ for (let i = 0; i < originalArray.length; i += chunkSize) {
246
+ const chunk = originalArray.slice(i, i + chunkSize);
247
+ resultArray.push(chunk);
248
+ }
249
+ return resultArray;
250
+ }
251
+ /**
252
+ * Converts an array of bits to a byte
253
+ * @param bits
254
+ * @returns
255
+ */
256
+ static bitsToByte(bits) {
257
+ let byteValue = 0;
258
+ for (let i = 0; i < bits.length; i++) {
259
+ byteValue = byteValue << 1 | bits[i];
260
+ }
261
+ return byteValue;
262
+ }
263
+ };
264
+
265
+ // src/commands/tspl/commands/basic/TSPLBitmapCommand.ts
266
+ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
267
+ /**
158
268
  * @param bitmap Bitmap to present.
159
269
  * @param x X coordinates in dots
160
270
  * @param y Y Coordinates in dots
@@ -192,6 +302,22 @@ var TSPLBitmapCommand = class extends TSPLVisualCommand {
192
302
  yield this.terminateCommand(device);
193
303
  });
194
304
  }
305
+ /**
306
+ * Create a new bitmap command for the given image url
307
+ * @param image Image to create command for
308
+ * @param x X coordinate of the image
309
+ * @param y Y coordinate of the image
310
+ * @param imageWidth Desired width of the image
311
+ * @param imageHeight Desired height of the image
312
+ * @param mode Graphics mode
313
+ * @returns
314
+ */
315
+ static forImageUrl(image, x, y, imageWidth, imageHeight, mode) {
316
+ return __async(this, null, function* () {
317
+ const bitmap = yield ImageUtils.getBWBitmap(image, imageWidth, imageHeight);
318
+ return new _TSPLBitmapCommand(bitmap, x, y, mode);
319
+ });
320
+ }
195
321
  };
196
322
 
197
323
  // src/commands/tspl/types.ts
@@ -438,6 +564,14 @@ var getDevices = () => __async(void 0, null, function* () {
438
564
  const devices = yield usbAgent.getDevices();
439
565
  return devices.map((device) => new UsbDevice(device));
440
566
  });
567
+ var requestDevice = () => __async(void 0, null, function* () {
568
+ const device = yield usbAgent.requestDevice();
569
+ if (device) {
570
+ return new UsbDevice(device);
571
+ } else {
572
+ return void 0;
573
+ }
574
+ });
441
575
  var UsbDevice = class {
442
576
  get opened() {
443
577
  return this.device.opened;
@@ -587,6 +721,21 @@ var PrinterService = class _PrinterService {
587
721
  return optionalPrinters.filter((printer) => !!printer);
588
722
  });
589
723
  }
724
+ /**
725
+ * This is intended to be used in the browser although it also works in node
726
+ * In the browser, it provides a UI for the user to choose a USB device and if it is a
727
+ * printer, it returns a new printer instance. In Node however, this will try to create
728
+ * a printer for the first available device and returns it. This means that even if there is a
729
+ * printer, it may return undefined. In node, use `getPrinters` instead
730
+ */
731
+ static requestPrinter() {
732
+ return __async(this, null, function* () {
733
+ const device = yield requestDevice();
734
+ if (device) {
735
+ return _PrinterService.printerForDevice(device);
736
+ }
737
+ });
738
+ }
590
739
  };
591
740
  export {
592
741
  commands_exports as commands,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/index.ts","../src/commands/Command.ts","../src/commands/CommandGroup.ts","../src/commands/tspl/index.ts","../src/commands/tspl/TSPLCommand.ts","../src/commands/tspl/commands/TSPLRawCommand.ts","../src/commands/tspl/commands/TSPLCommandGroup.ts","../src/commands/tspl/commands/TSPLVisualCommand.ts","../src/commands/tspl/commands/basic/TSPLBitmapCommand.ts","../src/commands/tspl/types.ts","../src/commands/tspl/commands/basic/TSPLTextCommand.ts","../src/commands/tspl/commands/basic/TSPLGapCommand.ts","../src/commands/tspl/commands/basic/TSPLSizeCommand.ts","../src/commands/tspl/commands/basic/TSPLCLSCommand.ts","../src/commands/tspl/commands/basic/TSPLDirectionCommand.ts","../src/commands/tspl/commands/basic/TSPLPrintCommand.ts","../src/commands/tspl/commands/basic/TSPLBarCommand.ts","../src/commands/tspl/commands/basic/TSPLQRCommand.ts","../src/commands/tspl/commands/basic/TSPLBlockCommand.ts","../src/printers/index.ts","../src/printers/Printer.ts","../src/helpers/USBUtils.ts","../src/helpers/StringUtils.ts","../src/printers/TSPLPrinter.ts","../src/printers/PrinterService.ts"],"sourcesContent":["export { default as Command } from \"./Command\"\nexport { default as CommandGroup } from \"./CommandGroup\"\n\nexport type PrinterLanguage = \"tspl\"\n\nexport * as tspl from \"./tspl\"","import { UsbDevice } from \"@/helpers/USBUtils\"\n\n/**\n * Base implementation for all types of command\n * Represents a command to be send to the printer to execute, such as print\n */\nexport default abstract class Command {\n /**\n * Returns a string representation of the command\n */\n abstract get commandString(): string\n\n /**\n * Write the command data to a USB device\n * @param device Device to write to\n */\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Byte representation of a newline\n */\n protected get commandTerminatorBytes(): Uint8Array {\n return new Uint8Array([10])\n }\n\n /**\n * Writes a string to a device\n * @param data String representation of data\n * @param device Device to write to\n */\n protected async writeString(data: string, device: UsbDevice): Promise<void> {\n await device.writeString(data)\n }\n\n /**\n * Writes bytes to a device. It will automatically end a command with @see{commandTerminatorBytes}\n * @param data Byte array to send\n * @param device Device to write to\n */\n protected async writeBytes(data: Uint8Array, device: UsbDevice): Promise<void> {\n await device.writeData(data)\n }\n\n /**\n * Write the command terminator to the device\n * @param device \n */\n protected async terminateCommand(device: UsbDevice): Promise<void> {\n await this.writeBytes(this.commandTerminatorBytes, device)\n }\n}","import { UsbDevice } from \"@/helpers/USBUtils\";\nimport Command from \"./Command\";\n\n/**\n * A utility class that helps groupping commands together\n * Should be implemnted with a specific command type to ensure only commands for the same lagnuage are\n * groupped together\n */\nexport default abstract class CommandGroup<T extends Command> extends Command {\n private commands: T[]\n\n constructor(commands: T[]) {\n super()\n this.commands = commands\n }\n\n async write(device: UsbDevice): Promise<void> {\n for (let commandIndex in this.commands) {\n await this.commands[commandIndex].write(device)\n }\n }\n\n get commandString(): string {\n return \"\"\n }\n}","export { default as TSPLCommand } from \"./TSPLCommand\"\n\nexport * from \"./commands\"\nexport * from \"./types\"","import Command from \"@/commands/Command\";\n\n/**\n * Base for TSPL specific commands\n */\nexport default abstract class TSPLCommand extends Command {\n}","import TSPLCommand from \"../TSPLCommand\"\n\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLRawCommand extends TSPLCommand {\n /**\n * Raw command string\n */\n private readonly commandBody: string\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(body: string) {\n super()\n this.commandBody = body\n }\n\n get commandString(): string {\n return this.commandBody;\n }\n}\n","import CommandGroup from \"@/commands/CommandGroup\";\nimport TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Command group for tspl commands\n */\nexport default class TSPLCommandGroup extends CommandGroup<TSPLCommand> {}","import TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Base for all TSPL commands that have a visual effect on the final label\n */\nexport default abstract class TSPLVisualCommand extends TSPLCommand {\n protected readonly x: number\n protected readonly y: number\n\n constructor(x: number, y: number) {\n super()\n this.x = x\n this.y = y\n }\n}","import { BWBitmap } from \"@/helpers/ImageUtils\";\nimport { GraphicMode } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Represents a bitmap command. Can be used to draw an image to the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBitmapCommand extends TSPLVisualCommand {\n /**\n * Bitmap to present. \n * TSPL only supports black and write printing so this bitmap contains a matrix of 1 (White pixel)\n * and 0 (Black pixel) values\n */\n private readonly bitmap: BWBitmap\n private readonly mode: GraphicMode\n \n /**\n * \n * @param bitmap Bitmap to present. \n * @param x X coordinates in dots\n * @param y Y Coordinates in dots\n * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values\n */\n constructor(bitmap: BWBitmap, x: number, y: number, mode?: GraphicMode) {\n super(x, y);\n this.bitmap = bitmap;\n this.mode = mode ?? \"overwrite\"\n }\n\n get commandString(): string {\n const textDecoder = new TextDecoder('utf-8')\n const bytesString = textDecoder.decode(this.bitmap.bytes)\n\n return `${this.commandWithoutBytes}${bytesString.slice(0,5)}...\\n`;\n }\n\n private get commandWithoutBytes(): string {\n return `BITMAP ${this.x}, ${this.y},${this.bitmap.width},${this.bitmap.height},${this.modeValue},`\n }\n\n private get modeValue(): 0|1|2 {\n switch (this.mode) {\n case \"overwrite\": return 0\n case \"or\": return 1\n case \"xor\": return 2\n }\n }\n\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandWithoutBytes, device)\n await this.writeBytes(this.bitmap.bytes, device)\n await this.terminateCommand(device)\n }\n}","export type Rotation = 0|90|180|270\nexport type Alignment = undefined|\"left\"|\"center\"|\"right\"\n\n/**\n * Convert an alignemnt string to its number value\n * @param alignment \n * @returns \n */\nexport const alignmentToNumber = (alignment: Alignment): 0|1|2|3 => {\n switch(alignment) {\n case undefined: return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n}\n\n/**\n * Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation\n * on the values\n */\nexport type GraphicMode = \"overwrite\"|\"or\"|\"xor\"\nexport type UnitSystem = \"imperial\"|\"metric\"|\"dot\"\nexport type ECCLevel = \"L\"|\"M\"|\"Q\"|\"H\"\nexport type AutoManual = \"A\"|\"M\"\nexport type QRModel = \"M1\"|\"M2\"\nexport type BarcodeType = \"CODE128\"|\"EAN13\"|\"EAN8\"|\"EAN5\"|\"EAN2\"|\"UPC\"|\"CODE39\"|\"ITF14\"|\"MSI10\"|\"MSI11\"|\"MSI1010\"|\"MSI1110\"|\"pharmacode\"|\"codabar\"\nexport type BarcodeHumanReable = \"none\"|\"left\"|\"right\"|\"center\"","import { Alignment, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a single line text on the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLTextCommand extends TSPLVisualCommand {\n /**\n * Name of the font to use. Consult documentation for more info\n */\n protected readonly font: string\n /**\n * Angle of rotation of the text. 0, 90, 180 or 270\n */\n protected readonly rotatation: Rotation\n /**\n * Multiplication of the font size in x axis\n */\n protected readonly xMultiplication: number\n /**\n * Multiplication of the font size in y axis\n */\n protected readonly yMultiplication: number\n /**\n * Text alignment. Left, Center or Right. The default alignmnet is left\n */\n protected readonly alignment: number\n /**\n * Text to print\n */\n protected readonly content: string\n\n constructor(content: string, x: number, y: number, font: string, rotation?: Rotation, xMultiplication?: number, yMultiplication?: number, alignment?: Alignment) {\n super(x, y)\n this.font = font\n this.rotatation = rotation ?? 0\n this.xMultiplication = xMultiplication ?? 1\n this.yMultiplication = yMultiplication ?? 1\n this.alignment = alignmentToNumber(alignment)\n this.content = content\n }\n\n get commandString(): string {\n return `TEXT ${this.x},${this.y},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the gap between two labels\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLGapCommand extends TSPLCommand {\n private readonly gap: number\n private readonly offset: number\n\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(gap: number, offset: number, unitSystem: UnitSystem) {\n super()\n this.gap = gap\n this.offset = offset\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `GAP ${this.valueWithUnit(this.gap)}, ${this.valueWithUnit(this.offset)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the size of the label to rpint\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLSizeCommand extends TSPLCommand {\n private readonly width: number\n private readonly height: number\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(width: number, height: number, unitSystem: UnitSystem) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `SIZE ${this.valueWithUnit(this.width)}, ${this.valueWithUnit(this.height)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Clear the image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLCLSCommand extends TSPLCommand {\n get commandString(): string {\n return \"CLS\"\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * This command defines in which direction will the label be printed and wether or not to mirror the image\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDirectionCommand extends TSPLCommand {\n private readonly direction: 0|1\n private readonly mirror: 0|1\n\n /**\n * @param direction Controls the orientation of the resulting label compared to the printer\n * @param mirror Controls mirroring relative to the center line of the label perpendicular to the printhead. See the documentsion for examples\n */\n constructor(direction: \"normal\"|\"inverse\", mirror?: boolean) {\n super()\n this.direction = direction == \"normal\" ? 1 : 0\n this.mirror = mirror ? 1 : 0\n }\n\n get commandString(): string {\n return `DIRECTION ${this.direction}, ${this.mirror}`\n }\n}\n","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Prints the current image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLPrintCommand extends TSPLCommand {\n /**\n * The number of set to print.\n */\n private readonly sets: number\n /**\n * The number of copies to print of each set.\n * The difference between a set and a copy is that if you have a counter for example,\n * the counter will be incremented for each set but not for each copy\n */\n private readonly copies: number\n\n constructor(sets: number, copies: number = 1) {\n super()\n this.sets = sets\n this.copies = copies\n }\n\n get commandString(): string {\n return `PRINT ${this.sets}, ${this.copies}`\n }\n}","import TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Draws a black bar\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBarCommand extends TSPLVisualCommand {\n private readonly width: number\n private readonly height: number\n\n /**\n * @param x X coordinates in dots\n * @param y Y coordinates in dots\n * @param width Width of tha bar in dots\n * @param height Height of the bar in dots\n */\n constructor(x: number, y: number, width: number, height: number) {\n super(x,y)\n this.width = width\n this.height = height\n }\n\n get commandString(): string {\n return `BAR ${this.x}, ${this.y}, ${this.width}, ${this.height}`\n }\n}","import { ECCLevel, AutoManual, Rotation, QRModel } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a QR code\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLQRCommand extends TSPLVisualCommand {\n private readonly ecc: ECCLevel\n private readonly cellWidth: number\n private readonly mode: AutoManual\n private readonly rotation: Rotation\n private readonly model: QRModel\n /**\n * Should be between 0 and 7\n */\n private readonly mask: number\n private readonly content: string\n\n constructor(content: string, \n x: number, \n y: number, \n cellWidth: number, \n ecc: ECCLevel = \"H\", \n mode: AutoManual = \"A\", \n rotation: Rotation = 0, \n model: QRModel = \"M2\", \n mask: number = 7) {\n super(x,y)\n this.content = content\n this.cellWidth = cellWidth\n this.ecc = ecc\n this.mode = mode\n this.rotation = rotation\n this.model = model\n this.mask = mask\n\n if (mask < 0 || mask > 8) {\n throw new Error(`Invalid mask provided: ${mask}`)\n }\n }\n\n get commandString(): string {\n return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, ${this.mask}, \\\"${this.content}\\\"`\n }\n}","import { Alignment, Rotation } from \"../../types\";\nimport TSPLTextCommand from \"./TSPLTextCommand\";\n\nexport default class TSPLBlockCommand extends TSPLTextCommand {\n private readonly width: number\n private readonly height: number\n private readonly lineSpacing: number\n\n constructor(content: string, \n x: number, \n y: number, \n width: number,\n height: number,\n font: string, \n rotation?: Rotation, \n xMultiplication?: number, \n yMultiplication?: number, \n lineSpacing: number = 0,\n alignment?: Alignment) {\n super(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment)\n this.width = width\n this.height = height\n this.lineSpacing = lineSpacing\n }\n\n get commandString(): string {\n return `BLOCK ${this.x},${this.y},${this.width}, ${this.height},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.lineSpacing},${this.alignment},\\\"${this.content}\\\"`\n }\n}","export { default as Printer } from \"./Printer\"\nexport { PrinterService } from \"./PrinterService\"","import { Command, PrinterLanguage } from \"@/commands\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Base class that encapsulates functionality of all printers\n */\nexport default abstract class Printer {\n private readonly usbDevice: UsbDevice\n\n /**\n * Printer language used by the type of printer the subclass represents\n */\n abstract get language(): PrinterLanguage\n\n /**\n * When called, it will feed the labels to the beginig of the next label\n */\n abstract feedLabel(): Promise<void>\n\n constructor(device: UsbDevice) {\n this.usbDevice = device\n }\n\n /**\n * Close the printer USB\n */\n async close() {\n await this.usbDevice.close()\n }\n\n /**\n * Writes a command to the printers usb\n * @param command Command to send to the usb\n */\n protected async writeCommand(command: Command): Promise<void> {\n if(!this.usbDevice.opened) await this.usbDevice.openAndConfigure()\n await command.write(this.usbDevice)\n }\n\n /**\n * Check if the device is indeed a printer\n * @param device \n */\n static try(_device: UsbDevice): Promise<boolean> {\n throw new Error(\"try(device:) should be implemented\")\n }\n}","import { InEndpoint, WebUSB } from \"usb\";\nimport StringUtils from \"./StringUtils\";\n\nconst unsupportedUsbError = \"usb-unsupported\"\nconst stringHelper = new StringUtils()\n\n/**\n * @returns The appropiate USB agent based on the environment\n */\nconst getUSB = (): USB => {\n if(typeof navigator !== \"undefined\") {\n if(navigator.usb) {\n return navigator.usb\n } else {\n throw unsupportedUsbError\n }\n }\n\n return new WebUSB({allowAllDevices: true})\n}\n\nexport const usbAgent = getUSB()\n\n/**\n * @returns A list of available devices\n */\nexport const getDevices = async (): Promise<UsbDevice[]> => {\n const devices = await usbAgent.getDevices()\n return devices.map(device => new UsbDevice(device) )\n}\n\n/**\n * Convenience wrapper for a web usb device\n * Its main purpose is to hide the details of the usb library from client code so in case\n * it needs to be switched, compatibility can be retained\n */\nexport class UsbDevice {\n private readonly device: USBDevice\n\n get opened() {\n return this.device.opened\n }\n\n /**\n * All available endpoints\n */\n private get endpoints() {\n return this.device.configuration?.interfaces[0].alternate.endpoints ?? []\n }\n\n /**\n * Endpoint for writing\n */\n private get outEndpoint() {\n return this.endpoints.find(e => e.direction == \"out\")?.endpointNumber\n }\n\n /**\n * Endpoint for reading\n */\n private get inEndpoint() {\n return this.endpoints.find(e => e.direction == \"in\")?.endpointNumber\n }\n\n constructor(device: USBDevice) {\n this.device = device\n }\n\n /**\n * Open the device and claim its interface\n */\n async openAndConfigure() {\n await this.device.open();\n await this.device.selectConfiguration(1);\n await this.device.claimInterface(0);\n }\n\n /**\n * Closes the device\n */\n async close() {\n await this.device.releaseInterface(0)\n await this.device.close()\n }\n\n /**\n * Write data to an USB device\n * @param data Data to write\n */\n async writeData(data: Uint8Array): Promise<void> {\n const endpointNumber = this.outEndpoint\n await this.device.transferOut(endpointNumber!, data)\n }\n\n /**\n * Writes a text to a device\n * @param text Text to write\n */\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n /**\n * Reads bytes from the usb device\n * @param length The max length of the incoming data. \n * @returns Bytes received as a DataView or undefined. If data is longer then `length`, undefined will be returned\n */\n async readData(length: number): Promise<DataView|undefined> {\n const endpointNumber = this.inEndpoint\n const result = await this.device.transferIn(endpointNumber!, length)\n\n if(result.status == \"ok\" && result.data) {\n return result.data\n } else {\n return undefined\n }\n }\n\n /**\n * Reads data from the usb device and converts it to string\n * {@see readData}\n */\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","/**\n * Collection of helpers to work with strings\n */\nexport default class StringUtils {\n /**\n * Convert string to utf8 array\n * @param str Convert string to byte array\n */\n toUTF8Array(str: string) {\n let utf8Encode = new TextEncoder();\n return utf8Encode.encode(str)\n }\n\n /**\n * Convert bytes to utf8 encoded string\n * @param bytes Bytes to decode\n * @returns A string\n */\n toString(bytes: Uint8Array|DataView) {\n let decoder = new TextDecoder()\n return decoder.decode(bytes)\n }\n}","import { TSPLRawCommand } from \"@/commands/tspl\";\nimport { PrinterLanguage } from \"@/commands\"\nimport Printer from \"./Printer\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\nexport default class TSPLPrinter extends Printer {\n get language(): PrinterLanguage {\n return \"tspl\"\n }\n\n async feedLabel(): Promise<void> {\n const feedCommand = new TSPLRawCommand(\"FORMFEED\")\n await this.writeCommand(feedCommand)\n }\n\n static async try(device: UsbDevice): Promise<boolean> {\n if(!device.opened) await device.openAndConfigure()\n const testCommand = new TSPLRawCommand(\"~!I\")\n await testCommand.write(device)\n\n const response = await device.readString(64)\n await device.close()\n // If there is a response, we have a TSPL printer\n return !!response\n }\n}","import { UsbDevice, getDevices } from \"@/helpers/USBUtils\"\nimport TSPLPrinter from \"./TSPLPrinter\"\nimport Printer from \"./Printer\"\n\nexport class PrinterService {\n /**\n * Try each type of printer and return the one that mathces the usb device\n * @param device \n * @returns \n */\n static async printerForDevice(device: UsbDevice): Promise<Printer|undefined> {\n const classes = [TSPLPrinter]\n\n for (const key in classes) {\n if(await classes[key].try(device)) {\n return new classes[key](device)\n }\n }\n\n return undefined\n }\n\n /**\n * @returns List of available printers\n */\n static async getPrinters(): Promise<Printer[]> {\n const devices = await getDevices()\n const optionalPrinters = await Promise.all(devices.map(PrinterService.printerForDevice))\n return optionalPrinters.filter(printer => !!printer) as Printer[]\n }\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/index.ts","../src/commands/Command.ts","../src/commands/CommandGroup.ts","../src/commands/tspl/index.ts","../src/commands/tspl/TSPLCommand.ts","../src/commands/tspl/commands/TSPLRawCommand.ts","../src/commands/tspl/commands/TSPLCommandGroup.ts","../src/commands/tspl/commands/TSPLVisualCommand.ts","../src/helpers/ImageUtils.ts","../src/commands/tspl/commands/basic/TSPLBitmapCommand.ts","../src/commands/tspl/types.ts","../src/commands/tspl/commands/basic/TSPLTextCommand.ts","../src/commands/tspl/commands/basic/TSPLGapCommand.ts","../src/commands/tspl/commands/basic/TSPLSizeCommand.ts","../src/commands/tspl/commands/basic/TSPLCLSCommand.ts","../src/commands/tspl/commands/basic/TSPLDirectionCommand.ts","../src/commands/tspl/commands/basic/TSPLPrintCommand.ts","../src/commands/tspl/commands/basic/TSPLBarCommand.ts","../src/commands/tspl/commands/basic/TSPLQRCommand.ts","../src/commands/tspl/commands/basic/TSPLBlockCommand.ts","../src/printers/index.ts","../src/printers/Printer.ts","../src/helpers/USBUtils.ts","../src/helpers/StringUtils.ts","../src/printers/TSPLPrinter.ts","../src/printers/PrinterService.ts"],"sourcesContent":["export { default as Command } from \"./Command\"\nexport { default as CommandGroup } from \"./CommandGroup\"\n\nexport type PrinterLanguage = \"tspl\"\n\nexport * as tspl from \"./tspl\"","import { UsbDevice } from \"@/helpers/USBUtils\"\n\n/**\n * Base implementation for all types of command\n * Represents a command to be send to the printer to execute, such as print\n */\nexport default abstract class Command {\n /**\n * Returns a string representation of the command\n */\n abstract get commandString(): string\n\n /**\n * Write the command data to a USB device\n * @param device Device to write to\n */\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandString, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Byte representation of a newline\n */\n protected get commandTerminatorBytes(): Uint8Array {\n return new Uint8Array([10])\n }\n\n /**\n * Writes a string to a device\n * @param data String representation of data\n * @param device Device to write to\n */\n protected async writeString(data: string, device: UsbDevice): Promise<void> {\n await device.writeString(data)\n }\n\n /**\n * Writes bytes to a device. It will automatically end a command with @see{commandTerminatorBytes}\n * @param data Byte array to send\n * @param device Device to write to\n */\n protected async writeBytes(data: Uint8Array, device: UsbDevice): Promise<void> {\n await device.writeData(data)\n }\n\n /**\n * Write the command terminator to the device\n * @param device \n */\n protected async terminateCommand(device: UsbDevice): Promise<void> {\n await this.writeBytes(this.commandTerminatorBytes, device)\n }\n}","import { UsbDevice } from \"@/helpers/USBUtils\";\nimport Command from \"./Command\";\n\n/**\n * A utility class that helps groupping commands together\n * Should be implemnted with a specific command type to ensure only commands for the same lagnuage are\n * groupped together\n */\nexport default abstract class CommandGroup<T extends Command> extends Command {\n private commands: T[]\n\n constructor(commands: T[]) {\n super()\n this.commands = commands\n }\n\n async write(device: UsbDevice): Promise<void> {\n for (let commandIndex in this.commands) {\n await this.commands[commandIndex].write(device)\n }\n }\n\n get commandString(): string {\n return \"\"\n }\n}","export { default as TSPLCommand } from \"./TSPLCommand\"\n\nexport * from \"./commands\"\nexport * from \"./types\"","import Command from \"@/commands/Command\";\n\n/**\n * Base for TSPL specific commands\n */\nexport default abstract class TSPLCommand extends Command {\n}","import TSPLCommand from \"../TSPLCommand\"\n\n/**\n * A raw TSPL command. Can be used to use a command that is not yet supported\n */\nexport default class TSPLRawCommand extends TSPLCommand {\n /**\n * Raw command string\n */\n private readonly commandBody: string\n\n /**\n * Initialize a command with a raw body\n * @param body\n */\n constructor(body: string) {\n super()\n this.commandBody = body\n }\n\n get commandString(): string {\n return this.commandBody;\n }\n}\n","import CommandGroup from \"@/commands/CommandGroup\";\nimport TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Command group for tspl commands\n */\nexport default class TSPLCommandGroup extends CommandGroup<TSPLCommand> {}","import TSPLCommand from \"../TSPLCommand\";\n\n/**\n * Base for all TSPL commands that have a visual effect on the final label\n */\nexport default abstract class TSPLVisualCommand extends TSPLCommand {\n protected readonly x: number\n protected readonly y: number\n\n constructor(x: number, y: number) {\n super()\n this.x = x\n this.y = y\n }\n}","// @ts-ignore\nimport pixels from \"image-pixels\"\n\n/**\n * Helper type to transmit image bitmap data\n */\nexport type Pixels = {\n data: Uint8Array, \n width: number,\n height: number, \n bitsPerPixel: number\n}\n\n/**\n * Helper type to transmit black and white bitmap data\n */\nexport type BWBitmap = {\n width: number,\n height: number,\n bytes: Uint8Array\n}\n\nconst BLACK_PIXEL = 0\nconst WHITE_PIXEL = 1\n\n/**\n * Set of image utility\n */\nexport default class ImageUtils {\n /**\n * Get pixel information about an image\n * @param image Image to process\n * @returns \n */\n static async getPixels(image: string|Blob): Promise<Pixels> {\n const {width, height, data} = await pixels(image) as Omit<Pixels, \"bitsPerPixel\">\n const bitsPerPixel = data.length / height / width\n\n return {\n data, width, height, bitsPerPixel\n }\n }\n\n /**\n * Return a bitmap in which all pixels are represented with one bit of either 1 or 0 representing white and black\n * pixels respectively. `destinationWidth` and `destinationHeight` have to be smaller or equal to the\n * input size as only downscaling is performed\n * \n * @param image Image to process \n * @param destinationWidth Width of the ouput bitmap\n * @param destinationHeight Height of the output bitmap\n * @returns \n */\n static async getBWBitmap(image: string, destinationWidth?: number, destinationHeight?: number): Promise<BWBitmap> {\n const {\n data,\n width,\n height,\n bitsPerPixel\n } = await this.getPixels(image)\n \n // Number of pixels width and height => number of bits for each row and number of rows\n const dWidth = destinationWidth ?? width\n const dHeight = destinationHeight ?? height\n \n const differenceToDividable = dWidth % 8 == 0 ? 0 : (8 - (dWidth % 8))\n const dividableDWidth = dWidth + differenceToDividable\n \n // Size of the array has to be with * height but width has to be extended to be dividable by 8\n const bitmapData = new Uint8Array(dividableDWidth * dHeight)\n \n let destinationIndex = 0\n for (let h=0; h < dHeight; h++) {\n const originalHeight = Math.round((h * (height - 1)) / (dHeight - 1))\n \n for(let w=0; w < dWidth; w++) {\n const originalWidth = Math.round((w * (width - 1)) / (dWidth - 1))\n \n const baseIndex = (originalHeight * width * bitsPerPixel) + (originalWidth * bitsPerPixel)\n \n const r = data[baseIndex]\n const g = data[baseIndex + 1]\n const b = data[baseIndex + 2]\n const a = data[baseIndex + 3]\n \n if(a > 128) {\n const avg = (r + g + b) / 3\n \n if(avg > 128) {\n bitmapData[destinationIndex] = WHITE_PIXEL\n } else {\n bitmapData[destinationIndex] = BLACK_PIXEL\n }\n } else {\n bitmapData[destinationIndex] = WHITE_PIXEL\n }\n destinationIndex += 1\n }\n \n for(let i=0; i < differenceToDividable; i++) {\n bitmapData[destinationIndex] = WHITE_PIXEL\n destinationIndex += 1\n }\n }\n \n const byteArrays = this.chunk(bitmapData,8)\n const widthInBytes = dividableDWidth / 8\n \n const bytes = byteArrays.map(this.bitsToByte)\n const finalBytes = new Uint8Array(bytes)\n \n return {\n width: widthInBytes,\n height: dHeight,\n bytes: finalBytes\n }\n }\n\n /**\n * Splits an array into chunks.\n * @param originalArray\n * @param chunkSize\n * @returns\n */\n private static chunk(originalArray: Uint8Array, chunkSize: number): Uint8Array[] {\n const resultArray = [];\n\n for (let i = 0; i < originalArray.length; i += chunkSize) {\n const chunk = originalArray.slice(i, i + chunkSize);\n resultArray.push(chunk);\n }\n\n return resultArray;\n }\n\n /**\n * Converts an array of bits to a byte\n * @param bits\n * @returns\n */\n private static bitsToByte(bits: Uint8Array) {\n let byteValue = 0;\n for (let i = 0; i < bits.length; i++) {\n byteValue = (byteValue << 1) | bits[i];\n }\n return byteValue;\n }\n}","import ImageUtils, { BWBitmap } from \"@/helpers/ImageUtils\";\nimport { GraphicMode } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Represents a bitmap command. Can be used to draw an image to the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBitmapCommand extends TSPLVisualCommand {\n /**\n * Bitmap to present. \n * TSPL only supports black and write printing so this bitmap contains a matrix of 1 (White pixel)\n * and 0 (Black pixel) values\n */\n private readonly bitmap: BWBitmap\n private readonly mode: GraphicMode\n\n /**\n * @param bitmap Bitmap to present. \n * @param x X coordinates in dots\n * @param y Y Coordinates in dots\n * @param mode Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation on the values\n */\n constructor(bitmap: BWBitmap, x: number, y: number, mode?: GraphicMode) {\n super(x, y);\n this.bitmap = bitmap;\n this.mode = mode ?? \"overwrite\"\n }\n\n get commandString(): string {\n const textDecoder = new TextDecoder('utf-8')\n const bytesString = textDecoder.decode(this.bitmap.bytes)\n\n return `${this.commandWithoutBytes}${bytesString.slice(0,5)}...\\n`;\n }\n\n private get commandWithoutBytes(): string {\n return `BITMAP ${this.x}, ${this.y},${this.bitmap.width},${this.bitmap.height},${this.modeValue},`\n }\n\n private get modeValue(): 0|1|2 {\n switch (this.mode) {\n case \"overwrite\": return 0\n case \"or\": return 1\n case \"xor\": return 2\n }\n }\n\n async write(device: UsbDevice): Promise<void> {\n await this.writeString(this.commandWithoutBytes, device)\n await this.writeBytes(this.bitmap.bytes, device)\n await this.terminateCommand(device)\n }\n\n /**\n * Create a new bitmap command for the given image url\n * @param image Image to create command for \n * @param x X coordinate of the image\n * @param y Y coordinate of the image\n * @param imageWidth Desired width of the image\n * @param imageHeight Desired height of the image\n * @param mode Graphics mode\n * @returns \n */\n static async forImageUrl(image: string, x: number, y: number, imageWidth?: number, imageHeight?: number, mode?: GraphicMode) {\n const bitmap = await ImageUtils.getBWBitmap(image, imageWidth, imageHeight)\n return new TSPLBitmapCommand(bitmap, x, y, mode)\n }\n}","export type Rotation = 0|90|180|270\nexport type Alignment = undefined|\"left\"|\"center\"|\"right\"\n\n/**\n * Convert an alignemnt string to its number value\n * @param alignment \n * @returns \n */\nexport const alignmentToNumber = (alignment: Alignment): 0|1|2|3 => {\n switch(alignment) {\n case undefined: return 0\n case \"left\": return 1\n case \"center\": return 2\n case \"right\": return 3\n }\n}\n\n/**\n * Represents the strategy to use when two bitmaps overlap. The final value will be determined by\n * either overwriting the first bitmap's value with the second one or performing an 'or' or 'xor' operation\n * on the values\n */\nexport type GraphicMode = \"overwrite\"|\"or\"|\"xor\"\nexport type UnitSystem = \"imperial\"|\"metric\"|\"dot\"\nexport type ECCLevel = \"L\"|\"M\"|\"Q\"|\"H\"\nexport type AutoManual = \"A\"|\"M\"\nexport type QRModel = \"M1\"|\"M2\"\nexport type BarcodeType = \"CODE128\"|\"EAN13\"|\"EAN8\"|\"EAN5\"|\"EAN2\"|\"UPC\"|\"CODE39\"|\"ITF14\"|\"MSI10\"|\"MSI11\"|\"MSI1010\"|\"MSI1110\"|\"pharmacode\"|\"codabar\"\nexport type BarcodeHumanReable = \"none\"|\"left\"|\"right\"|\"center\"","import { Alignment, Rotation, alignmentToNumber } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a single line text on the label\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLTextCommand extends TSPLVisualCommand {\n /**\n * Name of the font to use. Consult documentation for more info\n */\n protected readonly font: string\n /**\n * Angle of rotation of the text. 0, 90, 180 or 270\n */\n protected readonly rotatation: Rotation\n /**\n * Multiplication of the font size in x axis\n */\n protected readonly xMultiplication: number\n /**\n * Multiplication of the font size in y axis\n */\n protected readonly yMultiplication: number\n /**\n * Text alignment. Left, Center or Right. The default alignmnet is left\n */\n protected readonly alignment: number\n /**\n * Text to print\n */\n protected readonly content: string\n\n constructor(content: string, x: number, y: number, font: string, rotation?: Rotation, xMultiplication?: number, yMultiplication?: number, alignment?: Alignment) {\n super(x, y)\n this.font = font\n this.rotatation = rotation ?? 0\n this.xMultiplication = xMultiplication ?? 1\n this.yMultiplication = yMultiplication ?? 1\n this.alignment = alignmentToNumber(alignment)\n this.content = content\n }\n\n get commandString(): string {\n return `TEXT ${this.x},${this.y},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.alignment},\\\"${this.content}\\\"`\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the gap between two labels\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLGapCommand extends TSPLCommand {\n private readonly gap: number\n private readonly offset: number\n\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(gap: number, offset: number, unitSystem: UnitSystem) {\n super()\n this.gap = gap\n this.offset = offset\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `GAP ${this.valueWithUnit(this.gap)}, ${this.valueWithUnit(this.offset)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\nimport { UnitSystem } from \"../../types\";\n\n/**\n * Defines the size of the label to rpint\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLSizeCommand extends TSPLCommand {\n private readonly width: number\n private readonly height: number\n /**\n * This controls what unit the {@link width} and {@link height} will be\n * - For imperial, the unit is inches\n * - For metric, the unit is milimeters\n * - For dots, the unit is dots\n */\n private readonly unitSystem: UnitSystem\n\n constructor(width: number, height: number, unitSystem: UnitSystem) {\n super()\n this.width = width\n this.height = height\n this.unitSystem = unitSystem\n } \n\n get commandString(): string {\n return `SIZE ${this.valueWithUnit(this.width)}, ${this.valueWithUnit(this.height)}`\n }\n\n private valueWithUnit(value: number) {\n switch(this.unitSystem) {\n case \"dot\": return `${value} dot`\n case \"imperial\": return value\n case \"metric\": return `${value} mm`\n }\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Clear the image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLCLSCommand extends TSPLCommand {\n get commandString(): string {\n return \"CLS\"\n }\n}","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * This command defines in which direction will the label be printed and wether or not to mirror the image\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLDirectionCommand extends TSPLCommand {\n private readonly direction: 0|1\n private readonly mirror: 0|1\n\n /**\n * @param direction Controls the orientation of the resulting label compared to the printer\n * @param mirror Controls mirroring relative to the center line of the label perpendicular to the printhead. See the documentsion for examples\n */\n constructor(direction: \"normal\"|\"inverse\", mirror?: boolean) {\n super()\n this.direction = direction == \"normal\" ? 1 : 0\n this.mirror = mirror ? 1 : 0\n }\n\n get commandString(): string {\n return `DIRECTION ${this.direction}, ${this.mirror}`\n }\n}\n","import TSPLCommand from \"../../TSPLCommand\";\n\n/**\n * Prints the current image buffer\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLPrintCommand extends TSPLCommand {\n /**\n * The number of set to print.\n */\n private readonly sets: number\n /**\n * The number of copies to print of each set.\n * The difference between a set and a copy is that if you have a counter for example,\n * the counter will be incremented for each set but not for each copy\n */\n private readonly copies: number\n\n constructor(sets: number, copies: number = 1) {\n super()\n this.sets = sets\n this.copies = copies\n }\n\n get commandString(): string {\n return `PRINT ${this.sets}, ${this.copies}`\n }\n}","import TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Draws a black bar\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLBarCommand extends TSPLVisualCommand {\n private readonly width: number\n private readonly height: number\n\n /**\n * @param x X coordinates in dots\n * @param y Y coordinates in dots\n * @param width Width of tha bar in dots\n * @param height Height of the bar in dots\n */\n constructor(x: number, y: number, width: number, height: number) {\n super(x,y)\n this.width = width\n this.height = height\n }\n\n get commandString(): string {\n return `BAR ${this.x}, ${this.y}, ${this.width}, ${this.height}`\n }\n}","import { ECCLevel, AutoManual, Rotation, QRModel } from \"../../types\";\nimport TSPLVisualCommand from \"../TSPLVisualCommand\";\n\n/**\n * Prints a QR code\n * {@link /documentsions/TSPL.pdf}\n */\nexport default class TSPLQRCommand extends TSPLVisualCommand {\n private readonly ecc: ECCLevel\n private readonly cellWidth: number\n private readonly mode: AutoManual\n private readonly rotation: Rotation\n private readonly model: QRModel\n /**\n * Should be between 0 and 7\n */\n private readonly mask: number\n private readonly content: string\n\n constructor(content: string, \n x: number, \n y: number, \n cellWidth: number, \n ecc: ECCLevel = \"H\", \n mode: AutoManual = \"A\", \n rotation: Rotation = 0, \n model: QRModel = \"M2\", \n mask: number = 7) {\n super(x,y)\n this.content = content\n this.cellWidth = cellWidth\n this.ecc = ecc\n this.mode = mode\n this.rotation = rotation\n this.model = model\n this.mask = mask\n\n if (mask < 0 || mask > 8) {\n throw new Error(`Invalid mask provided: ${mask}`)\n }\n }\n\n get commandString(): string {\n return `QRCODE ${this.x}, ${this.y}, ${this.ecc}, ${this.cellWidth}, ${this.mode}, ${this.rotation}, ${this.model}, ${this.mask}, \\\"${this.content}\\\"`\n }\n}","import { Alignment, Rotation } from \"../../types\";\nimport TSPLTextCommand from \"./TSPLTextCommand\";\n\nexport default class TSPLBlockCommand extends TSPLTextCommand {\n private readonly width: number\n private readonly height: number\n private readonly lineSpacing: number\n\n constructor(content: string, \n x: number, \n y: number, \n width: number,\n height: number,\n font: string, \n rotation?: Rotation, \n xMultiplication?: number, \n yMultiplication?: number, \n lineSpacing: number = 0,\n alignment?: Alignment) {\n super(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment)\n this.width = width\n this.height = height\n this.lineSpacing = lineSpacing\n }\n\n get commandString(): string {\n return `BLOCK ${this.x},${this.y},${this.width}, ${this.height},\\\"${this.font}\\\",${this.rotatation},${this.xMultiplication},${this.yMultiplication},${this.lineSpacing},${this.alignment},\\\"${this.content}\\\"`\n }\n}","export { default as Printer } from \"./Printer\"\nexport { PrinterService } from \"./PrinterService\"","import { Command, PrinterLanguage } from \"@/commands\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\n/**\n * Base class that encapsulates functionality of all printers\n */\nexport default abstract class Printer {\n private readonly usbDevice: UsbDevice\n\n /**\n * Printer language used by the type of printer the subclass represents\n */\n abstract get language(): PrinterLanguage\n\n /**\n * When called, it will feed the labels to the beginig of the next label\n */\n abstract feedLabel(): Promise<void>\n\n constructor(device: UsbDevice) {\n this.usbDevice = device\n }\n\n /**\n * Close the printer USB\n */\n async close() {\n await this.usbDevice.close()\n }\n\n /**\n * Writes a command to the printers usb\n * @param command Command to send to the usb\n */\n async writeCommand(command: Command): Promise<void> {\n if(!this.usbDevice.opened) await this.usbDevice.openAndConfigure()\n await command.write(this.usbDevice)\n }\n\n /**\n * Check if the device is indeed a printer\n * @param device \n */\n static try(_device: UsbDevice): Promise<boolean> {\n throw new Error(\"try(device:) should be implemented\")\n }\n}","import { WebUSB } from \"usb\";\nimport StringUtils from \"./StringUtils\";\n\nconst unsupportedUsbError = \"usb-unsupported\"\nconst stringHelper = new StringUtils()\n\n/**\n * @returns The appropiate USB agent based on the environment\n */\nconst getUSB = (): USB => {\n if(typeof navigator !== \"undefined\") {\n if(navigator.usb) {\n return navigator.usb\n } else {\n throw unsupportedUsbError\n }\n }\n\n return new WebUSB({allowAllDevices: true})\n}\n\nexport const usbAgent = getUSB()\n\n/**\n * Returns the list of available devices\n * In node this returns all the connected devices but in the browser it will only return devices \n * that the user already gave permission to\n * @returns A list of available devices\n */\nexport const getDevices = async (): Promise<UsbDevice[]> => {\n const devices = await usbAgent.getDevices()\n return devices.map(device => new UsbDevice(device) )\n}\n\n/**\n * In node, it returns the first available device, in the browser (supported browsers only) it shows \n * a UI for the user to choose a device\n * @returns The first available device\n */\nexport const requestDevice = async (): Promise<UsbDevice|undefined> => {\n const device = await usbAgent.requestDevice()\n if(device) {\n return new UsbDevice(device)\n } else {\n return undefined\n }\n}\n\n/**\n * Convenience wrapper for a web usb device\n * Its main purpose is to hide the details of the usb library from client code so in case\n * it needs to be switched, compatibility can be retained\n */\nexport class UsbDevice {\n private readonly device: USBDevice\n\n get opened() {\n return this.device.opened\n }\n\n /**\n * All available endpoints\n */\n private get endpoints() {\n return this.device.configuration?.interfaces[0].alternate.endpoints ?? []\n }\n\n /**\n * Endpoint for writing\n */\n private get outEndpoint() {\n return this.endpoints.find(e => e.direction == \"out\")?.endpointNumber\n }\n\n /**\n * Endpoint for reading\n */\n private get inEndpoint() {\n return this.endpoints.find(e => e.direction == \"in\")?.endpointNumber\n }\n\n constructor(device: USBDevice) {\n this.device = device\n }\n\n /**\n * Open the device and claim its interface\n */\n async openAndConfigure() {\n await this.device.open();\n await this.device.selectConfiguration(1);\n await this.device.claimInterface(0);\n }\n\n /**\n * Closes the device\n */\n async close() {\n await this.device.releaseInterface(0)\n await this.device.close()\n }\n\n /**\n * Write data to an USB device\n * @param data Data to write\n */\n async writeData(data: Uint8Array): Promise<void> {\n const endpointNumber = this.outEndpoint\n await this.device.transferOut(endpointNumber!, data)\n }\n\n /**\n * Writes a text to a device\n * @param text Text to write\n */\n async writeString(text: string): Promise<void> {\n const bytes = stringHelper.toUTF8Array(text)\n await this.writeData(bytes)\n }\n\n /**\n * Reads bytes from the usb device\n * @param length The max length of the incoming data. \n * @returns Bytes received as a DataView or undefined. If data is longer then `length`, undefined will be returned\n */\n async readData(length: number): Promise<DataView|undefined> {\n const endpointNumber = this.inEndpoint\n const result = await this.device.transferIn(endpointNumber!, length)\n\n if(result.status == \"ok\" && result.data) {\n return result.data\n } else {\n return undefined\n }\n }\n\n /**\n * Reads data from the usb device and converts it to string\n * {@see readData}\n */\n async readString(length: number): Promise<string|undefined> {\n const bytes = await this.readData(length)\n if(bytes) return stringHelper.toString(bytes)\n return undefined\n }\n}\n","/**\n * Collection of helpers to work with strings\n */\nexport default class StringUtils {\n /**\n * Convert string to utf8 array\n * @param str Convert string to byte array\n */\n toUTF8Array(str: string) {\n let utf8Encode = new TextEncoder();\n return utf8Encode.encode(str)\n }\n\n /**\n * Convert bytes to utf8 encoded string\n * @param bytes Bytes to decode\n * @returns A string\n */\n toString(bytes: Uint8Array|DataView) {\n let decoder = new TextDecoder()\n return decoder.decode(bytes)\n }\n}","import { TSPLRawCommand } from \"@/commands/tspl\";\nimport { PrinterLanguage } from \"@/commands\"\nimport Printer from \"./Printer\";\nimport { UsbDevice } from \"@/helpers/USBUtils\";\n\nexport default class TSPLPrinter extends Printer {\n get language(): PrinterLanguage {\n return \"tspl\"\n }\n\n async feedLabel(): Promise<void> {\n const feedCommand = new TSPLRawCommand(\"FORMFEED\")\n await this.writeCommand(feedCommand)\n }\n\n static async try(device: UsbDevice): Promise<boolean> {\n if(!device.opened) await device.openAndConfigure()\n const testCommand = new TSPLRawCommand(\"~!I\")\n await testCommand.write(device)\n\n const response = await device.readString(64)\n await device.close()\n // If there is a response, we have a TSPL printer\n return !!response\n }\n}","import { UsbDevice, getDevices, requestDevice } from \"@/helpers/USBUtils\"\nimport TSPLPrinter from \"./TSPLPrinter\"\nimport Printer from \"./Printer\"\n\nexport class PrinterService {\n /**\n * Try each type of printer and return the one that mathces the usb device\n * @param device \n * @returns \n */\n static async printerForDevice(device: UsbDevice): Promise<Printer|undefined> {\n const classes = [TSPLPrinter]\n\n for (const key in classes) {\n if(await classes[key].try(device)) {\n return new classes[key](device)\n }\n }\n\n return undefined\n }\n\n /**\n * @returns List of available printers\n */\n static async getPrinters(): Promise<Printer[]> {\n const devices = await getDevices()\n const optionalPrinters = await Promise.all(devices.map(PrinterService.printerForDevice))\n return optionalPrinters.filter(printer => !!printer) as Printer[]\n }\n\n /**\n * This is intended to be used in the browser although it also works in node\n * In the browser, it provides a UI for the user to choose a USB device and if it is a\n * printer, it returns a new printer instance. In Node however, this will try to create\n * a printer for the first available device and returns it. This means that even if there is a \n * printer, it may return undefined. In node, use `getPrinters` instead\n */\n static async requestPrinter(): Promise<Printer|undefined> {\n const device = await requestDevice()\n if(device) {\n return PrinterService.printerForDevice(device)\n }\n }\n}"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "label-printer",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "js package providing an abstraction over different thermal printer languages",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -23,10 +23,10 @@
23
23
  "ts-node": "^10.9.2",
24
24
  "tsconfig-paths": "^4.2.0",
25
25
  "tsup": "^8.0.1",
26
- "typescript": "^5.3.3"
26
+ "typescript": "^5.3.3",
27
+ "@changesets/cli": "^2.27.1"
27
28
  },
28
29
  "dependencies": {
29
- "@changesets/cli": "^2.27.1",
30
30
  "@types/w3c-web-usb": "^1.0.10",
31
31
  "image-pixels": "^2.2.2",
32
32
  "usb": "^2.11.0"