@asteby/storefront 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { GeoPoint } from './geo.cjs';
2
2
  export { OpenStatus, OpeningHours } from './geo.cjs';
3
- import { at as ProductSort, aI as Shop, ar as ProductConnection, ao as Product, x as Connection, w as Collection, Z as LocationListParams, W as Location, a3 as NearestLocation, aM as StockLevel, aA as RestockSubscriptionInput, aB as RestockSubscriptionResult, l as CartLineInput, C as Cart, o as CartLineUpdateInput, f as CartBuyerInput, a as AddressInput, O as DeliveryOptions, ag as PaymentMethods, M as DeliveryInput, az as RecommendationPlacement, r as CartRecommendations, t as CheckoutInput, v as CheckoutResult, ay as PromotionsList, ad as PaymentConfig, al as PaymentSubmitInput, a9 as PaymentAttemptResult, B as CustomerIdentifier, I as CustomerSessionInput, H as CustomerSession, z as CustomerCapabilities, E as CustomerRegisterInput, F as CustomerRegisterResult, K as CustomerVerifyRegistrationInput, D as CustomerPasswordLoginInput, J as CustomerSetPasswordInput, G as CustomerResetPasswordInput, y as Customer, a4 as Order, aD as ReturnRequestInput, aC as ReturnRequest, U as InvoiceRequest, V as InvoiceResult, A as Address, aP as Theme, a6 as Page, $ as Menu, b as Article, aO as StorefrontErrorCode, T as InsufficientStockLine, a1 as Money, d as AvailabilityStatus, n as CartLineProblem, c as Availability, au as ProductVariant, L as DeclineCode, am as PaymentVoucher, ah as PaymentNextStep, p as CartPromotions, aw as PromotionReward, N as DeliveryMethod, aQ as UnavailableRateProvider } from './types-DdLzlxw4.cjs';
4
- export { e as CartBuyer, g as CartCost, h as CartDelivery, i as CartDiscountCode, j as CartDiscountLine, k as CartLine, m as CartLineMerchandise, q as CartRecommendation, s as CheckoutInfo, u as CheckoutPayment, P as Facet, Q as FacetValue, R as Image, S as InsufficientStockDetails, X as LocationContacts, Y as LocationKind, _ as LocationPickup, a0 as MenuItem, a2 as MoneyRange, a5 as OrderLine, a7 as PageInfo, a8 as PaymentAction, aa as PaymentAttemptStatus, ab as PaymentClient, ac as PaymentClientCsp, ae as PaymentFlow, af as PaymentMethod, ai as PaymentOption, aj as PaymentOptionKey, ak as PaymentPoint, an as PickupOption, ap as ProductAttributeValue, aq as ProductCategory, as as ProductOption, av as PromotionAnnouncement, ax as PromotionTier, aE as SEO, aF as Section, aG as SelectedOption, aH as ShippingRate, aJ as ShopBranch, aK as ShopContact, aL as ShopPolicies, aN as StorefrontErrorBody } from './types-DdLzlxw4.cjs';
3
+ import { aJ as ProductSort, b8 as TokenIntrospection, b0 as Shop, aQ as Region, aH as ProductConnection, aE as Product, y as Connection, x as Collection, ad as LocationListParams, aa as Location, aj as NearestLocation, b4 as StockLevel, aU as RestockSubscriptionInput, aV as RestockSubscriptionResult, m as CartLineInput, C as Cart, p as CartLineUpdateInput, f as CartBuyerInput, a as AddressInput, Q as DeliveryOptions, aw as PaymentMethods, O as DeliveryInput, a5 as InvoiceRequest, aP as RecommendationPlacement, s as CartRecommendations, u as CheckoutInput, w as CheckoutResult, aO as PromotionsList, at as PaymentConfig, aB as PaymentSubmitInput, ap as PaymentAttemptResult, D as CustomerIdentifier, J as CustomerSessionInput, I as CustomerSession, B as CustomerCapabilities, F as CustomerRegisterInput, G as CustomerRegisterResult, M as CustomerVerifyRegistrationInput, E as CustomerPasswordLoginInput, K as CustomerSetPasswordInput, H as CustomerResetPasswordInput, z as Customer, L as CustomerUpdateInput, ak as Order, aX as ReturnRequestInput, aW as ReturnRequest, a6 as InvoiceResult, A as Address, b7 as Theme, am as Page, af as Menu, b as Article, b6 as StorefrontErrorCode, a3 as InsufficientStockLine, ah as Money, d as AvailabilityStatus, o as CartLineProblem, c as Availability, aK as ProductVariant, N as DeclineCode, aC as PaymentVoucher, ax as PaymentNextStep, q as CartPromotions, aM as PromotionReward, P as DeliveryMethod, b9 as UnavailableRateProvider } from './types-bsdlAumU.cjs';
4
+ export { e as CartBuyer, g as CartCost, h as CartDelivery, i as CartDiscountCode, j as CartDiscountLine, k as CartInvoice, l as CartLine, n as CartLineMerchandise, r as CartRecommendation, t as CheckoutInfo, v as CheckoutPayment, R as Facet, S as FacetValue, T as FiscalDocumentEvidence, U as FiscalDocumentSource, V as FiscalIdentity, W as FiscalIdentityInput, X as FiscalVerification, Y as IdentityCapture, Z as IdentityDocumentSpec, _ as IdentityFieldRule, $ as IdentityRulesV1, a0 as IdentityStrategy, a1 as Image, a2 as InsufficientStockDetails, a4 as InvoiceAction, a7 as InvoiceStage, a8 as InvoiceSummary, a9 as InvoicingCapabilities, ab as LocationContacts, ac as LocationKind, ae as LocationPickup, ag as MenuItem, ai as MoneyRange, al as OrderLine, an as PageInfo, ao as PaymentAction, aq as PaymentAttemptStatus, ar as PaymentClient, as as PaymentClientCsp, au as PaymentFlow, av as PaymentMethod, ay as PaymentOption, az as PaymentOptionKey, aA as PaymentPoint, aD as PickupOption, aF as ProductAttributeValue, aG as ProductCategory, aI as ProductOption, aL as PromotionAnnouncement, aN as PromotionTier, aR as RegionFiscalEntry, aS as RegionFiscalId, aT as RegionPaymentMethod, aY as SEO, aZ as Section, a_ as SelectedOption, a$ as ShippingRate, b1 as ShopBranch, b2 as ShopContact, b3 as ShopPolicies, b5 as StorefrontErrorBody } from './types-bsdlAumU.cjs';
5
5
 
6
6
  type QueryValue = string | number | boolean | null | undefined;
7
7
  type QueryParams = Record<string, QueryValue | QueryValue[]>;
