arky-sdk 0.9.20 → 0.11.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.
@@ -42,70 +42,50 @@ var COMMON_ACTION_KEYS = [
42
42
  "share",
43
43
  "wishlist.added"
44
44
  ];
45
- var createActionApi = (apiConfig) => ({
45
+ var createActionApi = (apiConfig, lifecycle) => ({
46
46
  COMMON_ACTION_KEYS,
47
47
  async track(params) {
48
+ await lifecycle.ensureVisitorSession();
48
49
  try {
49
- await apiConfig.httpClient.post(
50
- `/v1/storefront/${apiConfig.storeId}/actions/track`,
51
- { key: params.key, payload: params.payload }
52
- );
50
+ await apiConfig.httpClient.post("/v1/storefront/actions/track", {
51
+ key: params.key,
52
+ payload: params.payload
53
+ });
53
54
  } catch {
54
55
  }
55
56
  }
56
57
  });
57
- var createStorefrontApi = (apiConfig, updateContactSession) => {
58
- const base = (storeId = apiConfig.storeId) => `/v1/storefront/${storeId}`;
59
- const pendingVerifications = /* @__PURE__ */ new Map();
58
+ var createStorefrontApi = (apiConfig, updateContactSession, lifecycle) => {
59
+ const base = "/v1/storefront";
60
60
  function persistIdentification(result) {
61
- const issued = result.token;
62
- if (issued?.token) {
61
+ const sessionToken = result.token?.token;
62
+ if (sessionToken) {
63
63
  updateContactSession(() => ({
64
- access_token: issued.token,
65
- contact: result.contact,
66
- store: result.store,
67
- market: result.market
64
+ sessionToken,
65
+ contact: result.contact
68
66
  }));
69
67
  } else {
70
- if (result.verification_challenge) {
71
- pendingVerifications.set(result.verification_challenge.challenge_id, {
72
- store: result.store,
73
- market: result.market
74
- });
75
- }
76
68
  updateContactSession(
77
- (current) => current ? {
78
- ...current,
79
- contact: result.contact,
80
- store: result.store,
81
- market: result.market
82
- } : null
69
+ (current) => current ? { ...current, contact: result.contact } : null
83
70
  );
84
71
  }
85
72
  return result;
86
73
  }
87
74
  async function submitIdentification(path, params, options) {
88
- const store_id = apiConfig.storeId;
89
75
  const result = await apiConfig.httpClient.post(
90
- `${base(store_id)}/account/${path}`,
91
- {
92
- store_id,
93
- market: params?.market || apiConfig.market || null,
94
- email: params?.email
95
- },
76
+ `${base}/account/${path}`,
77
+ { email: params?.email },
96
78
  options
97
79
  );
98
80
  return persistIdentification(result);
99
81
  }
100
82
  return {
101
83
  store: {
102
- getStore(options) {
103
- return apiConfig.httpClient.get(base(), options);
104
- },
84
+ getSetup: lifecycle.getSetup,
105
85
  location: {
106
86
  getCountries(options) {
107
87
  return apiConfig.httpClient.get(
108
- `/v1/platform/countries`,
88
+ "/v1/platform/countries",
109
89
  options
110
90
  );
111
91
  },
@@ -117,13 +97,13 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
117
97
  },
118
98
  list(options) {
119
99
  return apiConfig.httpClient.get(
120
- `${base()}/locations`,
100
+ `${base}/locations`,
121
101
  options
122
102
  );
123
103
  },
124
104
  get(id, options) {
125
105
  return apiConfig.httpClient.get(
126
- `${base()}/locations/${id}`,
106
+ `${base}/locations/${id}`,
127
107
  options
128
108
  );
129
109
  }
@@ -131,13 +111,13 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
131
111
  market: {
132
112
  list(options) {
133
113
  return apiConfig.httpClient.get(
134
- `${base()}/markets`,
114
+ `${base}/markets`,
135
115
  options
136
116
  );
137
117
  },
138
118
  get(id, options) {
139
119
  return apiConfig.httpClient.get(
140
- `${base()}/markets/${id}`,
120
+ `${base}/markets/${id}`,
141
121
  options
142
122
  );
143
123
  }
@@ -146,85 +126,59 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
146
126
  cms: {
147
127
  collection: {
148
128
  get(params, options) {
149
- const store_id = params.store_id || apiConfig.storeId;
150
- const identifier = params.id !== void 0 ? params.id : `${store_id}:${params.key}`;
129
+ const identifier = params.id ?? params.key;
151
130
  return apiConfig.httpClient.get(
152
- `${base(store_id)}/collections/${identifier}`,
131
+ `${base}/collections/${identifier}`,
153
132
  options
154
133
  );
155
134
  }
156
135
  },
157
136
  entry: {
158
137
  get(params, options) {
159
- const store_id = params.store_id || apiConfig.storeId;
160
- if (!params.id) {
161
- throw new Error("GetEntryParams requires id");
162
- }
163
138
  return apiConfig.httpClient.get(
164
- `${base(store_id)}/entries/${params.id}`,
139
+ `${base}/entries/${params.id}`,
165
140
  options
166
141
  );
167
142
  },
168
143
  find(params, options) {
169
- const { store_id, ...queryParams } = params;
170
144
  return apiConfig.httpClient.get(
171
- `${base(store_id)}/entries`,
172
- {
173
- ...options,
174
- params: queryParams
175
- }
145
+ `${base}/entries`,
146
+ { ...options, params }
176
147
  );
177
148
  }
178
149
  },
179
150
  form: {
180
151
  get(params, options) {
181
- const store_id = params.store_id || apiConfig.storeId;
182
- let identifier;
183
- if (params.id) {
184
- identifier = params.id;
185
- } else if (params.key) {
186
- identifier = `${store_id}:${params.key}`;
187
- } else {
188
- throw new Error("GetFormParams requires id or key");
189
- }
152
+ const identifier = params.id ?? params.key;
153
+ if (!identifier) throw new Error("GetFormParams requires id or key");
190
154
  return apiConfig.httpClient.get(
191
- `${base(store_id)}/forms/${identifier}`,
155
+ `${base}/forms/${identifier}`,
192
156
  options
193
157
  );
194
158
  },
195
- submit(params, options) {
196
- const { store_id, form_id, ...payload } = params;
197
- const target_store_id = store_id || apiConfig.storeId;
198
- if (!form_id) {
199
- throw new Error("SubmitFormParams requires form_id");
200
- }
159
+ async submit(params, options) {
160
+ await lifecycle.ensureVisitorSession();
161
+ const { form_id, ...payload } = params;
162
+ if (!form_id) throw new Error("SubmitFormParams requires form_id");
201
163
  return apiConfig.httpClient.post(
202
- `${base(target_store_id)}/forms/${form_id}/submissions`,
203
- { ...payload, form_id, store_id: target_store_id },
164
+ `${base}/forms/${form_id}/submissions`,
165
+ { ...payload, form_id },
204
166
  options
205
167
  );
206
168
  }
207
169
  },
208
170
  taxonomy: {
209
171
  get(params, options) {
210
- const store_id = params.store_id || apiConfig.storeId;
211
- let identifier;
212
- if (params.id) {
213
- identifier = params.id;
214
- } else if (params.key) {
215
- identifier = `${store_id}:${params.key}`;
216
- } else {
217
- throw new Error("GetTaxonomyParams requires id or key");
218
- }
172
+ const identifier = params.id ?? params.key;
173
+ if (!identifier) throw new Error("GetTaxonomyParams requires id or key");
219
174
  return apiConfig.httpClient.get(
220
- `${base(store_id)}/taxonomies/${identifier}`,
175
+ `${base}/taxonomies/${identifier}`,
221
176
  options
222
177
  );
223
178
  },
224
179
  getChildren(params, options) {
225
- const store_id = params.store_id || apiConfig.storeId;
226
180
  return apiConfig.httpClient.get(
227
- `${base(store_id)}/taxonomies/${params.id}/children`,
181
+ `${base}/taxonomies/${params.id}/children`,
228
182
  options
229
183
  );
230
184
  }
@@ -233,113 +187,106 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
233
187
  eshop: {
234
188
  product: {
235
189
  get(params, options) {
236
- const store_id = params.store_id || apiConfig.storeId;
237
- let identifier;
238
- if (params.id) {
239
- identifier = params.id;
240
- } else if (params.slug) {
241
- identifier = `${store_id}:${apiConfig.locale}:${params.slug}`;
242
- } else {
243
- throw new Error("GetProductParams requires id or slug");
244
- }
190
+ const identifier = params.id ?? params.slug;
191
+ if (!identifier) throw new Error("GetProductParams requires id or slug");
245
192
  return apiConfig.httpClient.get(
246
- `${base(store_id)}/products/${identifier}`,
193
+ `${base}/products/${identifier}`,
247
194
  options
248
195
  );
249
196
  },
250
197
  find(params, options) {
251
- const { store_id, ...queryParams } = params;
252
198
  return apiConfig.httpClient.get(
253
- `${base(store_id)}/products`,
254
- {
255
- ...options,
256
- params: queryParams
257
- }
199
+ `${base}/products`,
200
+ { ...options, params }
258
201
  );
259
202
  }
260
203
  },
261
204
  cart: {
262
- current(params = {}, options) {
263
- const store_id = params.store_id || apiConfig.storeId;
264
- const { store_id: _store_id, ...payload } = params;
205
+ async current(options) {
206
+ await lifecycle.ensureVisitorSession();
265
207
  return apiConfig.httpClient.post(
266
- `${base(store_id)}/carts/current`,
267
- {
268
- ...payload,
269
- store_id,
270
- market: payload.market || apiConfig.market
271
- },
208
+ `${base}/carts/current`,
209
+ {},
272
210
  options
273
211
  );
274
212
  },
275
- get(params, options) {
276
- const store_id = params.store_id || apiConfig.storeId;
213
+ async get(params, options) {
214
+ await lifecycle.ensureVisitorSession();
215
+ const queryParams = Object.fromEntries(
216
+ Object.entries(
217
+ options?.params || {}
218
+ ).filter(
219
+ ([name]) => !["token", "cart_token"].includes(name.toLowerCase())
220
+ )
221
+ );
222
+ const headers = Object.fromEntries(
223
+ Object.entries(options?.headers || {}).filter(
224
+ ([name]) => name.toLowerCase() !== "x-arky-cart-token"
225
+ )
226
+ );
277
227
  return apiConfig.httpClient.get(
278
- `${base(store_id)}/carts/${params.id}`,
228
+ `${base}/carts/${params.id}`,
279
229
  {
280
230
  ...options,
281
- params: params.token ? { token: params.token } : options?.params
231
+ headers: {
232
+ ...headers,
233
+ ...params.token ? { "X-Arky-Cart-Token": params.token } : {}
234
+ },
235
+ params: Object.keys(queryParams).length > 0 ? queryParams : void 0
282
236
  }
283
237
  );
284
238
  },
285
- update(params, options) {
286
- const { store_id, items, ...payload } = params;
287
- const target = store_id || apiConfig.storeId;
239
+ async update(params, options) {
240
+ await lifecycle.ensureVisitorSession();
241
+ const { items, ...payload } = params;
288
242
  return apiConfig.httpClient.put(
289
- `${base(target)}/carts/${params.id}`,
243
+ `${base}/carts/${params.id}`,
290
244
  {
291
245
  ...payload,
292
- store_id: target,
293
246
  ...items ? { items: sanitizePublicCheckoutItems(items) } : {}
294
247
  },
295
248
  options
296
249
  );
297
250
  },
298
- addItem(params, options) {
299
- const { store_id, item, ...payload } = params;
300
- const target = store_id || apiConfig.storeId;
251
+ async addItem(params, options) {
252
+ await lifecycle.ensureVisitorSession();
253
+ const { item, ...payload } = params;
301
254
  return apiConfig.httpClient.post(
302
- `${base(target)}/carts/${params.id}/items`,
303
- {
304
- ...payload,
305
- store_id: target,
306
- item: sanitizePublicCheckoutItems([item])[0]
307
- },
255
+ `${base}/carts/${params.id}/items`,
256
+ { ...payload, item: sanitizePublicCheckoutItems([item])[0] },
308
257
  options
309
258
  );
310
259
  },
311
- removeItem(params, options) {
312
- const { store_id, ...payload } = params;
313
- const target = store_id || apiConfig.storeId;
260
+ async removeItem(params, options) {
261
+ await lifecycle.ensureVisitorSession();
314
262
  return apiConfig.httpClient.post(
315
- `${base(target)}/carts/${params.id}/items/remove`,
316
- { ...payload, store_id: target },
263
+ `${base}/carts/${params.id}/items/remove`,
264
+ params,
317
265
  options
318
266
  );
319
267
  },
320
- clear(params, options) {
321
- const store_id = params.store_id || apiConfig.storeId;
268
+ async clear(params, options) {
269
+ await lifecycle.ensureVisitorSession();
322
270
  return apiConfig.httpClient.post(
323
- `${base(store_id)}/carts/${params.id}/clear`,
324
- { id: params.id, store_id },
271
+ `${base}/carts/${params.id}/clear`,
272
+ { id: params.id },
325
273
  options
326
274
  );
327
275
  },
328
- quote(params, options) {
329
- const store_id = params.store_id || apiConfig.storeId;
276
+ async quote(params, options) {
277
+ await lifecycle.ensureVisitorSession();
330
278
  return apiConfig.httpClient.post(
331
- `${base(store_id)}/carts/${params.id}/quote`,
332
- { id: params.id, store_id },
279
+ `${base}/carts/${params.id}/quote`,
280
+ { id: params.id },
333
281
  options
334
282
  );
335
283
  },
336
- checkout(params, options) {
337
- const store_id = params.store_id || apiConfig.storeId;
284
+ async checkout(params, options) {
285
+ await lifecycle.ensureVisitorSession();
338
286
  return apiConfig.httpClient.post(
339
- `${base(store_id)}/carts/${params.id}/checkout`,
287
+ `${base}/carts/${params.id}/checkout`,
340
288
  {
341
289
  id: params.id,
342
- store_id,
343
290
  payment_method_key: params.payment_method_key,
344
291
  confirmation_token_id: params.confirmation_token_id,
345
292
  return_url: params.return_url
@@ -349,115 +296,85 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
349
296
  }
350
297
  },
351
298
  order: {
352
- get(params, options) {
353
- const store_id = params.store_id || apiConfig.storeId;
299
+ async get(params, options) {
300
+ await lifecycle.ensureVisitorSession();
354
301
  return apiConfig.httpClient.get(
355
- `${base(store_id)}/orders/${params.id}`,
302
+ `${base}/orders/${params.id}`,
356
303
  options
357
304
  );
358
305
  },
359
- find(params, options) {
360
- const { store_id, ...queryParams } = params;
306
+ async find(params, options) {
307
+ await lifecycle.ensureVisitorSession();
361
308
  return apiConfig.httpClient.get(
362
- `${base(store_id)}/orders`,
363
- {
364
- ...options,
365
- params: queryParams
366
- }
309
+ `${base}/orders`,
310
+ { ...options, params }
367
311
  );
368
312
  },
369
- downloadDigitalAccess(params, options) {
370
- const store_id = params.store_id || apiConfig.storeId;
313
+ async downloadDigitalAccess(params, options) {
314
+ await lifecycle.ensureVisitorSession();
371
315
  return apiConfig.httpClient.post(
372
- `${base(store_id)}/orders/${params.order_id}/digital-access/${params.grant_id}/download`,
316
+ `${base}/orders/${params.order_id}/digital-access/${params.grant_id}/download`,
373
317
  {},
374
318
  options
375
319
  );
376
320
  },
377
- findDigitalAccess(params, options) {
378
- const { order_id, store_id, ...queryParams } = params;
321
+ async findDigitalAccess(params, options) {
322
+ await lifecycle.ensureVisitorSession();
323
+ const { order_id, ...queryParams } = params;
379
324
  return apiConfig.httpClient.get(
380
- `${base(store_id)}/orders/${order_id}/digital-access`,
325
+ `${base}/orders/${order_id}/digital-access`,
381
326
  { ...options, params: queryParams }
382
327
  );
383
328
  },
384
- getDigitalAccess(params, options) {
385
- const store_id = params.store_id || apiConfig.storeId;
329
+ async getDigitalAccess(params, options) {
330
+ await lifecycle.ensureVisitorSession();
386
331
  return apiConfig.httpClient.get(
387
- `${base(store_id)}/orders/${params.order_id}/digital-access/${params.grant_id}`,
332
+ `${base}/orders/${params.order_id}/digital-access/${params.grant_id}`,
388
333
  options
389
334
  );
390
335
  }
391
336
  },
392
337
  service: {
393
338
  get(params, options) {
394
- const store_id = params.store_id || apiConfig.storeId;
395
- let identifier;
396
- if (params.id) {
397
- identifier = params.id;
398
- } else if (params.slug) {
399
- identifier = `${store_id}:${apiConfig.locale}:${params.slug}`;
400
- } else {
401
- throw new Error("GetServiceParams requires id or slug");
402
- }
339
+ const identifier = params.id ?? params.slug;
340
+ if (!identifier) throw new Error("GetServiceParams requires id or slug");
403
341
  return apiConfig.httpClient.get(
404
- `${base(store_id)}/services/${identifier}`,
342
+ `${base}/services/${identifier}`,
405
343
  options
406
344
  );
407
345
  },
408
346
  find(params, options) {
409
- const { store_id, ...queryParams } = params;
410
347
  return apiConfig.httpClient.get(
411
- `${base(store_id)}/services`,
412
- {
413
- ...options,
414
- params: queryParams
415
- }
348
+ `${base}/services`,
349
+ { ...options, params }
416
350
  );
417
351
  },
418
352
  findProviders(params, options) {
419
- const { store_id, ...queryParams } = params;
420
353
  return apiConfig.httpClient.get(
421
- `${base(store_id)}/service-providers`,
422
- {
423
- ...options,
424
- params: queryParams
425
- }
354
+ `${base}/service-providers`,
355
+ { ...options, params }
426
356
  );
427
357
  },
428
358
  getAvailability(params, options) {
429
- const { store_id, ...queryParams } = params;
430
- const target_store_id = store_id || apiConfig.storeId;
431
359
  return apiConfig.httpClient.get(
432
- `${base(target_store_id)}/services/availability`,
433
- { ...options, params: queryParams }
360
+ `${base}/services/availability`,
361
+ { ...options, params }
434
362
  );
435
363
  }
436
364
  },
437
365
  provider: {
438
366
  get(params, options) {
439
- const store_id = params.store_id || apiConfig.storeId;
440
- let identifier;
441
- if (params.id) {
442
- identifier = params.id;
443
- } else if (params.slug) {
444
- identifier = `${store_id}:${apiConfig.locale}:${params.slug}`;
445
- } else {
446
- throw new Error("GetProviderParams requires id or slug");
447
- }
367
+ const identifier = params.id ?? params.slug;
368
+ if (!identifier) throw new Error("GetProviderParams requires id or slug");
448
369
  return apiConfig.httpClient.get(
449
- `${base(store_id)}/providers/${identifier}`,
370
+ `${base}/providers/${identifier}`,
450
371
  options
451
372
  );
452
373
  },
453
374
  find(params, options) {
454
- const { store_id, ...queryParams } = params;
455
375
  return apiConfig.httpClient.get(
456
- `${base(store_id)}/providers`,
457
- {
458
- ...options,
459
- params: queryParams
460
- }
376
+ `${base}/providers`,
377
+ { ...options, params }
461
378
  );
462
379
  }
463
380
  }
@@ -471,36 +388,23 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
471
388
  return submitIdentification("code", params, options);
472
389
  },
473
390
  async verify(params, options) {
474
- const store_id = apiConfig.storeId;
475
391
  const result = await apiConfig.httpClient.post(
476
- `${base(store_id)}/account/verify`,
477
- { store_id, challenge_id: params.challenge_id, code: params.code },
392
+ `${base}/account/verify`,
393
+ params,
478
394
  options
479
395
  );
480
- if (result?.token?.token) {
481
- const pending = pendingVerifications.get(params.challenge_id);
482
- const identifiedStore = pending?.store || await apiConfig.httpClient.get(base(store_id), options);
483
- updateContactSession(
484
- (prev) => prev ? {
485
- ...prev,
486
- access_token: result.token.token,
487
- contact: result.contact
488
- } : {
489
- access_token: result.token.token,
490
- contact: result.contact,
491
- store: identifiedStore,
492
- market: pending?.market || null
493
- }
494
- );
495
- pendingVerifications.delete(params.challenge_id);
396
+ if (result.token?.token) {
397
+ updateContactSession(() => ({
398
+ sessionToken: result.token.token,
399
+ contact: result.contact
400
+ }));
496
401
  }
497
402
  return result;
498
403
  },
499
404
  async logout(options) {
500
- const store_id = apiConfig.storeId;
501
405
  try {
502
406
  await apiConfig.httpClient.post(
503
- `${base(store_id)}/account/logout`,
407
+ `${base}/account/logout`,
504
408
  {},
505
409
  options
506
410
  );
@@ -510,110 +414,74 @@ var createStorefrontApi = (apiConfig, updateContactSession) => {
510
414
  },
511
415
  getMe(options) {
512
416
  return apiConfig.httpClient.get(
513
- `${base()}/account/me`,
417
+ `${base}/account/me`,
514
418
  options
515
419
  );
516
420
  }
517
421
  },
518
422
  contactList: {
519
423
  get(params, options) {
520
- const store_id = params.store_id || apiConfig.storeId;
521
424
  return apiConfig.httpClient.get(
522
- `${base(store_id)}/contact-lists/${params.id}`,
425
+ `${base}/contact-lists/${params.id}`,
523
426
  options
524
427
  );
525
428
  },
526
- find(params, options) {
527
- const { store_id, ...queryParams } = params || {};
429
+ find(params = {}, options) {
528
430
  return apiConfig.httpClient.get(
529
- `${base(store_id)}/contact-lists`,
530
- {
531
- ...options,
532
- params: queryParams
533
- }
431
+ `${base}/contact-lists`,
432
+ { ...options, params }
534
433
  );
535
434
  },
536
435
  plans: {
537
436
  find(params, options) {
538
- const { store_id, contact_list_id, ...queryParams } = params;
437
+ const { contact_list_id, ...queryParams } = params;
539
438
  return apiConfig.httpClient.get(
540
- `${base(store_id)}/contact-lists/${contact_list_id}/plans`,
439
+ `${base}/contact-lists/${contact_list_id}/plans`,
541
440
  { ...options, params: queryParams }
542
441
  );
543
442
  }
544
443
  },
545
444
  memberships: {
546
- find(params, options) {
547
- const { store_id, ...queryParams } = params || {};
548
- return apiConfig.httpClient.get(`${base(store_id)}/contact-lists/memberships`, {
445
+ async find(params = {}, options) {
446
+ await lifecycle.ensureVisitorSession();
447
+ return apiConfig.httpClient.get(`${base}/contact-lists/memberships`, {
549
448
  ...options,
550
- params: queryParams
449
+ params
551
450
  });
552
451
  }
553
452
  },
554
- subscribe(params, options) {
555
- const { store_id, id, ...payload } = params;
453
+ async subscribe(params, options) {
454
+ await lifecycle.ensureVisitorSession();
455
+ const { id, ...payload } = params;
556
456
  return apiConfig.httpClient.post(
557
- `${base(store_id)}/contact-lists/${id}/subscribe`,
457
+ `${base}/contact-lists/${id}/subscribe`,
558
458
  payload,
559
459
  options
560
460
  );
561
461
  },
562
- checkAccess(params, options) {
563
- const store_id = params.store_id || apiConfig.storeId;
462
+ async checkAccess(params, options) {
463
+ await lifecycle.ensureVisitorSession();
564
464
  return apiConfig.httpClient.get(
565
- `${base(store_id)}/contact-lists/${params.id}/access`,
566
- options
567
- );
568
- },
569
- checkContentAccess(params, options) {
570
- const { store_id, ...payload } = params;
571
- return apiConfig.httpClient.post(
572
- `${base(store_id)}/contact-lists/access`,
573
- payload,
574
- options
575
- );
576
- },
577
- manage(token, options) {
578
- return apiConfig.httpClient.post(
579
- `${base()}/contact-lists/manage`,
580
- { token },
465
+ `${base}/contact-lists/${params.id}/access`,
581
466
  options
582
467
  );
583
468
  },
584
- unsubscribe(token, options) {
585
- const headers = { ...options?.headers };
586
- for (const name of Object.keys(headers)) {
587
- if (name.toLowerCase() === "content-type") delete headers[name];
588
- }
469
+ async checkContentAccess(params, options) {
470
+ await lifecycle.ensureVisitorSession();
589
471
  return apiConfig.httpClient.post(
590
- `${base()}/contact-lists/unsubscribe`,
591
- new URLSearchParams({ "List-Unsubscribe": "One-Click" }),
592
- {
593
- ...options,
594
- params: { ...options?.params || {}, token },
595
- headers: {
596
- ...headers,
597
- "Content-Type": "application/x-www-form-urlencoded"
598
- }
599
- }
600
- );
601
- },
602
- confirm(token, options) {
603
- return apiConfig.httpClient.post(
604
- `${base()}/contact-lists/confirm`,
605
- { token },
472
+ `${base}/contact-lists/access`,
473
+ params,
606
474
  options
607
475
  );
608
476
  }
609
477
  }
610
478
  },
611
- action: createActionApi(apiConfig),
479
+ action: createActionApi(apiConfig, lifecycle),
612
480
  experiments: {
613
- use(params, options) {
614
- const store_id = params.store_id || apiConfig.storeId;
481
+ async use(params, options) {
482
+ await lifecycle.ensureVisitorSession();
615
483
  return apiConfig.httpClient.post(
616
- `${base(store_id)}/experiments/use`,
484
+ `${base}/experiments/use`,
617
485
  { key: params.key },
618
486
  options
619
487
  );
@@ -773,6 +641,15 @@ function requestError(name, message, details = {}) {
773
641
  function isRecord(value) {
774
642
  return typeof value === "object" && value !== null;
775
643
  }
644
+ function omitStorefrontRouting(value) {
645
+ if (!isRecord(value) || Array.isArray(value)) return value;
646
+ const prototype = Object.getPrototypeOf(value);
647
+ if (prototype !== Object.prototype && prototype !== null) return value;
648
+ const result = { ...value };
649
+ delete result.store_id;
650
+ delete result.market;
651
+ return result;
652
+ }
776
653
  function isTokenSet(value) {
777
654
  return isRecord(value) && typeof value.access_token === "string" && (value.refresh_token === void 0 || typeof value.refresh_token === "string") && (value.access_expires_at === void 0 || typeof value.access_expires_at === "number");
778
655
  }
@@ -848,10 +725,25 @@ function createHttpClient(cfg) {
848
725
  if (!retried && options?.transformRequest) {
849
726
  body = options.transformRequest(body);
850
727
  }
728
+ if (cfg.storefrontMode) {
729
+ body = omitStorefrontRouting(body);
730
+ }
731
+ const forcedHeaders = typeof cfg.forcedHeaders === "function" ? cfg.forcedHeaders() : cfg.forcedHeaders || {};
732
+ const callerHeaders = { ...options?.headers || {} };
733
+ const protectedHeaderNames = new Set(
734
+ Object.keys(forcedHeaders).map((name) => name.toLowerCase())
735
+ );
736
+ if (cfg.storefrontMode) protectedHeaderNames.add("authorization");
737
+ for (const name of Object.keys(callerHeaders)) {
738
+ if (protectedHeaderNames.has(name.toLowerCase())) {
739
+ delete callerHeaders[name];
740
+ }
741
+ }
851
742
  const headers = {
852
743
  Accept: "application/json",
853
744
  "Content-Type": "application/json",
854
- ...options?.headers || {}
745
+ ...callerHeaders,
746
+ ...forcedHeaders
855
747
  };
856
748
  let tokens = authStorage.getTokens();
857
749
  const nowSec = Date.now() / 1e3;
@@ -862,7 +754,8 @@ function createHttpClient(cfg) {
862
754
  if (tokens?.access_token) {
863
755
  headers["Authorization"] = `Bearer ${tokens.access_token}`;
864
756
  }
865
- const finalPath = options?.params ? path + buildQueryString(options.params) : path;
757
+ const requestParams = cfg.storefrontMode ? omitStorefrontRouting(options?.params) : options?.params;
758
+ const finalPath = requestParams ? path + buildQueryString(requestParams) : path;
866
759
  const fetchOptions = {
867
760
  method,
868
761
  headers,
@@ -893,8 +786,19 @@ function createHttpClient(cfg) {
893
786
  throw err;
894
787
  }
895
788
  if (res.status === 401 && !retried) {
896
- await ensureFreshToken();
897
- return request(method, path, body, options, true);
789
+ if (cfg.onUnauthorized) {
790
+ const recovered = await cfg.onUnauthorized({
791
+ hadAuthorization: Boolean(tokens?.access_token),
792
+ authorizationToken: tokens?.access_token || null,
793
+ path
794
+ });
795
+ if (recovered) {
796
+ return request(method, path, body, options, true);
797
+ }
798
+ } else {
799
+ await ensureFreshToken();
800
+ return request(method, path, body, options, true);
801
+ }
898
802
  }
899
803
  try {
900
804
  const contentLength = res.headers.get("content-length");
@@ -975,13 +879,6 @@ function createHttpClient(cfg) {
975
879
  }
976
880
 
977
881
  // src/api/support.ts
978
- function supportConversationQuery(params) {
979
- const qs = new URLSearchParams({ store_id: params.store_id });
980
- if (params.message_limit) qs.set("message_limit", String(params.message_limit));
981
- if (typeof params.after_created_at === "number") qs.set("after_created_at", String(params.after_created_at));
982
- if (params.after_id) qs.set("after_id", params.after_id);
983
- return qs.toString();
984
- }
985
882
  function storefrontSupportOptions(supportToken, options) {
986
883
  if (!/^[0-9a-f]{64}$/.test(supportToken)) {
987
884
  throw new Error("support_token must be a 64-character lowercase hexadecimal token");
@@ -998,32 +895,38 @@ function storefrontSupportOptions(supportToken, options) {
998
895
  }
999
896
  };
1000
897
  }
1001
- function createStorefrontSupportApi(config) {
898
+ function createStorefrontSupportApi(config, ensureVisitorSession) {
1002
899
  const { httpClient } = config;
1003
900
  return {
1004
901
  async startConversation(params = {}, opts) {
1005
- const storeId = config.storeId;
902
+ await ensureVisitorSession();
1006
903
  return httpClient.post(
1007
- `/v1/storefront/${storeId}/support/conversations`,
1008
- { ...params, store_id: storeId },
904
+ "/v1/storefront/support/conversations",
905
+ params,
1009
906
  opts
1010
907
  );
1011
908
  },
1012
909
  async sendMessage(params, opts) {
910
+ await ensureVisitorSession();
1013
911
  const { support_token, ...request } = params;
1014
- const storeId = config.storeId;
1015
912
  return httpClient.post(
1016
- `/v1/storefront/${storeId}/support/conversations/${request.conversation_id}/messages`,
1017
- { ...request, store_id: storeId },
913
+ `/v1/storefront/support/conversations/${request.conversation_id}/messages`,
914
+ request,
1018
915
  storefrontSupportOptions(support_token, opts)
1019
916
  );
1020
917
  },
1021
918
  async getConversation(params, opts) {
919
+ await ensureVisitorSession();
1022
920
  const { support_token, ...request } = params;
1023
- const storeId = config.storeId;
1024
- const qs = supportConversationQuery({ ...request, store_id: storeId });
921
+ const query = new URLSearchParams();
922
+ if (request.message_limit) query.set("message_limit", String(request.message_limit));
923
+ if (typeof request.after_created_at === "number") {
924
+ query.set("after_created_at", String(request.after_created_at));
925
+ }
926
+ if (request.after_id) query.set("after_id", request.after_id);
927
+ const suffix = query.size ? `?${query}` : "";
1025
928
  return httpClient.get(
1026
- `/v1/storefront/${storeId}/support/conversations/${request.conversation_id}?${qs}`,
929
+ `/v1/storefront/support/conversations/${request.conversation_id}${suffix}`,
1027
930
  storefrontSupportOptions(support_token, opts)
1028
931
  );
1029
932
  }
@@ -1481,280 +1384,6 @@ function getFirstAvailableFCId(variant, quantity = 1) {
1481
1384
  return inv?.location_id;
1482
1385
  }
1483
1386
 
1484
- // src/index.ts
1485
- function createUtilitySurface(apiConfig) {
1486
- return {
1487
- getImageUrl: (imageBlock, isBlock2 = true) => getImageUrl(imageBlock, isBlock2),
1488
- getBlockValue,
1489
- getBlockTextValue,
1490
- getBlockContentValue,
1491
- getBlockValues,
1492
- getBlockLabel,
1493
- getBlockObjectValues,
1494
- getBlockFromArray,
1495
- formatBlockValue,
1496
- prepareBlocksForSubmission,
1497
- extractBlockValues,
1498
- formatPrice: (prices) => formatPrice(prices, apiConfig.market),
1499
- getPriceAmount: (prices) => getPriceAmount(prices, apiConfig.market),
1500
- formatPayment,
1501
- formatMinor,
1502
- getCurrencySymbol,
1503
- getCurrencyName,
1504
- validatePhoneNumber,
1505
- tzGroups,
1506
- findTimeZone,
1507
- slugify,
1508
- humanize,
1509
- categorify,
1510
- formatDate,
1511
- getSvgContentForAstro,
1512
- fetchSvgContent,
1513
- injectSvgIntoElement,
1514
- isValidKey,
1515
- validateKey,
1516
- toKey,
1517
- nameToKey,
1518
- getAvailableStock,
1519
- getReservedStock,
1520
- hasStock,
1521
- getInventoryAt,
1522
- getFirstAvailableFCId
1523
- };
1524
- }
1525
- function defaultStorefrontSessionStorage() {
1526
- if (typeof window === "undefined") return null;
1527
- try {
1528
- return window.localStorage;
1529
- } catch {
1530
- return null;
1531
- }
1532
- }
1533
- function storefrontSessionStorageKey(baseUrl, storeId) {
1534
- const normalizedBaseUrl = baseUrl.trim().replace(/\/+$/, "").toLowerCase();
1535
- return `arky_contact_session:${encodeURIComponent(normalizedBaseUrl)}:${encodeURIComponent(storeId)}`;
1536
- }
1537
- function createStorefrontClient(config) {
1538
- const locale = config.locale || "en";
1539
- const initialMarket = config.market || "";
1540
- const listeners = /* @__PURE__ */ new Set();
1541
- let bareIdentifyPromise = null;
1542
- let identityTail = Promise.resolve();
1543
- const sessionStorage = config.sessionStorage || defaultStorefrontSessionStorage();
1544
- let memorySession = null;
1545
- function readContactSession() {
1546
- if (!sessionStorage) return memorySession;
1547
- try {
1548
- const raw = sessionStorage.getItem(
1549
- storefrontSessionStorageKey(config.baseUrl, config.storeId)
1550
- );
1551
- return raw ? JSON.parse(raw) : null;
1552
- } catch {
1553
- return memorySession;
1554
- }
1555
- }
1556
- function writeContactSession(session) {
1557
- memorySession = session;
1558
- if (!sessionStorage) return;
1559
- const key = storefrontSessionStorageKey(config.baseUrl, config.storeId);
1560
- try {
1561
- if (session) {
1562
- sessionStorage.setItem(key, JSON.stringify(session));
1563
- } else {
1564
- sessionStorage.removeItem(key);
1565
- }
1566
- } catch {
1567
- }
1568
- }
1569
- function toPublic(s) {
1570
- return s ? { contact: s.contact, store: s.store, market: s.market } : null;
1571
- }
1572
- function emit() {
1573
- const pub = toPublic(readContactSession());
1574
- for (const l of listeners) {
1575
- Promise.resolve().then(() => l(pub)).catch(() => {
1576
- });
1577
- }
1578
- }
1579
- const updateSession = (updater) => {
1580
- if (config.apiToken) return;
1581
- const prev = readContactSession();
1582
- const next = updater(prev);
1583
- writeContactSession(next);
1584
- emit();
1585
- };
1586
- const authStorage = config.apiToken ? {
1587
- getTokens: () => ({ access_token: config.apiToken }),
1588
- onTokensRefreshed: () => {
1589
- },
1590
- onForcedLogout: () => {
1591
- }
1592
- } : {
1593
- getTokens() {
1594
- const s = readContactSession();
1595
- return s ? { access_token: s.access_token } : null;
1596
- },
1597
- onTokensRefreshed() {
1598
- },
1599
- onForcedLogout() {
1600
- bareIdentifyPromise = null;
1601
- updateSession(() => null);
1602
- }
1603
- };
1604
- const httpClient = createHttpClient({
1605
- baseUrl: config.baseUrl,
1606
- storeId: config.storeId,
1607
- refreshPath: config.refreshPath,
1608
- navigate: config.navigate,
1609
- loginFallbackPath: config.loginFallbackPath,
1610
- authStorage
1611
- });
1612
- const apiConfig = {
1613
- httpClient,
1614
- storeId: config.storeId,
1615
- baseUrl: config.baseUrl,
1616
- market: initialMarket,
1617
- locale,
1618
- authStorage
1619
- };
1620
- const storefrontApi = createStorefrontApi(apiConfig, updateSession);
1621
- const contactApi = storefrontApi.crm.contact;
1622
- function identify(params) {
1623
- if (params?.market !== void 0) apiConfig.market = params.market;
1624
- const market = apiConfig.market;
1625
- const isBareCall = !params?.email && !params?.verify;
1626
- if (isBareCall && bareIdentifyPromise) return bareIdentifyPromise;
1627
- const run = async () => {
1628
- try {
1629
- const result = await (params?.verify ? contactApi.requestCode({
1630
- market,
1631
- email: params.email
1632
- }) : contactApi.identify({
1633
- market,
1634
- email: params?.email
1635
- }));
1636
- return {
1637
- contact: result.contact,
1638
- store: result.store,
1639
- market: result.market,
1640
- verification_challenge: result.verification_challenge
1641
- };
1642
- } catch (err) {
1643
- const e = err;
1644
- const status = e?.statusCode || e?.status || e?.response?.status;
1645
- if (isBareCall && status === 401) {
1646
- updateSession(() => null);
1647
- const result = await contactApi.identify({
1648
- market
1649
- });
1650
- return {
1651
- contact: result.contact,
1652
- store: result.store,
1653
- market: result.market,
1654
- verification_challenge: result.verification_challenge
1655
- };
1656
- }
1657
- throw err;
1658
- }
1659
- };
1660
- const promise = identityTail.then(run);
1661
- identityTail = promise.then(
1662
- () => void 0,
1663
- () => void 0
1664
- );
1665
- if (isBareCall) {
1666
- bareIdentifyPromise = promise;
1667
- void promise.then(
1668
- () => {
1669
- if (bareIdentifyPromise === promise) bareIdentifyPromise = null;
1670
- },
1671
- () => {
1672
- if (bareIdentifyPromise === promise) bareIdentifyPromise = null;
1673
- }
1674
- );
1675
- }
1676
- return promise;
1677
- }
1678
- async function verify(params) {
1679
- const result = await contactApi.verify(params);
1680
- bareIdentifyPromise = null;
1681
- return result;
1682
- }
1683
- async function logout() {
1684
- if (config.apiToken) return;
1685
- bareIdentifyPromise = null;
1686
- try {
1687
- await contactApi.logout();
1688
- } catch {
1689
- updateSession(() => null);
1690
- }
1691
- }
1692
- return {
1693
- identify,
1694
- verify,
1695
- logout,
1696
- me: () => contactApi.getMe(),
1697
- get session() {
1698
- if (config.apiToken) return null;
1699
- return toPublic(readContactSession());
1700
- },
1701
- get isAuthenticated() {
1702
- if (config.apiToken) return true;
1703
- const s = readContactSession();
1704
- return s !== null && !!s.access_token;
1705
- },
1706
- onAuthStateChanged(listener) {
1707
- listeners.add(listener);
1708
- const current = toPublic(readContactSession());
1709
- if (current) {
1710
- Promise.resolve().then(() => listener(current)).catch(() => {
1711
- });
1712
- }
1713
- return () => {
1714
- listeners.delete(listener);
1715
- };
1716
- },
1717
- store: storefrontApi.store,
1718
- cms: storefrontApi.cms,
1719
- eshop: storefrontApi.eshop,
1720
- crm: storefrontApi.crm,
1721
- action: storefrontApi.action,
1722
- experiments: storefrontApi.experiments,
1723
- support: createStorefrontSupportApi(apiConfig),
1724
- getStoreId: () => apiConfig.storeId,
1725
- setMarket: (key) => {
1726
- apiConfig.market = key;
1727
- bareIdentifyPromise = null;
1728
- },
1729
- getMarket: () => apiConfig.market,
1730
- setLocale: (l) => {
1731
- apiConfig.locale = l;
1732
- },
1733
- getLocale: () => apiConfig.locale,
1734
- utils: createUtilitySurface(apiConfig)
1735
- };
1736
- }
1737
- function createStorefront(config) {
1738
- const sessionStorage = config.sessionStorage || defaultStorefrontSessionStorage() || void 0;
1739
- const scopedConfig = {
1740
- ...config,
1741
- sessionStorage
1742
- };
1743
- const client = createStorefrontClient(scopedConfig);
1744
- Object.defineProperty(client, "forStore", {
1745
- enumerable: true,
1746
- configurable: false,
1747
- writable: false,
1748
- value: (storeId) => createStorefront({
1749
- ...scopedConfig,
1750
- storeId,
1751
- market: client.getMarket(),
1752
- locale: client.getLocale()
1753
- })
1754
- });
1755
- return client;
1756
- }
1757
-
1758
1387
  // src/payments/stripe.ts
1759
1388
  async function defaultStripeLoader(publishableKey, options) {
1760
1389
  const { loadStripe } = await import('@stripe/stripe-js');
@@ -1828,7 +1457,8 @@ function createElements(stripe, config) {
1828
1457
  amount: config.amount,
1829
1458
  currency: normalizeCurrency(config.currency),
1830
1459
  paymentMethodCreation: "manual",
1831
- ...config.appearance ? { appearance: config.appearance } : {}
1460
+ ...config.appearance ? { appearance: config.appearance } : {},
1461
+ ...config.setupFutureUsage ? { setupFutureUsage: config.setupFutureUsage } : {}
1832
1462
  });
1833
1463
  }
1834
1464
 
@@ -2131,22 +1761,24 @@ function normalizeTimezoneGroups(groups) {
2131
1761
  function firstFiniteNumber(...values) {
2132
1762
  return values.find((value) => typeof value === "number" && Number.isFinite(value));
2133
1763
  }
2134
- function initializeStore(config) {
2135
- const client = createStorefront(config);
2136
- const formClients = /* @__PURE__ */ new Map([[client.getStoreId(), client]]);
1764
+ function initializeStoreCore(publishableKey, config, scopedClient) {
1765
+ const client = scopedClient || createStorefront(publishableKey, config);
2137
1766
  const session = nanostores.atom(client.session);
1767
+ const setup = nanostores.atom(null);
2138
1768
  const locale = nanostores.atom(config.locale || client.getLocale());
2139
1769
  const market_key = nanostores.atom(config.market || client.getMarket());
2140
- const market = nanostores.computed(session, (value) => value?.market || null);
1770
+ const market = nanostores.computed([setup, market_key], (setupValue, marketKey) => {
1771
+ const resolvedKey = marketKey || setupValue?.markets.default;
1772
+ return setupValue?.markets.available.find((candidate) => candidate.key === resolvedKey) || null;
1773
+ });
2141
1774
  const currency = nanostores.computed(market, (value) => value?.currency || null);
2142
1775
  const allowed_payment_methods = nanostores.computed(market, (value) => value?.payment_methods || []);
2143
- const payment_config = nanostores.computed(session, (value) => {
2144
- const store = value?.store;
2145
- const methods = value?.market?.payment_methods || [];
1776
+ const payment_config = nanostores.computed([setup, market], (setupValue, marketValue) => {
1777
+ const methods = marketValue?.payment_methods || [];
2146
1778
  const hasCreditCard = methods.some((method) => method.type === "credit_card");
2147
1779
  return {
2148
- provider: store?.payment || null,
2149
- enabled: hasCreditCard && !!store?.payment
1780
+ provider: setupValue?.payment || null,
1781
+ enabled: hasCreditCard && Boolean(setupValue?.readiness.payment)
2150
1782
  };
2151
1783
  });
2152
1784
  const cart = nanostores.atom(null);
@@ -2242,24 +1874,17 @@ function initializeStore(config) {
2242
1874
  const service_form_blocks = nanostores.computed(service_form_groups, (groups) => groups.flatMap((group) => group.blocks));
2243
1875
  client.onAuthStateChanged((value) => session.set(value));
2244
1876
  currency.subscribe((value) => service_state.setKey("currency", value));
2245
- session.subscribe((value) => {
2246
- const methods = value?.market?.payment_methods || [];
1877
+ market.subscribe((value) => {
1878
+ const methods = value?.payment_methods || [];
2247
1879
  if (methods.length && service_state.get().availablePaymentMethods.length === 0) {
2248
1880
  service_state.setKey("availablePaymentMethods", methods);
2249
1881
  }
2250
1882
  });
2251
1883
  function currentMarketKey() {
2252
- return market_key.get() || client.getMarket() || market.get()?.key || "";
1884
+ return market_key.get() || client.getMarket() || setup.get()?.markets.default || "";
2253
1885
  }
2254
1886
  function currentLocale() {
2255
- return locale.get() || client.getLocale() || "en";
2256
- }
2257
- function clientForStore(storeId) {
2258
- const existing = formClients.get(storeId);
2259
- if (existing) return existing;
2260
- const scoped = client.forStore(storeId);
2261
- formClients.set(storeId, scoped);
2262
- return scoped;
1887
+ return locale.get() || client.getLocale() || setup.get()?.languages.default || "en";
2263
1888
  }
2264
1889
  function currentStripePublishableKey() {
2265
1890
  const provider = payment_config.get()?.provider;
@@ -2289,10 +1914,24 @@ function initializeStore(config) {
2289
1914
  function destroyPaymentController() {
2290
1915
  setPaymentController(null);
2291
1916
  }
2292
- async function mountStripePayment(target, options = {}) {
2293
- const publishableKey = options.publishableKey || currentStripePublishableKey();
2294
- if (!publishableKey) {
2295
- throw new Error("Stripe publishable key is required to mount card payment");
1917
+ async function loadSetup() {
1918
+ const current = setup.get();
1919
+ if (current) return current;
1920
+ const result = await client.getSetup();
1921
+ setup.set(result);
1922
+ if (!market_key.get() && result.markets.default) {
1923
+ market_key.set(result.markets.default);
1924
+ }
1925
+ if (!locale.get() && result.languages.default) {
1926
+ locale.set(result.languages.default);
1927
+ }
1928
+ return result;
1929
+ }
1930
+ async function mountPayment(target, options = {}) {
1931
+ await loadSetup();
1932
+ const publishableKey2 = currentStripePublishableKey();
1933
+ if (!publishableKey2) {
1934
+ throw new Error("Stripe card payment is not configured for this Store");
2296
1935
  }
2297
1936
  const hasExplicitAmount = options.amount !== void 0;
2298
1937
  const hasExplicitCurrency = Boolean(options.currency?.trim());
@@ -2308,11 +1947,12 @@ function initializeStore(config) {
2308
1947
  throw new Error("An explicit three-letter payment currency is required to mount card payment");
2309
1948
  }
2310
1949
  const controller = await createStripeConfirmationTokenController({
2311
- publishableKey,
2312
- connectedAccountId: options.connectedAccountId || currentStripeConnectedAccountId() || void 0,
1950
+ publishableKey: publishableKey2,
1951
+ connectedAccountId: currentStripeConnectedAccountId() || void 0,
2313
1952
  amount,
2314
1953
  currency: paymentCurrency,
2315
- ...options.appearance ? { appearance: options.appearance } : {}
1954
+ ...options.appearance ? { appearance: options.appearance } : {},
1955
+ ...options.setupFutureUsage ? { setupFutureUsage: options.setupFutureUsage } : {}
2316
1956
  });
2317
1957
  controller.mount(target);
2318
1958
  setPaymentController(controller);
@@ -2321,15 +1961,11 @@ function initializeStore(config) {
2321
1961
  function updatePaymentController(input) {
2322
1962
  payment_controller.get()?.update(input);
2323
1963
  }
2324
- function marketForLocale(value) {
2325
- return config.marketForLocale?.(value) || null;
2326
- }
2327
1964
  async function ensureSession() {
2328
1965
  const current = session.get();
2329
- const marketKey = currentMarketKey();
2330
- if (current && (!marketKey || current.market?.key === marketKey)) return current;
1966
+ if (client.isAuthenticated) return current;
2331
1967
  if (!sessionRequest) {
2332
- sessionRequest = identify({ market: marketKey }).finally(() => {
1968
+ sessionRequest = identify().finally(() => {
2333
1969
  sessionRequest = null;
2334
1970
  });
2335
1971
  }
@@ -2342,9 +1978,7 @@ function initializeStore(config) {
2342
1978
  market: params.market || currentMarketKey()
2343
1979
  });
2344
1980
  session.set({
2345
- contact: result.contact,
2346
- store: result.store,
2347
- market: result.market
1981
+ contact: result.contact
2348
1982
  });
2349
1983
  return result;
2350
1984
  }
@@ -2356,21 +1990,24 @@ function initializeStore(config) {
2356
1990
  return identify({ email: normalizedEmail });
2357
1991
  }
2358
1992
  function setMarket(key) {
2359
- market_key.set(key);
2360
- client.setMarket(key);
1993
+ const next = key.trim();
1994
+ const current = currentMarketKey();
1995
+ if (next && current && next !== current && (cart.get()?.item_count || item_count.get()) > 0) {
1996
+ throw Object.assign(
1997
+ new Error("Market cannot change while the cart contains items"),
1998
+ { code: "CART_MARKET_LOCKED" }
1999
+ );
2000
+ }
2001
+ market_key.set(next);
2002
+ client.setMarket(next);
2361
2003
  }
2362
- function setLocale(value, options = {}) {
2004
+ function setLocale(value) {
2363
2005
  locale.set(value);
2364
2006
  client.setLocale(value);
2365
- const nextMarket = options.market || marketForLocale(value);
2366
- if (nextMarket) setMarket(nextMarket);
2367
2007
  }
2368
2008
  function setContext(context) {
2369
- if (context.locale) {
2370
- setLocale(context.locale, { market: context.market });
2371
- return;
2372
- }
2373
- if (context.market) setMarket(context.market);
2009
+ if (context.market !== void 0) setMarket(context.market);
2010
+ if (context.locale !== void 0) setLocale(context.locale);
2374
2011
  }
2375
2012
  async function ensureCart() {
2376
2013
  if (cartRequest) return cartRequest;
@@ -2379,9 +2016,7 @@ function initializeStore(config) {
2379
2016
  const refreshRevision = cartWriteRevision;
2380
2017
  cartRequest = (async () => {
2381
2018
  await ensureSession();
2382
- const response = await client.eshop.cart.current({
2383
- market: currentMarketKey()
2384
- });
2019
+ const response = await client.eshop.cart.current();
2385
2020
  await applyCartResponse(response, { ifRevision: refreshRevision });
2386
2021
  return response;
2387
2022
  })();
@@ -2398,8 +2033,16 @@ function initializeStore(config) {
2398
2033
  async function buildProductCartItem(item, source, productHint) {
2399
2034
  try {
2400
2035
  const product = productHint?.id === item.product_id ? productHint : await client.eshop.product.get({ id: item.product_id });
2401
- const variant = product.variants.find((candidate) => candidate.id === item.variant_id);
2402
- if (!variant) return null;
2036
+ const variant = product.variants.find(
2037
+ (candidate) => candidate.id === item.variant_id
2038
+ );
2039
+ if (!variant) {
2040
+ cart_status.setKey(
2041
+ "error",
2042
+ `Cart product ${item.product_id} references unavailable variant ${item.variant_id}.`
2043
+ );
2044
+ return null;
2045
+ }
2403
2046
  return {
2404
2047
  id: item.id || createId("product"),
2405
2048
  product_id: product.id,
@@ -2413,7 +2056,14 @@ function initializeStore(config) {
2413
2056
  added_at: source.created_at ? source.created_at * 1e3 : Date.now(),
2414
2057
  max_stock: availableStock(client, variant)
2415
2058
  };
2416
- } catch {
2059
+ } catch (error) {
2060
+ cart_status.setKey(
2061
+ "error",
2062
+ readErrorMessage(
2063
+ error,
2064
+ `Failed to load cart product ${item.product_id}.`
2065
+ )
2066
+ );
2417
2067
  return null;
2418
2068
  }
2419
2069
  }
@@ -2452,6 +2102,7 @@ function initializeStore(config) {
2452
2102
  promo_code.set(response.promo_code || null);
2453
2103
  quote.set(response.quote_snapshot || null);
2454
2104
  const items = response.items || [];
2105
+ if (items.length > 0) await loadSetup();
2455
2106
  const products = await Promise.all(
2456
2107
  items.filter((item) => item.type === "product").map((item) => buildProductCartItem(item, response, options.productHint))
2457
2108
  );
@@ -2473,7 +2124,6 @@ function initializeStore(config) {
2473
2124
  const current = cart.get() || await ensureCart();
2474
2125
  const response = await client.eshop.cart.update({
2475
2126
  id: current.id,
2476
- market: currentMarketKey(),
2477
2127
  items: checkoutItems(input),
2478
2128
  shipping_address: input.shipping_address,
2479
2129
  billing_address: input.billing_address,
@@ -2889,7 +2539,7 @@ function initializeStore(config) {
2889
2539
  async initialize() {
2890
2540
  service_state.setKey("tzGroups", normalizeTimezoneGroups(client.utils.tzGroups));
2891
2541
  await ensureCart();
2892
- const methods = session.get()?.market?.payment_methods || [];
2542
+ const methods = market.get()?.payment_methods || [];
2893
2543
  if (methods.length) service_state.setKey("availablePaymentMethods", methods);
2894
2544
  },
2895
2545
  setTimezone(tz) {
@@ -2938,7 +2588,9 @@ function initializeStore(config) {
2938
2588
  ...service_state.get(),
2939
2589
  service: fullService,
2940
2590
  serviceProviders,
2941
- providers: providerResults.filter((provider) => provider !== null),
2591
+ providers: providerResults.filter(
2592
+ (provider) => provider !== null
2593
+ ),
2942
2594
  selectedProviderId: null,
2943
2595
  availability: null,
2944
2596
  selectedDate: null,
@@ -3152,7 +2804,7 @@ function initializeStore(config) {
3152
2804
  });
3153
2805
  service_state.setKey("cartId", cart.get()?.id || null);
3154
2806
  service_state.setKey("quote", response);
3155
- const methods = response?.payment_methods || session.get()?.market?.payment_methods || [];
2807
+ const methods = response?.payment_methods || market.get()?.payment_methods || [];
3156
2808
  if (methods.length) service_state.setKey("availablePaymentMethods", methods);
3157
2809
  return response;
3158
2810
  } catch (error) {
@@ -3244,20 +2896,17 @@ function initializeStore(config) {
3244
2896
  }
3245
2897
  }
3246
2898
  function formCacheKey(params) {
3247
- const storeId = params.store_id || client.getStoreId();
3248
2899
  const identifier = params.id ? `id:${params.id}` : params.key ? `key:${params.key}` : "missing";
3249
- return `${storeId}:${identifier}`;
2900
+ return identifier;
3250
2901
  }
3251
2902
  async function loadForm(params, options) {
3252
2903
  cms_state.setKey("loading", true);
3253
2904
  cms_state.setKey("error", null);
3254
2905
  try {
3255
- const storeId = params.store_id || client.getStoreId();
3256
- const formClient = clientForStore(storeId);
3257
- const form = await formClient.cms.form.get({ ...params, store_id: storeId }, options);
2906
+ const form = await client.cms.form.get(params, options);
3258
2907
  const forms = { ...cms_state.get().forms };
3259
- forms[formCacheKey({ id: form.id, store_id: storeId })] = form;
3260
- forms[formCacheKey({ key: form.key, store_id: storeId })] = form;
2908
+ forms[formCacheKey({ id: form.id })] = form;
2909
+ forms[formCacheKey({ key: form.key })] = form;
3261
2910
  cms_state.setKey("forms", forms);
3262
2911
  return form;
3263
2912
  } catch (error) {
@@ -3267,26 +2916,14 @@ function initializeStore(config) {
3267
2916
  cms_state.setKey("loading", false);
3268
2917
  }
3269
2918
  }
3270
- async function ensureFormClient(storeId) {
3271
- const formClient = clientForStore(storeId);
3272
- const marketKey = currentMarketKey();
3273
- if (formClient === client) {
3274
- await ensureSession();
3275
- } else if (!formClient.session || marketKey && formClient.session.market?.key !== marketKey) {
3276
- await formClient.identify({ market: marketKey });
3277
- }
3278
- return formClient;
3279
- }
3280
2919
  async function submitForm(params, options) {
3281
- const storeId = params.store_id || client.getStoreId();
3282
- const formClient = await ensureFormClient(storeId);
3283
- return formClient.cms.form.submit({ ...params, store_id: storeId }, options);
2920
+ await ensureSession();
2921
+ return client.cms.form.submit(params, options);
3284
2922
  }
3285
2923
  async function submitFormByKey(params, options) {
3286
- const storeId = params.store_id || client.getStoreId();
3287
- const form = await loadForm({ key: params.key, store_id: storeId }, options);
2924
+ const form = await loadForm({ key: params.key }, options);
3288
2925
  const entry = createFormEntryFromValues(form, params.values);
3289
- return submitForm({ store_id: storeId, form_id: form.id, fields: entry.fields }, options);
2926
+ return submitForm({ form_id: form.id, fields: entry.fields }, options);
3290
2927
  }
3291
2928
  async function loadProducts(params = {}, options) {
3292
2929
  eshop_state.setKey("loading_products", true);
@@ -3384,7 +3021,7 @@ function initializeStore(config) {
3384
3021
  ready: payment_ready,
3385
3022
  setController: setPaymentController,
3386
3023
  getController: () => payment_controller.get(),
3387
- mountStripe: mountStripePayment,
3024
+ mount: mountPayment,
3388
3025
  update: updatePaymentController,
3389
3026
  destroy: destroyPaymentController
3390
3027
  },
@@ -3448,6 +3085,7 @@ function initializeStore(config) {
3448
3085
  return {
3449
3086
  client,
3450
3087
  session,
3088
+ setup,
3451
3089
  market,
3452
3090
  market_key,
3453
3091
  locale,
@@ -3466,7 +3104,6 @@ function initializeStore(config) {
3466
3104
  setMarket,
3467
3105
  setLocale,
3468
3106
  setContext,
3469
- getStoreId: client.getStoreId,
3470
3107
  getMarket: currentMarketKey,
3471
3108
  getLocale: currentLocale,
3472
3109
  cms: {
@@ -3510,31 +3147,400 @@ function initializeStore(config) {
3510
3147
  use: useExperiment
3511
3148
  },
3512
3149
  support: client.support,
3513
- store: client.store,
3150
+ store: {
3151
+ ...client.store,
3152
+ setup,
3153
+ load: loadSetup
3154
+ },
3514
3155
  utils: client.utils
3515
3156
  };
3516
3157
  }
3517
- function initialize(config) {
3518
- const stores = /* @__PURE__ */ new Map();
3519
- const createScope = (scopeConfig) => {
3520
- const existing = stores.get(scopeConfig.storeId);
3521
- if (existing) return existing;
3522
- const store = initializeStore(scopeConfig);
3523
- stores.set(scopeConfig.storeId, store);
3524
- Object.defineProperty(store, "forStore", {
3525
- enumerable: true,
3526
- configurable: false,
3527
- writable: false,
3528
- value: (storeId) => createScope({
3529
- ...config,
3530
- storeId,
3531
- market: store.getMarket(),
3532
- locale: store.getLocale()
3533
- })
3158
+ function initializeStore(publishableKey, config, scopedClient) {
3159
+ const store = initializeStoreCore(publishableKey, config, scopedClient);
3160
+ return Object.assign(store, {
3161
+ withContext(context) {
3162
+ return initializeStore(
3163
+ publishableKey,
3164
+ {
3165
+ ...config,
3166
+ locale: context.locale ?? store.getLocale(),
3167
+ market: context.market ?? store.getMarket()
3168
+ },
3169
+ store.client.withContext(context)
3170
+ );
3171
+ }
3172
+ });
3173
+ }
3174
+ function initialize(publishableKey, options = {}) {
3175
+ return initializeStore(publishableKey, options);
3176
+ }
3177
+
3178
+ // src/index.ts
3179
+ function createUtilitySurface(apiConfig) {
3180
+ return {
3181
+ getImageUrl: (imageBlock, isBlock2 = true) => getImageUrl(imageBlock, isBlock2),
3182
+ getBlockValue,
3183
+ getBlockTextValue,
3184
+ getBlockContentValue,
3185
+ getBlockValues,
3186
+ getBlockLabel,
3187
+ getBlockObjectValues,
3188
+ getBlockFromArray,
3189
+ formatBlockValue,
3190
+ prepareBlocksForSubmission,
3191
+ extractBlockValues,
3192
+ formatPrice: (prices) => formatPrice(prices, apiConfig.market),
3193
+ getPriceAmount: (prices) => getPriceAmount(prices, apiConfig.market),
3194
+ formatPayment,
3195
+ formatMinor,
3196
+ getCurrencySymbol,
3197
+ getCurrencyName,
3198
+ validatePhoneNumber,
3199
+ tzGroups,
3200
+ findTimeZone,
3201
+ slugify,
3202
+ humanize,
3203
+ categorify,
3204
+ formatDate,
3205
+ getSvgContentForAstro,
3206
+ fetchSvgContent,
3207
+ injectSvgIntoElement,
3208
+ isValidKey,
3209
+ validateKey,
3210
+ toKey,
3211
+ nameToKey,
3212
+ getAvailableStock,
3213
+ getReservedStock,
3214
+ hasStock,
3215
+ getInventoryAt,
3216
+ getFirstAvailableFCId
3217
+ };
3218
+ }
3219
+ var DEFAULT_STOREFRONT_API_URL = "https://api.arky.io";
3220
+ var storefrontScopeSequence = 0;
3221
+ function defaultStorefrontSessionStorage() {
3222
+ if (typeof window === "undefined") return null;
3223
+ try {
3224
+ return window.localStorage;
3225
+ } catch {
3226
+ return null;
3227
+ }
3228
+ }
3229
+ function normalizeStorefrontApiUrl(value) {
3230
+ const input = value?.trim() || DEFAULT_STOREFRONT_API_URL;
3231
+ let parsed;
3232
+ try {
3233
+ parsed = new URL(input);
3234
+ } catch {
3235
+ throw new Error("Storefront apiUrl must be a valid HTTP(S) URL");
3236
+ }
3237
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
3238
+ throw new Error("Storefront apiUrl must use HTTP or HTTPS");
3239
+ }
3240
+ return input.replace(/\/+$/, "");
3241
+ }
3242
+ function validatePublishableKey(publishableKey) {
3243
+ if (typeof publishableKey !== "string") {
3244
+ throw new Error(
3245
+ "A valid Arky publishable key is required (arky_pk_ followed by 43 URL-safe characters)"
3246
+ );
3247
+ }
3248
+ const key = publishableKey.trim();
3249
+ if (!/^arky_pk_[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/.test(key)) {
3250
+ throw new Error(
3251
+ "A valid Arky publishable key is required (arky_pk_ followed by 43 URL-safe characters)"
3252
+ );
3253
+ }
3254
+ return key;
3255
+ }
3256
+ function publishableKeyFingerprint(publishableKey) {
3257
+ let hashA = 2166136261;
3258
+ let hashB = 2654435769;
3259
+ for (let index = 0; index < publishableKey.length; index += 1) {
3260
+ const code = publishableKey.charCodeAt(index);
3261
+ hashA = Math.imul(hashA ^ code, 16777619);
3262
+ hashB = Math.imul(hashB ^ code, 2246822507);
3263
+ }
3264
+ return `${(hashA >>> 0).toString(36)}${(hashB >>> 0).toString(36)}`;
3265
+ }
3266
+ function storefrontSessionStorageKey(apiUrl, publishableKey) {
3267
+ return `arky_visitor_session:${encodeURIComponent(apiUrl.toLowerCase())}:${publishableKeyFingerprint(publishableKey)}`;
3268
+ }
3269
+ function isVisitorSessionToken(value) {
3270
+ return Boolean(value && /^arky_vst_[0-9a-f]{64}$/.test(value));
3271
+ }
3272
+ function createStorefrontClientCore(publishableKeyInput, options = {}, isolatedSession = false) {
3273
+ const publishableKey = validatePublishableKey(publishableKeyInput);
3274
+ const apiUrl = normalizeStorefrontApiUrl(options.apiUrl);
3275
+ let locale = options.locale?.trim() || "";
3276
+ let market = options.market?.trim() || "";
3277
+ const listeners = /* @__PURE__ */ new Set();
3278
+ let identifyPromise = null;
3279
+ let identityTail = Promise.resolve();
3280
+ let setupPromise = null;
3281
+ let setupValue = null;
3282
+ const explicitSessionStorage = options.sessionStorage;
3283
+ const sessionStorage = isolatedSession ? explicitSessionStorage || null : explicitSessionStorage || defaultStorefrontSessionStorage();
3284
+ const canCreateVisitorSession = typeof window !== "undefined" || Boolean(explicitSessionStorage);
3285
+ const storageKey = `${storefrontSessionStorageKey(apiUrl, publishableKey)}${isolatedSession ? `:scope:${++storefrontScopeSequence}` : ""}`;
3286
+ let memorySession = null;
3287
+ let memorySessionToken = null;
3288
+ function readSessionToken() {
3289
+ if (!sessionStorage) return memorySessionToken;
3290
+ try {
3291
+ const stored = sessionStorage.getItem(storageKey);
3292
+ return isVisitorSessionToken(stored) ? stored : memorySessionToken;
3293
+ } catch {
3294
+ return memorySessionToken;
3295
+ }
3296
+ }
3297
+ function writeContactSession(session) {
3298
+ memorySession = session;
3299
+ memorySessionToken = session?.sessionToken || null;
3300
+ if (!sessionStorage) return;
3301
+ try {
3302
+ if (session) {
3303
+ sessionStorage.setItem(storageKey, session.sessionToken);
3304
+ } else {
3305
+ sessionStorage.removeItem(storageKey);
3306
+ }
3307
+ } catch {
3308
+ }
3309
+ }
3310
+ function toPublic(s) {
3311
+ return s ? { contact: s.contact } : null;
3312
+ }
3313
+ function emit() {
3314
+ const pub = toPublic(memorySession);
3315
+ for (const l of listeners) {
3316
+ Promise.resolve().then(() => l(pub)).catch(() => {
3317
+ });
3318
+ }
3319
+ }
3320
+ const updateSession = (updater) => {
3321
+ const next = updater(memorySession);
3322
+ writeContactSession(next);
3323
+ emit();
3324
+ };
3325
+ const authStorage = {
3326
+ getTokens() {
3327
+ const sessionToken = readSessionToken();
3328
+ return sessionToken ? { access_token: sessionToken } : null;
3329
+ },
3330
+ onTokensRefreshed() {
3331
+ },
3332
+ onForcedLogout() {
3333
+ identifyPromise = null;
3334
+ updateSession(() => null);
3335
+ }
3336
+ };
3337
+ let recoverUnauthorized = async () => false;
3338
+ let visitorRecoveryPromise = null;
3339
+ const httpClient = createHttpClient({
3340
+ baseUrl: apiUrl,
3341
+ authStorage,
3342
+ storefrontMode: true,
3343
+ forcedHeaders: () => ({
3344
+ "X-Arky-Publishable-Key": publishableKey,
3345
+ ...locale ? { "X-Arky-Locale": locale } : {},
3346
+ ...market ? { "X-Arky-Market": market } : {}
3347
+ }),
3348
+ onUnauthorized: ({ authorizationToken, path }) => recoverUnauthorized(authorizationToken, path)
3349
+ });
3350
+ const apiConfig = {
3351
+ httpClient,
3352
+ apiUrl,
3353
+ publishableKey,
3354
+ market,
3355
+ locale,
3356
+ authStorage
3357
+ };
3358
+ function requireVisitorSessionCapability() {
3359
+ if (!canCreateVisitorSession) {
3360
+ throw new Error(
3361
+ "Stateful storefront operations during SSR require an explicit request-local sessionStorage adapter"
3362
+ );
3363
+ }
3364
+ }
3365
+ async function getSetup(requestOptions) {
3366
+ if (setupValue) return setupValue;
3367
+ if (setupPromise) return setupPromise;
3368
+ setupPromise = httpClient.get(
3369
+ "/v1/storefront",
3370
+ requestOptions
3371
+ ).then((setup) => {
3372
+ setupValue = setup;
3373
+ return setup;
3374
+ }).finally(() => {
3375
+ setupPromise = null;
3534
3376
  });
3535
- return store;
3377
+ return setupPromise;
3378
+ }
3379
+ async function ensureVisitorSession() {
3380
+ if (readSessionToken()) return;
3381
+ requireVisitorSessionCapability();
3382
+ await identify();
3383
+ }
3384
+ const storefrontApi = createStorefrontApi(apiConfig, updateSession, {
3385
+ ensureVisitorSession,
3386
+ getSetup
3387
+ });
3388
+ const contactApi = storefrontApi.crm.contact;
3389
+ function identify(params) {
3390
+ requireVisitorSessionCapability();
3391
+ if (params?.market !== void 0) setMarket(params.market);
3392
+ const isBareCall = !params?.email && !params?.verify;
3393
+ if (isBareCall && identifyPromise) return identifyPromise;
3394
+ const run = async () => {
3395
+ const result = await (params?.verify ? contactApi.requestCode({ email: params.email }) : contactApi.identify({ email: params?.email }));
3396
+ return {
3397
+ contact: result.contact,
3398
+ verification_challenge: result.verification_challenge
3399
+ };
3400
+ };
3401
+ const promise = identityTail.then(run);
3402
+ identityTail = promise.then(
3403
+ () => void 0,
3404
+ () => void 0
3405
+ );
3406
+ if (isBareCall) {
3407
+ identifyPromise = promise;
3408
+ void promise.then(
3409
+ () => {
3410
+ if (identifyPromise === promise) identifyPromise = null;
3411
+ },
3412
+ () => {
3413
+ if (identifyPromise === promise) identifyPromise = null;
3414
+ }
3415
+ );
3416
+ }
3417
+ return promise;
3418
+ }
3419
+ async function verify(params) {
3420
+ requireVisitorSessionCapability();
3421
+ const result = await contactApi.verify(params);
3422
+ identifyPromise = null;
3423
+ return { contact: result.contact };
3424
+ }
3425
+ async function me() {
3426
+ await ensureVisitorSession();
3427
+ return contactApi.getMe();
3428
+ }
3429
+ async function logout() {
3430
+ identifyPromise = null;
3431
+ if (!readSessionToken()) {
3432
+ updateSession(() => null);
3433
+ return;
3434
+ }
3435
+ try {
3436
+ await contactApi.logout();
3437
+ } catch {
3438
+ updateSession(() => null);
3439
+ }
3440
+ }
3441
+ function setMarket(value) {
3442
+ market = value.trim();
3443
+ apiConfig.market = market;
3444
+ identifyPromise = null;
3445
+ }
3446
+ function setLocale(value) {
3447
+ locale = value.trim();
3448
+ apiConfig.locale = locale;
3449
+ }
3450
+ function setContext(context) {
3451
+ if (context.locale !== void 0) setLocale(context.locale);
3452
+ if (context.market !== void 0) setMarket(context.market);
3453
+ }
3454
+ recoverUnauthorized = async (authorizationToken, path) => {
3455
+ if (!authorizationToken) return false;
3456
+ const currentToken = readSessionToken();
3457
+ if (currentToken !== authorizationToken) {
3458
+ if (currentToken) return true;
3459
+ if (!visitorRecoveryPromise) return false;
3460
+ await visitorRecoveryPromise;
3461
+ return Boolean(readSessionToken());
3462
+ }
3463
+ updateSession(() => null);
3464
+ if (/\/account\/(identify|code)$/.test(path)) return true;
3465
+ const recovery = ensureVisitorSession();
3466
+ const trackedRecovery = recovery.finally(() => {
3467
+ if (visitorRecoveryPromise === trackedRecovery) {
3468
+ visitorRecoveryPromise = null;
3469
+ }
3470
+ });
3471
+ visitorRecoveryPromise = trackedRecovery;
3472
+ await trackedRecovery;
3473
+ return true;
3536
3474
  };
3537
- return createScope(config);
3475
+ return {
3476
+ identify,
3477
+ verify,
3478
+ logout,
3479
+ me,
3480
+ get session() {
3481
+ return toPublic(memorySession);
3482
+ },
3483
+ get isAuthenticated() {
3484
+ return Boolean(readSessionToken());
3485
+ },
3486
+ onAuthStateChanged(listener) {
3487
+ listeners.add(listener);
3488
+ const current = toPublic(memorySession);
3489
+ if (current) {
3490
+ Promise.resolve().then(() => listener(current)).catch(() => {
3491
+ });
3492
+ }
3493
+ return () => {
3494
+ listeners.delete(listener);
3495
+ };
3496
+ },
3497
+ store: storefrontApi.store,
3498
+ cms: storefrontApi.cms,
3499
+ eshop: storefrontApi.eshop,
3500
+ crm: {
3501
+ ...storefrontApi.crm,
3502
+ contact: {
3503
+ identify: (params) => identify(params),
3504
+ requestCode: (params) => identify({ ...params, verify: true }),
3505
+ verify,
3506
+ logout,
3507
+ getMe: me
3508
+ }
3509
+ },
3510
+ action: storefrontApi.action,
3511
+ experiments: storefrontApi.experiments,
3512
+ support: createStorefrontSupportApi(apiConfig, ensureVisitorSession),
3513
+ getSetup,
3514
+ setContext,
3515
+ setMarket,
3516
+ getMarket: () => market,
3517
+ setLocale,
3518
+ getLocale: () => locale,
3519
+ utils: createUtilitySurface(apiConfig)
3520
+ };
3521
+ }
3522
+ function createStorefrontClient(publishableKey, options = {}, isolatedSession = false) {
3523
+ const client = createStorefrontClientCore(
3524
+ publishableKey,
3525
+ options,
3526
+ isolatedSession
3527
+ );
3528
+ return Object.assign(client, {
3529
+ withContext(context) {
3530
+ return createStorefrontClient(
3531
+ publishableKey,
3532
+ {
3533
+ ...options,
3534
+ locale: context.locale ?? client.getLocale(),
3535
+ market: context.market ?? client.getMarket()
3536
+ },
3537
+ true
3538
+ );
3539
+ }
3540
+ });
3541
+ }
3542
+ function createStorefront(publishableKey, options = {}) {
3543
+ return createStorefrontClient(publishableKey, options);
3538
3544
  }
3539
3545
 
3540
3546
  exports.COMMON_ACTION_KEYS = COMMON_ACTION_KEYS;