@legenki/print2medusa 0.8.1 → 0.9.2

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,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLEARED_BY_OPERATOR = exports.CLEAR_SYNC_CONFIRMATION = void 0;
4
+ exports.planSyncClear = planSyncClear;
5
+ /**
6
+ * Exact phrase the caller must send to clear a stuck sync.
7
+ *
8
+ * Clearing is destructive, so it must not be reachable by an empty POST. A
9
+ * typed phrase makes the operator's intent explicit and unambiguous in the
10
+ * request itself — a boolean `force: true` is too easy to send by accident
11
+ * from a curl line or a mis-wired button.
12
+ */
13
+ exports.CLEAR_SYNC_CONFIRMATION = "clear-stuck-sync";
14
+ /**
15
+ * Audit marker written to `error_message` when a human clears a sync.
16
+ *
17
+ * `reapStaleSyncLogs` writes the bare string "stale_running" when the timeout
18
+ * reclaims a row on its own. These two must never be confused: one says the
19
+ * system recovered by itself after `syncStaleMinutes`, the other says a person
20
+ * decided the sync was dead and intervened. Anyone reading this log six months
21
+ * from now needs to be able to tell those apart.
22
+ */
23
+ exports.CLEARED_BY_OPERATOR = "cleared_by_operator";
24
+ function toDate(value) {
25
+ if (value == null) {
26
+ return null;
27
+ }
28
+ const date = value instanceof Date ? value : new Date(value);
29
+ return Number.isNaN(date.getTime()) ? null : date;
30
+ }
31
+ /**
32
+ * Decide whether a running sync may be cleared by hand, and what to record.
33
+ *
34
+ * This exists instead of simply exposing `reapStaleSyncLogs(0)`, which would
35
+ * clear ANY running sync unconditionally. That call has no notion of whether
36
+ * the sync is alive: a healthy run mid-catalog would be marked `failed` while
37
+ * its process keeps writing, which both corrupts the log and frees the claim
38
+ * so a second sync can start against the same catalog.
39
+ *
40
+ * Two guards, deliberately layered:
41
+ *
42
+ * 1. The caller must send the confirmation phrase. Checked FIRST, so an
43
+ * unconfirmed request against a live sync is told it is unconfirmed rather
44
+ * than being told it is alive — the latter would wrongly imply that
45
+ * confirming alone would have been enough.
46
+ * 2. The heartbeat must actually be stale. Confirmation proves intent, not
47
+ * that the operator is right. An operator staring at a widget cannot see
48
+ * the heartbeat; the server can, and refuses on their behalf.
49
+ *
50
+ * The stale window is clamped to a minimum of one minute so that passing 0 —
51
+ * the exact foot-gun this function replaces — cannot make a live sync
52
+ * clearable.
53
+ *
54
+ * A row with no heartbeat at all falls back to `started_at`. A crash between
55
+ * the claim insert and the first heartbeat leaves `heartbeat_at` null, and
56
+ * such a row must not be permanently unclearable; but a claim made seconds ago
57
+ * is far more likely to be a sync starting up than a dead one.
58
+ */
59
+ function planSyncClear(input) {
60
+ const { log, confirmation, staleMinutes } = input;
61
+ const now = input.now ?? new Date();
62
+ if (!log || log.status !== "running") {
63
+ return { allowed: false, reason: "nothing_running" };
64
+ }
65
+ if (confirmation !== exports.CLEAR_SYNC_CONFIRMATION) {
66
+ return { allowed: false, reason: "unconfirmed", sync_id: log.id };
67
+ }
68
+ // Never trust a zero or negative window: that is precisely the call this
69
+ // function exists to prevent.
70
+ const window = Math.max(1, Number.isFinite(staleMinutes) ? staleMinutes : 1);
71
+ const lastSign = toDate(log.heartbeat_at) ?? toDate(log.started_at);
72
+ const silentMs = lastSign ? now.getTime() - lastSign.getTime() : Infinity;
73
+ const silentMinutes = Number.isFinite(silentMs)
74
+ ? Math.max(0, Math.floor(silentMs / 60_000))
75
+ : Number.MAX_SAFE_INTEGER;
76
+ if (silentMinutes < window) {
77
+ return {
78
+ allowed: false,
79
+ reason: "alive",
80
+ sync_id: log.id,
81
+ silent_minutes: silentMinutes,
82
+ };
83
+ }
84
+ return {
85
+ allowed: true,
86
+ sync_id: log.id,
87
+ error_message: `${exports.CLEARED_BY_OPERATOR}: no heartbeat for ${silentMinutes}m`,
88
+ silent_minutes: silentMinutes,
89
+ };
90
+ }
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xlYXItc3luYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy91dGlscy9jbGVhci1zeW5jLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTJGQSxzQ0EyQ0M7QUF0SUQ7Ozs7Ozs7R0FPRztBQUNVLFFBQUEsdUJBQXVCLEdBQUcsa0JBQWtCLENBQUE7QUFFekQ7Ozs7Ozs7O0dBUUc7QUFDVSxRQUFBLG1CQUFtQixHQUFHLHFCQUFxQixDQUFBO0FBb0N4RCxTQUFTLE1BQU0sQ0FBQyxLQUF1QztJQUNyRCxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNsQixPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyxLQUFLLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzVELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7QUFDbkQsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EyQkc7QUFDSCxTQUFnQixhQUFhLENBQUMsS0FNN0I7SUFDQyxNQUFNLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsR0FBRyxLQUFLLENBQUE7SUFDakQsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFBO0lBRW5DLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNyQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQTtJQUN0RCxDQUFDO0lBRUQsSUFBSSxZQUFZLEtBQUssK0JBQXVCLEVBQUUsQ0FBQztRQUM3QyxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUE7SUFDbkUsQ0FBQztJQUVELHlFQUF5RTtJQUN6RSw4QkFBOEI7SUFDOUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUU1RSxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDbkUsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEdBQUcsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUE7SUFDekUsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDN0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxDQUFDO1FBQzVDLENBQUMsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUE7SUFFM0IsSUFBSSxhQUFhLEdBQUcsTUFBTSxFQUFFLENBQUM7UUFDM0IsT0FBTztZQUNMLE9BQU8sRUFBRSxLQUFLO1lBQ2QsTUFBTSxFQUFFLE9BQU87WUFDZixPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDZixjQUFjLEVBQUUsYUFBYTtTQUM5QixDQUFBO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLEVBQUUsSUFBSTtRQUNiLE9BQU8sRUFBRSxHQUFHLENBQUMsRUFBRTtRQUNmLGFBQWEsRUFBRSxHQUFHLDJCQUFtQixzQkFBc0IsYUFBYSxHQUFHO1FBQzNFLGNBQWMsRUFBRSxhQUFhO0tBQzlCLENBQUE7QUFDSCxDQUFDIn0=
@@ -0,0 +1,438 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CatalogVariantCache = exports.DESIGN_METADATA_KEY = exports.PLACEMENTS_BY_CLASS = void 0;
4
+ exports.classifyProduct = classifyProduct;
5
+ exports.placementsFor = placementsFor;
6
+ exports.corePlacementsFor = corePlacementsFor;
7
+ exports.planDesignParameters = planDesignParameters;
8
+ exports.designProbeKey = designProbeKey;
9
+ exports.enrichVariantsWithDesign = enrichVariantsWithDesign;
10
+ exports.summarizeProductDesign = summarizeProductDesign;
11
+ /**
12
+ * The placements a design actually uses, per class. A tee exposes 17; these
13
+ * are the ones the admin should lead with.
14
+ *
15
+ * `embroidery_front` is why this is a table and not a front/back filter: the
16
+ * cap has no `front` placement at all, so filtering on front/back returns an
17
+ * empty list for a product that plainly has somewhere to put a design.
18
+ */
19
+ exports.PLACEMENTS_BY_CLASS = {
20
+ apparel: ["front", "back"],
21
+ embroidery: ["embroidery_front"],
22
+ print_media: ["default"],
23
+ };
24
+ /**
25
+ * Placement ids that are not print areas. Printful returns mockup and preview
26
+ * entries in the same `files` list as real placements.
27
+ */
28
+ const NON_PLACEMENT_TYPES = new Set(["preview", "mockup", "template"]);
29
+ /** Printful technique keys, normalized to the names a human uses. */
30
+ const TECHNIQUE_NAMES = {
31
+ dtg: "DTG",
32
+ dtfilm: "DTF",
33
+ dtf: "DTF",
34
+ embroidery: "EMBROIDERY",
35
+ digital: "DIGITAL",
36
+ cut_sew: "CUT_SEW",
37
+ sublimation: "SUBLIMATION",
38
+ uv: "UV",
39
+ };
40
+ /**
41
+ * Techniques that mean the design is *printed* onto fabric.
42
+ *
43
+ * DTF is deliberately absent. The cap supports EMBROIDERY and DTF and no DTG,
44
+ * and DTF alone is an accessory transfer Printful offers almost everywhere —
45
+ * treating it as evidence of apparel is exactly what turns the cap into a
46
+ * garment with front/back placements it does not have. DTG (or sublimation) is
47
+ * the technique that says "this is a printable garment".
48
+ */
49
+ const PRINTED_ON_FABRIC = new Set(["dtg", "sublimation"]);
50
+ /** Film transfer. Supported broadly; never on its own evidence of a class. */
51
+ const FILM = new Set(["dtfilm", "dtf"]);
52
+ function techniqueKeys(variant) {
53
+ const keys = [];
54
+ for (const t of variant.product?.techniques ?? []) {
55
+ const key = t?.key?.trim().toLowerCase();
56
+ if (key) {
57
+ keys.push(key);
58
+ }
59
+ }
60
+ return keys;
61
+ }
62
+ function normalizeTechnique(key) {
63
+ return TECHNIQUE_NAMES[key] ?? key.toUpperCase();
64
+ }
65
+ /**
66
+ * Decide the product class from what Printful says the variant supports.
67
+ *
68
+ * Order matters. `print_media` is checked before the fabric classes because
69
+ * DIGITAL is the only technique a poster or sticker reports, and a store that
70
+ * later stocks a DIGITAL-plus-DTG product is a garment, not paper.
71
+ *
72
+ * A variant with no techniques returns `unknown` rather than defaulting to
73
+ * apparel. Guessing here would put front/back placements on something that may
74
+ * have neither, and an admin reading a confident wrong answer is worse off
75
+ * than one reading no answer.
76
+ */
77
+ function classifyProduct(variant) {
78
+ if (!variant) {
79
+ return "unknown";
80
+ }
81
+ const keys = techniqueKeys(variant);
82
+ if (keys.length === 0) {
83
+ return "unknown";
84
+ }
85
+ const set = new Set(keys);
86
+ const hasPrintOnFabric = keys.some((k) => PRINTED_ON_FABRIC.has(k));
87
+ const hasFilm = keys.some((k) => FILM.has(k));
88
+ const hasEmbroidery = set.has("embroidery");
89
+ // Paper and vinyl: DIGITAL and nothing that touches fabric.
90
+ if (set.has("digital") && !hasPrintOnFabric && !hasFilm && !hasEmbroidery) {
91
+ return "print_media";
92
+ }
93
+ // Ink on fabric wins over thread: a tee supports embroidery too, but its
94
+ // design goes on with DTG.
95
+ if (hasPrintOnFabric) {
96
+ return "apparel";
97
+ }
98
+ // Thread, with no DTG anywhere. The cap. DTF may sit alongside it and does
99
+ // not make this apparel — the placement is `embroidery_front`, not `front`.
100
+ if (hasEmbroidery) {
101
+ return "embroidery";
102
+ }
103
+ // Film and nothing else: still a print on fabric, just not a direct one.
104
+ if (hasFilm) {
105
+ return "apparel";
106
+ }
107
+ return "unknown";
108
+ }
109
+ /** Every real print placement the variant offers, mockups excluded. */
110
+ function placementsFor(variant) {
111
+ const seen = new Set();
112
+ const out = [];
113
+ for (const f of variant?.product?.files ?? []) {
114
+ // `type`, not `id`. Printful names the primary placement `id: "default"`
115
+ // on every product and puts the meaning in `type` — a tee's default is
116
+ // `front`, a cap's is `embroidery_front`. Reading `id` therefore collapses
117
+ // every product's main placement to the same meaningless "default", which
118
+ // matched nothing in the core lists and left the cap with no placement at
119
+ // all. Verified against the live catalog for variants 4025 and 7853.
120
+ const id = (f?.type ?? f?.id)?.trim();
121
+ if (!id || NON_PLACEMENT_TYPES.has(id.toLowerCase()) || seen.has(id)) {
122
+ continue;
123
+ }
124
+ seen.add(id);
125
+ out.push(id);
126
+ }
127
+ return out;
128
+ }
129
+ /**
130
+ * The placements a design actually uses on this variant: the class's core
131
+ * list, intersected with what the variant really offers.
132
+ *
133
+ * The intersection is what keeps this honest in both directions. It never
134
+ * invents a `back` on a front-only garment, and — because the table is keyed
135
+ * by class rather than hardcoded to front/back — it never returns an empty
136
+ * list for the cap, whose only placement is `embroidery_front`.
137
+ */
138
+ function corePlacementsFor(variant) {
139
+ const productClass = classifyProduct(variant);
140
+ if (productClass === "unknown") {
141
+ return [];
142
+ }
143
+ const available = new Set(placementsFor(variant));
144
+ return exports.PLACEMENTS_BY_CLASS[productClass].filter((p) => available.has(p));
145
+ }
146
+ /**
147
+ * A hex colour, or nothing.
148
+ *
149
+ * Never returns `""`. An empty string renders as a black swatch, which tells
150
+ * the admin the shirt is black when in truth Printful did not say. Absence has
151
+ * to stay distinguishable from black.
152
+ */
153
+ function normalizeHex(raw) {
154
+ const value = raw?.trim();
155
+ if (!value) {
156
+ return undefined;
157
+ }
158
+ const body = value.startsWith("#") ? value.slice(1) : value;
159
+ if (!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(body)) {
160
+ return undefined;
161
+ }
162
+ return `#${body.toLowerCase()}`;
163
+ }
164
+ /** "100% Airlume cotton", "50% cotton, 50% polyester", or nothing. */
165
+ function summarizeMaterial(material) {
166
+ const parts = [];
167
+ for (const m of material ?? []) {
168
+ const name = m?.name?.trim();
169
+ if (!name) {
170
+ continue;
171
+ }
172
+ parts.push(m.percentage != null ? `${m.percentage}% ${name}` : name);
173
+ }
174
+ return parts.length ? parts.join(", ") : undefined;
175
+ }
176
+ /**
177
+ * The physical size of a print medium, when Printful states one.
178
+ *
179
+ * `dimensions` is keyed by size on posters and by placement on stickers, so
180
+ * the variant's own size is tried as a key first and a single-entry map falls
181
+ * through to its only value.
182
+ */
183
+ function physicalDimensions(variant) {
184
+ const dims = variant.product?.dimensions;
185
+ if (!dims) {
186
+ return undefined;
187
+ }
188
+ const size = variant.variant?.size?.trim();
189
+ if (size && dims[size]) {
190
+ return dims[size];
191
+ }
192
+ const values = Object.values(dims).filter((v) => typeof v === "string" && v);
193
+ return values.length === 1 ? values[0] : values[0] || undefined;
194
+ }
195
+ function orderedTechniques(variant) {
196
+ const list = variant.product?.techniques ?? [];
197
+ const named = [];
198
+ let defaultName;
199
+ for (const t of list) {
200
+ const key = t?.key?.trim().toLowerCase();
201
+ if (!key) {
202
+ continue;
203
+ }
204
+ const name = normalizeTechnique(key);
205
+ if (!named.includes(name)) {
206
+ named.push(name);
207
+ }
208
+ if (t.is_default && !defaultName) {
209
+ defaultName = name;
210
+ }
211
+ }
212
+ // No explicit default: the first technique listed is the one Printful leads
213
+ // with, and it is a better answer than none.
214
+ return { technique: defaultName ?? named[0], techniques: named };
215
+ }
216
+ /**
217
+ * Build the design parameters for a catalog variant.
218
+ *
219
+ * Returns `null` when the variant cannot be classified. The caller is a
220
+ * best-effort sync enrichment: writing a half-guessed object into variant
221
+ * metadata would put an unfounded claim in front of the admin and into a
222
+ * later prompt, where nothing distinguishes it from a verified one.
223
+ */
224
+ function planDesignParameters(variant) {
225
+ if (!variant) {
226
+ return null;
227
+ }
228
+ const productClass = classifyProduct(variant);
229
+ if (productClass === "unknown") {
230
+ return null;
231
+ }
232
+ const { technique, techniques } = orderedTechniques(variant);
233
+ const isPrintMedia = productClass === "print_media";
234
+ // Print media reports the stock's own colour — a poster is "White #ffffff".
235
+ // That is the paper, not a design parameter, and showing it as a swatch
236
+ // reads as a choice someone made.
237
+ const color = isPrintMedia ? undefined : variant.variant?.color?.trim();
238
+ const colorHex = isPrintMedia
239
+ ? undefined
240
+ : normalizeHex(variant.variant?.color_code);
241
+ return {
242
+ productClass,
243
+ ...(technique ? { technique } : {}),
244
+ techniques,
245
+ corePlacements: corePlacementsFor(variant),
246
+ placements: placementsFor(variant),
247
+ ...(color ? { color } : {}),
248
+ ...(colorHex ? { colorHex } : {}),
249
+ ...(variant.variant?.size?.trim()
250
+ ? { size: variant.variant.size.trim() }
251
+ : {}),
252
+ ...(summarizeMaterial(variant.variant?.material)
253
+ ? { material: summarizeMaterial(variant.variant?.material) }
254
+ : {}),
255
+ ...(variant.product?.brand?.trim()
256
+ ? { brand: variant.product.brand.trim() }
257
+ : {}),
258
+ ...(variant.product?.model?.trim()
259
+ ? { model: variant.product.model.trim() }
260
+ : {}),
261
+ ...(isPrintMedia && physicalDimensions(variant)
262
+ ? { dimensions: physicalDimensions(variant) }
263
+ : {}),
264
+ ...(variant.product?.id != null
265
+ ? { catalogProductId: String(variant.product.id) }
266
+ : {}),
267
+ };
268
+ }
269
+ /**
270
+ * Where design parameters live in variant metadata.
271
+ *
272
+ * Nested under one key rather than spread as `printful_design_color`,
273
+ * `printful_design_color_hex`, … The existing flat keys — `printful_store_id`,
274
+ * `printful_availability_status` — are each a single scalar the plugin reads
275
+ * back individually. This is one cohesive record read as a whole by one admin
276
+ * panel, and a dozen sibling keys would triple the width of every variant's
277
+ * metadata for no lookup that wants them separately. The `printful_design_`
278
+ * prefix is kept on the container so the namespace still reads at a glance.
279
+ */
280
+ exports.DESIGN_METADATA_KEY = "printful_design";
281
+ /**
282
+ * The identity of one catalog probe.
283
+ *
284
+ * This is the whole stampede defence, so it is a named function with its own
285
+ * tests rather than an inline template string.
286
+ *
287
+ * A tee is 84 colours across 9 sizes — 756 sync variants, each with its own
288
+ * catalog variant id. Asking the catalog about every one is 756 HTTP calls for
289
+ * a product whose technique, placements, brand and model are identical across
290
+ * all of them, and whose hex is identical across the sizes of a colour. So the
291
+ * probe is keyed by product and colour: 84 calls, not 756. Size is deliberately
292
+ * not part of the key — it is the axis that varies without changing any answer
293
+ * the catalog gives us, and it already arrives free on the sync variant.
294
+ */
295
+ function designProbeKey(input) {
296
+ const color = input.color?.trim().toLowerCase() ?? "";
297
+ return `${input.syncProductId}::${color}`;
298
+ }
299
+ /**
300
+ * Memoizes catalog lookups by probe key for the life of one sync.
301
+ *
302
+ * Caches the *promise*, not the result, so two variants of the same colour
303
+ * reaching this concurrently share one in-flight request instead of racing to
304
+ * start two. Caches `null` answers too — a blank the catalog fails on must
305
+ * cost one call, not one per variant that shares it.
306
+ */
307
+ class CatalogVariantCache {
308
+ constructor(fetchVariant) {
309
+ this.fetchVariant = fetchVariant;
310
+ this.entries = new Map();
311
+ this.made = 0;
312
+ }
313
+ /** How many catalog calls were actually issued. For logging and tests. */
314
+ get calls() {
315
+ return this.made;
316
+ }
317
+ async get(key, catalogVariantId) {
318
+ const cached = this.entries.get(key);
319
+ if (cached) {
320
+ return cached;
321
+ }
322
+ this.made += 1;
323
+ // Never let a rejection escape: this is a best-effort enrichment and the
324
+ // sync must survive a catalog that throws rather than returns null.
325
+ const pending = this.fetchVariant(String(catalogVariantId)).catch(() => null);
326
+ this.entries.set(key, pending);
327
+ return pending;
328
+ }
329
+ }
330
+ exports.CatalogVariantCache = CatalogVariantCache;
331
+ /**
332
+ * Attach design parameters to already-mapped Medusa variants.
333
+ *
334
+ * Best-effort throughout. A `null` from the catalog, a variant with no catalog
335
+ * id, or a variant the classifier cannot place all leave the variant exactly as
336
+ * it arrived — importable, with its price, title and every other metadata key
337
+ * untouched. The key is omitted entirely rather than written as `null`, so
338
+ * "we never asked" and "we asked and learned nothing" do not render alike.
339
+ *
340
+ * `variants` and `syncVariants` are positionally paired, which is how the
341
+ * mapper produces them.
342
+ */
343
+ async function enrichVariantsWithDesign(variants, syncVariants, options) {
344
+ const cache = options.cache ?? new CatalogVariantCache(options.getCatalogVariant);
345
+ return Promise.all(variants.map(async (variant, i) => {
346
+ const sync = syncVariants[i];
347
+ const catalogVariantId = sync?.variant_id;
348
+ // Nothing to look up. Printful leaves `variant_id` unset on sync
349
+ // variants it never bound to a catalog blank.
350
+ if (catalogVariantId == null || catalogVariantId === 0) {
351
+ return variant;
352
+ }
353
+ const key = designProbeKey({
354
+ syncProductId: options.syncProductId,
355
+ color: sync?.color,
356
+ });
357
+ const catalog = await cache.get(key, catalogVariantId);
358
+ if (!catalog) {
359
+ return variant;
360
+ }
361
+ const plan = planDesignParameters(catalog);
362
+ if (!plan) {
363
+ return variant;
364
+ }
365
+ // The probe answered for one arbitrary size of this colour, so its size
366
+ // is not this variant's. Everything else on the answer — technique,
367
+ // placements, hex, material, brand — is genuinely shared.
368
+ const size = sync?.size?.trim() || plan.size;
369
+ const design = {
370
+ ...plan,
371
+ ...(size ? { size } : {}),
372
+ };
373
+ if (!size) {
374
+ delete design.size;
375
+ }
376
+ return {
377
+ ...variant,
378
+ metadata: {
379
+ ...variant.metadata,
380
+ [exports.DESIGN_METADATA_KEY]: design,
381
+ },
382
+ };
383
+ }));
384
+ }
385
+ /**
386
+ * Fold a product's variants into one design summary.
387
+ *
388
+ * Product-level facts — class, technique, placements, brand — are identical
389
+ * across every variant, so the first variant carrying design metadata answers
390
+ * for the product. Colour and size are the axes that vary, and are collected.
391
+ *
392
+ * Returns `null` when no variant carries design metadata. That is deliberately
393
+ * distinct from a summary with empty fields: a product that was never enriched
394
+ * is not a product with no design parameters, and a page that renders the two
395
+ * identically tells the owner something false about a product that is fine.
396
+ */
397
+ function summarizeProductDesign(variants) {
398
+ let shape;
399
+ const colors = [];
400
+ const sizes = [];
401
+ const seenColor = new Set();
402
+ const seenSize = new Set();
403
+ for (const variant of variants) {
404
+ const design = (variant?.metadata ?? {})[exports.DESIGN_METADATA_KEY];
405
+ if (!design) {
406
+ continue;
407
+ }
408
+ shape ??= design;
409
+ if (design.color && !seenColor.has(design.color)) {
410
+ seenColor.add(design.color);
411
+ // The hex rides with the name rather than being looked up separately:
412
+ // a swatch without one must render as absent, not as black.
413
+ colors.push({ name: design.color, hex: design.colorHex });
414
+ }
415
+ if (design.size && !seenSize.has(design.size)) {
416
+ seenSize.add(design.size);
417
+ sizes.push(design.size);
418
+ }
419
+ }
420
+ if (!shape) {
421
+ return null;
422
+ }
423
+ return {
424
+ product_class: shape.productClass,
425
+ technique: shape.technique,
426
+ techniques: shape.techniques,
427
+ core_placements: shape.corePlacements,
428
+ placements: shape.placements,
429
+ brand: shape.brand,
430
+ model: shape.model,
431
+ material: shape.material,
432
+ dimensions: shape.dimensions,
433
+ catalog_product_id: shape.catalogProductId,
434
+ colors,
435
+ sizes,
436
+ };
437
+ }
438
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzaWduLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL2Rlc2lnbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFnR0EsMENBd0NDO0FBR0Qsc0NBc0JDO0FBV0QsOENBVUM7QUFvSUQsb0RBa0RDO0FBNkJELHdDQU1DO0FBc0VELDREQXVEQztBQW9DRCx3REFnREM7QUE1a0JEOzs7Ozs7O0dBT0c7QUFDVSxRQUFBLG1CQUFtQixHQUc1QjtJQUNGLE9BQU8sRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUM7SUFDMUIsVUFBVSxFQUFFLENBQUMsa0JBQWtCLENBQUM7SUFDaEMsV0FBVyxFQUFFLENBQUMsU0FBUyxDQUFDO0NBQ3pCLENBQUE7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLG1CQUFtQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFBO0FBRXRFLHFFQUFxRTtBQUNyRSxNQUFNLGVBQWUsR0FBMkI7SUFDOUMsR0FBRyxFQUFFLEtBQUs7SUFDVixNQUFNLEVBQUUsS0FBSztJQUNiLEdBQUcsRUFBRSxLQUFLO0lBQ1YsVUFBVSxFQUFFLFlBQVk7SUFDeEIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLGFBQWE7SUFDMUIsRUFBRSxFQUFFLElBQUk7Q0FDVCxDQUFBO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUE7QUFFekQsOEVBQThFO0FBQzlFLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUE7QUFFdkMsU0FBUyxhQUFhLENBQUMsT0FBK0I7SUFDcEQsTUFBTSxJQUFJLEdBQWEsRUFBRSxDQUFBO0lB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
@@ -107,6 +107,50 @@ class PrintfulClient {
107
107
  });