@@ -67,8 +67,12 @@ type StorefrontResponseContext = StorefrontRequestContext & {
67
67
  type StorefrontClientOptions = {
68
68
  /** Base URL of the gateway, e.g. `https://ops.example.com/api/gw`. Routes are appended as `/storefront/...`. */
69
69
  baseUrl: string;
70
- /** `pk_...` (browser) or `sk_...` (server only). Sent as `Authorization: Bearer <token>`. */
71
- token: string;
70
+ /**
71
+ * `pk_...` (browser) or `sk_...` (server only). Sent as `Authorization: Bearer <token>`. A function is called on
72
+ * EVERY request, so a token read from a file (`createFileTokenSource` in `@asteby/storefront/node`) can rotate
73
+ * without restarting the server.
74
+ */
75
+ token: string | (() => string);
72
76
  /** Buyer session (`X-Customer-Token`) for `/storefront/customer/*` routes. */
73
77
  customerToken?: string | null;
74
78
  /** Custom fetch (defaults to `globalThis.fetch`). */
@@ -162,6 +166,13 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
162
166
  }): Promise<T | null>;
163
167
  <T>(spec: RequestSpec): Promise<T>;
164
168
  };
169
+ token: {
170
+ /**
171
+ * What the token in use is and can do (`GET {baseUrl}/_token`, a gateway route, not a `/storefront` one).
172
+ * Needs no scope, so it answers even when the token is under-provisioned: `missing_scopes` says what to repair.
173
+ */
174
+ introspect: (options?: RequestOptions) => Promise<TokenIntrospection>;
175
+ };
165
176
  /** Returns a new client that sends the given buyer session token. */
166
177
  withCustomerToken(customerToken: string | null): /*elided*/ any;
167
178
  /** Returns a new client that reports the shopper's IP (`X-Storefront-Client-IP`) on every call. */
@@ -169,6 +180,12 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
169
180
  shop: {
170
181
  get: (options?: RequestOptions) => Promise<Shop>;
171
182
  };
