@kotao/storefront 0.2.2 → 0.2.4

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.
Files changed (48) hide show
  1. package/dist/chunk-4OQYNUGM.js +29 -0
  2. package/dist/chunk-4OQYNUGM.js.map +1 -0
  3. package/dist/{chunk-7XYWHWT4.js → chunk-4TEFGD42.js} +331 -38
  4. package/dist/chunk-4TEFGD42.js.map +1 -0
  5. package/dist/chunk-7MTCGXIG.js +144 -0
  6. package/dist/chunk-7MTCGXIG.js.map +1 -0
  7. package/dist/chunk-IIOHENCG.js +239 -0
  8. package/dist/chunk-IIOHENCG.js.map +1 -0
  9. package/dist/chunk-VV653S52.js +246 -0
  10. package/dist/chunk-VV653S52.js.map +1 -0
  11. package/dist/chunk-WG7HYVHJ.js +38 -0
  12. package/dist/chunk-WG7HYVHJ.js.map +1 -0
  13. package/dist/{client-DiPdlvPu.d.ts → client-D51WdvYR.d.ts} +55 -8
  14. package/dist/client-bsiNPHBi.d.ts +159 -0
  15. package/dist/createCartHandler-C4RrPwSG.d.ts +58 -0
  16. package/dist/editor.d.ts +1 -1
  17. package/dist/events-react.d.ts +68 -0
  18. package/dist/events-react.js +557 -0
  19. package/dist/events-react.js.map +1 -0
  20. package/dist/events.d.ts +18 -0
  21. package/dist/events.js +5 -0
  22. package/dist/events.js.map +1 -0
  23. package/dist/{fetch-B6TIc6lI.d.ts → fetch-M3Y-fQrW.d.ts} +1 -1
  24. package/dist/forms.d.ts +58 -0
  25. package/dist/forms.js +3 -0
  26. package/dist/forms.js.map +1 -0
  27. package/dist/http-types-CGh8WGHB.d.ts +11 -0
  28. package/dist/index.d.ts +74 -12
  29. package/dist/index.js +55 -9
  30. package/dist/index.js.map +1 -1
  31. package/dist/offer-token-C-nk_nj8.d.ts +16 -0
  32. package/dist/{pagination-CPgH3fAa.d.ts → pagination-DCrQk02Q.d.ts} +1 -1
  33. package/dist/product.d.ts +1 -1
  34. package/dist/react-router.d.ts +11 -7
  35. package/dist/react-router.js +4 -3
  36. package/dist/react-router.js.map +1 -1
  37. package/dist/react.d.ts +30 -7
  38. package/dist/react.js +4 -2
  39. package/dist/react.js.map +1 -1
  40. package/dist/{routing-BxRlep_-.d.ts → routing-sEonP93J.d.ts} +17 -60
  41. package/dist/seo.d.ts +2 -1
  42. package/dist/settings.d.ts +5 -4
  43. package/dist/{shop-DkQmro-Y.d.ts → shop-BJSvtmnV.d.ts} +2 -2
  44. package/dist/{store-DQK1nhob.d.ts → store-CtCWHI8H.d.ts} +1 -1
  45. package/dist/types-CSNXbGFW.d.ts +108 -0
  46. package/dist/{types-Df3bGbKU.d.ts → types-bcbQzx87.d.ts} +1 -1
  47. package/package.json +14 -2
  48. package/dist/chunk-7XYWHWT4.js.map +0 -1
@@ -0,0 +1,18 @@
1
+ import { C as CartHandler } from './createCartHandler-C4RrPwSG.js';
2
+ export { C as ClaimEventApprovalOffer, d as CreateEventApprovalRequest, e as CreateEventCheckoutSession, f as CreateEventWaitlistEntry, b as EventApprovalOfferResolution, g as EventApprovalRequestReceipt, a as EventCheckoutSession, h as EventFormAnswer, i as EventFormSubmissionInput, j as EventRegistrationMode, k as EventRegistrationResult, c as EventRegistrationSubmission, l as EventWaitlistReceipt, E as EventsClient, P as PublicEvent, m as PublicEventForm, n as PublicEventOccurrence, o as PublicEventTicketType, p as PublicEventVenue, S as StorefrontEventsRequestError, q as createEventsClient } from './client-bsiNPHBi.js';
3
+ export { a as OfferTokenHistory, O as OfferTokenLocation, c as consumeOfferTokenFragment, o as offerTokenHrefMarker } from './offer-token-C-nk_nj8.js';
4
+ import './client-D51WdvYR.js';
5
+ import './http-types-CGh8WGHB.js';
6
+ import './types-bcbQzx87.js';
7
+ import './types-CSNXbGFW.js';
8
+
9
+ declare class EventCartPreparationError extends Error {
10
+ constructor();
11
+ }
12
+ declare function eventCartToken(cartId: string): string;
13
+ declare function prepareEventCart(cart: CartHandler): Promise<{
14
+ cartToken: string;
15
+ headers: Headers;
16
+ }>;
17
+
18
+ export { EventCartPreparationError, eventCartToken, prepareEventCart };
package/dist/events.js ADDED
@@ -0,0 +1,5 @@
1
+ export { EventCartPreparationError, eventCartToken, prepareEventCart } from './chunk-4OQYNUGM.js';
2
+ export { consumeOfferTokenFragment, offerTokenHrefMarker } from './chunk-WG7HYVHJ.js';
3
+ export { StorefrontEventsRequestError, createEventsClient } from './chunk-7MTCGXIG.js';
4
+ //# sourceMappingURL=events.js.map
5
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"events.js"}
@@ -1,5 +1,5 @@
1
1
  import { SectionInstance, ValuesDocument } from '@kotao/storefront-contracts/theme';
2
- import { S as StorefrontAuthHeader } from './client-DiPdlvPu.js';
2
+ import { a as StorefrontAuthHeader } from './client-D51WdvYR.js';
3
3
 
