@fayz-ai/storefront 0.84.2 → 0.84.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 (53) hide show
  1. package/dist/CheckoutPage-4MFKLBEI.js +12 -0
  2. package/dist/{CheckoutPage-DDY4WLFJ.js.map → CheckoutPage-4MFKLBEI.js.map} +1 -1
  3. package/dist/MyPurchasesPage-F25MIFXT.js +11 -0
  4. package/dist/{MyPurchasesPage-IHCB5QRR.js.map → MyPurchasesPage-F25MIFXT.js.map} +1 -1
  5. package/dist/OrderConfirmationPage-SOQDD767.js +10 -0
  6. package/dist/{OrderConfirmationPage-SAKAGOCC.js.map → OrderConfirmationPage-SOQDD767.js.map} +1 -1
  7. package/dist/{chunk-6NUBVJJY.js → chunk-BR3XHNVM.js} +5 -5
  8. package/dist/{chunk-6NUBVJJY.js.map → chunk-BR3XHNVM.js.map} +1 -1
  9. package/dist/{chunk-K27LYMSF.js → chunk-C4XATNI2.js} +3 -3
  10. package/dist/{chunk-K27LYMSF.js.map → chunk-C4XATNI2.js.map} +1 -1
  11. package/dist/{chunk-45R7CIEA.js → chunk-CE4U65TZ.js} +4 -4
  12. package/dist/{chunk-45R7CIEA.js.map → chunk-CE4U65TZ.js.map} +1 -1
  13. package/dist/{chunk-PATS4DIF.js → chunk-EFHQ5MAJ.js} +57 -17
  14. package/dist/chunk-EFHQ5MAJ.js.map +1 -0
  15. package/dist/{chunk-JLCF7CPP.js → chunk-ELW7QWDJ.js} +13 -12
  16. package/dist/chunk-ELW7QWDJ.js.map +1 -0
  17. package/dist/{chunk-GQ3TCJVX.js → chunk-IUP5SDTX.js} +5 -5
  18. package/dist/{chunk-GQ3TCJVX.js.map → chunk-IUP5SDTX.js.map} +1 -1
  19. package/dist/{chunk-WPWNYBNG.js → chunk-NS6UPIJ3.js} +3 -3
  20. package/dist/{chunk-WPWNYBNG.js.map → chunk-NS6UPIJ3.js.map} +1 -1
  21. package/dist/{chunk-MFAU3AWK.js → chunk-OOQRYH3N.js} +6 -6
  22. package/dist/{chunk-MFAU3AWK.js.map → chunk-OOQRYH3N.js.map} +1 -1
  23. package/dist/{chunk-GVZ2SAOI.js → chunk-PSDR5TZD.js} +3 -2
  24. package/dist/chunk-PSDR5TZD.js.map +1 -0
  25. package/dist/{chunk-D5C5U2SG.js → chunk-RJUEUMR6.js} +4 -4
  26. package/dist/{chunk-D5C5U2SG.js.map → chunk-RJUEUMR6.js.map} +1 -1
  27. package/dist/{chunk-BKO2AQ3Q.js → chunk-SLJ4BRXD.js} +3 -3
  28. package/dist/{chunk-BKO2AQ3Q.js.map → chunk-SLJ4BRXD.js.map} +1 -1
  29. package/dist/{chunk-DRMDBXMT.js → chunk-YCAWAON6.js} +7 -7
  30. package/dist/{chunk-DRMDBXMT.js.map → chunk-YCAWAON6.js.map} +1 -1
  31. package/dist/{chunk-OHWX6BEY.js → chunk-YDZU2SZL.js} +4 -4
  32. package/dist/{chunk-OHWX6BEY.js.map → chunk-YDZU2SZL.js.map} +1 -1
  33. package/dist/{chunk-CV6RYJIC.js → chunk-Z5JT7T4I.js} +8 -8
  34. package/dist/{chunk-CV6RYJIC.js.map → chunk-Z5JT7T4I.js.map} +1 -1
  35. package/dist/components/delivery/StoreCover.d.ts.map +1 -1
  36. package/dist/data/auth.d.ts +7 -0
  37. package/dist/data/auth.d.ts.map +1 -1
  38. package/dist/document/config.d.ts +8 -0
  39. package/dist/document/config.d.ts.map +1 -1
  40. package/dist/host.js +4 -4
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +22 -22
  44. package/dist/index.js.map +1 -1
  45. package/dist/render.js +9 -9
  46. package/dist/tanstack.js +8 -8
  47. package/package.json +3 -3
  48. package/dist/CheckoutPage-DDY4WLFJ.js +0 -12
  49. package/dist/MyPurchasesPage-IHCB5QRR.js +0 -11
  50. package/dist/OrderConfirmationPage-SAKAGOCC.js +0 -10
  51. package/dist/chunk-GVZ2SAOI.js.map +0 -1
  52. package/dist/chunk-JLCF7CPP.js.map +0 -1
  53. package/dist/chunk-PATS4DIF.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { roundCents } from './chunk-PATS4DIF.js';
1
+ import { roundCents } from './chunk-EFHQ5MAJ.js';
2
2
  import { create } from 'zustand';
3
3
  import { persist } from 'zustand/middleware';
4
4
  import { normalizePostalCode, getCountrySchema, lookupPostalCode } from '@fayz-ai/core';