183
+ /**
184
+ * How the market formats, taxes, addresses and invoices (`fiscal_id` carries the tax-id pattern, the regimes,
185
+ * the invoice uses and the identity documents the buyer can upload). Cacheable; `null` when the organization
186
+ * has no region configured.
187
+ */
188
+ region: (options?: RequestOptions) => Promise<Region | null>;
172
189
  products: {
173
190
  list: (params?: ProductListParams, options?: RequestOptions) => Promise<ProductConnection>;
174
191
  /** `null` when the product does not exist or is unpublished. */
@@ -231,6 +248,13 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
231
248
  setDelivery: (id: string, delivery: DeliveryInput, options?: WriteOptions) => Promise<Cart>;
232
249
  /** Order note (up to 1000 characters). `null` or empty clears it. */
233
250
  setNote: (id: string, note: string | null, options?: WriteOptions) => Promise<Cart>;
251
+ /**
252
+ * Asks for an invoice for this cart (`null` or `{ requested: false }` withdraws it). The server validates the
253
+ * data against the region BEFORE any charge: `422` with `field: 'invoice.<field>'` (e.g. `invoice.tax_regime`)
254
+ * names what to fix. `409 already_checked_out` when the cart is already an order. Checkout uses it when
255
+ * `CheckoutInput.invoice` is omitted.
256
+ */
257
+ setInvoice: (id: string, invoice: InvoiceRequest | null, options?: WriteOptions) => Promise<Cart>;
234
258
  /**
235
259
  * Cross-sell suggestions: only sellable variants, with `unlocks` when adding one reaches the next
236
260
  * discount tier. `first` 1-8 (default 4). `private, no-store`; ask on demand, not on every render.
@@ -286,6 +310,8 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
286
310
  /** Resets a forgotten password with the code from `requestOtp({ email })`. */
287
311
  resetPassword: (input: CustomerResetPasswordInput, options?: WriteOptions) => Promise<void>;
288
312
  get: (options?: RequestOptions) => Promise<Customer>;
313
+ /** Updates the profile and the saved fiscal data; `fiscal: null` deletes the latter. `422` with `field: 'fiscal.<field>'`. */
314
+ update: (input: CustomerUpdateInput, options?: WriteOptions) => Promise<Customer>;
289
315
  orders: (params?: PaginationParams, options?: RequestOptions) => Promise<Connection<Order>>;
290
316
  /** `null` when the order does not exist or belongs to someone else. */
291
317
  order: (id: string, options?: RequestOptions) => Promise<Order | null>;
@@ -325,6 +351,8 @@ type StorefrontErrorInit = {
325
351
  /** Request URL that failed (without credentials). */
326
352
  url?: string;
327
353
  cause?: unknown;
354
+ /** Scopes named by the gateway on a `403 insufficient_scope`. */
355
+ requiredScopes?: string[];
328
356
  };
329
357
  /**
330
358
  * Error thrown by the client for any non-2xx response, network failure,
@@ -337,6 +365,8 @@ declare class StorefrontError extends Error {
337
365
  readonly field: string | undefined;
338
366
  readonly details: unknown;
339
367
  readonly url: string | undefined;
368
+ /** Scopes a `403 insufficient_scope` says the route needs (empty for any other error). */
369
+ readonly requiredScopes: string[];
340
370
  constructor(init: StorefrontErrorInit);
341
371
  /**
342
372
  * Affected lines of a `409 insufficient_stock` (empty for any other error or a
@@ -345,6 +375,7 @@ declare class StorefrontError extends Error {
345
375
  */
346
376
  get stockLines(): InsufficientStockLine[];
347
377
  toJSON(): {
378
+ requiredScopes?: string[] | undefined;
348
379
  name: string;
349
380
  status: number;
350
381
  code: StorefrontErrorCode;
@@ -354,6 +385,31 @@ declare class StorefrontError extends Error {
354
385
  }
355
386
  declare function isStorefrontError(err: unknown): err is StorefrontError;
356
387
 
388
+ /** `sk_…a91f`: the prefix and the last four characters, never enough to use the token. */
389
+ declare function maskToken(token: string | null | undefined): string;
390
+ type DiagnoseOptions = {
391
+ /** Where the warning goes (default `console.warn`). Receives ONE line per problem. */
392
+ log?: (message: string) => void;
393
+ /** Name of the connection, shown in the repair path. */
394
+ connectionName?: string;
395
+ /** Give up after this long (default 3000 ms). */
396
+ timeoutMs?: number;
397
+ };
398
+ /** Where the operator repairs a connection in OPS (es-MX, as the screen names it). */
399
+ declare function repairPath(connectionName?: string): string;
400
+ /**
401
+ * Startup check of the store's credential: asks `token.introspect()` and, when scopes are missing, logs ONE clear
402
+ * warning with the repair path (never the token, only `sk_…a91f`). It NEVER throws and is meant to be fired and
403
+ * forgotten, so it cannot delay or break the boot:
404
+ *
405
+ * ```ts
406
+ * void diagnose(storefront)
407
+ * ```
408
+ *
409
+ * Resolves with the introspection, or `null` when it could not be obtained (older OPS, outage, bad token).
410
+ */
411
+ declare function diagnose(client: StorefrontClient, options?: DiagnoseOptions): Promise<TokenIntrospection | null>;
412
+
357
413
  type FormatMoneyOptions = {
358
414
  /** Drop `.00` when the amount is a whole number. */
359
415
  withoutTrailingZeros?: boolean;
@@ -692,4 +748,4 @@ type DeliveryNotices = {
692
748
  /** Splits `delivery.unavailable` into the `missing_weight` notice and the generic one. */
693
749
  declare function deliveryNotices(delivery: Pick<DeliveryOptions, 'unavailable' | 'partial'> | null | undefined): DeliveryNotices;
694
750
 
695
- export { Address, AddressInput, Article, type ArticleListParams, Availability, type AvailabilityLocale, type AvailabilityMessageKey, type AvailabilityMessages, AvailabilityStatus, type AvailabilityTone, type AvailabilityView, type AvailabilityViewOptions, CLIENT_IP_HEADER, COUNTRY_HEADERS, Cart, CartBuyerInput, CartLineInput, CartLineProblem, type CartLineProblemView, CartLineUpdateInput, CartPromotions, CartRecommendations, CheckoutInput, CheckoutResult, Collection, type CollectionListParams, Connection, Customer, CustomerCapabilities, CustomerIdentifier, CustomerPasswordLoginInput, CustomerRegisterInput, CustomerRegisterResult, CustomerResetPasswordInput, CustomerSession, CustomerSessionInput, CustomerSetPasswordInput, CustomerVerifyRegistrationInput, DeclineCode, type DeliveryChoice, type DeliveryChoiceKind, DeliveryInput, DeliveryMethod, type DeliveryNotices, DeliveryOptions, type DiscountBarState, type DiscountBarView, type FetchLike, type FormatMoneyOptions, GeoPoint, InsufficientStockLine, InvoiceRequest, InvoiceResult, Location, LocationListParams, MISSING_WEIGHT, type MarketInfo, type MarketSuggestion, Menu, Money, NOTE_MAX_LENGTH, NearestLocation, Order, Page, type PaginationParams, PaymentAttemptResult, PaymentConfig, type PaymentErrorKind, type PaymentErrorView, type PaymentLocale, type PaymentMessageKey, type PaymentMessages, PaymentMethods, PaymentNextStep, type PaymentOutcome, type PaymentOutcomeKind, PaymentSubmitInput, PaymentVoucher, type PreviewOptions, Product, ProductConnection, type ProductListParams, ProductSort, ProductVariant, type PromoProgressView, type PromotionLocale, type PromotionMessageKey, type PromotionMessages, PromotionReward, PromotionsList, type QueryParams, type QueryValue, RecommendationPlacement, type RequestOptions, type ResolveAvailabilityOptions, RestockSubscriptionInput, RestockSubscriptionResult, ReturnRequest, ReturnRequestInput, type ShippingBarState, type ShippingBarView, Shop, StockLevel, type StorefrontClient, type StorefrontClientOptions, StorefrontError, StorefrontErrorCode, type StorefrontErrorInit, type StorefrontRequestContext, type StorefrontResponseContext, Theme, UnavailableRateProvider, type WriteOptions, appendParams, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, clampPercent, createStorefrontClient, declineMessage, declineMessageKey, deliveryInput, deliveryNotices, formatAvailabilityMessage, formatMoney, formatVoucherExpiry, generateIdempotencyKey, hreflangLinks, isStorefrontError, isTokenPublishable, negotiateLocale, normalizeClientIp, normalizeNote, parseDelivery, parseMoney, parseProductFilters, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, preferredLanguages, productAvailability, productListQuery, promoProgressView, promotionMessages, resolveAvailability, rewardLabel, safeHttpsUrl, schemaAvailability, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
751
+ export { Address, AddressInput, Article, type ArticleListParams, Availability, type AvailabilityLocale, type AvailabilityMessageKey, type AvailabilityMessages, AvailabilityStatus, type AvailabilityTone, type AvailabilityView, type AvailabilityViewOptions, CLIENT_IP_HEADER, COUNTRY_HEADERS, Cart, CartBuyerInput, CartLineInput, CartLineProblem, type CartLineProblemView, CartLineUpdateInput, CartPromotions, CartRecommendations, CheckoutInput, CheckoutResult, Collection, type CollectionListParams, Connection, Customer, CustomerCapabilities, CustomerIdentifier, CustomerPasswordLoginInput, CustomerRegisterInput, CustomerRegisterResult, CustomerResetPasswordInput, CustomerSession, CustomerSessionInput, CustomerSetPasswordInput, CustomerUpdateInput, CustomerVerifyRegistrationInput, DeclineCode, type DeliveryChoice, type DeliveryChoiceKind, DeliveryInput, DeliveryMethod, type DeliveryNotices, DeliveryOptions, type DiagnoseOptions, type DiscountBarState, type DiscountBarView, type FetchLike, type FormatMoneyOptions, GeoPoint, InsufficientStockLine, InvoiceRequest, InvoiceResult, Location, LocationListParams, MISSING_WEIGHT, type MarketInfo, type MarketSuggestion, Menu, Money, NOTE_MAX_LENGTH, NearestLocation, Order, Page, type PaginationParams, PaymentAttemptResult, PaymentConfig, type PaymentErrorKind, type PaymentErrorView, type PaymentLocale, type PaymentMessageKey, type PaymentMessages, PaymentMethods, PaymentNextStep, type PaymentOutcome, type PaymentOutcomeKind, PaymentSubmitInput, PaymentVoucher, type PreviewOptions, Product, ProductConnection, type ProductListParams, ProductSort, ProductVariant, type PromoProgressView, type PromotionLocale, type PromotionMessageKey, type PromotionMessages, PromotionReward, PromotionsList, type QueryParams, type QueryValue, RecommendationPlacement, Region, type RequestOptions, type ResolveAvailabilityOptions, RestockSubscriptionInput, RestockSubscriptionResult, ReturnRequest, ReturnRequestInput, type ShippingBarState, type ShippingBarView, Shop, StockLevel, type StorefrontClient, type StorefrontClientOptions, StorefrontError, StorefrontErrorCode, type StorefrontErrorInit, type StorefrontRequestContext, type StorefrontResponseContext, Theme, TokenIntrospection, UnavailableRateProvider, type WriteOptions, appendParams, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, clampPercent, createStorefrontClient, declineMessage, declineMessageKey, deliveryInput, deliveryNotices, diagnose, formatAvailabilityMessage, formatMoney, formatVoucherExpiry, generateIdempotencyKey, hreflangLinks, isStorefrontError, isTokenPublishable, maskToken, negotiateLocale, normalizeClientIp, normalizeNote, parseDelivery, parseMoney, parseProductFilters, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, preferredLanguages, productAvailability, productListQuery, promoProgressView, promotionMessages, repairPath, resolveAvailability, rewardLabel, safeHttpsUrl, schemaAvailability, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { GeoPoint } from './geo.js';
2
2
  export { OpenStatus, OpeningHours } from './geo.js';
3
- import { at as ProductSort, aI as Shop, ar as ProductConnection, ao as Product, x as Connection, w as Collection, Z as LocationListParams, W as Location, a3 as NearestLocation, aM as StockLevel, aA as RestockSubscriptionInput, aB as RestockSubscriptionResult, l as CartLineInput, C as Cart, o as CartLineUpdateInput, f as CartBuyerInput, a as AddressInput, O as DeliveryOptions, ag as PaymentMethods, M as DeliveryInput, az as RecommendationPlacement, r as CartRecommendations, t as CheckoutInput, v as CheckoutResult, ay as PromotionsList, ad as PaymentConfig, al as PaymentSubmitInput, a9 as PaymentAttemptResult, B as CustomerIdentifier, I as CustomerSessionInput, H as CustomerSession, z as CustomerCapabilities, E as CustomerRegisterInput, F as CustomerRegisterResult, K as CustomerVerifyRegistrationInput, D as CustomerPasswordLoginInput, J as CustomerSetPasswordInput, G as CustomerResetPasswordInput, y as Customer, a4 as Order, aD as ReturnRequestInput, aC as ReturnRequest, U as InvoiceRequest, V as InvoiceResult, A as Address, aP as Theme, a6 as Page, $ as Menu, b as Article, aO as StorefrontErrorCode, T as InsufficientStockLine, a1 as Money, d as AvailabilityStatus, n as CartLineProblem, c as Availability, au as ProductVariant, L as DeclineCode, am as PaymentVoucher, ah as PaymentNextStep, p as CartPromotions, aw as PromotionReward, N as DeliveryMethod, aQ as UnavailableRateProvider } from './types-COSwo4ND.js';
4
- export { e as CartBuyer, g as CartCost, h as CartDelivery, i as CartDiscountCode, j as CartDiscountLine, k as CartLine, m as CartLineMerchandise, q as CartRecommendation, s as CheckoutInfo, u as CheckoutPayment, P as Facet, Q as FacetValue, R as Image, S as InsufficientStockDetails, X as LocationContacts, Y as LocationKind, _ as LocationPickup, a0 as MenuItem, a2 as MoneyRange, a5 as OrderLine, a7 as PageInfo, a8 as PaymentAction, aa as PaymentAttemptStatus, ab as PaymentClient, ac as PaymentClientCsp, ae as PaymentFlow, af as PaymentMethod, ai as PaymentOption, aj as PaymentOptionKey, ak as PaymentPoint, an as PickupOption, ap as ProductAttributeValue, aq as ProductCategory, as as ProductOption, av as PromotionAnnouncement, ax as PromotionTier, aE as SEO, aF as Section, aG as SelectedOption, aH as ShippingRate, aJ as ShopBranch, aK as ShopContact, aL as ShopPolicies, aN as StorefrontErrorBody } from './types-COSwo4ND.js';
3
+ import { aJ as ProductSort, b8 as TokenIntrospection, b0 as Shop, aQ as Region, aH as ProductConnection, aE as Product, y as Connection, x as Collection, ad as LocationListParams, aa as Location, aj as NearestLocation, b4 as StockLevel, aU as RestockSubscriptionInput, aV as RestockSubscriptionResult, m as CartLineInput, C as Cart, p as CartLineUpdateInput, f as CartBuyerInput, a as AddressInput, Q as DeliveryOptions, aw as PaymentMethods, O as DeliveryInput, a5 as InvoiceRequest, aP as RecommendationPlacement, s as CartRecommendations, u as CheckoutInput, w as CheckoutResult, aO as PromotionsList, at as PaymentConfig, aB as PaymentSubmitInput, ap as PaymentAttemptResult, D as CustomerIdentifier, J as CustomerSessionInput, I as CustomerSession, B as CustomerCapabilities, F as CustomerRegisterInput, G as CustomerRegisterResult, M as CustomerVerifyRegistrationInput, E as CustomerPasswordLoginInput, K as CustomerSetPasswordInput, H as CustomerResetPasswordInput, z as Customer, L as CustomerUpdateInput, ak as Order, aX as ReturnRequestInput, aW as ReturnRequest, a6 as InvoiceResult, A as Address, b7 as Theme, am as Page, af as Menu, b as Article, b6 as StorefrontErrorCode, a3 as InsufficientStockLine, ah as Money, d as AvailabilityStatus, o as CartLineProblem, c as Availability, aK as ProductVariant, N as DeclineCode, aC as PaymentVoucher, ax as PaymentNextStep, q as CartPromotions, aM as PromotionReward, P as DeliveryMethod, b9 as UnavailableRateProvider } from './types-B1E3GySa.js';
4
+ export { e as CartBuyer, g as CartCost, h as CartDelivery, i as CartDiscountCode, j as CartDiscountLine, k as CartInvoice, l as CartLine, n as CartLineMerchandise, r as CartRecommendation, t as CheckoutInfo, v as CheckoutPayment, R as Facet, S as FacetValue, T as FiscalDocumentEvidence, U as FiscalDocumentSource, V as FiscalIdentity, W as FiscalIdentityInput, X as FiscalVerification, Y as IdentityCapture, Z as IdentityDocumentSpec, _ as IdentityFieldRule, $ as IdentityRulesV1, a0 as IdentityStrategy, a1 as Image, a2 as InsufficientStockDetails, a4 as InvoiceAction, a7 as InvoiceStage, a8 as InvoiceSummary, a9 as InvoicingCapabilities, ab as LocationContacts, ac as LocationKind, ae as LocationPickup, ag as MenuItem, ai as MoneyRange, al as OrderLine, an as PageInfo, ao as PaymentAction, aq as PaymentAttemptStatus, ar as PaymentClient, as as PaymentClientCsp, au as PaymentFlow, av as PaymentMethod, ay as PaymentOption, az as PaymentOptionKey, aA as PaymentPoint, aD as PickupOption, aF as ProductAttributeValue, aG as ProductCategory, aI as ProductOption, aL as PromotionAnnouncement, aN as PromotionTier, aR as RegionFiscalEntry, aS as RegionFiscalId, aT as RegionPaymentMethod, aY as SEO, aZ as Section, a_ as SelectedOption, a$ as ShippingRate, b1 as ShopBranch, b2 as ShopContact, b3 as ShopPolicies, b5 as StorefrontErrorBody } from './types-B1E3GySa.js';
5
5
 
6
6
  type QueryValue = string | number | boolean | null | undefined;
7
7
  type QueryParams = Record<string, QueryValue | QueryValue[]>;
@@ -67,8 +67,12 @@ type StorefrontResponseContext = StorefrontRequestContext & {
67
67
  type StorefrontClientOptions = {
68
68
  /** Base URL of the gateway, e.g. `https://ops.example.com/api/gw`. Routes are appended as `/storefront/...`. */
69
69
  baseUrl: string;
70
- /** `pk_...` (browser) or `sk_...` (server only). Sent as `Authorization: Bearer <token>`. */
71
- token: string;
70
+ /**
71
+ * `pk_...` (browser) or `sk_...` (server only). Sent as `Authorization: Bearer <token>`. A function is called on
72
+ * EVERY request, so a token read from a file (`createFileTokenSource` in `@asteby/storefront/node`) can rotate
73
+ * without restarting the server.
74
+ */
75
+ token: string | (() => string);
72
76
  /** Buyer session (`X-Customer-Token`) for `/storefront/customer/*` routes. */
73
77
  customerToken?: string | null;
74
78
  /** Custom fetch (defaults to `globalThis.fetch`). */
@@ -162,6 +166,13 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
162
166
  }): Promise<T | null>;
163
167
  <T>(spec: RequestSpec): Promise<T>;
164
168
  };
169
+ token: {
170
+ /**
171
+ * What the token in use is and can do (`GET {baseUrl}/_token`, a gateway route, not a `/storefront` one).
172
+ * Needs no scope, so it answers even when the token is under-provisioned: `missing_scopes` says what to repair.
173
+ */
174
+ introspect: (options?: RequestOptions) => Promise<TokenIntrospection>;
175
+ };
165
176
  /** Returns a new client that sends the given buyer session token. */
166
177
  withCustomerToken(customerToken: string | null): /*elided*/ any;
167
178
  /** Returns a new client that reports the shopper's IP (`X-Storefront-Client-IP`) on every call. */
@@ -169,6 +180,12 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
169
180
  shop: {
170
181
  get: (options?: RequestOptions) => Promise<Shop>;
171
182
  };
183
+ /**
184
+ * How the market formats, taxes, addresses and invoices (`fiscal_id` carries the tax-id pattern, the regimes,
185
+ * the invoice uses and the identity documents the buyer can upload). Cacheable; `null` when the organization
186
+ * has no region configured.
187
+ */
188
+ region: (options?: RequestOptions) => Promise<Region | null>;
172
189
  products: {
173
190
  list: (params?: ProductListParams, options?: RequestOptions) => Promise<ProductConnection>;
174
191
  /** `null` when the product does not exist or is unpublished. */
@@ -231,6 +248,13 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
231
248
  setDelivery: (id: string, delivery: DeliveryInput, options?: WriteOptions) => Promise<Cart>;
232
249
  /** Order note (up to 1000 characters). `null` or empty clears it. */
233
250
  setNote: (id: string, note: string | null, options?: WriteOptions) => Promise<Cart>;
251
+ /**
252
+ * Asks for an invoice for this cart (`null` or `{ requested: false }` withdraws it). The server validates the
253
+ * data against the region BEFORE any charge: `422` with `field: 'invoice.<field>'` (e.g. `invoice.tax_regime`)
254
+ * names what to fix. `409 already_checked_out` when the cart is already an order. Checkout uses it when
255
+ * `CheckoutInput.invoice` is omitted.
256
+ */
257
+ setInvoice: (id: string, invoice: InvoiceRequest | null, options?: WriteOptions) => Promise<Cart>;
234
258
  /**
235
259
  * Cross-sell suggestions: only sellable variants, with `unlocks` when adding one reaches the next
236
260
  * discount tier. `first` 1-8 (default 4). `private, no-store`; ask on demand, not on every render.
@@ -286,6 +310,8 @@ declare function createStorefrontClient(config: StorefrontClientOptions): {
286
310
  /** Resets a forgotten password with the code from `requestOtp({ email })`. */
287
311
  resetPassword: (input: CustomerResetPasswordInput, options?: WriteOptions) => Promise<void>;
288
312
  get: (options?: RequestOptions) => Promise<Customer>;
313
+ /** Updates the profile and the saved fiscal data; `fiscal: null` deletes the latter. `422` with `field: 'fiscal.<field>'`. */
314
+ update: (input: CustomerUpdateInput, options?: WriteOptions) => Promise<Customer>;
289
315
  orders: (params?: PaginationParams, options?: RequestOptions) => Promise<Connection<Order>>;
290
316
  /** `null` when the order does not exist or belongs to someone else. */
291
317
  order: (id: string, options?: RequestOptions) => Promise<Order | null>;
@@ -325,6 +351,8 @@ type StorefrontErrorInit = {
325
351
  /** Request URL that failed (without credentials). */
326
352
  url?: string;
327
353
  cause?: unknown;
354
+ /** Scopes named by the gateway on a `403 insufficient_scope`. */
355
+ requiredScopes?: string[];
328
356
  };
329
357
  /**
330
358
  * Error thrown by the client for any non-2xx response, network failure,
@@ -337,6 +365,8 @@ declare class StorefrontError extends Error {
337
365
  readonly field: string | undefined;
338
366
  readonly details: unknown;
339
367
  readonly url: string | undefined;
368
+ /** Scopes a `403 insufficient_scope` says the route needs (empty for any other error). */
369
+ readonly requiredScopes: string[];
340
370
  constructor(init: StorefrontErrorInit);
341
371
  /**
342
372
  * Affected lines of a `409 insufficient_stock` (empty for any other error or a
@@ -345,6 +375,7 @@ declare class StorefrontError extends Error {
345
375
  */
346
376
  get stockLines(): InsufficientStockLine[];
347
377
  toJSON(): {
378
+ requiredScopes?: string[] | undefined;
348
379
  name: string;
349
380
  status: number;
350
381
  code: StorefrontErrorCode;
@@ -354,6 +385,31 @@ declare class StorefrontError extends Error {
354
385
  }
355
386
  declare function isStorefrontError(err: unknown): err is StorefrontError;
356
387
 
388
+ /** `sk_…a91f`: the prefix and the last four characters, never enough to use the token. */
389
+ declare function maskToken(token: string | null | undefined): string;
390
+ type DiagnoseOptions = {
391
+ /** Where the warning goes (default `console.warn`). Receives ONE line per problem. */
392
+ log?: (message: string) => void;
393
+ /** Name of the connection, shown in the repair path. */
394
+ connectionName?: string;
395
+ /** Give up after this long (default 3000 ms). */
396
+ timeoutMs?: number;
397
+ };
398
+ /** Where the operator repairs a connection in OPS (es-MX, as the screen names it). */
399
+ declare function repairPath(connectionName?: string): string;
400
+ /**
401
+ * Startup check of the store's credential: asks `token.introspect()` and, when scopes are missing, logs ONE clear
402
+ * warning with the repair path (never the token, only `sk_…a91f`). It NEVER throws and is meant to be fired and
403
+ * forgotten, so it cannot delay or break the boot:
404
+ *
405
+ * ```ts
406
+ * void diagnose(storefront)
407
+ * ```
408
+ *
409
+ * Resolves with the introspection, or `null` when it could not be obtained (older OPS, outage, bad token).
410
+ */
411
+ declare function diagnose(client: StorefrontClient, options?: DiagnoseOptions): Promise<TokenIntrospection | null>;
412
+
357
413
  type FormatMoneyOptions = {
358
414
  /** Drop `.00` when the amount is a whole number. */
359
415
  withoutTrailingZeros?: boolean;
@@ -692,4 +748,4 @@ type DeliveryNotices = {
692
748
  /** Splits `delivery.unavailable` into the `missing_weight` notice and the generic one. */
693
749
  declare function deliveryNotices(delivery: Pick<DeliveryOptions, 'unavailable' | 'partial'> | null | undefined): DeliveryNotices;
694
750
 
695
- export { Address, AddressInput, Article, type ArticleListParams, Availability, type AvailabilityLocale, type AvailabilityMessageKey, type AvailabilityMessages, AvailabilityStatus, type AvailabilityTone, type AvailabilityView, type AvailabilityViewOptions, CLIENT_IP_HEADER, COUNTRY_HEADERS, Cart, CartBuyerInput, CartLineInput, CartLineProblem, type CartLineProblemView, CartLineUpdateInput, CartPromotions, CartRecommendations, CheckoutInput, CheckoutResult, Collection, type CollectionListParams, Connection, Customer, CustomerCapabilities, CustomerIdentifier, CustomerPasswordLoginInput, CustomerRegisterInput, CustomerRegisterResult, CustomerResetPasswordInput, CustomerSession, CustomerSessionInput, CustomerSetPasswordInput, CustomerVerifyRegistrationInput, DeclineCode, type DeliveryChoice, type DeliveryChoiceKind, DeliveryInput, DeliveryMethod, type DeliveryNotices, DeliveryOptions, type DiscountBarState, type DiscountBarView, type FetchLike, type FormatMoneyOptions, GeoPoint, InsufficientStockLine, InvoiceRequest, InvoiceResult, Location, LocationListParams, MISSING_WEIGHT, type MarketInfo, type MarketSuggestion, Menu, Money, NOTE_MAX_LENGTH, NearestLocation, Order, Page, type PaginationParams, PaymentAttemptResult, PaymentConfig, type PaymentErrorKind, type PaymentErrorView, type PaymentLocale, type PaymentMessageKey, type PaymentMessages, PaymentMethods, PaymentNextStep, type PaymentOutcome, type PaymentOutcomeKind, PaymentSubmitInput, PaymentVoucher, type PreviewOptions, Product, ProductConnection, type ProductListParams, ProductSort, ProductVariant, type PromoProgressView, type PromotionLocale, type PromotionMessageKey, type PromotionMessages, PromotionReward, PromotionsList, type QueryParams, type QueryValue, RecommendationPlacement, type RequestOptions, type ResolveAvailabilityOptions, RestockSubscriptionInput, RestockSubscriptionResult, ReturnRequest, ReturnRequestInput, type ShippingBarState, type ShippingBarView, Shop, StockLevel, type StorefrontClient, type StorefrontClientOptions, StorefrontError, StorefrontErrorCode, type StorefrontErrorInit, type StorefrontRequestContext, type StorefrontResponseContext, Theme, UnavailableRateProvider, type WriteOptions, appendParams, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, clampPercent, createStorefrontClient, declineMessage, declineMessageKey, deliveryInput, deliveryNotices, formatAvailabilityMessage, formatMoney, formatVoucherExpiry, generateIdempotencyKey, hreflangLinks, isStorefrontError, isTokenPublishable, negotiateLocale, normalizeClientIp, normalizeNote, parseDelivery, parseMoney, parseProductFilters, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, preferredLanguages, productAvailability, productListQuery, promoProgressView, promotionMessages, resolveAvailability, rewardLabel, safeHttpsUrl, schemaAvailability, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
751
+ export { Address, AddressInput, Article, type ArticleListParams, Availability, type AvailabilityLocale, type AvailabilityMessageKey, type AvailabilityMessages, AvailabilityStatus, type AvailabilityTone, type AvailabilityView, type AvailabilityViewOptions, CLIENT_IP_HEADER, COUNTRY_HEADERS, Cart, CartBuyerInput, CartLineInput, CartLineProblem, type CartLineProblemView, CartLineUpdateInput, CartPromotions, CartRecommendations, CheckoutInput, CheckoutResult, Collection, type CollectionListParams, Connection, Customer, CustomerCapabilities, CustomerIdentifier, CustomerPasswordLoginInput, CustomerRegisterInput, CustomerRegisterResult, CustomerResetPasswordInput, CustomerSession, CustomerSessionInput, CustomerSetPasswordInput, CustomerUpdateInput, CustomerVerifyRegistrationInput, DeclineCode, type DeliveryChoice, type DeliveryChoiceKind, DeliveryInput, DeliveryMethod, type DeliveryNotices, DeliveryOptions, type DiagnoseOptions, type DiscountBarState, type DiscountBarView, type FetchLike, type FormatMoneyOptions, GeoPoint, InsufficientStockLine, InvoiceRequest, InvoiceResult, Location, LocationListParams, MISSING_WEIGHT, type MarketInfo, type MarketSuggestion, Menu, Money, NOTE_MAX_LENGTH, NearestLocation, Order, Page, type PaginationParams, PaymentAttemptResult, PaymentConfig, type PaymentErrorKind, type PaymentErrorView, type PaymentLocale, type PaymentMessageKey, type PaymentMessages, PaymentMethods, PaymentNextStep, type PaymentOutcome, type PaymentOutcomeKind, PaymentSubmitInput, PaymentVoucher, type PreviewOptions, Product, ProductConnection, type ProductListParams, ProductSort, ProductVariant, type PromoProgressView, type PromotionLocale, type PromotionMessageKey, type PromotionMessages, PromotionReward, PromotionsList, type QueryParams, type QueryValue, RecommendationPlacement, Region, type RequestOptions, type ResolveAvailabilityOptions, RestockSubscriptionInput, RestockSubscriptionResult, ReturnRequest, ReturnRequestInput, type ShippingBarState, type ShippingBarView, Shop, StockLevel, type StorefrontClient, type StorefrontClientOptions, StorefrontError, StorefrontErrorCode, type StorefrontErrorInit, type StorefrontRequestContext, type StorefrontResponseContext, Theme, TokenIntrospection, UnavailableRateProvider, type WriteOptions, appendParams, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, clampPercent, createStorefrontClient, declineMessage, declineMessageKey, deliveryInput, deliveryNotices, diagnose, formatAvailabilityMessage, formatMoney, formatVoucherExpiry, generateIdempotencyKey, hreflangLinks, isStorefrontError, isTokenPublishable, maskToken, negotiateLocale, normalizeClientIp, normalizeNote, parseDelivery, parseMoney, parseProductFilters, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, preferredLanguages, productAvailability, productListQuery, promoProgressView, promotionMessages, repairPath, resolveAvailability, rewardLabel, safeHttpsUrl, schemaAvailability, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ var StorefrontError = class extends Error {
10
10
  field;
11
11
  details;
12
12
  url;
13
+ /** Scopes a `403 insufficient_scope` says the route needs (empty for any other error). */
14
+ requiredScopes;
13
15
  constructor(init) {
14
16
  super(init.message, init.cause === void 0 ? void 0 : { cause: init.cause });
15
17
  this.status = init.status;
@@ -17,6 +19,7 @@ var StorefrontError = class extends Error {
17
19
  this.field = init.field;
18
20
  this.details = init.details;
19
21
  this.url = init.url;
22
+ this.requiredScopes = init.requiredScopes ?? [];
20
23
  }
21
24
  /**
22
25
  * Affected lines of a `409 insufficient_stock` (empty for any other error or a
@@ -29,7 +32,14 @@ var StorefrontError = class extends Error {
29
32
  return lines.filter((l) => typeof l === "object" && l !== null && typeof l.sku === "string");
30
33
  }
31
34
  toJSON() {
32
- return { name: this.name, status: this.status, code: this.code, message: this.message, field: this.field };
35
+ return {
36
+ name: this.name,
37
+ status: this.status,
38
+ code: this.code,
39
+ message: this.message,
40
+ field: this.field,
41
+ ...this.requiredScopes.length ? { requiredScopes: this.requiredScopes } : {}
42
+ };
33
43
  }
34
44
  };
35
45
  function isStorefrontError(err) {
@@ -167,6 +177,9 @@ function linkSignals(signals) {
167
177
  cleanup: () => listeners.forEach(([s, on]) => s.removeEventListener("abort", on))
168
178
  };
169
179
  }
180
+ function scopeList(raw) {
181
+ return Array.isArray(raw) ? raw.filter((s) => typeof s === "string" && s.length > 0) : [];
182
+ }
170
183
  async function readError(res, url) {
171
184
  let body;
172
185
  try {
@@ -176,9 +189,13 @@ async function readError(res, url) {
176
189
  body = void 0;
177
190
  }
178
191
  const e = body?.error;
192
+ const top = body;
193
+ const code = e?.code ?? (typeof top?.code === "string" ? top.code : void 0);
194
+ const requiredScopes = code === "insufficient_scope" ? scopeList(e?.required_scopes ?? top?.required_scopes ?? e?.details?.required_scopes) : [];
179
195
  return new StorefrontError({
180
196
  status: res.status,
181
- code: e?.code ?? defaultCodeForStatus(res.status),
197
+ code: code ?? defaultCodeForStatus(res.status),
198
+ ...requiredScopes.length ? { requiredScopes } : {},
182
199
  message: e?.message ?? `Storefront API responded ${res.status}${res.statusText ? " " + res.statusText : ""}`,
183
200
  ...e?.field ? { field: e.field } : {},
184
201
  ...e?.details !== void 0 ? { details: e.details } : {},
@@ -188,8 +205,14 @@ async function readError(res, url) {
188
205
  function createStorefrontClient(config) {
189
206
  if (!config.baseUrl) throw new TypeError("createStorefrontClient: baseUrl is required");
190
207
  if (!config.token) throw new TypeError("createStorefrontClient: token is required");
208
+ const currentToken = () => {
209
+ const t = typeof config.token === "function" ? config.token() : config.token;
210
+ if (!t) throw new StorefrontError({ status: 0, code: "unauthorized", message: "Storefront token is empty (token source returned nothing)" });
211
+ return t;
212
+ };
191
213
  const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
192
- if (isBrowser && !isTokenPublishable(config.token) && config.token.startsWith("sk_")) {
214
+ const initialToken = typeof config.token === "string" ? config.token : "";
215
+ if (isBrowser && initialToken.startsWith("sk_")) {
193
216
  console.warn("[@asteby/storefront] A private sk_ token is being used in a browser. Use a public pk_ token instead.");
194
217
  }
195
218
  async function request(spec) {
@@ -201,13 +224,14 @@ function createStorefrontClient(config) {
201
224
  const url = joinUrl(config.baseUrl, spec.path) + (qs ? `?${qs}` : "");
202
225
  const headers = new Headers(config.headers);
203
226
  headers.set("Accept", "application/json");
204
- headers.set("Authorization", `Bearer ${config.token}`);
227
+ const token = currentToken();
228
+ headers.set("Authorization", `Bearer ${token}`);
205
229
  if (config.locale) headers.set("Accept-Language", config.locale);
206
230
  if (config.domain) headers.set("X-Storefront-Domain", storefrontDomainHeader(config.domain, config.market));
207
231
  const customerToken = options.customerToken !== void 0 ? options.customerToken : config.customerToken;
208
232
  if (customerToken) headers.set("X-Customer-Token", customerToken);
209
233
  const clientIp = options.clientIp !== void 0 ? options.clientIp : config.clientIp;
210
- const ip = isTokenPublishable(config.token) ? void 0 : normalizeClientIp(clientIp);
234
+ const ip = isTokenPublishable(token) ? void 0 : normalizeClientIp(clientIp);
211
235
  if (ip) headers.set(CLIENT_IP_HEADER, ip);
212
236
  if (options.idempotencyKey) headers.set("Idempotency-Key", options.idempotencyKey);
213
237
  if (spec.body !== void 0) headers.set("Content-Type", "application/json");
@@ -272,6 +296,17 @@ function createStorefrontClient(config) {
272
296
  config: Object.freeze({ ...config }),
273
297
  /** Low-level escape hatch: any route under `baseUrl`. */
274
298
  request,
299
+ token: {
300
+ /**
301
+ * What the token in use is and can do (`GET {baseUrl}/_token`, a gateway route, not a `/storefront` one).
302
+ * Needs no scope, so it answers even when the token is under-provisioned: `missing_scopes` says what to repair.
303
+ */
304
+ introspect: async (options) => {
305
+ const body = await get("/_token", void 0, options);
306
+ const env = body;
307
+ return typeof env?.success === "boolean" && env.data ? env.data : body;
308
+ }
309
+ },
275
310
  /** Returns a new client that sends the given buyer session token. */
276
311
  withCustomerToken(customerToken) {
277
312
  return createStorefrontClient({ ...config, customerToken });
@@ -283,6 +318,12 @@ function createStorefrontClient(config) {
283
318
  shop: {
284
319
  get: (options) => get("/storefront/shop", void 0, options)
285
320
  },
321
+ /**
322
+ * How the market formats, taxes, addresses and invoices (`fiscal_id` carries the tax-id pattern, the regimes,
323
+ * the invoice uses and the identity documents the buyer can upload). Cacheable; `null` when the organization
324
+ * has no region configured.
325
+ */
326
+ region: (options) => getOrNull("/storefront/region", void 0, options),
286
327
  products: {
287
328
  list: (params, options) => get("/storefront/products", productListQuery(params), options),
288
329
  /** `null` when the product does not exist or is unpublished. */
@@ -338,6 +379,13 @@ function createStorefrontClient(config) {
338
379
  setDelivery: (id, delivery, options) => write("PUT", cartPath(id, "/delivery"), delivery, options),
339
380
  /** Order note (up to 1000 characters). `null` or empty clears it. */
340
381
  setNote: (id, note, options) => write("PUT", cartPath(id, "/note"), { note }, options),
382
+ /**
383
+ * Asks for an invoice for this cart (`null` or `{ requested: false }` withdraws it). The server validates the
384
+ * data against the region BEFORE any charge: `422` with `field: 'invoice.<field>'` (e.g. `invoice.tax_regime`)
385
+ * names what to fix. `409 already_checked_out` when the cart is already an order. Checkout uses it when
386
+ * `CheckoutInput.invoice` is omitted.
387
+ */
388
+ setInvoice: (id, invoice, options) => write("PUT", cartPath(id, "/invoice"), invoice ?? { requested: false }, options),
341
389
  /**
342
390
  * Cross-sell suggestions: only sellable variants, with `unlocks` when adding one reaches the next
343
391
  * discount tier. `first` 1-8 (default 4). `private, no-store`; ask on demand, not on every render.
@@ -399,6 +447,8 @@ function createStorefrontClient(config) {
399
447
  /** Resets a forgotten password with the code from `requestOtp({ email })`. */
400
448
  resetPassword: (input, options) => write("POST", "/storefront/customer/password/reset", input, options),
401
449
  get: (options) => get("/storefront/customer", void 0, options),
450
+ /** Updates the profile and the saved fiscal data; `fiscal: null` deletes the latter. `422` with `field: 'fiscal.<field>'`. */
451
+ update: (input, options) => write("PATCH", "/storefront/customer", input, options),
402
452
  orders: (params, options) => get("/storefront/customer/orders", params, options),
403
453
  /** `null` when the order does not exist or belongs to someone else. */
404
454
  order: (id, options) => getOrNull(`/storefront/customer/orders/${enc(id)}`, void 0, options),
@@ -430,6 +480,45 @@ function storefrontDomainHeader(domain, market) {
430
480
  return code && /^[a-z0-9_-]{1,32}$/.test(code) ? `${host}#${code}` : host;
431
481
  }
432
482
 
483
+ // src/diagnose.ts
484
+ function maskToken(token) {
485
+ if (!token) return "(sin token)";
486
+ const prefix = /^[a-z]{2}_/.exec(token)?.[0] ?? "";
487
+ return token.length <= prefix.length + 8 ? `${prefix}\u2026` : `${prefix}\u2026${token.slice(-4)}`;
488
+ }
489
+ function repairPath(connectionName) {
490
+ return `OPS \u2192 Conexiones y API \u2192 ${connectionName ?? "<conexi\xF3n>"} \u2192 Reparar permisos`;
491
+ }
492
+ async function diagnose(client, options = {}) {
493
+ const log = options.log ?? ((m) => console.warn(m));
494
+ const timeoutMs = options.timeoutMs ?? 3e3;
495
+ const raw = client.config.token;
496
+ let mask;
497
+ try {
498
+ mask = maskToken(typeof raw === "function" ? raw() : raw);
499
+ } catch {
500
+ mask = maskToken(null);
501
+ }
502
+ try {
503
+ const info = await client.token.introspect({ signal: AbortSignal.timeout(timeoutMs) });
504
+ const missing = Array.isArray(info?.missing_scopes) ? info.missing_scopes : [];
505
+ if (missing.length > 0) {
506
+ log(
507
+ `[@asteby/storefront] La credencial ${mask} no tiene permisos que la tienda necesita: ${missing.join(", ")}. Rep\xE1ralo en ${repairPath(options.connectionName)} (no hace falta cambiar la clave ni reiniciar).`
508
+ );
509
+ }
510
+ return info ?? null;
511
+ } catch (err) {
512
+ if (isStorefrontError(err) && err.status === 401) {
513
+ try {
514
+ log(`[@asteby/storefront] OPS rechaz\xF3 la credencial ${mask} (401): est\xE1 revocada o vencida. Vuelve a conectar la tienda en OPS \u2192 Conexiones y API.`);
515
+ } catch {
516
+ }
517
+ }
518
+ return null;
519
+ }
520
+ }
521
+
433
522
  // src/payments.ts
434
523
  var ES = {
435
524
  "decline.insufficient_funds": "Tu tarjeta no tiene saldo suficiente. Prueba con otra tarjeta o paga en efectivo.",
@@ -935,6 +1024,6 @@ function deliveryNotices(delivery) {
935
1024
  };
936
1025
  }
937
1026
 
938
- export { CLIENT_IP_HEADER, COUNTRY_HEADERS, MISSING_WEIGHT, NOTE_MAX_LENGTH, StorefrontError, appendParams, clampPercent, createStorefrontClient, declineMessage, declineMessageKey, deliveryInput, deliveryNotices, formatMoney, formatVoucherExpiry, generateIdempotencyKey, hreflangLinks, isStorefrontError, isTokenPublishable, negotiateLocale, normalizeClientIp, normalizeNote, parseDelivery, parseMoney, parseProductFilters, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, preferredLanguages, productListQuery, promoProgressView, promotionMessages, rewardLabel, safeHttpsUrl, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
1027
+ export { CLIENT_IP_HEADER, COUNTRY_HEADERS, MISSING_WEIGHT, NOTE_MAX_LENGTH, StorefrontError, appendParams, clampPercent, createStorefrontClient, declineMessage, declineMessageKey, deliveryInput, deliveryNotices, diagnose, formatMoney, formatVoucherExpiry, generateIdempotencyKey, hreflangLinks, isStorefrontError, isTokenPublishable, maskToken, negotiateLocale, normalizeClientIp, normalizeNote, parseDelivery, parseMoney, parseProductFilters, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, preferredLanguages, productListQuery, promoProgressView, promotionMessages, repairPath, rewardLabel, safeHttpsUrl, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
939
1028
  //# sourceMappingURL=index.js.map
940
1029
  //# sourceMappingURL=index.js.map