4
4
  /**
5
5
  * The stored settings a theme hydrates from (#93): the layout document's ordered section instances +
@@ -0,0 +1,58 @@
1
+ import { i as FormVisibilityRule, a as FormAnswers, F as FormVersionSchema, e as FormField, f as FormLocalizedText, g as FormRenderState, P as PublicForm, b as FormFieldErrors, h as FormSubmission } from './types-CSNXbGFW.js';
2
+ export { c as FormAnswer, d as FormBlock, j as PublicFormDefinition, k as PublicFormVersion } from './types-CSNXbGFW.js';
3
+
4
+ declare const FORM_ANSWER_PREFIX = "answers";
5
+ declare const ADDRESS_PROPERTIES: readonly ["line1", "line2", "city", "postalCode", "countryCode", "provinceCode"];
6
+ declare function formAnswerName(fieldKey: string, property?: string): string;
7
+ declare function resolveFormText(value: FormLocalizedText | undefined, locale: string, fallbackLocale?: string): string;
8
+ declare function evaluateFormRule(rule: FormVisibilityRule, answers: FormAnswers): boolean;
9
+ declare function isFormFieldVisible(field: FormField, answers: FormAnswers): boolean;
10
+ declare function formFields(schema: FormVersionSchema): FormField[];
11
+ declare function parseFormAnswers(schema: FormVersionSchema, data: FormData): FormAnswers;
12
+
13
+ interface RenderFormHtmlOptions extends FormRenderState {
14
+ locale: string;
15
+ action?: string;
16
+ formClass?: string;
17
+ fallbackLocale?: string;
18
+ idempotencyKey?: string;
19
+ honeypotName?: string;
20
+ }
21
+ declare function renderFormHtml(form: PublicForm, options: RenderFormHtmlOptions): string;
22
+
23
+ interface FormFetchOptions {
24
+ fetch?: typeof fetch;
25
+ apiBaseUrl?: string;
26
+ headers?: ConstructorParameters<typeof Headers>[0];
27
+ signal?: AbortSignal;
28
+ }
29
+ interface SubmitFormInput extends FormFetchOptions {
30
+ versionId: string;
31
+ locale: string;
32
+ answers: FormAnswers;
33
+ idempotencyKey?: string;
34
+ }
35
+ declare class StorefrontFormRequestError extends Error {
36
+ readonly status: number;
37
+ readonly fieldErrors: FormFieldErrors;
38
+ constructor(status: number, message: string, fieldErrors?: FormFieldErrors);
39
+ }
40
+ declare function loadPublishedForm(handle: string, options?: FormFetchOptions): Promise<PublicForm>;
41
+ declare function submitPublishedForm(handle: string, input: SubmitFormInput): Promise<FormSubmission>;
42
+
43
+ interface ShopifyContactInput {
44
+ readonly name?: string | null;
45
+ readonly email: string;
46
+ readonly body: string;
47
+ readonly phone?: string | null;
48
+ }
49
+ type ShopifyContactCompatibility = {
50
+ readonly compatible: true;
51
+ readonly answers: FormAnswers;
52
+ } | {
53
+ readonly compatible: false;
54
+ readonly reason: 'not-contact-purpose' | 'unsupported-required-field' | 'incompatible-standard-field';
55
+ };
56
+ declare function adaptShopifyContactForm(form: PublicForm, input: ShopifyContactInput): ShopifyContactCompatibility;
57
+
58
+ export { ADDRESS_PROPERTIES, FORM_ANSWER_PREFIX, FormAnswers, type FormFetchOptions, FormField, FormFieldErrors, FormLocalizedText, FormRenderState, FormSubmission, FormVersionSchema, FormVisibilityRule, PublicForm, type RenderFormHtmlOptions, type ShopifyContactCompatibility, type ShopifyContactInput, StorefrontFormRequestError, type SubmitFormInput, adaptShopifyContactForm, evaluateFormRule, formAnswerName, formFields, isFormFieldVisible, loadPublishedForm, parseFormAnswers, renderFormHtml, resolveFormText, submitPublishedForm };
package/dist/forms.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ADDRESS_PROPERTIES, FORM_ANSWER_PREFIX, StorefrontFormRequestError, adaptShopifyContactForm, evaluateFormRule, formAnswerName, formFields, isFormFieldVisible, loadPublishedForm, parseFormAnswers, renderFormHtml, resolveFormText, submitPublishedForm } from './chunk-IIOHENCG.js';
2
+ //# sourceMappingURL=forms.js.map
3
+ //# sourceMappingURL=forms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"forms.js"}
@@ -0,0 +1,11 @@
1
+ /** Structural Headers-compatible value without depending on an ambient `HeadersInit` alias. */
2
+ interface StorefrontHeadersLike {
3
+ forEach(callback: (value: string, key: string) => void): void;
4
+ }
5
+ /**
6
+ * Header input accepted by storefront clients. This preserves the iterable and record shapes
7
+ * accepted by the Web Headers constructor while remaining portable to Node-only declarations.
8
+ */
9
+ type StorefrontHeadersInit = StorefrontHeadersLike | Iterable<Iterable<string>> | Record<string, string>;
10
+
11
+ export type { StorefrontHeadersInit as S };
package/dist/index.d.ts CHANGED
@@ -1,20 +1,28 @@
1
- export { b as CacheCustom, c as CacheLong, d as CacheNone, e as CacheShort, C as CacheStrategy, H as HydrogenStorefrontClientOptions, K as KotaoCache, f as Storefront, S as StorefrontAuthHeader, a as StorefrontClient, g as StorefrontClientOptions, h as StorefrontClientResult, i as StorefrontDefaultCache, j as StorefrontQueryOptions, k as createCache, l as createStorefrontClient, m as generateCacheControlHeader } from './client-DiPdlvPu.js';
2
- import { a as Cart } from './types-Df3bGbKU.js';
3
- export { k as CART_FORM_ACTIONS, c as CartAttribute, l as CartBuyerIdentity, d as CartBuyerIdentityInput, i as CartDeliveryAddress, C as CartFormAction, m as CartLine, b as CartLineInput, f as CartLineUpdateInput, g as CartMetafield, h as CartMetafieldIdentifier, e as CartMutationResult, j as CartSelectedDeliveryOption, n as CartUserError, o as HydrogenCart, p as HydrogenCartCreateInput, q as HydrogenCartMutationResult, H as HydrogenSession, r as HydrogenSessionData } from './types-Df3bGbKU.js';
4
- import { C as ConsentBucket, a as ConsentState, B as BoundNonceProvider } from './shop-DkQmro-Y.js';
5
- export { A as ANALYTICS_EVENTS, b as AnalyticsBus, c as AnalyticsBusOptions, d as AnalyticsContext, e as AnalyticsEmitter, f as AnalyticsEventMap, g as AnalyticsEventName, h as AnalyticsGeo, i as CONSENT_BUCKETS, j as CONSENT_COOKIE, k as CartForm, l as CartFormProps, m as CartViewedPayload, n as CollectionViewedPayload, D as DENIED_CONSENT, E as EventHandler, G as GRANTED_CONSENT, o as GetShopAnalyticsOptions, P as PageViewedPayload, p as PixelEvent, q as PixelSend, r as PixelTransport, s as PixelTransportOptions, t as ProductAddedToCartPayload, u as ProductViewedPayload, S as SearchViewedPayload, v as ShopAnalytics, w as buildConsentCookie, x as createAnalyticsBus, y as createAnalyticsEmitter, z as createPixelTransport, F as getShopAnalytics, H as isGranted, I as mergeConsent, J as parseConsent, K as readConsentCookie, L as serializeConsent } from './shop-DkQmro-Y.js';
6
- import { C as CartDispatchAction, c as CustomerAccountClient } from './routing-BxRlep_-.js';
7
- export { A as Address, d as AddressConnection, e as CartGetId, f as CartHandler, g as CartSetId, h as CreateCartHandlerOptions, i as CustomerAccount, j as CustomerAccountError, k as CustomerAccountErrorCode, G as GEO_HEADER, l as GEO_SIGNATURE_HEADER, m as Geo, H as HydrogenCartHandlerOptions, a as KotaoContext, K as KotaoEnv, b as KotaoSession, L as LocalizePathOptions, M as Money, O as Order, n as OrderConnection, o as OrderPageInfo, p as OrdersOptions, R as ROUTING_LOCALE_HEADER, q as ROUTING_ORIGINAL_PATHNAME_HEADER, r as RequestCartHandlerOptions, t as RequestLoginCodeInput, u as RequestLoginCodeResult, S as StrippedLocalePath, V as VerifyLoginCodeInput, W as WithCache, v as cartGetIdDefault, w as cartSetIdDefault, x as createCartHandler, y as createKotaoContext, z as createWithCache, B as isLocalePathSegment, D as localeFromAcceptLanguage, E as localeFromPathname, F as localeFromRequest, I as localizePath, J as originalPathnameFromRequest, N as signGeo, P as stripLocalePrefixFromPathname, s as stripLocalePrefixFromRequest, Q as verifyGeo } from './routing-BxRlep_-.js';
8
- import { T as ThemeSettingsSnapshot } from './store-DQK1nhob.js';
9
- export { R as ResolvedBlock, a as ResolvedSection, b as ResolvedSettings, c as ThemeSettingsStore, d as createThemeSettingsStore } from './store-DQK1nhob.js';
1
+ export { c as CacheCustom, d as CacheLong, e as CacheNone, f as CacheShort, C as CacheStrategy, H as HydrogenStorefrontClientOptions, K as KotaoCache, g as StaleIfErrorFallback, h as Storefront, a as StorefrontAuthHeader, i as StorefrontCache, b as StorefrontCacheInput, j as StorefrontCacheQueryOptions, k as StorefrontCacheRequest, S as StorefrontClient, l as StorefrontClientOptions, m as StorefrontClientResult, n as StorefrontDefaultCache, o as StorefrontQueryOptions, p as StorefrontQueryTimeoutError, q as StorefrontUpstreamError, r as createCache, s as createStorefrontClient, t as generateCacheControlHeader } from './client-D51WdvYR.js';
2
+ import { C as Cart } from './types-bcbQzx87.js';
3
+ export { k as CART_FORM_ACTIONS, b as CartAttribute, l as CartBuyerIdentity, c as CartBuyerIdentityInput, h as CartDeliveryAddress, j as CartFormAction, m as CartLine, a as CartLineInput, e as CartLineUpdateInput, f as CartMetafield, g as CartMetafieldIdentifier, d as CartMutationResult, i as CartSelectedDeliveryOption, n as CartUserError, o as HydrogenCart, p as HydrogenCartCreateInput, q as HydrogenCartMutationResult, H as HydrogenSession, r as HydrogenSessionData } from './types-bcbQzx87.js';
4
+ import { c as ConsentBucket, C as ConsentState, B as BoundNonceProvider } from './shop-BJSvtmnV.js';
5
+ export { d as ANALYTICS_EVENTS, b as AnalyticsBus, e as AnalyticsBusOptions, A as AnalyticsContext, a as AnalyticsEmitter, f as AnalyticsEventMap, h as AnalyticsEventName, i as AnalyticsGeo, j as CONSENT_BUCKETS, k as CONSENT_COOKIE, l as CartForm, m as CartFormProps, n as CartViewedPayload, o as CollectionViewedPayload, D as DENIED_CONSENT, E as EventHandler, G as GRANTED_CONSENT, p as GetShopAnalyticsOptions, P as PageViewedPayload, q as PixelEvent, r as PixelSend, s as PixelTransport, t as PixelTransportOptions, v as ProductAddedToCartPayload, w as ProductViewedPayload, x as SearchViewedPayload, S as ShopAnalytics, y as buildConsentCookie, z as createAnalyticsBus, F as createAnalyticsEmitter, H as createPixelTransport, I as getShopAnalytics, J as isGranted, K as mergeConsent, L as parseConsent, M as readConsentCookie, N as serializeConsent } from './shop-BJSvtmnV.js';
6
+ import { a as CartDispatchAction } from './createCartHandler-C4RrPwSG.js';
7
+ export { b as CartGetId, C as CartHandler, c as CartSetId, d as CreateCartHandlerOptions, H as HydrogenCartHandlerOptions, R as RequestCartHandlerOptions, e as cartGetIdDefault, f as cartSetIdDefault, g as createCartHandler } from './createCartHandler-C4RrPwSG.js';
8
+ import { a as ThemeSettingsSnapshot, R as ResolvedSettings } from './store-CtCWHI8H.js';
9
+ export { b as ResolvedBlock, c as ResolvedSection, T as ThemeSettingsStore, d as createThemeSettingsStore } from './store-CtCWHI8H.js';
10
+ import { C as CustomerAccountClient } from './routing-sEonP93J.js';
11
+ export { A as Address, c as AddressConnection, d as CustomerAccount, e as CustomerAccountError, f as CustomerAccountErrorCode, G as GEO_HEADER, g as GEO_SIGNATURE_HEADER, h as Geo, a as KotaoContext, K as KotaoEnv, b as KotaoSession, L as LocalizePathOptions, M as Money, O as Order, i as OrderConnection, j as OrderPageInfo, k as OrdersOptions, R as ROUTING_LOCALE_HEADER, l as ROUTING_ORIGINAL_PATHNAME_HEADER, m as RequestLoginCodeInput, n as RequestLoginCodeResult, S as StorefrontExecutionContext, o as StrippedLocalePath, V as VerifyLoginCodeInput, W as WithCache, p as createKotaoContext, q as createWithCache, r as isLocalePathSegment, t as localeFromAcceptLanguage, u as localeFromPathname, v as localeFromRequest, w as localizePath, x as originalPathnameFromRequest, y as signGeo, z as stripLocalePrefixFromPathname, s as stripLocalePrefixFromRequest, B as trustedShopOriginFromHeaders, D as verifyGeo } from './routing-sEonP93J.js';
10
12
  export { ImageAttrs, ImageAttrsOptions, ImageCrop, ImageData, ImageFit, ImageFormat, ImageSrcSetOptions, ImageUrlOptions, buildImageAttrs, imageSrcSet, imageUrl } from './image.js';
11
- export { C as Connection, a as ConnectionEdge, F as FlattenableConnection, P as PageInfo, b as PaginationInfo, c as PaginationOptions, d as PaginationVariables, f as flattenConnection, g as getPaginationInfo, e as getPaginationVariables } from './pagination-CPgH3fAa.js';
13
+ export { C as Connection, a as ConnectionEdge, F as FlattenableConnection, b as PageInfo, P as PaginationInfo, c as PaginationOptions, d as PaginationVariables, f as flattenConnection, g as getPaginationInfo, e as getPaginationVariables } from './pagination-DCrQk02Q.js';
12
14
  export { MappedProductOptions, ProductLike, ProductOptionDef, ProductOptionState, ProductOptionValueState, SelectedOption, SelectedOptionsMap, VariantLike, VariantSelectionLike, getAdjacentAndFirstAvailableVariants, getProductOptions, getSelectedProductOptions, getSelectedVariant, mapSelectedProductOptionToObject, useOptimisticVariant, useSelectedOptionInUrlParam } from './product.js';
13
15
  export { ResolveThemeSettingsArgs, mergeSection, mergeSettings, resolveThemeSettings } from './settings.js';
