isahaq-barcode 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js ADDED
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Isahaq Barcode Generator
3
+ * A universal barcode generator package supporting multiple barcode types and output formats
4
+ */
5
+
6
+ const BarcodeService = require('./src/services/BarcodeService');
7
+ const QrCodeBuilder = require('./src/builders/QrCodeBuilder');
8
+ const { BarcodeTypes } = require('./src/types/BarcodeTypes');
9
+ const { RenderFormats } = require('./src/renderers/RenderFormats');
10
+
11
+ // Main service instance
12
+ const barcodeService = new BarcodeService();
13
+
14
+ /**
15
+ * Main Barcode Generator Class
16
+ */
17
+ class BarcodeGenerator {
18
+ /**
19
+ * Generate a barcode in PNG format
20
+ * @param {string} data - The data to encode
21
+ * @param {string} type - The barcode type
22
+ * @param {Object} options - Additional options
23
+ * @returns {Buffer} PNG buffer
24
+ */
25
+ static png(data, type = 'code128', options = {}) {
26
+ return barcodeService.generate(data, type, 'png', options);
27
+ }
28
+
29
+ /**
30
+ * Generate a barcode in SVG format
31
+ * @param {string} data - The data to encode
32
+ * @param {string} type - The barcode type
33
+ * @param {Object} options - Additional options
34
+ * @returns {string} SVG string
35
+ */
36
+ static svg(data, type = 'code128', options = {}) {
37
+ return barcodeService.generate(data, type, 'svg', options);
38
+ }
39
+
40
+ /**
41
+ * Generate a barcode in HTML format
42
+ * @param {string} data - The data to encode
43
+ * @param {string} type - The barcode type
44
+ * @param {Object} options - Additional options
45
+ * @returns {string} HTML string
46
+ */
47
+ static html(data, type = 'code128', options = {}) {
48
+ return barcodeService.generate(data, type, 'html', options);
49
+ }
50
+
51
+ /**
52
+ * Generate a barcode in PDF format
53
+ * @param {string} data - The data to encode
54
+ * @param {string} type - The barcode type
55
+ * @param {Object} options - Additional options
56
+ * @returns {Buffer} PDF buffer
57
+ */
58
+ static pdf(data, type = 'code128', options = {}) {
59
+ return barcodeService.generate(data, type, 'pdf', options);
60
+ }
61
+
62
+ /**
63
+ * Generate a QR code with advanced features
64
+ * @param {Object} options - QR code options
65
+ * @returns {Object} QR code result
66
+ */
67
+ static modernQr(options = {}) {
68
+ return QrCodeBuilder.create(options);
69
+ }
70
+
71
+ /**
72
+ * Get available barcode types
73
+ * @returns {Array} Array of barcode types
74
+ */
75
+ static getBarcodeTypes() {
76
+ return BarcodeTypes.getAll();
77
+ }
78
+
79
+ /**
80
+ * Get available render formats
81
+ * @returns {Array} Array of render formats
82
+ */
83
+ static getRenderFormats() {
84
+ return RenderFormats.getAll();
85
+ }
86
+
87
+ /**
88
+ * Validate data for a specific barcode type
89
+ * @param {string} data - The data to validate
90
+ * @param {string} type - The barcode type
91
+ * @returns {Object} Validation result
92
+ */
93
+ static validate(data, type) {
94
+ return barcodeService.validate(data, type);
95
+ }
96
+
97
+ /**
98
+ * Generate multiple barcodes in batch
99
+ * @param {Array} items - Array of barcode generation items
100
+ * @returns {Array} Array of generated barcodes
101
+ */
102
+ static batch(items) {
103
+ return barcodeService.batch(items);
104
+ }
105
+
106
+ /**
107
+ * Get watermark positions for QR codes
108
+ * @returns {Array} Array of watermark positions
109
+ */
110
+ static getWatermarkPositions() {
111
+ return [
112
+ 'top-left',
113
+ 'top-right',
114
+ 'bottom-left',
115
+ 'bottom-right',
116
+ 'center',
117
+ 'top-center',
118
+ 'bottom-center',
119
+ 'left-center',
120
+ 'right-center',
121
+ ];
122
+ }
123
+ }
124
+
125
+ // Export main class and utilities
126
+ module.exports = BarcodeGenerator;
127
+ module.exports.BarcodeGenerator = BarcodeGenerator;
128
+ module.exports.BarcodeService = BarcodeService;
129
+ module.exports.QrCodeBuilder = QrCodeBuilder;
130
+ module.exports.BarcodeTypes = BarcodeTypes;
131
+ module.exports.RenderFormats = RenderFormats;
132
+
133
+ // Default export
134
+ module.exports.default = BarcodeGenerator;
package/jest.config.js ADDED
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ testEnvironment: 'node',
3
+ testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'],
4
+ collectCoverageFrom: [
5
+ 'src/**/*.js',
6
+ '!src/**/*.test.js',
7
+ '!src/**/__tests__/**',
8
+ ],
9
+ coverageDirectory: 'coverage',
10
+ coverageReporters: ['text', 'lcov', 'html'],
11
+ setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
12
+ testTimeout: 10000,
13
+ };
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "isahaq-barcode",
3
+ "version": "1.0.0",
4
+ "description": "A universal barcode generator package supporting multiple barcode types and output formats, with extra features like batch generation, watermarking, validation, CLI, and Express.js integration",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "barcode-generate": "./bin/generate.js"
8
+ },
9
+ "scripts": {
10
+ "test": "npx jest",
11
+ "test:watch": "npx jest --watch",
12
+ "test:coverage": "npx jest --coverage",
13
+ "lint": "npx eslint .",
14
+ "lint:fix": "npx eslint . --fix",
15
+ "build": "npm run lint",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "barcode",
20
+ "qrcode",
21
+ "generator",
22
+ "code128",
23
+ "code39",
24
+ "ean13",
25
+ "upc",
26
+ "datamatrix",
27
+ "pdf417",
28
+ "aztec",
29
+ "svg",
30
+ "png",
31
+ "pdf",
32
+ "cli",
33
+ "express",
34
+ "node"
35
+ ],
36
+ "author": "hmisahaq01@gmail.com",
37
+ "license": "MIT",
38
+ "dependencies": {
39
+ "canvas": "^2.11.2",
40
+ "jsbarcode": "^3.11.5",
41
+ "qrcode": "^1.5.3",
42
+ "pdfkit": "^0.14.0",
43
+ "commander": "^11.1.0",
44
+ "chalk": "^4.1.2",
45
+ "ora": "^5.4.1"
46
+ },
47
+ "devDependencies": {
48
+ "jest": "^29.7.0",
49
+ "eslint": "^8.57.0",
50
+ "eslint-config-standard": "^17.1.0",
51
+ "eslint-plugin-import": "^2.29.1",
52
+ "eslint-plugin-node": "^11.1.0",
53
+ "eslint-plugin-promise": "^6.1.1"
54
+ },
55
+ "engines": {
56
+ "node": ">=14.0.0"
57
+ },
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "https://github.com/isahaq1/barcode-generator-npm.git"
61
+ },
62
+ "bugs": {
63
+ "url": "https://github.com/isahaq1/barcode-generator-npm/issues"
64
+ },
65
+ "homepage": "https://github.com/isahaq1/barcode-generator-npm#readme"
66
+ }
@@ -0,0 +1,401 @@
1
+ /**
2
+ * QR Code Builder - Advanced QR code generation with logo and watermark support
3
+ */
4
+
5
+ const QRCode = require('qrcode');
6
+ const { createCanvas, loadImage } = require('canvas');
7
+ const fs = require('fs').promises;
8
+
9
+ class QrCodeBuilder {
10
+ constructor(options = {}) {
11
+ this.options = {
12
+ data: '',
13
+ size: 300,
14
+ margin: 10,
15
+ errorCorrectionLevel: 'M',
16
+ foregroundColor: [0, 0, 0],
17
+ backgroundColor: [255, 255, 255],
18
+ logoPath: null,
19
+ logoSize: 60, // Percentage of QR code size
20
+ label: null,
21
+ labelFont: null,
22
+ labelFontSize: 16,
23
+ watermark: null,
24
+ watermarkPosition: 'center',
25
+ format: 'png',
26
+ ...options,
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Create a new QR Code Builder instance
32
+ * @param {Object} options - Initial options
33
+ * @returns {QrCodeBuilder} Builder instance
34
+ */
35
+ static create(options = {}) {
36
+ return new QrCodeBuilder(options);
37
+ }
38
+
39
+ /**
40
+ * Set the data to encode
41
+ * @param {string} data - The data to encode
42
+ * @returns {QrCodeBuilder} Builder instance
43
+ */
44
+ data(data) {
45
+ this.options.data = data;
46
+ return this;
47
+ }
48
+
49
+ /**
50
+ * Set the QR code size
51
+ * @param {number} size - Size in pixels
52
+ * @returns {QrCodeBuilder} Builder instance
53
+ */
54
+ size(size) {
55
+ this.options.size = size;
56
+ return this;
57
+ }
58
+
59
+ /**
60
+ * Set the margin
61
+ * @param {number} margin - Margin in pixels
62
+ * @returns {QrCodeBuilder} Builder instance
63
+ */
64
+ margin(margin) {
65
+ this.options.margin = margin;
66
+ return this;
67
+ }
68
+
69
+ /**
70
+ * Set the error correction level
71
+ * @param {string} level - Error correction level (L, M, Q, H)
72
+ * @returns {QrCodeBuilder} Builder instance
73
+ */
74
+ errorCorrectionLevel(level) {
75
+ this.options.errorCorrectionLevel = level;
76
+ return this;
77
+ }
78
+
79
+ /**
80
+ * Set the foreground color
81
+ * @param {Array} color - RGB color array [r, g, b]
82
+ * @returns {QrCodeBuilder} Builder instance
83
+ */
84
+ foregroundColor(color) {
85
+ this.options.foregroundColor = color;
86
+ return this;
87
+ }
88
+
89
+ /**
90
+ * Set the background color
91
+ * @param {Array} color - RGB color array [r, g, b]
92
+ * @returns {QrCodeBuilder} Builder instance
93
+ */
94
+ backgroundColor(color) {
95
+ this.options.backgroundColor = color;
96
+ return this;
97
+ }
98
+
99
+ /**
100
+ * Set the logo path
101
+ * @param {string} logoPath - Path to logo image
102
+ * @returns {QrCodeBuilder} Builder instance
103
+ */
104
+ logoPath(logoPath) {
105
+ this.options.logoPath = logoPath;
106
+ return this;
107
+ }
108
+
109
+ /**
110
+ * Set the logo size
111
+ * @param {number} logoSize - Logo size as percentage of QR code size
112
+ * @returns {QrCodeBuilder} Builder instance
113
+ */
114
+ logoSize(logoSize) {
115
+ this.options.logoSize = logoSize;
116
+ return this;
117
+ }
118
+
119
+ /**
120
+ * Set the label text
121
+ * @param {string} label - Label text
122
+ * @returns {QrCodeBuilder} Builder instance
123
+ */
124
+ label(label) {
125
+ this.options.label = label;
126
+ return this;
127
+ }
128
+
129
+ /**
130
+ * Set the label font
131
+ * @param {string} fontPath - Path to font file
132
+ * @param {number} fontSize - Font size
133
+ * @returns {QrCodeBuilder} Builder instance
134
+ */
135
+ labelFont(fontPath, fontSize = 16) {
136
+ this.options.labelFont = fontPath;
137
+ this.options.labelFontSize = fontSize;
138
+ return this;
139
+ }
140
+
141
+ /**
142
+ * Set the watermark
143
+ * @param {string} watermark - Watermark text or image path
144
+ * @param {string} position - Watermark position
145
+ * @returns {QrCodeBuilder} Builder instance
146
+ */
147
+ watermark(watermark, position = 'center') {
148
+ this.options.watermark = watermark;
149
+ this.options.watermarkPosition = position;
150
+ return this;
151
+ }
152
+
153
+ /**
154
+ * Set the output format
155
+ * @param {string} format - Output format (png, svg, jpg)
156
+ * @returns {QrCodeBuilder} Builder instance
157
+ */
158
+ format(format) {
159
+ this.options.format = format;
160
+ return this;
161
+ }
162
+
163
+ /**
164
+ * Build the QR code
165
+ * @returns {Object} QR code result
166
+ */
167
+ build() {
168
+ return new QrCodeResult(this.options);
169
+ }
170
+
171
+ /**
172
+ * Generate QR code and return as buffer
173
+ * @returns {Promise<Buffer>} QR code buffer
174
+ */
175
+ async generate() {
176
+ const result = this.build();
177
+ return await result.generate();
178
+ }
179
+
180
+ /**
181
+ * Generate QR code and save to file
182
+ * @param {string} filePath - Output file path
183
+ * @returns {Promise<void>}
184
+ */
185
+ async saveToFile(filePath) {
186
+ const result = this.build();
187
+ return await result.saveToFile(filePath);
188
+ }
189
+
190
+ /**
191
+ * Generate QR code and return as data URI
192
+ * @returns {Promise<string>} Data URI
193
+ */
194
+ async getDataUri() {
195
+ const result = this.build();
196
+ return await result.getDataUri();
197
+ }
198
+ }
199
+
200
+ /**
201
+ * QR Code Result - Handles QR code generation and output
202
+ */
203
+ class QrCodeResult {
204
+ constructor(options) {
205
+ this.options = options;
206
+ }
207
+
208
+ /**
209
+ * Generate the QR code
210
+ * @returns {Promise<Buffer>} QR code buffer
211
+ */
212
+ async generate() {
213
+ try {
214
+ // Create canvas
215
+ const canvas = createCanvas(this.options.size, this.options.size);
216
+ const ctx = canvas.getContext('2d');
217
+
218
+ // Set background
219
+ ctx.fillStyle = this.rgbToHex(this.options.backgroundColor);
220
+ ctx.fillRect(0, 0, this.options.size, this.options.size);
221
+
222
+ // Generate QR code
223
+ const qrCodeDataURL = await QRCode.toDataURL(this.options.data, {
224
+ width: this.options.size - this.options.margin * 2,
225
+ margin: 0,
226
+ color: {
227
+ dark: this.rgbToHex(this.options.foregroundColor),
228
+ light: this.rgbToHex(this.options.backgroundColor),
229
+ },
230
+ errorCorrectionLevel: this.options.errorCorrectionLevel,
231
+ });
232
+
233
+ // Load QR code image
234
+ const qrCodeImage = await loadImage(qrCodeDataURL);
235
+ ctx.drawImage(qrCodeImage, this.options.margin, this.options.margin);
236
+
237
+ // Add logo if specified
238
+ if (this.options.logoPath) {
239
+ await this.addLogo(ctx);
240
+ }
241
+
242
+ // Add watermark if specified
243
+ if (this.options.watermark) {
244
+ await this.addWatermark(ctx);
245
+ }
246
+
247
+ // Add label if specified
248
+ if (this.options.label) {
249
+ this.addLabel(ctx);
250
+ }
251
+
252
+ // Convert to buffer
253
+ return canvas.toBuffer(`image/${this.options.format}`);
254
+ } catch (error) {
255
+ throw new Error(`QR code generation failed: ${error.message}`);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Add logo to QR code
261
+ * @param {CanvasRenderingContext2D} ctx - Canvas context
262
+ */
263
+ async addLogo(ctx) {
264
+ try {
265
+ const logoImage = await loadImage(this.options.logoPath);
266
+ const logoSize = (this.options.size * this.options.logoSize) / 100;
267
+ const logoX = (this.options.size - logoSize) / 2;
268
+ const logoY = (this.options.size - logoSize) / 2;
269
+
270
+ // Draw white background for logo
271
+ ctx.fillStyle = this.rgbToHex(this.options.backgroundColor);
272
+ ctx.fillRect(logoX - 5, logoY - 5, logoSize + 10, logoSize + 10);
273
+
274
+ // Draw logo
275
+ ctx.drawImage(logoImage, logoX, logoY, logoSize, logoSize);
276
+ } catch (error) {
277
+ console.warn(`Failed to add logo: ${error.message}`);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Add watermark to QR code
283
+ * @param {CanvasRenderingContext2D} ctx - Canvas context
284
+ */
285
+ async addWatermark(ctx) {
286
+ try {
287
+ // Check if watermark is an image path
288
+ if (
289
+ this.options.watermark.includes('.') &&
290
+ this.options.watermark.includes('/')
291
+ ) {
292
+ const watermarkImage = await loadImage(this.options.watermark);
293
+ const watermarkSize = this.options.size / 4;
294
+ const position = this.getWatermarkPosition(watermarkSize);
295
+
296
+ ctx.drawImage(
297
+ watermarkImage,
298
+ position.x,
299
+ position.y,
300
+ watermarkSize,
301
+ watermarkSize
302
+ );
303
+ } else {
304
+ // Text watermark
305
+ ctx.font = `${this.options.labelFontSize}px Arial`;
306
+ ctx.fillStyle = this.rgbToHex(this.options.foregroundColor);
307
+ ctx.textAlign = 'center';
308
+
309
+ const position = this.getWatermarkPosition(0);
310
+ ctx.fillText(this.options.watermark, position.x, position.y);
311
+ }
312
+ } catch (error) {
313
+ console.warn(`Failed to add watermark: ${error.message}`);
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Add label to QR code
319
+ * @param {CanvasRenderingContext2D} ctx - Canvas context
320
+ */
321
+ addLabel(ctx) {
322
+ ctx.font = `${this.options.labelFontSize}px Arial`;
323
+ ctx.fillStyle = this.rgbToHex(this.options.foregroundColor);
324
+ ctx.textAlign = 'center';
325
+
326
+ const labelY = this.options.size - 10;
327
+ ctx.fillText(this.options.label, this.options.size / 2, labelY);
328
+ }
329
+
330
+ /**
331
+ * Get watermark position
332
+ * @param {number} size - Watermark size
333
+ * @returns {Object} Position coordinates
334
+ */
335
+ getWatermarkPosition(size) {
336
+ const positions = {
337
+ 'top-left': { x: 10, y: 10 },
338
+ 'top-right': { x: this.options.size - size - 10, y: 10 },
339
+ 'bottom-left': { x: 10, y: this.options.size - size - 10 },
340
+ 'bottom-right': {
341
+ x: this.options.size - size - 10,
342
+ y: this.options.size - size - 10,
343
+ },
344
+ center: {
345
+ x: (this.options.size - size) / 2,
346
+ y: (this.options.size - size) / 2,
347
+ },
348
+ 'top-center': { x: (this.options.size - size) / 2, y: 10 },
349
+ 'bottom-center': {
350
+ x: (this.options.size - size) / 2,
351
+ y: this.options.size - size - 10,
352
+ },
353
+ 'left-center': { x: 10, y: (this.options.size - size) / 2 },
354
+ 'right-center': {
355
+ x: this.options.size - size - 10,
356
+ y: (this.options.size - size) / 2,
357
+ },
358
+ };
359
+
360
+ return positions[this.options.watermarkPosition] || positions.center;
361
+ }
362
+
363
+ /**
364
+ * Convert RGB array to hex color
365
+ * @param {Array} rgb - RGB color array
366
+ * @returns {string} Hex color
367
+ */
368
+ rgbToHex(rgb) {
369
+ return `#${rgb.map((c) => c.toString(16).padStart(2, '0')).join('')}`;
370
+ }
371
+
372
+ /**
373
+ * Save QR code to file
374
+ * @param {string} filePath - Output file path
375
+ * @returns {Promise<void>}
376
+ */
377
+ async saveToFile(filePath) {
378
+ const buffer = await this.generate();
379
+ await fs.writeFile(filePath, buffer);
380
+ }
381
+
382
+ /**
383
+ * Get QR code as data URI
384
+ * @returns {Promise<string>} Data URI
385
+ */
386
+ async getDataUri() {
387
+ const buffer = await this.generate();
388
+ const base64 = buffer.toString('base64');
389
+ return `data:image/${this.options.format};base64,${base64}`;
390
+ }
391
+
392
+ /**
393
+ * Get QR code as string
394
+ * @returns {Promise<string>} QR code string
395
+ */
396
+ async getString() {
397
+ return await this.generate();
398
+ }
399
+ }
400
+
401
+ module.exports = QrCodeBuilder;