shop-client 3.9.2 → 3.10.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/dist/ai/{enrich.js → enrich.mjs} +2 -2
- package/dist/{checkout.js → checkout.mjs} +1 -1
- package/dist/{chunk-MOBWPEY4.js → chunk-554O5ED6.mjs} +2 -2
- package/dist/{chunk-CXUCPK6X.js → chunk-CNJRHWIK.mjs} +5 -5
- package/dist/{chunk-2MF53V33.js → chunk-D5MTUWFO.mjs} +36 -10
- package/dist/{chunk-QUDGES3A.js → chunk-G7OCMGA6.mjs} +67 -34
- package/dist/{chunk-VPPCOJC3.js → chunk-GNIBTUEK.mjs} +1 -1
- package/dist/{chunk-DJQEZNHG.js → chunk-MSIVKUGN.mjs} +3 -3
- package/dist/collections.mjs +8 -0
- package/dist/{index.js → index.mjs} +8 -8
- package/dist/products.mjs +8 -0
- package/dist/store.mjs +9 -0
- package/dist/utils/{detect-country.js → detect-country.mjs} +1 -1
- package/dist/utils/{func.js → func.mjs} +1 -1
- package/dist/utils/rate-limit.d.ts +1 -0
- package/dist/utils/{rate-limit.js → rate-limit.mjs} +1 -1
- package/package.json +1 -1
- package/dist/collections.js +0 -8
- package/dist/products.js +0 -8
- package/dist/store.js +0 -9
- /package/dist/{chunk-CN7L3BHG.js → chunk-U3RQRBXZ.mjs} +0 -0
- /package/dist/{chunk-RR6YTQWP.js → chunk-W4SF6W2P.mjs} +0 -0
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
htmlToMarkdown,
|
|
10
10
|
mergeWithLLM,
|
|
11
11
|
pruneBreakdownForSignals
|
|
12
|
-
} from "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
} from "../chunk-GNIBTUEK.mjs";
|
|
13
|
+
import "../chunk-D5MTUWFO.mjs";
|
|
14
14
|
export {
|
|
15
15
|
classifyProduct,
|
|
16
16
|
determineStoreType,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rateLimitedFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-D5MTUWFO.mjs";
|
|
4
4
|
import {
|
|
5
5
|
formatPrice
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-U3RQRBXZ.mjs";
|
|
7
7
|
|
|
8
8
|
// src/products.ts
|
|
9
9
|
import { filter, isNonNullish } from "remeda";
|
|
@@ -253,7 +253,7 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
|
|
|
253
253
|
return null;
|
|
254
254
|
}
|
|
255
255
|
const handle = baseProduct.handle;
|
|
256
|
-
const { enrichProduct } = await import("./ai/enrich.
|
|
256
|
+
const { enrichProduct } = await import("./ai/enrich.mjs");
|
|
257
257
|
const enriched = await enrichProduct(storeDomain, handle, {
|
|
258
258
|
apiKey,
|
|
259
259
|
useGfm: options == null ? void 0 : options.useGfm,
|
|
@@ -302,7 +302,7 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
|
|
|
302
302
|
productContent = lines.join("\n");
|
|
303
303
|
} catch {
|
|
304
304
|
}
|
|
305
|
-
const { classifyProduct } = await import("./ai/enrich.
|
|
305
|
+
const { classifyProduct } = await import("./ai/enrich.mjs");
|
|
306
306
|
const classification = await classifyProduct(productContent, {
|
|
307
307
|
apiKey,
|
|
308
308
|
model: options == null ? void 0 : options.model
|
|
@@ -328,7 +328,7 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
|
|
|
328
328
|
price: baseProduct.price,
|
|
329
329
|
tags: baseProduct.tags
|
|
330
330
|
};
|
|
331
|
-
const { generateSEOContent: generateSEOContentLLM } = await import("./ai/enrich.
|
|
331
|
+
const { generateSEOContent: generateSEOContentLLM } = await import("./ai/enrich.mjs");
|
|
332
332
|
const seo = await generateSEOContentLLM(payload, {
|
|
333
333
|
apiKey,
|
|
334
334
|
model: options == null ? void 0 : options.model
|
|
@@ -50,7 +50,7 @@ var RateLimiter = class {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
|
-
var enabled =
|
|
53
|
+
var enabled = true;
|
|
54
54
|
var defaultOptions = {
|
|
55
55
|
maxRequestsPerInterval: 5,
|
|
56
56
|
// 5 requests
|
|
@@ -149,25 +149,38 @@ function sleep(ms) {
|
|
|
149
149
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
150
150
|
}
|
|
151
151
|
async function rateLimitedFetch(input, init) {
|
|
152
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
152
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
153
|
+
const timeoutMs = Math.max(0, (_a = init == null ? void 0 : init.timeoutMs) != null ? _a : 0);
|
|
154
|
+
let controller;
|
|
155
|
+
let timer;
|
|
156
|
+
const hasSignal = !!(init == null ? void 0 : init.signal);
|
|
157
|
+
if (timeoutMs > 0 && !hasSignal) {
|
|
158
|
+
controller = new AbortController();
|
|
159
|
+
timer = setTimeout(() => controller == null ? void 0 : controller.abort(), timeoutMs);
|
|
160
|
+
}
|
|
161
|
+
const effInit = {
|
|
162
|
+
...init,
|
|
163
|
+
signal: hasSignal ? init == null ? void 0 : init.signal : controller == null ? void 0 : controller.signal
|
|
164
|
+
};
|
|
153
165
|
const klass = init == null ? void 0 : init.rateLimitClass;
|
|
154
166
|
const byClass = klass ? classLimiters.get(klass) : void 0;
|
|
155
167
|
const byHost = getHostLimiter(getHost(input));
|
|
156
|
-
const eff = enabled ? (
|
|
157
|
-
const maxRetries = Math.max(0, (
|
|
158
|
-
const baseDelayMs = Math.max(0, (
|
|
159
|
-
const retryOnStatuses = (
|
|
168
|
+
const eff = enabled ? (_b = byClass != null ? byClass : byHost) != null ? _b : limiter : void 0;
|
|
169
|
+
const maxRetries = Math.max(0, (_d = (_c = init == null ? void 0 : init.retry) == null ? void 0 : _c.maxRetries) != null ? _d : 2);
|
|
170
|
+
const baseDelayMs = Math.max(0, (_f = (_e = init == null ? void 0 : init.retry) == null ? void 0 : _e.baseDelayMs) != null ? _f : 200);
|
|
171
|
+
const retryOnStatuses = (_h = (_g = init == null ? void 0 : init.retry) == null ? void 0 : _g.retryOnStatuses) != null ? _h : [429, 503];
|
|
160
172
|
let attempt = 0;
|
|
161
173
|
let lastError = null;
|
|
162
174
|
let response = null;
|
|
163
175
|
while (attempt <= maxRetries) {
|
|
164
176
|
try {
|
|
165
177
|
if (eff) {
|
|
166
|
-
response = await eff.schedule(() => fetch(input,
|
|
178
|
+
response = await eff.schedule(() => fetch(input, effInit));
|
|
167
179
|
} else {
|
|
168
|
-
response = await fetch(input,
|
|
180
|
+
response = await fetch(input, effInit);
|
|
169
181
|
}
|
|
170
182
|
if (!response || response.ok || !retryOnStatuses.includes(response.status)) {
|
|
183
|
+
if (timer) clearTimeout(timer);
|
|
171
184
|
return response;
|
|
172
185
|
}
|
|
173
186
|
} catch (err) {
|
|
@@ -175,10 +188,23 @@ async function rateLimitedFetch(input, init) {
|
|
|
175
188
|
}
|
|
176
189
|
attempt += 1;
|
|
177
190
|
if (attempt > maxRetries) break;
|
|
178
|
-
|
|
179
|
-
const
|
|
191
|
+
let delay = baseDelayMs * 2 ** (attempt - 1) + Math.floor(Math.random() * 100);
|
|
192
|
+
const retryAfter = (_i = response == null ? void 0 : response.headers) == null ? void 0 : _i.get("retry-after");
|
|
193
|
+
if (retryAfter) {
|
|
194
|
+
const asNumber = Number(retryAfter);
|
|
195
|
+
if (!Number.isNaN(asNumber) && asNumber >= 0) {
|
|
196
|
+
delay = Math.max(delay, Math.floor(asNumber * 1e3));
|
|
197
|
+
} else {
|
|
198
|
+
const parsed = Date.parse(retryAfter);
|
|
199
|
+
if (!Number.isNaN(parsed)) {
|
|
200
|
+
const until = parsed - Date.now();
|
|
201
|
+
if (until > 0) delay = Math.max(delay, until);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
180
205
|
await sleep(delay);
|
|
181
206
|
}
|
|
207
|
+
if (timer) clearTimeout(timer);
|
|
182
208
|
if (response) return response;
|
|
183
209
|
throw lastError != null ? lastError : new Error("rateLimitedFetch failed without response");
|
|
184
210
|
}
|
|
@@ -33,6 +33,32 @@ var COUNTRY_CODES = {
|
|
|
33
33
|
"+7": "RU"
|
|
34
34
|
// Russia
|
|
35
35
|
};
|
|
36
|
+
var CURRENCY_JSON_RE = /Shopify\.currency\s*=\s*(\{[^}]*\})/i;
|
|
37
|
+
var CURRENCY_ACTIVE_ASSIGN_RE = /Shopify\.currency\.active\s*=\s*['"]([A-Za-z]{3})['"]/i;
|
|
38
|
+
var SHOPIFY_COUNTRY_RE = /Shopify\.country\s*=\s*['"]([A-Za-z]{2})['"]/i;
|
|
39
|
+
var JSON_LD_RE = /<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi;
|
|
40
|
+
var TEL_HREF_RE = /href=["']tel:([^"']+)["']/gi;
|
|
41
|
+
var COUNTRY_NAME_TO_ISO = {
|
|
42
|
+
india: "IN",
|
|
43
|
+
"united states": "US",
|
|
44
|
+
canada: "CA",
|
|
45
|
+
australia: "AU",
|
|
46
|
+
"united kingdom": "GB",
|
|
47
|
+
britain: "GB",
|
|
48
|
+
uk: "GB",
|
|
49
|
+
japan: "JP",
|
|
50
|
+
"south korea": "KR",
|
|
51
|
+
korea: "KR",
|
|
52
|
+
germany: "DE",
|
|
53
|
+
france: "FR",
|
|
54
|
+
italy: "IT",
|
|
55
|
+
spain: "ES",
|
|
56
|
+
brazil: "BR",
|
|
57
|
+
russia: "RU",
|
|
58
|
+
singapore: "SG",
|
|
59
|
+
indonesia: "ID",
|
|
60
|
+
pakistan: "PK"
|
|
61
|
+
};
|
|
36
62
|
var CURRENCY_CODE_TO_COUNTRY = {
|
|
37
63
|
INR: "IN",
|
|
38
64
|
USD: "US",
|
|
@@ -51,11 +77,18 @@ function scoreCountry(countryScores, country, weight, reason) {
|
|
|
51
77
|
countryScores[country].score += weight;
|
|
52
78
|
countryScores[country].reasons.push(reason);
|
|
53
79
|
}
|
|
80
|
+
function currentConfidence(countryScores) {
|
|
81
|
+
const sorted = Object.entries(countryScores).sort(
|
|
82
|
+
(a, b) => b[1].score - a[1].score
|
|
83
|
+
);
|
|
84
|
+
const best = sorted[0];
|
|
85
|
+
return best ? Math.min(1, best[1].score / 2) : 0;
|
|
86
|
+
}
|
|
54
87
|
async function detectShopCountry(html) {
|
|
55
|
-
var _a;
|
|
88
|
+
var _a, _b, _c;
|
|
56
89
|
const countryScores = {};
|
|
57
90
|
let detectedCurrencyCode;
|
|
58
|
-
const currencyJsonMatch = html.match(
|
|
91
|
+
const currencyJsonMatch = html.match(CURRENCY_JSON_RE);
|
|
59
92
|
if (currencyJsonMatch) {
|
|
60
93
|
try {
|
|
61
94
|
const raw = currencyJsonMatch[1];
|
|
@@ -71,9 +104,7 @@ async function detectShopCountry(html) {
|
|
|
71
104
|
} catch (_error) {
|
|
72
105
|
}
|
|
73
106
|
} else {
|
|
74
|
-
const currencyActiveAssignMatch = html.match(
|
|
75
|
-
/Shopify\.currency\.active\s*=\s*['"]([A-Za-z]{3})['"]/i
|
|
76
|
-
);
|
|
107
|
+
const currencyActiveAssignMatch = html.match(CURRENCY_ACTIVE_ASSIGN_RE);
|
|
77
108
|
if (currencyActiveAssignMatch) {
|
|
78
109
|
const captured = currencyActiveAssignMatch[1];
|
|
79
110
|
const code = typeof captured === "string" ? captured.toUpperCase() : void 0;
|
|
@@ -86,9 +117,7 @@ async function detectShopCountry(html) {
|
|
|
86
117
|
}
|
|
87
118
|
}
|
|
88
119
|
}
|
|
89
|
-
const shopifyCountryMatch = html.match(
|
|
90
|
-
/Shopify\.country\s*=\s*['"]([A-Za-z]{2})['"]/i
|
|
91
|
-
);
|
|
120
|
+
const shopifyCountryMatch = html.match(SHOPIFY_COUNTRY_RE);
|
|
92
121
|
if (shopifyCountryMatch) {
|
|
93
122
|
const captured = shopifyCountryMatch[1];
|
|
94
123
|
const iso = typeof captured === "string" ? captured.toUpperCase() : void 0;
|
|
@@ -96,10 +125,34 @@ async function detectShopCountry(html) {
|
|
|
96
125
|
scoreCountry(countryScores, iso, 1, "Shopify.country");
|
|
97
126
|
}
|
|
98
127
|
}
|
|
128
|
+
if (currentConfidence(countryScores) >= 0.9) {
|
|
129
|
+
const sorted2 = Object.entries(countryScores).sort(
|
|
130
|
+
(a, b) => b[1].score - a[1].score
|
|
131
|
+
);
|
|
132
|
+
const best2 = sorted2[0];
|
|
133
|
+
return {
|
|
134
|
+
country: best2[0],
|
|
135
|
+
confidence: Math.min(1, best2[1].score / 2),
|
|
136
|
+
signals: best2[1].reasons,
|
|
137
|
+
currencyCode: detectedCurrencyCode
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const telMatches = html.matchAll(TEL_HREF_RE);
|
|
141
|
+
for (const m of telMatches) {
|
|
142
|
+
const tel = (_a = m[1]) != null ? _a : "";
|
|
143
|
+
const prefix = (_b = tel.match(/^\+\d{1,3}/)) == null ? void 0 : _b[0];
|
|
144
|
+
if (prefix && COUNTRY_CODES[prefix])
|
|
145
|
+
scoreCountry(
|
|
146
|
+
countryScores,
|
|
147
|
+
COUNTRY_CODES[prefix],
|
|
148
|
+
0.8,
|
|
149
|
+
`phone prefix ${prefix}`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
99
152
|
const phones = html.match(/\+\d{1,3}[\s\-()0-9]{5,}/g);
|
|
100
153
|
if (phones) {
|
|
101
154
|
for (const phone of phones) {
|
|
102
|
-
const prefix = (
|
|
155
|
+
const prefix = (_c = phone.match(/^\+\d{1,3}/)) == null ? void 0 : _c[0];
|
|
103
156
|
if (prefix && COUNTRY_CODES[prefix])
|
|
104
157
|
scoreCountry(
|
|
105
158
|
countryScores,
|
|
@@ -109,8 +162,7 @@ async function detectShopCountry(html) {
|
|
|
109
162
|
);
|
|
110
163
|
}
|
|
111
164
|
}
|
|
112
|
-
|
|
113
|
-
let jsonLdMatch = jsonLdRegex.exec(html);
|
|
165
|
+
let jsonLdMatch = JSON_LD_RE.exec(html);
|
|
114
166
|
while (jsonLdMatch !== null) {
|
|
115
167
|
try {
|
|
116
168
|
const json = jsonLdMatch[1];
|
|
@@ -141,34 +193,15 @@ async function detectShopCountry(html) {
|
|
|
141
193
|
}
|
|
142
194
|
} catch (_error) {
|
|
143
195
|
}
|
|
144
|
-
|
|
196
|
+
if (currentConfidence(countryScores) >= 0.9)
|
|
197
|
+
break;
|
|
198
|
+
jsonLdMatch = JSON_LD_RE.exec(html);
|
|
145
199
|
}
|
|
146
200
|
const footerMatch = html.match(/<footer[^>]*>(.*?)<\/footer>/i);
|
|
147
201
|
if (footerMatch) {
|
|
148
202
|
const footerTextGroup = footerMatch[1];
|
|
149
203
|
const footerText = footerTextGroup ? footerTextGroup.toLowerCase() : "";
|
|
150
|
-
const
|
|
151
|
-
india: "IN",
|
|
152
|
-
"united states": "US",
|
|
153
|
-
canada: "CA",
|
|
154
|
-
australia: "AU",
|
|
155
|
-
"united kingdom": "GB",
|
|
156
|
-
britain: "GB",
|
|
157
|
-
uk: "GB",
|
|
158
|
-
japan: "JP",
|
|
159
|
-
"south korea": "KR",
|
|
160
|
-
korea: "KR",
|
|
161
|
-
germany: "DE",
|
|
162
|
-
france: "FR",
|
|
163
|
-
italy: "IT",
|
|
164
|
-
spain: "ES",
|
|
165
|
-
brazil: "BR",
|
|
166
|
-
russia: "RU",
|
|
167
|
-
singapore: "SG",
|
|
168
|
-
indonesia: "ID",
|
|
169
|
-
pakistan: "PK"
|
|
170
|
-
};
|
|
171
|
-
for (const [countryName, isoCode] of Object.entries(countryNameToISO)) {
|
|
204
|
+
for (const [countryName, isoCode] of Object.entries(COUNTRY_NAME_TO_ISO)) {
|
|
172
205
|
if (footerText.includes(countryName))
|
|
173
206
|
scoreCountry(countryScores, isoCode, 0.4, "footer mention");
|
|
174
207
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rateLimitedFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-D5MTUWFO.mjs";
|
|
4
4
|
import {
|
|
5
5
|
detectShopCountry
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-G7OCMGA6.mjs";
|
|
7
7
|
import {
|
|
8
8
|
extractDomainWithoutSuffix,
|
|
9
9
|
generateStoreSlug,
|
|
10
10
|
sanitizeDomain
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-U3RQRBXZ.mjs";
|
|
12
12
|
|
|
13
13
|
// src/client/get-info.ts
|
|
14
14
|
import { unique } from "remeda";
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCheckoutOperations
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-W4SF6W2P.mjs";
|
|
4
4
|
import {
|
|
5
5
|
createCollectionOperations
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-554O5ED6.mjs";
|
|
7
7
|
import {
|
|
8
8
|
createProductOperations
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CNJRHWIK.mjs";
|
|
10
10
|
import {
|
|
11
11
|
createStoreOperations,
|
|
12
12
|
getInfoForStore
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-MSIVKUGN.mjs";
|
|
14
14
|
import {
|
|
15
15
|
classifyProduct,
|
|
16
16
|
determineStoreType,
|
|
17
17
|
generateSEOContent
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-GNIBTUEK.mjs";
|
|
19
19
|
import {
|
|
20
20
|
configureRateLimit,
|
|
21
21
|
rateLimitedFetch
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-D5MTUWFO.mjs";
|
|
23
23
|
import {
|
|
24
24
|
detectShopCountry
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-G7OCMGA6.mjs";
|
|
26
26
|
import {
|
|
27
27
|
buildVariantOptionsMap,
|
|
28
28
|
calculateDiscount,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
normalizeKey,
|
|
33
33
|
safeParseDate,
|
|
34
34
|
sanitizeDomain
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-U3RQRBXZ.mjs";
|
|
36
36
|
|
|
37
37
|
// src/ai/determine-store-type.ts
|
|
38
38
|
async function determineStoreTypeForStore(args) {
|
package/dist/store.mjs
ADDED
package/package.json
CHANGED
package/dist/collections.js
DELETED
package/dist/products.js
DELETED
package/dist/store.js
DELETED
|
File without changes
|
|
File without changes
|