@growupsell/commerce 0.0.0-stage → 1.0.0-alpha.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 +33 -0
- package/README.md +6 -2
- package/dist/chunk-4PHF3WVQ.js +76 -0
- package/dist/chunk-4PHF3WVQ.js.map +1 -0
- package/dist/chunk-YZJTPFCH.js +2789 -0
- package/dist/chunk-YZJTPFCH.js.map +1 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +9 -0
- package/dist/http/index.js.map +1 -0
- package/dist/index-tlJ3s67B.d.ts +2107 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/promotions-Ck9FZD7h.d.ts +298 -0
- package/dist/rules/index.d.ts +111 -0
- package/dist/rules/index.js +19 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.js +1 -0
- package/dist/stores/index.js.map +1 -0
- package/package.json +42 -4
|
@@ -0,0 +1,2789 @@
|
|
|
1
|
+
// src/http/convert.ts
|
|
2
|
+
var text = (value) => value == null || value.trim() === "" ? null : value;
|
|
3
|
+
var amount = (value) => {
|
|
4
|
+
if (value == null || value === "") return null;
|
|
5
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
6
|
+
return Number.isFinite(n) ? n : null;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/http/blog.ts
|
|
10
|
+
var PUBLIC = { anonymous: true, business: "required" };
|
|
11
|
+
var MERCHANT = { merchant: true, anonymous: true, business: "required" };
|
|
12
|
+
function createBlogApi(request) {
|
|
13
|
+
return {
|
|
14
|
+
async list(options = {}) {
|
|
15
|
+
const categorySlug = options.categorySlug?.trim();
|
|
16
|
+
const rows = await request("GET", "/blog/list", {
|
|
17
|
+
...PUBLIC,
|
|
18
|
+
query: categorySlug ? { category_slug: categorySlug } : void 0
|
|
19
|
+
});
|
|
20
|
+
return rows.map(toBlogPostSummary);
|
|
21
|
+
},
|
|
22
|
+
async get(slug) {
|
|
23
|
+
return toBlogPost(await request("GET", `/blog/get/${path(slug)}`, PUBLIC));
|
|
24
|
+
},
|
|
25
|
+
async updateBody(slug, body) {
|
|
26
|
+
const json = { body };
|
|
27
|
+
await request("PATCH", `/blog/update/${path(slug)}`, { ...MERCHANT, json });
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function path(slug) {
|
|
32
|
+
if (!slug.trim()) throw new Error("blog: slug is required.");
|
|
33
|
+
return encodeURIComponent(slug.trim());
|
|
34
|
+
}
|
|
35
|
+
function toBlogPostSummary(wire) {
|
|
36
|
+
return summary(wire, wire.user);
|
|
37
|
+
}
|
|
38
|
+
function toBlogPost(wire) {
|
|
39
|
+
return {
|
|
40
|
+
...summary(wire, wire.created_by),
|
|
41
|
+
body: Array.isArray(wire.body) ? wire.body.filter((s) => typeof s === "string") : [],
|
|
42
|
+
editor: EDITORS.includes(wire.editor_type) ? wire.editor_type : "quill"
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
var EDITORS = ["quill", "ckeditor", "froala"];
|
|
46
|
+
function summary(wire, author) {
|
|
47
|
+
return {
|
|
48
|
+
id: wire.id,
|
|
49
|
+
slug: wire.slug,
|
|
50
|
+
title: wire.title,
|
|
51
|
+
shortDescription: text(wire.short_description),
|
|
52
|
+
image: text(wire.image),
|
|
53
|
+
category: wire.category ? toCategory(wire.category) : null,
|
|
54
|
+
tags: Array.isArray(wire.tags) ? wire.tags.filter((t) => typeof t === "string" && t.trim() !== "") : [],
|
|
55
|
+
author: author ? toAuthor(author) : null,
|
|
56
|
+
isPublished: wire.is_published ?? false,
|
|
57
|
+
createdAt: wire.created_at,
|
|
58
|
+
updatedAt: wire.updated_at
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function toCategory(wire) {
|
|
62
|
+
return {
|
|
63
|
+
id: wire.id,
|
|
64
|
+
name: text(wire.name),
|
|
65
|
+
slug: wire.slug,
|
|
66
|
+
image: text(wire.image),
|
|
67
|
+
seoDescription: text(wire.seo_description)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function toAuthor(wire) {
|
|
71
|
+
return { id: wire.id, name: text(wire.name.trim()), photo: text(wire.photo) };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/http/business.ts
|
|
75
|
+
var PUBLIC2 = { business: "required", anonymous: true };
|
|
76
|
+
var MERCHANT2 = { merchant: true, anonymous: true };
|
|
77
|
+
function createBusinessApi(request) {
|
|
78
|
+
return {
|
|
79
|
+
async detail(domain) {
|
|
80
|
+
const trimmed = domain.trim();
|
|
81
|
+
if (!trimmed) throw new Error("business.detail: domain is required.");
|
|
82
|
+
const wire = await request(
|
|
83
|
+
"GET",
|
|
84
|
+
`/business/detail/${encodeURIComponent(trimmed)}`,
|
|
85
|
+
{ anonymous: true }
|
|
86
|
+
);
|
|
87
|
+
return toBusiness(wire);
|
|
88
|
+
},
|
|
89
|
+
async settings() {
|
|
90
|
+
return toBusinessSettings(
|
|
91
|
+
await request("GET", "/business/setting/get", PUBLIC2)
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
async media() {
|
|
95
|
+
return toBusinessMedia(
|
|
96
|
+
await request("GET", "/business/media/get", PUBLIC2)
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
async socialLinks() {
|
|
100
|
+
return toSocialLinks(
|
|
101
|
+
await request(
|
|
102
|
+
"GET",
|
|
103
|
+
"/business/social-media-link/get",
|
|
104
|
+
PUBLIC2
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
async bankTransferOptions() {
|
|
109
|
+
const wire = await request(
|
|
110
|
+
"GET",
|
|
111
|
+
"/business/direct/transfer/list",
|
|
112
|
+
{
|
|
113
|
+
business: "required"
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
return wire.filter((o) => !o.deleted).map(toBankTransferOption);
|
|
117
|
+
},
|
|
118
|
+
async themeSettings() {
|
|
119
|
+
return toThemeSettings(
|
|
120
|
+
await request("GET", "/business/theme/setting/get", PUBLIC2)
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
async updateThemeSettings(changes) {
|
|
124
|
+
const wire = await request(
|
|
125
|
+
"PATCH",
|
|
126
|
+
"/business/theme/setting/update",
|
|
127
|
+
{ ...MERCHANT2, json: toThemeSettingWrite(changes) }
|
|
128
|
+
);
|
|
129
|
+
return toThemeSettings(wire);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function toBusiness(wire) {
|
|
134
|
+
const tag = wire.website_tag;
|
|
135
|
+
return {
|
|
136
|
+
id: wire.id,
|
|
137
|
+
name: wire.name ?? null,
|
|
138
|
+
description: wire.description ?? null,
|
|
139
|
+
legalName: wire.legal_name ?? null,
|
|
140
|
+
gstNumber: wire.gst_number ?? null,
|
|
141
|
+
panNumber: wire.pan_number ?? null,
|
|
142
|
+
isTemplate: wire.is_template ?? false,
|
|
143
|
+
category: wire.category ? { id: wire.category.id, name: wire.category.name, type: wire.category.type } : null,
|
|
144
|
+
legalForm: wire.legal_forms ? { id: wire.legal_forms.id, name: wire.legal_forms.name } : null,
|
|
145
|
+
features: wire.features.filter((f) => f.is_active !== false).map((f) => f.name),
|
|
146
|
+
googleTagManagerId: tag?.is_active && tag.gtm_container_id ? tag.gtm_container_id : null,
|
|
147
|
+
createdAt: wire.created_at,
|
|
148
|
+
updatedAt: wire.updated_at
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function toBusinessSettings(wire) {
|
|
152
|
+
return {
|
|
153
|
+
currency: wire.currency ? { code: wire.currency.currency_code, symbol: wire.currency.currency_symbol } : null,
|
|
154
|
+
domain: text(wire.domain)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function toBusinessMedia(wire) {
|
|
158
|
+
return { logoSquare: text(wire.logo_square), logoRectangle: text(wire.logo_rectangle) };
|
|
159
|
+
}
|
|
160
|
+
function toSocialLinks(wire) {
|
|
161
|
+
return {
|
|
162
|
+
facebook: text(wire.facebook),
|
|
163
|
+
instagram: text(wire.instagram),
|
|
164
|
+
twitter: text(wire.twitter),
|
|
165
|
+
telegram: text(wire.telegram),
|
|
166
|
+
whatsapp: text(wire.whatsapp),
|
|
167
|
+
linkedin: text(wire.linkedin)
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function toThemeSettings(wire) {
|
|
171
|
+
return {
|
|
172
|
+
id: wire.id,
|
|
173
|
+
// Required by the model; '#CCC' is its default.
|
|
174
|
+
primaryColor: text(wire.primary_color) ?? "#CCC",
|
|
175
|
+
accentColor: text(wire.accent_color),
|
|
176
|
+
fontFamily: text(wire.font_family),
|
|
177
|
+
websiteThemeId: themeId(wire.website_theme),
|
|
178
|
+
appThemeId: themeId(wire.app_theme)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
var themeId = (theme) => typeof theme === "number" ? theme : theme?.id ?? null;
|
|
182
|
+
function toThemeSettingWrite(changes) {
|
|
183
|
+
const body = {};
|
|
184
|
+
if (changes.primaryColor !== void 0) body.primary_color = changes.primaryColor;
|
|
185
|
+
if (changes.accentColor !== void 0) body.accent_color = changes.accentColor;
|
|
186
|
+
if (changes.fontFamily !== void 0) body.font_family = changes.fontFamily;
|
|
187
|
+
if (changes.websiteThemeId !== void 0) body.website_theme = changes.websiteThemeId;
|
|
188
|
+
if (changes.appThemeId !== void 0) body.app_theme = changes.appThemeId;
|
|
189
|
+
return body;
|
|
190
|
+
}
|
|
191
|
+
function toBankTransferOption(wire) {
|
|
192
|
+
return {
|
|
193
|
+
id: wire.id,
|
|
194
|
+
type: text(wire.type),
|
|
195
|
+
description: text(wire.description),
|
|
196
|
+
photo: text(wire.photo),
|
|
197
|
+
paymentMethodId: wire.payment_method ?? null
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/http/cart.ts
|
|
202
|
+
var SHOPPER = { business: "required", customerOrSession: "required" };
|
|
203
|
+
function createCartApi(request) {
|
|
204
|
+
async function removeItem(lineId) {
|
|
205
|
+
await request("DELETE", `/order/cart/product/delete/${lineId}`, SHOPPER);
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
async get() {
|
|
209
|
+
return toCart(await request("GET", "/order/cart/get", SHOPPER));
|
|
210
|
+
},
|
|
211
|
+
async addItem({ skuId, quantity, customData }) {
|
|
212
|
+
checkQuantity(quantity, 1);
|
|
213
|
+
const json = { sku: skuId, qty: quantity };
|
|
214
|
+
if (customData) json.custom_data = customData;
|
|
215
|
+
const wire = await request("POST", "/order/cart/product/create", {
|
|
216
|
+
...SHOPPER,
|
|
217
|
+
json
|
|
218
|
+
});
|
|
219
|
+
return { lineId: wire.id };
|
|
220
|
+
},
|
|
221
|
+
async setQuantity(lineId, quantity) {
|
|
222
|
+
checkQuantity(quantity, 0);
|
|
223
|
+
if (quantity === 0) return removeItem(lineId);
|
|
224
|
+
await request("PATCH", `/order/cart/product/update/${lineId}`, {
|
|
225
|
+
...SHOPPER,
|
|
226
|
+
json: { qty: quantity }
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
removeItem,
|
|
230
|
+
async setOrderType(type) {
|
|
231
|
+
const wire = await request("PATCH", "/order/cart/type/update", {
|
|
232
|
+
...SHOPPER,
|
|
233
|
+
json: { type }
|
|
234
|
+
});
|
|
235
|
+
return {
|
|
236
|
+
subtotal: amount(wire.total_amount) ?? 0,
|
|
237
|
+
deliveryCharge: amount(wire.delivery_charge) ?? 0,
|
|
238
|
+
payable: amount(wire.final_payable_amount) ?? 0
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
async setAddresses({ shippingAddressId, billingAddressId }) {
|
|
242
|
+
if (shippingAddressId == null && billingAddressId == null) {
|
|
243
|
+
throw new TypeError("setAddresses: pass shippingAddressId, billingAddressId or both.");
|
|
244
|
+
}
|
|
245
|
+
const json = {};
|
|
246
|
+
if (shippingAddressId != null) json.shipping_address = shippingAddressId;
|
|
247
|
+
if (billingAddressId != null) json.billing_address = billingAddressId;
|
|
248
|
+
const wire = await request("PATCH", "/order/cart/address/update", {
|
|
249
|
+
business: "required",
|
|
250
|
+
customer: "required",
|
|
251
|
+
json
|
|
252
|
+
});
|
|
253
|
+
return {
|
|
254
|
+
shippingAddressId: wire.shipping_address ?? null,
|
|
255
|
+
billingAddressId: wire.billing_address ?? null
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
async applyOffer(offerId) {
|
|
259
|
+
const json = { offer: offerId };
|
|
260
|
+
await request("PATCH", "/order/cart/offer/update", { ...SHOPPER, json });
|
|
261
|
+
},
|
|
262
|
+
async applyPromoCode(promoCodeId) {
|
|
263
|
+
const json = { promo: promoCodeId };
|
|
264
|
+
await request("PATCH", "/order/cart/promo/update", { ...SHOPPER, json });
|
|
265
|
+
},
|
|
266
|
+
async setTaxDetails({ legalName, taxNumber }) {
|
|
267
|
+
const json = { legal_name: legalName, tax_number: taxNumber };
|
|
268
|
+
const wire = await request("PATCH", "/order/cart/tax/update", {
|
|
269
|
+
business: "required",
|
|
270
|
+
session: "required",
|
|
271
|
+
json
|
|
272
|
+
});
|
|
273
|
+
return { legalName: wire.legal_name, taxNumber: wire.tax_number };
|
|
274
|
+
},
|
|
275
|
+
async deliveryEstimate(cartId, options = {}) {
|
|
276
|
+
const wire = await request(
|
|
277
|
+
"GET",
|
|
278
|
+
`/order/cart/delivery/charge/info/get/${cartId}`,
|
|
279
|
+
// The backend calls Shiprocket synchronously; a blank pincode is left out.
|
|
280
|
+
{ ...SHOPPER, timeoutMs: 3e4, query: { pincode: options.pincode?.trim() } }
|
|
281
|
+
);
|
|
282
|
+
return {
|
|
283
|
+
deliveryCharge: amount(wire.delivery_charge) ?? 0,
|
|
284
|
+
payable: amount(wire.final_payable_amount) ?? 0,
|
|
285
|
+
estimatedDelivery: text(wire.estimate_delivery_day)
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function checkQuantity(quantity, min) {
|
|
291
|
+
if (!Number.isInteger(quantity) || quantity < min) {
|
|
292
|
+
throw new RangeError(`Cart quantity must be a whole number of at least ${min}: ${quantity}.`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function toCart(wire) {
|
|
296
|
+
const lines = (wire.products ?? []).map(toCartLine);
|
|
297
|
+
const orderOffer = amount(wire.offer_redeem_amount) ?? 0;
|
|
298
|
+
return {
|
|
299
|
+
id: wire.id,
|
|
300
|
+
type: wire.type,
|
|
301
|
+
lines,
|
|
302
|
+
subtotal: amount(wire.total_amount) ?? 0,
|
|
303
|
+
// The backend stores the offer amount on the order for order-level offers, or on each line
|
|
304
|
+
// for product, category and brand offers (never both).
|
|
305
|
+
offerDiscount: orderOffer > 0 ? orderOffer : sum(lines.map((line) => line.offerDiscount)),
|
|
306
|
+
promoDiscount: amount(wire.promo_redeem_amount) ?? 0,
|
|
307
|
+
deliveryCharge: amount(wire.delivery_charge) ?? 0,
|
|
308
|
+
payable: amount(wire.final_payable_amount) ?? 0,
|
|
309
|
+
deliveryChargeType: wire.delivery_charge_type ?? null,
|
|
310
|
+
offer: wire.offers ? { id: wire.offers.id, name: wire.offers.name, couponCode: text(wire.offers.coupon_code) } : null,
|
|
311
|
+
promoCode: wire.promo ? toAppliedPromoCode(wire.promo) : null,
|
|
312
|
+
shippingAddressId: idOf(wire.shipping_address),
|
|
313
|
+
billingAddressId: idOf(wire.billing_address),
|
|
314
|
+
advanceAmount: amount(wire.advance_amount)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function toCartLine(wire) {
|
|
318
|
+
const { sku } = wire;
|
|
319
|
+
const mrp = sku ? amount(sku.mrp) : null;
|
|
320
|
+
return {
|
|
321
|
+
id: wire.id,
|
|
322
|
+
skuId: sku?.id ?? null,
|
|
323
|
+
productId: sku?.product.id ?? null,
|
|
324
|
+
name: wire.label ?? wire.name ?? "",
|
|
325
|
+
photo: text(wire.photo),
|
|
326
|
+
unitPrice: amount(wire.price) ?? 0,
|
|
327
|
+
// An MRP of 0 means "not set", as in products.
|
|
328
|
+
mrp: mrp && mrp > 0 ? mrp : null,
|
|
329
|
+
quantity: wire.qty,
|
|
330
|
+
lineTotal: amount(wire.total) ?? 0,
|
|
331
|
+
offerDiscount: amount(wire.offer_redeem_amount) ?? 0,
|
|
332
|
+
taxPercent: amount(wire.tax),
|
|
333
|
+
maxQuantity: sku ? wire.max_qty : null,
|
|
334
|
+
isDigital: wire.is_digital_product,
|
|
335
|
+
fulfillmentMode: text(wire.fulfillment_mode) ?? "none",
|
|
336
|
+
customData: wire.custom_data ?? null,
|
|
337
|
+
variantIds: sku?.selected_variants ?? []
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function toAppliedPromoCode(wire) {
|
|
341
|
+
return {
|
|
342
|
+
id: wire.id,
|
|
343
|
+
code: wire.code ?? "",
|
|
344
|
+
type: wire.type ?? "percentage",
|
|
345
|
+
value: amount(wire.value) ?? 0
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function idOf(value) {
|
|
349
|
+
if (value == null) return null;
|
|
350
|
+
return typeof value === "number" ? value : value.id;
|
|
351
|
+
}
|
|
352
|
+
function sum(values) {
|
|
353
|
+
return Math.round(values.reduce((total, value) => total + value, 0) * 100) / 100;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// src/http/catalog.ts
|
|
357
|
+
var PUBLIC3 = { business: "required", anonymous: true };
|
|
358
|
+
function createCatalogApi(request) {
|
|
359
|
+
return {
|
|
360
|
+
async categories(options = {}) {
|
|
361
|
+
const search = options.search?.trim();
|
|
362
|
+
const wire = await request("GET", "/product/category/list", {
|
|
363
|
+
...PUBLIC3,
|
|
364
|
+
query: { search }
|
|
365
|
+
});
|
|
366
|
+
return wire.map(toCategoryTree);
|
|
367
|
+
},
|
|
368
|
+
async category(id) {
|
|
369
|
+
return toCategory2(
|
|
370
|
+
await request("GET", `/product/category/get/${id}`, {
|
|
371
|
+
anonymous: true
|
|
372
|
+
})
|
|
373
|
+
);
|
|
374
|
+
},
|
|
375
|
+
async categoriesByIds(ids) {
|
|
376
|
+
if (ids.length === 0) return [];
|
|
377
|
+
const wire = await request("GET", "/product/category/list/filter", {
|
|
378
|
+
...PUBLIC3,
|
|
379
|
+
query: { ids }
|
|
380
|
+
});
|
|
381
|
+
return wire.map(toCategory2);
|
|
382
|
+
},
|
|
383
|
+
async brands(options = {}) {
|
|
384
|
+
const wire = await request("GET", "/product/brand/list", {
|
|
385
|
+
...PUBLIC3,
|
|
386
|
+
query: { category_ids: options.categoryIds }
|
|
387
|
+
});
|
|
388
|
+
return wire.map(toBrand);
|
|
389
|
+
},
|
|
390
|
+
async settings() {
|
|
391
|
+
return toCatalogSettings(
|
|
392
|
+
await request("GET", "/product/business/setting/get", PUBLIC3)
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function toCategory2(wire) {
|
|
398
|
+
return {
|
|
399
|
+
id: wire.id,
|
|
400
|
+
name: wire.name,
|
|
401
|
+
description: text(wire.description),
|
|
402
|
+
photo: text(wire.photo),
|
|
403
|
+
parentId: wire.parent ?? null,
|
|
404
|
+
productCount: wire.product_count
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function toCategoryTree(wire) {
|
|
408
|
+
return { ...toCategory2(wire), children: wire.child.map(toCategoryTree) };
|
|
409
|
+
}
|
|
410
|
+
function toBrand(wire) {
|
|
411
|
+
return {
|
|
412
|
+
id: wire.id,
|
|
413
|
+
name: wire.name,
|
|
414
|
+
description: text(wire.description),
|
|
415
|
+
photo: text(wire.photo),
|
|
416
|
+
productCount: wire.product_count
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function toCatalogSettings(wire) {
|
|
420
|
+
return {
|
|
421
|
+
reviews: wire.is_active_review ?? true,
|
|
422
|
+
brands: wire.is_active_brand ?? true,
|
|
423
|
+
categories: wire.is_active_category ?? true,
|
|
424
|
+
subscriptions: wire.is_active_subscription ?? true,
|
|
425
|
+
digitalDelivery: wire.enable_digital_delivery ?? false,
|
|
426
|
+
variants: wire.is_active_variants ?? true,
|
|
427
|
+
specifications: wire.is_active_specification ?? true,
|
|
428
|
+
unitTracking: wire.has_product_unit_tracking_info ?? false,
|
|
429
|
+
manufactureAndExpiryDates: wire.has_mfg_expiry_date ?? false
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/http/faq.ts
|
|
434
|
+
var PUBLIC4 = { business: "required", anonymous: true };
|
|
435
|
+
var MERCHANT3 = { business: "required", merchant: true, anonymous: true };
|
|
436
|
+
function createFaqApi(request) {
|
|
437
|
+
return {
|
|
438
|
+
async list() {
|
|
439
|
+
return (await request("GET", "/content/faq/list", PUBLIC4)).map(toFaq);
|
|
440
|
+
},
|
|
441
|
+
async create(input) {
|
|
442
|
+
const json = { question: input.question, answer: input.answer };
|
|
443
|
+
return toFaq(await request("POST", "/content/faq/create", { ...MERCHANT3, json }));
|
|
444
|
+
},
|
|
445
|
+
async update(id, changes) {
|
|
446
|
+
const json = {};
|
|
447
|
+
if (changes.question !== void 0) json.question = changes.question;
|
|
448
|
+
if (changes.answer !== void 0) json.answer = changes.answer;
|
|
449
|
+
return toFaq(
|
|
450
|
+
await request("PATCH", `/content/faq/update/${id}`, { ...MERCHANT3, json })
|
|
451
|
+
);
|
|
452
|
+
},
|
|
453
|
+
async move(id, direction) {
|
|
454
|
+
const json = { direction };
|
|
455
|
+
await request("PATCH", `/content/faq/update/${id}`, { ...MERCHANT3, json });
|
|
456
|
+
},
|
|
457
|
+
async remove(id) {
|
|
458
|
+
await request("DELETE", `/content/faq/delete/${id}`, MERCHANT3);
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function toFaq(wire) {
|
|
463
|
+
return {
|
|
464
|
+
id: wire.id,
|
|
465
|
+
question: text(wire.question),
|
|
466
|
+
answer: text(wire.answer),
|
|
467
|
+
displayOrder: wire.display_order
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// src/http/forms.ts
|
|
472
|
+
var PUBLIC5 = { anonymous: true, business: "required" };
|
|
473
|
+
var SUBMIT = { business: "required" };
|
|
474
|
+
var MERCHANT4 = { merchant: true, anonymous: true, business: "required" };
|
|
475
|
+
function createFormsApi(request) {
|
|
476
|
+
return {
|
|
477
|
+
async get(slug) {
|
|
478
|
+
return toPublicForm(
|
|
479
|
+
await request("GET", `/forms/public/${path2(slug)}`, PUBLIC5)
|
|
480
|
+
);
|
|
481
|
+
},
|
|
482
|
+
async submit(slug, values) {
|
|
483
|
+
const json = { data: values };
|
|
484
|
+
await request("POST", `/forms/submit/${path2(slug)}`, { ...SUBMIT, json });
|
|
485
|
+
},
|
|
486
|
+
async listForMerchant() {
|
|
487
|
+
const rows = await request("GET", "/forms/list", {
|
|
488
|
+
...MERCHANT4,
|
|
489
|
+
query: { is_active: true }
|
|
490
|
+
});
|
|
491
|
+
return rows.map(toFormSummary);
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function path2(slug) {
|
|
496
|
+
if (!slug.trim()) throw new Error("forms: slug is required.");
|
|
497
|
+
return encodeURIComponent(slug.trim());
|
|
498
|
+
}
|
|
499
|
+
function toPublicForm(wire) {
|
|
500
|
+
const fields = Array.isArray(wire.field_configuration) ? wire.field_configuration : [];
|
|
501
|
+
return {
|
|
502
|
+
id: wire.id,
|
|
503
|
+
slug: wire.slug,
|
|
504
|
+
name: wire.name,
|
|
505
|
+
description: text(wire.description),
|
|
506
|
+
successMessage: text(wire.success_message),
|
|
507
|
+
fields: fields.map(toFormField)
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
function toFormSummary(wire) {
|
|
511
|
+
return { id: wire.id, name: wire.name, slug: wire.slug };
|
|
512
|
+
}
|
|
513
|
+
function toFormField(wire) {
|
|
514
|
+
return {
|
|
515
|
+
name: wire.name,
|
|
516
|
+
// The backend only saves the ten known types (`validation.py:4-7`).
|
|
517
|
+
type: wire.type,
|
|
518
|
+
required: wire.required,
|
|
519
|
+
label: text(wire.label) ?? wire.name.replace(/_/g, " "),
|
|
520
|
+
options: wire.options?.map((o) => ({ label: o.label, value: o.value })) ?? []
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/http/helpdesk.ts
|
|
525
|
+
var CREATE = { business: "required" };
|
|
526
|
+
function createHelpdeskApi(request) {
|
|
527
|
+
return {
|
|
528
|
+
async createInquiry(input) {
|
|
529
|
+
const title = input.subject.trim();
|
|
530
|
+
const description = input.message.trim();
|
|
531
|
+
if (!title || !description) {
|
|
532
|
+
throw new Error("helpdesk.createInquiry: subject and message are required.");
|
|
533
|
+
}
|
|
534
|
+
const json = { title, description };
|
|
535
|
+
const name = input.name?.trim();
|
|
536
|
+
const email = input.email?.trim();
|
|
537
|
+
const phone = input.phone?.trim();
|
|
538
|
+
if (name) json.name = name;
|
|
539
|
+
if (email) json.email = email;
|
|
540
|
+
if (phone) json.phone_number = phone;
|
|
541
|
+
await request("POST", "/helpdesk/inquiry/web/create", { ...CREATE, json });
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/http/newsletter.ts
|
|
547
|
+
var PUBLIC6 = { anonymous: true, business: "required" };
|
|
548
|
+
function createNewsletterApi(request) {
|
|
549
|
+
return {
|
|
550
|
+
async subscribe(email) {
|
|
551
|
+
const json = { email: required(email, "email") };
|
|
552
|
+
await request("POST", "/subscribers/create/email", {
|
|
553
|
+
...PUBLIC6,
|
|
554
|
+
json
|
|
555
|
+
});
|
|
556
|
+
},
|
|
557
|
+
async verify(email, otp) {
|
|
558
|
+
const json = { email: required(email, "email"), otp: required(otp, "otp") };
|
|
559
|
+
await request("PATCH", "/subscribers/email/verify", {
|
|
560
|
+
...PUBLIC6,
|
|
561
|
+
json
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
function required(value, name) {
|
|
567
|
+
const trimmed = value.trim();
|
|
568
|
+
if (!trimmed) throw new Error(`newsletter: ${name} is required.`);
|
|
569
|
+
return trimmed;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/http/live-support.ts
|
|
573
|
+
var PUBLIC7 = { anonymous: true, business: "required" };
|
|
574
|
+
function createLiveSupportApi(request) {
|
|
575
|
+
return {
|
|
576
|
+
async widget() {
|
|
577
|
+
return toLiveSupportWidget(
|
|
578
|
+
await request(
|
|
579
|
+
"GET",
|
|
580
|
+
"/website/live-support-widget/config/get",
|
|
581
|
+
PUBLIC7
|
|
582
|
+
)
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
function toLiveSupportWidget(wire) {
|
|
588
|
+
const number = text(wire.whatsapp_no)?.trim();
|
|
589
|
+
if (!wire.is_active || !number) return null;
|
|
590
|
+
return { channel: "whatsapp", whatsappNumber: number };
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/http/policies.ts
|
|
594
|
+
var TYPES = {
|
|
595
|
+
privacy_policy: "privacy",
|
|
596
|
+
terms_of_use: "terms-of-use",
|
|
597
|
+
cancellations_refunds_policy: "cancellation-refund",
|
|
598
|
+
shipping_policy: "shipping",
|
|
599
|
+
warranty_policy: "warranty"
|
|
600
|
+
};
|
|
601
|
+
var WIRE_TYPES = Object.fromEntries(
|
|
602
|
+
Object.entries(TYPES).map(([wire, type]) => [type, wire])
|
|
603
|
+
);
|
|
604
|
+
var PUBLIC8 = { business: "required", anonymous: true };
|
|
605
|
+
var MERCHANT5 = { merchant: true, anonymous: true };
|
|
606
|
+
function createPoliciesApi(request) {
|
|
607
|
+
return {
|
|
608
|
+
async list(options = {}) {
|
|
609
|
+
const wire = await request("GET", "/policy_and_terms/list", {
|
|
610
|
+
...PUBLIC8,
|
|
611
|
+
query: { type: options.type && WIRE_TYPES[options.type] }
|
|
612
|
+
});
|
|
613
|
+
return wire.map(toPolicy).filter((p) => p !== null);
|
|
614
|
+
},
|
|
615
|
+
async create(input) {
|
|
616
|
+
const wire = await request("POST", "/policy_and_terms/create", {
|
|
617
|
+
...MERCHANT5,
|
|
618
|
+
business: "required",
|
|
619
|
+
json: toWrite(input)
|
|
620
|
+
});
|
|
621
|
+
return required2(wire);
|
|
622
|
+
},
|
|
623
|
+
async createMany(inputs) {
|
|
624
|
+
if (inputs.length === 0) return [];
|
|
625
|
+
const wire = await request("POST", "/policy_and_terms/bulk/create", {
|
|
626
|
+
...MERCHANT5,
|
|
627
|
+
json: inputs.map(toWrite)
|
|
628
|
+
});
|
|
629
|
+
return wire.map(required2);
|
|
630
|
+
},
|
|
631
|
+
async update(id, changes) {
|
|
632
|
+
const wire = await request("PUT", `/policy_and_terms/update/${id}`, {
|
|
633
|
+
...MERCHANT5,
|
|
634
|
+
json: toWrite(changes)
|
|
635
|
+
});
|
|
636
|
+
return required2(wire);
|
|
637
|
+
},
|
|
638
|
+
async move(id, direction) {
|
|
639
|
+
const body = { direction };
|
|
640
|
+
await request("PUT", `/policy_and_terms/update/${id}`, {
|
|
641
|
+
...MERCHANT5,
|
|
642
|
+
json: body
|
|
643
|
+
});
|
|
644
|
+
},
|
|
645
|
+
async remove(id) {
|
|
646
|
+
await request("DELETE", `/policy_and_terms/delete/${id}`, MERCHANT5);
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function toWrite(input) {
|
|
651
|
+
const body = {};
|
|
652
|
+
if (input.type !== void 0) body.type = WIRE_TYPES[input.type];
|
|
653
|
+
if (input.heading !== void 0) body.heading = input.heading;
|
|
654
|
+
if (input.description !== void 0) body.description = input.description;
|
|
655
|
+
return body;
|
|
656
|
+
}
|
|
657
|
+
var required2 = (wire) => toPolicy(wire);
|
|
658
|
+
function toPolicy(wire) {
|
|
659
|
+
const type = TYPES[wire.type];
|
|
660
|
+
if (!type) return null;
|
|
661
|
+
return {
|
|
662
|
+
id: wire.id,
|
|
663
|
+
type,
|
|
664
|
+
heading: wire.heading,
|
|
665
|
+
description: text(wire.description),
|
|
666
|
+
displayOrder: wire.display_order
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/http/productPage.ts
|
|
671
|
+
var PUBLIC9 = { business: "required", anonymous: true };
|
|
672
|
+
var MERCHANT6 = { merchant: true, business: "required", anonymous: true };
|
|
673
|
+
function targetFields(target) {
|
|
674
|
+
if (target === void 0) return {};
|
|
675
|
+
if (target === "all") return { selected_variants: [], variant: null };
|
|
676
|
+
if ("variantId" in target) return { variant: target.variantId };
|
|
677
|
+
return { selected_variants: target.variantIds, variant: null };
|
|
678
|
+
}
|
|
679
|
+
function createProductPageApi(request) {
|
|
680
|
+
const sentItem = (wire, target) => {
|
|
681
|
+
const item = toProductSectionItem(wire);
|
|
682
|
+
if (wire.sku != null && typeof target === "object" && "variantIds" in target) {
|
|
683
|
+
item.target = { skuId: wire.sku, variantIds: [...target.variantIds] };
|
|
684
|
+
}
|
|
685
|
+
return item;
|
|
686
|
+
};
|
|
687
|
+
return {
|
|
688
|
+
async sections(productId) {
|
|
689
|
+
const wire = await request(
|
|
690
|
+
"GET",
|
|
691
|
+
`/product/detail/list/${productId}`,
|
|
692
|
+
PUBLIC9
|
|
693
|
+
);
|
|
694
|
+
return wire.map(toProductSection);
|
|
695
|
+
},
|
|
696
|
+
async blocks(productId, options = {}) {
|
|
697
|
+
const wire = await request("GET", `/product/content/list/${productId}`, {
|
|
698
|
+
...PUBLIC9,
|
|
699
|
+
query: { slug: options.slug }
|
|
700
|
+
});
|
|
701
|
+
return wire.map(toProductBlock);
|
|
702
|
+
},
|
|
703
|
+
async createSection({ productId, title }) {
|
|
704
|
+
return toProductSection(
|
|
705
|
+
await request("POST", "/product/detail/create", {
|
|
706
|
+
...MERCHANT6,
|
|
707
|
+
json: { product: productId, title }
|
|
708
|
+
})
|
|
709
|
+
);
|
|
710
|
+
},
|
|
711
|
+
async deleteSection(id) {
|
|
712
|
+
await request("DELETE", `/product/detail/delete/${id}`, MERCHANT6);
|
|
713
|
+
},
|
|
714
|
+
async addSectionItem({ sectionId, data, target }) {
|
|
715
|
+
const wire = await request("POST", "/product/detail/content/create", {
|
|
716
|
+
...MERCHANT6,
|
|
717
|
+
json: { product_detail: sectionId, data, ...targetFields(target) }
|
|
718
|
+
});
|
|
719
|
+
return sentItem(wire, target);
|
|
720
|
+
},
|
|
721
|
+
async updateSectionItem(id, { sectionId, data, target }) {
|
|
722
|
+
const wire = await request(
|
|
723
|
+
"PATCH",
|
|
724
|
+
`/product/detail/content/update/${id}`,
|
|
725
|
+
{
|
|
726
|
+
...MERCHANT6,
|
|
727
|
+
json: {
|
|
728
|
+
product_detail: sectionId,
|
|
729
|
+
...data === void 0 ? {} : { data },
|
|
730
|
+
...targetFields(target)
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
);
|
|
734
|
+
return sentItem(wire, target);
|
|
735
|
+
},
|
|
736
|
+
async moveSectionItem(id, direction) {
|
|
737
|
+
await request("PATCH", `/product/detail/content/update/${id}`, {
|
|
738
|
+
...MERCHANT6,
|
|
739
|
+
json: { direction }
|
|
740
|
+
});
|
|
741
|
+
},
|
|
742
|
+
async deleteSectionItem(id) {
|
|
743
|
+
await request("DELETE", `/product/detail/content/delete/${id}`, MERCHANT6);
|
|
744
|
+
},
|
|
745
|
+
async createBlock({ productId, slug, data }) {
|
|
746
|
+
return toProductBlock(
|
|
747
|
+
await request("POST", "/product/content/create", {
|
|
748
|
+
...MERCHANT6,
|
|
749
|
+
json: { product: productId, slug, data }
|
|
750
|
+
})
|
|
751
|
+
);
|
|
752
|
+
},
|
|
753
|
+
async updateBlock(id, { slug, data }) {
|
|
754
|
+
return toProductBlock(
|
|
755
|
+
await request("PATCH", `/product/content/update/${id}`, {
|
|
756
|
+
...MERCHANT6,
|
|
757
|
+
json: { slug, data }
|
|
758
|
+
})
|
|
759
|
+
);
|
|
760
|
+
},
|
|
761
|
+
async deleteBlock(id) {
|
|
762
|
+
await request("DELETE", `/product/content/delete/${id}`, MERCHANT6);
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function toTarget(wire) {
|
|
767
|
+
if (wire.sku != null) {
|
|
768
|
+
const variants = wire.selected_variants ?? [];
|
|
769
|
+
return { skuId: wire.sku, variantIds: variants.length ? variants.map((v) => v.id) : null };
|
|
770
|
+
}
|
|
771
|
+
if (wire.variant != null) return { variantId: wire.variant };
|
|
772
|
+
return "all";
|
|
773
|
+
}
|
|
774
|
+
function toProductSectionItem(wire) {
|
|
775
|
+
return {
|
|
776
|
+
id: wire.id,
|
|
777
|
+
sectionId: wire.product_detail,
|
|
778
|
+
data: wire.data ?? null,
|
|
779
|
+
order: wire.display_order,
|
|
780
|
+
target: toTarget(wire)
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
function toProductSection(wire) {
|
|
784
|
+
return {
|
|
785
|
+
id: wire.id,
|
|
786
|
+
productId: wire.product,
|
|
787
|
+
title: wire.title,
|
|
788
|
+
// Already ordered by the backend; sorted again so the order never depends on it.
|
|
789
|
+
items: [...wire.content].sort((a, b) => a.display_order - b.display_order).map(toProductSectionItem)
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
function toProductBlock(wire) {
|
|
793
|
+
return {
|
|
794
|
+
id: wire.id,
|
|
795
|
+
productId: wire.product,
|
|
796
|
+
slug: wire.slug,
|
|
797
|
+
data: wire.data ?? null,
|
|
798
|
+
order: wire.display_order
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/http/products.ts
|
|
803
|
+
var DEFAULT_LIMIT = 20;
|
|
804
|
+
var SORT = {
|
|
805
|
+
"price-low-to-high": "low_to_high",
|
|
806
|
+
"price-high-to-low": "high_to_low",
|
|
807
|
+
newest: "newest_first",
|
|
808
|
+
popularity: "popularity",
|
|
809
|
+
category: "category"
|
|
810
|
+
};
|
|
811
|
+
var PUBLIC10 = { business: "required", anonymous: true };
|
|
812
|
+
function createProductsApi(request) {
|
|
813
|
+
return {
|
|
814
|
+
async search(options = {}) {
|
|
815
|
+
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
816
|
+
const offset = options.offset ?? 0;
|
|
817
|
+
const page = await request(
|
|
818
|
+
"GET",
|
|
819
|
+
"/product/sku/list/search",
|
|
820
|
+
{
|
|
821
|
+
...PUBLIC10,
|
|
822
|
+
session: "required",
|
|
823
|
+
query: {
|
|
824
|
+
status: "available",
|
|
825
|
+
search: options.search?.trim(),
|
|
826
|
+
category_ids: options.categoryIds,
|
|
827
|
+
brand_ids: options.brandIds,
|
|
828
|
+
variants: options.variantLabels,
|
|
829
|
+
specifications: options.specifications?.length ? JSON.stringify(options.specifications) : void 0,
|
|
830
|
+
min_price: options.minPrice,
|
|
831
|
+
max_price: options.maxPrice,
|
|
832
|
+
min_discount: options.minDiscountPercent,
|
|
833
|
+
min_rating: options.minRating,
|
|
834
|
+
sort_by: options.sortBy ? SORT[options.sortBy] : void 0,
|
|
835
|
+
limit,
|
|
836
|
+
offset
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
);
|
|
840
|
+
return { items: page.results.map(toProductListItem), total: page.count, offset, limit };
|
|
841
|
+
},
|
|
842
|
+
async list(options = {}) {
|
|
843
|
+
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
844
|
+
const offset = options.offset ?? 0;
|
|
845
|
+
const page = await request("GET", "/product/base/list", {
|
|
846
|
+
...PUBLIC10,
|
|
847
|
+
// The backend does not hide drafts here by itself; the old storefront never asked it to.
|
|
848
|
+
query: {
|
|
849
|
+
status: "available",
|
|
850
|
+
ids: options.ids,
|
|
851
|
+
category_ids: options.categoryIds,
|
|
852
|
+
limit,
|
|
853
|
+
offset
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
return { items: page.results.map(toProductOverview), total: page.count, offset, limit };
|
|
857
|
+
},
|
|
858
|
+
async detail(id) {
|
|
859
|
+
return toProductDetail(
|
|
860
|
+
await request("GET", `/product/details/${id}`, PUBLIC10)
|
|
861
|
+
);
|
|
862
|
+
},
|
|
863
|
+
async filterConfig(options = {}) {
|
|
864
|
+
const wire = await request("GET", "/product/filter/config", {
|
|
865
|
+
...PUBLIC10,
|
|
866
|
+
query: { category: options.categoryId }
|
|
867
|
+
});
|
|
868
|
+
return {
|
|
869
|
+
price: { min: wire.price.min, max: wire.price.max },
|
|
870
|
+
specifications: wire.specifications.map((s) => ({
|
|
871
|
+
id: s.id,
|
|
872
|
+
name: s.name,
|
|
873
|
+
type: s.data_type,
|
|
874
|
+
options: s.options
|
|
875
|
+
}))
|
|
876
|
+
};
|
|
877
|
+
},
|
|
878
|
+
async variantFilters(categoryIds) {
|
|
879
|
+
if (categoryIds.length === 0) return [];
|
|
880
|
+
const wire = await request("GET", "/product/category/filter/variant", {
|
|
881
|
+
...PUBLIC10,
|
|
882
|
+
query: { category_ids: categoryIds }
|
|
883
|
+
});
|
|
884
|
+
return wire.map(toVariantGroup);
|
|
885
|
+
},
|
|
886
|
+
async suggestions(query) {
|
|
887
|
+
const word = query.trim();
|
|
888
|
+
if (!word) return [];
|
|
889
|
+
const wire = await request(
|
|
890
|
+
"GET",
|
|
891
|
+
`/product/search/${encodeURIComponent(word)}`,
|
|
892
|
+
PUBLIC10
|
|
893
|
+
);
|
|
894
|
+
return wire.map(
|
|
895
|
+
(s) => s.type === "product" ? {
|
|
896
|
+
type: "product",
|
|
897
|
+
id: s.id,
|
|
898
|
+
name: s.name,
|
|
899
|
+
categoryName: text(s.category),
|
|
900
|
+
image: text(s.image)
|
|
901
|
+
} : { type: "category", id: s.id, name: s.name }
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
var mrpOf = (value) => {
|
|
907
|
+
const n = amount(value);
|
|
908
|
+
return n && n > 0 ? n : null;
|
|
909
|
+
};
|
|
910
|
+
function toVariantGroup(wire) {
|
|
911
|
+
return {
|
|
912
|
+
id: wire.variant_type.id,
|
|
913
|
+
name: wire.variant_type.type,
|
|
914
|
+
options: wire.variants.filter((v) => !v.deleted).map((v) => ({ id: v.id, label: v.label, available: v.sku_available ?? true }))
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
function toSku(wire) {
|
|
918
|
+
return {
|
|
919
|
+
id: wire.id,
|
|
920
|
+
code: wire.sku,
|
|
921
|
+
slug: wire.url_slug,
|
|
922
|
+
price: amount(wire.selling_price) ?? 0,
|
|
923
|
+
mrp: mrpOf(wire.mrp),
|
|
924
|
+
stockQty: wire.stock_qty ?? 0,
|
|
925
|
+
active: wire.is_active !== false,
|
|
926
|
+
variantIds: wire.selected_variants ?? []
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
function toImage(wire) {
|
|
930
|
+
return {
|
|
931
|
+
id: wire.id,
|
|
932
|
+
url: wire.photo,
|
|
933
|
+
originalUrl: text(wire.original_photo),
|
|
934
|
+
variantId: wire.variant ?? null,
|
|
935
|
+
order: wire.display_order
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
var liveSkus = (skus) => skus.filter((s) => !s.deleted && !s.invalid);
|
|
939
|
+
var liveImages = (images) => images.filter((i) => !i.deleted).sort((a, b) => a.display_order - b.display_order);
|
|
940
|
+
function toProductListItem(wire) {
|
|
941
|
+
const tax = amount(wire.tax);
|
|
942
|
+
return {
|
|
943
|
+
skuId: wire.id,
|
|
944
|
+
productId: wire.product,
|
|
945
|
+
name: wire.name,
|
|
946
|
+
slug: wire.url_slug,
|
|
947
|
+
skuCode: wire.sku,
|
|
948
|
+
photos: wire.photo,
|
|
949
|
+
price: amount(wire.selling_price) ?? 0,
|
|
950
|
+
mrp: mrpOf(wire.mrp),
|
|
951
|
+
stockQty: wire.stock_qty ?? 0,
|
|
952
|
+
taxPercent: tax,
|
|
953
|
+
unit: text(wire.unit),
|
|
954
|
+
variantGroups: (wire.variant ?? []).map(toVariantGroup),
|
|
955
|
+
selectedVariantIds: wire.selected_variants,
|
|
956
|
+
fulfillmentMode: wire.fulfillment_mode,
|
|
957
|
+
hasDigitalDelivery: wire.has_digital_delivery,
|
|
958
|
+
advanceAmount: amount(wire.advance_amount)
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
function toSpecifications(wire) {
|
|
962
|
+
return Object.entries(wire ?? {}).map(([name, items]) => ({
|
|
963
|
+
name: text(name),
|
|
964
|
+
items: items.filter((i) => !i.deleted && i.key).map((i) => ({
|
|
965
|
+
key: i.key.name,
|
|
966
|
+
value: i.value,
|
|
967
|
+
appliesTo: i.sku ? { type: "sku", skuId: i.sku.id } : i.variant ? { type: "variant", variantId: i.variant.id } : { type: "all" }
|
|
968
|
+
}))
|
|
969
|
+
})).filter((g) => g.items.length > 0);
|
|
970
|
+
}
|
|
971
|
+
function toProductDetail(wire) {
|
|
972
|
+
const policies = wire.product_policies;
|
|
973
|
+
return {
|
|
974
|
+
id: wire.id,
|
|
975
|
+
name: wire.name,
|
|
976
|
+
slug: wire.url_slug,
|
|
977
|
+
description: text(wire.description),
|
|
978
|
+
descriptionFormat: text(wire.description_editor_type),
|
|
979
|
+
categoryId: wire.category ?? null,
|
|
980
|
+
categoryName: text(wire.category_name),
|
|
981
|
+
brandId: wire.brand ?? null,
|
|
982
|
+
taxPercent: amount(wire.tax_percent),
|
|
983
|
+
rating: wire.rating ?? 0,
|
|
984
|
+
reviewCount: wire.total_review ?? 0,
|
|
985
|
+
hasVariants: wire.has_variant ?? (wire.variant ?? []).length > 0,
|
|
986
|
+
images: liveImages(wire.images).map(toImage),
|
|
987
|
+
variantGroups: (wire.variant ?? []).map(toVariantGroup),
|
|
988
|
+
skus: liveSkus(wire.sku).map(toSku),
|
|
989
|
+
specifications: toSpecifications(wire.specification),
|
|
990
|
+
policies: policies ? {
|
|
991
|
+
returnDays: policies.return_days,
|
|
992
|
+
replacementDays: policies.replacement_days,
|
|
993
|
+
exchangeDays: policies.exchange_days,
|
|
994
|
+
exchangeEnabled: policies.exchange_enabled,
|
|
995
|
+
warrantyMonths: policies.warranty_months,
|
|
996
|
+
guaranteeMonths: policies.guarantee_months
|
|
997
|
+
} : null,
|
|
998
|
+
availableForSubscription: wire.available_for_subscription ?? false,
|
|
999
|
+
hasDigitalDelivery: wire.has_digital_delivery ?? false,
|
|
1000
|
+
fulfillmentMode: wire.fulfillment_mode ?? "none",
|
|
1001
|
+
advanceAmount: amount(wire.advance_amount)
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
function toProductOverview(wire) {
|
|
1005
|
+
return {
|
|
1006
|
+
id: wire.id,
|
|
1007
|
+
name: wire.name,
|
|
1008
|
+
slug: wire.url_slug,
|
|
1009
|
+
categoryName: text(wire.category_name),
|
|
1010
|
+
images: liveImages(wire.images).map(toImage),
|
|
1011
|
+
variantGroups: (wire.variant ?? []).map(toVariantGroup),
|
|
1012
|
+
skus: liveSkus(wire.sku).map(toSku),
|
|
1013
|
+
priceFrom: amount(wire.starting_from),
|
|
1014
|
+
unit: text(wire.unit)
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// src/http/errors.ts
|
|
1019
|
+
var GrowupsellApiError = class extends Error {
|
|
1020
|
+
kind;
|
|
1021
|
+
/** HTTP status; undefined when no response arrived (network, timeout). */
|
|
1022
|
+
status;
|
|
1023
|
+
/** Validation messages per field, as returned by the backend (`non_field_errors` included). */
|
|
1024
|
+
fieldErrors;
|
|
1025
|
+
/** The parsed response body, for anything the fields above don't cover. */
|
|
1026
|
+
body;
|
|
1027
|
+
constructor(init) {
|
|
1028
|
+
super(init.message);
|
|
1029
|
+
this.name = "GrowupsellApiError";
|
|
1030
|
+
this.kind = init.kind;
|
|
1031
|
+
this.status = init.status;
|
|
1032
|
+
this.fieldErrors = init.fieldErrors ?? {};
|
|
1033
|
+
this.body = init.body;
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
function messageFromBody(body) {
|
|
1037
|
+
if (typeof body === "string") {
|
|
1038
|
+
const text2 = body.trim();
|
|
1039
|
+
return text2 && !text2.startsWith("<") ? text2 : void 0;
|
|
1040
|
+
}
|
|
1041
|
+
if (Array.isArray(body)) return body.length > 0 ? messageFromBody(body[0]) : void 0;
|
|
1042
|
+
if (body && typeof body === "object") {
|
|
1043
|
+
const record = body;
|
|
1044
|
+
for (const key of ["detail", "message"]) {
|
|
1045
|
+
if (typeof record[key] === "string" && record[key]) return record[key];
|
|
1046
|
+
}
|
|
1047
|
+
for (const value of Object.values(record)) {
|
|
1048
|
+
if (typeof value === "boolean" || typeof value === "number" || value == null) continue;
|
|
1049
|
+
const found = messageFromBody(value);
|
|
1050
|
+
if (found) return found;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
return void 0;
|
|
1054
|
+
}
|
|
1055
|
+
function fieldErrorsFromBody(body) {
|
|
1056
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return {};
|
|
1057
|
+
const errors = {};
|
|
1058
|
+
for (const [field, value] of Object.entries(body)) {
|
|
1059
|
+
if (field === "detail" || field === "message") continue;
|
|
1060
|
+
if (typeof value === "string") errors[field] = [value];
|
|
1061
|
+
else if (Array.isArray(value) && value.length > 0 && value.every((v) => typeof v === "string")) {
|
|
1062
|
+
errors[field] = value;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
return errors;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// src/http/promotions.ts
|
|
1069
|
+
var DEFAULT_LIMIT2 = 20;
|
|
1070
|
+
var PUBLIC_BUSINESS = { anonymous: true, business: "required" };
|
|
1071
|
+
var SHOPPER2 = { business: "required", customerOrSession: "required" };
|
|
1072
|
+
function createPromotionsApi(request) {
|
|
1073
|
+
return {
|
|
1074
|
+
async offers(options = {}) {
|
|
1075
|
+
const limit = options.limit ?? DEFAULT_LIMIT2;
|
|
1076
|
+
const offset = options.offset ?? 0;
|
|
1077
|
+
const page = await request("GET", "/offer/list", {
|
|
1078
|
+
...PUBLIC_BUSINESS,
|
|
1079
|
+
query: { limit, offset }
|
|
1080
|
+
});
|
|
1081
|
+
return { items: page.results.map(toOffer), total: page.count, offset, limit };
|
|
1082
|
+
},
|
|
1083
|
+
async eligibleOffers() {
|
|
1084
|
+
const wire = await request("GET", "/offer/eligibility/list", SHOPPER2);
|
|
1085
|
+
return wire.map(toOffer);
|
|
1086
|
+
},
|
|
1087
|
+
async promoCode(code) {
|
|
1088
|
+
const normalized = code.trim().toUpperCase();
|
|
1089
|
+
if (!normalized) return null;
|
|
1090
|
+
try {
|
|
1091
|
+
const wire = await request("GET", "/promocode/get", {
|
|
1092
|
+
...SHOPPER2,
|
|
1093
|
+
query: { code: normalized }
|
|
1094
|
+
});
|
|
1095
|
+
return toPromoCode(wire);
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
if (isNotFoundJson(error)) return null;
|
|
1098
|
+
throw error;
|
|
1099
|
+
}
|
|
1100
|
+
},
|
|
1101
|
+
async validateGiftCard({ code, pin }) {
|
|
1102
|
+
const wire = await request("POST", "/giftcard/validate", {
|
|
1103
|
+
business: "required",
|
|
1104
|
+
json: { code: code.trim(), pin: pin.trim() }
|
|
1105
|
+
});
|
|
1106
|
+
return toGiftCard(wire);
|
|
1107
|
+
},
|
|
1108
|
+
async rewardPointSettings() {
|
|
1109
|
+
return toRewardPointSettings(
|
|
1110
|
+
await request(
|
|
1111
|
+
"GET",
|
|
1112
|
+
"/reward_points/business/setting/get",
|
|
1113
|
+
PUBLIC_BUSINESS
|
|
1114
|
+
)
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
function isNotFoundJson(error) {
|
|
1120
|
+
return error instanceof GrowupsellApiError && error.status === 404 && typeof error.body === "object" && error.body !== null;
|
|
1121
|
+
}
|
|
1122
|
+
function toOffer(wire) {
|
|
1123
|
+
return {
|
|
1124
|
+
id: wire.id,
|
|
1125
|
+
name: wire.name,
|
|
1126
|
+
description: text(wire.description),
|
|
1127
|
+
image: text(wire.image),
|
|
1128
|
+
type: wire.type ?? "percentage",
|
|
1129
|
+
percentOff: amount(wire.percentage_of) ?? 0,
|
|
1130
|
+
amountOff: amount(wire.discount_upto_price) ?? 0,
|
|
1131
|
+
minOrderAmount: amount(wire.min_order_amount) ?? 0,
|
|
1132
|
+
startsAt: wire.start_date ?? "",
|
|
1133
|
+
endsAt: wire.end_date ?? "",
|
|
1134
|
+
couponCode: text(wire.coupon_code),
|
|
1135
|
+
scope: wire.only_for ?? "order",
|
|
1136
|
+
isActive: wire.is_active ?? false
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
function toPromoCode(wire) {
|
|
1140
|
+
return {
|
|
1141
|
+
id: wire.id,
|
|
1142
|
+
code: wire.code ?? "",
|
|
1143
|
+
description: text(wire.description),
|
|
1144
|
+
type: wire.type ?? "percentage",
|
|
1145
|
+
value: amount(wire.value) ?? 0,
|
|
1146
|
+
expiresAt: wire.expire_date,
|
|
1147
|
+
status: wire.status
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
function toGiftCard(wire) {
|
|
1151
|
+
return {
|
|
1152
|
+
id: wire.id,
|
|
1153
|
+
code: wire.code,
|
|
1154
|
+
amount: amount(wire.amount) ?? 0,
|
|
1155
|
+
usedAmount: amount(wire.used_amount) ?? 0,
|
|
1156
|
+
issuedAt: wire.created_at
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
function toRewardPointSettings(wire) {
|
|
1160
|
+
return {
|
|
1161
|
+
// Points work on orders only when both switches are on.
|
|
1162
|
+
enabled: !!wire.is_active && !!wire.is_active_order_reward,
|
|
1163
|
+
pointsPerCurrencyUnit: amount(wire.order_credit_multiplier) ?? 0,
|
|
1164
|
+
currencyPerPoint: amount(wire.order_debit_multiplier) ?? 0,
|
|
1165
|
+
signupPoints: amount(wire.signup_points) ?? 0
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// src/http/multipart.ts
|
|
1170
|
+
var runtime = globalThis;
|
|
1171
|
+
function multipart(fields, files, caller = "This upload") {
|
|
1172
|
+
if (!runtime.FormData) {
|
|
1173
|
+
throw new Error(`${caller}: sending a file needs FormData, which this runtime lacks.`);
|
|
1174
|
+
}
|
|
1175
|
+
const form = new runtime.FormData();
|
|
1176
|
+
for (const [name, value] of Object.entries(fields)) {
|
|
1177
|
+
if (value !== void 0) form.append(name, String(value));
|
|
1178
|
+
}
|
|
1179
|
+
for (const [name, entry] of Object.entries(files)) {
|
|
1180
|
+
if (!entry) continue;
|
|
1181
|
+
if (entry.fileName === void 0) form.append(name, entry.file);
|
|
1182
|
+
else form.append(name, entry.file, entry.fileName);
|
|
1183
|
+
}
|
|
1184
|
+
return form;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// src/http/reviews.ts
|
|
1188
|
+
var DEFAULT_LIMIT3 = 20;
|
|
1189
|
+
var PUBLIC11 = { anonymous: true };
|
|
1190
|
+
var PUBLIC_BUSINESS2 = { anonymous: true, business: "required" };
|
|
1191
|
+
var CUSTOMER = { customer: "required" };
|
|
1192
|
+
function createReviewsApi(request) {
|
|
1193
|
+
function body(fields, photo) {
|
|
1194
|
+
if (photo === void 0) {
|
|
1195
|
+
return {
|
|
1196
|
+
json: Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== void 0))
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
return { formData: multipart(fields, { photo: { file: photo } }, "Review photo") };
|
|
1200
|
+
}
|
|
1201
|
+
return {
|
|
1202
|
+
async forProduct(productId) {
|
|
1203
|
+
const wire = await request(
|
|
1204
|
+
"GET",
|
|
1205
|
+
`/product/review/list/${productId}`,
|
|
1206
|
+
PUBLIC11
|
|
1207
|
+
);
|
|
1208
|
+
return wire.map(toReviewListItem);
|
|
1209
|
+
},
|
|
1210
|
+
async latest(options = {}) {
|
|
1211
|
+
const limit = options.limit ?? DEFAULT_LIMIT3;
|
|
1212
|
+
const offset = options.offset ?? 0;
|
|
1213
|
+
const page = await request("GET", "/product/review/list", {
|
|
1214
|
+
...PUBLIC_BUSINESS2,
|
|
1215
|
+
query: {
|
|
1216
|
+
rating_gt: options.minRating,
|
|
1217
|
+
search: options.search?.trim() || void 0,
|
|
1218
|
+
limit,
|
|
1219
|
+
offset
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
return { items: page.results.map(toReviewListItem), total: page.count, offset, limit };
|
|
1223
|
+
},
|
|
1224
|
+
async summary(productId) {
|
|
1225
|
+
return toReviewSummary(
|
|
1226
|
+
await request(
|
|
1227
|
+
"GET",
|
|
1228
|
+
`/product/review/conclusion/${productId}`,
|
|
1229
|
+
PUBLIC_BUSINESS2
|
|
1230
|
+
)
|
|
1231
|
+
);
|
|
1232
|
+
},
|
|
1233
|
+
async eligibility(productId) {
|
|
1234
|
+
const wire = await request(
|
|
1235
|
+
"GET",
|
|
1236
|
+
`/product/can/i/review/${productId}`,
|
|
1237
|
+
CUSTOMER
|
|
1238
|
+
);
|
|
1239
|
+
return wire.can_i_review ? { canReview: true, orderProductId: wire.order_product } : { canReview: false, orderProductId: null };
|
|
1240
|
+
},
|
|
1241
|
+
async create(input) {
|
|
1242
|
+
const wire = await request("POST", "/product/review/create", {
|
|
1243
|
+
...CUSTOMER,
|
|
1244
|
+
...body(
|
|
1245
|
+
{
|
|
1246
|
+
customer: input.customerId,
|
|
1247
|
+
product: input.productId,
|
|
1248
|
+
order_product: input.orderProductId,
|
|
1249
|
+
title: input.title,
|
|
1250
|
+
message: input.message,
|
|
1251
|
+
ratting: input.rating
|
|
1252
|
+
},
|
|
1253
|
+
input.photo
|
|
1254
|
+
)
|
|
1255
|
+
});
|
|
1256
|
+
return toReview(wire);
|
|
1257
|
+
},
|
|
1258
|
+
async update(reviewId, changes) {
|
|
1259
|
+
const wire = await request("PATCH", `/product/review/update/${reviewId}`, {
|
|
1260
|
+
...CUSTOMER,
|
|
1261
|
+
...body(
|
|
1262
|
+
{ title: changes.title, message: changes.message, ratting: changes.rating },
|
|
1263
|
+
changes.photo
|
|
1264
|
+
)
|
|
1265
|
+
});
|
|
1266
|
+
return toReview(wire);
|
|
1267
|
+
},
|
|
1268
|
+
async remove(reviewId) {
|
|
1269
|
+
await request("DELETE", `/product/review/customer/delete/${reviewId}`, {
|
|
1270
|
+
...CUSTOMER,
|
|
1271
|
+
business: "required"
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
function toReview(wire) {
|
|
1277
|
+
return {
|
|
1278
|
+
id: wire.id,
|
|
1279
|
+
productId: wire.product,
|
|
1280
|
+
customerId: wire.customer,
|
|
1281
|
+
title: wire.title,
|
|
1282
|
+
message: text(wire.message),
|
|
1283
|
+
photo: text(wire.photo),
|
|
1284
|
+
rating: amount(wire.ratting),
|
|
1285
|
+
createdAt: wire.created_at
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
function toReviewListItem(wire) {
|
|
1289
|
+
const reply = wire.reply;
|
|
1290
|
+
return {
|
|
1291
|
+
...toReview(wire),
|
|
1292
|
+
productName: wire.product_name,
|
|
1293
|
+
customerName: text(wire.customer_name),
|
|
1294
|
+
customerPhoto: text(wire.customer_photo),
|
|
1295
|
+
// The backend also sends the replying staff member's email and phone; not passed on.
|
|
1296
|
+
reply: reply ? {
|
|
1297
|
+
id: reply.id,
|
|
1298
|
+
message: reply.message,
|
|
1299
|
+
authorName: text(reply.user_name),
|
|
1300
|
+
authorPhoto: text(reply.user_photo)
|
|
1301
|
+
} : null
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
function toReviewSummary(wire) {
|
|
1305
|
+
const average = amount(wire.average_rating) ?? 0;
|
|
1306
|
+
return {
|
|
1307
|
+
reviewCount: wire.total_reviews,
|
|
1308
|
+
averageRating: Math.round(average * 10) / 10,
|
|
1309
|
+
starCounts: {
|
|
1310
|
+
1: wire.total_one_star_reviews,
|
|
1311
|
+
2: wire.total_two_star_reviews,
|
|
1312
|
+
3: wire.total_three_star_reviews,
|
|
1313
|
+
4: wire.total_four_star_reviews,
|
|
1314
|
+
5: wire.total_five_star_reviews
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
// src/http/wishlist.ts
|
|
1320
|
+
var CUSTOMER2 = { customer: "required" };
|
|
1321
|
+
function createWishlistApi(request) {
|
|
1322
|
+
return {
|
|
1323
|
+
async list() {
|
|
1324
|
+
const wire = await request("GET", "/product/wishlist/list/", CUSTOMER2);
|
|
1325
|
+
return wire.map(toWishlistItem);
|
|
1326
|
+
},
|
|
1327
|
+
async add(skuId) {
|
|
1328
|
+
const wire = await request("POST", "/product/wishlist/create", {
|
|
1329
|
+
...CUSTOMER2,
|
|
1330
|
+
json: { sku: skuId }
|
|
1331
|
+
});
|
|
1332
|
+
return { id: wire.id, productId: wire.product };
|
|
1333
|
+
},
|
|
1334
|
+
async remove(wishlistId) {
|
|
1335
|
+
await request("DELETE", `/product/wishlist/delete/${wishlistId}`, CUSTOMER2);
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
function toWishlistItem(wire) {
|
|
1340
|
+
const { product, sku } = wire;
|
|
1341
|
+
const mrp = sku ? amount(sku.mrp) : null;
|
|
1342
|
+
return {
|
|
1343
|
+
id: wire.id,
|
|
1344
|
+
name: wire.label,
|
|
1345
|
+
photo: text(wire.photo),
|
|
1346
|
+
productId: product.id,
|
|
1347
|
+
productSlug: product.url_slug,
|
|
1348
|
+
sku: sku ? {
|
|
1349
|
+
id: sku.id,
|
|
1350
|
+
code: sku.sku,
|
|
1351
|
+
slug: sku.url_slug,
|
|
1352
|
+
price: amount(sku.selling_price) ?? 0,
|
|
1353
|
+
// An MRP of 0 means "not set".
|
|
1354
|
+
mrp: mrp && mrp > 0 ? mrp : null,
|
|
1355
|
+
stockQty: sku.stock_qty,
|
|
1356
|
+
// As in products: only an explicit `false` deactivates a SKU.
|
|
1357
|
+
active: sku.is_active !== false,
|
|
1358
|
+
variantIds: sku.selected_variants
|
|
1359
|
+
} : null,
|
|
1360
|
+
// The backend lists entries whose product or SKU is gone or hidden. Same rule as the
|
|
1361
|
+
// storefront listing (ProductSKUSearchView with a guest session).
|
|
1362
|
+
available: !!sku && !sku.deleted && !sku.invalid && product.is_active && !product.is_draft && !product.deleted && product.available_on.includes("website"),
|
|
1363
|
+
fulfillmentMode: text(wire.fulfillment_mode) ?? "none",
|
|
1364
|
+
advanceAmount: amount(wire.advance_amount),
|
|
1365
|
+
hasDigitalDelivery: wire.has_digital_delivery
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
// src/http/theme-content.ts
|
|
1370
|
+
var USAGES = {
|
|
1371
|
+
banner: "banner",
|
|
1372
|
+
slider: "slider",
|
|
1373
|
+
header_logo: "header-logo",
|
|
1374
|
+
footer_logo: "footer-logo",
|
|
1375
|
+
other: "other"
|
|
1376
|
+
};
|
|
1377
|
+
var WIRE_USAGES = Object.fromEntries(
|
|
1378
|
+
Object.entries(USAGES).map(([wire, usage]) => [usage, wire])
|
|
1379
|
+
);
|
|
1380
|
+
var PUBLIC12 = { business: "required", anonymous: true };
|
|
1381
|
+
var MERCHANT7 = { business: "required", merchant: true, anonymous: true };
|
|
1382
|
+
function createThemeContentApi(request) {
|
|
1383
|
+
async function getMany(themeId2, slugs) {
|
|
1384
|
+
const keys = slugs.map(listSlug);
|
|
1385
|
+
if (keys.length === 0) return [];
|
|
1386
|
+
const wire = await request("GET", `/content/get/${themeId2}/v2`, {
|
|
1387
|
+
...PUBLIC12,
|
|
1388
|
+
query: { slug: [...new Set(keys)] }
|
|
1389
|
+
});
|
|
1390
|
+
if (!Array.isArray(wire)) {
|
|
1391
|
+
throw new GrowupsellApiError({
|
|
1392
|
+
kind: "parse",
|
|
1393
|
+
message: "Expected a list of theme content sections.",
|
|
1394
|
+
body: wire
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
const bySlug = new Map(wire.flatMap((row) => row ? [[row.slug, toThemeContent(row)]] : []));
|
|
1398
|
+
return keys.map((key) => bySlug.get(key) ?? null);
|
|
1399
|
+
}
|
|
1400
|
+
return {
|
|
1401
|
+
// The return types are proven by the tests; the implementation works on plain lists.
|
|
1402
|
+
getMany,
|
|
1403
|
+
async get(themeId2, slug) {
|
|
1404
|
+
if (slug === "v2") return (await getMany(themeId2, [slug]))[0];
|
|
1405
|
+
const wire = await request(
|
|
1406
|
+
"GET",
|
|
1407
|
+
`/content/get/${themeId2}/${segment(slug)}`,
|
|
1408
|
+
PUBLIC12
|
|
1409
|
+
);
|
|
1410
|
+
return toThemeContent(wire);
|
|
1411
|
+
},
|
|
1412
|
+
async update(themeId2, slug, content) {
|
|
1413
|
+
const json = { slug, platform: content.platform, data: content.data };
|
|
1414
|
+
const wire = await request(
|
|
1415
|
+
"PUT",
|
|
1416
|
+
`/content/update/${themeId2}/${segment(slug)}`,
|
|
1417
|
+
{ ...MERCHANT7, json }
|
|
1418
|
+
);
|
|
1419
|
+
return toThemeContent(wire);
|
|
1420
|
+
},
|
|
1421
|
+
async uploadImage(upload) {
|
|
1422
|
+
if (upload.file == null) throw new Error("themeContent.uploadImage needs a file.");
|
|
1423
|
+
upload.form.append("image", upload.file, upload.fileName);
|
|
1424
|
+
if (upload.usage) upload.form.append("related", WIRE_USAGES[upload.usage]);
|
|
1425
|
+
const wire = await request("POST", "/content/images/create", {
|
|
1426
|
+
...MERCHANT7,
|
|
1427
|
+
formData: upload.form
|
|
1428
|
+
});
|
|
1429
|
+
return toContentImage(wire);
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
function segment(slug) {
|
|
1434
|
+
if (slug.trim() === "") throw new Error("themeContent: slug is required.");
|
|
1435
|
+
return encodeURIComponent(slug);
|
|
1436
|
+
}
|
|
1437
|
+
function listSlug(slug) {
|
|
1438
|
+
const trimmed = slug.trim();
|
|
1439
|
+
if (trimmed === "") throw new Error("themeContent: slug is required.");
|
|
1440
|
+
if (trimmed.includes(",")) throw new Error(`themeContent: slug "${slug}" contains a comma.`);
|
|
1441
|
+
return trimmed;
|
|
1442
|
+
}
|
|
1443
|
+
function toThemeContent(wire) {
|
|
1444
|
+
if (!("id" in wire)) return null;
|
|
1445
|
+
return {
|
|
1446
|
+
id: wire.id,
|
|
1447
|
+
themeId: wire.theme,
|
|
1448
|
+
slug: wire.slug,
|
|
1449
|
+
platform: wire.platform,
|
|
1450
|
+
data: wire.data
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function toContentImage(wire) {
|
|
1454
|
+
if (!wire.image) {
|
|
1455
|
+
throw new GrowupsellApiError({
|
|
1456
|
+
kind: "parse",
|
|
1457
|
+
message: "The upload was accepted but no file was stored.",
|
|
1458
|
+
body: wire
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
id: wire.id,
|
|
1463
|
+
url: wire.image,
|
|
1464
|
+
usage: wire.related ? USAGES[wire.related] ?? null : null
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
// src/http/customPages.ts
|
|
1469
|
+
var PUBLIC13 = { business: "required", anonymous: true };
|
|
1470
|
+
var MERCHANT8 = { merchant: true, anonymous: true };
|
|
1471
|
+
var HERO_BLOCK_SLUG = "__hero_slider";
|
|
1472
|
+
function createCustomPagesApi(request) {
|
|
1473
|
+
return {
|
|
1474
|
+
async byPath(path3) {
|
|
1475
|
+
const urlPath = normalizePath(path3);
|
|
1476
|
+
try {
|
|
1477
|
+
const wire = await request("GET", "/website/custom-page/public", {
|
|
1478
|
+
...PUBLIC13,
|
|
1479
|
+
query: { url_path: urlPath }
|
|
1480
|
+
});
|
|
1481
|
+
return toCustomPage(wire);
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
if (error instanceof GrowupsellApiError && error.status === 404) return null;
|
|
1484
|
+
throw error;
|
|
1485
|
+
}
|
|
1486
|
+
},
|
|
1487
|
+
async content(pageId) {
|
|
1488
|
+
const wire = await request(
|
|
1489
|
+
"GET",
|
|
1490
|
+
contentPath(pageId, "content"),
|
|
1491
|
+
MERCHANT8
|
|
1492
|
+
);
|
|
1493
|
+
return toCustomPageContent(wire);
|
|
1494
|
+
},
|
|
1495
|
+
async updateContent(pageId, input) {
|
|
1496
|
+
const path3 = contentPath(pageId, "updateContent");
|
|
1497
|
+
const json = toContentWrite(input);
|
|
1498
|
+
const wire = await request("PATCH", path3, { ...MERCHANT8, json });
|
|
1499
|
+
return toCustomPageContent(wire);
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
function normalizePath(path3) {
|
|
1504
|
+
const segments = path3.trim().replace(/\\/g, "/").split("/");
|
|
1505
|
+
const normalized = segments.filter((s) => s.trim() !== "").join("/");
|
|
1506
|
+
if (!normalized) throw new Error("customPages.byPath: path is required.");
|
|
1507
|
+
return normalized;
|
|
1508
|
+
}
|
|
1509
|
+
function contentPath(pageId, method) {
|
|
1510
|
+
if (!Number.isInteger(pageId) || pageId <= 0) {
|
|
1511
|
+
throw new Error(`customPages.${method}: page id must be a positive integer.`);
|
|
1512
|
+
}
|
|
1513
|
+
return `/website/custom-page/${pageId}/content`;
|
|
1514
|
+
}
|
|
1515
|
+
function toHero(raw) {
|
|
1516
|
+
if (Array.isArray(raw)) return raw.length > 0 ? { type: "slider", data: raw } : null;
|
|
1517
|
+
if (!isObject(raw)) return null;
|
|
1518
|
+
const { type, data } = raw;
|
|
1519
|
+
return typeof type === "string" && type !== "" ? { type, data } : null;
|
|
1520
|
+
}
|
|
1521
|
+
function toDocument(heroContent, blocks) {
|
|
1522
|
+
const objects = (blocks ?? []).filter(isObject);
|
|
1523
|
+
const hero = heroContent != null ? toHero(heroContent) : toHero(objects.find((b) => b.slug === HERO_BLOCK_SLUG)?.content);
|
|
1524
|
+
return { hero, sections: objects.filter((b) => b.slug !== HERO_BLOCK_SLUG) };
|
|
1525
|
+
}
|
|
1526
|
+
function toCustomPage(wire) {
|
|
1527
|
+
return {
|
|
1528
|
+
id: wire.id,
|
|
1529
|
+
title: wire.title,
|
|
1530
|
+
path: wire.url_path,
|
|
1531
|
+
seoTitle: text(wire.seo_title),
|
|
1532
|
+
seoDescription: text(wire.seo_description),
|
|
1533
|
+
seoKeywords: (wire.seo_keywords ?? []).flatMap(
|
|
1534
|
+
(k) => typeof k === "string" && k.trim() !== "" ? [k.trim()] : []
|
|
1535
|
+
),
|
|
1536
|
+
...toDocument(wire.hero_content, wire.contents)
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
function toCustomPageContent(wire) {
|
|
1540
|
+
return {
|
|
1541
|
+
id: wire.id,
|
|
1542
|
+
pageId: wire.page,
|
|
1543
|
+
...toDocument(wire.hero_content, wire.content),
|
|
1544
|
+
createdAt: wire.created_at,
|
|
1545
|
+
updatedAt: wire.updated_at
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
function toContentWrite(input) {
|
|
1549
|
+
const { hero } = input;
|
|
1550
|
+
if (hero && hero.type.trim() === "") {
|
|
1551
|
+
throw new Error("customPages.updateContent: the hero type is required.");
|
|
1552
|
+
}
|
|
1553
|
+
return {
|
|
1554
|
+
content: input.sections.filter((s) => isObject(s) && s.slug !== HERO_BLOCK_SLUG),
|
|
1555
|
+
hero_content: hero ? { type: hero.type, data: hero.data } : null
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
function isObject(value) {
|
|
1559
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// src/http/session.ts
|
|
1563
|
+
function createSessionApi(request) {
|
|
1564
|
+
return {
|
|
1565
|
+
async create() {
|
|
1566
|
+
const wire = await request("POST", "/session/create", {
|
|
1567
|
+
anonymous: true,
|
|
1568
|
+
session: "omit",
|
|
1569
|
+
json: {}
|
|
1570
|
+
});
|
|
1571
|
+
return toGuestSession(wire);
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
function toGuestSession(wire) {
|
|
1576
|
+
return { id: wire.id, token: wire.session_token };
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
// src/http/lookup.ts
|
|
1580
|
+
var PUBLIC14 = { anonymous: true };
|
|
1581
|
+
function createLookupApi(request) {
|
|
1582
|
+
return {
|
|
1583
|
+
async countries(search) {
|
|
1584
|
+
const wire = await request("GET", "/lookup/country/list", {
|
|
1585
|
+
...PUBLIC14,
|
|
1586
|
+
query: { search }
|
|
1587
|
+
});
|
|
1588
|
+
return wire.data.map(toCountry);
|
|
1589
|
+
},
|
|
1590
|
+
async states(countryCode) {
|
|
1591
|
+
const wire = await request("GET", "/lookup/country/state/list", {
|
|
1592
|
+
...PUBLIC14,
|
|
1593
|
+
query: { country: countryCode }
|
|
1594
|
+
});
|
|
1595
|
+
return wire.map(toCountryState);
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
function toCountry(wire) {
|
|
1600
|
+
return { code: wire.code, name: wire.name };
|
|
1601
|
+
}
|
|
1602
|
+
function toCountryState(wire) {
|
|
1603
|
+
return {
|
|
1604
|
+
id: wire.id,
|
|
1605
|
+
name: wire.name,
|
|
1606
|
+
shortName: wire.short_name,
|
|
1607
|
+
code: wire.code,
|
|
1608
|
+
country: wire.country
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
// src/http/auth.ts
|
|
1613
|
+
var SIGNED_OUT = { anonymous: true };
|
|
1614
|
+
var BUSINESS = { ...SIGNED_OUT, business: "required" };
|
|
1615
|
+
function createAuthApi(request) {
|
|
1616
|
+
return {
|
|
1617
|
+
async settings() {
|
|
1618
|
+
const wire = await request("GET", "/customer/setting/get", BUSINESS);
|
|
1619
|
+
return toSettings(wire);
|
|
1620
|
+
},
|
|
1621
|
+
async login({ username, password }) {
|
|
1622
|
+
const wire = await request("POST", "/customer/login", {
|
|
1623
|
+
...BUSINESS,
|
|
1624
|
+
session: "required",
|
|
1625
|
+
json: { username, password }
|
|
1626
|
+
});
|
|
1627
|
+
return toAuthResult(wire, username);
|
|
1628
|
+
},
|
|
1629
|
+
async verifyOtp({ customerId, otp }) {
|
|
1630
|
+
const wire = await request("POST", "/customer/otp/verify", {
|
|
1631
|
+
...SIGNED_OUT,
|
|
1632
|
+
json: { otp, customer: customerId }
|
|
1633
|
+
});
|
|
1634
|
+
return toSignedIn(wire, wire.token);
|
|
1635
|
+
},
|
|
1636
|
+
async register(input) {
|
|
1637
|
+
const wire = await request(
|
|
1638
|
+
"POST",
|
|
1639
|
+
"/customer/register",
|
|
1640
|
+
{ ...BUSINESS, session: "required", json: fromRegisterInput(input) }
|
|
1641
|
+
);
|
|
1642
|
+
return toAuthResult(wire);
|
|
1643
|
+
},
|
|
1644
|
+
async sendOtp(username) {
|
|
1645
|
+
const { message } = await request("POST", "/customer/otp/resend", {
|
|
1646
|
+
...BUSINESS,
|
|
1647
|
+
json: { username }
|
|
1648
|
+
});
|
|
1649
|
+
return { message };
|
|
1650
|
+
},
|
|
1651
|
+
async resetPassword({ username, otp, newPassword, confirmPassword }) {
|
|
1652
|
+
const { message } = await request("POST", "/customer/password/reset", {
|
|
1653
|
+
...BUSINESS,
|
|
1654
|
+
json: { username, otp, new_password: newPassword, confirm_password: confirmPassword }
|
|
1655
|
+
});
|
|
1656
|
+
return { message };
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
function fromRegisterInput(input) {
|
|
1661
|
+
return {
|
|
1662
|
+
...input.email !== void 0 && { email: input.email },
|
|
1663
|
+
...input.phone !== void 0 && { phone: input.phone },
|
|
1664
|
+
password: input.password,
|
|
1665
|
+
type: input.type,
|
|
1666
|
+
first_name: input.firstName ?? null,
|
|
1667
|
+
last_name: input.lastName ?? null,
|
|
1668
|
+
business_name: input.businessName ?? null,
|
|
1669
|
+
tax_number: input.taxNumber ?? null,
|
|
1670
|
+
...input.referralCode && { referral_code: input.referralCode }
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
function toSettings(wire) {
|
|
1674
|
+
return {
|
|
1675
|
+
authType: wire.authentication_type ?? "email",
|
|
1676
|
+
allowBusinessSignup: wire.allow_business_signup ?? false,
|
|
1677
|
+
requireVerification: wire.require_customer_verification ?? true,
|
|
1678
|
+
lastNameRequired: wire.is_last_name_required ?? false
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
function toCustomerProfile(wire) {
|
|
1682
|
+
const photo = text(wire.photo);
|
|
1683
|
+
return {
|
|
1684
|
+
id: wire.id,
|
|
1685
|
+
type: wire.type ?? "individual",
|
|
1686
|
+
firstName: text(wire.first_name),
|
|
1687
|
+
lastName: text(wire.last_name),
|
|
1688
|
+
email: text(wire.email),
|
|
1689
|
+
// Sign-up without verification sends `str(None)` for a missing phone.
|
|
1690
|
+
phone: wire.phone === "None" ? null : text(wire.phone),
|
|
1691
|
+
businessName: text(wire.business_name),
|
|
1692
|
+
taxNumber: text(wire.tax_number),
|
|
1693
|
+
// The login dump sends the storage path, not a URL; only a URL is usable.
|
|
1694
|
+
photo: photo && /^https?:\/\//.test(photo) ? photo : null,
|
|
1695
|
+
isActive: wire.is_active ?? false,
|
|
1696
|
+
emailVerified: wire.email_verified ?? false,
|
|
1697
|
+
phoneVerified: wire.phone_verified ?? false
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
function toAuthResult(wire, username) {
|
|
1701
|
+
if (wire.is_active && typeof wire.token === "string") {
|
|
1702
|
+
return { status: "signed-in", session: toSignedIn(wire, wire.token) };
|
|
1703
|
+
}
|
|
1704
|
+
const profile = toCustomerProfile(wire);
|
|
1705
|
+
return {
|
|
1706
|
+
status: "verification-required",
|
|
1707
|
+
customerId: wire.id,
|
|
1708
|
+
contact: username ?? profile.phone ?? profile.email
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
function toSignedIn(wire, token) {
|
|
1712
|
+
return {
|
|
1713
|
+
customer: toCustomerProfile(wire),
|
|
1714
|
+
token,
|
|
1715
|
+
rewardPoints: wire.reward_points ?? null
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
// src/http/customer.ts
|
|
1720
|
+
var CUSTOMER3 = { customer: "required" };
|
|
1721
|
+
var CUSTOMER_BUSINESS = { ...CUSTOMER3, business: "required" };
|
|
1722
|
+
function createCustomerApi(request) {
|
|
1723
|
+
return {
|
|
1724
|
+
async updateProfile(id, input) {
|
|
1725
|
+
const wire = await request("PATCH", `/customer/update/${id}`, {
|
|
1726
|
+
...CUSTOMER_BUSINESS,
|
|
1727
|
+
json: fromProfileInput(input)
|
|
1728
|
+
});
|
|
1729
|
+
return toCustomerProfile(wire);
|
|
1730
|
+
},
|
|
1731
|
+
async changePassword({ oldPassword, newPassword, confirmPassword }) {
|
|
1732
|
+
const { message } = await request("PUT", "/customer/password/update", {
|
|
1733
|
+
...CUSTOMER3,
|
|
1734
|
+
json: {
|
|
1735
|
+
old_password: oldPassword,
|
|
1736
|
+
new_password: newPassword,
|
|
1737
|
+
confirm_password: confirmPassword
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
return { message };
|
|
1741
|
+
},
|
|
1742
|
+
async requestEmailChange(email) {
|
|
1743
|
+
await request("POST", "/customer/email/change/request", {
|
|
1744
|
+
...CUSTOMER_BUSINESS,
|
|
1745
|
+
json: { email }
|
|
1746
|
+
});
|
|
1747
|
+
},
|
|
1748
|
+
async confirmEmailChange({ email, otp }) {
|
|
1749
|
+
const wire = await request("PUT", "/customer/email/change/verify", {
|
|
1750
|
+
...CUSTOMER3,
|
|
1751
|
+
json: { email, otp }
|
|
1752
|
+
});
|
|
1753
|
+
return { message: wire.message, newEmail: wire.new_email };
|
|
1754
|
+
},
|
|
1755
|
+
async requestPhoneChange(phone) {
|
|
1756
|
+
await request("POST", "/customer/phone/change/request", {
|
|
1757
|
+
...CUSTOMER_BUSINESS,
|
|
1758
|
+
json: { phone }
|
|
1759
|
+
});
|
|
1760
|
+
},
|
|
1761
|
+
async confirmPhoneChange({ phone, otp }) {
|
|
1762
|
+
const wire = await request("PUT", "/customer/phone/change/verify", {
|
|
1763
|
+
...CUSTOMER3,
|
|
1764
|
+
json: { phone, otp }
|
|
1765
|
+
});
|
|
1766
|
+
return { message: wire.message, newPhone: wire.new_phone };
|
|
1767
|
+
}
|
|
1768
|
+
};
|
|
1769
|
+
}
|
|
1770
|
+
function fromProfileInput(input) {
|
|
1771
|
+
const body = {};
|
|
1772
|
+
if (input.firstName !== void 0) body.first_name = input.firstName;
|
|
1773
|
+
if (input.lastName !== void 0) body.last_name = input.lastName;
|
|
1774
|
+
if (input.businessName !== void 0) body.business_name = input.businessName;
|
|
1775
|
+
if (input.taxNumber !== void 0) body.tax_number = input.taxNumber;
|
|
1776
|
+
return body;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
// src/http/addresses.ts
|
|
1780
|
+
var CUSTOMER4 = { customer: "required" };
|
|
1781
|
+
function createAddressesApi(request) {
|
|
1782
|
+
return {
|
|
1783
|
+
async list() {
|
|
1784
|
+
const wire = await request("GET", "/customer/address/list", CUSTOMER4);
|
|
1785
|
+
return wire.map(toAddress);
|
|
1786
|
+
},
|
|
1787
|
+
async create(input) {
|
|
1788
|
+
const wire = await request("POST", "/customer/address/create", {
|
|
1789
|
+
...CUSTOMER4,
|
|
1790
|
+
json: fromAddressInput(input)
|
|
1791
|
+
});
|
|
1792
|
+
return toAddress(wire);
|
|
1793
|
+
},
|
|
1794
|
+
async update(id, input) {
|
|
1795
|
+
const wire = await request("PUT", `/customer/address/update/${id}`, {
|
|
1796
|
+
...CUSTOMER4,
|
|
1797
|
+
json: fromAddressInput(input)
|
|
1798
|
+
});
|
|
1799
|
+
return toAddress(wire);
|
|
1800
|
+
},
|
|
1801
|
+
async remove(id) {
|
|
1802
|
+
await request("DELETE", `/customer/address/delete/${id}`, {
|
|
1803
|
+
...CUSTOMER4,
|
|
1804
|
+
business: "required"
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
function toAddress(wire) {
|
|
1810
|
+
return {
|
|
1811
|
+
id: wire.id,
|
|
1812
|
+
addressLine1: wire.address_line_1,
|
|
1813
|
+
addressLine2: wire.address_line_2,
|
|
1814
|
+
postalCode: text(wire.postal_code),
|
|
1815
|
+
city: wire.city,
|
|
1816
|
+
type: wire.type,
|
|
1817
|
+
country: text(wire.country),
|
|
1818
|
+
state: wire.state ?? null,
|
|
1819
|
+
stateName: text(wire.state_name),
|
|
1820
|
+
landmark: wire.landmark,
|
|
1821
|
+
contactNo: text(wire.contact_no),
|
|
1822
|
+
latitude: amount(wire.latitude),
|
|
1823
|
+
longitude: amount(wire.longitude),
|
|
1824
|
+
isDefault: wire.default ?? false,
|
|
1825
|
+
isUsed: wire.is_used
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
function fromAddressInput(input) {
|
|
1829
|
+
return {
|
|
1830
|
+
address_line_1: input.addressLine1,
|
|
1831
|
+
address_line_2: input.addressLine2,
|
|
1832
|
+
postal_code: input.postalCode ?? "",
|
|
1833
|
+
city: input.city,
|
|
1834
|
+
type: input.type,
|
|
1835
|
+
country: input.country ?? null,
|
|
1836
|
+
state: input.state ?? null,
|
|
1837
|
+
landmark: input.landmark,
|
|
1838
|
+
contact_no: input.contactNo ?? null,
|
|
1839
|
+
latitude: input.latitude ?? null,
|
|
1840
|
+
longitude: input.longitude ?? null,
|
|
1841
|
+
default: input.isDefault ?? false
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
// src/http/checkout.ts
|
|
1846
|
+
var PUBLIC_BUSINESS3 = { anonymous: true, business: "required" };
|
|
1847
|
+
var CUSTOMER_BUSINESS2 = { business: "required", customer: "required" };
|
|
1848
|
+
var PLACE_ORDER_TIMEOUT_MS = 6e4;
|
|
1849
|
+
function createCheckoutApi(request) {
|
|
1850
|
+
const placing = /* @__PURE__ */ new Map();
|
|
1851
|
+
async function charge(cartId, options) {
|
|
1852
|
+
const body = {
|
|
1853
|
+
giftcard: [...options.giftCardIds ?? []],
|
|
1854
|
+
use_reward_points: options.useRewardPoints ?? false
|
|
1855
|
+
};
|
|
1856
|
+
const wire = await request("POST", `/order/charge/delivery/${cartId}`, {
|
|
1857
|
+
...CUSTOMER_BUSINESS2,
|
|
1858
|
+
timeoutMs: PLACE_ORDER_TIMEOUT_MS,
|
|
1859
|
+
json: body
|
|
1860
|
+
});
|
|
1861
|
+
if (wire.action === "done" || wire.payment.type === "cod") {
|
|
1862
|
+
return { status: "placed", orderId: cartId };
|
|
1863
|
+
}
|
|
1864
|
+
return { status: "payment-required", orderId: cartId, payment: toPendingPayment(wire.payment) };
|
|
1865
|
+
}
|
|
1866
|
+
return {
|
|
1867
|
+
async settings() {
|
|
1868
|
+
return toCheckoutSettings(
|
|
1869
|
+
await request(
|
|
1870
|
+
"GET",
|
|
1871
|
+
"/order/business/setting/get",
|
|
1872
|
+
PUBLIC_BUSINESS3
|
|
1873
|
+
)
|
|
1874
|
+
);
|
|
1875
|
+
},
|
|
1876
|
+
placeOrder(cartId, options = {}) {
|
|
1877
|
+
const inFlight = placing.get(cartId);
|
|
1878
|
+
if (inFlight) return inFlight;
|
|
1879
|
+
if ((options.giftCardIds?.length ?? 0) > 0 && options.useRewardPoints) {
|
|
1880
|
+
return Promise.reject(
|
|
1881
|
+
new Error(
|
|
1882
|
+
"placeOrder: gift cards and reward points cannot be combined; choose one (backend issue W36)."
|
|
1883
|
+
)
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1886
|
+
const promise = charge(cartId, options).finally(() => placing.delete(cartId));
|
|
1887
|
+
placing.set(cartId, promise);
|
|
1888
|
+
return promise;
|
|
1889
|
+
},
|
|
1890
|
+
async createAdvanceOrder(input) {
|
|
1891
|
+
const body = {
|
|
1892
|
+
product: input.productId,
|
|
1893
|
+
sku: input.skuId,
|
|
1894
|
+
custom_data: input.customData,
|
|
1895
|
+
qty: 1,
|
|
1896
|
+
type: input.type,
|
|
1897
|
+
shipping_address: input.shippingAddressId,
|
|
1898
|
+
billing_address: input.billingAddressId
|
|
1899
|
+
};
|
|
1900
|
+
const wire = await request(
|
|
1901
|
+
"POST",
|
|
1902
|
+
"/order/custom-advance/create",
|
|
1903
|
+
{ ...CUSTOMER_BUSINESS2, timeoutMs: PLACE_ORDER_TIMEOUT_MS, json: body }
|
|
1904
|
+
);
|
|
1905
|
+
return { orderId: wire.order_id, payment: toPendingPayment(wire.payment) };
|
|
1906
|
+
}
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
function toCheckoutSettings(wire) {
|
|
1910
|
+
return {
|
|
1911
|
+
allowCashOnDelivery: wire.allow_cash_on_delivery ?? false,
|
|
1912
|
+
allowCancellation: wire.allow_cancellation_from_customer ?? false,
|
|
1913
|
+
autoAccept: wire.auto_accept ?? false,
|
|
1914
|
+
onlineOrdersEnabled: wire.enable_online_order ?? false,
|
|
1915
|
+
deliveryChargeEnabled: wire.delivery_charge ?? false,
|
|
1916
|
+
maxQuantityIndividual: wire.max_allowed_qty_for_individual ?? 0,
|
|
1917
|
+
maxQuantityBusiness: wire.max_allowed_qty_for_business ?? 0
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
function toPendingPayment(wire) {
|
|
1921
|
+
const method = wire.payment_method?.type ?? null;
|
|
1922
|
+
return {
|
|
1923
|
+
id: wire.id,
|
|
1924
|
+
amount: amount(wire.amount) ?? 0,
|
|
1925
|
+
method,
|
|
1926
|
+
publicKey: text(wire.payment_method?.payment_key),
|
|
1927
|
+
providerOrderId: text(wire.payment_order_key),
|
|
1928
|
+
// `payment_key` means something else for every provider; only Stripe's is a client secret.
|
|
1929
|
+
clientSecret: method === "stripe" ? text(wire.payment_key) : null,
|
|
1930
|
+
// Razorpay and Stripe rows carry links too, to pages the SDK flows do not use.
|
|
1931
|
+
redirectUrl: method === "phonepe" ? text(wire.payment_url) : null
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
// src/http/payments.ts
|
|
1936
|
+
var PUBLIC_BUSINESS4 = { anonymous: true, business: "required" };
|
|
1937
|
+
var CUSTOMER_BUSINESS3 = { customer: "required", business: "required" };
|
|
1938
|
+
var STRIPE_VERIFICATION_FAILED = "Payment verification failed";
|
|
1939
|
+
function createPaymentsApi(request) {
|
|
1940
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
1941
|
+
function once(key, run) {
|
|
1942
|
+
const existing = inFlight.get(key);
|
|
1943
|
+
if (existing) return existing;
|
|
1944
|
+
const promise = run().finally(() => inFlight.delete(key));
|
|
1945
|
+
inFlight.set(key, promise);
|
|
1946
|
+
return promise;
|
|
1947
|
+
}
|
|
1948
|
+
return {
|
|
1949
|
+
confirmPhonePe(paymentId) {
|
|
1950
|
+
return once(`phonepe:${paymentId}`, async () => {
|
|
1951
|
+
const wire = await request(
|
|
1952
|
+
"GET",
|
|
1953
|
+
`/payment/phonepe/order/web/success/${paymentId}`,
|
|
1954
|
+
PUBLIC_BUSINESS4
|
|
1955
|
+
);
|
|
1956
|
+
return { status: wire.payment_status === "paid" ? "paid" : "unpaid" };
|
|
1957
|
+
});
|
|
1958
|
+
},
|
|
1959
|
+
confirmStripe(payment) {
|
|
1960
|
+
const intentId = payment.providerOrderId;
|
|
1961
|
+
if (!intentId) {
|
|
1962
|
+
return Promise.reject(
|
|
1963
|
+
new TypeError("confirmStripe: the payment has no providerOrderId (PaymentIntent id).")
|
|
1964
|
+
);
|
|
1965
|
+
}
|
|
1966
|
+
return once(`stripe:${payment.id}`, async () => {
|
|
1967
|
+
const json = { payment_intent_id: intentId };
|
|
1968
|
+
try {
|
|
1969
|
+
await request(
|
|
1970
|
+
"POST",
|
|
1971
|
+
`/payment/stripe/order/web/success/${payment.id}`,
|
|
1972
|
+
{ ...PUBLIC_BUSINESS4, json }
|
|
1973
|
+
);
|
|
1974
|
+
return { status: "paid" };
|
|
1975
|
+
} catch (error) {
|
|
1976
|
+
if (isStripeVerificationFailure(error)) return { status: "unpaid" };
|
|
1977
|
+
throw error;
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
},
|
|
1981
|
+
confirmRazorpay(payment, result) {
|
|
1982
|
+
return once(`razorpay:${payment.id}`, async () => {
|
|
1983
|
+
const json = {
|
|
1984
|
+
razorpay_payment_id: result.razorpayPaymentId,
|
|
1985
|
+
razorpay_order_id: result.razorpayOrderId,
|
|
1986
|
+
razorpay_signature: result.razorpaySignature
|
|
1987
|
+
};
|
|
1988
|
+
await request(
|
|
1989
|
+
"POST",
|
|
1990
|
+
`/payment/razorpay/order/web/success/${payment.id}`,
|
|
1991
|
+
{ ...PUBLIC_BUSINESS4, json }
|
|
1992
|
+
);
|
|
1993
|
+
});
|
|
1994
|
+
},
|
|
1995
|
+
submitTransferProof(paymentId, screenshot) {
|
|
1996
|
+
return once(`transfer:${paymentId}`, async () => {
|
|
1997
|
+
const formData = multipart(
|
|
1998
|
+
{},
|
|
1999
|
+
{ verification_screenshot: { file: screenshot } },
|
|
2000
|
+
"Transfer proof"
|
|
2001
|
+
);
|
|
2002
|
+
await request("PATCH", `/payment/status/update/${paymentId}`, {
|
|
2003
|
+
...CUSTOMER_BUSINESS3,
|
|
2004
|
+
formData
|
|
2005
|
+
});
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
function isStripeVerificationFailure(error) {
|
|
2011
|
+
return error instanceof GrowupsellApiError && error.status === 400 && error.body?.message === STRIPE_VERIFICATION_FAILED;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
// src/http/custom-manufacturing.ts
|
|
2015
|
+
var CUSTOMER_BUSINESS4 = { customer: "required", business: "required" };
|
|
2016
|
+
function createCustomManufacturingApi(request) {
|
|
2017
|
+
return {
|
|
2018
|
+
async uploadFile(file, fileName) {
|
|
2019
|
+
if (file == null) throw new Error("customManufacturing.uploadFile needs a file.");
|
|
2020
|
+
const wire = await request(
|
|
2021
|
+
"POST",
|
|
2022
|
+
"/manufacture/custom-request/customer/upload",
|
|
2023
|
+
{
|
|
2024
|
+
...CUSTOMER_BUSINESS4,
|
|
2025
|
+
formData: multipart({}, { file: { file, fileName } }, "customManufacturing.uploadFile")
|
|
2026
|
+
}
|
|
2027
|
+
);
|
|
2028
|
+
if (!wire.url)
|
|
2029
|
+
throw new Error("customManufacturing.uploadFile: the backend returned no URL.");
|
|
2030
|
+
return { id: wire.id, url: wire.url };
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
// src/http/subscriptions.ts
|
|
2036
|
+
var DEFAULT_LIMIT4 = 20;
|
|
2037
|
+
var CUSTOMER5 = { customer: "required", business: "required" };
|
|
2038
|
+
function createSubscriptionsApi(request) {
|
|
2039
|
+
return {
|
|
2040
|
+
async list(options = {}) {
|
|
2041
|
+
const limit = options.limit ?? DEFAULT_LIMIT4;
|
|
2042
|
+
const offset = options.offset ?? 0;
|
|
2043
|
+
const page = await request("GET", "/subscription/list", {
|
|
2044
|
+
...CUSTOMER5,
|
|
2045
|
+
query: { limit, offset }
|
|
2046
|
+
});
|
|
2047
|
+
return { items: page.results.map(toSubscription), total: page.count, offset, limit };
|
|
2048
|
+
},
|
|
2049
|
+
async detail(id) {
|
|
2050
|
+
return toSubscription(
|
|
2051
|
+
await request("GET", `/subscription/detail/${id}`, CUSTOMER5)
|
|
2052
|
+
);
|
|
2053
|
+
},
|
|
2054
|
+
async deliveries(id) {
|
|
2055
|
+
const wire = await request(
|
|
2056
|
+
"GET",
|
|
2057
|
+
`/subscription/delivery/list/${id}`,
|
|
2058
|
+
CUSTOMER5
|
|
2059
|
+
);
|
|
2060
|
+
return wire.map(toSubscriptionDelivery);
|
|
2061
|
+
},
|
|
2062
|
+
async holds(id) {
|
|
2063
|
+
const wire = await request(
|
|
2064
|
+
"GET",
|
|
2065
|
+
`/subscription/hold/history/list/${id}`,
|
|
2066
|
+
CUSTOMER5
|
|
2067
|
+
);
|
|
2068
|
+
return wire.map(toSubscriptionHold);
|
|
2069
|
+
},
|
|
2070
|
+
async invoices(id) {
|
|
2071
|
+
const wire = await request(
|
|
2072
|
+
"GET",
|
|
2073
|
+
`/subscription/invoice/list/${id}`,
|
|
2074
|
+
CUSTOMER5
|
|
2075
|
+
);
|
|
2076
|
+
return wire.map(toSubscriptionInvoice);
|
|
2077
|
+
},
|
|
2078
|
+
async payInvoice(invoiceId) {
|
|
2079
|
+
return toInvoicePayment(
|
|
2080
|
+
await request(
|
|
2081
|
+
"GET",
|
|
2082
|
+
`/subscription/invoice/get/${invoiceId}`,
|
|
2083
|
+
CUSTOMER5
|
|
2084
|
+
)
|
|
2085
|
+
);
|
|
2086
|
+
},
|
|
2087
|
+
async create(input) {
|
|
2088
|
+
const body = toCreateBody(input);
|
|
2089
|
+
return toSubscription(
|
|
2090
|
+
await request("POST", "/subscription/create", {
|
|
2091
|
+
...CUSTOMER5,
|
|
2092
|
+
json: body
|
|
2093
|
+
})
|
|
2094
|
+
);
|
|
2095
|
+
},
|
|
2096
|
+
hold: (id) => updateStatus(id, { action: "hold" }),
|
|
2097
|
+
resume: (id) => updateStatus(id, { action: "resume" }),
|
|
2098
|
+
async cancel(id, reason) {
|
|
2099
|
+
const trimmed = reason?.trim();
|
|
2100
|
+
if (!trimmed) throw new Error("subscriptions.cancel needs a reason.");
|
|
2101
|
+
return updateStatus(id, { action: "cancel", decline_message: trimmed });
|
|
2102
|
+
}
|
|
2103
|
+
};
|
|
2104
|
+
async function updateStatus(id, body) {
|
|
2105
|
+
return toSubscription(
|
|
2106
|
+
await request("POST", `/subscription/status/update/${id}`, {
|
|
2107
|
+
...CUSTOMER5,
|
|
2108
|
+
json: body
|
|
2109
|
+
})
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
var WIRE_INTERVAL = {
|
|
2114
|
+
daily: "daily",
|
|
2115
|
+
"alternate-day": "alternate_day",
|
|
2116
|
+
weekly: "weekly",
|
|
2117
|
+
monthly: "monthly"
|
|
2118
|
+
};
|
|
2119
|
+
function toCreateBody(input) {
|
|
2120
|
+
const fail = (message) => {
|
|
2121
|
+
throw new Error(`subscriptions.create: ${message}`);
|
|
2122
|
+
};
|
|
2123
|
+
if (!Number.isInteger(input.quantity) || input.quantity < 1) {
|
|
2124
|
+
fail("quantity must be a whole number of at least 1.");
|
|
2125
|
+
}
|
|
2126
|
+
if (input.endDate < input.startDate) fail("endDate is before startDate.");
|
|
2127
|
+
const body = {
|
|
2128
|
+
customer: input.customerId,
|
|
2129
|
+
address: input.addressId,
|
|
2130
|
+
start_date: input.startDate,
|
|
2131
|
+
end_date: input.endDate,
|
|
2132
|
+
interval: WIRE_INTERVAL[input.interval],
|
|
2133
|
+
products: [{ id: input.skuId, quantity: input.quantity, price: input.price }]
|
|
2134
|
+
};
|
|
2135
|
+
if (input.interval === "weekly") {
|
|
2136
|
+
if (!input.weekdays?.length) fail("weekly needs at least one weekday.");
|
|
2137
|
+
body.selected_days = input.weekdays;
|
|
2138
|
+
}
|
|
2139
|
+
if (input.interval === "monthly") {
|
|
2140
|
+
if (!input.monthDay)
|
|
2141
|
+
fail("monthly needs monthDay (an ISO date whose day is the delivery day).");
|
|
2142
|
+
body.month_day = input.monthDay;
|
|
2143
|
+
}
|
|
2144
|
+
return body;
|
|
2145
|
+
}
|
|
2146
|
+
var STATUS = {
|
|
2147
|
+
created: "created",
|
|
2148
|
+
accepted: "accepted",
|
|
2149
|
+
paid: "paid",
|
|
2150
|
+
"in-progress": "in-progress",
|
|
2151
|
+
hold: "hold",
|
|
2152
|
+
completed: "completed",
|
|
2153
|
+
cancelled: "cancelled",
|
|
2154
|
+
decline: "declined"
|
|
2155
|
+
};
|
|
2156
|
+
var INTERVAL = {
|
|
2157
|
+
daily: "daily",
|
|
2158
|
+
alternate_day: "alternate-day",
|
|
2159
|
+
weekly: "weekly",
|
|
2160
|
+
monthly: "monthly"
|
|
2161
|
+
};
|
|
2162
|
+
function weekdays(value) {
|
|
2163
|
+
if (value == null) return [];
|
|
2164
|
+
const names = Array.isArray(value) ? value : value.split(",");
|
|
2165
|
+
return names.map((name) => name.trim()).filter((name) => name !== "");
|
|
2166
|
+
}
|
|
2167
|
+
function toSubscription(wire) {
|
|
2168
|
+
const address = wire.address;
|
|
2169
|
+
return {
|
|
2170
|
+
id: wire.id,
|
|
2171
|
+
number: text(wire.subscription_no),
|
|
2172
|
+
// The model defaults to `created`; null only for rows written outside the API.
|
|
2173
|
+
status: wire.status ? STATUS[wire.status] : "created",
|
|
2174
|
+
interval: wire.interval ? INTERVAL[wire.interval] : null,
|
|
2175
|
+
startDate: wire.start_date,
|
|
2176
|
+
endDate: wire.end_date,
|
|
2177
|
+
weekdays: weekdays(wire.weekly_days),
|
|
2178
|
+
monthDay: wire.month_day,
|
|
2179
|
+
// The list sends the address id, the detail the address row.
|
|
2180
|
+
addressId: typeof address === "object" ? address?.id ?? null : address ?? null,
|
|
2181
|
+
reason: text(wire.decline_message),
|
|
2182
|
+
createdAt: wire.created_at
|
|
2183
|
+
};
|
|
2184
|
+
}
|
|
2185
|
+
function toSubscriptionDelivery(wire) {
|
|
2186
|
+
return {
|
|
2187
|
+
id: wire.id,
|
|
2188
|
+
date: wire.date,
|
|
2189
|
+
status: wire.status,
|
|
2190
|
+
items: wire.products.map((p) => ({
|
|
2191
|
+
id: p.id,
|
|
2192
|
+
skuId: p.sku,
|
|
2193
|
+
name: p.product_name,
|
|
2194
|
+
quantity: p.qty,
|
|
2195
|
+
unit: text(p.unit),
|
|
2196
|
+
price: amount(p.price),
|
|
2197
|
+
status: p.status,
|
|
2198
|
+
removed: p.deleted
|
|
2199
|
+
}))
|
|
2200
|
+
};
|
|
2201
|
+
}
|
|
2202
|
+
function toSubscriptionHold(wire) {
|
|
2203
|
+
return { id: wire.id, startDate: wire.start_date ?? null, endDate: wire.end_date ?? null };
|
|
2204
|
+
}
|
|
2205
|
+
function toInvoicePayment(wire) {
|
|
2206
|
+
return wire.action === "done" ? { status: "paid" } : { status: "payment-required", payment: toPendingPayment(wire.payment) };
|
|
2207
|
+
}
|
|
2208
|
+
function toSubscriptionInvoice(wire) {
|
|
2209
|
+
return {
|
|
2210
|
+
id: wire.id,
|
|
2211
|
+
orderId: wire.order,
|
|
2212
|
+
invoiceNumber: text(wire.invoice_number),
|
|
2213
|
+
invoiceDate: wire.invoice_date,
|
|
2214
|
+
dueDate: wire.due_date ?? null,
|
|
2215
|
+
billingPeriod: wire.billing_period,
|
|
2216
|
+
amount: amount(wire.amount),
|
|
2217
|
+
paymentStatus: wire.payment?.status ?? "unpaid"
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
// src/http/orders.ts
|
|
2222
|
+
var CUSTOMER6 = { business: "required", customer: "required" };
|
|
2223
|
+
var DEFAULT_LIMIT5 = 10;
|
|
2224
|
+
var TRACKING_TIMEOUT_MS = 3e4;
|
|
2225
|
+
var DOCUMENT_TIMEOUT_MS = 6e4;
|
|
2226
|
+
function createOrdersApi(request) {
|
|
2227
|
+
function pdf(path3, options = {}) {
|
|
2228
|
+
return request("POST", path3, {
|
|
2229
|
+
...CUSTOMER6,
|
|
2230
|
+
query: { send_to_customer: false, invoice_type: options.format ?? "a4" },
|
|
2231
|
+
responseType: "binary",
|
|
2232
|
+
timeoutMs: DOCUMENT_TIMEOUT_MS
|
|
2233
|
+
});
|
|
2234
|
+
}
|
|
2235
|
+
async function email(path3, options = {}) {
|
|
2236
|
+
await request("POST", path3, {
|
|
2237
|
+
...CUSTOMER6,
|
|
2238
|
+
query: { send_to_customer: true, invoice_type: options.format ?? "a4" },
|
|
2239
|
+
timeoutMs: DOCUMENT_TIMEOUT_MS
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
return {
|
|
2243
|
+
async list(options = {}) {
|
|
2244
|
+
const limit = options.limit ?? DEFAULT_LIMIT5;
|
|
2245
|
+
const offset = options.offset ?? 0;
|
|
2246
|
+
const wire = await request("GET", "/order/list", {
|
|
2247
|
+
...CUSTOMER6,
|
|
2248
|
+
query: { limit, offset, status: options.status, search: options.search }
|
|
2249
|
+
});
|
|
2250
|
+
return { items: wire.results.map(toOrderListItem), total: wire.count, offset, limit };
|
|
2251
|
+
},
|
|
2252
|
+
async detail(orderId) {
|
|
2253
|
+
return toOrderDetail(
|
|
2254
|
+
await request("GET", `/order/detail/${orderId}`, CUSTOMER6)
|
|
2255
|
+
);
|
|
2256
|
+
},
|
|
2257
|
+
async summary(orderId) {
|
|
2258
|
+
return toOrderSummary(
|
|
2259
|
+
await request("GET", `/order/ecommerce/detail/${orderId}`, CUSTOMER6)
|
|
2260
|
+
);
|
|
2261
|
+
},
|
|
2262
|
+
async shipments(orderId) {
|
|
2263
|
+
const wire = await request(
|
|
2264
|
+
"GET",
|
|
2265
|
+
`/order/product/delivery/info/list/${orderId}`,
|
|
2266
|
+
CUSTOMER6
|
|
2267
|
+
);
|
|
2268
|
+
return wire.map(toShipment);
|
|
2269
|
+
},
|
|
2270
|
+
async tracking(trackingNumber) {
|
|
2271
|
+
const wire = await request(
|
|
2272
|
+
"GET",
|
|
2273
|
+
`/delivery/order/tracking/info/${encodeURIComponent(trackingNumber)}`,
|
|
2274
|
+
{ ...CUSTOMER6, timeoutMs: TRACKING_TIMEOUT_MS }
|
|
2275
|
+
);
|
|
2276
|
+
return { trackingUrl: text(wire.tracking_url), events: wire.data };
|
|
2277
|
+
},
|
|
2278
|
+
invoice: (orderId, options) => pdf(`/order/invoice/pdf/send/${orderId}`, options),
|
|
2279
|
+
emailInvoice: (orderId, options) => email(`/order/invoice/pdf/send/${orderId}`, options),
|
|
2280
|
+
creditNote: (returnId, options) => pdf(`/order/credit/note/pdf/${returnId}`, options),
|
|
2281
|
+
emailCreditNote: (returnId, options) => email(`/order/credit/note/pdf/${returnId}`, options),
|
|
2282
|
+
async cancelCodItems({ orderId, items, reason }) {
|
|
2283
|
+
if (items.length === 0) throw new TypeError("cancelCodItems: items must not be empty.");
|
|
2284
|
+
if (items.some((item) => !(item.quantity >= 1))) {
|
|
2285
|
+
throw new RangeError("cancelCodItems: every quantity must be at least 1.");
|
|
2286
|
+
}
|
|
2287
|
+
if (reason.trim() === "") throw new TypeError("cancelCodItems: reason must not be blank.");
|
|
2288
|
+
await request("POST", "/order/cancel/cod", {
|
|
2289
|
+
...CUSTOMER6,
|
|
2290
|
+
json: {
|
|
2291
|
+
order: orderId,
|
|
2292
|
+
order_products: items.map((item) => ({ id: item.orderLineId, qty: item.quantity })),
|
|
2293
|
+
status_message: reason
|
|
2294
|
+
}
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
var status = (value) => value ?? "created";
|
|
2300
|
+
function toOrderListItem(wire) {
|
|
2301
|
+
return {
|
|
2302
|
+
id: wire.id,
|
|
2303
|
+
orderNumber: text(wire.order_no),
|
|
2304
|
+
type: wire.type,
|
|
2305
|
+
status: status(wire.status),
|
|
2306
|
+
payable: amount(wire.final_payable_amount) ?? 0,
|
|
2307
|
+
placedAt: wire.created_at
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2310
|
+
function toOrderLine(wire) {
|
|
2311
|
+
return {
|
|
2312
|
+
id: wire.id,
|
|
2313
|
+
skuId: wire.sku?.id ?? null,
|
|
2314
|
+
productId: wire.sku?.product?.id ?? null,
|
|
2315
|
+
name: wire.label ?? wire.name ?? "",
|
|
2316
|
+
photo: text(wire.photo),
|
|
2317
|
+
unitPrice: amount(wire.price) ?? 0,
|
|
2318
|
+
quantity: wire.qty,
|
|
2319
|
+
lineTotal: amount(wire.total) ?? 0,
|
|
2320
|
+
offerDiscount: amount(wire.offer_redeem_amount) ?? 0,
|
|
2321
|
+
taxPercent: amount(wire.tax),
|
|
2322
|
+
isDigital: wire.is_digital_product,
|
|
2323
|
+
customData: wire.custom_data,
|
|
2324
|
+
canReplace: wire.can_replace,
|
|
2325
|
+
canExchange: wire.can_exchange,
|
|
2326
|
+
maxReplaceOrExchangeQuantity: wire.max_qty_for_replace_or_exchange
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
function toOrderAddress(wire) {
|
|
2330
|
+
return {
|
|
2331
|
+
id: wire.id,
|
|
2332
|
+
line1: text(wire.address_line_1),
|
|
2333
|
+
line2: text(wire.address_line_2),
|
|
2334
|
+
landmark: text(wire.landmark),
|
|
2335
|
+
city: text(wire.city),
|
|
2336
|
+
state: text(wire.state_name),
|
|
2337
|
+
postalCode: text(wire.postal_code),
|
|
2338
|
+
country: text(wire.country),
|
|
2339
|
+
type: text(wire.type)
|
|
2340
|
+
};
|
|
2341
|
+
}
|
|
2342
|
+
function toOrderPaymentEntry(wire) {
|
|
2343
|
+
return {
|
|
2344
|
+
id: wire.id,
|
|
2345
|
+
type: text(wire.type),
|
|
2346
|
+
amount: amount(wire.amount) ?? 0,
|
|
2347
|
+
status: wire.status,
|
|
2348
|
+
method: wire.payment_method?.type ?? null,
|
|
2349
|
+
label: wire.payment_method_label
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
function toOrderDetail(wire) {
|
|
2353
|
+
const lines = (wire.products ?? []).map(toOrderLine);
|
|
2354
|
+
const orderOffer = amount(wire.offer_redeem_amount) ?? 0;
|
|
2355
|
+
const offerDiscount = orderOffer > 0 ? orderOffer : lines.reduce((sum2, line) => sum2 + line.offerDiscount, 0);
|
|
2356
|
+
return {
|
|
2357
|
+
id: wire.id,
|
|
2358
|
+
orderNumber: text(wire.order_no),
|
|
2359
|
+
invoiceNumber: text(wire.invoice_number),
|
|
2360
|
+
type: wire.type,
|
|
2361
|
+
status: status(wire.status),
|
|
2362
|
+
statusMessage: text(wire.status_message),
|
|
2363
|
+
placedAt: wire.created_at,
|
|
2364
|
+
lines,
|
|
2365
|
+
subtotal: amount(wire.total_amount) ?? 0,
|
|
2366
|
+
offerDiscount,
|
|
2367
|
+
promoDiscount: amount(wire.promo_redeem_amount) ?? 0,
|
|
2368
|
+
deliveryCharge: amount(wire.delivery_charge) ?? 0,
|
|
2369
|
+
payable: amount(wire.final_payable_amount) ?? 0,
|
|
2370
|
+
shippingAddress: wire.shipping_address ? toOrderAddress(wire.shipping_address) : null,
|
|
2371
|
+
billingAddress: wire.billing_address ? toOrderAddress(wire.billing_address) : null,
|
|
2372
|
+
payments: (wire.payment_history ?? []).map(toOrderPaymentEntry),
|
|
2373
|
+
hasExchangeOrReplacement: wire.has_exchange_or_replacement
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
function toOrderSummary(wire) {
|
|
2377
|
+
return {
|
|
2378
|
+
id: wire.id,
|
|
2379
|
+
orderNumber: text(wire.order_no),
|
|
2380
|
+
invoiceNumber: text(wire.invoice_number),
|
|
2381
|
+
status: status(wire.status),
|
|
2382
|
+
subtotal: amount(wire.total_amount) ?? 0,
|
|
2383
|
+
payable: amount(wire.order_total) ?? 0,
|
|
2384
|
+
placedAt: wire.placed_at,
|
|
2385
|
+
items: wire.order_products.map((item) => ({
|
|
2386
|
+
name: item.product_name ?? "",
|
|
2387
|
+
variant: text(item.variant_name),
|
|
2388
|
+
photo: text(item.photo),
|
|
2389
|
+
quantity: item.qty,
|
|
2390
|
+
unitPrice: amount(item.price) ?? 0
|
|
2391
|
+
})),
|
|
2392
|
+
deliveryAddress: wire.delivery_address ? toOrderAddress(wire.delivery_address) : null,
|
|
2393
|
+
payment: wire.payment ? {
|
|
2394
|
+
id: wire.payment.id,
|
|
2395
|
+
status: wire.payment.status ?? "unpaid",
|
|
2396
|
+
amount: wire.payment.order_amount ?? 0,
|
|
2397
|
+
mode: text(wire.payment.mode)
|
|
2398
|
+
} : null
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
function toShipment(wire) {
|
|
2402
|
+
const info = wire.delivery_info;
|
|
2403
|
+
return {
|
|
2404
|
+
id: info.id,
|
|
2405
|
+
partner: text(info.label) ?? "Self",
|
|
2406
|
+
trackingNumber: text(info.tracking_number),
|
|
2407
|
+
status: info.status,
|
|
2408
|
+
createdAt: info.created_at,
|
|
2409
|
+
items: wire.products.map((item) => ({
|
|
2410
|
+
orderLineId: item.order_product,
|
|
2411
|
+
name: item.product_name ?? "",
|
|
2412
|
+
photo: text(item.photo),
|
|
2413
|
+
quantity: item.qty
|
|
2414
|
+
}))
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
// src/http/returns.ts
|
|
2419
|
+
var CUSTOMER7 = { business: "required", customer: "required" };
|
|
2420
|
+
function createReturnsApi(request) {
|
|
2421
|
+
return {
|
|
2422
|
+
async eligibleItems(orderId) {
|
|
2423
|
+
const wire = await request(
|
|
2424
|
+
"GET",
|
|
2425
|
+
`/order/return/eligible/products/${orderId}/`,
|
|
2426
|
+
CUSTOMER7
|
|
2427
|
+
);
|
|
2428
|
+
return wire.map(toReturnableItem);
|
|
2429
|
+
},
|
|
2430
|
+
async list(orderId) {
|
|
2431
|
+
const wire = await request(
|
|
2432
|
+
"GET",
|
|
2433
|
+
`/order/return/order/list/${orderId}`,
|
|
2434
|
+
CUSTOMER7
|
|
2435
|
+
);
|
|
2436
|
+
return wire.map(toReturnRequest);
|
|
2437
|
+
},
|
|
2438
|
+
async create({ orderId, reason, items }) {
|
|
2439
|
+
if (items.length === 0) throw new TypeError("returns.create: items must not be empty.");
|
|
2440
|
+
if (items.some((item) => !(item.quantity >= 1))) {
|
|
2441
|
+
throw new RangeError("returns.create: every quantity must be at least 1.");
|
|
2442
|
+
}
|
|
2443
|
+
if (reason.trim() === "") throw new TypeError("returns.create: reason must not be blank.");
|
|
2444
|
+
const wire = await request("POST", "/order/return/customer/create", {
|
|
2445
|
+
...CUSTOMER7,
|
|
2446
|
+
json: {
|
|
2447
|
+
order: orderId,
|
|
2448
|
+
requested_message: reason,
|
|
2449
|
+
order_products: items.map((item) => ({
|
|
2450
|
+
id: item.orderLineId,
|
|
2451
|
+
qty: item.quantity,
|
|
2452
|
+
...item.unitTrackingIds ? { tracking_info_ids: item.unitTrackingIds } : {}
|
|
2453
|
+
}))
|
|
2454
|
+
}
|
|
2455
|
+
});
|
|
2456
|
+
return { id: wire.id };
|
|
2457
|
+
}
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
function toReturnableItem(wire) {
|
|
2461
|
+
return {
|
|
2462
|
+
orderLineId: wire.id,
|
|
2463
|
+
name: wire.product_name ?? "",
|
|
2464
|
+
photo: text(wire.product_photo),
|
|
2465
|
+
unitPrice: amount(wire.price) ?? 0,
|
|
2466
|
+
maxQuantity: wire.max_returnable_qty,
|
|
2467
|
+
unitTrackingIds: wire.unit_tracking_infos.map((unit) => unit.id)
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2470
|
+
function toReturnRequest(wire) {
|
|
2471
|
+
return {
|
|
2472
|
+
id: wire.id,
|
|
2473
|
+
status: wire.status,
|
|
2474
|
+
createdAt: wire.created_at,
|
|
2475
|
+
amount: amount(wire.final_amount) ?? 0,
|
|
2476
|
+
items: (wire.products ?? []).map((item) => ({
|
|
2477
|
+
id: item.id,
|
|
2478
|
+
name: item.product_name ?? "",
|
|
2479
|
+
quantity: item.qty,
|
|
2480
|
+
status: item.status
|
|
2481
|
+
}))
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
// src/http/exchanges.ts
|
|
2486
|
+
var CUSTOMER8 = { business: "required", customer: "required" };
|
|
2487
|
+
function createExchangesApi(request) {
|
|
2488
|
+
return {
|
|
2489
|
+
async create(input) {
|
|
2490
|
+
const wire = await request(
|
|
2491
|
+
"POST",
|
|
2492
|
+
"/order/exchange-replacement/customer/create",
|
|
2493
|
+
{ ...CUSTOMER8, ...exchangeBody(input) }
|
|
2494
|
+
);
|
|
2495
|
+
return toExchangeResult(wire);
|
|
2496
|
+
},
|
|
2497
|
+
async list(orderId) {
|
|
2498
|
+
const wire = await request(
|
|
2499
|
+
"GET",
|
|
2500
|
+
`/order/exchange-replacement/list/by/order/${orderId}`,
|
|
2501
|
+
CUSTOMER8
|
|
2502
|
+
);
|
|
2503
|
+
return wire.map(toExchangeListItem);
|
|
2504
|
+
},
|
|
2505
|
+
async detail(exchangeId) {
|
|
2506
|
+
return toExchangeDetail(
|
|
2507
|
+
await request(
|
|
2508
|
+
"GET",
|
|
2509
|
+
`/order/exchange-replacement/detail/${exchangeId}`,
|
|
2510
|
+
CUSTOMER8
|
|
2511
|
+
)
|
|
2512
|
+
);
|
|
2513
|
+
}
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
function exchangeBody({ orderId, type, reason, items }) {
|
|
2517
|
+
if (items.length === 0) throw new TypeError("exchanges.create: items must not be empty.");
|
|
2518
|
+
if (items.some((item) => !(item.quantity >= 1))) {
|
|
2519
|
+
throw new RangeError("exchanges.create: every quantity must be at least 1.");
|
|
2520
|
+
}
|
|
2521
|
+
if (type === "exchange" && items.some((item) => item.targetSkuId === void 0)) {
|
|
2522
|
+
throw new TypeError("exchanges.create: every exchange item needs a targetSkuId.");
|
|
2523
|
+
}
|
|
2524
|
+
const products = items.map((item) => ({
|
|
2525
|
+
order_product_id: item.orderLineId,
|
|
2526
|
+
qty: item.quantity,
|
|
2527
|
+
...type === "exchange" ? { target_sku_id: item.targetSkuId } : {},
|
|
2528
|
+
...item.reason !== void 0 ? { requested_message: item.reason } : {}
|
|
2529
|
+
}));
|
|
2530
|
+
if (items.every((item) => item.photo === void 0)) {
|
|
2531
|
+
return { json: { order_id: orderId, type, requested_message: reason, products } };
|
|
2532
|
+
}
|
|
2533
|
+
const files = Object.fromEntries(
|
|
2534
|
+
items.map((item, index) => [
|
|
2535
|
+
`request_media_${index}`,
|
|
2536
|
+
item.photo === void 0 ? void 0 : { file: item.photo }
|
|
2537
|
+
])
|
|
2538
|
+
);
|
|
2539
|
+
return {
|
|
2540
|
+
formData: multipart(
|
|
2541
|
+
{ order_id: orderId, type, requested_message: reason, products: JSON.stringify(products) },
|
|
2542
|
+
files,
|
|
2543
|
+
"Exchange photo"
|
|
2544
|
+
)
|
|
2545
|
+
};
|
|
2546
|
+
}
|
|
2547
|
+
function toExchangeResult(wire) {
|
|
2548
|
+
if (wire.action === "pay" && wire.payment.type !== "cod") {
|
|
2549
|
+
return { status: "payment-required", id: wire.id, payment: toPendingPayment(wire.payment) };
|
|
2550
|
+
}
|
|
2551
|
+
return { status: "submitted", id: wire.id, message: text(wire.message) };
|
|
2552
|
+
}
|
|
2553
|
+
function toExchangeListItem(wire) {
|
|
2554
|
+
return {
|
|
2555
|
+
id: wire.id,
|
|
2556
|
+
type: wire.type,
|
|
2557
|
+
status: wire.status,
|
|
2558
|
+
createdAt: wire.created_at,
|
|
2559
|
+
paymentId: wire.payment_id,
|
|
2560
|
+
itemCount: wire.products_count
|
|
2561
|
+
};
|
|
2562
|
+
}
|
|
2563
|
+
function toExchangeDetail(wire) {
|
|
2564
|
+
return {
|
|
2565
|
+
...toExchangeListItem({ ...wire, products_count: wire.products.length }),
|
|
2566
|
+
items: wire.products.map((row) => ({
|
|
2567
|
+
orderLineId: row.order_product,
|
|
2568
|
+
name: text(row.original_sku?.product_name),
|
|
2569
|
+
targetSkuId: row.target_sku,
|
|
2570
|
+
quantity: row.qty,
|
|
2571
|
+
priceDifference: amount(row.price_difference) ?? 0,
|
|
2572
|
+
status: row.status
|
|
2573
|
+
}))
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
// src/http/query.ts
|
|
2578
|
+
function buildQuery(query) {
|
|
2579
|
+
if (!query) return "";
|
|
2580
|
+
const parts = [];
|
|
2581
|
+
for (const [key, raw] of Object.entries(query)) {
|
|
2582
|
+
if (raw === void 0 || raw === null || raw === "") continue;
|
|
2583
|
+
let value;
|
|
2584
|
+
if (Array.isArray(raw)) {
|
|
2585
|
+
if (raw.length === 0) continue;
|
|
2586
|
+
value = raw.join(",");
|
|
2587
|
+
} else {
|
|
2588
|
+
value = String(raw);
|
|
2589
|
+
}
|
|
2590
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
2591
|
+
}
|
|
2592
|
+
return parts.length > 0 ? `?${parts.join("&")}` : "";
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
// src/http/client.ts
|
|
2596
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
2597
|
+
var runtime2 = globalThis;
|
|
2598
|
+
function createClient(options) {
|
|
2599
|
+
if (!options.baseURL) throw new Error("createClient: baseURL is required.");
|
|
2600
|
+
if (!options.fetch && typeof runtime2.fetch !== "function") {
|
|
2601
|
+
throw new Error("createClient: no global fetch in this runtime; pass the `fetch` option.");
|
|
2602
|
+
}
|
|
2603
|
+
const baseURL = options.baseURL.replace(/\/+$/, "");
|
|
2604
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2605
|
+
const doFetch = options.fetch ? (url, init) => options.fetch(url, init) : (url, init) => runtime2.fetch(url, init);
|
|
2606
|
+
const reported = {};
|
|
2607
|
+
async function request(method, path3, opts = {}) {
|
|
2608
|
+
const credentials = await options.credentials?.() ?? {};
|
|
2609
|
+
if (opts.business === "required" && (credentials.businessId == null || credentials.businessId === "")) {
|
|
2610
|
+
throw new Error(
|
|
2611
|
+
`${method} ${path3} needs the business: return businessId from credentials().`
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
if (opts.session === "required" && !credentials.sessionToken) {
|
|
2615
|
+
throw new Error(
|
|
2616
|
+
`${method} ${path3} needs a guest session: return sessionToken from credentials().`
|
|
2617
|
+
);
|
|
2618
|
+
}
|
|
2619
|
+
if (opts.customer === "required" && !credentials.customerToken) {
|
|
2620
|
+
throw new Error(
|
|
2621
|
+
`${method} ${path3} needs a logged-in customer: return customerToken from credentials().`
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2624
|
+
if (opts.merchant && !credentials.merchantToken) {
|
|
2625
|
+
throw new Error(
|
|
2626
|
+
`${method} ${path3} is a merchant request: return merchantToken from credentials().`
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2629
|
+
const headers = buildHeaders(credentials, opts);
|
|
2630
|
+
const binary = opts.responseType === "binary";
|
|
2631
|
+
if (binary) headers.accept = "*/*";
|
|
2632
|
+
if (opts.customerOrSession === "required" && !headers["x-customer-token"] && !headers["x-session-token"]) {
|
|
2633
|
+
throw new Error(
|
|
2634
|
+
`${method} ${path3} needs a customer or a guest session: return customerToken or sessionToken from credentials().`
|
|
2635
|
+
);
|
|
2636
|
+
}
|
|
2637
|
+
const init = { method, headers };
|
|
2638
|
+
if (opts.formData) {
|
|
2639
|
+
init.body = opts.formData;
|
|
2640
|
+
} else if (opts.json !== void 0) {
|
|
2641
|
+
headers["content-type"] = "application/json";
|
|
2642
|
+
init.body = JSON.stringify(opts.json);
|
|
2643
|
+
}
|
|
2644
|
+
const url = `${baseURL}/${path3.replace(/^\/+/, "")}${buildQuery(opts.query)}`;
|
|
2645
|
+
const { status: status2, ok, text: text2, data } = await send(url, init, opts.timeoutMs ?? timeoutMs, binary);
|
|
2646
|
+
if (data) return data;
|
|
2647
|
+
const body = parseBody(text2, ok, status2);
|
|
2648
|
+
if (ok) return body;
|
|
2649
|
+
if (status2 === 401) reportUnauthorized(headers);
|
|
2650
|
+
if (isDeadSession(status2, body, headers)) report("session", headers["x-session-token"]);
|
|
2651
|
+
throw new GrowupsellApiError({
|
|
2652
|
+
kind: "http",
|
|
2653
|
+
status: status2,
|
|
2654
|
+
message: messageFromBody(body) ?? `Request failed with status ${status2}`,
|
|
2655
|
+
fieldErrors: fieldErrorsFromBody(body),
|
|
2656
|
+
body
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
2659
|
+
async function send(url, init, ms, binary) {
|
|
2660
|
+
const controller = runtime2.AbortController ? new runtime2.AbortController() : void 0;
|
|
2661
|
+
if (controller) init.signal = controller.signal;
|
|
2662
|
+
let timedOut = false;
|
|
2663
|
+
let timer;
|
|
2664
|
+
const timeout = new Promise((_, reject) => {
|
|
2665
|
+
timer = runtime2.setTimeout(() => {
|
|
2666
|
+
timedOut = true;
|
|
2667
|
+
controller?.abort();
|
|
2668
|
+
reject(timeoutError(ms));
|
|
2669
|
+
}, ms);
|
|
2670
|
+
});
|
|
2671
|
+
try {
|
|
2672
|
+
return await Promise.race([
|
|
2673
|
+
doFetch(url, init).then(async (res) => ({
|
|
2674
|
+
status: res.status,
|
|
2675
|
+
ok: res.ok,
|
|
2676
|
+
// Error responses are read as text even for binary requests: they carry the message.
|
|
2677
|
+
text: binary && res.ok ? "" : await res.text(),
|
|
2678
|
+
data: binary && res.ok ? await readBinary(res) : void 0
|
|
2679
|
+
})),
|
|
2680
|
+
timeout
|
|
2681
|
+
]);
|
|
2682
|
+
} catch (error) {
|
|
2683
|
+
if (timedOut) throw timeoutError(ms);
|
|
2684
|
+
if (error instanceof GrowupsellApiError) throw error;
|
|
2685
|
+
throw new GrowupsellApiError({
|
|
2686
|
+
kind: "network",
|
|
2687
|
+
message: error instanceof Error ? error.message : "Network request failed"
|
|
2688
|
+
});
|
|
2689
|
+
} finally {
|
|
2690
|
+
runtime2.clearTimeout(timer);
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
function reportUnauthorized(headers) {
|
|
2694
|
+
const merchant = headers.authorization?.replace(/^Token /, "");
|
|
2695
|
+
const customer = headers["x-customer-token"];
|
|
2696
|
+
const kind = merchant ? "merchant" : customer ? "customer" : void 0;
|
|
2697
|
+
if (!kind) return;
|
|
2698
|
+
report(kind, kind === "merchant" ? merchant : customer);
|
|
2699
|
+
}
|
|
2700
|
+
function report(kind, token) {
|
|
2701
|
+
if (reported[kind] === token) return;
|
|
2702
|
+
reported[kind] = token;
|
|
2703
|
+
options.onUnauthorized?.({ kind });
|
|
2704
|
+
}
|
|
2705
|
+
return {
|
|
2706
|
+
request,
|
|
2707
|
+
business: createBusinessApi(request),
|
|
2708
|
+
catalog: createCatalogApi(request),
|
|
2709
|
+
products: createProductsApi(request),
|
|
2710
|
+
reviews: createReviewsApi(request),
|
|
2711
|
+
wishlist: createWishlistApi(request),
|
|
2712
|
+
policies: createPoliciesApi(request),
|
|
2713
|
+
faq: createFaqApi(request),
|
|
2714
|
+
themeContent: createThemeContentApi(request),
|
|
2715
|
+
productPage: createProductPageApi(request),
|
|
2716
|
+
customPages: createCustomPagesApi(request),
|
|
2717
|
+
session: createSessionApi(request),
|
|
2718
|
+
lookup: createLookupApi(request),
|
|
2719
|
+
auth: createAuthApi(request),
|
|
2720
|
+
customer: createCustomerApi(request),
|
|
2721
|
+
addresses: createAddressesApi(request),
|
|
2722
|
+
checkout: createCheckoutApi(request),
|
|
2723
|
+
payments: createPaymentsApi(request),
|
|
2724
|
+
blog: createBlogApi(request),
|
|
2725
|
+
forms: createFormsApi(request),
|
|
2726
|
+
helpdesk: createHelpdeskApi(request),
|
|
2727
|
+
newsletter: createNewsletterApi(request),
|
|
2728
|
+
liveSupport: createLiveSupportApi(request),
|
|
2729
|
+
customManufacturing: createCustomManufacturingApi(request),
|
|
2730
|
+
subscriptions: createSubscriptionsApi(request),
|
|
2731
|
+
cart: createCartApi(request),
|
|
2732
|
+
promotions: createPromotionsApi(request),
|
|
2733
|
+
orders: createOrdersApi(request),
|
|
2734
|
+
returns: createReturnsApi(request),
|
|
2735
|
+
exchanges: createExchangesApi(request)
|
|
2736
|
+
};
|
|
2737
|
+
}
|
|
2738
|
+
function buildHeaders(credentials, opts) {
|
|
2739
|
+
const headers = { accept: "application/json" };
|
|
2740
|
+
if (credentials.businessId != null && credentials.businessId !== "") {
|
|
2741
|
+
headers.business = String(credentials.businessId);
|
|
2742
|
+
}
|
|
2743
|
+
if (credentials.customerToken && !opts.anonymous) {
|
|
2744
|
+
headers["x-customer-token"] = credentials.customerToken;
|
|
2745
|
+
}
|
|
2746
|
+
if (credentials.sessionToken && opts.session !== "omit") {
|
|
2747
|
+
headers["x-session-token"] = credentials.sessionToken;
|
|
2748
|
+
}
|
|
2749
|
+
if (opts.merchant && credentials.merchantToken) {
|
|
2750
|
+
headers.authorization = `Token ${credentials.merchantToken}`;
|
|
2751
|
+
}
|
|
2752
|
+
return headers;
|
|
2753
|
+
}
|
|
2754
|
+
function isDeadSession(status2, body, headers) {
|
|
2755
|
+
return status2 === 404 && typeof body === "string" && !!headers["x-session-token"];
|
|
2756
|
+
}
|
|
2757
|
+
function parseBody(text2, ok, status2) {
|
|
2758
|
+
if (text2 === "") return void 0;
|
|
2759
|
+
try {
|
|
2760
|
+
return JSON.parse(text2);
|
|
2761
|
+
} catch {
|
|
2762
|
+
if (!ok) return text2;
|
|
2763
|
+
throw new GrowupsellApiError({
|
|
2764
|
+
kind: "parse",
|
|
2765
|
+
status: status2,
|
|
2766
|
+
message: "The server returned a response that is not valid JSON.",
|
|
2767
|
+
body: text2
|
|
2768
|
+
});
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
async function readBinary(res) {
|
|
2772
|
+
if (!res.arrayBuffer) {
|
|
2773
|
+
throw new GrowupsellApiError({
|
|
2774
|
+
kind: "parse",
|
|
2775
|
+
status: res.status,
|
|
2776
|
+
message: "This fetch cannot read binary responses."
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
return { contentType: res.headers?.get("content-type") ?? null, data: await res.arrayBuffer() };
|
|
2780
|
+
}
|
|
2781
|
+
function timeoutError(ms) {
|
|
2782
|
+
return new GrowupsellApiError({ kind: "timeout", message: `Request timed out after ${ms} ms` });
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2785
|
+
export {
|
|
2786
|
+
GrowupsellApiError,
|
|
2787
|
+
createClient
|
|
2788
|
+
};
|
|
2789
|
+
//# sourceMappingURL=chunk-YZJTPFCH.js.map
|