medusa-pos-plugin 0.0.34 → 0.0.36

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.
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HOST_BARCODE_TEMPLATE_PATH = exports.MAX_BARCODE_QTY_PER_VARIANT = void 0;
7
+ exports.clampQty = clampQty;
8
+ exports.parseBarcodePrintBody = parseBarcodePrintBody;
9
+ exports.buildPrintQueue = buildPrintQueue;
10
+ exports.escapeHtml = escapeHtml;
11
+ exports.contactDetailsFromConfig = contactDetailsFromConfig;
12
+ exports.buildContactHtml = buildContactHtml;
13
+ exports.resolvePrices = resolvePrices;
14
+ exports.buildPriceHtml = buildPriceHtml;
15
+ exports.buildOptionsHtml = buildOptionsHtml;
16
+ exports.loadBarcodeTemplate = loadBarcodeTemplate;
17
+ exports.renderBarcodeLabelsHtml = renderBarcodeLabelsHtml;
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const path_1 = __importDefault(require("path"));
20
+ const barcode_template_default_1 = require("./barcode-template-default");
21
+ exports.MAX_BARCODE_QTY_PER_VARIANT = 500;
22
+ /** Host override path, relative to the Medusa project root. */
23
+ exports.HOST_BARCODE_TEMPLATE_PATH = path_1.default.join("templates", "barcode-template.html");
24
+ function clampQty(value) {
25
+ const n = Math.floor(Number(value));
26
+ if (!Number.isFinite(n) || n < 1)
27
+ return 1;
28
+ return Math.min(n, exports.MAX_BARCODE_QTY_PER_VARIANT);
29
+ }
30
+ /** Normalises an untrusted request body into the supported print body shape. */
31
+ function parseBarcodePrintBody(raw) {
32
+ if (!raw || typeof raw !== "object")
33
+ return {};
34
+ const body = raw;
35
+ const parsed = {};
36
+ if (Array.isArray(body.items)) {
37
+ parsed.items = body.items
38
+ .filter((item) => !!item && typeof item === "object")
39
+ .filter((item) => typeof item.variant_id === "string" && !!item.variant_id)
40
+ .map((item) => ({
41
+ variant_id: String(item.variant_id),
42
+ quantity: item.quantity === undefined ? undefined : Number(item.quantity),
43
+ }));
44
+ }
45
+ if (Array.isArray(body.variant_ids)) {
46
+ parsed.variant_ids = body.variant_ids.filter((id) => typeof id === "string" && !!id);
47
+ }
48
+ if (typeof body.region_id === "string")
49
+ parsed.region_id = body.region_id;
50
+ if (body.print_width !== undefined)
51
+ parsed.print_width = Number(body.print_width);
52
+ if (body.print_height !== undefined) {
53
+ parsed.print_height = Number(body.print_height);
54
+ }
55
+ return parsed;
56
+ }
57
+ /** Expand items/ids into an ordered list of variant ids (with repeats for qty). */
58
+ function buildPrintQueue(body) {
59
+ if (Array.isArray(body.items) && body.items.length > 0) {
60
+ const queue = [];
61
+ for (const item of body.items) {
62
+ if (!item?.variant_id)
63
+ continue;
64
+ const qty = clampQty(item.quantity);
65
+ for (let i = 0; i < qty; i++)
66
+ queue.push(item.variant_id);
67
+ }
68
+ return queue;
69
+ }
70
+ return Array.isArray(body.variant_ids) ? body.variant_ids.filter(Boolean) : [];
71
+ }
72
+ function takeAmount(value) {
73
+ const n = Number(value);
74
+ return Number.isFinite(n) && n > 0 ? n : 0;
75
+ }
76
+ function escapeHtml(value) {
77
+ return value
78
+ .replace(/&/g, "&amp;")
79
+ .replace(/</g, "&lt;")
80
+ .replace(/>/g, "&gt;")
81
+ .replace(/"/g, "&quot;");
82
+ }
83
+ /** Reads phone/email/address from dynamic config values (keys containing contact-*). */
84
+ function contactDetailsFromConfig(values) {
85
+ const contactDetails = { phone: "", email: "", address: "" };
86
+ for (const [key, val] of Object.entries(values)) {
87
+ if (key.includes("contact-phone"))
88
+ contactDetails.phone = String(val || "");
89
+ if (key.includes("contact-email"))
90
+ contactDetails.email = String(val || "");
91
+ if (key.includes("contact-address"))
92
+ contactDetails.address = String(val || "");
93
+ }
94
+ return contactDetails;
95
+ }
96
+ function buildContactHtml(contact) {
97
+ const rows = [];
98
+ rows.push(`<div class="info-row info-row-inline"><span class="info-inline">Country Of Origin India</span></div>`);
99
+ if (contact.address) {
100
+ rows.push(`<div class="info-row info-row-address"><span class="info-label info-label-mixed">Manufactured &amp; Marketed by</span><span class="info-value">${escapeHtml(contact.address)}</span></div>`);
101
+ }
102
+ if (contact.email || contact.phone) {
103
+ const lines = [
104
+ `<span class="complaints-title">For Customer Complaints:</span>`,
105
+ ];
106
+ if (contact.email) {
107
+ lines.push(`<span class="complaints-line contact-email">${escapeHtml(contact.email)}</span>`);
108
+ }
109
+ if (contact.phone) {
110
+ lines.push(`<span class="complaints-line">${escapeHtml(contact.phone)}</span>`);
111
+ }
112
+ rows.push(`<div class="info-row complaints-block">${lines.join("")}</div>`);
113
+ }
114
+ return rows.join("");
115
+ }
116
+ function resolvePrices(variant) {
117
+ const calc = variant.calculated_price;
118
+ const original = takeAmount(calc?.original_amount);
119
+ const current = takeAmount(calc?.calculated_amount);
120
+ if (original > 0 && current > 0 && current < original) {
121
+ return { mrp: original, sale: current };
122
+ }
123
+ const prices = variant.price_set?.prices || [];
124
+ const inr = prices.filter((p) => (p.currency_code || "").toLowerCase() === "inr");
125
+ const pool = inr.length > 0 ? inr : prices;
126
+ const baseAmounts = pool
127
+ .filter((p) => !p.price_list_id)
128
+ .map((p) => takeAmount(p.amount))
129
+ .filter(Boolean);
130
+ const listAmounts = pool
131
+ .filter((p) => !!p.price_list_id)
132
+ .map((p) => takeAmount(p.amount))
133
+ .filter(Boolean);
134
+ let mrp = original || current || (baseAmounts.length ? Math.max(...baseAmounts) : 0);
135
+ let sale = listAmounts.length ? Math.min(...listAmounts) : 0;
136
+ if (!sale && baseAmounts.length >= 2) {
137
+ const minBase = Math.min(...baseAmounts);
138
+ const maxBase = Math.max(...baseAmounts);
139
+ if (minBase < maxBase) {
140
+ mrp = maxBase;
141
+ sale = minBase;
142
+ }
143
+ }
144
+ if (sale > 0 && mrp > 0 && sale < mrp) {
145
+ return { mrp, sale };
146
+ }
147
+ return { mrp: mrp || sale || 0, sale: 0 };
148
+ }
149
+ function buildPriceHtml(mrp, sale) {
150
+ if (sale > 0 && mrp > 0 && sale < mrp) {
151
+ return [
152
+ `<span class="price-label">Maximum Retail Price</span>`,
153
+ `<div class="price-row">`,
154
+ `<div class="mrp-crossed">₹&nbsp;${mrp}</div>`,
155
+ `<div class="sale-price">₹&nbsp;${sale}</div>`,
156
+ `</div>`,
157
+ ].join("");
158
+ }
159
+ if (mrp > 0) {
160
+ return [
161
+ `<span class="price-label">Maximum Retail Price</span>`,
162
+ `<div class="mrp-only">₹&nbsp;${mrp}</div>`,
163
+ ].join("");
164
+ }
165
+ return `<div class="mrp-only">₹&nbsp;0</div>`;
166
+ }
167
+ function buildOptionsHtml(variant) {
168
+ return (variant.options || [])
169
+ .map((o) => {
170
+ const optionTitle = o.option?.title || o.title || "Option";
171
+ const value = (o.value || "").toUpperCase();
172
+ return `<div class="option-line"><span class="option-label">${escapeHtml(optionTitle)}:</span><span class="option-value">${escapeHtml(value)}</span></div>`;
173
+ })
174
+ .join("");
175
+ }
176
+ /** Host file `templates/barcode-template.html` wins; otherwise the bundled default. */
177
+ function loadBarcodeTemplate(cwd = process.cwd()) {
178
+ const hostPath = path_1.default.join(cwd, exports.HOST_BARCODE_TEMPLATE_PATH);
179
+ try {
180
+ if (fs_1.default.existsSync(hostPath)) {
181
+ return fs_1.default.readFileSync(hostPath, "utf-8");
182
+ }
183
+ }
184
+ catch {
185
+ // Unreadable host override — fall back to the bundled template
186
+ }
187
+ return barcode_template_default_1.DEFAULT_BARCODE_TEMPLATE_HTML;
188
+ }
189
+ function buildPrintScript(barcodesList, printWidth, printHeight) {
190
+ return `
191
+ <script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
192
+ <script>
193
+ const barcodes = ${JSON.stringify(barcodesList)};
194
+ const BAR_MODULE_WIDTH = ${Math.max(1.5, printWidth)};
195
+ const BAR_HEIGHT = ${Math.max(40, printHeight)};
196
+
197
+ function drawBarcodes() {
198
+ if (typeof JsBarcode !== 'function') {
199
+ throw new Error('JsBarcode failed to load');
200
+ }
201
+
202
+ // Draw barcode horizontal (no CSS rotate) — natural CODE128 orientation.
203
+ // Keep module ratios intact (no stretch) so scanners can read.
204
+ barcodes.forEach((item) => {
205
+ const host = document.getElementById('barcode-' + item.svgId);
206
+ if (!host) return;
207
+ try {
208
+ // Always treat as string — avoids scientific notation like 1.6013E+12
209
+ const code = String(item.value == null ? '' : item.value);
210
+ const canvas = document.createElement('canvas');
211
+ JsBarcode(canvas, code, {
212
+ format: 'CODE128',
213
+ lineColor: '#000000',
214
+ background: '#ffffff',
215
+ width: Math.max(2, BAR_MODULE_WIDTH),
216
+ height: Math.max(48, BAR_HEIGHT),
217
+ displayValue: true,
218
+ text: code,
219
+ font: 'Arial',
220
+ fontOptions: 'bold',
221
+ fontSize: 12,
222
+ textAlign: 'center',
223
+ textPosition: 'bottom',
224
+ textMargin: 2,
225
+ margin: 3,
226
+ marginTop: 2,
227
+ marginBottom: 2,
228
+ });
229
+
230
+ const img = document.createElement('img');
231
+ img.className = 'barcode-img';
232
+ img.alt = code;
233
+ img.src = canvas.toDataURL('image/png');
234
+ img.style.width = '1.55in';
235
+ img.style.height = 'auto';
236
+ img.style.maxWidth = '1.55in';
237
+ img.style.maxHeight = '0.62in';
238
+ img.style.objectFit = 'contain';
239
+ img.style.imageRendering = 'pixelated';
240
+ img.style.display = 'block';
241
+ host.replaceWith(img);
242
+ } catch (e) {
243
+ console.error('Invalid barcode format:', item.value, e);
244
+ }
245
+ });
246
+ }
247
+
248
+ function waitFrames(n) {
249
+ return new Promise((resolve) => {
250
+ const step = () => {
251
+ if (n <= 0) return resolve();
252
+ n -= 1;
253
+ requestAnimationFrame(step);
254
+ };
255
+ step();
256
+ });
257
+ }
258
+
259
+ function waitForJsBarcode(timeoutMs) {
260
+ const start = Date.now();
261
+ return new Promise((resolve, reject) => {
262
+ const tick = () => {
263
+ if (typeof JsBarcode === 'function') return resolve();
264
+ if (Date.now() - start > timeoutMs) {
265
+ return reject(new Error('JsBarcode load timeout'));
266
+ }
267
+ setTimeout(tick, 50);
268
+ };
269
+ tick();
270
+ });
271
+ }
272
+
273
+ async function startPrint() {
274
+ try {
275
+ await waitForJsBarcode(8000);
276
+ drawBarcodes();
277
+ // Let images decode before opening the print dialog
278
+ await waitFrames(2);
279
+ await new Promise((r) => setTimeout(r, 300));
280
+ const imgs = Array.from(document.querySelectorAll('img.barcode-img'));
281
+ await Promise.all(
282
+ imgs.map((img) =>
283
+ img.decode ? img.decode().catch(() => {}) : Promise.resolve()
284
+ )
285
+ );
286
+ window.focus();
287
+ window.print();
288
+ } catch (e) {
289
+ console.error('Print prep failed:', e);
290
+ window.print();
291
+ }
292
+ }
293
+
294
+ if (document.readyState === 'complete') {
295
+ startPrint();
296
+ } else {
297
+ window.addEventListener('load', startPrint);
298
+ }
299
+ </script>
300
+ </body>`;
301
+ }
302
+ /**
303
+ * Fills the template with one tag per variant (repeats allowed for quantity)
304
+ * and appends the JsBarcode draw + auto-print script. SVG ids are unique per copy.
305
+ */
306
+ function renderBarcodeLabelsHtml(input) {
307
+ const templateMatch = input.template.match(/<template id="single-tag">([\s\S]*?)<\/template>/);
308
+ const singleTagHtml = templateMatch ? templateMatch[1] : "";
309
+ const barcodesList = [];
310
+ const tagsHtml = input.variants
311
+ .map((variant, index) => {
312
+ const barcodeValue = String(variant.barcode || variant.id || "");
313
+ const svgId = `bc${index}`;
314
+ barcodesList.push({ svgId, value: barcodeValue });
315
+ const { mrp, sale } = resolvePrices(variant);
316
+ const skuHtml = variant.sku
317
+ ? `<div class="sku-inline">SKU: ${escapeHtml(variant.sku)}</div>`
318
+ : "";
319
+ return singleTagHtml
320
+ .replace(/{{PRODUCT_NAME}}/g, escapeHtml(variant.product?.title || "Product"))
321
+ .replace(/{{OPTIONS_HTML}}/g, buildOptionsHtml(variant))
322
+ .replace(/{{SKU_HTML}}/g, skuHtml)
323
+ .replace(/{{PRICE_HTML}}/g, buildPriceHtml(mrp, sale))
324
+ .replace(/{{CONTACT_DETAILS}}/g, input.contactHtml)
325
+ .replace(/{{BARCODE_SVG_ID}}/g, svgId)
326
+ .replace(/{{BARCODE_ID}}/g, escapeHtml(barcodeValue));
327
+ })
328
+ .join("\n");
329
+ let html = input.template.replace("{{ALL_TAGS_HTML}}", tagsHtml);
330
+ html = html.replace("</head>", `
331
+ <title>Barcode Labels</title>
332
+ </head>`);
333
+ html = html.replace("</body>", buildPrintScript(barcodesList, input.printWidth, input.printHeight));
334
+ return { html, count: input.variants.length };
335
+ }
336
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFyY29kZS1sYWJlbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvYmFyY29kZS1sYWJlbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBdURBLDRCQUlDO0FBR0Qsc0RBNEJDO0FBR0QsMENBV0M7QUFPRCxnQ0FNQztBQUdELDREQVVDO0FBRUQsNENBK0JDO0FBRUQsc0NBMENDO0FBRUQsd0NBaUJDO0FBRUQsNENBVUM7QUFHRCxrREFVQztBQTRIRCwwREFxREM7QUE1YUQsNENBQW1CO0FBQ25CLGdEQUF1QjtBQUN2Qix5RUFBMEU7QUE2QzdELFFBQUEsMkJBQTJCLEdBQUcsR0FBRyxDQUFBO0FBRTlDLCtEQUErRDtBQUNsRCxRQUFBLDBCQUEwQixHQUFHLGNBQUksQ0FBQyxJQUFJLENBQ2pELFdBQVcsRUFDWCx1QkFBdUIsQ0FDeEIsQ0FBQTtBQUVELFNBQWdCLFFBQVEsQ0FBQyxLQUFjO0lBQ3JDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7SUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQTtJQUMxQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLG1DQUEyQixDQUFDLENBQUE7QUFDakQsQ0FBQztBQUVELGdGQUFnRjtBQUNoRixTQUFnQixxQkFBcUIsQ0FBQyxHQUFZO0lBQ2hELElBQUksQ0FBQyxHQUFHLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUTtRQUFFLE9BQU8sRUFBRSxDQUFBO0lBQzlDLE1BQU0sSUFBSSxHQUFHLEdBQThCLENBQUE7SUFDM0MsTUFBTSxNQUFNLEdBQXFCLEVBQUUsQ0FBQTtJQUVuQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxF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