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/.eslintrc.js +29 -0
- package/README.md +549 -0
- package/bin/generate.js +274 -0
- package/eslint.config.js +68 -0
- package/examples/basic-usage.js +58 -0
- package/examples/batch-example.json +56 -0
- package/examples/express-server.js +159 -0
- package/index.js +134 -0
- package/jest.config.js +13 -0
- package/package.json +66 -0
- package/src/builders/QrCodeBuilder.js +401 -0
- package/src/renderers/HTMLRenderer.js +212 -0
- package/src/renderers/PDFRenderer.js +184 -0
- package/src/renderers/PNGRenderer.js +123 -0
- package/src/renderers/RenderFormats.js +87 -0
- package/src/renderers/SVGRenderer.js +221 -0
- package/src/services/BarcodeService.js +175 -0
- package/src/types/BarcodeTypes.js +195 -0
- package/src/validators/Validator.js +352 -0
- package/tests/BarcodeGenerator.test.js +187 -0
- package/tests/BarcodeService.test.js +76 -0
- package/tests/QrCodeBuilder.test.js +130 -0
- package/tests/setup.js +59 -0
package/bin/generate.js
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI for Isahaq Barcode Generator
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Command } = require('commander');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const ora = require('ora');
|
|
10
|
+
const fs = require('fs').promises;
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const BarcodeGenerator = require('../index');
|
|
13
|
+
|
|
14
|
+
const program = new Command();
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.name('barcode-generate')
|
|
18
|
+
.description('Generate barcodes and QR codes from command line')
|
|
19
|
+
.version('1.0.0');
|
|
20
|
+
|
|
21
|
+
// Barcode generation command
|
|
22
|
+
program
|
|
23
|
+
.command('barcode')
|
|
24
|
+
.description('Generate a barcode')
|
|
25
|
+
.requiredOption('-d, --data <data>', 'Data to encode')
|
|
26
|
+
.option('-t, --type <type>', 'Barcode type', 'code128')
|
|
27
|
+
.option('-f, --format <format>', 'Output format (png, svg, html, pdf)', 'png')
|
|
28
|
+
.option('-o, --output <file>', 'Output file path')
|
|
29
|
+
.option('-w, --width <width>', 'Barcode width', '2')
|
|
30
|
+
.option('-h, --height <height>', 'Barcode height', '100')
|
|
31
|
+
.option('--no-text', 'Hide text below barcode')
|
|
32
|
+
.option('--foreground <color>', 'Foreground color (hex)', '#000000')
|
|
33
|
+
.option('--background <color>', 'Background color (hex)', '#ffffff')
|
|
34
|
+
.action(async (options) => {
|
|
35
|
+
const spinner = ora('Generating barcode...').start();
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const renderOptions = {
|
|
39
|
+
width: parseInt(options.width),
|
|
40
|
+
height: parseInt(options.height),
|
|
41
|
+
displayValue: options.text,
|
|
42
|
+
lineColor: options.foreground,
|
|
43
|
+
background: options.background,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
let result;
|
|
47
|
+
switch (options.format) {
|
|
48
|
+
case 'png':
|
|
49
|
+
result = BarcodeGenerator.png(
|
|
50
|
+
options.data,
|
|
51
|
+
options.type,
|
|
52
|
+
renderOptions
|
|
53
|
+
);
|
|
54
|
+
break;
|
|
55
|
+
case 'svg':
|
|
56
|
+
result = BarcodeGenerator.svg(
|
|
57
|
+
options.data,
|
|
58
|
+
options.type,
|
|
59
|
+
renderOptions
|
|
60
|
+
);
|
|
61
|
+
break;
|
|
62
|
+
case 'html':
|
|
63
|
+
result = BarcodeGenerator.html(
|
|
64
|
+
options.data,
|
|
65
|
+
options.type,
|
|
66
|
+
renderOptions
|
|
67
|
+
);
|
|
68
|
+
break;
|
|
69
|
+
case 'pdf':
|
|
70
|
+
result = BarcodeGenerator.pdf(
|
|
71
|
+
options.data,
|
|
72
|
+
options.type,
|
|
73
|
+
renderOptions
|
|
74
|
+
);
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Unsupported format: ${options.format}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (options.output) {
|
|
81
|
+
await fs.writeFile(options.output, result);
|
|
82
|
+
spinner.succeed(`Barcode saved to ${options.output}`);
|
|
83
|
+
} else {
|
|
84
|
+
// Output to stdout (for base64 encoding)
|
|
85
|
+
if (Buffer.isBuffer(result)) {
|
|
86
|
+
console.log(result.toString('base64'));
|
|
87
|
+
} else {
|
|
88
|
+
console.log(result);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
spinner.fail(`Error: ${error.message}`);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// QR code generation command
|
|
98
|
+
program
|
|
99
|
+
.command('qr')
|
|
100
|
+
.description('Generate a QR code')
|
|
101
|
+
.requiredOption('-d, --data <data>', 'Data to encode')
|
|
102
|
+
.option('-s, --size <size>', 'QR code size', '300')
|
|
103
|
+
.option('-f, --format <format>', 'Output format (png, svg, jpg)', 'png')
|
|
104
|
+
.option('-o, --output <file>', 'Output file path')
|
|
105
|
+
.option('-m, --margin <margin>', 'Margin size', '10')
|
|
106
|
+
.option(
|
|
107
|
+
'-e, --error-correction <level>',
|
|
108
|
+
'Error correction level (L, M, Q, H)',
|
|
109
|
+
'M'
|
|
110
|
+
)
|
|
111
|
+
.option('--foreground <color>', 'Foreground color (hex)', '#000000')
|
|
112
|
+
.option('--background <color>', 'Background color (hex)', '#ffffff')
|
|
113
|
+
.option('--logo <path>', 'Logo image path')
|
|
114
|
+
.option('--logo-size <size>', 'Logo size percentage', '60')
|
|
115
|
+
.option('--label <text>', 'Label text')
|
|
116
|
+
.option('--watermark <text>', 'Watermark text')
|
|
117
|
+
.option('--watermark-position <position>', 'Watermark position', 'center')
|
|
118
|
+
.action(async (options) => {
|
|
119
|
+
const spinner = ora('Generating QR code...').start();
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const qrOptions = {
|
|
123
|
+
data: options.data,
|
|
124
|
+
size: parseInt(options.size),
|
|
125
|
+
margin: parseInt(options.margin),
|
|
126
|
+
errorCorrectionLevel: options.errorCorrection,
|
|
127
|
+
foregroundColor: hexToRgb(options.foreground),
|
|
128
|
+
backgroundColor: hexToRgb(options.background),
|
|
129
|
+
format: options.format,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (options.logo) {
|
|
133
|
+
qrOptions.logoPath = options.logo;
|
|
134
|
+
qrOptions.logoSize = parseInt(options.logoSize);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (options.label) {
|
|
138
|
+
qrOptions.label = options.label;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (options.watermark) {
|
|
142
|
+
qrOptions.watermark = options.watermark;
|
|
143
|
+
qrOptions.watermarkPosition = options.watermarkPosition;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const qrCode = BarcodeGenerator.modernQr(qrOptions);
|
|
147
|
+
const result = await qrCode.generate();
|
|
148
|
+
|
|
149
|
+
if (options.output) {
|
|
150
|
+
await fs.writeFile(options.output, result);
|
|
151
|
+
spinner.succeed(`QR code saved to ${options.output}`);
|
|
152
|
+
} else {
|
|
153
|
+
// Output to stdout (for base64 encoding)
|
|
154
|
+
console.log(result.toString('base64'));
|
|
155
|
+
}
|
|
156
|
+
} catch (error) {
|
|
157
|
+
spinner.fail(`Error: ${error.message}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Batch generation command
|
|
163
|
+
program
|
|
164
|
+
.command('batch')
|
|
165
|
+
.description('Generate multiple barcodes from a JSON file')
|
|
166
|
+
.requiredOption('-i, --input <file>', 'Input JSON file')
|
|
167
|
+
.option('-o, --output-dir <dir>', 'Output directory', './output')
|
|
168
|
+
.action(async (options) => {
|
|
169
|
+
const spinner = ora('Processing batch generation...').start();
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const inputData = JSON.parse(await fs.readFile(options.input, 'utf8'));
|
|
173
|
+
|
|
174
|
+
if (!Array.isArray(inputData)) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
'Input file must contain an array of barcode configurations'
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Create output directory if it doesn't exist
|
|
181
|
+
await fs.mkdir(options.outputDir, { recursive: true });
|
|
182
|
+
|
|
183
|
+
const results = BarcodeGenerator.batch(inputData);
|
|
184
|
+
|
|
185
|
+
let successCount = 0;
|
|
186
|
+
let errorCount = 0;
|
|
187
|
+
|
|
188
|
+
for (const result of results) {
|
|
189
|
+
if (result.success) {
|
|
190
|
+
const filename = `barcode_${result.index}.${result.format}`;
|
|
191
|
+
const filepath = path.join(options.outputDir, filename);
|
|
192
|
+
await fs.writeFile(filepath, result.result);
|
|
193
|
+
successCount++;
|
|
194
|
+
} else {
|
|
195
|
+
errorCount++;
|
|
196
|
+
console.error(
|
|
197
|
+
chalk.red(`Error in item ${result.index}: ${result.error}`)
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
spinner.succeed(
|
|
203
|
+
`Batch generation completed: ${successCount} successful, ${errorCount} errors`
|
|
204
|
+
);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
spinner.fail(`Error: ${error.message}`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// List supported types command
|
|
212
|
+
program
|
|
213
|
+
.command('types')
|
|
214
|
+
.description('List supported barcode types')
|
|
215
|
+
.action(() => {
|
|
216
|
+
const types = BarcodeGenerator.getBarcodeTypes();
|
|
217
|
+
console.log(chalk.blue('Supported barcode types:'));
|
|
218
|
+
types.forEach((type) => {
|
|
219
|
+
console.log(` - ${type}`);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// List supported formats command
|
|
224
|
+
program
|
|
225
|
+
.command('formats')
|
|
226
|
+
.description('List supported output formats')
|
|
227
|
+
.action(() => {
|
|
228
|
+
const formats = BarcodeGenerator.getRenderFormats();
|
|
229
|
+
console.log(chalk.blue('Supported output formats:'));
|
|
230
|
+
formats.forEach((format) => {
|
|
231
|
+
console.log(` - ${format}`);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Validate data command
|
|
236
|
+
program
|
|
237
|
+
.command('validate')
|
|
238
|
+
.description('Validate data for a specific barcode type')
|
|
239
|
+
.requiredOption('-d, --data <data>', 'Data to validate')
|
|
240
|
+
.requiredOption('-t, --type <type>', 'Barcode type')
|
|
241
|
+
.action((options) => {
|
|
242
|
+
try {
|
|
243
|
+
const validation = BarcodeGenerator.validate(options.data, options.type);
|
|
244
|
+
|
|
245
|
+
if (validation.valid) {
|
|
246
|
+
console.log(chalk.green('✓ Data is valid'));
|
|
247
|
+
console.log(` Type: ${validation.type}`);
|
|
248
|
+
console.log(` Length: ${validation.length}`);
|
|
249
|
+
console.log(` Charset: ${validation.charset}`);
|
|
250
|
+
} else {
|
|
251
|
+
console.log(chalk.red('✗ Data is invalid'));
|
|
252
|
+
console.log(` Error: ${validation.error}`);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error(chalk.red(`Validation error: ${error.message}`));
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Helper function to convert hex to RGB
|
|
262
|
+
function hexToRgb(hex) {
|
|
263
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
264
|
+
return result
|
|
265
|
+
? [
|
|
266
|
+
parseInt(result[1], 16),
|
|
267
|
+
parseInt(result[2], 16),
|
|
268
|
+
parseInt(result[3], 16),
|
|
269
|
+
]
|
|
270
|
+
: [0, 0, 0];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Parse command line arguments
|
|
274
|
+
program.parse();
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module.exports = [
|
|
2
|
+
{
|
|
3
|
+
files: ['**/*.js'],
|
|
4
|
+
languageOptions: {
|
|
5
|
+
ecmaVersion: 2022,
|
|
6
|
+
sourceType: 'module',
|
|
7
|
+
globals: {
|
|
8
|
+
console: 'readonly',
|
|
9
|
+
process: 'readonly',
|
|
10
|
+
Buffer: 'readonly',
|
|
11
|
+
__dirname: 'readonly',
|
|
12
|
+
__filename: 'readonly',
|
|
13
|
+
global: 'readonly',
|
|
14
|
+
module: 'readonly',
|
|
15
|
+
require: 'readonly',
|
|
16
|
+
exports: 'readonly',
|
|
17
|
+
document: 'readonly'
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
rules: {
|
|
21
|
+
'indent': ['error', 2],
|
|
22
|
+
'quotes': ['error', 'single'],
|
|
23
|
+
'semi': ['error', 'always'],
|
|
24
|
+
'no-unused-vars': 'warn',
|
|
25
|
+
'no-console': 'off',
|
|
26
|
+
'no-undef': 'error',
|
|
27
|
+
'no-trailing-spaces': 'error',
|
|
28
|
+
'eol-last': 'error'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
files: ['tests/**/*.js', '**/*.test.js'],
|
|
33
|
+
languageOptions: {
|
|
34
|
+
ecmaVersion: 2022,
|
|
35
|
+
sourceType: 'module',
|
|
36
|
+
globals: {
|
|
37
|
+
console: 'readonly',
|
|
38
|
+
process: 'readonly',
|
|
39
|
+
Buffer: 'readonly',
|
|
40
|
+
__dirname: 'readonly',
|
|
41
|
+
__filename: 'readonly',
|
|
42
|
+
global: 'readonly',
|
|
43
|
+
module: 'readonly',
|
|
44
|
+
require: 'readonly',
|
|
45
|
+
exports: 'readonly',
|
|
46
|
+
describe: 'readonly',
|
|
47
|
+
test: 'readonly',
|
|
48
|
+
it: 'readonly',
|
|
49
|
+
expect: 'readonly',
|
|
50
|
+
beforeEach: 'readonly',
|
|
51
|
+
afterEach: 'readonly',
|
|
52
|
+
beforeAll: 'readonly',
|
|
53
|
+
afterAll: 'readonly',
|
|
54
|
+
jest: 'readonly'
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
rules: {
|
|
58
|
+
'indent': ['error', 2],
|
|
59
|
+
'quotes': ['error', 'single'],
|
|
60
|
+
'semi': ['error', 'always'],
|
|
61
|
+
'no-unused-vars': 'warn',
|
|
62
|
+
'no-console': 'off',
|
|
63
|
+
'no-undef': 'error',
|
|
64
|
+
'no-trailing-spaces': 'error',
|
|
65
|
+
'eol-last': 'error'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic usage examples for Isahaq Barcode Generator
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const BarcodeGenerator = require('../index');
|
|
6
|
+
|
|
7
|
+
async function basicExamples() {
|
|
8
|
+
console.log('🚀 Basic Barcode Generation Examples\n');
|
|
9
|
+
|
|
10
|
+
// 1. Generate PNG barcode
|
|
11
|
+
console.log('1. Generating PNG barcode...');
|
|
12
|
+
const pngBuffer = BarcodeGenerator.png('1234567890', 'code128');
|
|
13
|
+
console.log(` PNG buffer size: ${pngBuffer.length} bytes`);
|
|
14
|
+
|
|
15
|
+
// 2. Generate SVG barcode
|
|
16
|
+
console.log('2. Generating SVG barcode...');
|
|
17
|
+
const svgString = BarcodeGenerator.svg('1234567890', 'ean13');
|
|
18
|
+
console.log(` SVG length: ${svgString.length} characters`);
|
|
19
|
+
|
|
20
|
+
// 3. Generate HTML barcode
|
|
21
|
+
console.log('3. Generating HTML barcode...');
|
|
22
|
+
const htmlString = BarcodeGenerator.html('1234567890', 'code39');
|
|
23
|
+
console.log(` HTML length: ${htmlString.length} characters`);
|
|
24
|
+
|
|
25
|
+
// 4. Generate PDF barcode
|
|
26
|
+
console.log('4. Generating PDF barcode...');
|
|
27
|
+
const pdfBuffer = await BarcodeGenerator.pdf('1234567890', 'code128');
|
|
28
|
+
console.log(` PDF buffer size: ${pdfBuffer.length} bytes`);
|
|
29
|
+
|
|
30
|
+
// 5. Generate QR code
|
|
31
|
+
console.log('5. Generating QR code...');
|
|
32
|
+
const qrCode = BarcodeGenerator.modernQr({
|
|
33
|
+
data: 'https://example.com',
|
|
34
|
+
size: 300,
|
|
35
|
+
margin: 10,
|
|
36
|
+
});
|
|
37
|
+
const qrBuffer = await qrCode.generate();
|
|
38
|
+
console.log(` QR code buffer size: ${qrBuffer.length} bytes`);
|
|
39
|
+
|
|
40
|
+
// 6. Generate QR code with logo
|
|
41
|
+
console.log('6. Generating QR code with logo...');
|
|
42
|
+
const qrWithLogo = BarcodeGenerator.modernQr({
|
|
43
|
+
data: 'https://example.com',
|
|
44
|
+
size: 300,
|
|
45
|
+
logoPath: 'path/to/logo.png',
|
|
46
|
+
logoSize: 60,
|
|
47
|
+
label: 'Scan me!',
|
|
48
|
+
});
|
|
49
|
+
const qrWithLogoBuffer = await qrWithLogo.generate();
|
|
50
|
+
console.log(
|
|
51
|
+
` QR code with logo buffer size: ${qrWithLogoBuffer.length} bytes`
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
console.log('\n✅ All examples completed successfully!');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Run examples
|
|
58
|
+
basicExamples().catch(console.error);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"data": "1234567890",
|
|
4
|
+
"type": "code128",
|
|
5
|
+
"format": "png",
|
|
6
|
+
"options": {
|
|
7
|
+
"width": 3,
|
|
8
|
+
"height": 150,
|
|
9
|
+
"displayValue": true
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"data": "9876543210",
|
|
14
|
+
"type": "code39",
|
|
15
|
+
"format": "svg",
|
|
16
|
+
"options": {
|
|
17
|
+
"width": 2,
|
|
18
|
+
"height": 100,
|
|
19
|
+
"displayValue": false
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"data": "1234567890123",
|
|
24
|
+
"type": "ean13",
|
|
25
|
+
"format": "png",
|
|
26
|
+
"options": {
|
|
27
|
+
"width": 2,
|
|
28
|
+
"height": 120,
|
|
29
|
+
"displayValue": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"data": "https://example.com",
|
|
34
|
+
"type": "qrcode",
|
|
35
|
+
"format": "png",
|
|
36
|
+
"options": {
|
|
37
|
+
"size": 300,
|
|
38
|
+
"margin": 10,
|
|
39
|
+
"logoPath": "path/to/logo.png",
|
|
40
|
+
"logoSize": 60,
|
|
41
|
+
"label": "Scan me!"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"data": "https://github.com",
|
|
46
|
+
"type": "qrcode",
|
|
47
|
+
"format": "png",
|
|
48
|
+
"options": {
|
|
49
|
+
"size": 400,
|
|
50
|
+
"margin": 15,
|
|
51
|
+
"watermark": "GitHub",
|
|
52
|
+
"watermarkPosition": "center",
|
|
53
|
+
"errorCorrectionLevel": "H"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
]
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express.js server example for Isahaq Barcode Generator
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const express = require('express');
|
|
6
|
+
const BarcodeGenerator = require('../index');
|
|
7
|
+
|
|
8
|
+
const app = express();
|
|
9
|
+
const PORT = process.env.PORT || 3000;
|
|
10
|
+
|
|
11
|
+
// Middleware
|
|
12
|
+
app.use(express.json());
|
|
13
|
+
app.use(express.static('public'));
|
|
14
|
+
|
|
15
|
+
// Barcode generation endpoint
|
|
16
|
+
app.get('/barcode/:data', async (req, res) => {
|
|
17
|
+
const { data } = req.params;
|
|
18
|
+
const { type = 'code128', format = 'png', width, height } = req.query;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const options = {};
|
|
22
|
+
if (width) options.width = parseInt(width);
|
|
23
|
+
if (height) options.height = parseInt(height);
|
|
24
|
+
|
|
25
|
+
let result;
|
|
26
|
+
let contentType;
|
|
27
|
+
|
|
28
|
+
switch (format) {
|
|
29
|
+
case 'png':
|
|
30
|
+
result = BarcodeGenerator.png(data, type, options);
|
|
31
|
+
contentType = 'image/png';
|
|
32
|
+
break;
|
|
33
|
+
case 'svg':
|
|
34
|
+
result = BarcodeGenerator.svg(data, type, options);
|
|
35
|
+
contentType = 'image/svg+xml';
|
|
36
|
+
break;
|
|
37
|
+
case 'html':
|
|
38
|
+
result = BarcodeGenerator.html(data, type, options);
|
|
39
|
+
contentType = 'text/html';
|
|
40
|
+
break;
|
|
41
|
+
case 'pdf':
|
|
42
|
+
result = await BarcodeGenerator.pdf(data, type, options);
|
|
43
|
+
contentType = 'application/pdf';
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
res.set('Content-Type', contentType);
|
|
50
|
+
res.send(result);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
res.status(400).json({ error: error.message });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// QR code generation endpoint
|
|
57
|
+
app.get('/qr/:data', async (req, res) => {
|
|
58
|
+
const { data } = req.params;
|
|
59
|
+
const {
|
|
60
|
+
size = 300,
|
|
61
|
+
logo,
|
|
62
|
+
label,
|
|
63
|
+
watermark,
|
|
64
|
+
watermarkPosition = 'center',
|
|
65
|
+
errorCorrection = 'M'
|
|
66
|
+
} = req.query;
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const qrOptions = {
|
|
70
|
+
data: decodeURIComponent(data),
|
|
71
|
+
size: parseInt(size),
|
|
72
|
+
errorCorrectionLevel: errorCorrection
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (logo) qrOptions.logoPath = logo;
|
|
76
|
+
if (label) qrOptions.label = label;
|
|
77
|
+
if (watermark) {
|
|
78
|
+
qrOptions.watermark = watermark;
|
|
79
|
+
qrOptions.watermarkPosition = watermarkPosition;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const qrCode = BarcodeGenerator.modernQr(qrOptions);
|
|
83
|
+
const result = await qrCode.generate();
|
|
84
|
+
|
|
85
|
+
res.set('Content-Type', 'image/png');
|
|
86
|
+
res.send(result);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
res.status(400).json({ error: error.message });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Batch generation endpoint
|
|
93
|
+
app.post('/batch', async (req, res) => {
|
|
94
|
+
try {
|
|
95
|
+
const { items } = req.body;
|
|
96
|
+
|
|
97
|
+
if (!Array.isArray(items)) {
|
|
98
|
+
throw new Error('Items must be an array');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const results = BarcodeGenerator.batch(items);
|
|
102
|
+
res.json({ results });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
res.status(400).json({ error: error.message });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Validation endpoint
|
|
109
|
+
app.get('/validate/:data/:type', (req, res) => {
|
|
110
|
+
const { data, type } = req.params;
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const validation = BarcodeGenerator.validate(data, type);
|
|
114
|
+
res.json(validation);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
res.status(400).json({ error: error.message });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Get supported types
|
|
121
|
+
app.get('/types', (req, res) => {
|
|
122
|
+
const types = BarcodeGenerator.getBarcodeTypes();
|
|
123
|
+
res.json({ types });
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Get supported formats
|
|
127
|
+
app.get('/formats', (req, res) => {
|
|
128
|
+
const formats = BarcodeGenerator.getRenderFormats();
|
|
129
|
+
res.json({ formats });
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Get watermark positions
|
|
133
|
+
app.get('/watermark-positions', (req, res) => {
|
|
134
|
+
const positions = BarcodeGenerator.getWatermarkPositions();
|
|
135
|
+
res.json({ positions });
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Health check
|
|
139
|
+
app.get('/health', (req, res) => {
|
|
140
|
+
res.json({ status: 'OK', timestamp: new Date().toISOString() });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Error handling middleware
|
|
144
|
+
app.use((error, req, res) => {
|
|
145
|
+
console.error('Error:', error);
|
|
146
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Start server
|
|
150
|
+
app.listen(PORT, () => {
|
|
151
|
+
console.log(`🚀 Server running on http://localhost:${PORT}`);
|
|
152
|
+
console.log(`📊 Health check: http://localhost:${PORT}/health`);
|
|
153
|
+
console.log(`🔗 Barcode endpoint: http://localhost:${PORT}/barcode/{data}?type=code128&format=png`);
|
|
154
|
+
console.log(`🔗 QR code endpoint: http://localhost:${PORT}/qr/{data}?size=300`);
|
|
155
|
+
console.log(`🔗 Types endpoint: http://localhost:${PORT}/types`);
|
|
156
|
+
console.log(`🔗 Formats endpoint: http://localhost:${PORT}/formats`);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
module.exports = app;
|