14
- export { F as FetchThemeSettingsOptions, S as StoredThemeSettings, f as fetchThemeSettings } from './fetch-B6TIc6lI.js';
16
+ export { F as FetchThemeSettingsOptions, S as StoredThemeSettings, f as fetchThemeSettings } from './fetch-M3Y-fQrW.js';
15
17
  export { AddressInput, BreadcrumbItem, ChangeFreq, GeoInput, LocalBusinessInput, OfferInput, OrganizationInput, ProductJsonLdInput, RedirectLookup, RedirectOptions, RobotsOptions, SitemapEntry, SitemapIndexEntry, StorefrontRedirectOptions, URL_REDIRECT_QUERY, WebSiteInput, breadcrumbListJsonLd, buildRobotsTxt, buildSitemapIndexXml, buildSitemapXml, getSeoMeta, localBusinessJsonLd, organizationJsonLd, productJsonLd, resolveRedirect, resolveStorefrontRedirect, restaurantJsonLd, robotsResponse, serializeJsonLd, sitemapIndexResponse, sitemapResponse, storefrontRedirect, websiteJsonLd } from './seo.js';
16
18
  export { A as Alternate, J as JsonLd, O as OpenGraph, a as OpenGraphImage, S as SeoConfig, b as SeoDescriptor, T as TwitterCard } from './types-BDhHWZsP.js';
19
+ export { c as FormAnswer, a as FormAnswers, d as FormBlock, e as FormField, b as FormFieldErrors, f as FormLocalizedText, g as FormRenderState, h as FormSubmission, F as FormVersionSchema, i as FormVisibilityRule, P as PublicForm, j as PublicFormDefinition, k as PublicFormVersion } from './types-CSNXbGFW.js';
20
+ export { ADDRESS_PROPERTIES, FORM_ANSWER_PREFIX, FormFetchOptions, RenderFormHtmlOptions, ShopifyContactCompatibility, ShopifyContactInput, StorefrontFormRequestError, SubmitFormInput, adaptShopifyContactForm, evaluateFormRule, formAnswerName, formFields, isFormFieldVisible, loadPublishedForm, parseFormAnswers, renderFormHtml, resolveFormText, submitPublishedForm } from './forms.js';
21
+ export { EventCartPreparationError, eventCartToken, prepareEventCart } from './events.js';
22
+ export { C as ClaimEventApprovalOffer, d as CreateEventApprovalRequest, e as CreateEventCheckoutSession, f as CreateEventWaitlistEntry, b as EventApprovalOfferResolution, g as EventApprovalRequestReceipt, a as EventCheckoutSession, h as EventFormAnswer, i as EventFormSubmissionInput, j as EventRegistrationMode, k as EventRegistrationResult, c as EventRegistrationSubmission, l as EventWaitlistReceipt, E as EventsClient, P as PublicEvent, m as PublicEventForm, n as PublicEventOccurrence, o as PublicEventTicketType, p as PublicEventVenue, S as StorefrontEventsRequestError, q as createEventsClient } from './client-bsiNPHBi.js';
23
+ export { a as OfferTokenHistory, O as OfferTokenLocation, c as consumeOfferTokenFragment, o as offerTokenHrefMarker } from './offer-token-C-nk_nj8.js';
17
24
  export { CreateStorefrontEditorBridgeArgs, CreateStorefrontEditorHostBridgeArgs, StorefrontEditorBlockSchema, StorefrontEditorBridge, StorefrontEditorHostBridge, StorefrontEditorMessageEvent, StorefrontEditorMessageSource, StorefrontEditorMessageTarget, StorefrontEditorReady, StorefrontEditorSectionPreset, StorefrontEditorSectionPresetBlock, StorefrontEditorSectionSchema, StorefrontEditorSelection, StorefrontEditorSettingInput, StorefrontEditorSettingOption, createStorefrontEditorBridge, createStorefrontEditorHostBridge } from './editor.js';
25
+ import './http-types-CGh8WGHB.js';
18
26
  import 'react';
19
27
  import './storefront-api-types.js';
20
28
  import '@kotao/storefront-contracts/theme';
@@ -144,6 +152,10 @@ interface CustomerAccountClientOptions {
144
152
  readonly customerAccountId?: string | undefined;
145
153
  /** Hydrogen server compatibility: accepted for original server.ts call sites; Kotao proxies do not need it. */
146
154
  readonly shopId?: string | undefined;
155
+ /** Stage/configuration-pinned HTTPS shop origin used for account mutations. */
156
+ readonly shopOrigin?: string | undefined;
157
+ /** Bounded rollout fallback; opaque hosted sessions always win. Defaults true during migration. */
158
+ readonly allowLegacySessionForwarding?: boolean | undefined;
147
159
  }
148
160
  /**
149
161
  * Theme-facing customer-account client (#91), mirroring Hydrogen's `createCustomerAccount`. Kotao
@@ -161,6 +173,12 @@ declare function createCustomerAccountClient(opts: CustomerAccountClientOptions)
161
173
  */
162
174
  declare const CUSTOMER_SESSION_COOKIE = "kotao_customer_session";
163
175
  declare const DEFAULT_SESSION_MAX_AGE: number;
176
+ declare const HOSTED_CUSTOMER_SESSION_COOKIE = "__Host-kotao_customer_session";
177
+ declare const HOSTED_CUSTOMER_CSRF_COOKIE = "__Host-kotao_customer_csrf";
178
+ declare const HOSTED_CUSTOMER_CSRF_HEADER = "x-kotao-csrf-token";
179
+ declare const MAX_HOSTED_SESSION_MAX_AGE: number;
180
+ declare const DEFAULT_HOSTED_SESSION_MAX_AGE: number;
181
+ declare const MAX_LEGACY_CUSTOMER_SESSION_TOKEN_LENGTH = 4096;
164
182
  interface SessionCookieAttrs {
165
183
  /**
166
184
  * The shop's custom hostname. `Domain` is pinned to it host-scoped (no leading dot), so the cookie
@@ -169,6 +187,13 @@ interface SessionCookieAttrs {
169
187
  readonly hostname: string;
170
188
  readonly maxAgeSeconds?: number;
171
189
  }
190
+ interface HostedSessionCookieAttrs {
191
+ readonly maxAgeSeconds?: number;
192
+ }
193
+ interface LegacySessionReadOptions {
194
+ /** The caller must opt in only while the one-time legacy exchange is enabled. */
195
+ readonly allowLegacy: boolean;
196
+ }
172
197
  /** The shop custom host of the current request — the session isolation boundary. */
173
198
  declare function shopHostname(request: Request): string;
174
199
  /**
@@ -180,5 +205,42 @@ declare function buildCustomerSessionCookie(token: string, attrs: SessionCookieA
180
205
  declare function clearCustomerSessionCookie(attrs: SessionCookieAttrs): string;
181
206
  /** Read the session token out of a server-side `Cookie` header; null if absent or empty. */
182
207
  declare function readCustomerSessionToken(cookieHeader: string | null | undefined): string | null;
208
+ /** Build the opaque hosted-session cookie required by the `__Host-` browser contract. */
209
+ declare function buildHostedCustomerSessionCookie(token: string, attrs?: HostedSessionCookieAttrs): string;
210
+ /** Clear the host-only opaque session without ever adding a Domain attribute. */
211
+ declare function clearHostedCustomerSessionCookie(): string;
212
+ /** Read only the new host-only opaque session cookie. */
213
+ declare function readHostedCustomerSessionToken(cookieHeader: string | null | undefined): string | null;
214
+ declare function readHostedCustomerCsrfToken(cookieHeader: string | null | undefined): string | null;
215
+ /**
216
+ * Read the old stateless cookie only during an explicitly enabled migration window. Oversized
217
+ * values are rejected before decoding so the compatibility path remains bounded.
218
+ */
219
+ declare function readLegacyCustomerSessionToken(cookieHeader: string | null | undefined, options: LegacySessionReadOptions): string | null;
220
+ /** Explicitly clear the old Domain-scoped cookie after a migration attempt. */
221
+ declare function clearLegacyCustomerSessionCookie(attrs: SessionCookieAttrs): string;
222
+
223
+ /** Resolve the token contract shared by trusted checkout and customer-account surfaces. */
224
+ declare function resolveHostedBranding(global: ResolvedSettings): CheckoutDesignTokens;
225
+ /** Escape merchant-controlled text for an HTML text node or double-quoted attribute. */
226
+ declare function escapeHostedHtml(value: string): string;
227
+ /**
228
+ * Strip characters that can terminate an inline CSS declaration, block, quote, or style element.
229
+ * Trusted renderers must apply this at the CSS-value sink; the resolved token values themselves
230
+ * remain byte-for-byte compatible with checkout's existing contract.
231
+ */
232
+ declare function sanitizeHostedCssValue(value: string): string;
233
+
234
+ interface HostedLocaleInput {
235
+ readonly configuredLocales: readonly string[];
236
+ readonly localizationCookie: string | null;
237
+ readonly customerLocale: string | null;
238
+ readonly primaryLocale: string;
239
+ }
240
+ /**
241
+ * Resolve display language within the verified shop's configured locale allowlist. Payment
242
+ * jurisdiction and legal-copy decisions deliberately stay outside this display-only resolver.
243
+ */
244
+ declare function resolveHostedLocale(input: HostedLocaleInput): string;
183
245
 
