@asteby/storefront 0.16.1 → 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/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { isStorefrontError, availabilityLocale, StorefrontError, formatAvailabilityMessage, defaultCodeForStatus } from './chunk-IPUAZ3LQ.js';
2
- export { PICKUP_STEPS, SHIPPING_STEPS, StorefrontError, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, declineMessage, declineMessageKey, formatAvailabilityMessage, formatVoucherExpiry, isStorefrontError, isTestInvoice, isTestShipment, nextAction, orderProgress, orderShipments, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, productAvailability, resolveAvailability, safeHttpsUrl, safeTrackingUrl, schemaAvailability, shipmentsStatus, sortTrackingEvents } from './chunk-IPUAZ3LQ.js';
1
+ import { isStorefrontError, availabilityLocale, StorefrontError, formatAvailabilityMessage, defaultCodeForStatus } from './chunk-5BJRZIS3.js';
2
+ export { DEFAULT_FIT_TAG_PREFIX, MAX_SUBJECT_YEAR, MIN_SUBJECT_YEAR, PICKUP_STEPS, PRIVATE_MASK, SHIPPING_STEPS, SUBJECT_CATALOG_PAGE_BYTES, StorefrontError, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, coversYear, declineMessage, declineMessageKey, fitTag, fitTagsAny, formatAvailabilityMessage, formatVoucherExpiry, isMasked, isStorefrontError, isTestInvoice, isTestShipment, nextAction, orderProgress, orderShipments, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, productAvailability, reconcileSubjectValues, resolveAvailability, resolveSubject, safeHttpsUrl, safeTrackingUrl, schemaAvailability, shipmentsStatus, sortTrackingEvents, splitSubjectTree, subjectFields, subjectLevels, subjectOptions } from './chunk-5BJRZIS3.js';
3
3
  import { isValidPoint } from './chunk-45R47HYO.js';
4
4
 
5
5
  // src/money.ts
@@ -48,9 +48,14 @@ function appendParams(search, params) {
48
48
  return search;
49
49
  }