108
108
  return data.result ?? { url: null, types: [] };
109
109
  }
110
+ /**
111
+ * Catalog detail for one variant: colour and its hex, material, brand, and
112
+ * the techniques and placements the design can use.
113
+ *
114
+ * Reads `/products/variant/{id}` rather than `/products/{id}` because the
115
+ * techniques it lists are the ones applicable to **this variant**. Variant
116
+ * 4025 reports `DTG` alone where product 71 reports `DTG, EMBROIDERY,
117
+ * DTFILM` — the narrower answer is the true one for a given colour and size.
118
+ *
119
+ * Returns `null` on any failure rather than throwing. This is called during
120
+ * a catalog sync, and design parameters are an enrichment: losing them must
121
+ * not fail an import of a product that is otherwise fine to sell.
122
+ */
123
+ async getCatalogVariant(catalogVariantId) {
124
+ try {
125
+ const data = await this.request(`/products/variant/${catalogVariantId}`);
126
+ return data.result ?? null;
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ /**
133
+ * Sales, costs and profit for a date range.
134
+ *
135
+ * Returns the per-store list, empty when Printful reports none — the admin
136
+ * page maps over this, and a missing key must not crash the one screen whose
137
+ * job is telling the owner what is going on.
138
+ *
139
+ * `currency` is omitted rather than defaulted when absent: Printful then
140
+ * reports in the store's own currency, which is a different request from
141
+ * asking for a specific one.
142
+ */
143
+ async getStatistics(params) {
144
+ const search = new URLSearchParams();
145
+ search.set("date_from", params.dateFrom);
146
+ search.set("date_to", params.dateTo);
147
+ search.set("report_types", params.reportTypes);
148
+ if (params.currency) {
149
+ search.set("currency", params.currency);
150
+ }
151
+ const data = await this.request(`/reports/statistics?${search.toString()}`);
152
+ return data.result?.store_statistics ?? [];
153
+ }
110
154
  /**
111
155
  * Quote shipping for a cart. Returns every method Printful offers for that
112
156
  * destination in one response — the caller picks the one it needs.
@@ -208,4 +252,4 @@ class PrintfulClient {
208
252
  }
209
253
  }
210
254
  exports.PrintfulClient = PrintfulClient;
211
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbnRmdWwtY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3ByaW50ZnVsLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxQ0FBZ0U7QUFrQ2hFLE1BQU0sZ0JBQWdCLEdBQUcsMEJBQTBCLENBQUE7QUFFbkQsTUFBYSxjQUFjO0lBU3pCLFlBQVksT0FBOEI7UUFDeEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksNEJBQW1CLENBQUMsK0JBQStCLENBQUMsQ0FBQTtRQUNoRSxDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFBO1FBQ2hDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQTtRQUM5QixJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDdkUsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQTtRQUMzQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFBO1FBQ3pDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSxHQUFHLENBQUE7UUFDN0MsSUFBSSxDQUFDLFNBQVM7WUFDWixNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFBO0lBQ3JFLENBQUM7SUFFRCxLQUFLLENBQUMsZ0JBQWdCLENBQUMsU0FBaUMsRUFBRTtRQUl4RCxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQWUsRUFBRSxD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
255
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbnRmdWwtY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3ByaW50ZnVsLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxQ0FBZ0U7QUFxQ2hFLE1BQU0sZ0JBQWdCLEdBQUcsMEJBQTBCLENBQUE7QUFFbkQsTUFBYSxjQUFjO0lBU3pCLFlBQVksT0FBOEI7UUFDeEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksNEJBQW1CLENBQUMsK0JBQStCLENBQUMsQ0FBQTtRQUNoRSxDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFBO1FBQ2hDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQTtRQUM5QixJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDdkUsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQTtRQUMzQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFBO1FBQ3pDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSxHQUFHLENBQUE7UUFDN0MsSUFBSSxDQUFDLFNBQVM7WUFDWixNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFBO0lBQ3JFLENBQUM7SUFFRCxLQUFLLENBQUMsZ0JBQWdCLENBQUMsU0FBaUMsRUFBRTtRQUl4RCxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQWUsRUFBRSxD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