184
- export { CART_ID_COOKIE, CHECKOUT_CONSENT_CATEGORIES, CHECKOUT_CONSENT_PARAM_PREFIX, CHECKOUT_DESIGN_TOKEN_INPUTS, CUSTOMER_SESSION_COOKIE, Cart, CartDispatchAction, type CheckoutDesignTokens, ConsentBucket, ConsentState, type ContentSecurityPolicyResult, type ContentSecurityPolicyShop, type CreateContentSecurityPolicyOptions, CustomerAccountClient, type CustomerAccountClientOptions, DEFAULT_SESSION_MAX_AGE, LOCALIZATION_COOKIE, type ResolveCheckoutUrlOptions, type SessionCookieAttrs, ThemeSettingsSnapshot, appendConsentToCheckoutUrl, applyOptimisticCartAction, buildCartIdCookie, buildCustomerSessionCookie, buildLocalizationCookie, clearCustomerSessionCookie, createContentSecurityPolicy, createCustomerAccountClient, decodeCheckoutConsent, decodeConsent, encodeCheckoutConsent, encodeConsent, extractCheckoutDesignTokens, handleLocalizationPost, readCartIdCookie, readCustomerSessionToken, readLocalizationCookie, resolveCheckoutUrl, shopHostname, useOptimisticCart };
246
+ export { CART_ID_COOKIE, CHECKOUT_CONSENT_CATEGORIES, CHECKOUT_CONSENT_PARAM_PREFIX, CHECKOUT_DESIGN_TOKEN_INPUTS, CUSTOMER_SESSION_COOKIE, Cart, CartDispatchAction, type CheckoutDesignTokens, ConsentBucket, ConsentState, type ContentSecurityPolicyResult, type ContentSecurityPolicyShop, type CreateContentSecurityPolicyOptions, CustomerAccountClient, type CustomerAccountClientOptions, DEFAULT_HOSTED_SESSION_MAX_AGE, DEFAULT_SESSION_MAX_AGE, HOSTED_CUSTOMER_CSRF_COOKIE, HOSTED_CUSTOMER_CSRF_HEADER, HOSTED_CUSTOMER_SESSION_COOKIE, type HostedLocaleInput, type HostedSessionCookieAttrs, LOCALIZATION_COOKIE, type LegacySessionReadOptions, MAX_HOSTED_SESSION_MAX_AGE, MAX_LEGACY_CUSTOMER_SESSION_TOKEN_LENGTH, type ResolveCheckoutUrlOptions, ResolvedSettings, type SessionCookieAttrs, ThemeSettingsSnapshot, appendConsentToCheckoutUrl, applyOptimisticCartAction, buildCartIdCookie, buildCustomerSessionCookie, buildHostedCustomerSessionCookie, buildLocalizationCookie, clearCustomerSessionCookie, clearHostedCustomerSessionCookie, clearLegacyCustomerSessionCookie, createContentSecurityPolicy, createCustomerAccountClient, decodeCheckoutConsent, decodeConsent, encodeCheckoutConsent, encodeConsent, escapeHostedHtml, extractCheckoutDesignTokens, handleLocalizationPost, readCartIdCookie, readCustomerSessionToken, readHostedCustomerCsrfToken, readHostedCustomerSessionToken, readLegacyCustomerSessionToken, readLocalizationCookie, resolveCheckoutUrl, resolveHostedBranding, resolveHostedLocale, sanitizeHostedCssValue, shopHostname, useOptimisticCart };
package/dist/index.js CHANGED
@@ -1,17 +1,21 @@
1
- export { URL_REDIRECT_QUERY, breadcrumbListJsonLd, buildRobotsTxt, buildSitemapIndexXml, buildSitemapXml, localBusinessJsonLd, organizationJsonLd, productJsonLd, resolveRedirect, resolveStorefrontRedirect, restaurantJsonLd, robotsResponse, sitemapIndexResponse, sitemapResponse, storefrontRedirect, websiteJsonLd } from './chunk-PXVDVUFX.js';
2
- export { createThemeSettingsStore, mergeSection, mergeSettings, resolveThemeSettings } from './chunk-H3D7BAOL.js';
3
- export { createStorefrontEditorBridge, createStorefrontEditorHostBridge } from './chunk-PXZ737N3.js';
4
1
  export { getAdjacentAndFirstAvailableVariants, getProductOptions, getSelectedProductOptions, getSelectedVariant, mapSelectedProductOptionToObject, useOptimisticVariant, useSelectedOptionInUrlParam } from './chunk-QOEEUTHQ.js';
5
2
  import { createNonceProvider } from './chunk-XMTWFJCZ.js';
6
3
  export { CartForm, createAnalyticsBus, createAnalyticsEmitter, createPixelTransport } from './chunk-XMTWFJCZ.js';
7
- export { getSeoMeta, serializeJsonLd } from './chunk-MYDKIJRH.js';
8
- export { buildImageAttrs, imageSrcSet, imageUrl } from './chunk-3YQXJNR7.js';
9
4
  export { flattenConnection, getPaginationInfo, getPaginationVariables } from './chunk-5QOFKGKD.js';
10
- import { localizePath, buildLocalizationCookie } from './chunk-7XYWHWT4.js';
11
- export { CART_ID_COOKIE, CHECKOUT_CONSENT_CATEGORIES, CHECKOUT_CONSENT_PARAM_PREFIX, CHECKOUT_DESIGN_TOKEN_INPUTS, CUSTOMER_SESSION_COOKIE, CacheCustom, CacheLong, CacheNone, CacheShort, CustomerAccountError, DEFAULT_SESSION_MAX_AGE, GEO_HEADER, GEO_SIGNATURE_HEADER, LOCALIZATION_COOKIE, ROUTING_LOCALE_HEADER, ROUTING_ORIGINAL_PATHNAME_HEADER, StorefrontDefaultCache, buildCartIdCookie, buildCustomerSessionCookie, buildLocalizationCookie, cartGetIdDefault, cartSetIdDefault, clearCustomerSessionCookie, createCache, createCartHandler, createCustomerAccountClient, createKotaoContext, createStorefrontClient, createWithCache, decodeCheckoutConsent, encodeCheckoutConsent, extractCheckoutDesignTokens, generateCacheControlHeader, isLocalePathSegment, localeFromAcceptLanguage, localeFromPathname, localeFromRequest, localizePath, originalPathnameFromRequest, readCartIdCookie, readCustomerSessionToken, readLocalizationCookie, resolveCheckoutUrl, shopHostname, signGeo, stripLocalePrefixFromPathname, stripLocalePrefixFromRequest, verifyGeo } from './chunk-7XYWHWT4.js';
12
- export { fetchThemeSettings } from './chunk-M7BPQ54D.js';
5
+ import { CHECKOUT_DESIGN_TOKEN_INPUTS, localizePath, buildLocalizationCookie, extractCheckoutDesignTokens, readLocalizationCookie } from './chunk-4TEFGD42.js';
6
+ export { CART_ID_COOKIE, CHECKOUT_CONSENT_CATEGORIES, CHECKOUT_CONSENT_PARAM_PREFIX, CHECKOUT_DESIGN_TOKEN_INPUTS, CUSTOMER_SESSION_COOKIE, CacheCustom, CacheLong, CacheNone, CacheShort, CustomerAccountError, DEFAULT_HOSTED_SESSION_MAX_AGE, DEFAULT_SESSION_MAX_AGE, GEO_HEADER, GEO_SIGNATURE_HEADER, HOSTED_CUSTOMER_CSRF_COOKIE, HOSTED_CUSTOMER_CSRF_HEADER, HOSTED_CUSTOMER_SESSION_COOKIE, LOCALIZATION_COOKIE, MAX_HOSTED_SESSION_MAX_AGE, MAX_LEGACY_CUSTOMER_SESSION_TOKEN_LENGTH, ROUTING_LOCALE_HEADER, ROUTING_ORIGINAL_PATHNAME_HEADER, StorefrontDefaultCache, StorefrontQueryTimeoutError, StorefrontUpstreamError, buildCartIdCookie, buildCustomerSessionCookie, buildHostedCustomerSessionCookie, buildLocalizationCookie, cartGetIdDefault, cartSetIdDefault, clearCustomerSessionCookie, clearHostedCustomerSessionCookie, clearLegacyCustomerSessionCookie, createCache, createCartHandler, createCustomerAccountClient, createKotaoContext, createStorefrontClient, createWithCache, decodeCheckoutConsent, encodeCheckoutConsent, extractCheckoutDesignTokens, generateCacheControlHeader, isLocalePathSegment, localeFromAcceptLanguage, localeFromPathname, localeFromRequest, localizePath, originalPathnameFromRequest, readCartIdCookie, readCustomerSessionToken, readHostedCustomerCsrfToken, readHostedCustomerSessionToken, readLegacyCustomerSessionToken, readLocalizationCookie, resolveCheckoutUrl, shopHostname, signGeo, stripLocalePrefixFromPathname, stripLocalePrefixFromRequest, trustedShopOriginFromHeaders, verifyGeo } from './chunk-4TEFGD42.js';
13
7
  import { CART_FORM_ACTIONS, CONSENT_BUCKETS } from './chunk-OGWYTYYS.js';
14
8
  export { CART_FORM_ACTIONS, CONSENT_BUCKETS, CONSENT_COOKIE, DENIED_CONSENT, GRANTED_CONSENT, buildConsentCookie, isGranted, mergeConsent, parseConsent, readConsentCookie, serializeConsent } from './chunk-OGWYTYYS.js';
9
+ export { URL_REDIRECT_QUERY, breadcrumbListJsonLd, buildRobotsTxt, buildSitemapIndexXml, buildSitemapXml, localBusinessJsonLd, organizationJsonLd, productJsonLd, resolveRedirect, resolveStorefrontRedirect, restaurantJsonLd, robotsResponse, sitemapIndexResponse, sitemapResponse, storefrontRedirect, websiteJsonLd } from './chunk-PXVDVUFX.js';
10
+ export { getSeoMeta, serializeJsonLd } from './chunk-MYDKIJRH.js';
11
+ export { createThemeSettingsStore, mergeSection, mergeSettings, resolveThemeSettings } from './chunk-H3D7BAOL.js';
12
+ export { fetchThemeSettings } from './chunk-M7BPQ54D.js';
13
+ export { createStorefrontEditorBridge, createStorefrontEditorHostBridge } from './chunk-PXZ737N3.js';
14
+ export { EventCartPreparationError, eventCartToken, prepareEventCart } from './chunk-4OQYNUGM.js';
15
+ export { consumeOfferTokenFragment, offerTokenHrefMarker } from './chunk-WG7HYVHJ.js';
16
+ export { StorefrontEventsRequestError, createEventsClient } from './chunk-7MTCGXIG.js';
17
+ export { ADDRESS_PROPERTIES, FORM_ANSWER_PREFIX, StorefrontFormRequestError, adaptShopifyContactForm, evaluateFormRule, formAnswerName, formFields, isFormFieldVisible, loadPublishedForm, parseFormAnswers, renderFormHtml, resolveFormText, submitPublishedForm } from './chunk-IIOHENCG.js';
18
+ export { buildImageAttrs, imageSrcSet, imageUrl } from './chunk-3YQXJNR7.js';
15
19
 
16
20
  // src/cart/useOptimisticCart.ts