@@ -431,5 +431,5 @@ var selectShipping = (s, cfg) => {
431
431
  var selectTotal = (s, cfg) => roundCents(selectSubtotal(s) - selectDiscountTotal(s) + selectShipping(s, cfg));
432
432
 
433
433
  export { formatProductOptionSelection, getProductOptionGroups, marketForCountry, marketUnitPrice, normalizeProductOptionSelection, productOptionSelectionKey, resetProductOptionsDeprecationWarnings, resolveOptionRate, resolveVariantForSelection, selectCount, selectDiscountTotal, selectRequiresShipping, selectShipping, selectSubtotal, selectTotal, selectionPrice, useCartStore, useDeliveryStore, useMarketStore, withMarketPrice };
434
- //# sourceMappingURL=chunk-K27LYMSF.js.map
435
- //# sourceMappingURL=chunk-K27LYMSF.js.map
434
+ //# sourceMappingURL=chunk-C4XATNI2.js.map
435
+ //# sourceMappingURL=chunk-C4XATNI2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stores/market.store.ts","../src/stores/delivery.store.ts","../src/data/product-options.ts","../src/stores/cart.store.ts"],"names":["create","code","address","persist"],"mappings":"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","file":"chunk-K27LYMSF.js","sourcesContent":["import { create } from 'zustand'\nimport type { MarketPrice, Product, ShopMarket } from '@fayz-ai/shop/types'\n\n// The store's markets (0116) and the active one's price list.\n//\n// Module-level on purpose, like the cart: the cart prices a line when it is\n// added, far from any render, and must read the same numbers the page shows.\n// Not persisted: prices are asked for again on every visit.\n\nexport interface MarketState {\n markets: ShopMarket[]\n /** The market the buyer is in, null when the store has none. */\n active: ShopMarket | null\n /** code → `${productId}:${variantId ?? ''}` → price. */\n prices: Record<string, Record<string, number>>\n setMarkets(markets: ShopMarket[]): void\n setActive(market: ShopMarket | null): void\n setPrices(code: string, list: MarketPrice[]): void\n}\n\nexport const useMarketStore = create<MarketState>()((set) => ({\n markets: [],\n active: null,\n prices: {},\n setMarkets: (markets) => set({ markets }),\n setActive: (active) => set({ active }),\n setPrices: (code, list) =>\n set((state) => ({\n prices: {\n ...state.prices,\n [code]: Object.fromEntries(list.map((p) => [`${p.productId}:${p.variantId ?? ''}`, p.price])),\n },\n })),\n}))\n\n/** The market for a country: the one that ships there, else the default. */\nexport function marketForCountry(markets: readonly ShopMarket[], country: string): ShopMarket | null {\n const iso2 = country.toUpperCase()\n return markets.find((m) => m.countries.includes(iso2)) ?? markets.find((m) => m.isDefault) ?? null\n}\n\n/**\n * A unit price in the active market, by shop_market_unit_price's rule: the\n * market's price (variant over product), the catalogue's own in the default\n * market, and `null` — not for sale here — anywhere else.\n */\nexport function marketUnitPrice(\n state: Pick<MarketState, 'active' | 'prices'>,\n productId: string,\n variantId: string | null | undefined,\n fallback: number,\n): number | null {\n const market = state.active\n if (!market) return fallback\n const list = state.prices[market.code]\n const hit = list?.[`${productId}:${variantId ?? ''}`] ?? list?.[`${productId}:`]\n if (hit != null) return hit\n return market.isDefault ? fallback : null\n}\n\n/**\n * The product as the buyer's market sells it: its price, no compare-at (that\n * number is in the default market's money), and out of stock where the market\n * has no price — the page must not offer a sale the checkout will refuse.\n */\nexport function withMarketPrice(product: Product, state: Pick<MarketState, 'active' | 'prices'> = useMarketStore.getState()): Product {\n const market = state.active\n if (!market || market.isDefault) return product\n const price = marketUnitPrice(state, product.id, null, product.price)\n if (price == null) {\n return { ...product, compareAtPrice: null, currency: market.currency, inventoryCount: 0, metadata: { ...product.metadata, unavailableInMarket: market.code } }\n }\n return {\n ...product,\n price,\n compareAtPrice: null,\n currency: market.currency,\n variants: product.variants?.map((v) => ({ ...v, price: marketUnitPrice(state, product.id, v.id, v.price ?? product.price), compareAtPrice: null })),\n }\n}\n","import { create } from 'zustand'\nimport { persist } from 'zustand/middleware'\nimport { getCountrySchema, lookupPostalCode, normalizePostalCode, type PostalAddress } from '@fayz-ai/core'\nimport { getShopProvider } from '@fayz-ai/shop/runtime'\nimport type { FulfillmentType, ShippingQuoteOption } from '@fayz-ai/shop/types'\nimport type { MessageKey } from '../locales/messages'\n\n/**\n * Where the shopper wants it delivered, decided before the cart exists.\n *\n * Two different things live here and they are persisted differently on purpose:\n *\n * the ADDRESS is durable — a CEP maps to the same street for years, and\n * carrying it to checkout is the whole point (the buyer types the number and\n * nothing else);\n *\n * the QUOTE is not persisted at all. It is a price, and a price restored from\n * localStorage is a price the shopper can edit with devtools. It is re-asked\n * on demand, and resolved for the current cart through resolveOptionRate —\n * the same rule shop_shipping_for applies — so it can never go stale. The\n * order is charged from shop_place_order, which recomputes from the same\n * zones and ignores anything the client sends.\n */\n\nexport type DeliveryStatus = 'idle' | 'loading' | 'served' | 'unserved' | 'error'\n\n/**\n * Um endereço que o comprador salvou NESTE navegador.\n *\n * Existe porque o caderno de endereços do `plugin-shop` é de quem tem conta, e\n * num delivery a pessoa tem endereço antes de ter login — é a primeira coisa\n * que ela informa e a última que quer digitar de novo. O CEP resolve rua,\n * bairro e cidade; o que NENHUMA consulta de CEP sabe é o número, o\n * complemento e \"o portão azul ao lado da padaria\". É exatamente isso que se\n * perde a cada visita quando não se guarda nada.\n *\n * Fica no navegador e só nele. Não é conta, não sincroniza entre aparelhos e\n * não vai para o servidor por conta própria — quem grava endereço no pedido é\n * o checkout, com o que a pessoa confirmou na hora.\n */\nexport interface SavedDeliveryAddress {\n id: string\n /** \"Casa\", \"Trabalho\"… Opcional: a maioria salva um só e não nomeia nada. */\n label: string | null\n postalCode: string\n street: string\n number: string\n complement: string | null\n /** O ponto de referência — \"portão azul\", \"prédio ao lado do mercado\". */\n reference: string | null\n district: string\n city: string\n state: string\n /** ISO2. Absent on everything saved before countries: those are Brazilian. */\n country?: string\n createdAt: string\n}\n\n/** How long the quote waits for the postcode lookup before going without it.\n * Short on purpose: the hint improves the answer, it must never delay it. */\nconst HINT_TIMEOUT_MS = 1200\n\nexport interface DeliveryState {\n postalCode: string\n /** ISO2 the postal code belongs to. 'BR' for everything stored before countries. */\n country: string\n address: PostalAddress | null\n options: ShippingQuoteOption[]\n selectedZoneId: string | null\n status: DeliveryStatus\n error: string | null\n /** `error` as a message key, so a screen can say it in the buyer's language. */\n errorKey: MessageKey | null\n errorVars: Record<string, string> | null\n /**\n * The name of the exclusion zone covering this CEP, when the store REFUSES the\n * region (0048). Null when it does not.\n *\n * Carried as a separate field rather than a fourth status because every\n * consumer already treats `unserved` as \"no delivery here\" and that is exactly\n * what this is — the field only lets the message say WHY.\n */\n refusedZone: string | null\n\n /**\n * The name of the rule that says this address is delivered but has to be\n * CONFIRMED first (0081) — the community that shares a postcode with the\n * neighbourhood next door.\n *\n * Not a status either, and for the opposite reason to `refusedZone`: the\n * order goes through and the price is real. Every consumer that shows a price\n * keeps showing it; this only adds a line saying the store will confirm.\n */\n reviewZone: string | null\n\n /** Look the postal code up and quote it. `subtotal` decides free-above\n * thresholds; `country` (ISO2, default 'BR') decides what a code looks like. */\n resolve: (postalCode: string, subtotal: number, country?: string) => Promise<void>\n selectZone: (zoneId: string) => void\n clear: () => void\n\n // -------------------------------------------------------------------------\n // O caderno de endereços do navegador\n // -------------------------------------------------------------------------\n savedAddresses: SavedDeliveryAddress[]\n selectedAddressId: string | null\n /** Grava e passa a ser o endereço corrente. Devolve o id gravado. */\n saveAddress: (input: Omit<SavedDeliveryAddress, 'id' | 'createdAt'>) => string\n /** Escolhe um já gravado e recota o frete para ele. */\n selectAddress: (id: string, subtotal: number) => Promise<void>\n removeAddress: (id: string) => void\n\n // -------------------------------------------------------------------------\n // 0094 — entrega × retirada, e quando\n // -------------------------------------------------------------------------\n /**\n * Mora AQUI e não numa store nova de propósito: esta já é a store do \"para\n * onde e como isso chega\", já persiste o endereço e já é lida pelo checkout.\n * Uma segunda store com a metade da resposta acabaria discordando desta na\n * primeira tela que lesse só uma das duas.\n */\n fulfillmentType: FulfillmentType\n /** Início da janela escolhida (ISO). null = o quanto antes. */\n scheduledFor: string | null\n setFulfillmentType: (type: FulfillmentType) => void\n setScheduledFor: (startsAt: string | null) => void\n}\n\n/** Quantos endereços o caderno guarda. Uma lista longa deixa de ser um atalho. */\nconst MAX_SAVED_ADDRESSES = 8\n\n/** `crypto.randomUUID` quando existe; um id local quando não (Safari antigo,\n * contexto sem crypto). O id só precisa ser único NESTE navegador. */\nfunction newAddressId(): string {\n const c = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `addr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n}\n\nconst EMPTY = {\n postalCode: '',\n country: 'BR',\n address: null,\n options: [] as ShippingQuoteOption[],\n selectedZoneId: null,\n status: 'idle' as DeliveryStatus,\n error: null,\n errorKey: null,\n errorVars: null,\n refusedZone: null,\n reviewZone: null,\n}\n\nexport const useDeliveryStore = create<DeliveryState>()(\n persist(\n (set, get) => ({\n ...EMPTY,\n\n // 'delivery' é o default porque é o que toda loja anterior à 0094 é, e o\n // que uma loja sem retirada continua sendo.\n fulfillmentType: 'delivery' as FulfillmentType,\n scheduledFor: null,\n\n setFulfillmentType(type: FulfillmentType) {\n // Trocar de modo derruba o agendamento: as janelas de entrega e de\n // retirada são cadastradas separadamente (0094 aceita fulfillment_type\n // por linha de horário), então um horário escolhido para entregar pode\n // não existir para retirar. Guardá-lo seria guardar uma escolha que o\n // servidor vai recusar no fim do checkout.\n if (get().fulfillmentType === type) return\n set({ fulfillmentType: type, scheduledFor: null })\n },\n\n setScheduledFor(startsAt: string | null) {\n set({ scheduledFor: startsAt })\n },\n\n async resolve(postalCode: string, subtotal: number, country = 'BR') {\n const iso2 = country.toUpperCase()\n if (iso2 !== 'BR') {\n // Outside Brazil there are no zones or carrier to ask yet: the store's\n // flat rate applies, in the cart and in shop_shipping_for alike. What\n // the code CAN tell is its region (Spain: the province), offline.\n const schema = getCountrySchema(iso2)\n const code = schema.postal.normalize(postalCode)\n if (!schema.postal.pattern.test(code)) {\n set({\n ...EMPTY, postalCode, country: iso2, status: 'error',\n error: `Confira o código postal (ex.: ${schema.postal.example}).`,\n errorKey: 'delivery.error.postal', errorVars: { example: schema.postal.example },\n })\n return\n }\n const address = await lookupPostalCode(code, iso2).catch(() => null)\n set({ ...EMPTY, postalCode: code, country: iso2, address, status: 'idle' })\n return\n }\n\n const code = normalizePostalCode(postalCode)\n if (code.length !== 8) {\n set({ ...EMPTY, postalCode, status: 'error', error: 'Digite os 8 dígitos do CEP.', errorKey: 'delivery.error.digits' })\n return\n }\n\n set({ postalCode: code, country: 'BR', status: 'loading', error: null, errorKey: null, errorVars: null })\n\n // 0081 changed what the quote needs to know. A rule can now name a\n // MUNICIPALITY or a NEIGHBOURHOOD, and eight digits alone do not carry\n // either — so the lookup has to happen before the quote, not after it.\n //\n // The original rule still stands, though, and it is why this is a race\n // and not a plain await: with ViaCEP slow or rate-limited, a perfectly\n // serviceable address used to report an error instead of a price. So the\n // lookup gets a short window to answer and the quote goes out with or\n // without it. The server is the authority either way — it prefers the\n // address IT resolved (public.postal_areas) and treats this as a hint.\n const shop = getShopProvider()\n\n const addressPromise = lookupPostalCode(code).catch(() => null)\n const hint = await Promise.race([\n addressPromise.then((a) => (a\n ? { district: a.district, city: a.city, state: a.state, cityCode: a.cityCode }\n : undefined)),\n new Promise<undefined>((resolve) => { setTimeout(() => resolve(undefined), HINT_TIMEOUT_MS) }),\n ])\n\n // The store's own refusal (0048), asked CONCURRENTLY with the quote —\n // both are one RPC against the same eight digits, and the shopper is on\n // the page waiting for a number.\n //\n // It is a different question from \"does a zone cover this\": an exclusion\n // beats every zone AND a carrier's quote, because the refusal is about\n // the store and not about who carries the parcel. So it empties the\n // options even when a carrier just answered with a price.\n //\n // Swallowing the failure is deliberate: the order itself is refused\n // server-side either way, so a check that cannot run costs the shopper a\n // clearer message, never a sale that should not have happened.\n const checkPromise = shop.checkDelivery\n ? shop.checkDelivery(code, hint).catch(() => null)\n : Promise.resolve(null)\n\n let options: ShippingQuoteOption[] = []\n try {\n options = (await shop.quoteShipping?.(code, subtotal, hint)) ?? []\n } catch {\n set({ ...EMPTY, postalCode: code, status: 'error',\n error: 'Não foi possível calcular o frete agora. Tente de novo.', errorKey: 'delivery.error.quote' })\n return\n }\n\n const check = await checkPromise\n const refusedZone = check?.refused ? (check.refusedZone || 'Região não atendida') : null\n const reviewZone = !refusedZone && check?.outcome === 'review'\n ? (check.zoneName || 'Região a confirmar')\n : null\n if (refusedZone) options = []\n\n // The ADDRESS is the convenience layer: it saves the buyer typing, and\n // losing it costs typing, not the sale. Failures here never change the\n // delivery verdict already decided above.\n // Already in flight since before the quote — awaited here only to fill in\n // the street the buyer would otherwise type.\n const address = await addressPromise\n const notFound = address === null\n\n set({\n postalCode: code,\n address,\n options,\n selectedZoneId: options[0]?.zoneId ?? null,\n refusedZone,\n reviewZone,\n // A store with no zones configured quotes nothing, and that must NOT\n // read as \"we don't deliver here\" — it falls back to the store-wide\n // flat rate, which the cart already knows how to show.\n status: options.length > 0 ? 'served' : 'unserved',\n // Reported alongside the price, not instead of it: the CEP may be\n // mistyped even though its range is covered.\n error: notFound ? 'CEP não encontrado. Confira os números.' : null,\n errorKey: notFound ? 'delivery.error.notFound' : null,\n errorVars: null,\n })\n },\n\n selectZone(zoneId: string) {\n if (!get().options.some((option) => option.zoneId === zoneId)) return\n set({ selectedZoneId: zoneId })\n // Told to the server as well, because a CARRIER price is not something\n // the order can re-derive on its own the way it re-derives a zone: it\n // has to read back the option the shopper chose. Deliberately not\n // awaited — the radio button must not wait on a round trip, and the\n // server defaults to the cheapest option, so a lost call can only ever\n // charge less than what is on screen. Stores quoting from their own\n // zones do not implement this at all.\n void getShopProvider().selectShippingOption?.(zoneId)?.catch(() => {})\n },\n\n clear() {\n set({ ...EMPTY })\n },\n\n savedAddresses: [],\n selectedAddressId: null,\n\n saveAddress(input) {\n const id = newAddressId()\n const entry: SavedDeliveryAddress = { ...input, id, createdAt: new Date().toISOString() }\n set((state) => ({\n // Mesmo CEP + mesmo número é o MESMO endereço com o complemento\n // corrigido, não um segundo. Sem isto, três tentativas de acertar o\n // apartamento viram três linhas idênticas na lista.\n savedAddresses: [\n entry,\n ...state.savedAddresses.filter(\n (a) =>\n normalizePostalCode(a.postalCode) !== normalizePostalCode(entry.postalCode) ||\n a.number.trim().toLowerCase() !== entry.number.trim().toLowerCase(),\n ),\n ].slice(0, MAX_SAVED_ADDRESSES),\n selectedAddressId: id,\n }))\n return id\n },\n\n async selectAddress(id: string, subtotal: number) {\n const entry = get().savedAddresses.find((a) => a.id === id)\n if (!entry) return\n set({ selectedAddressId: id })\n // Recota SEMPRE, e não restaura um preço guardado: a zona pode ter\n // mudado desde que a pessoa salvou, e um frete vindo do localStorage é\n // um frete que devtools edita.\n await get().resolve(entry.postalCode, subtotal)\n },\n\n removeAddress(id: string) {\n set((state) => ({\n savedAddresses: state.savedAddresses.filter((a) => a.id !== id),\n selectedAddressId: state.selectedAddressId === id ? null : state.selectedAddressId,\n }))\n },\n }),\n {\n name: 'fayz.storefront.delivery.v1',\n // Deliberately NOT persisting `options`: a rehydrated\n // price would be shown as current without anything having quoted it. The\n // address survives, the money is asked for again.\n // `fulfillmentType` acompanha o endereço e pela mesma razão: é uma\n // preferência (\"eu sempre busco na loja\"), e ela vale amanhã.\n // `scheduledFor` NÃO acompanha, pela mesma razão de `options`: um horário\n // escolhido ontem é um horário que já passou, e restaurá-lo mandaria o\n // comprador ao checkout com uma janela que o servidor vai recusar.\n partialize: (state) => ({\n postalCode: state.postalCode,\n country: state.country,\n address: state.address,\n fulfillmentType: state.fulfillmentType,\n // O caderno é o ponto: número e complemento são o que o comprador\n // digita de novo a cada visita, e o que nenhuma consulta de CEP\n // devolve. Sem persistir, salvar endereço não salva nada.\n savedAddresses: state.savedAddresses,\n selectedAddressId: state.selectedAddressId,\n }),\n onRehydrateStorage: () => (state) => {\n if (state?.address) state.status = 'idle'\n // Stored before countries existed: every one of those was a CEP.\n if (state && !state.country) state.country = 'BR'\n },\n },\n ),\n)\n\n/**\n * The freight for the chosen zone at THIS subtotal, or null when there is no\n * zone in play (no CEP yet, or a store that configured none) and the caller\n * should use the store-wide rate. Null never means free.\n *\n * The free-above rule is applied here rather than trusting the `rate` the\n * server resolved, because that one was resolved for whatever the cart held at\n * quote time. Re-deriving from `baseRate`/`freeAbove` — the same CASE\n * shop_shipping_for runs — means adding an item can never leave a stale price\n * on screen. An earlier version fell back to the config flat rate when the\n * quote went stale, which showed R$ 8 (the flat rate) for an address in an\n * R$ 18 zone: shown one number, charged another.\n */\nexport function resolveOptionRate(option: ShippingQuoteOption, subtotal: number): number {\n if (option.freeAbove != null && subtotal >= option.freeAbove) return 0\n return option.baseRate\n}\n\nexport const selectQuotedShipping = (\n state: Pick<DeliveryState, 'options' | 'selectedZoneId' | 'status'>,\n subtotal: number,\n): number | null => {\n if (state.status !== 'served') return null\n const option = state.options.find((o) => o.zoneId === state.selectedZoneId) ?? state.options[0]\n return option ? resolveOptionRate(option, subtotal) : null\n}\n","import type { Product, ProductVariant } from '@fayz-ai/shop/types'\n\nexport interface ProductOptionGroup {\n id: string\n label: string\n values: string[]\n}\n\nexport type ProductOptionSelection = Record<string, string>\n\nfunction cleanValues(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return Array.from(new Set(value.filter((item): item is string => typeof item === 'string' && item.trim().length > 0)))\n}\n\nfunction cleanOptionGroup(value: unknown): ProductOptionGroup | null {\n if (!value || typeof value !== 'object') return null\n const record = value as Record<string, unknown>\n const id = typeof record.id === 'string' ? record.id : typeof record.name === 'string' ? record.name : null\n const label = typeof record.label === 'string' ? record.label : typeof record.name === 'string' ? record.name : id\n const values = cleanValues(record.values)\n if (!id || !label || values.length === 0) return null\n return { id, label, values }\n}\n\n// I10: the overlay shim warns once per product, not per render — the console\n// is a signal channel, not a firehose.\nconst warnedOverlayProducts = new Set<string>()\n\n/** Test seam — re-arms the once-per-product overlay deprecation warning. */\nexport function resetProductOptionsDeprecationWarnings(): void {\n warnedOverlayProducts.clear()\n}\n\n/**\n * The option axes the PDP picker renders, in order of authority:\n *\n * 1. `product.options` — the variant tables (0028), attached by the\n * products.bySlug loader. THE source since spine M5: these axes are the\n * ones the server prices and decrements against.\n * 2. metadata options / sizes / colors — the retired productMetadata overlay,\n * kept rendering as an I10 deprecation shim (logged, documented). Display\n * only: nothing server-side has ever heard of these labels, which is\n * exactly why the overlay lost the job. Full deletion from the stores is\n * M9 (`catalog.ts` dies everywhere).\n */\nexport function getProductOptionGroups(product: Product): ProductOptionGroup[] {\n if (product.options && product.options.length > 0) {\n return [...product.options]\n .sort((a, b) => a.position - b.position)\n .map((option) => ({ id: option.name, label: option.name, values: [...option.values] }))\n }\n\n const options = product.metadata.options\n const explicit = Array.isArray(options)\n ? options.map(cleanOptionGroup).filter((group): group is ProductOptionGroup => Boolean(group))\n : []\n\n const groups: ProductOptionGroup[] = [...explicit]\n if (groups.length === 0) {\n const sizes = cleanValues(product.metadata.sizes)\n const colors = cleanValues(product.metadata.colors)\n if (sizes.length > 0) groups.push({ id: 'Tamanho', label: 'Tamanho', values: sizes })\n if (colors.length > 0) groups.push({ id: 'Cor', label: 'Cor', values: colors })\n }\n\n if (groups.length > 0 && !warnedOverlayProducts.has(product.id)) {\n warnedOverlayProducts.add(product.id)\n console.warn(\n `[storefront] product \"${product.slug}\" renders options from the DEPRECATED metadata overlay ` +\n '(metadata.options/sizes/colors). These labels are display-only — checkout cannot price or reserve them. ' +\n 'Define real variants (0028) instead; the overlay path is removed at M9.',\n )\n }\n return groups\n}\n\n/**\n * The variant a selection denotes, or null when the product has no variants\n * or the combination does not exist (a partial selection, or axes/values the\n * variant table never had). Matching is exact over the variant's own options\n * object — the same jsonb equality 0029 relies on server-side.\n */\nexport function resolveVariantForSelection(\n product: Product,\n selection?: ProductOptionSelection | null,\n): ProductVariant | null {\n const variants = product.variants\n if (!variants || variants.length === 0) return null\n const normalized = normalizeProductOptionSelection(selection)\n const wanted = Object.entries(normalized)\n return (\n variants.find((variant) => {\n const options = variant.options\n return (\n Object.keys(options).length === wanted.length &&\n wanted.every(([key, value]) => options[key] === value)\n )\n }) ?? null\n )\n}\n\n/** The price a selection sells for: the variant's own, or the product's when\n * the variant inherits (price null) or nothing matched. */\nexport function selectionPrice(product: Product, selection?: ProductOptionSelection | null): number {\n const variant = resolveVariantForSelection(product, selection)\n return variant?.price ?? product.price\n}\n\nexport function normalizeProductOptionSelection(selection?: ProductOptionSelection | null): ProductOptionSelection {\n if (!selection) return {}\n return Object.fromEntries(\n Object.entries(selection)\n .filter((entry): entry is [string, string] => entry[0].trim().length > 0 && entry[1].trim().length > 0)\n .sort(([a], [b]) => a.localeCompare(b)),\n )\n}\n\nexport function formatProductOptionSelection(selection?: ProductOptionSelection | null): string {\n return Object.entries(normalizeProductOptionSelection(selection))\n .map(([label, value]) => `${label}: ${value}`)\n .join(' · ')\n}\n\nexport function productOptionSelectionKey(selection?: ProductOptionSelection | null): string {\n const normalized = normalizeProductOptionSelection(selection)\n const entries = Object.entries(normalized)\n return entries.length > 0 ? JSON.stringify(entries) : ''\n}\n","import { create } from 'zustand'\nimport { marketUnitPrice, useMarketStore } from './market.store'\nimport { persist } from 'zustand/middleware'\nimport type { Product } from '@fayz-ai/shop/types'\nimport { roundCents } from '../lib/format'\nimport type { ResolvedStorefrontConfig } from '../document/config'\nimport { useDeliveryStore, selectQuotedShipping } from './delivery.store'\nimport {\n formatProductOptionSelection,\n normalizeProductOptionSelection,\n productOptionSelectionKey,\n resolveVariantForSelection,\n type ProductOptionSelection,\n} from '../data/product-options'\n\nexport interface CartLine {\n lineId: string\n productId: string\n /** Variant the selection resolved to (spine M5) — what checkout sends so\n * the server prices and decrements the right counter. Absent for\n * variantless products and overlay-only (display) options. */\n variantId?: string\n slug: string\n name: string\n sku: string | null\n options: ProductOptionSelection\n optionsLabel: string\n /** In the market the line was added in (0116). */\n unitPrice: number\n /** The catalogue's own price, kept so a change of market can reprice the\n * line. Absent on lines persisted before markets. */\n basePrice?: number\n quantity: number\n imageUrl: string | null\n /** inventoryCount at add time — clamps quantity */\n maxQuantity: number\n /**\n * What the carrier needs to price a box, copied at add time from the VARIANT\n * when there is one and the product otherwise (0046: a camiseta P and a GG do\n * not occupy the same box).\n *\n * Copied rather than re-fetched because the quote runs on every postcode\n * keystroke and the cart is the only thing that knows what is in it. Lines\n * persisted before FAY-1407 carry none of these and read as unmeasured, which\n * is exactly what they are — the quote degrades to the store's default\n * package instead of failing.\n */\n requiresShipping?: boolean\n weight?: number | null\n weightUnit?: string | null\n heightCm?: number | null\n widthCm?: number | null\n lengthCm?: number | null\n /** Em que embalagem da loja o lojista despacha este produto (0047). Do\n * PRODUTO, nunca da variante — a variante carrega medida, não caixa. */\n packageId?: string | null\n /**\n * O que o comprador pediu NESTA linha — \"sem cebola\" (0094). Até 250\n * caracteres, que é o que o banco aceita e o que a tela conta.\n *\n * Participa do `lineId`: ver addItem. Duas unidades do mesmo prato com\n * pedidos diferentes são duas linhas, não uma de quantidade 2.\n */\n notes?: string\n}\n\nexport interface CartState {\n lines: CartLine[]\n discountCode: string | null\n discountPercent: number\n /** The applied coupon zeroes freight (a `free_shipping` discount) rather than\n * discounting the subtotal. Kept apart from `discountPercent` because the\n * two answer different questions and a coupon can only be one of them. */\n discountFreeShipping: boolean\n isOpen: boolean\n /** Line most recently added — lets the drawer briefly highlight it. */\n justAddedLineId: string | null\n /** `notes` (0094) é a observação da linha — participa da identidade dela. */\n /**\n * `openDrawer` decide se a gaveta abre sozinha. Default `true`, que é o\n * comportamento de sempre: numa loja de catálogo você compra uma ou duas\n * coisas e a gaveta deslizando é a confirmação.\n *\n * Num CARDÁPIO isso está errado. A pessoa monta uma cesta de oito itens, e\n * abrir a gaveta a cada \"+\" interrompe a montagem oito vezes — cada uma\n * exigindo um toque para voltar ao ponto da lista onde ela estava. Lá o\n * cardápio passa `false` e avisa com um toast que oferece as duas saídas.\n */\n addItem(\n product: Product,\n qty?: number,\n options?: ProductOptionSelection,\n notes?: string,\n opts?: { openDrawer?: boolean },\n ): void\n setQuantity(lineId: string, qty: number): void\n removeItem(lineId: string): void\n applyDiscount(code: string, percent: number, options?: { freeShipping?: boolean }): void\n clearDiscount(): void\n clear(): void\n /** Reprice every line in the active market; drop the ones it does not sell. */\n repriceForMarket(): void\n openDrawer(): void\n closeDrawer(): void\n /** Drop persisted lines the active backend can no longer resolve (e.g. a cart\n * built in an earlier mock-mode session, whose ids don't exist live). The\n * resolver returns false only for a definitive \"not found\"; on error it must\n * return true so a transient failure never discards a legit line. */\n reconcile(resolve: (line: CartLine) => Promise<boolean>): Promise<void>\n}\n\nexport const useCartStore = create<CartState>()(\n persist(\n (set, get) => ({\n lines: [],\n discountCode: null,\n discountPercent: 0,\n discountFreeShipping: false,\n isOpen: false,\n justAddedLineId: null,\n\n addItem: (product, qty = 1, options, notes, opts) =>\n set((state) => {\n const normalizedOptions = normalizeProductOptionSelection(options)\n const optionKey = productOptionSelectionKey(normalizedOptions)\n // A observação ENTRA na identidade da linha (0094), e isto não é\n // detalhe: sem ela, \"1x costela sem cebola\" e \"1x costela bem passada\"\n // colidiriam no mesmo lineId e virariam uma linha de quantidade 2 com\n // UM dos dois pedidos — o outro sumiria em silêncio, e a cozinha\n // nunca saberia que existiu.\n const cleanNotes = notes?.trim().slice(0, 250) || undefined\n const baseId = optionKey ? `${product.id}:${optionKey}` : product.id\n const lineId = cleanNotes ? `${baseId}#${cleanNotes}` : baseId\n // The selection's variant (spine M5): when the product carries real\n // variants, the VARIANT is the sellable unit — its price and its own\n // stock counter, never the product's. Display-only overlay options\n // resolve to null and keep the product-level numbers.\n const variant = resolveVariantForSelection(product, normalizedOptions)\n const basePrice = variant?.price ?? product.price\n // In the buyer's market (0116). A product the market has no price for\n // is not for sale there: adding it would end in a checkout refusal.\n const unitPrice = marketUnitPrice(useMarketStore.getState(), product.id, variant?.id, basePrice)\n if (unitPrice == null) return state\n const stock = variant ? variant.inventoryCount : product.inventoryCount\n const existing = state.lines.find((l) => (l.lineId ?? l.productId) === lineId)\n if (existing) {\n const nextQty = Math.min(existing.quantity + qty, existing.maxQuantity || Infinity)\n return {\n // Auto-open the cart on add — the standard premium \"slide-in cart\"\n // signal — and flag the line so the drawer can highlight it.\n isOpen: opts?.openDrawer ?? true,\n justAddedLineId: lineId,\n lines: state.lines.map((l) =>\n (l.lineId ?? l.productId) === lineId ? { ...l, lineId, quantity: nextQty } : l,\n ),\n }\n }\n const image = product.images.find((i) => i.isPrimary) ?? product.images[0]\n const line: CartLine = {\n lineId,\n productId: product.id,\n variantId: variant?.id,\n slug: product.slug,\n name: product.name,\n sku: variant?.sku ?? product.sku,\n options: normalizedOptions,\n optionsLabel: formatProductOptionSelection(normalizedOptions),\n unitPrice,\n basePrice,\n quantity: Math.min(qty, stock || Infinity),\n imageUrl: image?.url ?? null,\n maxQuantity: stock,\n requiresShipping: product.isPhysical !== false,\n weight: variant?.weight ?? product.weight ?? null,\n weightUnit: variant?.weightUnit ?? product.weightUnit ?? null,\n heightCm: variant?.heightCm ?? product.heightCm ?? null,\n widthCm: variant?.widthCm ?? product.widthCm ?? null,\n lengthCm: variant?.lengthCm ?? product.lengthCm ?? null,\n packageId: product.packageId ?? null,\n notes: cleanNotes,\n }\n return {\n isOpen: opts?.openDrawer ?? true,\n justAddedLineId: lineId,\n lines: [...state.lines, line],\n }\n }),\n\n setQuantity: (lineId, qty) =>\n set((state) => {\n if (qty <= 0) return { lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) }\n return {\n lines: state.lines.map((l) =>\n (l.lineId ?? l.productId) === lineId\n ? { ...l, quantity: Math.min(qty, l.maxQuantity || Infinity) }\n : l,\n ),\n }\n }),\n\n removeItem: (lineId) =>\n set((state) => ({ lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) })),\n\n applyDiscount: (code, percent, options) => set({\n discountCode: code,\n discountPercent: percent,\n discountFreeShipping: options?.freeShipping === true,\n }),\n clearDiscount: () => set({ discountCode: null, discountPercent: 0, discountFreeShipping: false }),\n clear: () => set({ lines: [], discountCode: null, discountPercent: 0, discountFreeShipping: false }),\n\n repriceForMarket: () =>\n set((state) => {\n const market = useMarketStore.getState()\n let changed = false\n const lines = state.lines.flatMap((line) => {\n const price = marketUnitPrice(market, line.productId, line.variantId, line.basePrice ?? line.unitPrice)\n if (price == null) {\n changed = true\n return []\n }\n if (price !== line.unitPrice) changed = true\n return [{ ...line, unitPrice: price }]\n })\n return changed ? { lines } : state\n }),\n openDrawer: () => set({ isOpen: true }),\n closeDrawer: () => set({ isOpen: false, justAddedLineId: null }),\n\n reconcile: async (resolve) => {\n const lines = get().lines\n if (lines.length === 0) return\n const keep = await Promise.all(\n lines.map((line) => resolve(line).catch(() => true)),\n )\n const kept = lines.filter((_, i) => keep[i])\n if (kept.length !== lines.length) set({ lines: kept })\n },\n }),\n {\n name: 'fayz.storefront.cart.v1',\n partialize: (state) => ({\n lines: state.lines,\n discountCode: state.discountCode,\n discountPercent: state.discountPercent,\n discountFreeShipping: state.discountFreeShipping,\n }),\n },\n ),\n)\n\n// ---------------------------------------------------------------------------\n// Money selectors — the single place cart math happens. Checkout passes these\n// exact values to createOrder so drawer totals always match order totals.\n// ---------------------------------------------------------------------------\n\nexport const selectCount = (s: Pick<CartState, 'lines'>): number =>\n s.lines.reduce((n, l) => n + l.quantity, 0)\n\nexport const selectSubtotal = (s: Pick<CartState, 'lines'>): number =>\n roundCents(s.lines.reduce((sum, l) => sum + l.unitPrice * l.quantity, 0))\n\nexport const selectDiscountTotal = (s: Pick<CartState, 'lines' | 'discountPercent'>): number =>\n roundCents(selectSubtotal(s) * (s.discountPercent / 100))\n\n/**\n * Freight to display.\n *\n * When the shopper has given a CEP and the store quoted it, that quote wins —\n * it came from the same shipping_zones rows shop_place_order will charge from.\n * Otherwise this falls back to the store-wide rate in config, which is what\n * every storefront did before zones existed.\n *\n * The subtotal is PRE-discount on both sides of this. That is 0017's rule, and\n * the quote is requested against the same number, so a coupon can never make\n * the cart and the order disagree.\n *\n * Read through getState() rather than a hook because this is a plain selector\n * called from several screens; components that render the value subscribe to\n * useDeliveryStore themselves so a fresh quote re-renders them.\n */\n/**\n * Whether anything in this cart travels.\n *\n * A line added before FAY-1407 has no flag and counts as physical: a cart of\n * real goods that suddenly ships for free is a worse failure than a download\n * that shows a delivery box.\n */\nexport const selectRequiresShipping = (s: Pick<CartState, 'lines'>): boolean =>\n s.lines.some((l) => l.requiresShipping !== false)\n\nexport type ShippingCart = Pick<CartState, 'lines'> & Partial<Pick<CartState, 'discountFreeShipping'>>\n\nexport const selectShipping = (\n s: ShippingCart,\n cfg: ResolvedStorefrontConfig,\n): number => {\n if (s.lines.length === 0) return 0\n // Nothing here is delivered. Not \"free delivery\" — no delivery, so neither\n // the quote nor the store-wide flat rate applies. Without this a cart of\n // e-books was charged the config's flatRate for a parcel that never exists.\n if (!selectRequiresShipping(s)) return 0\n // A free_shipping coupon. shop_place_order zeroes freight the same way and\n // does not even consult the zones (0017:178), so the quote below would show\n // a number the order will never charge.\n if (s.discountFreeShipping) return 0\n const subtotal = selectSubtotal(s)\n\n const quoted = selectQuotedShipping(useDeliveryStore.getState(), subtotal)\n if (quoted != null) return quoted\n\n if (cfg.shipping.freeAbove != null && subtotal >= cfg.shipping.freeAbove) return 0\n return cfg.shipping.flatRate\n}\n\nexport const selectTotal = (\n s: Pick<CartState, 'lines' | 'discountPercent'> & Partial<Pick<CartState, 'discountFreeShipping'>>,\n cfg: ResolvedStorefrontConfig,\n): number =>\n roundCents(selectSubtotal(s) - selectDiscountTotal(s) + selectShipping(s, cfg))\n"]}
1
+ {"version":3,"sources":["../src/stores/market.store.ts","../src/stores/delivery.store.ts","../src/data/product-options.ts","../src/stores/cart.store.ts"],"names":["create","code","address","persist"],"mappings":"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","file":"chunk-C4XATNI2.js","sourcesContent":["import { create } from 'zustand'\nimport type { MarketPrice, Product, ShopMarket } from '@fayz-ai/shop/types'\n\n// The store's markets (0116) and the active one's price list.\n//\n// Module-level on purpose, like the cart: the cart prices a line when it is\n// added, far from any render, and must read the same numbers the page shows.\n// Not persisted: prices are asked for again on every visit.\n\nexport interface MarketState {\n markets: ShopMarket[]\n /** The market the buyer is in, null when the store has none. */\n active: ShopMarket | null\n /** code → `${productId}:${variantId ?? ''}` → price. */\n prices: Record<string, Record<string, number>>\n setMarkets(markets: ShopMarket[]): void\n setActive(market: ShopMarket | null): void\n setPrices(code: string, list: MarketPrice[]): void\n}\n\nexport const useMarketStore = create<MarketState>()((set) => ({\n markets: [],\n active: null,\n prices: {},\n setMarkets: (markets) => set({ markets }),\n setActive: (active) => set({ active }),\n setPrices: (code, list) =>\n set((state) => ({\n prices: {\n ...state.prices,\n [code]: Object.fromEntries(list.map((p) => [`${p.productId}:${p.variantId ?? ''}`, p.price])),\n },\n })),\n}))\n\n/** The market for a country: the one that ships there, else the default. */\nexport function marketForCountry(markets: readonly ShopMarket[], country: string): ShopMarket | null {\n const iso2 = country.toUpperCase()\n return markets.find((m) => m.countries.includes(iso2)) ?? markets.find((m) => m.isDefault) ?? null\n}\n\n/**\n * A unit price in the active market, by shop_market_unit_price's rule: the\n * market's price (variant over product), the catalogue's own in the default\n * market, and `null` — not for sale here — anywhere else.\n */\nexport function marketUnitPrice(\n state: Pick<MarketState, 'active' | 'prices'>,\n productId: string,\n variantId: string | null | undefined,\n fallback: number,\n): number | null {\n const market = state.active\n if (!market) return fallback\n const list = state.prices[market.code]\n const hit = list?.[`${productId}:${variantId ?? ''}`] ?? list?.[`${productId}:`]\n if (hit != null) return hit\n return market.isDefault ? fallback : null\n}\n\n/**\n * The product as the buyer's market sells it: its price, no compare-at (that\n * number is in the default market's money), and out of stock where the market\n * has no price — the page must not offer a sale the checkout will refuse.\n */\nexport function withMarketPrice(product: Product, state: Pick<MarketState, 'active' | 'prices'> = useMarketStore.getState()): Product {\n const market = state.active\n if (!market || market.isDefault) return product\n const price = marketUnitPrice(state, product.id, null, product.price)\n if (price == null) {\n return { ...product, compareAtPrice: null, currency: market.currency, inventoryCount: 0, metadata: { ...product.metadata, unavailableInMarket: market.code } }\n }\n return {\n ...product,\n price,\n compareAtPrice: null,\n currency: market.currency,\n variants: product.variants?.map((v) => ({ ...v, price: marketUnitPrice(state, product.id, v.id, v.price ?? product.price), compareAtPrice: null })),\n }\n}\n","import { create } from 'zustand'\nimport { persist } from 'zustand/middleware'\nimport { getCountrySchema, lookupPostalCode, normalizePostalCode, type PostalAddress } from '@fayz-ai/core'\nimport { getShopProvider } from '@fayz-ai/shop/runtime'\nimport type { FulfillmentType, ShippingQuoteOption } from '@fayz-ai/shop/types'\nimport type { MessageKey } from '../locales/messages'\n\n/**\n * Where the shopper wants it delivered, decided before the cart exists.\n *\n * Two different things live here and they are persisted differently on purpose:\n *\n * the ADDRESS is durable — a CEP maps to the same street for years, and\n * carrying it to checkout is the whole point (the buyer types the number and\n * nothing else);\n *\n * the QUOTE is not persisted at all. It is a price, and a price restored from\n * localStorage is a price the shopper can edit with devtools. It is re-asked\n * on demand, and resolved for the current cart through resolveOptionRate —\n * the same rule shop_shipping_for applies — so it can never go stale. The\n * order is charged from shop_place_order, which recomputes from the same\n * zones and ignores anything the client sends.\n */\n\nexport type DeliveryStatus = 'idle' | 'loading' | 'served' | 'unserved' | 'error'\n\n/**\n * Um endereço que o comprador salvou NESTE navegador.\n *\n * Existe porque o caderno de endereços do `plugin-shop` é de quem tem conta, e\n * num delivery a pessoa tem endereço antes de ter login — é a primeira coisa\n * que ela informa e a última que quer digitar de novo. O CEP resolve rua,\n * bairro e cidade; o que NENHUMA consulta de CEP sabe é o número, o\n * complemento e \"o portão azul ao lado da padaria\". É exatamente isso que se\n * perde a cada visita quando não se guarda nada.\n *\n * Fica no navegador e só nele. Não é conta, não sincroniza entre aparelhos e\n * não vai para o servidor por conta própria — quem grava endereço no pedido é\n * o checkout, com o que a pessoa confirmou na hora.\n */\nexport interface SavedDeliveryAddress {\n id: string\n /** \"Casa\", \"Trabalho\"… Opcional: a maioria salva um só e não nomeia nada. */\n label: string | null\n postalCode: string\n street: string\n number: string\n complement: string | null\n /** O ponto de referência — \"portão azul\", \"prédio ao lado do mercado\". */\n reference: string | null\n district: string\n city: string\n state: string\n /** ISO2. Absent on everything saved before countries: those are Brazilian. */\n country?: string\n createdAt: string\n}\n\n/** How long the quote waits for the postcode lookup before going without it.\n * Short on purpose: the hint improves the answer, it must never delay it. */\nconst HINT_TIMEOUT_MS = 1200\n\nexport interface DeliveryState {\n postalCode: string\n /** ISO2 the postal code belongs to. 'BR' for everything stored before countries. */\n country: string\n address: PostalAddress | null\n options: ShippingQuoteOption[]\n selectedZoneId: string | null\n status: DeliveryStatus\n error: string | null\n /** `error` as a message key, so a screen can say it in the buyer's language. */\n errorKey: MessageKey | null\n errorVars: Record<string, string> | null\n /**\n * The name of the exclusion zone covering this CEP, when the store REFUSES the\n * region (0048). Null when it does not.\n *\n * Carried as a separate field rather than a fourth status because every\n * consumer already treats `unserved` as \"no delivery here\" and that is exactly\n * what this is — the field only lets the message say WHY.\n */\n refusedZone: string | null\n\n /**\n * The name of the rule that says this address is delivered but has to be\n * CONFIRMED first (0081) — the community that shares a postcode with the\n * neighbourhood next door.\n *\n * Not a status either, and for the opposite reason to `refusedZone`: the\n * order goes through and the price is real. Every consumer that shows a price\n * keeps showing it; this only adds a line saying the store will confirm.\n */\n reviewZone: string | null\n\n /** Look the postal code up and quote it. `subtotal` decides free-above\n * thresholds; `country` (ISO2, default 'BR') decides what a code looks like. */\n resolve: (postalCode: string, subtotal: number, country?: string) => Promise<void>\n selectZone: (zoneId: string) => void\n clear: () => void\n\n // -------------------------------------------------------------------------\n // O caderno de endereços do navegador\n // -------------------------------------------------------------------------\n savedAddresses: SavedDeliveryAddress[]\n selectedAddressId: string | null\n /** Grava e passa a ser o endereço corrente. Devolve o id gravado. */\n saveAddress: (input: Omit<SavedDeliveryAddress, 'id' | 'createdAt'>) => string\n /** Escolhe um já gravado e recota o frete para ele. */\n selectAddress: (id: string, subtotal: number) => Promise<void>\n removeAddress: (id: string) => void\n\n // -------------------------------------------------------------------------\n // 0094 — entrega × retirada, e quando\n // -------------------------------------------------------------------------\n /**\n * Mora AQUI e não numa store nova de propósito: esta já é a store do \"para\n * onde e como isso chega\", já persiste o endereço e já é lida pelo checkout.\n * Uma segunda store com a metade da resposta acabaria discordando desta na\n * primeira tela que lesse só uma das duas.\n */\n fulfillmentType: FulfillmentType\n /** Início da janela escolhida (ISO). null = o quanto antes. */\n scheduledFor: string | null\n setFulfillmentType: (type: FulfillmentType) => void\n setScheduledFor: (startsAt: string | null) => void\n}\n\n/** Quantos endereços o caderno guarda. Uma lista longa deixa de ser um atalho. */\nconst MAX_SAVED_ADDRESSES = 8\n\n/** `crypto.randomUUID` quando existe; um id local quando não (Safari antigo,\n * contexto sem crypto). O id só precisa ser único NESTE navegador. */\nfunction newAddressId(): string {\n const c = globalThis.crypto\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n return `addr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n}\n\nconst EMPTY = {\n postalCode: '',\n country: 'BR',\n address: null,\n options: [] as ShippingQuoteOption[],\n selectedZoneId: null,\n status: 'idle' as DeliveryStatus,\n error: null,\n errorKey: null,\n errorVars: null,\n refusedZone: null,\n reviewZone: null,\n}\n\nexport const useDeliveryStore = create<DeliveryState>()(\n persist(\n (set, get) => ({\n ...EMPTY,\n\n // 'delivery' é o default porque é o que toda loja anterior à 0094 é, e o\n // que uma loja sem retirada continua sendo.\n fulfillmentType: 'delivery' as FulfillmentType,\n scheduledFor: null,\n\n setFulfillmentType(type: FulfillmentType) {\n // Trocar de modo derruba o agendamento: as janelas de entrega e de\n // retirada são cadastradas separadamente (0094 aceita fulfillment_type\n // por linha de horário), então um horário escolhido para entregar pode\n // não existir para retirar. Guardá-lo seria guardar uma escolha que o\n // servidor vai recusar no fim do checkout.\n if (get().fulfillmentType === type) return\n set({ fulfillmentType: type, scheduledFor: null })\n },\n\n setScheduledFor(startsAt: string | null) {\n set({ scheduledFor: startsAt })\n },\n\n async resolve(postalCode: string, subtotal: number, country = 'BR') {\n const iso2 = country.toUpperCase()\n if (iso2 !== 'BR') {\n // Outside Brazil there are no zones or carrier to ask yet: the store's\n // flat rate applies, in the cart and in shop_shipping_for alike. What\n // the code CAN tell is its region (Spain: the province), offline.\n const schema = getCountrySchema(iso2)\n const code = schema.postal.normalize(postalCode)\n if (!schema.postal.pattern.test(code)) {\n set({\n ...EMPTY, postalCode, country: iso2, status: 'error',\n error: `Confira o código postal (ex.: ${schema.postal.example}).`,\n errorKey: 'delivery.error.postal', errorVars: { example: schema.postal.example },\n })\n return\n }\n const address = await lookupPostalCode(code, iso2).catch(() => null)\n set({ ...EMPTY, postalCode: code, country: iso2, address, status: 'idle' })\n return\n }\n\n const code = normalizePostalCode(postalCode)\n if (code.length !== 8) {\n set({ ...EMPTY, postalCode, status: 'error', error: 'Digite os 8 dígitos do CEP.', errorKey: 'delivery.error.digits' })\n return\n }\n\n set({ postalCode: code, country: 'BR', status: 'loading', error: null, errorKey: null, errorVars: null })\n\n // 0081 changed what the quote needs to know. A rule can now name a\n // MUNICIPALITY or a NEIGHBOURHOOD, and eight digits alone do not carry\n // either — so the lookup has to happen before the quote, not after it.\n //\n // The original rule still stands, though, and it is why this is a race\n // and not a plain await: with ViaCEP slow or rate-limited, a perfectly\n // serviceable address used to report an error instead of a price. So the\n // lookup gets a short window to answer and the quote goes out with or\n // without it. The server is the authority either way — it prefers the\n // address IT resolved (public.postal_areas) and treats this as a hint.\n const shop = getShopProvider()\n\n const addressPromise = lookupPostalCode(code).catch(() => null)\n const hint = await Promise.race([\n addressPromise.then((a) => (a\n ? { district: a.district, city: a.city, state: a.state, cityCode: a.cityCode }\n : undefined)),\n new Promise<undefined>((resolve) => { setTimeout(() => resolve(undefined), HINT_TIMEOUT_MS) }),\n ])\n\n // The store's own refusal (0048), asked CONCURRENTLY with the quote —\n // both are one RPC against the same eight digits, and the shopper is on\n // the page waiting for a number.\n //\n // It is a different question from \"does a zone cover this\": an exclusion\n // beats every zone AND a carrier's quote, because the refusal is about\n // the store and not about who carries the parcel. So it empties the\n // options even when a carrier just answered with a price.\n //\n // Swallowing the failure is deliberate: the order itself is refused\n // server-side either way, so a check that cannot run costs the shopper a\n // clearer message, never a sale that should not have happened.\n const checkPromise = shop.checkDelivery\n ? shop.checkDelivery(code, hint).catch(() => null)\n : Promise.resolve(null)\n\n let options: ShippingQuoteOption[] = []\n try {\n options = (await shop.quoteShipping?.(code, subtotal, hint)) ?? []\n } catch {\n set({ ...EMPTY, postalCode: code, status: 'error',\n error: 'Não foi possível calcular o frete agora. Tente de novo.', errorKey: 'delivery.error.quote' })\n return\n }\n\n const check = await checkPromise\n const refusedZone = check?.refused ? (check.refusedZone || 'Região não atendida') : null\n const reviewZone = !refusedZone && check?.outcome === 'review'\n ? (check.zoneName || 'Região a confirmar')\n : null\n if (refusedZone) options = []\n\n // The ADDRESS is the convenience layer: it saves the buyer typing, and\n // losing it costs typing, not the sale. Failures here never change the\n // delivery verdict already decided above.\n // Already in flight since before the quote — awaited here only to fill in\n // the street the buyer would otherwise type.\n const address = await addressPromise\n const notFound = address === null\n\n set({\n postalCode: code,\n address,\n options,\n selectedZoneId: options[0]?.zoneId ?? null,\n refusedZone,\n reviewZone,\n // A store with no zones configured quotes nothing, and that must NOT\n // read as \"we don't deliver here\" — it falls back to the store-wide\n // flat rate, which the cart already knows how to show.\n status: options.length > 0 ? 'served' : 'unserved',\n // Reported alongside the price, not instead of it: the CEP may be\n // mistyped even though its range is covered.\n error: notFound ? 'CEP não encontrado. Confira os números.' : null,\n errorKey: notFound ? 'delivery.error.notFound' : null,\n errorVars: null,\n })\n },\n\n selectZone(zoneId: string) {\n if (!get().options.some((option) => option.zoneId === zoneId)) return\n set({ selectedZoneId: zoneId })\n // Told to the server as well, because a CARRIER price is not something\n // the order can re-derive on its own the way it re-derives a zone: it\n // has to read back the option the shopper chose. Deliberately not\n // awaited — the radio button must not wait on a round trip, and the\n // server defaults to the cheapest option, so a lost call can only ever\n // charge less than what is on screen. Stores quoting from their own\n // zones do not implement this at all.\n void getShopProvider().selectShippingOption?.(zoneId)?.catch(() => {})\n },\n\n clear() {\n set({ ...EMPTY })\n },\n\n savedAddresses: [],\n selectedAddressId: null,\n\n saveAddress(input) {\n const id = newAddressId()\n const entry: SavedDeliveryAddress = { ...input, id, createdAt: new Date().toISOString() }\n set((state) => ({\n // Mesmo CEP + mesmo número é o MESMO endereço com o complemento\n // corrigido, não um segundo. Sem isto, três tentativas de acertar o\n // apartamento viram três linhas idênticas na lista.\n savedAddresses: [\n entry,\n ...state.savedAddresses.filter(\n (a) =>\n normalizePostalCode(a.postalCode) !== normalizePostalCode(entry.postalCode) ||\n a.number.trim().toLowerCase() !== entry.number.trim().toLowerCase(),\n ),\n ].slice(0, MAX_SAVED_ADDRESSES),\n selectedAddressId: id,\n }))\n return id\n },\n\n async selectAddress(id: string, subtotal: number) {\n const entry = get().savedAddresses.find((a) => a.id === id)\n if (!entry) return\n set({ selectedAddressId: id })\n // Recota SEMPRE, e não restaura um preço guardado: a zona pode ter\n // mudado desde que a pessoa salvou, e um frete vindo do localStorage é\n // um frete que devtools edita.\n await get().resolve(entry.postalCode, subtotal)\n },\n\n removeAddress(id: string) {\n set((state) => ({\n savedAddresses: state.savedAddresses.filter((a) => a.id !== id),\n selectedAddressId: state.selectedAddressId === id ? null : state.selectedAddressId,\n }))\n },\n }),\n {\n name: 'fayz.storefront.delivery.v1',\n // Deliberately NOT persisting `options`: a rehydrated\n // price would be shown as current without anything having quoted it. The\n // address survives, the money is asked for again.\n // `fulfillmentType` acompanha o endereço e pela mesma razão: é uma\n // preferência (\"eu sempre busco na loja\"), e ela vale amanhã.\n // `scheduledFor` NÃO acompanha, pela mesma razão de `options`: um horário\n // escolhido ontem é um horário que já passou, e restaurá-lo mandaria o\n // comprador ao checkout com uma janela que o servidor vai recusar.\n partialize: (state) => ({\n postalCode: state.postalCode,\n country: state.country,\n address: state.address,\n fulfillmentType: state.fulfillmentType,\n // O caderno é o ponto: número e complemento são o que o comprador\n // digita de novo a cada visita, e o que nenhuma consulta de CEP\n // devolve. Sem persistir, salvar endereço não salva nada.\n savedAddresses: state.savedAddresses,\n selectedAddressId: state.selectedAddressId,\n }),\n onRehydrateStorage: () => (state) => {\n if (state?.address) state.status = 'idle'\n // Stored before countries existed: every one of those was a CEP.\n if (state && !state.country) state.country = 'BR'\n },\n },\n ),\n)\n\n/**\n * The freight for the chosen zone at THIS subtotal, or null when there is no\n * zone in play (no CEP yet, or a store that configured none) and the caller\n * should use the store-wide rate. Null never means free.\n *\n * The free-above rule is applied here rather than trusting the `rate` the\n * server resolved, because that one was resolved for whatever the cart held at\n * quote time. Re-deriving from `baseRate`/`freeAbove` — the same CASE\n * shop_shipping_for runs — means adding an item can never leave a stale price\n * on screen. An earlier version fell back to the config flat rate when the\n * quote went stale, which showed R$ 8 (the flat rate) for an address in an\n * R$ 18 zone: shown one number, charged another.\n */\nexport function resolveOptionRate(option: ShippingQuoteOption, subtotal: number): number {\n if (option.freeAbove != null && subtotal >= option.freeAbove) return 0\n return option.baseRate\n}\n\nexport const selectQuotedShipping = (\n state: Pick<DeliveryState, 'options' | 'selectedZoneId' | 'status'>,\n subtotal: number,\n): number | null => {\n if (state.status !== 'served') return null\n const option = state.options.find((o) => o.zoneId === state.selectedZoneId) ?? state.options[0]\n return option ? resolveOptionRate(option, subtotal) : null\n}\n","import type { Product, ProductVariant } from '@fayz-ai/shop/types'\n\nexport interface ProductOptionGroup {\n id: string\n label: string\n values: string[]\n}\n\nexport type ProductOptionSelection = Record<string, string>\n\nfunction cleanValues(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return Array.from(new Set(value.filter((item): item is string => typeof item === 'string' && item.trim().length > 0)))\n}\n\nfunction cleanOptionGroup(value: unknown): ProductOptionGroup | null {\n if (!value || typeof value !== 'object') return null\n const record = value as Record<string, unknown>\n const id = typeof record.id === 'string' ? record.id : typeof record.name === 'string' ? record.name : null\n const label = typeof record.label === 'string' ? record.label : typeof record.name === 'string' ? record.name : id\n const values = cleanValues(record.values)\n if (!id || !label || values.length === 0) return null\n return { id, label, values }\n}\n\n// I10: the overlay shim warns once per product, not per render — the console\n// is a signal channel, not a firehose.\nconst warnedOverlayProducts = new Set<string>()\n\n/** Test seam — re-arms the once-per-product overlay deprecation warning. */\nexport function resetProductOptionsDeprecationWarnings(): void {\n warnedOverlayProducts.clear()\n}\n\n/**\n * The option axes the PDP picker renders, in order of authority:\n *\n * 1. `product.options` — the variant tables (0028), attached by the\n * products.bySlug loader. THE source since spine M5: these axes are the\n * ones the server prices and decrements against.\n * 2. metadata options / sizes / colors — the retired productMetadata overlay,\n * kept rendering as an I10 deprecation shim (logged, documented). Display\n * only: nothing server-side has ever heard of these labels, which is\n * exactly why the overlay lost the job. Full deletion from the stores is\n * M9 (`catalog.ts` dies everywhere).\n */\nexport function getProductOptionGroups(product: Product): ProductOptionGroup[] {\n if (product.options && product.options.length > 0) {\n return [...product.options]\n .sort((a, b) => a.position - b.position)\n .map((option) => ({ id: option.name, label: option.name, values: [...option.values] }))\n }\n\n const options = product.metadata.options\n const explicit = Array.isArray(options)\n ? options.map(cleanOptionGroup).filter((group): group is ProductOptionGroup => Boolean(group))\n : []\n\n const groups: ProductOptionGroup[] = [...explicit]\n if (groups.length === 0) {\n const sizes = cleanValues(product.metadata.sizes)\n const colors = cleanValues(product.metadata.colors)\n if (sizes.length > 0) groups.push({ id: 'Tamanho', label: 'Tamanho', values: sizes })\n if (colors.length > 0) groups.push({ id: 'Cor', label: 'Cor', values: colors })\n }\n\n if (groups.length > 0 && !warnedOverlayProducts.has(product.id)) {\n warnedOverlayProducts.add(product.id)\n console.warn(\n `[storefront] product \"${product.slug}\" renders options from the DEPRECATED metadata overlay ` +\n '(metadata.options/sizes/colors). These labels are display-only — checkout cannot price or reserve them. ' +\n 'Define real variants (0028) instead; the overlay path is removed at M9.',\n )\n }\n return groups\n}\n\n/**\n * The variant a selection denotes, or null when the product has no variants\n * or the combination does not exist (a partial selection, or axes/values the\n * variant table never had). Matching is exact over the variant's own options\n * object — the same jsonb equality 0029 relies on server-side.\n */\nexport function resolveVariantForSelection(\n product: Product,\n selection?: ProductOptionSelection | null,\n): ProductVariant | null {\n const variants = product.variants\n if (!variants || variants.length === 0) return null\n const normalized = normalizeProductOptionSelection(selection)\n const wanted = Object.entries(normalized)\n return (\n variants.find((variant) => {\n const options = variant.options\n return (\n Object.keys(options).length === wanted.length &&\n wanted.every(([key, value]) => options[key] === value)\n )\n }) ?? null\n )\n}\n\n/** The price a selection sells for: the variant's own, or the product's when\n * the variant inherits (price null) or nothing matched. */\nexport function selectionPrice(product: Product, selection?: ProductOptionSelection | null): number {\n const variant = resolveVariantForSelection(product, selection)\n return variant?.price ?? product.price\n}\n\nexport function normalizeProductOptionSelection(selection?: ProductOptionSelection | null): ProductOptionSelection {\n if (!selection) return {}\n return Object.fromEntries(\n Object.entries(selection)\n .filter((entry): entry is [string, string] => entry[0].trim().length > 0 && entry[1].trim().length > 0)\n .sort(([a], [b]) => a.localeCompare(b)),\n )\n}\n\nexport function formatProductOptionSelection(selection?: ProductOptionSelection | null): string {\n return Object.entries(normalizeProductOptionSelection(selection))\n .map(([label, value]) => `${label}: ${value}`)\n .join(' · ')\n}\n\nexport function productOptionSelectionKey(selection?: ProductOptionSelection | null): string {\n const normalized = normalizeProductOptionSelection(selection)\n const entries = Object.entries(normalized)\n return entries.length > 0 ? JSON.stringify(entries) : ''\n}\n","import { create } from 'zustand'\nimport { marketUnitPrice, useMarketStore } from './market.store'\nimport { persist } from 'zustand/middleware'\nimport type { Product } from '@fayz-ai/shop/types'\nimport { roundCents } from '../lib/format'\nimport type { ResolvedStorefrontConfig } from '../document/config'\nimport { useDeliveryStore, selectQuotedShipping } from './delivery.store'\nimport {\n formatProductOptionSelection,\n normalizeProductOptionSelection,\n productOptionSelectionKey,\n resolveVariantForSelection,\n type ProductOptionSelection,\n} from '../data/product-options'\n\nexport interface CartLine {\n lineId: string\n productId: string\n /** Variant the selection resolved to (spine M5) — what checkout sends so\n * the server prices and decrements the right counter. Absent for\n * variantless products and overlay-only (display) options. */\n variantId?: string\n slug: string\n name: string\n sku: string | null\n options: ProductOptionSelection\n optionsLabel: string\n /** In the market the line was added in (0116). */\n unitPrice: number\n /** The catalogue's own price, kept so a change of market can reprice the\n * line. Absent on lines persisted before markets. */\n basePrice?: number\n quantity: number\n imageUrl: string | null\n /** inventoryCount at add time — clamps quantity */\n maxQuantity: number\n /**\n * What the carrier needs to price a box, copied at add time from the VARIANT\n * when there is one and the product otherwise (0046: a camiseta P and a GG do\n * not occupy the same box).\n *\n * Copied rather than re-fetched because the quote runs on every postcode\n * keystroke and the cart is the only thing that knows what is in it. Lines\n * persisted before FAY-1407 carry none of these and read as unmeasured, which\n * is exactly what they are — the quote degrades to the store's default\n * package instead of failing.\n */\n requiresShipping?: boolean\n weight?: number | null\n weightUnit?: string | null\n heightCm?: number | null\n widthCm?: number | null\n lengthCm?: number | null\n /** Em que embalagem da loja o lojista despacha este produto (0047). Do\n * PRODUTO, nunca da variante — a variante carrega medida, não caixa. */\n packageId?: string | null\n /**\n * O que o comprador pediu NESTA linha — \"sem cebola\" (0094). Até 250\n * caracteres, que é o que o banco aceita e o que a tela conta.\n *\n * Participa do `lineId`: ver addItem. Duas unidades do mesmo prato com\n * pedidos diferentes são duas linhas, não uma de quantidade 2.\n */\n notes?: string\n}\n\nexport interface CartState {\n lines: CartLine[]\n discountCode: string | null\n discountPercent: number\n /** The applied coupon zeroes freight (a `free_shipping` discount) rather than\n * discounting the subtotal. Kept apart from `discountPercent` because the\n * two answer different questions and a coupon can only be one of them. */\n discountFreeShipping: boolean\n isOpen: boolean\n /** Line most recently added — lets the drawer briefly highlight it. */\n justAddedLineId: string | null\n /** `notes` (0094) é a observação da linha — participa da identidade dela. */\n /**\n * `openDrawer` decide se a gaveta abre sozinha. Default `true`, que é o\n * comportamento de sempre: numa loja de catálogo você compra uma ou duas\n * coisas e a gaveta deslizando é a confirmação.\n *\n * Num CARDÁPIO isso está errado. A pessoa monta uma cesta de oito itens, e\n * abrir a gaveta a cada \"+\" interrompe a montagem oito vezes — cada uma\n * exigindo um toque para voltar ao ponto da lista onde ela estava. Lá o\n * cardápio passa `false` e avisa com um toast que oferece as duas saídas.\n */\n addItem(\n product: Product,\n qty?: number,\n options?: ProductOptionSelection,\n notes?: string,\n opts?: { openDrawer?: boolean },\n ): void\n setQuantity(lineId: string, qty: number): void\n removeItem(lineId: string): void\n applyDiscount(code: string, percent: number, options?: { freeShipping?: boolean }): void\n clearDiscount(): void\n clear(): void\n /** Reprice every line in the active market; drop the ones it does not sell. */\n repriceForMarket(): void\n openDrawer(): void\n closeDrawer(): void\n /** Drop persisted lines the active backend can no longer resolve (e.g. a cart\n * built in an earlier mock-mode session, whose ids don't exist live). The\n * resolver returns false only for a definitive \"not found\"; on error it must\n * return true so a transient failure never discards a legit line. */\n reconcile(resolve: (line: CartLine) => Promise<boolean>): Promise<void>\n}\n\nexport const useCartStore = create<CartState>()(\n persist(\n (set, get) => ({\n lines: [],\n discountCode: null,\n discountPercent: 0,\n discountFreeShipping: false,\n isOpen: false,\n justAddedLineId: null,\n\n addItem: (product, qty = 1, options, notes, opts) =>\n set((state) => {\n const normalizedOptions = normalizeProductOptionSelection(options)\n const optionKey = productOptionSelectionKey(normalizedOptions)\n // A observação ENTRA na identidade da linha (0094), e isto não é\n // detalhe: sem ela, \"1x costela sem cebola\" e \"1x costela bem passada\"\n // colidiriam no mesmo lineId e virariam uma linha de quantidade 2 com\n // UM dos dois pedidos — o outro sumiria em silêncio, e a cozinha\n // nunca saberia que existiu.\n const cleanNotes = notes?.trim().slice(0, 250) || undefined\n const baseId = optionKey ? `${product.id}:${optionKey}` : product.id\n const lineId = cleanNotes ? `${baseId}#${cleanNotes}` : baseId\n // The selection's variant (spine M5): when the product carries real\n // variants, the VARIANT is the sellable unit — its price and its own\n // stock counter, never the product's. Display-only overlay options\n // resolve to null and keep the product-level numbers.\n const variant = resolveVariantForSelection(product, normalizedOptions)\n const basePrice = variant?.price ?? product.price\n // In the buyer's market (0116). A product the market has no price for\n // is not for sale there: adding it would end in a checkout refusal.\n const unitPrice = marketUnitPrice(useMarketStore.getState(), product.id, variant?.id, basePrice)\n if (unitPrice == null) return state\n const stock = variant ? variant.inventoryCount : product.inventoryCount\n const existing = state.lines.find((l) => (l.lineId ?? l.productId) === lineId)\n if (existing) {\n const nextQty = Math.min(existing.quantity + qty, existing.maxQuantity || Infinity)\n return {\n // Auto-open the cart on add — the standard premium \"slide-in cart\"\n // signal — and flag the line so the drawer can highlight it.\n isOpen: opts?.openDrawer ?? true,\n justAddedLineId: lineId,\n lines: state.lines.map((l) =>\n (l.lineId ?? l.productId) === lineId ? { ...l, lineId, quantity: nextQty } : l,\n ),\n }\n }\n const image = product.images.find((i) => i.isPrimary) ?? product.images[0]\n const line: CartLine = {\n lineId,\n productId: product.id,\n variantId: variant?.id,\n slug: product.slug,\n name: product.name,\n sku: variant?.sku ?? product.sku,\n options: normalizedOptions,\n optionsLabel: formatProductOptionSelection(normalizedOptions),\n unitPrice,\n basePrice,\n quantity: Math.min(qty, stock || Infinity),\n imageUrl: image?.url ?? null,\n maxQuantity: stock,\n requiresShipping: product.isPhysical !== false,\n weight: variant?.weight ?? product.weight ?? null,\n weightUnit: variant?.weightUnit ?? product.weightUnit ?? null,\n heightCm: variant?.heightCm ?? product.heightCm ?? null,\n widthCm: variant?.widthCm ?? product.widthCm ?? null,\n lengthCm: variant?.lengthCm ?? product.lengthCm ?? null,\n packageId: product.packageId ?? null,\n notes: cleanNotes,\n }\n return {\n isOpen: opts?.openDrawer ?? true,\n justAddedLineId: lineId,\n lines: [...state.lines, line],\n }\n }),\n\n setQuantity: (lineId, qty) =>\n set((state) => {\n if (qty <= 0) return { lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) }\n return {\n lines: state.lines.map((l) =>\n (l.lineId ?? l.productId) === lineId\n ? { ...l, quantity: Math.min(qty, l.maxQuantity || Infinity) }\n : l,\n ),\n }\n }),\n\n removeItem: (lineId) =>\n set((state) => ({ lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) })),\n\n applyDiscount: (code, percent, options) => set({\n discountCode: code,\n discountPercent: percent,\n discountFreeShipping: options?.freeShipping === true,\n }),\n clearDiscount: () => set({ discountCode: null, discountPercent: 0, discountFreeShipping: false }),\n clear: () => set({ lines: [], discountCode: null, discountPercent: 0, discountFreeShipping: false }),\n\n repriceForMarket: () =>\n set((state) => {\n const market = useMarketStore.getState()\n let changed = false\n const lines = state.lines.flatMap((line) => {\n const price = marketUnitPrice(market, line.productId, line.variantId, line.basePrice ?? line.unitPrice)\n if (price == null) {\n changed = true\n return []\n }\n if (price !== line.unitPrice) changed = true\n return [{ ...line, unitPrice: price }]\n })\n return changed ? { lines } : state\n }),\n openDrawer: () => set({ isOpen: true }),\n closeDrawer: () => set({ isOpen: false, justAddedLineId: null }),\n\n reconcile: async (resolve) => {\n const lines = get().lines\n if (lines.length === 0) return\n const keep = await Promise.all(\n lines.map((line) => resolve(line).catch(() => true)),\n )\n const kept = lines.filter((_, i) => keep[i])\n if (kept.length !== lines.length) set({ lines: kept })\n },\n }),\n {\n name: 'fayz.storefront.cart.v1',\n partialize: (state) => ({\n lines: state.lines,\n discountCode: state.discountCode,\n discountPercent: state.discountPercent,\n discountFreeShipping: state.discountFreeShipping,\n }),\n },\n ),\n)\n\n// ---------------------------------------------------------------------------\n// Money selectors — the single place cart math happens. Checkout passes these\n// exact values to createOrder so drawer totals always match order totals.\n// ---------------------------------------------------------------------------\n\nexport const selectCount = (s: Pick<CartState, 'lines'>): number =>\n s.lines.reduce((n, l) => n + l.quantity, 0)\n\nexport const selectSubtotal = (s: Pick<CartState, 'lines'>): number =>\n roundCents(s.lines.reduce((sum, l) => sum + l.unitPrice * l.quantity, 0))\n\nexport const selectDiscountTotal = (s: Pick<CartState, 'lines' | 'discountPercent'>): number =>\n roundCents(selectSubtotal(s) * (s.discountPercent / 100))\n\n/**\n * Freight to display.\n *\n * When the shopper has given a CEP and the store quoted it, that quote wins —\n * it came from the same shipping_zones rows shop_place_order will charge from.\n * Otherwise this falls back to the store-wide rate in config, which is what\n * every storefront did before zones existed.\n *\n * The subtotal is PRE-discount on both sides of this. That is 0017's rule, and\n * the quote is requested against the same number, so a coupon can never make\n * the cart and the order disagree.\n *\n * Read through getState() rather than a hook because this is a plain selector\n * called from several screens; components that render the value subscribe to\n * useDeliveryStore themselves so a fresh quote re-renders them.\n */\n/**\n * Whether anything in this cart travels.\n *\n * A line added before FAY-1407 has no flag and counts as physical: a cart of\n * real goods that suddenly ships for free is a worse failure than a download\n * that shows a delivery box.\n */\nexport const selectRequiresShipping = (s: Pick<CartState, 'lines'>): boolean =>\n s.lines.some((l) => l.requiresShipping !== false)\n\nexport type ShippingCart = Pick<CartState, 'lines'> & Partial<Pick<CartState, 'discountFreeShipping'>>\n\nexport const selectShipping = (\n s: ShippingCart,\n cfg: ResolvedStorefrontConfig,\n): number => {\n if (s.lines.length === 0) return 0\n // Nothing here is delivered. Not \"free delivery\" — no delivery, so neither\n // the quote nor the store-wide flat rate applies. Without this a cart of\n // e-books was charged the config's flatRate for a parcel that never exists.\n if (!selectRequiresShipping(s)) return 0\n // A free_shipping coupon. shop_place_order zeroes freight the same way and\n // does not even consult the zones (0017:178), so the quote below would show\n // a number the order will never charge.\n if (s.discountFreeShipping) return 0\n const subtotal = selectSubtotal(s)\n\n const quoted = selectQuotedShipping(useDeliveryStore.getState(), subtotal)\n if (quoted != null) return quoted\n\n if (cfg.shipping.freeAbove != null && subtotal >= cfg.shipping.freeAbove) return 0\n return cfg.shipping.flatRate\n}\n\nexport const selectTotal = (\n s: Pick<CartState, 'lines' | 'discountPercent'> & Partial<Pick<CartState, 'discountFreeShipping'>>,\n cfg: ResolvedStorefrontConfig,\n): number =>\n roundCents(selectSubtotal(s) - selectDiscountTotal(s) + selectShipping(s, cfg))\n"]}
@@ -1,5 +1,5 @@
1
- import { matchContentPage } from './chunk-BKO2AQ3Q.js';
2
- import { matchPath, resolveConfig, currentStaticRenderPass } from './chunk-GVZ2SAOI.js';
1
+ import { matchContentPage } from './chunk-SLJ4BRXD.js';
2
+ import { matchPath, resolveConfig, currentStaticRenderPass } from './chunk-PSDR5TZD.js';
3
3
  import { breadcrumbJsonLd, dataNeedKey, seoOrigin } from '@fayz-ai/core';
4
4
  import { imageVariantUrl } from '@fayz-ai/shop';
5
5
 
@@ -230,5 +230,5 @@ function menuDataNeeds() {
230
230
  }
231
231
 
232
232
  export { MENU_DATA_NEEDS, isKnownPath, isPublicPath, menuDataNeeds, menuJsonLd, menuSeo, pageSeo, primaryImageUrl, productJsonLd, productSeo, resolveStorefrontRoute, storefrontPaths };
233
- //# sourceMappingURL=chunk-45R7CIEA.js.map
234
- //# sourceMappingURL=chunk-45R7CIEA.js.map
233
+ //# sourceMappingURL=chunk-CE4U65TZ.js.map
234
+ //# sourceMappingURL=chunk-CE4U65TZ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/seo.ts","../src/app/serving.ts","../src/data/menu-needs.ts"],"names":[],"mappings":"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","file":"chunk-45R7CIEA.js","sourcesContent":["import { breadcrumbJsonLd, seoOrigin } from '@fayz-ai/core'\nimport { currentStaticRenderPass } from '../app/static-render'\nimport type { Category, Product } from '@fayz-ai/shop/types'\nimport { imageVariantUrl } from '@fayz-ai/shop'\nimport type { ResolvedStorefrontConfig } from '../document/config'\nimport type { StaticHeadInput } from '../app/static-render'\n\n// ---------------------------------------------------------------------------\n// What a storefront route should tell a crawler about itself.\n//\n// Pure builders returning a head declaration, so the page that knows what it is\n// rendering also declares its own SEO — rather than a renderer re-deriving the\n// routing table on the server to guess. Same reason `useStorefrontHead` reports\n// the title instead of letting `renderStore` infer it.\n//\n// Absolute URLs need an origin the store does not know at build time. Callers\n// pass one explicitly (a server render knows the request host); in a browser it\n// falls back to the live origin. Without either, canonical and OG URLs are\n// omitted rather than emitted relative, because a relative canonical is ignored\n// by search engines and a relative og:image renders as a broken share.\n// ---------------------------------------------------------------------------\n\nexport interface StorefrontSeoContext {\n config: ResolvedStorefrontConfig\n /** In-app path, e.g. '/product/pork-ribs'. */\n path: string\n /** Absolute origin, e.g. 'https://loja.example.com'. */\n origin?: string\n}\n\nfunction absolute(ctx: StorefrontSeoContext, path = ctx.path): string | undefined {\n // Explicit wins, then the origin the static render was told about, then the\n // live browser origin. A page never has to know which of the three it is in.\n const origin = (ctx.origin ?? currentStaticRenderPass()?.origin ?? seoOrigin()).replace(/\\/$/, '')\n if (!origin) return undefined\n return `${origin}${path.startsWith('/') ? path : `/${path}`}`\n}\n\n/** Primary image, falling back to the first — how product cards pick one. */\nexport function primaryImageUrl(product: Product): string | undefined {\n return (product.images?.find((i) => i.isPrimary) ?? product.images?.[0])?.url\n}\n\n/**\n * The primary image as a share card wants it: 1200 px wide when the store\n * serves variants, so a WhatsApp/OG scraper does not pull the 4000 px\n * original — and the same URL for every scraper, so it is cached once.\n */\nfunction shareImageUrl(product: Product, ctx: StorefrontSeoContext): string | undefined {\n const url = primaryImageUrl(product)\n if (!url) return undefined\n return ctx.config.imageLoading.transform === 'supabase' ? imageVariantUrl(url, { width: 1200, quality: 82 }) : url\n}\n\n/**\n * schema.org Product. Availability is derived from inventory rather than\n * declared, because a rich result advertising an in-stock product that is not\n * is worse than no rich result.\n */\nexport function productJsonLd(\n product: Product,\n ctx: StorefrontSeoContext,\n): Record<string, unknown> {\n const url = absolute(ctx)\n const image = shareImageUrl(product, ctx)\n return {\n '@context': 'https://schema.org',\n '@type': 'Product',\n name: product.name,\n ...(product.description ? { description: product.description } : {}),\n ...(product.sku ? { sku: product.sku } : {}),\n ...(image ? { image: [image] } : {}),\n offers: {\n '@type': 'Offer',\n ...(url ? { url } : {}),\n price: product.price,\n priceCurrency: product.currency ?? ctx.config.currency,\n availability:\n (product.inventoryCount ?? 0) > 0\n ? 'https://schema.org/InStock'\n : 'https://schema.org/OutOfStock',\n },\n }\n}\n\n/** The head declaration for a product page. */\nexport function productSeo(product: Product, ctx: StorefrontSeoContext): StaticHeadInput {\n const url = absolute(ctx)\n const home = absolute(ctx, '/')\n const catalog = absolute(ctx, ctx.config.catalogPath)\n return {\n title: `${product.name} — ${ctx.config.name}`,\n description: product.description?.slice(0, 160),\n canonical: url,\n image: shareImageUrl(product, ctx),\n type: 'product',\n jsonLd: [\n productJsonLd(product, ctx),\n ...(home && catalog && url\n ? [\n breadcrumbJsonLd([\n { name: ctx.config.name, url: home },\n { name: 'Loja', url: catalog },\n { name: product.name, url },\n ]),\n ]\n : []),\n ],\n }\n}\n\n/** The head declaration for any non-product route: canonical only. */\nexport function pageSeo(\n ctx: StorefrontSeoContext,\n input: { title: string; description?: string | null },\n): StaticHeadInput {\n return { ...input, canonical: absolute(ctx), type: 'website' }\n}\n\n/**\n * Who serves the menu, as the store knows itself. Everything optional: a\n * field the store has not filled is left out of the JSON-LD rather than\n * guessed, because a wrong phone number in a rich result is worse than none.\n */\nexport interface MenuBusiness {\n /** schema.org type. 'Restaurant' unless the house is better described by\n * another FoodEstablishment subtype (e.g. 'FastFoodRestaurant', 'Bakery'). */\n type?: string\n description?: string\n telephone?: string\n email?: string\n /** Absolute URL. */\n logo?: string\n /** Absolute URL; the cover photo. */\n image?: string\n servesCuisine?: string | string[]\n priceRange?: string\n address?: { streetAddress?: string; locality?: string; region?: string; postalCode?: string; country?: string }\n /** Cities or neighbourhoods delivered to, by name. */\n areaServed?: string[]\n /** schema.org openingHours, e.g. ['Mo-Fr 11:00-22:00']. */\n openingHours?: string[]\n sameAs?: string[]\n}\n\n/** The menu as the shopper sees it: category order, each dish under its\n * category, the uncategorised ones last (same grouping as `MenuPage`). */\nfunction menuSections(products: Product[], categories: Category[]) {\n const byCategory = new Map<string, Product[]>()\n const loose: Product[] = []\n for (const p of products) {\n const key = p.categoryId ?? p.categoryName ?? ''\n if (!key) { loose.push(p); continue }\n byCategory.set(key, [...(byCategory.get(key) ?? []), p])\n }\n const sections = categories\n .map((c) => ({ name: c.name, description: c.description, products: byCategory.get(c.id) ?? byCategory.get(c.name) ?? [] }))\n .filter((s) => s.products.length > 0)\n if (loose.length) sections.push({ name: 'Outros', description: null, products: loose })\n if (!sections.length && products.length) return [{ name: 'Cardápio', description: null, products }]\n return sections\n}\n\n/**\n * schema.org Restaurant with its Menu — what lets a search engine answer\n * \"delivery de costela defumada\" with this house, and read every dish and\n * price without running the page's JavaScript.\n *\n * Each dish links to its own product page, where the full Product entity\n * lives; here it is a MenuItem, which is what a dish on a menu is.\n */\nexport function menuJsonLd(\n input: { products: Product[]; categories: Category[]; business?: MenuBusiness },\n ctx: StorefrontSeoContext,\n): Record<string, unknown> {\n const url = absolute(ctx)\n const home = absolute(ctx, '/')\n const b = input.business ?? {}\n const currency = ctx.config.currency\n const address = b.address\n ? {\n '@type': 'PostalAddress',\n ...(b.address.streetAddress ? { streetAddress: b.address.streetAddress } : {}),\n ...(b.address.locality ? { addressLocality: b.address.locality } : {}),\n ...(b.address.region ? { addressRegion: b.address.region } : {}),\n ...(b.address.postalCode ? { postalCode: b.address.postalCode } : {}),\n addressCountry: b.address.country ?? 'BR',\n }\n : undefined\n return {\n '@context': 'https://schema.org',\n '@type': b.type ?? 'Restaurant',\n ...(home ? { '@id': `${home.replace(/\\/$/, '')}/#business` } : {}),\n name: ctx.config.name,\n ...(home ? { url: home } : {}),\n ...(b.description ? { description: b.description } : {}),\n ...(b.image ? { image: [b.image] } : {}),\n ...(b.logo ? { logo: b.logo } : {}),\n ...(b.telephone ? { telephone: b.telephone } : {}),\n ...(b.email ? { email: b.email } : {}),\n ...(b.servesCuisine ? { servesCuisine: b.servesCuisine } : {}),\n ...(b.priceRange ? { priceRange: b.priceRange } : {}),\n ...(address ? { address } : {}),\n ...(b.areaServed?.length ? { areaServed: b.areaServed.map((name) => ({ '@type': 'Place', name })) } : {}),\n ...(b.openingHours?.length ? { openingHours: b.openingHours } : {}),\n ...(b.sameAs?.length ? { sameAs: b.sameAs } : {}),\n ...(url ? { hasMenu: url } : {}),\n ...(url\n ? {\n potentialAction: {\n '@type': 'OrderAction',\n target: { '@type': 'EntryPoint', urlTemplate: url, actionPlatform: ['https://schema.org/DesktopWebPlatform', 'https://schema.org/MobileWebPlatform'] },\n deliveryMethod: 'http://purl.org/goodrelations/v1#DeliveryModeOwnFleet',\n },\n }\n : {}),\n menu: {\n '@type': 'Menu',\n name: `Cardápio — ${ctx.config.name}`,\n ...(url ? { url } : {}),\n inLanguage: 'pt-BR',\n hasMenuSection: menuSections(input.products, input.categories).map((section) => ({\n '@type': 'MenuSection',\n name: section.name,\n ...(section.description ? { description: section.description } : {}),\n hasMenuItem: section.products.map((p) => {\n const image = shareImageUrl(p, ctx)\n const itemUrl = absolute(ctx, `/product/${p.slug}`)\n return {\n '@type': 'MenuItem',\n name: p.name,\n ...(p.description ? { description: p.description.slice(0, 300) } : {}),\n ...(image ? { image } : {}),\n ...(itemUrl ? { url: itemUrl } : {}),\n offers: {\n '@type': 'Offer',\n price: p.price,\n priceCurrency: p.currency ?? currency,\n availability: (p.inventoryCount ?? 0) > 0 ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',\n },\n }\n }),\n })),\n },\n }\n}\n\n/**\n * The head declaration for the delivery menu: its own title and description\n * (the store passes copy written for the query it should answer), the\n * Restaurant + Menu entity, and a breadcrumb back to the home page.\n */\nexport function menuSeo(\n input: {\n products: Product[]\n categories: Category[]\n title?: string\n description?: string | null\n business?: MenuBusiness\n },\n ctx: StorefrontSeoContext,\n): StaticHeadInput {\n const url = absolute(ctx)\n const home = absolute(ctx, '/')\n const names = input.products.slice(0, 4).map((p) => p.name).join(', ')\n return {\n title: input.title ?? `Delivery ${ctx.config.name} — peça online`,\n description:\n (input.description ?? (names ? `Peça online: ${names} e mais. Cardápio completo com preços.` : undefined))?.slice(0, 160),\n canonical: url,\n image: input.business?.image,\n type: 'website',\n jsonLd: [\n menuJsonLd(input, ctx),\n ...(home && url\n ? [breadcrumbJsonLd([{ name: ctx.config.name, url: home }, { name: 'Delivery', url }])]\n : []),\n ],\n }\n}\n","import type { ShopProvider } from '@fayz-ai/shop/provider'\nimport { matchPath } from './router'\nimport { matchContentPage } from '../blocks/page-blocks'\nimport { resolveConfig } from '../document/config'\nimport type { StorefrontConfig, ResolvedStorefrontConfig } from '../document/config'\n\n// ---------------------------------------------------------------------------\n// How a store is served, once its pages have URLs of their own.\n//\n// Two questions a host has to answer that the shell cannot: which paths exist\n// at all (what to prerender, what to put in a sitemap), and which of them are\n// the same for every visitor (what a shared cache may hold). Both are\n// properties of the route, so they are decided here rather than by each host\n// re-deriving them — and the second one has a failure mode a CDN makes\n// invisible: cache a cart or an order confirmation once and it is served to the\n// next shopper.\n// ---------------------------------------------------------------------------\n\nexport type StorefrontRouteMatch =\n | { kind: 'custom'; route: NonNullable<ResolvedStorefrontConfig['routes']>[number]; params: Record<string, string> }\n | { kind: 'product'; params: Record<string, string> }\n | { kind: 'order'; params: Record<string, string> }\n | { kind: 'checkout' }\n | { kind: 'account' }\n | { kind: 'catalog' }\n | { kind: 'menu' }\n | { kind: 'searchResults' }\n | { kind: 'policy'; policy: 'privacy' | 'terms' | 'returns' }\n | { kind: 'content'; slug: string; params: Record<string, string> }\n | { kind: 'home' }\n | { kind: 'notFound' }\n\n/**\n * What a path means, resolved once.\n *\n * The shell renders from this, cacheability is derived from it, and a host\n * framework asks it whether a URL exists at all before choosing a status code.\n * Those three answering separately is how a page ends up rendered as one thing\n * and cached or statused as another.\n *\n * The query string is stripped first: it addresses state WITHIN a page, so\n * `/?utm_source=instagram` is the home page — the single most common shape of\n * inbound marketing link, and a 404 for it is a silent, expensive bug.\n */\nexport function resolveStorefrontRoute(\n config: StorefrontConfig | ResolvedStorefrontConfig,\n rawPath: string,\n): StorefrontRouteMatch {\n const resolved = ensureResolved(config)\n const path = rawPath.split('?')[0] || '/'\n\n for (const route of resolved.routes ?? []) {\n const params = matchPath(route.path, path)\n if (params) return { kind: 'custom', route, params }\n }\n\n const product = matchPath('/product/:slug', path)\n if (product?.slug) return { kind: 'product', params: product }\n\n const order = matchPath('/order/:id', path)\n if (order?.id) return { kind: 'order', params: order }\n\n // Matched regardless of the feature flag: a disabled checkout still owns its\n // URL rather than falling through to an unrelated page.\n if (matchPath('/checkout', path)) return { kind: 'checkout' }\n if (matchPath('/account', path)) return { kind: 'account' }\n if (matchPath('/catalog', path)) return { kind: 'catalog' }\n // Só existe no modo delivery, e por isso é testado contra `resolved.delivery`\n // e não contra o literal '/menu': fora do modo, /menu é um 404 de verdade em\n // vez de uma página vazia — que é a diferença entre uma rota que não existe e\n // uma rota quebrada.\n if (resolved.delivery && matchPath(resolved.delivery.menuPath, path)) return { kind: 'menu' }\n if (resolved.search.mode === 'overlay' && matchPath(resolved.search.resultsPath, path)) {\n return { kind: 'searchResults' }\n }\n if (matchPath('/privacy', path)) return { kind: 'policy', policy: 'privacy' }\n if (matchPath('/terms', path)) return { kind: 'policy', policy: 'terms' }\n if (matchPath('/refunds', path)) return { kind: 'policy', policy: 'returns' }\n\n const content = matchContentPage(resolved.pages, path)\n if (content) return { kind: 'content', slug: content.slug, params: content.params }\n\n if (path === '/' || path === '') return { kind: 'home' }\n return { kind: 'notFound' }\n}\n\n/** Whether a URL exists at all — what a host needs before choosing a status. */\nexport function isKnownPath(\n config: StorefrontConfig | ResolvedStorefrontConfig,\n path: string,\n): boolean {\n return resolveStorefrontRoute(config, path).kind !== 'notFound'\n}\n\n/** Paths whose HTML is per-shopper and must never enter a shared cache. */\nconst PRIVATE_PATTERNS = ['/checkout', '/account', '/order/:id'] as const\n\n/** Paths the SDK serves that exist without knowing any product. The delivery\n * menu is added from the store's own `delivery.menuPath` — see `storefrontPaths`. */\nconst STATIC_PATTERNS = ['/', '/catalog', '/privacy', '/terms', '/refunds'] as const\n\nfunction ensureResolved(config: StorefrontConfig | ResolvedStorefrontConfig): ResolvedStorefrontConfig {\n return 'features' in config && 'pages' in config\n ? (config as ResolvedStorefrontConfig)\n : resolveConfig(config)\n}\n\n/**\n * Whether `path`'s HTML is identical for every visitor.\n *\n * Conservative by construction: a store's own route is private unless it says\n * otherwise, because guessing \"public\" is the direction that leaks one\n * shopper's page to another.\n */\nexport function isPublicPath(\n config: StorefrontConfig | ResolvedStorefrontConfig,\n path: string,\n): boolean {\n const match = resolveStorefrontRoute(config, path)\n switch (match.kind) {\n case 'checkout':\n case 'account':\n case 'order':\n return false\n case 'custom':\n return (\n match.route.kind !== 'checkout' &&\n match.route.kind !== 'account' &&\n match.route.chrome !== 'focused'\n )\n default:\n return true\n }\n}\n\n/**\n * Every path worth prerendering, and the same list a sitemap should carry.\n *\n * Product URLs come from the catalogue rather than the route table, so the\n * provider is asked rather than guessed at. Custom routes with parameters are\n * skipped: the SDK cannot know what values a store's own route accepts, and\n * emitting `/colecao/:slug` into a sitemap is worse than omitting it.\n */\nexport async function storefrontPaths(input: {\n config: StorefrontConfig | ResolvedStorefrontConfig\n provider: ShopProvider\n /** Include per-shopper routes. Off by default — they are not prerenderable. */\n includePrivate?: boolean\n}): Promise<string[]> {\n const resolved = ensureResolved(input.config)\n const paths = [...STATIC_PATTERNS] as string[]\n // The menu is the same for every visitor — what changes per shopper (address,\n // cart, open right now) resolves in the browser after hydration. It is listed\n // at the store's own path: a store whose menu lives at /delivery had /menu in\n // its sitemap and its real ordering page in none.\n if (resolved.delivery) paths.push(resolved.delivery.menuPath)\n\n for (const route of resolved.routes ?? []) {\n if (!route.path.includes(':')) paths.push(route.path)\n }\n\n const products = await input.provider.listProducts({ status: 'active' })\n for (const product of products) paths.push(`/product/${product.slug}`)\n\n const unique = Array.from(new Set(paths))\n return input.includePrivate ? unique : unique.filter((p) => isPublicPath(resolved, p))\n}\n","import { dataNeedKey } from '@fayz-ai/core'\n\n/**\n * The reads the delivery menu makes, named once so a server host can resolve\n * them before render. The menu is not a block tree, so nothing collects these\n * for it — a host that does not seed them sends a menu with no dishes in the\n * HTML, which is the page a crawler indexes.\n *\n * Its own module, free of React, because a host's route loader imports it on\n * every request.\n */\nexport const MENU_DATA_NEEDS = {\n products: { loader: 'products.list', params: {} },\n categories: { loader: 'categories.list', params: {} },\n featured: { loader: 'products.featured', params: {} },\n} as const\n\n/** The menu's data needs, keyed exactly as its `useLoader` calls will ask. */\nexport function menuDataNeeds(): Array<{ key: string; loader: string; params: Record<string, unknown> }> {\n return Object.values(MENU_DATA_NEEDS).map(({ loader, params }) => ({ key: dataNeedKey(loader, params), loader, params }))\n}\n"]}
1
+ {"version":3,"sources":["../src/lib/seo.ts","../src/app/serving.ts","../src/data/menu-needs.ts"],"names":[],"mappings":"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","file":"chunk-CE4U65TZ.js","sourcesContent":["import { breadcrumbJsonLd, seoOrigin } from '@fayz-ai/core'\nimport { currentStaticRenderPass } from '../app/static-render'\nimport type { Category, Product } from '@fayz-ai/shop/types'\nimport { imageVariantUrl } from '@fayz-ai/shop'\nimport type { ResolvedStorefrontConfig } from '../document/config'\nimport type { StaticHeadInput } from '../app/static-render'\n\n// ---------------------------------------------------------------------------\n// What a storefront route should tell a crawler about itself.\n//\n// Pure builders returning a head declaration, so the page that knows what it is\n// rendering also declares its own SEO — rather than a renderer re-deriving the\n// routing table on the server to guess. Same reason `useStorefrontHead` reports\n// the title instead of letting `renderStore` infer it.\n//\n// Absolute URLs need an origin the store does not know at build time. Callers\n// pass one explicitly (a server render knows the request host); in a browser it\n// falls back to the live origin. Without either, canonical and OG URLs are\n// omitted rather than emitted relative, because a relative canonical is ignored\n// by search engines and a relative og:image renders as a broken share.\n// ---------------------------------------------------------------------------\n\nexport interface StorefrontSeoContext {\n config: ResolvedStorefrontConfig\n /** In-app path, e.g. '/product/pork-ribs'. */\n path: string\n /** Absolute origin, e.g. 'https://loja.example.com'. */\n origin?: string\n}\n\nfunction absolute(ctx: StorefrontSeoContext, path = ctx.path): string | undefined {\n // Explicit wins, then the origin the static render was told about, then the\n // live browser origin. A page never has to know which of the three it is in.\n const origin = (ctx.origin ?? currentStaticRenderPass()?.origin ?? seoOrigin()).replace(/\\/$/, '')\n if (!origin) return undefined\n return `${origin}${path.startsWith('/') ? path : `/${path}`}`\n}\n\n/** Primary image, falling back to the first — how product cards pick one. */\nexport function primaryImageUrl(product: Product): string | undefined {\n return (product.images?.find((i) => i.isPrimary) ?? product.images?.[0])?.url\n}\n\n/**\n * The primary image as a share card wants it: 1200 px wide when the store\n * serves variants, so a WhatsApp/OG scraper does not pull the 4000 px\n * original — and the same URL for every scraper, so it is cached once.\n */\nfunction shareImageUrl(product: Product, ctx: StorefrontSeoContext): string | undefined {\n const url = primaryImageUrl(product)\n if (!url) return undefined\n return ctx.config.imageLoading.transform === 'supabase' ? imageVariantUrl(url, { width: 1200, quality: 82 }) : url\n}\n\n/**\n * schema.org Product. Availability is derived from inventory rather than\n * declared, because a rich result advertising an in-stock product that is not\n * is worse than no rich result.\n */\nexport function productJsonLd(\n product: Product,\n ctx: StorefrontSeoContext,\n): Record<string, unknown> {\n const url = absolute(ctx)\n const image = shareImageUrl(product, ctx)\n return {\n '@context': 'https://schema.org',\n '@type': 'Product',\n name: product.name,\n ...(product.description ? { description: product.description } : {}),\n ...(product.sku ? { sku: product.sku } : {}),\n ...(image ? { image: [image] } : {}),\n offers: {\n '@type': 'Offer',\n ...(url ? { url } : {}),\n price: product.price,\n priceCurrency: product.currency ?? ctx.config.currency,\n availability:\n (product.inventoryCount ?? 0) > 0\n ? 'https://schema.org/InStock'\n : 'https://schema.org/OutOfStock',\n },\n }\n}\n\n/** The head declaration for a product page. */\nexport function productSeo(product: Product, ctx: StorefrontSeoContext): StaticHeadInput {\n const url = absolute(ctx)\n const home = absolute(ctx, '/')\n const catalog = absolute(ctx, ctx.config.catalogPath)\n return {\n title: `${product.name} — ${ctx.config.name}`,\n description: product.description?.slice(0, 160),\n canonical: url,\n image: shareImageUrl(product, ctx),\n type: 'product',\n jsonLd: [\n productJsonLd(product, ctx),\n ...(home && catalog && url\n ? [\n breadcrumbJsonLd([\n { name: ctx.config.name, url: home },\n { name: 'Loja', url: catalog },\n { name: product.name, url },\n ]),\n ]\n : []),\n ],\n }\n}\n\n/** The head declaration for any non-product route: canonical only. */\nexport function pageSeo(\n ctx: StorefrontSeoContext,\n input: { title: string; description?: string | null },\n): StaticHeadInput {\n return { ...input, canonical: absolute(ctx), type: 'website' }\n}\n\n/**\n * Who serves the menu, as the store knows itself. Everything optional: a\n * field the store has not filled is left out of the JSON-LD rather than\n * guessed, because a wrong phone number in a rich result is worse than none.\n */\nexport interface MenuBusiness {\n /** schema.org type. 'Restaurant' unless the house is better described by\n * another FoodEstablishment subtype (e.g. 'FastFoodRestaurant', 'Bakery'). */\n type?: string\n description?: string\n telephone?: string\n email?: string\n /** Absolute URL. */\n logo?: string\n /** Absolute URL; the cover photo. */\n image?: string\n servesCuisine?: string | string[]\n priceRange?: string\n address?: { streetAddress?: string; locality?: string; region?: string; postalCode?: string; country?: string }\n /** Cities or neighbourhoods delivered to, by name. */\n areaServed?: string[]\n /** schema.org openingHours, e.g. ['Mo-Fr 11:00-22:00']. */\n openingHours?: string[]\n sameAs?: string[]\n}\n\n/** The menu as the shopper sees it: category order, each dish under its\n * category, the uncategorised ones last (same grouping as `MenuPage`). */\nfunction menuSections(products: Product[], categories: Category[]) {\n const byCategory = new Map<string, Product[]>()\n const loose: Product[] = []\n for (const p of products) {\n const key = p.categoryId ?? p.categoryName ?? ''\n if (!key) { loose.push(p); continue }\n byCategory.set(key, [...(byCategory.get(key) ?? []), p])\n }\n const sections = categories\n .map((c) => ({ name: c.name, description: c.description, products: byCategory.get(c.id) ?? byCategory.get(c.name) ?? [] }))\n .filter((s) => s.products.length > 0)\n if (loose.length) sections.push({ name: 'Outros', description: null, products: loose })\n if (!sections.length && products.length) return [{ name: 'Cardápio', description: null, products }]\n return sections\n}\n\n/**\n * schema.org Restaurant with its Menu — what lets a search engine answer\n * \"delivery de costela defumada\" with this house, and read every dish and\n * price without running the page's JavaScript.\n *\n * Each dish links to its own product page, where the full Product entity\n * lives; here it is a MenuItem, which is what a dish on a menu is.\n */\nexport function menuJsonLd(\n input: { products: Product[]; categories: Category[]; business?: MenuBusiness },\n ctx: StorefrontSeoContext,\n): Record<string, unknown> {\n const url = absolute(ctx)\n const home = absolute(ctx, '/')\n const b = input.business ?? {}\n const currency = ctx.config.currency\n const address = b.address\n ? {\n '@type': 'PostalAddress',\n ...(b.address.streetAddress ? { streetAddress: b.address.streetAddress } : {}),\n ...(b.address.locality ? { addressLocality: b.address.locality } : {}),\n ...(b.address.region ? { addressRegion: b.address.region } : {}),\n ...(b.address.postalCode ? { postalCode: b.address.postalCode } : {}),\n addressCountry: b.address.country ?? 'BR',\n }\n : undefined\n return {\n '@context': 'https://schema.org',\n '@type': b.type ?? 'Restaurant',\n ...(home ? { '@id': `${home.replace(/\\/$/, '')}/#business` } : {}),\n name: ctx.config.name,\n ...(home ? { url: home } : {}),\n ...(b.description ? { description: b.description } : {}),\n ...(b.image ? { image: [b.image] } : {}),\n ...(b.logo ? { logo: b.logo } : {}),\n ...(b.telephone ? { telephone: b.telephone } : {}),\n ...(b.email ? { email: b.email } : {}),\n ...(b.servesCuisine ? { servesCuisine: b.servesCuisine } : {}),\n ...(b.priceRange ? { priceRange: b.priceRange } : {}),\n ...(address ? { address } : {}),\n ...(b.areaServed?.length ? { areaServed: b.areaServed.map((name) => ({ '@type': 'Place', name })) } : {}),\n ...(b.openingHours?.length ? { openingHours: b.openingHours } : {}),\n ...(b.sameAs?.length ? { sameAs: b.sameAs } : {}),\n ...(url ? { hasMenu: url } : {}),\n ...(url\n ? {\n potentialAction: {\n '@type': 'OrderAction',\n target: { '@type': 'EntryPoint', urlTemplate: url, actionPlatform: ['https://schema.org/DesktopWebPlatform', 'https://schema.org/MobileWebPlatform'] },\n deliveryMethod: 'http://purl.org/goodrelations/v1#DeliveryModeOwnFleet',\n },\n }\n : {}),\n menu: {\n '@type': 'Menu',\n name: `Cardápio — ${ctx.config.name}`,\n ...(url ? { url } : {}),\n inLanguage: 'pt-BR',\n hasMenuSection: menuSections(input.products, input.categories).map((section) => ({\n '@type': 'MenuSection',\n name: section.name,\n ...(section.description ? { description: section.description } : {}),\n hasMenuItem: section.products.map((p) => {\n const image = shareImageUrl(p, ctx)\n const itemUrl = absolute(ctx, `/product/${p.slug}`)\n return {\n '@type': 'MenuItem',\n name: p.name,\n ...(p.description ? { description: p.description.slice(0, 300) } : {}),\n ...(image ? { image } : {}),\n ...(itemUrl ? { url: itemUrl } : {}),\n offers: {\n '@type': 'Offer',\n price: p.price,\n priceCurrency: p.currency ?? currency,\n availability: (p.inventoryCount ?? 0) > 0 ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',\n },\n }\n }),\n })),\n },\n }\n}\n\n/**\n * The head declaration for the delivery menu: its own title and description\n * (the store passes copy written for the query it should answer), the\n * Restaurant + Menu entity, and a breadcrumb back to the home page.\n */\nexport function menuSeo(\n input: {\n products: Product[]\n categories: Category[]\n title?: string\n description?: string | null\n business?: MenuBusiness\n },\n ctx: StorefrontSeoContext,\n): StaticHeadInput {\n const url = absolute(ctx)\n const home = absolute(ctx, '/')\n const names = input.products.slice(0, 4).map((p) => p.name).join(', ')\n return {\n title: input.title ?? `Delivery ${ctx.config.name} — peça online`,\n description:\n (input.description ?? (names ? `Peça online: ${names} e mais. Cardápio completo com preços.` : undefined))?.slice(0, 160),\n canonical: url,\n image: input.business?.image,\n type: 'website',\n jsonLd: [\n menuJsonLd(input, ctx),\n ...(home && url\n ? [breadcrumbJsonLd([{ name: ctx.config.name, url: home }, { name: 'Delivery', url }])]\n : []),\n ],\n }\n}\n","import type { ShopProvider } from '@fayz-ai/shop/provider'\nimport { matchPath } from './router'\nimport { matchContentPage } from '../blocks/page-blocks'\nimport { resolveConfig } from '../document/config'\nimport type { StorefrontConfig, ResolvedStorefrontConfig } from '../document/config'\n\n// ---------------------------------------------------------------------------\n// How a store is served, once its pages have URLs of their own.\n//\n// Two questions a host has to answer that the shell cannot: which paths exist\n// at all (what to prerender, what to put in a sitemap), and which of them are\n// the same for every visitor (what a shared cache may hold). Both are\n// properties of the route, so they are decided here rather than by each host\n// re-deriving them — and the second one has a failure mode a CDN makes\n// invisible: cache a cart or an order confirmation once and it is served to the\n// next shopper.\n// ---------------------------------------------------------------------------\n\nexport type StorefrontRouteMatch =\n | { kind: 'custom'; route: NonNullable<ResolvedStorefrontConfig['routes']>[number]; params: Record<string, string> }\n | { kind: 'product'; params: Record<string, string> }\n | { kind: 'order'; params: Record<string, string> }\n | { kind: 'checkout' }\n | { kind: 'account' }\n | { kind: 'catalog' }\n | { kind: 'menu' }\n | { kind: 'searchResults' }\n | { kind: 'policy'; policy: 'privacy' | 'terms' | 'returns' }\n | { kind: 'content'; slug: string; params: Record<string, string> }\n | { kind: 'home' }\n | { kind: 'notFound' }\n\n/**\n * What a path means, resolved once.\n *\n * The shell renders from this, cacheability is derived from it, and a host\n * framework asks it whether a URL exists at all before choosing a status code.\n * Those three answering separately is how a page ends up rendered as one thing\n * and cached or statused as another.\n *\n * The query string is stripped first: it addresses state WITHIN a page, so\n * `/?utm_source=instagram` is the home page — the single most common shape of\n * inbound marketing link, and a 404 for it is a silent, expensive bug.\n */\nexport function resolveStorefrontRoute(\n config: StorefrontConfig | ResolvedStorefrontConfig,\n rawPath: string,\n): StorefrontRouteMatch {\n const resolved = ensureResolved(config)\n const path = rawPath.split('?')[0] || '/'\n\n for (const route of resolved.routes ?? []) {\n const params = matchPath(route.path, path)\n if (params) return { kind: 'custom', route, params }\n }\n\n const product = matchPath('/product/:slug', path)\n if (product?.slug) return { kind: 'product', params: product }\n\n const order = matchPath('/order/:id', path)\n if (order?.id) return { kind: 'order', params: order }\n\n // Matched regardless of the feature flag: a disabled checkout still owns its\n // URL rather than falling through to an unrelated page.\n if (matchPath('/checkout', path)) return { kind: 'checkout' }\n if (matchPath('/account', path)) return { kind: 'account' }\n if (matchPath('/catalog', path)) return { kind: 'catalog' }\n // Só existe no modo delivery, e por isso é testado contra `resolved.delivery`\n // e não contra o literal '/menu': fora do modo, /menu é um 404 de verdade em\n // vez de uma página vazia — que é a diferença entre uma rota que não existe e\n // uma rota quebrada.\n if (resolved.delivery && matchPath(resolved.delivery.menuPath, path)) return { kind: 'menu' }\n if (resolved.search.mode === 'overlay' && matchPath(resolved.search.resultsPath, path)) {\n return { kind: 'searchResults' }\n }\n if (matchPath('/privacy', path)) return { kind: 'policy', policy: 'privacy' }\n if (matchPath('/terms', path)) return { kind: 'policy', policy: 'terms' }\n if (matchPath('/refunds', path)) return { kind: 'policy', policy: 'returns' }\n\n const content = matchContentPage(resolved.pages, path)\n if (content) return { kind: 'content', slug: content.slug, params: content.params }\n\n if (path === '/' || path === '') return { kind: 'home' }\n return { kind: 'notFound' }\n}\n\n/** Whether a URL exists at all — what a host needs before choosing a status. */\nexport function isKnownPath(\n config: StorefrontConfig | ResolvedStorefrontConfig,\n path: string,\n): boolean {\n return resolveStorefrontRoute(config, path).kind !== 'notFound'\n}\n\n/** Paths whose HTML is per-shopper and must never enter a shared cache. */\nconst PRIVATE_PATTERNS = ['/checkout', '/account', '/order/:id'] as const\n\n/** Paths the SDK serves that exist without knowing any product. The delivery\n * menu is added from the store's own `delivery.menuPath` — see `storefrontPaths`. */\nconst STATIC_PATTERNS = ['/', '/catalog', '/privacy', '/terms', '/refunds'] as const\n\nfunction ensureResolved(config: StorefrontConfig | ResolvedStorefrontConfig): ResolvedStorefrontConfig {\n return 'features' in config && 'pages' in config\n ? (config as ResolvedStorefrontConfig)\n : resolveConfig(config)\n}\n\n/**\n * Whether `path`'s HTML is identical for every visitor.\n *\n * Conservative by construction: a store's own route is private unless it says\n * otherwise, because guessing \"public\" is the direction that leaks one\n * shopper's page to another.\n */\nexport function isPublicPath(\n config: StorefrontConfig | ResolvedStorefrontConfig,\n path: string,\n): boolean {\n const match = resolveStorefrontRoute(config, path)\n switch (match.kind) {\n case 'checkout':\n case 'account':\n case 'order':\n return false\n case 'custom':\n return (\n match.route.kind !== 'checkout' &&\n match.route.kind !== 'account' &&\n match.route.chrome !== 'focused'\n )\n default:\n return true\n }\n}\n\n/**\n * Every path worth prerendering, and the same list a sitemap should carry.\n *\n * Product URLs come from the catalogue rather than the route table, so the\n * provider is asked rather than guessed at. Custom routes with parameters are\n * skipped: the SDK cannot know what values a store's own route accepts, and\n * emitting `/colecao/:slug` into a sitemap is worse than omitting it.\n */\nexport async function storefrontPaths(input: {\n config: StorefrontConfig | ResolvedStorefrontConfig\n provider: ShopProvider\n /** Include per-shopper routes. Off by default — they are not prerenderable. */\n includePrivate?: boolean\n}): Promise<string[]> {\n const resolved = ensureResolved(input.config)\n const paths = [...STATIC_PATTERNS] as string[]\n // The menu is the same for every visitor — what changes per shopper (address,\n // cart, open right now) resolves in the browser after hydration. It is listed\n // at the store's own path: a store whose menu lives at /delivery had /menu in\n // its sitemap and its real ordering page in none.\n if (resolved.delivery) paths.push(resolved.delivery.menuPath)\n\n for (const route of resolved.routes ?? []) {\n if (!route.path.includes(':')) paths.push(route.path)\n }\n\n const products = await input.provider.listProducts({ status: 'active' })\n for (const product of products) paths.push(`/product/${product.slug}`)\n\n const unique = Array.from(new Set(paths))\n return input.includePrivate ? unique : unique.filter((p) => isPublicPath(resolved, p))\n}\n","import { dataNeedKey } from '@fayz-ai/core'\n\n/**\n * The reads the delivery menu makes, named once so a server host can resolve\n * them before render. The menu is not a block tree, so nothing collects these\n * for it — a host that does not seed them sends a menu with no dishes in the\n * HTML, which is the page a crawler indexes.\n *\n * Its own module, free of React, because a host's route loader imports it on\n * every request.\n */\nexport const MENU_DATA_NEEDS = {\n products: { loader: 'products.list', params: {} },\n categories: { loader: 'categories.list', params: {} },\n featured: { loader: 'products.featured', params: {} },\n} as const\n\n/** The menu's data needs, keyed exactly as its `useLoader` calls will ask. */\nexport function menuDataNeeds(): Array<{ key: string; loader: string; params: Record<string, unknown> }> {\n return Object.values(MENU_DATA_NEEDS).map(({ loader, params }) => ({ key: dataNeedKey(loader, params), loader, params }))\n}\n"]}
@@ -1,8 +1,7 @@
1
- import { useStorefrontConfigOptional, currentStaticRenderPass } from './chunk-GVZ2SAOI.js';
1
+ import { useStorefrontConfigOptional, currentStaticRenderPass } from './chunk-PSDR5TZD.js';
2
2
  import { create } from 'zustand';
3
3
  import { persist } from 'zustand/middleware';
4
4
  import { createMockAuthAdapter } from '@fayz-ai/auth';
5
- import { createAuthRuntime } from '@fayz-ai/auth/lib/runtime';
6
5
  import { getShopProvider } from '@fayz-ai/shop/runtime';
7
6
  import { setShopAccessTokenResolver } from '@fayz-ai/sdk/shop';
8
7
  import React, { useEffect } from 'react';
@@ -48,19 +47,60 @@ function normalizeAuthConfig(configured) {
48
47
  }
49
48
  function resolveAuthAdapter(configured, fallback) {
50
49
  const config = normalizeAuthConfig(configured);
51
- return createAuthRuntime({
52
- provider: config.provider ?? config.adapter ?? (fallback?.supabaseUrl ? "supabase" : "mock"),
53
- adapter: config.adapter,
54
- routes: config.routes,
55
- requireAuth: false,
56
- supabase: {
57
- url: config.supabase?.url ?? fallback?.supabaseUrl,
58
- anonKey: config.supabase?.anonKey ?? fallback?.supabaseAnonKey,
59
- client: config.supabase?.client,
60
- callbackUrl: config.supabase?.callbackUrl,
61
- resetPasswordUrl: config.supabase?.resetPasswordUrl
50
+ if (isAuthAdapter(config.adapter)) return config.adapter;
51
+ const provider = config.provider ?? config.adapter ?? (fallback?.supabaseUrl ? "supabase" : "mock");
52
+ if (provider !== "supabase") return createMockAuthAdapter();
53
+ return createLazyAuthAdapter(
54
+ () => import('@fayz-ai/auth/lib/runtime').then(
55
+ ({ createAuthRuntime }) => createAuthRuntime({
56
+ provider: "supabase",
57
+ routes: config.routes,
58
+ requireAuth: false,
59
+ supabase: {
60
+ url: config.supabase?.url ?? fallback?.supabaseUrl,
61
+ anonKey: config.supabase?.anonKey ?? fallback?.supabaseAnonKey,
62
+ client: config.supabase?.client,
63
+ callbackUrl: config.supabase?.callbackUrl,
64
+ resetPasswordUrl: config.supabase?.resetPasswordUrl
65
+ }
66
+ }).adapter
67
+ )
68
+ );
69
+ }
70
+ function createLazyAuthAdapter(load) {
71
+ let loading = null;
72
+ const real = () => loading ?? (loading = load());
73
+ const call = (name) => async (...args) => {
74
+ const adapter = await real();
75
+ const fn = adapter[name];
76
+ if (typeof fn !== "function") throw new Error(`[storefront] the auth adapter has no ${String(name)}`);
77
+ return fn.apply(adapter, args);
78
+ };
79
+ return {
80
+ getSession: call("getSession"),
81
+ signIn: call("signIn"),
82
+ signUp: call("signUp"),
83
+ signOut: call("signOut"),
84
+ signInWithOAuth: call("signInWithOAuth"),
85
+ resetPassword: call("resetPassword"),
86
+ updatePassword: call("updatePassword"),
87
+ handleCallback: call("handleCallback"),
88
+ inviteUser: call("inviteUser"),
89
+ resendConfirmation: call("resendConfirmation"),
90
+ adoptSession: call("adoptSession"),
91
+ onAuthStateChange(cb) {
92
+ let unsubscribe = null;
93
+ let cancelled = false;
94
+ void real().then((adapter) => {
95
+ if (!cancelled) unsubscribe = adapter.onAuthStateChange(cb);
96
+ }).catch(() => {
97
+ });
98
+ return () => {
99
+ cancelled = true;
100
+ unsubscribe?.();
101
+ };
62
102
  }
63
- }).adapter;
103
+ };
64
104
  }
65
105
  var _accessToken = null;
66
106
  var _hadAuthUser = false;
@@ -479,6 +519,6 @@ function useStorefrontHead(input) {
479
519
  }, [description]);
480
520
  }
481
521
 
482
- export { EmailConfirmationRequiredError, SmoothImage, TID, establishCustomerSession, formatMoney, getCustomerAuthAdapter, hasCustomerAuth, initCustomerAuth, relinkCustomer, resolveAuthAdapter, roundCents, signInByEmail, signOutCustomer, signUpCustomer, useSessionStore, useStorefrontHead };
483
- //# sourceMappingURL=chunk-PATS4DIF.js.map
484
- //# sourceMappingURL=chunk-PATS4DIF.js.map
522
+ export { EmailConfirmationRequiredError, SmoothImage, TID, createLazyAuthAdapter, establishCustomerSession, formatMoney, getCustomerAuthAdapter, hasCustomerAuth, initCustomerAuth, relinkCustomer, resolveAuthAdapter, roundCents, signInByEmail, signOutCustomer, signUpCustomer, useSessionStore, useStorefrontHead };
523
+ //# sourceMappingURL=chunk-EFHQ5MAJ.js.map
524
+ //# sourceMappingURL=chunk-EFHQ5MAJ.js.map