shop-client 3.15.0 → 3.17.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/README.md +99 -7
- package/dist/ai/enrich.d.ts +4 -1
- package/dist/ai/enrich.mjs +2 -2
- package/dist/{chunk-QCB3U4AO.mjs → chunk-242GBM2V.mjs} +136 -14
- package/dist/chunk-3KRUT5BD.mjs +734 -0
- package/dist/{chunk-2W623LCW.mjs → chunk-5TGMDRUF.mjs} +100 -50
- package/dist/{chunk-D5MTUWFO.mjs → chunk-O77Z6OBJ.mjs} +21 -6
- package/dist/{chunk-G7OCMGA6.mjs → chunk-SBHTEKLB.mjs} +3 -1
- package/dist/{chunk-OA76XD32.mjs → chunk-YWAW6C74.mjs} +5 -5
- package/dist/collections.d.ts +16 -2
- package/dist/collections.mjs +2 -2
- package/dist/index.d.ts +8 -4
- package/dist/index.mjs +180 -79
- package/dist/products.d.ts +63 -2
- package/dist/products.mjs +2 -2
- package/dist/store.d.ts +1 -1
- package/dist/store.mjs +3 -3
- package/dist/{types-BRXamZMS.d.ts → types-w9n4csBQ.d.ts} +27 -1
- package/dist/utils/detect-country.d.ts +1 -1
- package/dist/utils/detect-country.mjs +1 -1
- package/dist/utils/func.d.ts +1 -1
- package/dist/utils/rate-limit.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-ESTBP7AD.mjs +0 -553
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rateLimitedFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-O77Z6OBJ.mjs";
|
|
4
4
|
|
|
5
5
|
// src/ai/enrich.ts
|
|
6
6
|
import TurndownService from "turndown";
|
|
@@ -30,6 +30,42 @@ var TURNDOWN_REMOVE_CLASSNAMES = [
|
|
|
30
30
|
"product-atc-wrapper"
|
|
31
31
|
];
|
|
32
32
|
var TURNDOWN_REMOVE_NODE_NAMES = ["button", "input", "select", "label"];
|
|
33
|
+
function isRecord(value) {
|
|
34
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
35
|
+
}
|
|
36
|
+
function isOneOf(values, value) {
|
|
37
|
+
return typeof value === "string" && values.includes(value);
|
|
38
|
+
}
|
|
39
|
+
function toOptionalStringOrNull(value) {
|
|
40
|
+
return typeof value === "string" ? value : null;
|
|
41
|
+
}
|
|
42
|
+
function getErrorMessage(err) {
|
|
43
|
+
if (err instanceof Error) return err.message;
|
|
44
|
+
return String(err);
|
|
45
|
+
}
|
|
46
|
+
function resolveGfmPlugin(mod) {
|
|
47
|
+
if (!isRecord(mod)) return mod;
|
|
48
|
+
const gfm = mod.gfm;
|
|
49
|
+
if (typeof gfm === "function" || isRecord(gfm)) return gfm;
|
|
50
|
+
const def = mod.default;
|
|
51
|
+
if (isRecord(def)) {
|
|
52
|
+
const defGfm = def.gfm;
|
|
53
|
+
if (typeof defGfm === "function" || isRecord(defGfm)) return defGfm;
|
|
54
|
+
return def;
|
|
55
|
+
}
|
|
56
|
+
return mod;
|
|
57
|
+
}
|
|
58
|
+
function extractOpenRouterContent(data) {
|
|
59
|
+
if (!isRecord(data)) return null;
|
|
60
|
+
const choices = data.choices;
|
|
61
|
+
if (!Array.isArray(choices) || choices.length === 0) return null;
|
|
62
|
+
const first = choices[0];
|
|
63
|
+
if (!isRecord(first)) return null;
|
|
64
|
+
const message = first.message;
|
|
65
|
+
if (!isRecord(message)) return null;
|
|
66
|
+
const content = message.content;
|
|
67
|
+
return typeof content === "string" ? content : null;
|
|
68
|
+
}
|
|
33
69
|
var cachedGfmPlugin;
|
|
34
70
|
var gfmPluginPromise;
|
|
35
71
|
var cachedTurndownPlain;
|
|
@@ -38,8 +74,7 @@ async function loadGfmPlugin() {
|
|
|
38
74
|
if (cachedGfmPlugin) return cachedGfmPlugin;
|
|
39
75
|
if (gfmPluginPromise) return gfmPluginPromise;
|
|
40
76
|
gfmPluginPromise = import("turndown-plugin-gfm").then((mod) => {
|
|
41
|
-
|
|
42
|
-
const resolved = (_d = (_c = (_b = mod == null ? void 0 : mod.gfm) != null ? _b : (_a = mod == null ? void 0 : mod.default) == null ? void 0 : _a.gfm) != null ? _c : mod == null ? void 0 : mod.default) != null ? _d : mod;
|
|
77
|
+
const resolved = resolveGfmPlugin(mod);
|
|
43
78
|
cachedGfmPlugin = resolved;
|
|
44
79
|
return resolved;
|
|
45
80
|
}).finally(() => {
|
|
@@ -55,7 +90,7 @@ function configureTurndown(td) {
|
|
|
55
90
|
});
|
|
56
91
|
}
|
|
57
92
|
const removeByClass = (className) => td.remove((node) => {
|
|
58
|
-
const cls = typeof node.getAttribute === "function" ? node.getAttribute("class") || "" : "";
|
|
93
|
+
const cls = isRecord(node) && typeof node.getAttribute === "function" ? String(node.getAttribute("class") || "") : "";
|
|
59
94
|
return cls.split(/\s+/).includes(className);
|
|
60
95
|
});
|
|
61
96
|
for (const className of TURNDOWN_REMOVE_CLASSNAMES) {
|
|
@@ -204,9 +239,11 @@ Return ONLY valid JSON (no markdown, no code fences) with keys:
|
|
|
204
239
|
}
|
|
205
240
|
async function buildEnrichPromptForProduct(domain, handle, options) {
|
|
206
241
|
var _a, _b;
|
|
242
|
+
const ajaxProductPromise = fetchAjaxProduct(domain, handle);
|
|
243
|
+
const pageHtmlPromise = (options == null ? void 0 : options.htmlContent) ? Promise.resolve(options.htmlContent) : fetchProductPage(domain, handle);
|
|
207
244
|
const [ajaxProduct, pageHtml] = await Promise.all([
|
|
208
|
-
|
|
209
|
-
|
|
245
|
+
ajaxProductPromise,
|
|
246
|
+
pageHtmlPromise
|
|
210
247
|
]);
|
|
211
248
|
const bodyHtml = ajaxProduct.description || "";
|
|
212
249
|
const extractedHtml = extractMainSection(pageHtml);
|
|
@@ -220,9 +257,11 @@ async function buildEnrichPromptForProduct(domain, handle, options) {
|
|
|
220
257
|
}
|
|
221
258
|
async function buildClassifyPromptForProduct(domain, handle, options) {
|
|
222
259
|
var _a;
|
|
260
|
+
const ajaxProductPromise = fetchAjaxProduct(domain, handle);
|
|
261
|
+
const pageHtmlPromise = (options == null ? void 0 : options.htmlContent) ? Promise.resolve(options.htmlContent) : fetchProductPage(domain, handle);
|
|
223
262
|
const [ajaxProduct, pageHtml] = await Promise.all([
|
|
224
|
-
|
|
225
|
-
|
|
263
|
+
ajaxProductPromise,
|
|
264
|
+
pageHtmlPromise
|
|
226
265
|
]);
|
|
227
266
|
const bodyHtml = ajaxProduct.description || "";
|
|
228
267
|
const extractedHtml = extractMainSection(pageHtml);
|
|
@@ -328,16 +367,18 @@ async function mergeWithLLM(bodyInput, pageInput, options) {
|
|
|
328
367
|
throw new Error(`LLM JSON schema invalid: ${schema.error}`);
|
|
329
368
|
}
|
|
330
369
|
const value = obj.value;
|
|
331
|
-
if (
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
370
|
+
if (isRecord(value)) {
|
|
371
|
+
const images = value.images;
|
|
372
|
+
if (Array.isArray(images)) {
|
|
373
|
+
const filtered = images.filter((url) => typeof url === "string").filter((url) => {
|
|
374
|
+
const u = url.toLowerCase();
|
|
375
|
+
const looksLikeProductImage = SHOPIFY_PRODUCT_IMAGE_PATTERNS.some(
|
|
376
|
+
(p) => u.includes(p)
|
|
377
|
+
);
|
|
378
|
+
return !looksLikeProductImage;
|
|
379
|
+
});
|
|
380
|
+
value.images = filtered.length > 0 ? filtered : null;
|
|
381
|
+
}
|
|
341
382
|
}
|
|
342
383
|
return JSON.stringify(value);
|
|
343
384
|
}
|
|
@@ -348,7 +389,7 @@ function safeParseJson(input) {
|
|
|
348
389
|
const v = JSON.parse(input);
|
|
349
390
|
return { ok: true, value: v };
|
|
350
391
|
} catch (err) {
|
|
351
|
-
return { ok: false, error: (err
|
|
392
|
+
return { ok: false, error: getErrorMessage(err) || "Failed to parse JSON" };
|
|
352
393
|
}
|
|
353
394
|
}
|
|
354
395
|
function validateStructuredJson(obj) {
|
|
@@ -356,16 +397,16 @@ function validateStructuredJson(obj) {
|
|
|
356
397
|
return { ok: false, error: "Top-level must be a JSON object" };
|
|
357
398
|
}
|
|
358
399
|
const o = obj;
|
|
359
|
-
if ("title" in o && !(o.title === null || typeof o.title === "string")) {
|
|
400
|
+
if ("title" in o && !(o.title === null || typeof o.title === "string" || o.title === void 0)) {
|
|
360
401
|
return { ok: false, error: "title must be null or string" };
|
|
361
402
|
}
|
|
362
|
-
if ("description" in o && !(o.description === null || typeof o.description === "string")) {
|
|
403
|
+
if ("description" in o && !(o.description === null || typeof o.description === "string" || o.description === void 0)) {
|
|
363
404
|
return { ok: false, error: "description must be null or string" };
|
|
364
405
|
}
|
|
365
|
-
if ("fit" in o && !(o.fit === null || typeof o.fit === "string")) {
|
|
406
|
+
if ("fit" in o && !(o.fit === null || typeof o.fit === "string" || o.fit === void 0)) {
|
|
366
407
|
return { ok: false, error: "fit must be null or string" };
|
|
367
408
|
}
|
|
368
|
-
if ("returnPolicy" in o && !(o.returnPolicy === null || typeof o.returnPolicy === "string")) {
|
|
409
|
+
if ("returnPolicy" in o && !(o.returnPolicy === null || typeof o.returnPolicy === "string" || o.returnPolicy === void 0)) {
|
|
369
410
|
return { ok: false, error: "returnPolicy must be null or string" };
|
|
370
411
|
}
|
|
371
412
|
const validateStringArray = (arr, field) => {
|
|
@@ -397,7 +438,7 @@ function validateStructuredJson(obj) {
|
|
|
397
438
|
return { ok: true };
|
|
398
439
|
}
|
|
399
440
|
async function callOpenRouter(args) {
|
|
400
|
-
var _a, _b, _c, _d, _e
|
|
441
|
+
var _a, _b, _c, _d, _e;
|
|
401
442
|
const openRouter = args.openRouter;
|
|
402
443
|
if (openRouter == null ? void 0 : openRouter.offline) {
|
|
403
444
|
return mockOpenRouterResponse(
|
|
@@ -456,12 +497,12 @@ async function callOpenRouter(args) {
|
|
|
456
497
|
continue;
|
|
457
498
|
}
|
|
458
499
|
const data = await response.json();
|
|
459
|
-
const content = (
|
|
500
|
+
const content = extractOpenRouterContent(data);
|
|
460
501
|
if (typeof content === "string") return content;
|
|
461
502
|
lastErrorText = JSON.stringify(data);
|
|
462
503
|
await new Promise((r) => setTimeout(r, 200));
|
|
463
504
|
} catch (err) {
|
|
464
|
-
lastErrorText = `${url}: ${(err
|
|
505
|
+
lastErrorText = `${url}: ${getErrorMessage(err)}`;
|
|
465
506
|
await new Promise((r) => setTimeout(r, 200));
|
|
466
507
|
}
|
|
467
508
|
}
|
|
@@ -499,9 +540,11 @@ function mockOpenRouterResponse(prompt) {
|
|
|
499
540
|
}
|
|
500
541
|
async function enrichProduct(domain, handle, options) {
|
|
501
542
|
var _a;
|
|
543
|
+
const ajaxProductPromise = fetchAjaxProduct(domain, handle);
|
|
544
|
+
const pageHtmlPromise = (options == null ? void 0 : options.htmlContent) ? Promise.resolve(options.htmlContent) : fetchProductPage(domain, handle);
|
|
502
545
|
const [ajaxProduct, pageHtml] = await Promise.all([
|
|
503
|
-
|
|
504
|
-
|
|
546
|
+
ajaxProductPromise,
|
|
547
|
+
pageHtmlPromise
|
|
505
548
|
]);
|
|
506
549
|
const bodyHtml = ajaxProduct.description || "";
|
|
507
550
|
const extractedHtml = extractMainSection(pageHtml);
|
|
@@ -607,7 +650,6 @@ async function classifyProduct(productContent, options) {
|
|
|
607
650
|
return validated.value;
|
|
608
651
|
}
|
|
609
652
|
function validateClassification(obj) {
|
|
610
|
-
var _a, _b;
|
|
611
653
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
612
654
|
return { ok: false, error: "Top-level must be a JSON object" };
|
|
613
655
|
}
|
|
@@ -619,7 +661,7 @@ function validateClassification(obj) {
|
|
|
619
661
|
"kid_female",
|
|
620
662
|
"generic"
|
|
621
663
|
];
|
|
622
|
-
if (
|
|
664
|
+
if (!isOneOf(audienceValues, o.audience)) {
|
|
623
665
|
return {
|
|
624
666
|
ok: false,
|
|
625
667
|
error: "audience must be one of: adult_male, adult_female, kid_male, kid_female, generic"
|
|
@@ -632,16 +674,16 @@ function validateClassification(obj) {
|
|
|
632
674
|
"home-decor",
|
|
633
675
|
"food-and-beverages"
|
|
634
676
|
];
|
|
635
|
-
if (
|
|
677
|
+
if (!isOneOf(verticalValues, o.vertical)) {
|
|
636
678
|
return {
|
|
637
679
|
ok: false,
|
|
638
680
|
error: "vertical must be one of: clothing, beauty, accessories, home-decor, food-and-beverages"
|
|
639
681
|
};
|
|
640
682
|
}
|
|
641
|
-
if ("category" in o && !(o.category === null || typeof o.category === "string")) {
|
|
683
|
+
if ("category" in o && !(o.category === null || typeof o.category === "string" || o.category === void 0)) {
|
|
642
684
|
return { ok: false, error: "category must be null or string" };
|
|
643
685
|
}
|
|
644
|
-
if ("subCategory" in o && !(o.subCategory === null || typeof o.subCategory === "string")) {
|
|
686
|
+
if ("subCategory" in o && !(o.subCategory === null || typeof o.subCategory === "string" || o.subCategory === void 0)) {
|
|
645
687
|
return { ok: false, error: "subCategory must be null or string" };
|
|
646
688
|
}
|
|
647
689
|
if (typeof o.subCategory === "string") {
|
|
@@ -653,13 +695,15 @@ function validateClassification(obj) {
|
|
|
653
695
|
};
|
|
654
696
|
}
|
|
655
697
|
}
|
|
698
|
+
const category = toOptionalStringOrNull(o.category);
|
|
699
|
+
const subCategory = toOptionalStringOrNull(o.subCategory);
|
|
656
700
|
return {
|
|
657
701
|
ok: true,
|
|
658
702
|
value: {
|
|
659
703
|
audience: o.audience,
|
|
660
704
|
vertical: o.vertical,
|
|
661
|
-
category
|
|
662
|
-
subCategory
|
|
705
|
+
category,
|
|
706
|
+
subCategory
|
|
663
707
|
}
|
|
664
708
|
};
|
|
665
709
|
}
|
|
@@ -754,7 +798,8 @@ function validateSEOContent(obj) {
|
|
|
754
798
|
"marketingCopy"
|
|
755
799
|
];
|
|
756
800
|
for (const key of requiredStrings) {
|
|
757
|
-
|
|
801
|
+
const v = o[key];
|
|
802
|
+
if (typeof v !== "string" || !v.trim()) {
|
|
758
803
|
return { ok: false, error: `${key} must be a non-empty string` };
|
|
759
804
|
}
|
|
760
805
|
}
|
|
@@ -783,15 +828,15 @@ async function determineStoreType(storeInfo, options) {
|
|
|
783
828
|
const offline = (_a = openRouter == null ? void 0 : openRouter.offline) != null ? _a : false;
|
|
784
829
|
const apiKey = (_b = options == null ? void 0 : options.apiKey) != null ? _b : openRouter == null ? void 0 : openRouter.apiKey;
|
|
785
830
|
const model = (_d = (_c = options == null ? void 0 : options.model) != null ? _c : openRouter == null ? void 0 : openRouter.model) != null ? _d : DEFAULT_OPENROUTER_MODEL;
|
|
786
|
-
const productLines =
|
|
831
|
+
const productLines = storeInfo.showcase.products.slice(0, 10).map((p) => {
|
|
787
832
|
if (typeof p === "string") return `- ${p}`;
|
|
788
|
-
const pt = typeof
|
|
789
|
-
return `- ${String(
|
|
790
|
-
})
|
|
791
|
-
const collectionLines =
|
|
833
|
+
const pt = typeof p.productType === "string" && p.productType.trim() ? p.productType : "N/A";
|
|
834
|
+
return `- ${String(p.title || "N/A")}: ${pt}`;
|
|
835
|
+
});
|
|
836
|
+
const collectionLines = storeInfo.showcase.collections.slice(0, 5).map((c) => {
|
|
792
837
|
if (typeof c === "string") return `- ${c}`;
|
|
793
|
-
return `- ${String(
|
|
794
|
-
})
|
|
838
|
+
return `- ${String(c.title || "N/A")}`;
|
|
839
|
+
});
|
|
795
840
|
const storeContent = `Store Title: ${storeInfo.title}
|
|
796
841
|
Store Description: ${(_e = storeInfo.description) != null ? _e : "N/A"}
|
|
797
842
|
|
|
@@ -920,6 +965,8 @@ function validateStoreTypeBreakdown(obj) {
|
|
|
920
965
|
"home-decor",
|
|
921
966
|
"food-and-beverages"
|
|
922
967
|
];
|
|
968
|
+
const audienceKeySet = new Set(audienceKeys);
|
|
969
|
+
const verticalKeySet = new Set(verticalKeys);
|
|
923
970
|
const o = obj;
|
|
924
971
|
const out = {};
|
|
925
972
|
const keys = Object.keys(o);
|
|
@@ -927,7 +974,7 @@ function validateStoreTypeBreakdown(obj) {
|
|
|
927
974
|
return { ok: false, error: "At least one audience key is required" };
|
|
928
975
|
}
|
|
929
976
|
for (const aKey of keys) {
|
|
930
|
-
if (!
|
|
977
|
+
if (!audienceKeySet.has(aKey)) {
|
|
931
978
|
return { ok: false, error: `Invalid audience key: ${aKey}` };
|
|
932
979
|
}
|
|
933
980
|
const vObj = o[aKey];
|
|
@@ -938,14 +985,15 @@ function validateStoreTypeBreakdown(obj) {
|
|
|
938
985
|
};
|
|
939
986
|
}
|
|
940
987
|
const vOut = {};
|
|
941
|
-
|
|
942
|
-
|
|
988
|
+
const vRec = vObj;
|
|
989
|
+
for (const vKey of Object.keys(vRec)) {
|
|
990
|
+
if (!verticalKeySet.has(vKey)) {
|
|
943
991
|
return {
|
|
944
992
|
ok: false,
|
|
945
993
|
error: `Invalid vertical key ${vKey} for audience ${aKey}`
|
|
946
994
|
};
|
|
947
995
|
}
|
|
948
|
-
const cats =
|
|
996
|
+
const cats = vRec[vKey];
|
|
949
997
|
if (!Array.isArray(cats) || cats.length === 0 || !cats.every((c) => typeof c === "string" && c.trim())) {
|
|
950
998
|
return {
|
|
951
999
|
ok: false,
|
|
@@ -998,14 +1046,16 @@ function pruneBreakdownForSignals(breakdown, text) {
|
|
|
998
1046
|
);
|
|
999
1047
|
if (signaledVerticals.size === 0) signaledVerticals.add("accessories");
|
|
1000
1048
|
const pruned = {};
|
|
1001
|
-
for (const
|
|
1049
|
+
for (const audience of Object.keys(breakdown)) {
|
|
1002
1050
|
const a = audience;
|
|
1003
1051
|
if (!signaledAudiences.has(a)) continue;
|
|
1052
|
+
const verticals = breakdown[a];
|
|
1004
1053
|
const vOut = {};
|
|
1005
|
-
for (const
|
|
1054
|
+
for (const vertical of Object.keys(verticals || {})) {
|
|
1006
1055
|
const v = vertical;
|
|
1007
1056
|
if (!signaledVerticals.has(v)) continue;
|
|
1008
|
-
|
|
1057
|
+
const categories = verticals == null ? void 0 : verticals[v];
|
|
1058
|
+
if (categories) vOut[v] = categories;
|
|
1009
1059
|
}
|
|
1010
1060
|
if (Object.keys(vOut).length > 0) {
|
|
1011
1061
|
pruned[a] = vOut;
|
|
@@ -13,8 +13,12 @@ var RateLimiter = class {
|
|
|
13
13
|
this.tokens = this.options.maxRequestsPerInterval;
|
|
14
14
|
this.tryRun();
|
|
15
15
|
}, this.options.intervalMs);
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const t = this.refillTimer;
|
|
17
|
+
if (t && typeof t === "object") {
|
|
18
|
+
const rec = t;
|
|
19
|
+
if (typeof rec.unref === "function") {
|
|
20
|
+
rec.unref();
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
24
|
ensureRefillStarted() {
|
|
@@ -34,7 +38,11 @@ var RateLimiter = class {
|
|
|
34
38
|
schedule(fn) {
|
|
35
39
|
return new Promise((resolve, reject) => {
|
|
36
40
|
this.ensureRefillStarted();
|
|
37
|
-
this.queue.push({
|
|
41
|
+
this.queue.push({
|
|
42
|
+
fn,
|
|
43
|
+
resolve,
|
|
44
|
+
reject
|
|
45
|
+
});
|
|
38
46
|
this.tryRun();
|
|
39
47
|
});
|
|
40
48
|
}
|
|
@@ -70,7 +78,8 @@ function getHost(input) {
|
|
|
70
78
|
if (input instanceof URL) {
|
|
71
79
|
return input.host;
|
|
72
80
|
}
|
|
73
|
-
const
|
|
81
|
+
const rec = input;
|
|
82
|
+
const url = typeof rec.url === "string" ? rec.url : void 0;
|
|
74
83
|
if (url) {
|
|
75
84
|
return new URL(url).host;
|
|
76
85
|
}
|
|
@@ -162,6 +171,12 @@ async function rateLimitedFetch(input, init) {
|
|
|
162
171
|
...init,
|
|
163
172
|
signal: hasSignal ? init == null ? void 0 : init.signal : controller == null ? void 0 : controller.signal
|
|
164
173
|
};
|
|
174
|
+
const {
|
|
175
|
+
rateLimitClass: _klass,
|
|
176
|
+
retry: _retry,
|
|
177
|
+
timeoutMs: _timeoutMs,
|
|
178
|
+
...fetchInit
|
|
179
|
+
} = effInit;
|
|
165
180
|
const klass = init == null ? void 0 : init.rateLimitClass;
|
|
166
181
|
const byClass = klass ? classLimiters.get(klass) : void 0;
|
|
167
182
|
const byHost = getHostLimiter(getHost(input));
|
|
@@ -175,9 +190,9 @@ async function rateLimitedFetch(input, init) {
|
|
|
175
190
|
while (attempt <= maxRetries) {
|
|
176
191
|
try {
|
|
177
192
|
if (eff) {
|
|
178
|
-
response = await eff.schedule(() => fetch(input,
|
|
193
|
+
response = await eff.schedule(() => fetch(input, fetchInit));
|
|
179
194
|
} else {
|
|
180
|
-
response = await fetch(input,
|
|
195
|
+
response = await fetch(input, fetchInit);
|
|
181
196
|
}
|
|
182
197
|
if (!response || response.ok || !retryOnStatuses.includes(response.status)) {
|
|
183
198
|
if (timer) clearTimeout(timer);
|
|
@@ -93,7 +93,9 @@ async function detectShopCountry(html) {
|
|
|
93
93
|
try {
|
|
94
94
|
const raw = currencyJsonMatch[1];
|
|
95
95
|
const obj = JSON.parse(raw || "{}");
|
|
96
|
-
const
|
|
96
|
+
const rec = obj && typeof obj === "object" ? obj : null;
|
|
97
|
+
const active = rec && typeof rec.active === "string" ? rec.active : void 0;
|
|
98
|
+
const activeCode = active ? active.toUpperCase() : void 0;
|
|
97
99
|
const iso = activeCode ? CURRENCY_CODE_TO_COUNTRY[activeCode] : void 0;
|
|
98
100
|
if (activeCode) {
|
|
99
101
|
detectedCurrencyCode = activeCode;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rateLimitedFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-O77Z6OBJ.mjs";
|
|
4
4
|
import {
|
|
5
5
|
detectShopCountry
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SBHTEKLB.mjs";
|
|
7
7
|
import {
|
|
8
8
|
extractDomainWithoutSuffix,
|
|
9
9
|
generateStoreSlug,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
// src/client/get-info.ts
|
|
14
14
|
import { unique } from "remeda";
|
|
15
15
|
async function getInfoForShop(args, options) {
|
|
16
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
16
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
17
17
|
const {
|
|
18
18
|
baseUrl,
|
|
19
19
|
storeDomain,
|
|
@@ -212,9 +212,9 @@ async function getInfoForShop(args, options) {
|
|
|
212
212
|
subDomain: myShopifySubdomain != null ? myShopifySubdomain : null
|
|
213
213
|
},
|
|
214
214
|
country: countryDetection.country,
|
|
215
|
-
currency: (countryDetection
|
|
215
|
+
currency: (_q = countryDetection.currencyCode) != null ? _q : null
|
|
216
216
|
};
|
|
217
|
-
const currencyCode = countryDetection
|
|
217
|
+
const currencyCode = countryDetection.currencyCode;
|
|
218
218
|
return { info, currencyCode };
|
|
219
219
|
}
|
|
220
220
|
|
package/dist/collections.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ShopInfo } from './store.js';
|
|
2
|
-
import { C as Collection, f as CurrencyCode, P as Product, b as ShopifyCollection } from './types-
|
|
2
|
+
import { C as Collection, f as CurrencyCode, P as Product, M as MinimalProduct, b as ShopifyCollection } from './types-w9n4csBQ.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Interface for collection operations
|
|
@@ -52,6 +52,19 @@ interface CollectionOperations {
|
|
|
52
52
|
* Fetches all product slugs from a specific collection.
|
|
53
53
|
*/
|
|
54
54
|
slugs(collectionHandle: string): Promise<string[] | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Convenience minimal namespace to always return MinimalProduct types.
|
|
57
|
+
*/
|
|
58
|
+
minimal: {
|
|
59
|
+
paginated(collectionHandle: string, options?: {
|
|
60
|
+
page?: number;
|
|
61
|
+
limit?: number;
|
|
62
|
+
currency?: CurrencyCode;
|
|
63
|
+
}): Promise<MinimalProduct[] | null>;
|
|
64
|
+
all(collectionHandle: string, options?: {
|
|
65
|
+
currency?: CurrencyCode;
|
|
66
|
+
}): Promise<MinimalProduct[] | null>;
|
|
67
|
+
};
|
|
55
68
|
};
|
|
56
69
|
}
|
|
57
70
|
/**
|
|
@@ -60,6 +73,7 @@ interface CollectionOperations {
|
|
|
60
73
|
declare function createCollectionOperations(baseUrl: string, storeDomain: string, fetchCollections: (page: number, limit: number) => Promise<Collection[] | null>, collectionsDto: (collections: ShopifyCollection[]) => Collection[], fetchPaginatedProductsFromCollection: (collectionHandle: string, options?: {
|
|
61
74
|
page?: number;
|
|
62
75
|
limit?: number;
|
|
63
|
-
|
|
76
|
+
minimal?: boolean;
|
|
77
|
+
}) => Promise<Product[] | MinimalProduct[] | null>, getStoreInfo: () => Promise<ShopInfo>, findCollection: (handle: string) => Promise<Collection | null>): CollectionOperations;
|
|
64
78
|
|
|
65
79
|
export { type CollectionOperations, createCollectionOperations };
|
package/dist/collections.mjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OpenRouterConfig, S as ShopifyProduct, P as Product, a as ShopifySingleProduct, b as ShopifyCollection, C as Collection, J as JsonLdEntry, c as StoreTypeBreakdown } from './types-
|
|
2
|
-
export { d as CountryDetectionResult, e as CountryScores, f as CurrencyCode, L as LocalizedPricing,
|
|
1
|
+
import { O as OpenRouterConfig, S as ShopifyProduct, P as Product, M as MinimalProduct, a as ShopifySingleProduct, b as ShopifyCollection, C as Collection, J as JsonLdEntry, c as StoreTypeBreakdown } from './types-w9n4csBQ.js';
|
|
2
|
+
export { d as CountryDetectionResult, e as CountryScores, f as CurrencyCode, L as LocalizedPricing, g as MetaTag, h as ProductImage, i as ProductOption, j as ProductVariant, k as ProductVariantImage } from './types-w9n4csBQ.js';
|
|
3
3
|
import { CheckoutOperations } from './checkout.js';
|
|
4
4
|
import { CollectionOperations } from './collections.js';
|
|
5
5
|
import { ProductOperations } from './products.js';
|
|
@@ -81,8 +81,12 @@ declare class ShopClient {
|
|
|
81
81
|
/**
|
|
82
82
|
* Transform Shopify products to our Product format
|
|
83
83
|
*/
|
|
84
|
-
productsDto(products: ShopifyProduct[]
|
|
85
|
-
|
|
84
|
+
productsDto(products: ShopifyProduct[], options?: {
|
|
85
|
+
minimal?: boolean;
|
|
86
|
+
}): Product[] | MinimalProduct[] | null;
|
|
87
|
+
productDto(product: ShopifySingleProduct, options?: {
|
|
88
|
+
minimal?: boolean;
|
|
89
|
+
}): Product | MinimalProduct;
|
|
86
90
|
collectionsDto(collections: ShopifyCollection[]): Collection[];
|
|
87
91
|
/**
|
|
88
92
|
* Enhanced error handling with context
|