shop-client 3.8.2 → 3.9.1
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/LICENSE +1 -1
- package/README.md +158 -1
- package/dist/ai/enrich.d.ts +93 -0
- package/dist/ai/enrich.js +25 -0
- package/dist/checkout.js +5 -114
- package/dist/{chunk-2KBOKOAD.mjs → chunk-2MF53V33.js} +32 -13
- package/dist/{chunk-BWKBRM2Z.mjs → chunk-CN7L3BHG.js} +12 -1
- package/dist/chunk-CXUCPK6X.js +460 -0
- package/dist/{chunk-QCTICSBE.mjs → chunk-MOBWPEY4.js} +29 -7
- package/dist/chunk-ROH545KI.js +274 -0
- package/dist/{chunk-QL5OUZGP.mjs → chunk-RR6YTQWP.js} +0 -1
- package/dist/{chunk-O4BPIIQ6.mjs → chunk-V52MFQZE.js} +11 -281
- package/dist/{chunk-WTK5HUFI.mjs → chunk-VPPCOJC3.js} +13 -435
- package/dist/collections.d.ts +2 -1
- package/dist/collections.js +7 -539
- package/dist/index.d.ts +28 -87
- package/dist/index.js +109 -2597
- package/dist/products.d.ts +2 -1
- package/dist/products.js +7 -1205
- package/dist/store.d.ts +53 -1
- package/dist/store.js +8 -697
- package/dist/{store-CJVUz2Yb.d.ts → types-luPg5O08.d.ts} +1 -208
- package/dist/utils/detect-country.d.ts +32 -0
- package/dist/utils/detect-country.js +6 -0
- package/dist/utils/func.d.ts +61 -0
- package/dist/utils/func.js +24 -0
- package/dist/utils/rate-limit.d.ts +5 -0
- package/dist/utils/rate-limit.js +7 -200
- package/package.json +21 -10
- package/dist/checkout.d.mts +0 -31
- package/dist/checkout.js.map +0 -1
- package/dist/checkout.mjs +0 -7
- package/dist/checkout.mjs.map +0 -1
- package/dist/chunk-2KBOKOAD.mjs.map +0 -1
- package/dist/chunk-BWKBRM2Z.mjs.map +0 -1
- package/dist/chunk-O4BPIIQ6.mjs.map +0 -1
- package/dist/chunk-QCTICSBE.mjs.map +0 -1
- package/dist/chunk-QL5OUZGP.mjs.map +0 -1
- package/dist/chunk-WTK5HUFI.mjs.map +0 -1
- package/dist/collections.d.mts +0 -64
- package/dist/collections.js.map +0 -1
- package/dist/collections.mjs +0 -9
- package/dist/collections.mjs.map +0 -1
- package/dist/index.d.mts +0 -233
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -702
- package/dist/index.mjs.map +0 -1
- package/dist/products.d.mts +0 -63
- package/dist/products.js.map +0 -1
- package/dist/products.mjs +0 -9
- package/dist/products.mjs.map +0 -1
- package/dist/store-CJVUz2Yb.d.mts +0 -608
- package/dist/store.d.mts +0 -1
- package/dist/store.js.map +0 -1
- package/dist/store.mjs +0 -9
- package/dist/store.mjs.map +0 -1
- package/dist/utils/rate-limit.d.mts +0 -25
- package/dist/utils/rate-limit.js.map +0 -1
- package/dist/utils/rate-limit.mjs +0 -11
- package/dist/utils/rate-limit.mjs.map +0 -1
package/dist/collections.js
CHANGED
|
@@ -1,540 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/collections.ts
|
|
21
|
-
var collections_exports = {};
|
|
22
|
-
__export(collections_exports, {
|
|
23
|
-
createCollectionOperations: () => createCollectionOperations
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(collections_exports);
|
|
26
|
-
var import_remeda = require("remeda");
|
|
27
|
-
|
|
28
|
-
// src/utils/func.ts
|
|
29
|
-
var import_tldts = require("tldts");
|
|
30
|
-
function formatPrice(amountInCents, currency) {
|
|
31
|
-
try {
|
|
32
|
-
return new Intl.NumberFormat(void 0, {
|
|
33
|
-
style: "currency",
|
|
34
|
-
currency
|
|
35
|
-
}).format((amountInCents || 0) / 100);
|
|
36
|
-
} catch {
|
|
37
|
-
const val = (amountInCents || 0) / 100;
|
|
38
|
-
return `${val} ${currency}`;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// src/utils/rate-limit.ts
|
|
43
|
-
var RateLimiter = class {
|
|
44
|
-
constructor(options) {
|
|
45
|
-
this.queue = [];
|
|
46
|
-
this.inFlight = 0;
|
|
47
|
-
this.refillTimer = null;
|
|
48
|
-
this.options = options;
|
|
49
|
-
this.tokens = options.maxRequestsPerInterval;
|
|
50
|
-
}
|
|
51
|
-
startRefill() {
|
|
52
|
-
if (this.refillTimer) return;
|
|
53
|
-
this.refillTimer = setInterval(() => {
|
|
54
|
-
this.tokens = this.options.maxRequestsPerInterval;
|
|
55
|
-
this.tryRun();
|
|
56
|
-
}, this.options.intervalMs);
|
|
57
|
-
if (this.refillTimer && typeof this.refillTimer.unref === "function") {
|
|
58
|
-
this.refillTimer.unref();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
stopRefill() {
|
|
62
|
-
if (this.refillTimer) {
|
|
63
|
-
clearInterval(this.refillTimer);
|
|
64
|
-
this.refillTimer = null;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
ensureRefillStarted() {
|
|
68
|
-
if (!this.refillTimer) {
|
|
69
|
-
this.startRefill();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
configure(next) {
|
|
73
|
-
this.options = { ...this.options, ...next };
|
|
74
|
-
this.options.maxRequestsPerInterval = Math.max(
|
|
75
|
-
1,
|
|
76
|
-
this.options.maxRequestsPerInterval
|
|
77
|
-
);
|
|
78
|
-
this.options.intervalMs = Math.max(10, this.options.intervalMs);
|
|
79
|
-
this.options.maxConcurrency = Math.max(1, this.options.maxConcurrency);
|
|
80
|
-
}
|
|
81
|
-
schedule(fn) {
|
|
82
|
-
return new Promise((resolve, reject) => {
|
|
83
|
-
this.ensureRefillStarted();
|
|
84
|
-
this.queue.push({ fn, resolve, reject });
|
|
85
|
-
this.tryRun();
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
tryRun() {
|
|
89
|
-
while (this.queue.length > 0 && this.inFlight < this.options.maxConcurrency && this.tokens > 0) {
|
|
90
|
-
const task = this.queue.shift();
|
|
91
|
-
this.tokens -= 1;
|
|
92
|
-
this.inFlight += 1;
|
|
93
|
-
Promise.resolve().then(task.fn).then((result) => task.resolve(result)).catch((err) => task.reject(err)).finally(() => {
|
|
94
|
-
this.inFlight -= 1;
|
|
95
|
-
setTimeout(() => this.tryRun(), 0);
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
var enabled = false;
|
|
101
|
-
var defaultOptions = {
|
|
102
|
-
maxRequestsPerInterval: 5,
|
|
103
|
-
// 5 requests
|
|
104
|
-
intervalMs: 1e3,
|
|
105
|
-
// per second
|
|
106
|
-
maxConcurrency: 5
|
|
107
|
-
// up to 5 in parallel
|
|
108
|
-
};
|
|
109
|
-
var limiter = new RateLimiter(defaultOptions);
|
|
110
|
-
var hostLimiters = /* @__PURE__ */ new Map();
|
|
111
|
-
var classLimiters = /* @__PURE__ */ new Map();
|
|
112
|
-
function getHost(input) {
|
|
113
|
-
try {
|
|
114
|
-
if (typeof input === "string") {
|
|
115
|
-
return new URL(input).host;
|
|
116
|
-
}
|
|
117
|
-
if (input instanceof URL) {
|
|
118
|
-
return input.host;
|
|
119
|
-
}
|
|
120
|
-
const url = input.url;
|
|
121
|
-
if (url) {
|
|
122
|
-
return new URL(url).host;
|
|
123
|
-
}
|
|
124
|
-
} catch {
|
|
125
|
-
}
|
|
126
|
-
return void 0;
|
|
127
|
-
}
|
|
128
|
-
function getHostLimiter(host) {
|
|
129
|
-
if (!host) return void 0;
|
|
130
|
-
const exact = hostLimiters.get(host);
|
|
131
|
-
if (exact) return exact;
|
|
132
|
-
for (const [key, lim] of hostLimiters.entries()) {
|
|
133
|
-
if (key.startsWith("*.") && host.endsWith(key.slice(2))) {
|
|
134
|
-
return lim;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return void 0;
|
|
138
|
-
}
|
|
139
|
-
async function rateLimitedFetch(input, init) {
|
|
140
|
-
var _a;
|
|
141
|
-
if (!enabled) {
|
|
142
|
-
return fetch(input, init);
|
|
143
|
-
}
|
|
144
|
-
const klass = init == null ? void 0 : init.rateLimitClass;
|
|
145
|
-
const byClass = klass ? classLimiters.get(klass) : void 0;
|
|
146
|
-
const byHost = getHostLimiter(getHost(input));
|
|
147
|
-
const eff = (_a = byClass != null ? byClass : byHost) != null ? _a : limiter;
|
|
148
|
-
return eff.schedule(() => fetch(input, init));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// src/collections.ts
|
|
152
|
-
function createCollectionOperations(baseUrl, storeDomain, fetchCollections, collectionsDto, fetchPaginatedProductsFromCollection, getStoreInfo, findCollection) {
|
|
153
|
-
function applyCurrencyOverride(product, currency) {
|
|
154
|
-
var _a, _b, _c, _d, _e, _f;
|
|
155
|
-
const priceMin = (_b = (_a = product.priceMin) != null ? _a : product.price) != null ? _b : 0;
|
|
156
|
-
const priceMax = (_d = (_c = product.priceMax) != null ? _c : product.price) != null ? _d : 0;
|
|
157
|
-
const compareAtMin = (_f = (_e = product.compareAtPriceMin) != null ? _e : product.compareAtPrice) != null ? _f : 0;
|
|
158
|
-
return {
|
|
159
|
-
...product,
|
|
160
|
-
currency,
|
|
161
|
-
localizedPricing: {
|
|
162
|
-
currency,
|
|
163
|
-
priceFormatted: formatPrice(priceMin, currency),
|
|
164
|
-
priceMinFormatted: formatPrice(priceMin, currency),
|
|
165
|
-
priceMaxFormatted: formatPrice(priceMax, currency),
|
|
166
|
-
compareAtPriceFormatted: formatPrice(compareAtMin, currency)
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
function maybeOverrideProductsCurrency(products, currency) {
|
|
171
|
-
if (!products || !currency) return products;
|
|
172
|
-
return products.map((p) => applyCurrencyOverride(p, currency));
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
/**
|
|
176
|
-
* Fetches collections with pagination support.
|
|
177
|
-
*
|
|
178
|
-
* @param options - Pagination options
|
|
179
|
-
* @param options.page - Page number (default: 1)
|
|
180
|
-
* @param options.limit - Number of collections per page (default: 10, max: 250)
|
|
181
|
-
*
|
|
182
|
-
* @returns {Promise<Collection[] | null>} Collections for the requested page, or null on error
|
|
183
|
-
*/
|
|
184
|
-
paginated: async (options) => {
|
|
185
|
-
var _a, _b;
|
|
186
|
-
const page = (_a = options == null ? void 0 : options.page) != null ? _a : 1;
|
|
187
|
-
const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 10;
|
|
188
|
-
if (page < 1 || limit < 1 || limit > 250) {
|
|
189
|
-
throw new Error(
|
|
190
|
-
"Invalid pagination parameters: page must be >= 1, limit must be between 1 and 250"
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
try {
|
|
194
|
-
const collections = await fetchCollections(page, limit);
|
|
195
|
-
return collections != null ? collections : null;
|
|
196
|
-
} catch (error) {
|
|
197
|
-
console.error(
|
|
198
|
-
"Failed to fetch paginated collections:",
|
|
199
|
-
storeDomain,
|
|
200
|
-
error
|
|
201
|
-
);
|
|
202
|
-
return null;
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
/**
|
|
206
|
-
* Fetches all collections from the store across all pages.
|
|
207
|
-
*
|
|
208
|
-
* @returns {Promise<Collection[]>} Array of all collections
|
|
209
|
-
*
|
|
210
|
-
* @throws {Error} When there's a network error or API failure
|
|
211
|
-
*
|
|
212
|
-
* @example
|
|
213
|
-
* ```typescript
|
|
214
|
-
* const shop = new ShopClient('https://exampleshop.com');
|
|
215
|
-
* const allCollections = await shop.collections.all();
|
|
216
|
-
*
|
|
217
|
-
* console.log(`Found ${allCollections.length} collections`);
|
|
218
|
-
* allCollections.forEach(collection => {
|
|
219
|
-
* console.log(collection.title, collection.handle);
|
|
220
|
-
* });
|
|
221
|
-
* ```
|
|
222
|
-
*/
|
|
223
|
-
all: async () => {
|
|
224
|
-
const limit = 250;
|
|
225
|
-
const allCollections = [];
|
|
226
|
-
async function fetchAll() {
|
|
227
|
-
let currentPage = 1;
|
|
228
|
-
while (true) {
|
|
229
|
-
const collections = await fetchCollections(currentPage, limit);
|
|
230
|
-
if (!collections || collections.length === 0 || collections.length < limit) {
|
|
231
|
-
if (!collections) {
|
|
232
|
-
console.warn(
|
|
233
|
-
"fetchCollections returned null, treating as empty array."
|
|
234
|
-
);
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
if (collections && collections.length > 0) {
|
|
238
|
-
allCollections.push(...collections);
|
|
239
|
-
}
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
allCollections.push(...collections);
|
|
243
|
-
currentPage++;
|
|
244
|
-
}
|
|
245
|
-
return allCollections;
|
|
246
|
-
}
|
|
247
|
-
try {
|
|
248
|
-
const collections = await fetchAll();
|
|
249
|
-
return collections || [];
|
|
250
|
-
} catch (error) {
|
|
251
|
-
console.error("Failed to fetch all collections:", storeDomain, error);
|
|
252
|
-
throw error;
|
|
253
|
-
}
|
|
254
|
-
},
|
|
255
|
-
/**
|
|
256
|
-
* Finds a specific collection by its handle.
|
|
257
|
-
*
|
|
258
|
-
* @param collectionHandle - The collection handle (URL slug) to search for
|
|
259
|
-
*
|
|
260
|
-
* @returns {Promise<Collection | null>} The collection if found, null if not found
|
|
261
|
-
*
|
|
262
|
-
* @throws {Error} When the handle is invalid or there's a network error
|
|
263
|
-
*
|
|
264
|
-
* @example
|
|
265
|
-
* ```typescript
|
|
266
|
-
* const shop = new ShopClient('https://example.myshopify.com');
|
|
267
|
-
* const collection = await shop.collections.find('summer-collection');
|
|
268
|
-
* if (collection) {
|
|
269
|
-
* console.log(collection.title); // "Summer Collection"
|
|
270
|
-
* }
|
|
271
|
-
* ```
|
|
272
|
-
*/
|
|
273
|
-
find: async (collectionHandle) => {
|
|
274
|
-
var _a, _b;
|
|
275
|
-
if (!collectionHandle || typeof collectionHandle !== "string") {
|
|
276
|
-
throw new Error("Collection handle is required and must be a string");
|
|
277
|
-
}
|
|
278
|
-
const sanitizedHandle = collectionHandle.trim().replace(/[^a-zA-Z0-9\-_]/g, "");
|
|
279
|
-
if (!sanitizedHandle) {
|
|
280
|
-
throw new Error("Invalid collection handle format");
|
|
281
|
-
}
|
|
282
|
-
if (sanitizedHandle.length > 255) {
|
|
283
|
-
throw new Error("Collection handle is too long");
|
|
284
|
-
}
|
|
285
|
-
try {
|
|
286
|
-
const url = `${baseUrl}collections/${encodeURIComponent(sanitizedHandle)}.json`;
|
|
287
|
-
const response = await rateLimitedFetch(url);
|
|
288
|
-
if (!response.ok) {
|
|
289
|
-
if (response.status === 404) {
|
|
290
|
-
return null;
|
|
291
|
-
}
|
|
292
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
293
|
-
}
|
|
294
|
-
const result = await response.json();
|
|
295
|
-
let collectionImage = result.collection.image;
|
|
296
|
-
if (!collectionImage) {
|
|
297
|
-
const collectionProduct = (_a = await fetchPaginatedProductsFromCollection(
|
|
298
|
-
result.collection.handle,
|
|
299
|
-
{
|
|
300
|
-
limit: 1,
|
|
301
|
-
page: 1
|
|
302
|
-
}
|
|
303
|
-
)) == null ? void 0 : _a.at(0);
|
|
304
|
-
const collectionProductImage = (_b = collectionProduct == null ? void 0 : collectionProduct.images) == null ? void 0 : _b[0];
|
|
305
|
-
if (collectionProduct && collectionProductImage) {
|
|
306
|
-
collectionImage = {
|
|
307
|
-
id: collectionProductImage.id,
|
|
308
|
-
src: collectionProductImage.src,
|
|
309
|
-
alt: collectionProductImage.alt || collectionProduct.title,
|
|
310
|
-
created_at: collectionProductImage.createdAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
const collectionData = collectionsDto([
|
|
315
|
-
{
|
|
316
|
-
...result.collection,
|
|
317
|
-
image: collectionImage
|
|
318
|
-
}
|
|
319
|
-
]);
|
|
320
|
-
return collectionData[0] || null;
|
|
321
|
-
} catch (error) {
|
|
322
|
-
if (error instanceof Error) {
|
|
323
|
-
console.error(
|
|
324
|
-
`Error fetching collection ${sanitizedHandle}:`,
|
|
325
|
-
baseUrl,
|
|
326
|
-
error.message
|
|
327
|
-
);
|
|
328
|
-
}
|
|
329
|
-
throw error;
|
|
330
|
-
}
|
|
331
|
-
},
|
|
332
|
-
/**
|
|
333
|
-
* Fetches collections that are showcased/featured on the store's homepage.
|
|
334
|
-
*
|
|
335
|
-
* @returns {Promise<Collection[]>} Array of showcased collections found on the homepage
|
|
336
|
-
*
|
|
337
|
-
* @throws {Error} When there's a network error or API failure
|
|
338
|
-
*
|
|
339
|
-
* @example
|
|
340
|
-
* ```typescript
|
|
341
|
-
* const shop = new ShopClient('https://exampleshop.com');
|
|
342
|
-
* const showcasedCollections = await shop.collections.showcased();
|
|
343
|
-
*
|
|
344
|
-
* console.log(`Found ${showcasedCollections.length} showcased collections`);
|
|
345
|
-
* showcasedCollections.forEach(collection => {
|
|
346
|
-
* console.log(`Featured: ${collection.title} - ${collection.productsCount} products`);
|
|
347
|
-
* });
|
|
348
|
-
* ```
|
|
349
|
-
*/
|
|
350
|
-
showcased: async () => {
|
|
351
|
-
const storeInfo = await getStoreInfo();
|
|
352
|
-
const collections = await Promise.all(
|
|
353
|
-
storeInfo.showcase.collections.map(
|
|
354
|
-
(collectionHandle) => findCollection(collectionHandle)
|
|
355
|
-
)
|
|
356
|
-
);
|
|
357
|
-
return (0, import_remeda.filter)(collections, import_remeda.isNonNullish);
|
|
358
|
-
},
|
|
359
|
-
products: {
|
|
360
|
-
/**
|
|
361
|
-
* Fetches products from a specific collection with pagination support.
|
|
362
|
-
*
|
|
363
|
-
* @param collectionHandle - The collection handle to fetch products from
|
|
364
|
-
* @param options - Pagination options
|
|
365
|
-
* @param options.page - Page number (default: 1)
|
|
366
|
-
* @param options.limit - Number of products per page (default: 250, max: 250)
|
|
367
|
-
*
|
|
368
|
-
* @returns {Promise<Product[] | null>} Array of products from the collection or null if error occurs
|
|
369
|
-
*
|
|
370
|
-
* @throws {Error} When the collection handle is invalid or there's a network error
|
|
371
|
-
*
|
|
372
|
-
* @example
|
|
373
|
-
* ```typescript
|
|
374
|
-
* const shop = new ShopClient('https://example.myshopify.com');
|
|
375
|
-
*
|
|
376
|
-
* // Get first page of products from a collection
|
|
377
|
-
* const products = await shop.collections.products.paginated('summer-collection');
|
|
378
|
-
*
|
|
379
|
-
* // Get second page with custom limit
|
|
380
|
-
* const moreProducts = await shop.collections.products.paginated(
|
|
381
|
-
* 'summer-collection',
|
|
382
|
-
* { page: 2, limit: 50 }
|
|
383
|
-
* );
|
|
384
|
-
* ```
|
|
385
|
-
*/
|
|
386
|
-
paginated: async (collectionHandle, options) => {
|
|
387
|
-
var _a, _b;
|
|
388
|
-
if (!collectionHandle || typeof collectionHandle !== "string") {
|
|
389
|
-
throw new Error("Collection handle is required and must be a string");
|
|
390
|
-
}
|
|
391
|
-
const sanitizedHandle = collectionHandle.trim().replace(/[^a-zA-Z0-9\-_]/g, "");
|
|
392
|
-
if (!sanitizedHandle) {
|
|
393
|
-
throw new Error("Invalid collection handle format");
|
|
394
|
-
}
|
|
395
|
-
if (sanitizedHandle.length > 255) {
|
|
396
|
-
throw new Error("Collection handle is too long");
|
|
397
|
-
}
|
|
398
|
-
const page = (_a = options == null ? void 0 : options.page) != null ? _a : 1;
|
|
399
|
-
const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 250;
|
|
400
|
-
if (page < 1 || limit < 1 || limit > 250) {
|
|
401
|
-
throw new Error(
|
|
402
|
-
"Invalid pagination parameters: page must be >= 1, limit must be between 1 and 250"
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
const products = await fetchPaginatedProductsFromCollection(
|
|
406
|
-
sanitizedHandle,
|
|
407
|
-
{ page, limit }
|
|
408
|
-
);
|
|
409
|
-
return maybeOverrideProductsCurrency(products, options == null ? void 0 : options.currency);
|
|
410
|
-
},
|
|
411
|
-
/**
|
|
412
|
-
* Fetches all products from a specific collection.
|
|
413
|
-
*
|
|
414
|
-
* @param collectionHandle - The collection handle to fetch products from
|
|
415
|
-
*
|
|
416
|
-
* @returns {Promise<Product[] | null>} Array of all products from the collection or null if error occurs
|
|
417
|
-
*
|
|
418
|
-
* @throws {Error} When the collection handle is invalid or there's a network error
|
|
419
|
-
*
|
|
420
|
-
* @example
|
|
421
|
-
* ```typescript
|
|
422
|
-
* const shop = new ShopClient('https://exampleshop.com');
|
|
423
|
-
* const allProducts = await shop.collections.products.all('summer-collection');
|
|
424
|
-
*
|
|
425
|
-
* if (allProducts) {
|
|
426
|
-
* console.log(`Found ${allProducts.length} products in the collection`);
|
|
427
|
-
* allProducts.forEach(product => {
|
|
428
|
-
* console.log(`${product.title} - $${product.price}`);
|
|
429
|
-
* });
|
|
430
|
-
* }
|
|
431
|
-
* ```
|
|
432
|
-
*/
|
|
433
|
-
all: async (collectionHandle, options) => {
|
|
434
|
-
if (!collectionHandle || typeof collectionHandle !== "string") {
|
|
435
|
-
throw new Error("Collection handle is required and must be a string");
|
|
436
|
-
}
|
|
437
|
-
const sanitizedHandle = collectionHandle.trim().replace(/[^a-zA-Z0-9\-_]/g, "");
|
|
438
|
-
if (!sanitizedHandle) {
|
|
439
|
-
throw new Error("Invalid collection handle format");
|
|
440
|
-
}
|
|
441
|
-
if (sanitizedHandle.length > 255) {
|
|
442
|
-
throw new Error("Collection handle is too long");
|
|
443
|
-
}
|
|
444
|
-
try {
|
|
445
|
-
const limit = 250;
|
|
446
|
-
const allProducts = [];
|
|
447
|
-
let currentPage = 1;
|
|
448
|
-
while (true) {
|
|
449
|
-
const products = await fetchPaginatedProductsFromCollection(
|
|
450
|
-
sanitizedHandle,
|
|
451
|
-
{
|
|
452
|
-
page: currentPage,
|
|
453
|
-
limit
|
|
454
|
-
}
|
|
455
|
-
);
|
|
456
|
-
if (!products || products.length === 0 || products.length < limit) {
|
|
457
|
-
if (products && products.length > 0) {
|
|
458
|
-
allProducts.push(...products);
|
|
459
|
-
}
|
|
460
|
-
break;
|
|
461
|
-
}
|
|
462
|
-
allProducts.push(...products);
|
|
463
|
-
currentPage++;
|
|
464
|
-
}
|
|
465
|
-
return maybeOverrideProductsCurrency(allProducts, options == null ? void 0 : options.currency);
|
|
466
|
-
} catch (error) {
|
|
467
|
-
console.error(
|
|
468
|
-
`Error fetching all products for collection ${sanitizedHandle}:`,
|
|
469
|
-
baseUrl,
|
|
470
|
-
error
|
|
471
|
-
);
|
|
472
|
-
return null;
|
|
473
|
-
}
|
|
474
|
-
},
|
|
475
|
-
/**
|
|
476
|
-
* Fetches all product slugs from a specific collection.
|
|
477
|
-
*
|
|
478
|
-
* @param collectionHandle - The collection handle to fetch product slugs from
|
|
479
|
-
*
|
|
480
|
-
* @returns {Promise<string[] | null>} Array of product slugs from the collection or null if error occurs
|
|
481
|
-
*
|
|
482
|
-
* @throws {Error} When the collection handle is invalid or there's a network error
|
|
483
|
-
*
|
|
484
|
-
* @example
|
|
485
|
-
* ```typescript
|
|
486
|
-
* const shop = new ShopClient('https://exampleshop.com');
|
|
487
|
-
* const productSlugs = await shop.collections.products.slugs('summer-collection');
|
|
488
|
-
* console.log(productSlugs);
|
|
489
|
-
* ```
|
|
490
|
-
*/
|
|
491
|
-
slugs: async (collectionHandle) => {
|
|
492
|
-
if (!collectionHandle || typeof collectionHandle !== "string") {
|
|
493
|
-
throw new Error("Collection handle is required and must be a string");
|
|
494
|
-
}
|
|
495
|
-
const sanitizedHandle = collectionHandle.trim().replace(/[^a-zA-Z0-9\-_]/g, "");
|
|
496
|
-
if (!sanitizedHandle) {
|
|
497
|
-
throw new Error("Invalid collection handle format");
|
|
498
|
-
}
|
|
499
|
-
if (sanitizedHandle.length > 255) {
|
|
500
|
-
throw new Error("Collection handle is too long");
|
|
501
|
-
}
|
|
502
|
-
try {
|
|
503
|
-
const limit = 250;
|
|
504
|
-
const slugs = [];
|
|
505
|
-
let currentPage = 1;
|
|
506
|
-
while (true) {
|
|
507
|
-
const products = await fetchPaginatedProductsFromCollection(
|
|
508
|
-
sanitizedHandle,
|
|
509
|
-
{
|
|
510
|
-
page: currentPage,
|
|
511
|
-
limit
|
|
512
|
-
}
|
|
513
|
-
);
|
|
514
|
-
if (!products || products.length === 0 || products.length < limit) {
|
|
515
|
-
if (products && products.length > 0) {
|
|
516
|
-
slugs.push(...products.map((p) => p.slug));
|
|
517
|
-
}
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
slugs.push(...products.map((p) => p.slug));
|
|
521
|
-
currentPage++;
|
|
522
|
-
}
|
|
523
|
-
return slugs;
|
|
524
|
-
} catch (error) {
|
|
525
|
-
console.error(
|
|
526
|
-
`Error fetching product slugs for collection ${sanitizedHandle}:`,
|
|
527
|
-
baseUrl,
|
|
528
|
-
error
|
|
529
|
-
);
|
|
530
|
-
return null;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
537
|
-
0 && (module.exports = {
|
|
1
|
+
import {
|
|
2
|
+
createCollectionOperations
|
|
3
|
+
} from "./chunk-MOBWPEY4.js";
|
|
4
|
+
import "./chunk-2MF53V33.js";
|
|
5
|
+
import "./chunk-CN7L3BHG.js";
|
|
6
|
+
export {
|
|
538
7
|
createCollectionOperations
|
|
539
|
-
}
|
|
540
|
-
//# sourceMappingURL=collections.js.map
|
|
8
|
+
};
|