17
21
  var recalculate = (cart, lines) => ({
@@ -204,6 +208,48 @@ function appendConsentToCheckoutUrl(checkoutUrl, state) {
204
208
  return `${url.pathname}${url.search}${url.hash}`;
205
209
  }
206
210
 
207
- export { ANALYTICS_EVENTS, appendConsentToCheckoutUrl, applyOptimisticCartAction, createContentSecurityPolicy, decodeConsent, encodeConsent, getShopAnalytics, handleLocalizationPost, useOptimisticCart };
211
+ // src/hosted-surface/branding.ts
212
+ var CHECKOUT_TOKEN_DEFAULTS = Object.fromEntries(
213
+ CHECKOUT_DESIGN_TOKEN_INPUTS.flatMap(
214
+ (input) => "defaultValue" in input && typeof input.defaultValue === "string" && input.defaultValue !== "" ? [[input.name, input.defaultValue]] : []
215
+ )
216
+ );
217
+ function resolveHostedBranding(global) {
218
+ return extractCheckoutDesignTokens({ global: { ...CHECKOUT_TOKEN_DEFAULTS, ...global } });
219
+ }
220
+ function escapeHostedHtml(value) {
221
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
222
+ }
223
+ function sanitizeHostedCssValue(value) {
224
+ return value.replace(/[<>"'`;{}\\]/g, "").replace(/[\r\n\t]+/g, " ").trim();
225
+ }
226
+
227
+ // src/hosted-surface/localization.ts
228
+ function resolveHostedLocale(input) {
229
+ const configured = input.configuredLocales.map((locale) => locale.trim()).filter(Boolean);
230
+ if (configured.length === 0) throw new Error("hosted surfaces require a configured locale");
231
+ const configuredByKey = new Map(configured.map((locale) => [localeKey(locale), locale]));
232
+ const cookieLocale = safelyReadCookieLocale(input.localizationCookie);
233
+ for (const candidate of [cookieLocale, input.customerLocale, input.primaryLocale]) {
234
+ if (candidate === null || candidate.trim() === "") continue;
235
+ const match = configuredByKey.get(localeKey(candidate));
236
+ if (match !== void 0) return match;
237
+ }
238
+ return configured[0];
239
+ }
240
+ function localeKey(locale) {
241
+ return locale.trim().replace(/_/g, "-").toLowerCase();
242
+ }
243
+ function safelyReadCookieLocale(cookieHeader) {
244
+ if (cookieHeader === null) return null;
245
+ if (!cookieHeader.includes("=")) return cookieHeader.trim() || null;
246
+ try {
247
+ return readLocalizationCookie(cookieHeader).locale;
248
+ } catch {
249
+ return null;
250
+ }
251
+ }
252
+
253
+ export { ANALYTICS_EVENTS, appendConsentToCheckoutUrl, applyOptimisticCartAction, createContentSecurityPolicy, decodeConsent, encodeConsent, escapeHostedHtml, getShopAnalytics, handleLocalizationPost, resolveHostedBranding, resolveHostedLocale, sanitizeHostedCssValue, useOptimisticCart };
208
254
  //# sourceMappingURL=index.js.map
209
255
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cart/useOptimisticCart.ts","../src/content-security-policy.ts","../src/localization/handler.ts","../src/analytics/events.ts","../src/analytics/shop.ts","../src/analytics/consent-encoding.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { CART_FORM_ACTIONS } from './actions'\nimport type { CartDispatchAction } from './createCartHandler'\nimport type { Cart, CartLine } from './types'\n\nconst recalculate = (cart: Cart, lines: readonly CartLine[]): Cart => ({\n ...cart,\n lines,\n totalQuantity: lines.reduce((sum, line) => sum + line.quantity, 0),\n})\n\nexport function applyOptimisticCartAction(cart: Cart, action: CartDispatchAction): Cart {\n switch (action.action) {\n case CART_FORM_ACTIONS.LinesAdd: {\n const inputLines = (action.inputs.lines ?? []) as Array<{\n merchandiseId: string\n quantity?: number | null\n }>\n const additions = inputLines.map<CartLine>((line) => ({\n id: `optimistic:${line.merchandiseId}`,\n quantity: line.quantity ?? 1,\n merchandise: { id: line.merchandiseId },\n attributes: [],\n }))\n return recalculate(cart, [...cart.lines, ...additions])\n }\n case CART_FORM_ACTIONS.LinesUpdate: {\n const updates = new Map(\n ((action.inputs.lines ?? []) as Array<{ id: string; quantity?: number | null }>).map(\n (line) => [line.id, line],\n ),\n )\n const lines = cart.lines\n .map((line) => {\n const update = updates.get(line.id)\n if (!update) return line\n if (update.quantity === 0) return null\n return {\n ...line,\n quantity: update.quantity ?? line.quantity,\n }\n })\n .filter((line): line is CartLine => line !== null)\n return recalculate(cart, lines)\n }\n case CART_FORM_ACTIONS.LinesRemove: {\n const remove = new Set((action.inputs.lineIds ?? []) as string[])\n return recalculate(\n cart,\n cart.lines.filter((line) => !remove.has(line.id)),\n )\n }\n default:\n return cart\n }\n}\n\n/**\n * Pure optimistic helper for React integrations. A React wrapper can call this from `useOptimistic`;\n * keeping the reducer pure lets non-React tests exercise the exact overlay behavior.\n */\nexport function useOptimisticCart(cart: Cart, action: CartDispatchAction | null): Cart {\n return action ? applyOptimisticCartAction(cart, action) : cart\n}\n","import { createNonceProvider, type BoundNonceProvider } from './react/nonce'\n\nexport interface ContentSecurityPolicyShop {\n readonly checkoutDomain?: string\n readonly storeDomain?: string\n}\n\nexport interface CreateContentSecurityPolicyOptions {\n readonly shop?: ContentSecurityPolicyShop\n readonly scriptSrc?: readonly string[]\n readonly connectSrc?: readonly string[]\n readonly imgSrc?: readonly string[]\n readonly styleSrc?: readonly string[]\n}\n\nexport interface ContentSecurityPolicyResult {\n readonly nonce: string\n readonly header: string\n readonly NonceProvider: BoundNonceProvider\n}\n\nconst QUOTED_TOKENS = new Set([\n 'self',\n 'none',\n 'unsafe-eval',\n 'unsafe-hashes',\n 'unsafe-inline',\n 'strict-dynamic',\n 'wasm-unsafe-eval',\n])\n\nexport function createContentSecurityPolicy(\n options: CreateContentSecurityPolicyOptions = {},\n): ContentSecurityPolicyResult {\n const nonce = createNonce()\n const shopDomains = shopSources(options.shop)\n const scriptSrc = uniqueSources([\n ...normalizeSources(options.scriptSrc ?? ['self']),\n `'nonce-${nonce}'`,\n ])\n const connectSrc = uniqueSources([\n 'self',\n ...shopDomains,\n ...normalizeSources(options.connectSrc),\n ])\n const imgSrc = uniqueSources([\n 'self',\n 'data:',\n 'https:',\n ...shopDomains,\n ...normalizeSources(options.imgSrc),\n ])\n const styleSrc = uniqueSources(['self', 'unsafe-inline', ...normalizeSources(options.styleSrc)])\n const directives = [\n ['base-uri', [\"'self'\"]],\n ['default-src', [\"'self'\"]],\n ['connect-src', connectSrc],\n ['img-src', imgSrc],\n ['script-src', scriptSrc],\n ['style-src', styleSrc],\n ]\n return {\n nonce,\n header: directives\n .map(([name, values]) => `${name} ${(values as readonly string[]).join(' ')}`)\n .join('; '),\n NonceProvider: createNonceProvider(nonce),\n }\n}\n\nfunction createNonce(): string {\n const bytes = new Uint8Array(18)\n const runtimeCrypto = (globalThis as typeof globalThis & { crypto?: Crypto }).crypto\n if (runtimeCrypto?.getRandomValues !== undefined) {\n runtimeCrypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < bytes.length; i += 1) {\n bytes[i] = Math.floor(Math.random() * 256)\n }\n }\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nfunction shopSources(shop: ContentSecurityPolicyShop | undefined): readonly string[] {\n if (shop === undefined) return []\n return [shop.storeDomain, shop.checkoutDomain]\n .filter((domain): domain is string => domain !== undefined && domain.trim() !== '')\n .map((domain) => {\n const trimmed = domain.trim()\n return /^https?:\\/\\//i.test(trimmed) ? new URL(trimmed).origin : `https://${trimmed}`\n })\n}\n\nfunction normalizeSources(sources: readonly string[] | undefined): readonly string[] {\n return (sources ?? []).map((source) => {\n const trimmed = source.trim()\n return QUOTED_TOKENS.has(trimmed) ? `'${trimmed}'` : trimmed\n })\n}\n\nfunction uniqueSources(sources: readonly string[]): readonly string[] {\n return Array.from(new Set(sources.filter((source) => source.length > 0)))\n}\n","import { buildLocalizationCookie } from './cookie'\nimport { localizePath } from './routing'\n\n/** Same-origin path only: must start with a single '/', not '//' or '/\\'. */\nfunction safeReturnTo(raw: string | null): { path: string; safe: boolean } {\n if (raw === null || raw === '') return { path: '/', safe: true }\n return /^\\/(?![/\\\\])/.test(raw) ? { path: raw, safe: true } : { path: '/', safe: false }\n}\n\nexport async function handleLocalizationPost(request: Request): Promise<Response> {\n const form = await request.formData()\n const country = (form.get('country_code') ?? '').toString().trim().toUpperCase() || null\n const locale = (form.get('locale_code') ?? '').toString().trim() || null\n const primaryLocale = (form.get('primary_locale') ?? '').toString().trim() || null\n const returnTo = safeReturnTo((form.get('return_to') ?? '').toString())\n const location =\n returnTo.safe && primaryLocale !== null\n ? localizePath(returnTo.path, locale, { primaryLocale })\n : returnTo.path\n return new Response(null, {\n status: 302,\n headers: { location, 'set-cookie': buildLocalizationCookie({ country, locale }) },\n })\n}\n","/**\n * Coarse visitor geo attached to pixel events — structurally the SDK's `context.geo` (a `Geo` value is\n * assignable here). Declared locally so the analytics surface (and its DOM/React preset) need not pull\n * in the geo crypto module.\n */\nexport interface AnalyticsGeo {\n readonly country: string | null\n readonly city: string | null\n readonly colo: string | null\n readonly botScore: number | null\n readonly clientIp: string | null\n}\n\n/** The standard storefront analytics events (Hydrogen-shaped names). */\nexport const ANALYTICS_EVENTS = {\n pageViewed: 'page_viewed',\n productViewed: 'product_viewed',\n collectionViewed: 'collection_viewed',\n cartViewed: 'cart_viewed',\n searchViewed: 'search_viewed',\n productAddedToCart: 'product_added_to_cart',\n} as const\n\nexport type AnalyticsEventName = (typeof ANALYTICS_EVENTS)[keyof typeof ANALYTICS_EVENTS]\n\n/** Ambient context the provider attaches to every event before it reaches the pixel. */\nexport interface AnalyticsContext {\n readonly shopId?: string\n readonly url?: string\n readonly geo?: AnalyticsGeo\n}\n\nexport interface PageViewedPayload {\n readonly title?: string\n}\nexport interface ProductViewedPayload {\n readonly productId: string\n readonly handle?: string\n}\nexport interface CollectionViewedPayload {\n readonly collectionId: string\n readonly handle?: string\n}\nexport interface CartViewedPayload {\n readonly cartId?: string\n}\nexport interface SearchViewedPayload {\n readonly query: string\n readonly resultCount?: number\n}\nexport interface ProductAddedToCartPayload {\n readonly productId: string\n readonly variantId: string\n readonly quantity: number\n}\n\n/** Event name → payload (the typed pub/sub surface). */\nexport interface AnalyticsEventMap {\n page_viewed: PageViewedPayload\n product_viewed: ProductViewedPayload\n collection_viewed: CollectionViewedPayload\n cart_viewed: CartViewedPayload\n search_viewed: SearchViewedPayload\n product_added_to_cart: ProductAddedToCartPayload\n}\n\n/** A pixel-bound event: the name, its payload, the ambient context, a timestamp, and consent state. */\nexport interface PixelEvent<E extends AnalyticsEventName = AnalyticsEventName> {\n readonly event: E\n readonly payload: AnalyticsEventMap[E]\n readonly context: AnalyticsContext\n readonly timestamp: string\n /** Whether the analytics-consent bucket was granted when this event was recorded. */\n readonly consent: boolean\n}\n","export interface ShopAnalytics {\n readonly acceptedLanguage?: string\n readonly currency?: string\n readonly shopId?: string\n readonly storefrontId?: string\n}\n\nexport interface GetShopAnalyticsOptions {\n readonly publicStorefrontId?: string\n readonly storefront?: {\n readonly i18n?: {\n readonly country?: string | null\n readonly currency?: string | null\n readonly language?: string | null\n readonly pathPrefix?: string | null\n } | null\n } | null\n}\n\nexport function getShopAnalytics(options: GetShopAnalyticsOptions): ShopAnalytics {\n const language = options.storefront?.i18n?.language ?? null\n const country = options.storefront?.i18n?.country ?? null\n const currency = options.storefront?.i18n?.currency ?? null\n const acceptedLanguage =\n language != null && country != null ? `${language}-${country}` : (language ?? country)\n\n return {\n ...(acceptedLanguage != null ? { acceptedLanguage } : {}),\n ...(currency != null ? { currency } : {}),\n ...(options.publicStorefrontId != null ? { shopId: options.publicStorefrontId } : {}),\n ...(options.publicStorefrontId != null ? { storefrontId: options.publicStorefrontId } : {}),\n }\n}\n","import { CONSENT_BUCKETS, type ConsentBucket, type ConsentState } from './consent'\n\n/**\n * Encode/decode consent into the `cart.checkoutUrl` handoff (query params), mirroring Shopify's\n * server-set-consent direction (design §Checkout handoff). The handoff target is the Gateway-owned\n * same-origin `/checkout/*` path — `appendConsentToCheckoutUrl` preserves a relative URL as relative\n * so it never points at a separate subdomain.\n */\nconst PARAM_PREFIX = 'consent_'\nconst RELATIVE_BASE = 'https://kotao.invalid'\n\nexport function encodeConsent(state: ConsentState): URLSearchParams {\n const params = new URLSearchParams()\n for (const bucket of CONSENT_BUCKETS)\n params.set(`${PARAM_PREFIX}${bucket}`, state[bucket] ? '1' : '0')\n return params\n}\n\nexport function decodeConsent(params: URLSearchParams): ConsentState {\n const read = (bucket: ConsentBucket): boolean => params.get(`${PARAM_PREFIX}${bucket}`) === '1'\n return {\n analytics: read('analytics'),\n marketing: read('marketing'),\n preferences: read('preferences'),\n }\n}\n\nexport function appendConsentToCheckoutUrl(checkoutUrl: string, state: ConsentState): string {\n // The checkout handoff is the same-origin `/checkout/*` path (cart.checkoutUrl is relative). Reject\n // absolute or protocol-relative URLs so consent params never ride to another origin.\n if (!/^\\/(?!\\/)/.test(checkoutUrl)) {\n throw new Error(`checkoutUrl must be a same-origin path starting with '/'; got: ${checkoutUrl}`)\n }\n const url = new URL(checkoutUrl, RELATIVE_BASE)\n for (const [key, value] of encodeConsent(state)) url.searchParams.set(key, value)\n return `${url.pathname}${url.search}${url.hash}`\n}\n"]}
1
+ {"version":3,"sources":["../src/cart/useOptimisticCart.ts","../src/content-security-policy.ts","../src/localization/handler.ts","../src/analytics/events.ts","../src/analytics/shop.ts","../src/analytics/consent-encoding.ts","../src/hosted-surface/branding.ts","../src/hosted-surface/localization.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { CART_FORM_ACTIONS } from './actions'\nimport type { CartDispatchAction } from './createCartHandler'\nimport type { Cart, CartLine } from './types'\n\nconst recalculate = (cart: Cart, lines: readonly CartLine[]): Cart => ({\n ...cart,\n lines,\n totalQuantity: lines.reduce((sum, line) => sum + line.quantity, 0),\n})\n\nexport function applyOptimisticCartAction(cart: Cart, action: CartDispatchAction): Cart {\n switch (action.action) {\n case CART_FORM_ACTIONS.LinesAdd: {\n const inputLines = (action.inputs.lines ?? []) as Array<{\n merchandiseId: string\n quantity?: number | null\n }>\n const additions = inputLines.map<CartLine>((line) => ({\n id: `optimistic:${line.merchandiseId}`,\n quantity: line.quantity ?? 1,\n merchandise: { id: line.merchandiseId },\n attributes: [],\n }))\n return recalculate(cart, [...cart.lines, ...additions])\n }\n case CART_FORM_ACTIONS.LinesUpdate: {\n const updates = new Map(\n ((action.inputs.lines ?? []) as Array<{ id: string; quantity?: number | null }>).map(\n (line) => [line.id, line],\n ),\n )\n const lines = cart.lines\n .map((line) => {\n const update = updates.get(line.id)\n if (!update) return line\n if (update.quantity === 0) return null\n return {\n ...line,\n quantity: update.quantity ?? line.quantity,\n }\n })\n .filter((line): line is CartLine => line !== null)\n return recalculate(cart, lines)\n }\n case CART_FORM_ACTIONS.LinesRemove: {\n const remove = new Set((action.inputs.lineIds ?? []) as string[])\n return recalculate(\n cart,\n cart.lines.filter((line) => !remove.has(line.id)),\n )\n }\n default:\n return cart\n }\n}\n\n/**\n * Pure optimistic helper for React integrations. A React wrapper can call this from `useOptimistic`;\n * keeping the reducer pure lets non-React tests exercise the exact overlay behavior.\n */\nexport function useOptimisticCart(cart: Cart, action: CartDispatchAction | null): Cart {\n return action ? applyOptimisticCartAction(cart, action) : cart\n}\n","import { createNonceProvider, type BoundNonceProvider } from './react/nonce'\n\nexport interface ContentSecurityPolicyShop {\n readonly checkoutDomain?: string\n readonly storeDomain?: string\n}\n\nexport interface CreateContentSecurityPolicyOptions {\n readonly shop?: ContentSecurityPolicyShop\n readonly scriptSrc?: readonly string[]\n readonly connectSrc?: readonly string[]\n readonly imgSrc?: readonly string[]\n readonly styleSrc?: readonly string[]\n}\n\nexport interface ContentSecurityPolicyResult {\n readonly nonce: string\n readonly header: string\n readonly NonceProvider: BoundNonceProvider\n}\n\nconst QUOTED_TOKENS = new Set([\n 'self',\n 'none',\n 'unsafe-eval',\n 'unsafe-hashes',\n 'unsafe-inline',\n 'strict-dynamic',\n 'wasm-unsafe-eval',\n])\n\nexport function createContentSecurityPolicy(\n options: CreateContentSecurityPolicyOptions = {},\n): ContentSecurityPolicyResult {\n const nonce = createNonce()\n const shopDomains = shopSources(options.shop)\n const scriptSrc = uniqueSources([\n ...normalizeSources(options.scriptSrc ?? ['self']),\n `'nonce-${nonce}'`,\n ])\n const connectSrc = uniqueSources([\n 'self',\n ...shopDomains,\n ...normalizeSources(options.connectSrc),\n ])\n const imgSrc = uniqueSources([\n 'self',\n 'data:',\n 'https:',\n ...shopDomains,\n ...normalizeSources(options.imgSrc),\n ])\n const styleSrc = uniqueSources(['self', 'unsafe-inline', ...normalizeSources(options.styleSrc)])\n const directives = [\n ['base-uri', [\"'self'\"]],\n ['default-src', [\"'self'\"]],\n ['connect-src', connectSrc],\n ['img-src', imgSrc],\n ['script-src', scriptSrc],\n ['style-src', styleSrc],\n ]\n return {\n nonce,\n header: directives\n .map(([name, values]) => `${name} ${(values as readonly string[]).join(' ')}`)\n .join('; '),\n NonceProvider: createNonceProvider(nonce),\n }\n}\n\nfunction createNonce(): string {\n const bytes = new Uint8Array(18)\n const runtimeCrypto = (globalThis as typeof globalThis & { crypto?: Crypto }).crypto\n if (runtimeCrypto?.getRandomValues !== undefined) {\n runtimeCrypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < bytes.length; i += 1) {\n bytes[i] = Math.floor(Math.random() * 256)\n }\n }\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n\nfunction shopSources(shop: ContentSecurityPolicyShop | undefined): readonly string[] {\n if (shop === undefined) return []\n return [shop.storeDomain, shop.checkoutDomain]\n .filter((domain): domain is string => domain !== undefined && domain.trim() !== '')\n .map((domain) => {\n const trimmed = domain.trim()\n return /^https?:\\/\\//i.test(trimmed) ? new URL(trimmed).origin : `https://${trimmed}`\n })\n}\n\nfunction normalizeSources(sources: readonly string[] | undefined): readonly string[] {\n return (sources ?? []).map((source) => {\n const trimmed = source.trim()\n return QUOTED_TOKENS.has(trimmed) ? `'${trimmed}'` : trimmed\n })\n}\n\nfunction uniqueSources(sources: readonly string[]): readonly string[] {\n return Array.from(new Set(sources.filter((source) => source.length > 0)))\n}\n","import { buildLocalizationCookie } from './cookie'\nimport { localizePath } from './routing'\n\n/** Same-origin path only: must start with a single '/', not '//' or '/\\'. */\nfunction safeReturnTo(raw: string | null): { path: string; safe: boolean } {\n if (raw === null || raw === '') return { path: '/', safe: true }\n return /^\\/(?![/\\\\])/.test(raw) ? { path: raw, safe: true } : { path: '/', safe: false }\n}\n\nexport async function handleLocalizationPost(request: Request): Promise<Response> {\n const form = await request.formData()\n const country = (form.get('country_code') ?? '').toString().trim().toUpperCase() || null\n const locale = (form.get('locale_code') ?? '').toString().trim() || null\n const primaryLocale = (form.get('primary_locale') ?? '').toString().trim() || null\n const returnTo = safeReturnTo((form.get('return_to') ?? '').toString())\n const location =\n returnTo.safe && primaryLocale !== null\n ? localizePath(returnTo.path, locale, { primaryLocale })\n : returnTo.path\n return new Response(null, {\n status: 302,\n headers: { location, 'set-cookie': buildLocalizationCookie({ country, locale }) },\n })\n}\n","/**\n * Coarse visitor geo attached to pixel events — structurally the SDK's `context.geo` (a `Geo` value is\n * assignable here). Declared locally so the analytics surface (and its DOM/React preset) need not pull\n * in the geo crypto module.\n */\nexport interface AnalyticsGeo {\n readonly country: string | null\n readonly city: string | null\n readonly colo: string | null\n readonly botScore: number | null\n readonly clientIp: string | null\n}\n\n/** The standard storefront analytics events (Hydrogen-shaped names). */\nexport const ANALYTICS_EVENTS = {\n pageViewed: 'page_viewed',\n productViewed: 'product_viewed',\n collectionViewed: 'collection_viewed',\n cartViewed: 'cart_viewed',\n searchViewed: 'search_viewed',\n productAddedToCart: 'product_added_to_cart',\n} as const\n\nexport type AnalyticsEventName = (typeof ANALYTICS_EVENTS)[keyof typeof ANALYTICS_EVENTS]\n\n/** Ambient context the provider attaches to every event before it reaches the pixel. */\nexport interface AnalyticsContext {\n readonly shopId?: string\n readonly url?: string\n readonly geo?: AnalyticsGeo\n}\n\nexport interface PageViewedPayload {\n readonly title?: string\n}\nexport interface ProductViewedPayload {\n readonly productId: string\n readonly handle?: string\n}\nexport interface CollectionViewedPayload {\n readonly collectionId: string\n readonly handle?: string\n}\nexport interface CartViewedPayload {\n readonly cartId?: string\n}\nexport interface SearchViewedPayload {\n readonly query: string\n readonly resultCount?: number\n}\nexport interface ProductAddedToCartPayload {\n readonly productId: string\n readonly variantId: string\n readonly quantity: number\n}\n\n/** Event name → payload (the typed pub/sub surface). */\nexport interface AnalyticsEventMap {\n page_viewed: PageViewedPayload\n product_viewed: ProductViewedPayload\n collection_viewed: CollectionViewedPayload\n cart_viewed: CartViewedPayload\n search_viewed: SearchViewedPayload\n product_added_to_cart: ProductAddedToCartPayload\n}\n\n/** A pixel-bound event: the name, its payload, the ambient context, a timestamp, and consent state. */\nexport interface PixelEvent<E extends AnalyticsEventName = AnalyticsEventName> {\n readonly event: E\n readonly payload: AnalyticsEventMap[E]\n readonly context: AnalyticsContext\n readonly timestamp: string\n /** Whether the analytics-consent bucket was granted when this event was recorded. */\n readonly consent: boolean\n}\n","export interface ShopAnalytics {\n readonly acceptedLanguage?: string\n readonly currency?: string\n readonly shopId?: string\n readonly storefrontId?: string\n}\n\nexport interface GetShopAnalyticsOptions {\n readonly publicStorefrontId?: string\n readonly storefront?: {\n readonly i18n?: {\n readonly country?: string | null\n readonly currency?: string | null\n readonly language?: string | null\n readonly pathPrefix?: string | null\n } | null\n } | null\n}\n\nexport function getShopAnalytics(options: GetShopAnalyticsOptions): ShopAnalytics {\n const language = options.storefront?.i18n?.language ?? null\n const country = options.storefront?.i18n?.country ?? null\n const currency = options.storefront?.i18n?.currency ?? null\n const acceptedLanguage =\n language != null && country != null ? `${language}-${country}` : (language ?? country)\n\n return {\n ...(acceptedLanguage != null ? { acceptedLanguage } : {}),\n ...(currency != null ? { currency } : {}),\n ...(options.publicStorefrontId != null ? { shopId: options.publicStorefrontId } : {}),\n ...(options.publicStorefrontId != null ? { storefrontId: options.publicStorefrontId } : {}),\n }\n}\n","import { CONSENT_BUCKETS, type ConsentBucket, type ConsentState } from './consent'\n\n/**\n * Encode/decode consent into the `cart.checkoutUrl` handoff (query params), mirroring Shopify's\n * server-set-consent direction (design §Checkout handoff). The handoff target is the Gateway-owned\n * same-origin `/checkout/*` path — `appendConsentToCheckoutUrl` preserves a relative URL as relative\n * so it never points at a separate subdomain.\n */\nconst PARAM_PREFIX = 'consent_'\nconst RELATIVE_BASE = 'https://kotao.invalid'\n\nexport function encodeConsent(state: ConsentState): URLSearchParams {\n const params = new URLSearchParams()\n for (const bucket of CONSENT_BUCKETS)\n params.set(`${PARAM_PREFIX}${bucket}`, state[bucket] ? '1' : '0')\n return params\n}\n\nexport function decodeConsent(params: URLSearchParams): ConsentState {\n const read = (bucket: ConsentBucket): boolean => params.get(`${PARAM_PREFIX}${bucket}`) === '1'\n return {\n analytics: read('analytics'),\n marketing: read('marketing'),\n preferences: read('preferences'),\n }\n}\n\nexport function appendConsentToCheckoutUrl(checkoutUrl: string, state: ConsentState): string {\n // The checkout handoff is the same-origin `/checkout/*` path (cart.checkoutUrl is relative). Reject\n // absolute or protocol-relative URLs so consent params never ride to another origin.\n if (!/^\\/(?!\\/)/.test(checkoutUrl)) {\n throw new Error(`checkoutUrl must be a same-origin path starting with '/'; got: ${checkoutUrl}`)\n }\n const url = new URL(checkoutUrl, RELATIVE_BASE)\n for (const [key, value] of encodeConsent(state)) url.searchParams.set(key, value)\n return `${url.pathname}${url.search}${url.hash}`\n}\n","import {\n CHECKOUT_DESIGN_TOKEN_INPUTS,\n extractCheckoutDesignTokens,\n type CheckoutDesignTokens,\n} from '../checkout/design-tokens'\nimport type { ResolvedSettings } from '../settings/types'\n\nconst CHECKOUT_TOKEN_DEFAULTS: Readonly<Record<string, string>> = Object.fromEntries(\n CHECKOUT_DESIGN_TOKEN_INPUTS.flatMap((input) =>\n 'defaultValue' in input && typeof input.defaultValue === 'string' && input.defaultValue !== ''\n ? [[input.name, input.defaultValue]]\n : [],\n ),\n)\n\n/** Resolve the token contract shared by trusted checkout and customer-account surfaces. */\nexport function resolveHostedBranding(global: ResolvedSettings): CheckoutDesignTokens {\n return extractCheckoutDesignTokens({ global: { ...CHECKOUT_TOKEN_DEFAULTS, ...global } })\n}\n\n/** Escape merchant-controlled text for an HTML text node or double-quoted attribute. */\nexport function escapeHostedHtml(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n}\n\n/**\n * Strip characters that can terminate an inline CSS declaration, block, quote, or style element.\n * Trusted renderers must apply this at the CSS-value sink; the resolved token values themselves\n * remain byte-for-byte compatible with checkout's existing contract.\n */\nexport function sanitizeHostedCssValue(value: string): string {\n return value\n .replace(/[<>\"'`;{}\\\\]/g, '')\n .replace(/[\\r\\n\\t]+/g, ' ')\n .trim()\n}\n","import { readLocalizationCookie } from '../localization/cookie'\n\nexport interface HostedLocaleInput {\n readonly configuredLocales: readonly string[]\n readonly localizationCookie: string | null\n readonly customerLocale: string | null\n readonly primaryLocale: string\n}\n\n/**\n * Resolve display language within the verified shop's configured locale allowlist. Payment\n * jurisdiction and legal-copy decisions deliberately stay outside this display-only resolver.\n */\nexport function resolveHostedLocale(input: HostedLocaleInput): string {\n const configured = input.configuredLocales.map((locale) => locale.trim()).filter(Boolean)\n if (configured.length === 0) throw new Error('hosted surfaces require a configured locale')\n\n const configuredByKey = new Map(configured.map((locale) => [localeKey(locale), locale] as const))\n const cookieLocale = safelyReadCookieLocale(input.localizationCookie)\n\n for (const candidate of [cookieLocale, input.customerLocale, input.primaryLocale]) {\n if (candidate === null || candidate.trim() === '') continue\n const match = configuredByKey.get(localeKey(candidate))\n if (match !== undefined) return match\n }\n\n return configured[0]!\n}\n\nfunction localeKey(locale: string): string {\n return locale.trim().replace(/_/g, '-').toLowerCase()\n}\n\nfunction safelyReadCookieLocale(cookieHeader: string | null): string | null {\n if (cookieHeader === null) return null\n if (!cookieHeader.includes('=')) return cookieHeader.trim() || null\n try {\n return readLocalizationCookie(cookieHeader).locale\n } catch {\n return null\n }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ interface OfferTokenLocation {
2
+ readonly href: string;
3
+ }
4
+ interface OfferTokenHistory {
5
+ readonly state: unknown;
6
+ replaceState(data: unknown, unused: string, url?: string | URL | null): void;
7
+ }
8
+ /** Lossy marker for replay detection. It never retains or reproduces the capability-bearing href. */
9
+ declare function offerTokenHrefMarker(href: string): string;
10
+ /**
11
+ * Consumes an offer capability from the fragment and removes capability-bearing URL state before
12
+ * the caller can issue a request. Query-string capabilities are sanitized but never accepted.
13
+ */
14
+ declare function consumeOfferTokenFragment(location: OfferTokenLocation, history: OfferTokenHistory): string | null;
15
+
16
+ export { type OfferTokenLocation as O, type OfferTokenHistory as a, consumeOfferTokenFragment as c, offerTokenHrefMarker as o };
@@ -74,4 +74,4 @@ declare function getPaginationInfo<T>(connection: Connection<T>, currentUrl: URL
74
74
  namespace?: string;
75
75
  }): PaginationInfo<T>;
76
76
 
77
- export { type Connection as C, type FlattenableConnection as F, type PageInfo as P, type ConnectionEdge as a, type PaginationInfo as b, type PaginationOptions as c, type PaginationVariables as d, getPaginationVariables as e, flattenConnection as f, getPaginationInfo as g };
77
+ export { type Connection as C, type FlattenableConnection as F, type PaginationInfo as P, type ConnectionEdge as a, type PageInfo as b, type PaginationOptions as c, type PaginationVariables as d, getPaginationVariables as e, flattenConnection as f, getPaginationInfo as g };
package/dist/product.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FlattenableConnection } from './pagination-CPgH3fAa.js';
1
+ import { F as FlattenableConnection } from './pagination-DCrQk02Q.js';
2
2
  import { ProductOptionValueSwatch, Image } from './storefront-api-types.js';
3
3
 
4
4
  /**
@@ -1,9 +1,13 @@
1
- import { K as KotaoEnv, a as KotaoContext } from './routing-BxRlep_-.js';
2
- export { b as KotaoSession, s as stripLocalePrefixFromRequest } from './routing-BxRlep_-.js';
3
- import { H as HydrogenSession } from './types-Df3bGbKU.js';
4
- import './fetch-B6TIc6lI.js';
1
+ import { K as KotaoEnv, S as StorefrontExecutionContext, a as KotaoContext } from './routing-sEonP93J.js';
2
+ export { b as KotaoSession, s as stripLocalePrefixFromRequest } from './routing-sEonP93J.js';
3
+ import { H as HydrogenSession } from './types-bcbQzx87.js';
4
+ import { b as StorefrontCacheInput } from './client-D51WdvYR.js';
5
+ import './fetch-M3Y-fQrW.js';
5
6
  import '@kotao/storefront-contracts/theme';
6
- import './client-DiPdlvPu.js';
7
+ import './createCartHandler-C4RrPwSG.js';
8
+ import './client-bsiNPHBi.js';
9
+ import './types-CSNXbGFW.js';
10
+ import './http-types-CGh8WGHB.js';
7
11
 
8
12
  type JsonInit = ResponseInit | number;
9
13
  interface JsonResponse<T> {
@@ -18,7 +22,7 @@ declare function json<T>(data: T, init?: JsonInit): JsonResponse<T>;
18
22
  declare function defer<T>(data: T, _init?: JsonInit): Promise<AwaitedDeferred<T>>;
19
23
 
20
24
  interface KotaoLoadContextDeps {
21
- readonly openCache?: (name: string) => Promise<Cache>;
25
+ readonly openCache?: (name: string) => Promise<StorefrontCacheInput>;
22
26
  readonly session?: HydrogenSession;
23
27
  }
24
28
  /**
@@ -26,6 +30,6 @@ interface KotaoLoadContextDeps {
26
30
  * entry's `getLoadContext`. Isolated here so the SDK core stays framework-agnostic (a TanStack
27
31
  * Start binding can be added alongside without touching the core).
28
32
  */
29
- declare const getKotaoLoadContext: (request: Request, env: KotaoEnv, executionCtx: ExecutionContext, deps?: KotaoLoadContextDeps) => Promise<KotaoContext>;
33
+ declare const getKotaoLoadContext: (request: Request, env: KotaoEnv, executionCtx: StorefrontExecutionContext, deps?: KotaoLoadContextDeps) => Promise<KotaoContext>;
30
34
 
31
35
  export { KotaoContext, KotaoEnv, defer, getKotaoLoadContext, json };
@@ -1,7 +1,8 @@
1
- import { createKotaoContext } from './chunk-7XYWHWT4.js';
2
- export { stripLocalePrefixFromRequest } from './chunk-7XYWHWT4.js';
3
- import './chunk-M7BPQ54D.js';
1
+ import { createKotaoContext } from './chunk-4TEFGD42.js';
2
+ export { stripLocalePrefixFromRequest } from './chunk-4TEFGD42.js';
4
3
  import './chunk-OGWYTYYS.js';
4
+ import './chunk-M7BPQ54D.js';
5
+ import './chunk-7MTCGXIG.js';
5
6
 
6
7
  // src/react-router/compat.ts
7
8
  function normalizeJsonInit(init) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react-router/compat.ts","../src/react-router/binding.ts"],"names":[],"mappings":";;;;;;AAUA,SAAS,kBAAkB,IAAA,EAA2C;AACpE,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,GAAW,EAAE,MAAA,EAAQ,MAAK,GAAI,IAAA;AACvD;AAEA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,YAAY,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAEA,SAAS,cAAc,KAAA,EAA+C;AACpE,EAAA,OAAO,QAAA,CAAS,KAAK,CAAA,IAAK,OAAO,MAAM,IAAA,KAAS,UAAA;AAClD;AAEO,SAAS,IAAA,CAAQ,MAAS,IAAA,EAAkC;AACjE,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,iBAAA,CAAkB,IAAI,CAAC,CAAA;AACpD;AAEA,eAAsB,KAAA,CAAS,MAAS,KAAA,EAA+C;AACrF,EAAA,IAAI,SAAS,IAAI,CAAA,IAAK,CAAC,aAAA,CAAc,IAAI,CAAA,EAAG;AAC1C,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,MAC5B,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,CAAE,IAAI,OAAO,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM,CAAC,GAAA,EAAK,MAAM,KAAK,CAAU;AAAA,KAC9E;AACA,IAAA,OAAO,MAAA,CAAO,YAAY,OAAO,CAAA;AAAA,EACnC;AAEA,EAAA,OAAQ,MAAM,IAAA;AAChB;;;ACrBO,IAAM,mBAAA,GAAsB,CACjC,OAAA,EACA,GAAA,EACA,YAAA,EACA,SAC0B,kBAAA,CAAmB,OAAA,EAAS,GAAA,EAAK,YAAA,EAAc,IAAI","file":"react-router.js","sourcesContent":["type JsonInit = ResponseInit | number\nexport interface JsonResponse<T> {\n readonly type: string\n readonly data: T\n readonly init: ResponseInit | null\n}\n\ntype AwaitedDeferred<T> =\n T extends Record<string, unknown> ? { [K in keyof T]: Awaited<T[K]> } : Awaited<T>\n\nfunction normalizeJsonInit(init?: JsonInit): ResponseInit | undefined {\n return typeof init === 'number' ? { status: init } : init\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return isRecord(value) && typeof value.then === 'function'\n}\n\nexport function json<T>(data: T, init?: JsonInit): JsonResponse<T> {\n return Response.json(data, normalizeJsonInit(init)) as unknown as JsonResponse<T>\n}\n\nexport async function defer<T>(data: T, _init?: JsonInit): Promise<AwaitedDeferred<T>> {\n if (isRecord(data) && !isPromiseLike(data)) {\n const entries = await Promise.all(\n Object.entries(data).map(async ([key, value]) => [key, await value] as const),\n )\n return Object.fromEntries(entries) as AwaitedDeferred<T>\n }\n\n return (await data) as AwaitedDeferred<T>\n}\n","import type { HydrogenSession } from '../cart/types'\nimport { createKotaoContext, type KotaoContext, type KotaoEnv } from '../context/context'\nexport { stripLocalePrefixFromRequest } from '../localization/routing'\n\nexport interface KotaoLoadContextDeps {\n readonly openCache?: (name: string) => Promise<Cache>\n readonly session?: HydrogenSession\n}\n\n/**\n * Build the React Router 7 load context for a storefront request. Call from the RR7 server\n * entry's `getLoadContext`. Isolated here so the SDK core stays framework-agnostic (a TanStack\n * Start binding can be added alongside without touching the core).\n */\nexport const getKotaoLoadContext = (\n request: Request,\n env: KotaoEnv,\n executionCtx: ExecutionContext,\n deps?: KotaoLoadContextDeps,\n): Promise<KotaoContext> => createKotaoContext(request, env, executionCtx, deps)\n"]}
1
+ {"version":3,"sources":["../src/react-router/compat.ts","../src/react-router/binding.ts"],"names":[],"mappings":";;;;;;;AAUA,SAAS,kBAAkB,IAAA,EAA2C;AACpE,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,GAAW,EAAE,MAAA,EAAQ,MAAK,GAAI,IAAA;AACvD;AAEA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,KAAA,KAAU,QAAQ,OAAO,KAAA,KAAU,YAAY,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAEA,SAAS,cAAc,KAAA,EAA+C;AACpE,EAAA,OAAO,QAAA,CAAS,KAAK,CAAA,IAAK,OAAO,MAAM,IAAA,KAAS,UAAA;AAClD;AAEO,SAAS,IAAA,CAAQ,MAAS,IAAA,EAAkC;AACjE,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,iBAAA,CAAkB,IAAI,CAAC,CAAA;AACpD;AAEA,eAAsB,KAAA,CAAS,MAAS,KAAA,EAA+C;AACrF,EAAA,IAAI,SAAS,IAAI,CAAA,IAAK,CAAC,aAAA,CAAc,IAAI,CAAA,EAAG;AAC1C,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,MAC5B,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,CAAE,IAAI,OAAO,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM,CAAC,GAAA,EAAK,MAAM,KAAK,CAAU;AAAA,KAC9E;AACA,IAAA,OAAO,MAAA,CAAO,YAAY,OAAO,CAAA;AAAA,EACnC;AAEA,EAAA,OAAQ,MAAM,IAAA;AAChB;;;ACfO,IAAM,mBAAA,GAAsB,CACjC,OAAA,EACA,GAAA,EACA,YAAA,EACA,SAC0B,kBAAA,CAAmB,OAAA,EAAS,GAAA,EAAK,YAAA,EAAc,IAAI","file":"react-router.js","sourcesContent":["type JsonInit = ResponseInit | number\nexport interface JsonResponse<T> {\n readonly type: string\n readonly data: T\n readonly init: ResponseInit | null\n}\n\ntype AwaitedDeferred<T> =\n T extends Record<string, unknown> ? { [K in keyof T]: Awaited<T[K]> } : Awaited<T>\n\nfunction normalizeJsonInit(init?: JsonInit): ResponseInit | undefined {\n return typeof init === 'number' ? { status: init } : init\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return isRecord(value) && typeof value.then === 'function'\n}\n\nexport function json<T>(data: T, init?: JsonInit): JsonResponse<T> {\n return Response.json(data, normalizeJsonInit(init)) as unknown as JsonResponse<T>\n}\n\nexport async function defer<T>(data: T, _init?: JsonInit): Promise<AwaitedDeferred<T>> {\n if (isRecord(data) && !isPromiseLike(data)) {\n const entries = await Promise.all(\n Object.entries(data).map(async ([key, value]) => [key, await value] as const),\n )\n return Object.fromEntries(entries) as AwaitedDeferred<T>\n }\n\n return (await data) as AwaitedDeferred<T>\n}\n","import type { HydrogenSession } from '../cart/types'\nimport type { StorefrontCacheInput } from '../cache/cache'\nimport {\n createKotaoContext,\n type KotaoContext,\n type KotaoEnv,\n type StorefrontExecutionContext,\n} from '../context/context'\nexport { stripLocalePrefixFromRequest } from '../localization/routing'\n\nexport interface KotaoLoadContextDeps {\n readonly openCache?: (name: string) => Promise<StorefrontCacheInput>\n readonly session?: HydrogenSession\n}\n\n/**\n * Build the React Router 7 load context for a storefront request. Call from the RR7 server\n * entry's `getLoadContext`. Isolated here so the SDK core stays framework-agnostic (a TanStack\n * Start binding can be added alongside without touching the core).\n */\nexport const getKotaoLoadContext = (\n request: Request,\n env: KotaoEnv,\n executionCtx: StorefrontExecutionContext,\n deps?: KotaoLoadContextDeps,\n): Promise<KotaoContext> => createKotaoContext(request, env, executionCtx, deps)\n"]}