50
50
  function productListQuery(params = {}) {
51
- const { filters, handles, ...rest } = params;
51
+ const { filters, handles, tags_any, ...rest } = params;
52
52
  const search = appendParams(new URLSearchParams(), rest);
53
53
  if (handles && handles.length > 0) search.set("handles", handles.join(","));
54
+ if (tags_any && tags_any.length > 0) {
55
+ if (tags_any.length > 5) throw new RangeError("tags_any takes at most 5 tags");
56
+ if (tags_any.some((t) => t.includes(",") || t.length > 120)) throw new TypeError("tags_any: a tag has at most 120 characters and no comma");
57
+ search.set("tags_any", tags_any.join(","));
58
+ }
54
59
  if (filters) {
55
60
  for (const [key, raw] of Object.entries(filters)) {
56
61
  const name = key.startsWith("filter.") ? key : `filter.${key}`;
@@ -410,6 +415,43 @@ function createStorefrontClient(config) {
410
415
  get: (options) => get("/storefront/customer", void 0, options),
411
416
  /** Updates the profile and the saved fiscal data; `fiscal: null` deletes the latter. `422` with `field: 'fiscal.<field>'`. */
412
417
  update: (input, options) => write("PATCH", "/storefront/customer", input, options),
418
+ /**
419
+ * Active sessions of the buyer («Devices»; contract 1.9). Private, never cached. The list carries no address
420
+ * and no token: only what the buyer needs to recognize their own devices.
421
+ */
422
+ sessions: {
423
+ list: async (options) => (await get("/storefront/customer/sessions", void 0, { ...options, cache: "no-store" })).nodes,
424
+ /** Closes one session. Repeating it is fine. `404` for a session that is not the buyer's. Closing the current one is a sign-out. */
425
+ revoke: (id, options) => write("DELETE", `/storefront/customer/sessions/${enc(id)}`, void 0, options),
426
+ /** Closes every session except the one making the call. */
427
+ revokeOthers: (options) => write("DELETE", "/storefront/customer/sessions/others", void 0, options)
428
+ },
429
+ /**
430
+ * Confirms the buyer's identity again with their password or a sign-in code (`requestOtp` first). The
431
+ * confirmation lasts `valid_for_seconds` (a few minutes) and counts only for the session that made the call;
432
+ * exporting data and deleting the account need it (`403 reauth_required` otherwise, see `isReauthRequired`).
433
+ * A wrong credential is always the same `400`; too many tries is `429` (`StorefrontError.retryAfter`).
434
+ */
435
+ reauth: (input, options) => write("POST", "/storefront/customer/reauth", input, options),
436
+ /**
437
+ * The buyer's data as a JSON file (contract 1.9, `capabilities().data_export`). Needs a recent `reauth`. It is
438
+ * built on request and is neither stored nor emailed: call it from YOUR server, stream the bytes
439
+ * (`dataExportBytes`, `safeExportFilename`) with `Cache-Control: no-store`, and keep nothing. Three a day per account.
440
+ */
441
+ exportData: async (options) => {
442
+ const file = await write("POST", "/storefront/customer/data-export", void 0, { ...options, cache: "no-store" });
443
+ if (!file || typeof file.content_base64 !== "string" || typeof file.filename !== "string" || typeof file.content_type !== "string") {
444
+ throw new StorefrontError({ status: 502, code: "invalid_response", message: "The data export answer is not a file" });
445
+ }
446
+ return { filename: file.filename, content_type: file.content_type, content_base64: file.content_base64 };
447
+ },
448
+ /**
449
+ * Deletes the buyer's account (contract 1.9, `capabilities().account_delete`). Needs a recent `reauth` and the
450
+ * text the buyer typed in `confirm`. Personal data is erased; orders and invoices are kept by the store.
451
+ * `409` (see `isAccountDeleteBlocked`) while an order is on its way or a payment is pending. Idempotent: a
452
+ * repeat after success is also fine. Afterwards the token is dead: drop it.
453
+ */
454
+ deleteAccount: (input, options) => write("DELETE", "/storefront/customer", input, options),
413
455
  orders: (params, options) => get("/storefront/customer/orders", params, options),
414
456
  /** `null` when the order does not exist or belongs to someone else. */
415
457
  order: (id, options) => getOrNull(`/storefront/customer/orders/${enc(id)}`, void 0, options),
@@ -460,6 +502,19 @@ function createStorefrontClient(config) {
460
502
  /** Physical delete (a profile leaves nothing behind). A saved default passes to another profile. */
461
503
  delete: (id, options) => write("DELETE", `/storefront/customer/fiscal-profiles/${enc(id)}`, void 0, options)
462
504
  },
505
+ /**
506
+ * Saved items of the buyer («My items», «My garage»; contract 1.9, `capabilities().subjects`). Personal data:
507
+ * private, never cached, never logged. `422` with `field: 'attributes.<field>'` when the kind refuses a value
508
+ * (it never echoes it); `409` for an item already saved or past the limit; `429` for too many saves; `404` for
509
+ * an item that is not the buyer's. The server builds `label` and `fit_key`; private fields come back masked.
510
+ */
511
+ subjects: {
512
+ list: async (params, options) => (await get("/storefront/customer/subjects", params, { ...options, cache: "no-store" })).nodes,
513
+ create: (input, options) => write("POST", "/storefront/customer/subjects", input, options),
514
+ update: (id, patch, options) => write("PATCH", `/storefront/customer/subjects/${enc(id)}`, patch, options),
515
+ /** Physical delete (the item leaves nothing behind). The default of its kind passes to another item. */
516
+ delete: (id, options) => write("DELETE", `/storefront/customer/subjects/${enc(id)}`, void 0, options)
517
+ },
463
518
  addresses: {
464
519
  list: (options) => get("/storefront/customer/addresses", void 0, options),
465
520
  create: (address, options) => write("POST", "/storefront/customer/addresses", address, options),
@@ -468,6 +523,11 @@ function createStorefrontClient(config) {
468
523
  }
469
524
  },
470
525
  content: {
526
+ /**
527
+ * The kinds of buyer item the organization declares («My garage») and their catalogs (contract 1.9; public,
528
+ * cacheable). `[]` when it declares none or the server predates the route: the store has no such section.
529
+ */
530
+ subjectKinds: async (options) => (await getOrNull("/storefront/subject-kinds", void 0, options))?.nodes ?? [],
471
531
  theme: (options) => get("/storefront/content/theme", void 0, options),
472
532
  /** `null` when the page does not exist. */
473
533
  page: (handle, options) => getOrNull(`/storefront/content/pages/${enc(handle)}`, previewQuery(options), options),
@@ -806,6 +866,29 @@ function hreflangLinks(markets, path, defaultMarket, protocol = "https") {
806
866
  return links;
807
867
  }
808
868
 
869
+ // src/account-settings.ts
870
+ function isReauthRequired(error) {
871
+ const e = error;
872
+ return !!e && typeof e === "object" && e.status === 403 && e.code === "reauth_required";
873
+ }
874
+ function isAccountDeleteBlocked(error) {
875
+ const e = error;
876
+ return !!e && typeof e === "object" && e.status === 409 && (e.field === "orders" || e.field === "pending_payments");
877
+ }
878
+ function dataExportBytes(file) {
879
+ const raw = typeof file.content_base64 === "string" ? file.content_base64.replace(/\s+/g, "") : "";
880
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(raw) || raw.length % 4 === 1) throw new TypeError("data export is not valid base64");
881
+ const bin = atob(raw);
882
+ const out = new Uint8Array(bin.length);
883
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
884
+ return out;
885
+ }
886
+ function safeExportFilename(name, fallback = "account-data.json") {
887
+ const base = typeof name === "string" ? name.split(/[\\/]/).pop() ?? "" : "";
888
+ const clean = base.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^\.+/, "").slice(0, 80);
889
+ return clean || fallback;
890
+ }
891
+
809
892
  // src/invoice-docs.ts
810
893
  function groupInvoiceDocs(docs) {
811
894
  const list = Array.isArray(docs) ? docs.filter((d) => !!d && typeof d === "object") : [];
@@ -859,6 +942,6 @@ function deliveryNotices(delivery) {
859
942
  };
860
943
  }
861
944
 
862
- export { CLIENT_IP_HEADER, COUNTRY_HEADERS, MISSING_WEIGHT, NOTE_MAX_LENGTH, PAYMENT_CHOICE_REFUSED_FIELD, appendParams, clampPercent, classifyPaymentError, createStorefrontClient, deliveryInput, deliveryNotices, diagnose, formatMoney, generateIdempotencyKey, groupInvoiceDocs, hreflangLinks, invoiceFileBytes, isTokenPublishable, maskToken, negotiateLocale, normalizeClientIp, normalizeNote, opsSaysNotRetryable, parseDelivery, parseMoney, parseProductFilters, preferredLanguages, productListQuery, promoProgressView, promotionMessages, repairPath, rewardLabel, safeInvoiceFilename, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
945
+ export { CLIENT_IP_HEADER, COUNTRY_HEADERS, MISSING_WEIGHT, NOTE_MAX_LENGTH, PAYMENT_CHOICE_REFUSED_FIELD, appendParams, clampPercent, classifyPaymentError, createStorefrontClient, dataExportBytes, deliveryInput, deliveryNotices, diagnose, formatMoney, generateIdempotencyKey, groupInvoiceDocs, hreflangLinks, invoiceFileBytes, isAccountDeleteBlocked, isReauthRequired, isTokenPublishable, maskToken, negotiateLocale, normalizeClientIp, normalizeNote, opsSaysNotRetryable, parseDelivery, parseMoney, parseProductFilters, preferredLanguages, productListQuery, promoProgressView, promotionMessages, repairPath, rewardLabel, safeExportFilename, safeInvoiceFilename, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
863
946
  //# sourceMappingURL=index.js.map
864
947
  //# sourceMappingURL=index.js.map