@cimplify/sdk 0.16.3 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.mts +2 -2
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.js +90 -2913
- package/dist/advanced.mjs +3 -2893
- package/dist/chunk-2JI47EYJ.mjs +2786 -0
- package/dist/chunk-DYKFSV77.js +2837 -0
- package/dist/chunk-FLPI2VVJ.js +72 -0
- package/dist/chunk-FTL2SXCG.mjs +674 -0
- package/dist/chunk-KTTQC5HG.mjs +687 -0
- package/dist/chunk-LM3CJ4L7.mjs +69 -0
- package/dist/chunk-MJECWMOY.js +692 -0
- package/dist/chunk-RYQ5IPWX.js +714 -0
- package/dist/chunk-S6TU55KP.js +170 -0
- package/dist/chunk-WDIMISRC.mjs +166 -0
- package/dist/{client-BaolRdB4.d.mts → client-B1UtuyOg.d.ts} +21 -12
- package/dist/{client-C59R79gx.d.ts → client-BFFfuzJr.d.mts} +21 -12
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +401 -4420
- package/dist/index.mjs +5 -4325
- package/dist/{payment-C6ULw3K-.d.mts → payment-D9FTaOse.d.mts} +66 -1
- package/dist/{payment-C6ULw3K-.d.ts → payment-D9FTaOse.d.ts} +66 -1
- package/dist/{price-CbR6DCt0.d.mts → price-9JsPuknm.d.mts} +1 -1
- package/dist/{price-Bd6JBV8W.d.ts → price-BD1iioLh.d.ts} +1 -1
- package/dist/react.d.mts +43 -11
- package/dist/react.d.ts +43 -11
- package/dist/react.js +540 -3981
- package/dist/react.mjs +489 -3933
- package/dist/styles.css +1 -1
- package/dist/utils.d.mts +5 -5
- package/dist/utils.d.ts +5 -5
- package/dist/utils.js +122 -721
- package/dist/utils.mjs +2 -695
- package/package.json +1 -1
- package/registry/add-on-selector.json +1 -1
- package/registry/catalogue-page.json +1 -1
- package/registry/checkout-page.json +1 -1
- package/registry/composite-selector.json +1 -1
- package/registry/product-grid.json +1 -1
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkDYKFSV77_js = require('./chunk-DYKFSV77.js');
|
|
4
|
+
var chunkRYQ5IPWX_js = require('./chunk-RYQ5IPWX.js');
|
|
5
|
+
|
|
6
|
+
// src/activity.ts
|
|
7
|
+
var ActivityService = class {
|
|
8
|
+
constructor(client) {
|
|
9
|
+
this.client = client;
|
|
10
|
+
}
|
|
11
|
+
trackProductView(productId, options = {}) {
|
|
12
|
+
const event = {
|
|
13
|
+
type: "product_view",
|
|
14
|
+
product_id: productId,
|
|
15
|
+
product_name: options.productName,
|
|
16
|
+
category_id: options.categoryId,
|
|
17
|
+
price: options.price,
|
|
18
|
+
page_path: options.pagePath ?? currentPath()
|
|
19
|
+
};
|
|
20
|
+
this.sendEvents([event]);
|
|
21
|
+
}
|
|
22
|
+
trackCategoryView(categoryId, options = {}) {
|
|
23
|
+
const event = {
|
|
24
|
+
type: "category_view",
|
|
25
|
+
category_id: categoryId,
|
|
26
|
+
category_name: options.categoryName,
|
|
27
|
+
page_path: options.pagePath ?? currentPath()
|
|
28
|
+
};
|
|
29
|
+
this.sendEvents([event]);
|
|
30
|
+
}
|
|
31
|
+
sendEvents(events) {
|
|
32
|
+
try {
|
|
33
|
+
this.client.post("/api/v1/activity/events", { events }).catch(() => {
|
|
34
|
+
});
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function currentPath() {
|
|
40
|
+
if (typeof window !== "undefined") {
|
|
41
|
+
return window.location.pathname;
|
|
42
|
+
}
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/client.ts
|
|
47
|
+
var ACCESS_TOKEN_STORAGE_KEY = "cimplify_access_token";
|
|
48
|
+
var SESSION_TOKEN_STORAGE_KEY = "cimplify_session_token";
|
|
49
|
+
var ORDER_TOKEN_PREFIX = "cimplify_ot_";
|
|
50
|
+
var SESSION_TOKEN_HEADER = "x-session-token";
|
|
51
|
+
var ORDER_TOKEN_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
52
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
53
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
54
|
+
var DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
55
|
+
function sleep(ms) {
|
|
56
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
57
|
+
}
|
|
58
|
+
function isRetryable(error) {
|
|
59
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (error instanceof chunkRYQ5IPWX_js.CimplifyError) {
|
|
66
|
+
return error.retryable;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
function toNetworkError(error, isTestMode) {
|
|
71
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
72
|
+
return chunkRYQ5IPWX_js.enrichError(
|
|
73
|
+
new chunkRYQ5IPWX_js.CimplifyError(
|
|
74
|
+
chunkRYQ5IPWX_js.ErrorCode.TIMEOUT,
|
|
75
|
+
"Request timed out. Please check your connection and try again.",
|
|
76
|
+
true
|
|
77
|
+
),
|
|
78
|
+
{ isTestMode }
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
82
|
+
return chunkRYQ5IPWX_js.enrichError(
|
|
83
|
+
new chunkRYQ5IPWX_js.CimplifyError(
|
|
84
|
+
chunkRYQ5IPWX_js.ErrorCode.NETWORK_ERROR,
|
|
85
|
+
"Network error. Please check your internet connection.",
|
|
86
|
+
true
|
|
87
|
+
),
|
|
88
|
+
{ isTestMode }
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (error instanceof chunkRYQ5IPWX_js.CimplifyError) {
|
|
92
|
+
return chunkRYQ5IPWX_js.enrichError(error, { isTestMode });
|
|
93
|
+
}
|
|
94
|
+
return chunkRYQ5IPWX_js.enrichError(
|
|
95
|
+
new chunkRYQ5IPWX_js.CimplifyError(
|
|
96
|
+
chunkRYQ5IPWX_js.ErrorCode.UNKNOWN_ERROR,
|
|
97
|
+
error instanceof Error ? error.message : "An unknown error occurred",
|
|
98
|
+
false
|
|
99
|
+
),
|
|
100
|
+
{ isTestMode }
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
function deriveUrls() {
|
|
104
|
+
const hostname = typeof window !== "undefined" ? window.location.hostname : "";
|
|
105
|
+
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
106
|
+
const protocol = window.location.protocol;
|
|
107
|
+
return {
|
|
108
|
+
baseUrl: `${protocol}//${hostname}:8082`,
|
|
109
|
+
linkApiUrl: `${protocol}//${hostname}:8080`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
baseUrl: "https://storefronts.cimplify.io",
|
|
114
|
+
linkApiUrl: "https://api.cimplify.io"
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function normalizeUrl(url) {
|
|
118
|
+
const trimmed = url.trim();
|
|
119
|
+
if (!trimmed) return trimmed;
|
|
120
|
+
return trimmed.replace(/\/+$/, "");
|
|
121
|
+
}
|
|
122
|
+
function getEnvPublicKey() {
|
|
123
|
+
try {
|
|
124
|
+
const env = globalThis.process;
|
|
125
|
+
return env?.env.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || void 0;
|
|
126
|
+
} catch {
|
|
127
|
+
return void 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
var CimplifyClient = class {
|
|
131
|
+
constructor(config = {}) {
|
|
132
|
+
this.accessToken = null;
|
|
133
|
+
this.sessionToken = null;
|
|
134
|
+
this.context = {};
|
|
135
|
+
this.businessId = null;
|
|
136
|
+
this.businessIdResolvePromise = null;
|
|
137
|
+
this.inflightRequests = /* @__PURE__ */ new Map();
|
|
138
|
+
this.publicKey = config.publicKey || getEnvPublicKey() || "";
|
|
139
|
+
const urls = deriveUrls();
|
|
140
|
+
this.baseUrl = config.baseUrl ? normalizeUrl(config.baseUrl) : urls.baseUrl;
|
|
141
|
+
this.linkApiUrl = config.linkApiUrl ? normalizeUrl(config.linkApiUrl) : urls.linkApiUrl;
|
|
142
|
+
this.credentials = config.credentials || "include";
|
|
143
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
144
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
145
|
+
this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
|
|
146
|
+
this.hooks = config.hooks ?? {};
|
|
147
|
+
this.accessToken = this.loadAccessToken();
|
|
148
|
+
this.sessionToken = this.loadSessionToken();
|
|
149
|
+
if (!this.publicKey && !config.suppressPublicKeyWarning) {
|
|
150
|
+
console.warn(
|
|
151
|
+
'[Cimplify] No public key found. Set NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY in your environment, or pass { publicKey: "pk_..." } to createCimplifyClient().'
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
buildUrl(base, path) {
|
|
156
|
+
const url = `${base}${path}`;
|
|
157
|
+
const locationId = this.context.location_id;
|
|
158
|
+
if (!locationId) return url;
|
|
159
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
160
|
+
return `${url}${separator}location_id=${encodeURIComponent(locationId)}`;
|
|
161
|
+
}
|
|
162
|
+
getAccessToken() {
|
|
163
|
+
return this.accessToken;
|
|
164
|
+
}
|
|
165
|
+
getPublicKey() {
|
|
166
|
+
return this.publicKey;
|
|
167
|
+
}
|
|
168
|
+
isTestMode() {
|
|
169
|
+
return this.publicKey.trim().startsWith("pk_test_");
|
|
170
|
+
}
|
|
171
|
+
setAccessToken(token) {
|
|
172
|
+
const previous = this.accessToken;
|
|
173
|
+
this.accessToken = token;
|
|
174
|
+
this.saveAccessToken(token);
|
|
175
|
+
this.hooks.onSessionChange?.({
|
|
176
|
+
previousToken: previous,
|
|
177
|
+
newToken: token,
|
|
178
|
+
source: "manual"
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
clearSession() {
|
|
182
|
+
const previous = this.accessToken;
|
|
183
|
+
this.accessToken = null;
|
|
184
|
+
this.sessionToken = null;
|
|
185
|
+
this.saveAccessToken(null);
|
|
186
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
187
|
+
localStorage.removeItem(SESSION_TOKEN_STORAGE_KEY);
|
|
188
|
+
}
|
|
189
|
+
this.hooks.onSessionChange?.({
|
|
190
|
+
previousToken: previous,
|
|
191
|
+
newToken: null,
|
|
192
|
+
source: "clear"
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
setOrderToken(orderId, token) {
|
|
196
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
197
|
+
try {
|
|
198
|
+
const entry = JSON.stringify({ token, storedAt: Date.now() });
|
|
199
|
+
localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
getOrderToken(orderId) {
|
|
205
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
206
|
+
try {
|
|
207
|
+
const raw = localStorage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
|
|
208
|
+
if (!raw) return null;
|
|
209
|
+
const entry = JSON.parse(raw);
|
|
210
|
+
if (Date.now() - entry.storedAt > ORDER_TOKEN_TTL_MS) {
|
|
211
|
+
localStorage.removeItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
return entry.token;
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
clearOrderTokens() {
|
|
222
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
223
|
+
const keysToRemove = [];
|
|
224
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
225
|
+
const key = localStorage.key(i);
|
|
226
|
+
if (key?.startsWith(ORDER_TOKEN_PREFIX)) {
|
|
227
|
+
keysToRemove.push(key);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
keysToRemove.forEach((k) => localStorage.removeItem(k));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
setLocationId(locationId) {
|
|
234
|
+
if (locationId) {
|
|
235
|
+
this.context.location_id = locationId;
|
|
236
|
+
} else {
|
|
237
|
+
delete this.context.location_id;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
getLocationId() {
|
|
241
|
+
return this.context.location_id ?? null;
|
|
242
|
+
}
|
|
243
|
+
setBusinessId(businessId) {
|
|
244
|
+
const normalized = businessId.trim();
|
|
245
|
+
if (!normalized) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
this.businessId = normalized;
|
|
249
|
+
}
|
|
250
|
+
getBusinessId() {
|
|
251
|
+
return this.businessId;
|
|
252
|
+
}
|
|
253
|
+
async resolveBusinessId() {
|
|
254
|
+
if (this.businessId) {
|
|
255
|
+
return this.businessId;
|
|
256
|
+
}
|
|
257
|
+
if (this.businessIdResolvePromise) {
|
|
258
|
+
return this.businessIdResolvePromise;
|
|
259
|
+
}
|
|
260
|
+
this.businessIdResolvePromise = (async () => {
|
|
261
|
+
const result = await this.business.getInfo();
|
|
262
|
+
if (!result.ok || !result.value?.id) {
|
|
263
|
+
throw new chunkRYQ5IPWX_js.CimplifyError(
|
|
264
|
+
chunkRYQ5IPWX_js.ErrorCode.NOT_FOUND,
|
|
265
|
+
"Unable to resolve business ID from the current public key.",
|
|
266
|
+
true
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
this.businessId = result.value.id;
|
|
270
|
+
return result.value.id;
|
|
271
|
+
})();
|
|
272
|
+
try {
|
|
273
|
+
return await this.businessIdResolvePromise;
|
|
274
|
+
} finally {
|
|
275
|
+
this.businessIdResolvePromise = null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
loadAccessToken() {
|
|
279
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
280
|
+
return localStorage.getItem(ACCESS_TOKEN_STORAGE_KEY);
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
saveAccessToken(token) {
|
|
285
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
286
|
+
try {
|
|
287
|
+
if (token) {
|
|
288
|
+
localStorage.setItem(ACCESS_TOKEN_STORAGE_KEY, token);
|
|
289
|
+
} else {
|
|
290
|
+
localStorage.removeItem(ACCESS_TOKEN_STORAGE_KEY);
|
|
291
|
+
}
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
loadSessionToken() {
|
|
297
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
298
|
+
return localStorage.getItem(SESSION_TOKEN_STORAGE_KEY);
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
saveSessionToken(token) {
|
|
303
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
304
|
+
try {
|
|
305
|
+
localStorage.setItem(SESSION_TOKEN_STORAGE_KEY, token);
|
|
306
|
+
} catch {
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
captureSessionToken(response) {
|
|
311
|
+
const token = response.headers.get(SESSION_TOKEN_HEADER);
|
|
312
|
+
if (token && token !== this.sessionToken) {
|
|
313
|
+
this.sessionToken = token;
|
|
314
|
+
this.saveSessionToken(token);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
getHeaders() {
|
|
318
|
+
const headers = {
|
|
319
|
+
"Content-Type": "application/json"
|
|
320
|
+
};
|
|
321
|
+
const trimmedPublicKey = this.publicKey.trim();
|
|
322
|
+
if (trimmedPublicKey) {
|
|
323
|
+
headers["X-API-Key"] = trimmedPublicKey;
|
|
324
|
+
}
|
|
325
|
+
if (this.accessToken) {
|
|
326
|
+
headers["Authorization"] = `Bearer ${this.accessToken}`;
|
|
327
|
+
}
|
|
328
|
+
if (this.sessionToken) {
|
|
329
|
+
headers[SESSION_TOKEN_HEADER] = this.sessionToken;
|
|
330
|
+
}
|
|
331
|
+
return headers;
|
|
332
|
+
}
|
|
333
|
+
async resilientFetch(url, options) {
|
|
334
|
+
const method = options.method || "GET";
|
|
335
|
+
const path = url.replace(this.baseUrl, "").replace(this.linkApiUrl, "");
|
|
336
|
+
const startTime = Date.now();
|
|
337
|
+
let retryCount = 0;
|
|
338
|
+
const context = {
|
|
339
|
+
method,
|
|
340
|
+
path,
|
|
341
|
+
url,
|
|
342
|
+
body: options.body ? JSON.parse(options.body) : void 0,
|
|
343
|
+
startTime
|
|
344
|
+
};
|
|
345
|
+
this.hooks.onRequestStart?.(context);
|
|
346
|
+
let lastError;
|
|
347
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
348
|
+
try {
|
|
349
|
+
const controller = new AbortController();
|
|
350
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
351
|
+
const response = await fetch(url, {
|
|
352
|
+
...options,
|
|
353
|
+
signal: controller.signal
|
|
354
|
+
});
|
|
355
|
+
clearTimeout(timeoutId);
|
|
356
|
+
this.captureSessionToken(response);
|
|
357
|
+
if (response.ok) {
|
|
358
|
+
this.hooks.onRequestSuccess?.({
|
|
359
|
+
...context,
|
|
360
|
+
status: response.status,
|
|
361
|
+
durationMs: Date.now() - startTime
|
|
362
|
+
});
|
|
363
|
+
return response;
|
|
364
|
+
}
|
|
365
|
+
if (response.status === 429 && attempt < this.maxRetries) {
|
|
366
|
+
retryCount++;
|
|
367
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
368
|
+
const delay = retryAfter ? Math.min(parseInt(retryAfter, 10) * 1e3, 3e4) || this.retryDelay * Math.pow(2, attempt) : this.retryDelay * Math.pow(2, attempt);
|
|
369
|
+
this.hooks.onRetry?.({
|
|
370
|
+
...context,
|
|
371
|
+
attempt: retryCount,
|
|
372
|
+
delayMs: delay,
|
|
373
|
+
error: new Error(`Rate limited: ${response.status}`)
|
|
374
|
+
});
|
|
375
|
+
await sleep(delay);
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (response.status >= 400 && response.status < 500) {
|
|
379
|
+
this.hooks.onRequestError?.({
|
|
380
|
+
...context,
|
|
381
|
+
error: new chunkRYQ5IPWX_js.CimplifyError(
|
|
382
|
+
`HTTP_${response.status}`,
|
|
383
|
+
`Request failed with status ${response.status}`,
|
|
384
|
+
false
|
|
385
|
+
),
|
|
386
|
+
status: response.status,
|
|
387
|
+
durationMs: Date.now() - startTime,
|
|
388
|
+
retryCount,
|
|
389
|
+
retryable: false
|
|
390
|
+
});
|
|
391
|
+
return response;
|
|
392
|
+
}
|
|
393
|
+
if (response.status >= 500 && attempt < this.maxRetries) {
|
|
394
|
+
retryCount++;
|
|
395
|
+
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
396
|
+
this.hooks.onRetry?.({
|
|
397
|
+
...context,
|
|
398
|
+
attempt: retryCount,
|
|
399
|
+
delayMs: delay,
|
|
400
|
+
error: new Error(`Server error: ${response.status}`)
|
|
401
|
+
});
|
|
402
|
+
await sleep(delay);
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
this.hooks.onRequestError?.({
|
|
406
|
+
...context,
|
|
407
|
+
error: new chunkRYQ5IPWX_js.CimplifyError(
|
|
408
|
+
"SERVER_ERROR",
|
|
409
|
+
`Server error ${response.status} after ${retryCount} retries`,
|
|
410
|
+
false
|
|
411
|
+
),
|
|
412
|
+
status: response.status,
|
|
413
|
+
durationMs: Date.now() - startTime,
|
|
414
|
+
retryCount,
|
|
415
|
+
retryable: false
|
|
416
|
+
});
|
|
417
|
+
return response;
|
|
418
|
+
} catch (error) {
|
|
419
|
+
lastError = error;
|
|
420
|
+
const networkError = toNetworkError(error, this.isTestMode());
|
|
421
|
+
const errorRetryable = isRetryable(error);
|
|
422
|
+
if (!errorRetryable || attempt >= this.maxRetries) {
|
|
423
|
+
this.hooks.onRequestError?.({
|
|
424
|
+
...context,
|
|
425
|
+
error: networkError,
|
|
426
|
+
durationMs: Date.now() - startTime,
|
|
427
|
+
retryCount,
|
|
428
|
+
retryable: errorRetryable
|
|
429
|
+
});
|
|
430
|
+
throw networkError;
|
|
431
|
+
}
|
|
432
|
+
retryCount++;
|
|
433
|
+
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
434
|
+
this.hooks.onRetry?.({
|
|
435
|
+
...context,
|
|
436
|
+
attempt: retryCount,
|
|
437
|
+
delayMs: delay,
|
|
438
|
+
error: networkError
|
|
439
|
+
});
|
|
440
|
+
await sleep(delay);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const finalError = toNetworkError(lastError, this.isTestMode());
|
|
444
|
+
this.hooks.onRequestError?.({
|
|
445
|
+
...context,
|
|
446
|
+
error: finalError,
|
|
447
|
+
durationMs: Date.now() - startTime,
|
|
448
|
+
retryCount,
|
|
449
|
+
retryable: false
|
|
450
|
+
});
|
|
451
|
+
throw finalError;
|
|
452
|
+
}
|
|
453
|
+
getDedupeKey(type, payload) {
|
|
454
|
+
return `${type}:${JSON.stringify(payload)}`;
|
|
455
|
+
}
|
|
456
|
+
async deduplicatedRequest(key, requestFn) {
|
|
457
|
+
const existing = this.inflightRequests.get(key);
|
|
458
|
+
if (existing) {
|
|
459
|
+
return existing;
|
|
460
|
+
}
|
|
461
|
+
const request = requestFn().finally(() => {
|
|
462
|
+
this.inflightRequests.delete(key);
|
|
463
|
+
});
|
|
464
|
+
this.inflightRequests.set(key, request);
|
|
465
|
+
return request;
|
|
466
|
+
}
|
|
467
|
+
async get(path) {
|
|
468
|
+
const key = this.getDedupeKey("get", path);
|
|
469
|
+
return this.deduplicatedRequest(key, async () => {
|
|
470
|
+
const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
|
|
471
|
+
method: "GET",
|
|
472
|
+
credentials: this.credentials,
|
|
473
|
+
headers: this.getHeaders()
|
|
474
|
+
});
|
|
475
|
+
return this.handleRestResponse(response);
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
async post(path, body) {
|
|
479
|
+
const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
|
|
480
|
+
method: "POST",
|
|
481
|
+
credentials: this.credentials,
|
|
482
|
+
headers: this.getHeaders(),
|
|
483
|
+
body: body ? JSON.stringify(body) : void 0
|
|
484
|
+
});
|
|
485
|
+
return this.handleRestResponse(response);
|
|
486
|
+
}
|
|
487
|
+
async patch(path, body) {
|
|
488
|
+
const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
|
|
489
|
+
method: "PATCH",
|
|
490
|
+
credentials: this.credentials,
|
|
491
|
+
headers: this.getHeaders(),
|
|
492
|
+
body: body ? JSON.stringify(body) : void 0
|
|
493
|
+
});
|
|
494
|
+
return this.handleRestResponse(response);
|
|
495
|
+
}
|
|
496
|
+
async delete(path) {
|
|
497
|
+
const response = await this.resilientFetch(this.buildUrl(this.baseUrl, path), {
|
|
498
|
+
method: "DELETE",
|
|
499
|
+
credentials: this.credentials,
|
|
500
|
+
headers: this.getHeaders()
|
|
501
|
+
});
|
|
502
|
+
return this.handleRestResponse(response);
|
|
503
|
+
}
|
|
504
|
+
async linkGet(path) {
|
|
505
|
+
const key = this.getDedupeKey("linkGet", path);
|
|
506
|
+
return this.deduplicatedRequest(key, async () => {
|
|
507
|
+
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|
|
508
|
+
method: "GET",
|
|
509
|
+
credentials: this.credentials,
|
|
510
|
+
headers: this.getHeaders()
|
|
511
|
+
});
|
|
512
|
+
return this.handleRestResponse(response);
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
async linkPost(path, body) {
|
|
516
|
+
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|
|
517
|
+
method: "POST",
|
|
518
|
+
credentials: this.credentials,
|
|
519
|
+
headers: this.getHeaders(),
|
|
520
|
+
body: body ? JSON.stringify(body) : void 0
|
|
521
|
+
});
|
|
522
|
+
return this.handleRestResponse(response);
|
|
523
|
+
}
|
|
524
|
+
async linkDelete(path) {
|
|
525
|
+
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|
|
526
|
+
method: "DELETE",
|
|
527
|
+
credentials: this.credentials,
|
|
528
|
+
headers: this.getHeaders()
|
|
529
|
+
});
|
|
530
|
+
return this.handleRestResponse(response);
|
|
531
|
+
}
|
|
532
|
+
async handleRestResponse(response) {
|
|
533
|
+
const json = await response.json();
|
|
534
|
+
if (!response.ok) {
|
|
535
|
+
const errorCode = typeof json.error === "object" && json.error?.error_code || typeof json.error === "object" && json.error?.code || "API_ERROR";
|
|
536
|
+
const errorMessage = typeof json.error === "object" && json.error?.error_message || typeof json.error === "object" && json.error?.message || typeof json.error === "string" && json.error || typeof json.message === "string" && json.message || "An error occurred";
|
|
537
|
+
const retryable = typeof json.error === "object" && typeof json.error?.retryable === "boolean" ? json.error.retryable : false;
|
|
538
|
+
const error = chunkRYQ5IPWX_js.enrichError(
|
|
539
|
+
new chunkRYQ5IPWX_js.CimplifyError(
|
|
540
|
+
errorCode,
|
|
541
|
+
errorMessage,
|
|
542
|
+
retryable
|
|
543
|
+
),
|
|
544
|
+
{ isTestMode: this.isTestMode() }
|
|
545
|
+
);
|
|
546
|
+
if (response.status === 401 || error.code === chunkRYQ5IPWX_js.ErrorCode.UNAUTHORIZED) {
|
|
547
|
+
console.warn(
|
|
548
|
+
"[Cimplify] Received 401 Unauthorized. Access token may be missing/expired. Refresh authentication and retry the request."
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
if (json?.success === false || json?.error?.code || json?.error?.message) {
|
|
554
|
+
const error = chunkRYQ5IPWX_js.enrichError(
|
|
555
|
+
new chunkRYQ5IPWX_js.CimplifyError(
|
|
556
|
+
json.error?.code || "API_ERROR",
|
|
557
|
+
json.error?.message || "An error occurred",
|
|
558
|
+
json.error?.retryable || false
|
|
559
|
+
),
|
|
560
|
+
{ isTestMode: this.isTestMode() }
|
|
561
|
+
);
|
|
562
|
+
throw error;
|
|
563
|
+
}
|
|
564
|
+
if (json?.data !== void 0) {
|
|
565
|
+
return json.data;
|
|
566
|
+
}
|
|
567
|
+
return json;
|
|
568
|
+
}
|
|
569
|
+
get catalogue() {
|
|
570
|
+
if (!this._catalogue) {
|
|
571
|
+
this._catalogue = new chunkDYKFSV77_js.CatalogueQueries(this);
|
|
572
|
+
}
|
|
573
|
+
return this._catalogue;
|
|
574
|
+
}
|
|
575
|
+
get cart() {
|
|
576
|
+
if (!this._cart) {
|
|
577
|
+
this._cart = new chunkDYKFSV77_js.CartOperations(this);
|
|
578
|
+
}
|
|
579
|
+
return this._cart;
|
|
580
|
+
}
|
|
581
|
+
get checkout() {
|
|
582
|
+
if (!this._checkout) {
|
|
583
|
+
this._checkout = new chunkDYKFSV77_js.CheckoutService(this);
|
|
584
|
+
}
|
|
585
|
+
return this._checkout;
|
|
586
|
+
}
|
|
587
|
+
get orders() {
|
|
588
|
+
if (!this._orders) {
|
|
589
|
+
this._orders = new chunkDYKFSV77_js.OrderQueries(this);
|
|
590
|
+
}
|
|
591
|
+
return this._orders;
|
|
592
|
+
}
|
|
593
|
+
get link() {
|
|
594
|
+
if (!this._link) {
|
|
595
|
+
this._link = new chunkDYKFSV77_js.LinkService(this);
|
|
596
|
+
}
|
|
597
|
+
return this._link;
|
|
598
|
+
}
|
|
599
|
+
get auth() {
|
|
600
|
+
if (!this._auth) {
|
|
601
|
+
this._auth = new chunkDYKFSV77_js.AuthService(this);
|
|
602
|
+
}
|
|
603
|
+
return this._auth;
|
|
604
|
+
}
|
|
605
|
+
get business() {
|
|
606
|
+
if (!this._business) {
|
|
607
|
+
this._business = new chunkDYKFSV77_js.BusinessService(this);
|
|
608
|
+
}
|
|
609
|
+
return this._business;
|
|
610
|
+
}
|
|
611
|
+
get inventory() {
|
|
612
|
+
if (!this._inventory) {
|
|
613
|
+
this._inventory = new chunkDYKFSV77_js.InventoryService(this);
|
|
614
|
+
}
|
|
615
|
+
return this._inventory;
|
|
616
|
+
}
|
|
617
|
+
get scheduling() {
|
|
618
|
+
if (!this._scheduling) {
|
|
619
|
+
this._scheduling = new chunkDYKFSV77_js.SchedulingService(this);
|
|
620
|
+
}
|
|
621
|
+
return this._scheduling;
|
|
622
|
+
}
|
|
623
|
+
get lite() {
|
|
624
|
+
if (!this._lite) {
|
|
625
|
+
this._lite = new chunkDYKFSV77_js.LiteService(this);
|
|
626
|
+
}
|
|
627
|
+
return this._lite;
|
|
628
|
+
}
|
|
629
|
+
get fx() {
|
|
630
|
+
if (!this._fx) {
|
|
631
|
+
this._fx = new chunkDYKFSV77_js.FxService(this);
|
|
632
|
+
}
|
|
633
|
+
return this._fx;
|
|
634
|
+
}
|
|
635
|
+
get activity() {
|
|
636
|
+
if (!this._activity) {
|
|
637
|
+
this._activity = new ActivityService(this);
|
|
638
|
+
}
|
|
639
|
+
return this._activity;
|
|
640
|
+
}
|
|
641
|
+
elements(businessId, options) {
|
|
642
|
+
if (businessId) {
|
|
643
|
+
this.setBusinessId(businessId);
|
|
644
|
+
}
|
|
645
|
+
return chunkDYKFSV77_js.createElements(this, businessId ?? this.businessId ?? void 0, options);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
function createCimplifyClient(config = {}) {
|
|
649
|
+
return new CimplifyClient(config);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// src/utils/variant.ts
|
|
653
|
+
function stripProductPrefix(variantName, productName) {
|
|
654
|
+
if (!variantName || !productName) return variantName || productName;
|
|
655
|
+
const lower = variantName.toLowerCase().trim();
|
|
656
|
+
if (lower === "default" || lower === "standard") return productName;
|
|
657
|
+
if (lower.endsWith("-default") || lower.endsWith("-standard")) return productName;
|
|
658
|
+
if (variantName.startsWith(productName)) {
|
|
659
|
+
const rest = variantName.slice(productName.length);
|
|
660
|
+
const match = rest.match(/^\s*[-–—]\s*(.*)/);
|
|
661
|
+
if (match && match[1].length > 0) return match[1];
|
|
662
|
+
}
|
|
663
|
+
const lowerProduct = productName.toLowerCase().trim();
|
|
664
|
+
if (lower.startsWith(lowerProduct)) {
|
|
665
|
+
const rest = variantName.slice(productName.length);
|
|
666
|
+
const match = rest.match(/^\s*[-–—]\s*(.*)/);
|
|
667
|
+
if (match && match[1].length > 0) return match[1];
|
|
668
|
+
}
|
|
669
|
+
const lastDash = variantName.lastIndexOf("-");
|
|
670
|
+
if (lastDash > 0 && lastDash < variantName.length - 1) {
|
|
671
|
+
const prefix = variantName.slice(0, lastDash).trim();
|
|
672
|
+
const suffix = variantName.slice(lastDash + 1).trim();
|
|
673
|
+
if (suffix.length > 0 && prefix.length > suffix.length * 2) {
|
|
674
|
+
return suffix;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return variantName;
|
|
678
|
+
}
|
|
679
|
+
function getVariantDisplayName(variant, productName) {
|
|
680
|
+
if (variant.display_attributes?.length) {
|
|
681
|
+
return variant.display_attributes.map((a) => a.value_name).join(" / ");
|
|
682
|
+
}
|
|
683
|
+
if (variant.name) {
|
|
684
|
+
return productName ? stripProductPrefix(variant.name, productName) : variant.name;
|
|
685
|
+
}
|
|
686
|
+
return productName || (variant.is_default ? "Default" : "Option");
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
exports.ActivityService = ActivityService;
|
|
690
|
+
exports.CimplifyClient = CimplifyClient;
|
|
691
|
+
exports.createCimplifyClient = createCimplifyClient;
|
|
692
|
+
exports.getVariantDisplayName = getVariantDisplayName;
|