@fayz-ai/storefront 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"SmoothImage.d.ts","sourceRoot":"","sources":["../../src/components/SmoothImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAA+B,KAAK,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AAEnG;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC;IACjF,YAAY,CAAC,EAAE,4BAA4B,CAAA;IAC3C,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,OAAO,EACP,OAAgB,EAChB,QAAkB,EAClB,MAAM,EACN,KAAK,EACL,GAAG,EACH,MAAM,EACN,KAAK,EACL,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAqElB"}
1
+ {"version":3,"file":"SmoothImage.d.ts","sourceRoot":"","sources":["../../src/components/SmoothImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAA+B,KAAK,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AAEnG;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC;IACjF,YAAY,CAAC,EAAE,4BAA4B,CAAA;IAC3C,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B;AAqBD,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,OAAO,EACP,OAAgB,EAChB,QAAkB,EAClB,MAAM,EACN,KAAK,EACL,GAAG,EACH,MAAM,EACN,KAAK,EACL,GAAG,KAAK,EACT,EAAE,gBAAgB,qBA2ElB"}
@@ -60,17 +60,6 @@ export interface RenderStoreOptions {
60
60
  * silently truncating the page. Default 4.
61
61
  */
62
62
  maxPasses?: number;
63
- /**
64
- * Which frame of an image's reveal animation to render.
65
- *
66
- * `'settled'` (default) renders images at their loaded state. A store with
67
- * `imageLoading.mode: 'fade'` paints every image at `opacity: 0` until its
68
- * load event fires — an event a static render never has — so the honest
69
- * frame to show is the one every shopper's browser reaches milliseconds
70
- * later, not a blank page. `'initial'` renders the pre-load frame verbatim,
71
- * for a caller specifically inspecting first paint.
72
- */
73
- imageReveal?: 'settled' | 'initial';
74
63
  /** Stylesheet URLs to link from the emitted document — how a preview server
75
64
  * hands in the app's real (Tailwind) CSS. */
76
65
  stylesheets?: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/document/render.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/document/render.tsx"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { STORE_SECTION_NAMES, isRecord, STORE_SECTIONS, slugifyStoreName, exportStore, resolveConfig, initStorefrontRuntime, StorefrontConfigHost, StorefrontShell, validateStore, isJsonValue, registerStorefrontBlocks, registerStorefrontExtensionPoints, sectionToJsonSchema, STOREFRONT_PAGE_KINDS, STOREFRONT_COMPONENT_KEYS, STOREFRONT_SLOTS, useStorefrontConfig, useCatalogStore, formatMoney, useCartStore, useSessionStore, selectTotal, selectShipping, selectDiscountTotal, selectSubtotal, selectCount, placeStorefrontOrder, useDeliveryStore, selectRequiresShipping, isNestedBlockRef, BLOCK_STRUCTURAL_KEYS, StorefrontPage, hydrateStoreDocument, blockInstanceId } from './chunk-6DWZAAIW.js';
2
- export { BEFORE_PLACE_ORDER_VALVE, BenefitsRow, BlockDataError, CART_LINE_ANNOTATION_POINT, CATALOG_BODY_BLOCK, CHECKOUT_FIELD_POINT, CartDrawer, CatalogPage, CategoryShowcase, CheckoutPage, CollectionCta, CollectionHero, ContentPage, CountdownBand, EmailConfirmationRequiredError, EntityListBlock, FaqSection, FiltersPanel, FormBlock, HeroSection, ImageTiles, Link, ManifestoBlock, MediaCarousel, MotifStrip, MyPurchasesPage, NewsletterBand, ORDER_METADATA_POINT, OrderConfirmationPage, OrderTrackingTimeline, PAGE_DATA_SCRIPT_ID, PLACEHOLDER_ASPECTS, PRODUCT_BODY_BLOCK, PRODUCT_CARD_BADGE_POINT, PageDataScope, PaymentTerms, Price, ProductCard, ProductDetailPage, ProductEnquiryForm, ProductGallery, ProductGrid, ProductOptionSelector, ProductRail, ProductReviews, ProductSlider, ProductSpecs, ProductSpotlight, PromoBanner, QuantityInput, Reveal, STOREFRONT_COMPONENT_KEYS, STOREFRONT_PAGE_KINDS, STOREFRONT_SLOTS, STORE_BACKEND_PROVIDERS, STORE_COMMERCE_MODES, STORE_DOCUMENT_KIND, STORE_PAYMENT_METHOD_KINDS, STORE_PAYMENT_MODES, STORE_ROUTE_CHROMES, STORE_ROUTE_KINDS, STORE_SECTIONS, STORE_SECTION_NAMES, SealsBand, SearchOverlay, Slot, SmoothImage, StepsSection, StorefrontConfigHost, StorefrontConfigProvider, StorefrontFooter, StorefrontHeader, StorefrontPage, StorefrontRouterProvider, StorefrontShell, StorefrontThemeStyle, StoryQuote, THEME_SCALE_FIELDS, THEME_SCALE_VAR_PREFIX, TID, Testimonials, TierCards, applyStoreSettings, bannerPlaceholder, buildEnquiryFromForm, checkPageBlocks, collectDataNeeds, collectOrderMetadata, contentPagePath, createStorefront, createStorefrontApp, currentStaticRenderPass, defaultPageBlocks, entityListBlockMeta, establishCustomerSession, exportStore, formatMoney, formatProductOptionSelection, getCartLineAnnotations, getCheckoutFieldContributions, getCustomerAuthAdapter, getProductCardBadges, getProductOptionGroups, hydrateStoreDocument, hydratedEntriesFor, initStorefrontRuntime, isKnownPath, isPublicPath, listSlots, matchContentPage, matchPath, matchesFacets, mergeCollectionFacet, mergePageTheme, navigateTo, nextMilestone, normalizeProductOptionSelection, orderGalleryImages, overrideComponent, overrideProps, pageSeo, pageThemeSelector, pickProductCardImage, placeStorefrontOrder, prefersReducedMotion, primaryImageUrl, productCardComponentContract, productJsonLd, productOptionSelectionKey, productPlaceholder, productSeo, readHydratedPageData, registerStorefrontBlocks, registerStorefrontEntities, registerStorefrontExtensionPoints, registerStorefrontLoaders, resetPageDiagnostics, resetProductOptionsDeprecationWarnings, resetStorefrontExtensionPoints, resolveAuthAdapter, resolveConfig, resolveDataParams, resolveOverride, resolvePageData, resolvePageDataNeed, resolvePaymentTerms, resolveStorefrontProvider, resolveStorefrontRoute, resolveVariantForSelection, roundCents, routePathParams, runBeforePlaceOrderValve, sectionToJsonSchema, sectionsToBlocks, selectCount, selectDiscountTotal, selectShipping, selectSubtotal, selectTotal, selectionPrice, serializePageData, shellRouterAdapter, signInByEmail, signOutCustomer, signUpCustomer, slugifyStoreName, storefrontComponentContracts, storefrontPaths, themeToCss, toBlockNodes, toFacetMap, useBlockData, useCartStore, useCatalogStore, useCategories, useDiscountValidator, useEnquiry, useHashPath, useInView, useLoader, useMyOrders, useNavigate, usePopOnChange, useProduct, useProducts, useRoutePath, useRouterAdapter, useScrollToTopOnNavigate, useScrolled, useSessionStore, useSlotContext, useStorefrontActions, useStorefrontConfig, useStorefrontConfigOptional, useStorefrontHead, useStorefrontPage, useStorefrontPageOptional, usedSlots, validateStore, withFacet, withStaticRenderPass } from './chunk-6DWZAAIW.js';
1
+ import { STORE_SECTION_NAMES, isRecord, STORE_SECTIONS, slugifyStoreName, exportStore, resolveConfig, initStorefrontRuntime, StorefrontConfigHost, StorefrontShell, validateStore, isJsonValue, registerStorefrontBlocks, registerStorefrontExtensionPoints, sectionToJsonSchema, STOREFRONT_PAGE_KINDS, STOREFRONT_COMPONENT_KEYS, STOREFRONT_SLOTS, useStorefrontConfig, useCatalogStore, formatMoney, useCartStore, useSessionStore, selectTotal, selectShipping, selectDiscountTotal, selectSubtotal, selectCount, placeStorefrontOrder, useDeliveryStore, selectRequiresShipping, isNestedBlockRef, BLOCK_STRUCTURAL_KEYS, StorefrontPage, hydrateStoreDocument, blockInstanceId } from './chunk-NBYDY2C3.js';
2
+ export { BEFORE_PLACE_ORDER_VALVE, BenefitsRow, BlockDataError, CART_LINE_ANNOTATION_POINT, CATALOG_BODY_BLOCK, CHECKOUT_FIELD_POINT, CartDrawer, CatalogPage, CategoryShowcase, CheckoutPage, CollectionCta, CollectionHero, ContentPage, CountdownBand, EmailConfirmationRequiredError, EntityListBlock, FaqSection, FiltersPanel, FormBlock, HeroSection, ImageTiles, Link, ManifestoBlock, MediaCarousel, MotifStrip, MyPurchasesPage, NewsletterBand, ORDER_METADATA_POINT, OrderConfirmationPage, OrderTrackingTimeline, PAGE_DATA_SCRIPT_ID, PLACEHOLDER_ASPECTS, PRODUCT_BODY_BLOCK, PRODUCT_CARD_BADGE_POINT, PageDataScope, PaymentTerms, Price, ProductCard, ProductDetailPage, ProductEnquiryForm, ProductGallery, ProductGrid, ProductOptionSelector, ProductRail, ProductReviews, ProductSlider, ProductSpecs, ProductSpotlight, PromoBanner, QuantityInput, Reveal, STOREFRONT_COMPONENT_KEYS, STOREFRONT_PAGE_KINDS, STOREFRONT_SLOTS, STORE_BACKEND_PROVIDERS, STORE_COMMERCE_MODES, STORE_DOCUMENT_KIND, STORE_PAYMENT_METHOD_KINDS, STORE_PAYMENT_MODES, STORE_ROUTE_CHROMES, STORE_ROUTE_KINDS, STORE_SECTIONS, STORE_SECTION_NAMES, SealsBand, SearchOverlay, Slot, SmoothImage, StepsSection, StorefrontConfigHost, StorefrontConfigProvider, StorefrontFooter, StorefrontHeader, StorefrontPage, StorefrontRouterProvider, StorefrontShell, StorefrontThemeStyle, StoryQuote, THEME_SCALE_FIELDS, THEME_SCALE_VAR_PREFIX, TID, Testimonials, TierCards, applyStoreSettings, bannerPlaceholder, buildEnquiryFromForm, checkPageBlocks, collectDataNeeds, collectOrderMetadata, contentPagePath, createStorefront, createStorefrontApp, currentStaticRenderPass, defaultPageBlocks, entityListBlockMeta, establishCustomerSession, exportStore, formatMoney, formatProductOptionSelection, getCartLineAnnotations, getCheckoutFieldContributions, getCustomerAuthAdapter, getProductCardBadges, getProductOptionGroups, hydrateStoreDocument, hydratedEntriesFor, initStorefrontRuntime, isKnownPath, isPublicPath, listSlots, matchContentPage, matchPath, matchesFacets, mergeCollectionFacet, mergePageTheme, navigateTo, nextMilestone, normalizeProductOptionSelection, orderGalleryImages, overrideComponent, overrideProps, pageSeo, pageThemeSelector, pickProductCardImage, placeStorefrontOrder, prefersReducedMotion, primaryImageUrl, productCardComponentContract, productJsonLd, productOptionSelectionKey, productPlaceholder, productSeo, readHydratedPageData, registerStorefrontBlocks, registerStorefrontEntities, registerStorefrontExtensionPoints, registerStorefrontLoaders, resetPageDiagnostics, resetProductOptionsDeprecationWarnings, resetStorefrontExtensionPoints, resolveAuthAdapter, resolveConfig, resolveDataParams, resolveOverride, resolvePageData, resolvePageDataNeed, resolvePaymentTerms, resolveStorefrontProvider, resolveStorefrontRoute, resolveVariantForSelection, roundCents, routePathParams, runBeforePlaceOrderValve, sectionToJsonSchema, sectionsToBlocks, selectCount, selectDiscountTotal, selectShipping, selectSubtotal, selectTotal, selectionPrice, serializePageData, shellRouterAdapter, signInByEmail, signOutCustomer, signUpCustomer, slugifyStoreName, storefrontComponentContracts, storefrontPaths, themeToCss, toBlockNodes, toFacetMap, useBlockData, useCartStore, useCatalogStore, useCategories, useDiscountValidator, useEnquiry, useHashPath, useInView, useLoader, useMyOrders, useNavigate, usePopOnChange, useProduct, useProducts, useRoutePath, useRouterAdapter, useScrollToTopOnNavigate, useScrolled, useSessionStore, useSlotContext, useStorefrontActions, useStorefrontConfig, useStorefrontConfigOptional, useStorefrontHead, useStorefrontPage, useStorefrontPageOptional, usedSlots, validateStore, withFacet, withStaticRenderPass } from './chunk-NBYDY2C3.js';
3
3
  export { auditStorefrontSeo, collectSeoAuditInput } from './chunk-6IXTENLB.js';
4
4
  import React3 from 'react';
5
5
  import { defineApp, registerScaffold, describeExtensionPoints, handleRegistry, describeEntities, describeLoaders, describeBlocks, ENTITY_FIELD_TYPES, BLOCK_SETTING_TYPES, normalizePostalCode, lookupPostalCode, formatPostalCode, BLOCK_PATH_ATTRIBUTE, BLOCK_TYPE_ATTRIBUTE, setBlockEditorMode, renderApp as renderApp$1 } from '@fayz-ai/core';
package/dist/render.js CHANGED
@@ -1,4 +1,4 @@
1
- import { validateStore, resolveConfig, registerStorefrontBlocks, registerStorefrontEntities, resetPageDiagnostics, withStaticRenderPass, StorefrontConfigProvider, StorefrontShell, resolvePageData, themeToCss, serializePageData, hydrateStoreDocument, storefrontPaths, isPublicPath, resolveStorefrontProvider } from './chunk-6DWZAAIW.js';
1
+ import { validateStore, resolveConfig, registerStorefrontBlocks, registerStorefrontEntities, resetPageDiagnostics, withStaticRenderPass, StorefrontConfigProvider, StorefrontShell, resolvePageData, themeToCss, serializePageData, hydrateStoreDocument, storefrontPaths, isPublicPath, resolveStorefrontProvider } from './chunk-NBYDY2C3.js';
2
2
  import { renderToStaticMarkup } from 'react-dom/server';
3
3
  import { historyRouterAdapter, setBlockErrorVisibility, setBlockEditorMode, staticRouterAdapter, buildSeoTags } from '@fayz-ai/core';
4
4
  import { createMockShopProvider } from '@fayz-ai/shop/mock';
@@ -113,9 +113,7 @@ ${validation.errors.map((e) => ` - ${e.path || "(document)"}: ${e.message}${e.va
113
113
  const hydrationLog = [];
114
114
  const config = captureConsole(hydrationLog, () => hydrateStoreDocument(input, { onError: "report" }));
115
115
  diagnostics.push(...hydrationLog.filter((d) => !d.message.includes("Store document failed validation")));
116
- const resolved = resolveConfig(
117
- (options.imageReveal ?? "settled") === "settled" ? { ...config, imageLoading: { ...config.imageLoading, mode: "none" } } : config
118
- );
116
+ const resolved = resolveConfig({ ...config, imageLoading: { ...config.imageLoading, mode: "none" } });
119
117
  registerStorefrontBlocks();
120
118
  registerStorefrontEntities(config);
121
119
  const previousProvider = getShopProvider();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/document/render.tsx","../src/app/prerender.ts"],"names":["staticRouterAdapter"],"mappings":"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","file":"render.js","sourcesContent":["import React from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { buildSeoTags, setBlockEditorMode, setBlockErrorVisibility, staticRouterAdapter } from '@fayz-ai/core'\nimport { serializePageData } from '../app/hydration'\nimport type { RouterAdapter } from '@fayz-ai/core'\nimport type { BlockNode } from '@fayz-ai/core'\nimport { createMockShopProvider } from '@fayz-ai/shop/mock'\nimport { getShopProvider, setShopProvider } from '@fayz-ai/shop/runtime'\nimport type { ShopProvider } from '@fayz-ai/shop/provider'\nimport { registerStorefrontBlocks } from '../blocks/registry'\nimport { StorefrontConfigProvider, resolveConfig } from './config'\nimport type { StorefrontConfig } from './config'\nimport {\n StorefrontShell,\n registerStorefrontEntities,\n resolveStorefrontProvider,\n} from '../app/createStorefrontApp'\nimport { resetPageDiagnostics } from '../views/StorefrontPage'\nimport { resolvePageData } from '../blocks/page-data'\nimport type { PageDataEntry, PageDataNeed } from '../blocks/page-data'\nimport { withStaticRenderPass } from '../app/static-render'\nimport type { StaticHeadInput, StaticRenderPass } from '../app/static-render'\nimport { hydrateStoreDocument } from './round-trip'\nimport type { StoreDocument } from './sections'\nimport { themeToCss } from '../lib/theme'\nimport { validateStore } from './validate'\nimport type { StoreValidationReport } from './validate'\n\n// ---------------------------------------------------------------------------\n// renderStore — the third ability, and the one M8 exists for (spine §5).\n//\n// The bet the whole spine rests on is that an AI can author a store. An author\n// that cannot SEE what it authored is guessing: it can be told the document is\n// valid (validateStore) and what the vocabulary is (describeStore) and still\n// place a hero above a header, leave a rail empty because its loader returned\n// nothing, or ship a page whose only content is an error card. This closes\n// that loop without a human driving a browser.\n//\n// Three decisions worth stating, because each has a cheaper wrong version:\n//\n// 1. It renders the REAL shell, driven by path. Not a server-side\n// reimplementation of routing and page composition — that would be a\n// second mechanism silently drifting from the first, which is the exact\n// failure §4 lists for WooCommerce's template overrides (\"227 @version\n// headers, the loader never reads one\"). The components report what they\n// need through the static-render pass; nothing here knows the route table.\n//\n// 2. Data is resolved BETWEEN passes, not faked. `PageDataScope` publishes\n// the needs it would fetch, `resolvePageData` answers them through the\n// ShopProvider port (I11 — no backend is named here), and the next pass\n// renders with the answers seeded. So a rail that is empty in the output\n// is empty in the shopper's browser too, and the report says which loader\n// returned what.\n//\n// 3. The return value is a REPORT, not a string. HTML alone makes an agent\n// parse markup to answer \"did my change land\". `text`, `outline`,\n// `blocks`, `data` and `diagnostics` answer it directly, and\n// `diagnostics` is where the M2 error-isolation machinery (crashed block,\n// unknown block, misplaced block, forced-layout repair) finally becomes\n// readable by the thing that caused it.\n// ---------------------------------------------------------------------------\n\nexport interface StoreRenderDataEntry {\n /** Canonical `dataNeedKey` — the same key the browser would dedupe on. */\n key: string\n loader: string\n params: Record<string, unknown>\n status: 'ready' | 'error' | 'unresolved'\n /** Item count for an array result, so \"the rail is empty\" is one field. */\n count?: number\n error?: string\n}\n\nexport interface StoreRenderDiagnostic {\n level: 'error' | 'warn'\n /** Where it came from: 'blocks' (core), 'storefront', or 'render'. */\n source: string\n message: string\n}\n\nexport interface StoreRenderHeading {\n level: number\n text: string\n}\n\nexport interface StoreRenderBlock {\n type: string\n id?: string\n /** Ancestor block types, outermost first — empty for a top-level block. */\n within?: string[]\n}\n\nexport interface RenderStoreOptions {\n /** Route to render, in the storefront's own path space ('/', '/catalog',\n * '/product/anel-de-ouro', '/biography'). Default '/'. */\n path?: string\n /**\n * Where catalog data comes from.\n *\n * - `'config'` (default): the provider the config implies — its explicit\n * provider, or a mock seeded from its catalog. What the shopper sees.\n * - `'document'`: a mock seeded from the document's own `catalog` section.\n * Deterministic and network-free, which is what you want while iterating\n * on a document whose store is backed by a live database.\n * - a `ShopProvider`: bring your own.\n */\n provider?: ShopProvider | 'config' | 'document'\n /**\n * 'report' (default) renders an invalid document anyway and returns the\n * findings — an agent fixing a broken store needs to see the broken store.\n * 'throw' refuses, for a caller using this as a gate.\n */\n onError?: 'throw' | 'report'\n /** 'document' (default) wraps the markup in a full HTML document with the\n * theme CSS and the route's title; 'fragment' returns the shell markup. */\n html?: 'document' | 'fragment'\n /**\n * How many render/resolve rounds to run. One page's data can reveal the\n * next need (a route param feeding a rail), so the loop repeats until no new\n * need appears. Reaching the cap is reported as a diagnostic rather than\n * silently truncating the page. Default 4.\n */\n maxPasses?: number\n /**\n * Which frame of an image's reveal animation to render.\n *\n * `'settled'` (default) renders images at their loaded state. A store with\n * `imageLoading.mode: 'fade'` paints every image at `opacity: 0` until its\n * load event fires — an event a static render never has — so the honest\n * frame to show is the one every shopper's browser reaches milliseconds\n * later, not a blank page. `'initial'` renders the pre-load frame verbatim,\n * for a caller specifically inspecting first paint.\n */\n imageReveal?: 'settled' | 'initial'\n /** Stylesheet URLs to link from the emitted document — how a preview server\n * hands in the app's real (Tailwind) CSS. */\n stylesheets?: readonly string[]\n /** Extra markup for the emitted `<head>`. */\n head?: string\n /**\n * How the rendered store is ADDRESSED when served.\n *\n * Defaults to hash, matching how storefronts ship today, so a headless render\n * describes links that actually resolve. Pass `historyRouterAdapter()` (or any\n * adapter) for a store served at real URLs — that is what makes each page\n * come out with a crawlable href of its own, which is the difference between\n * prerendered HTML that can be indexed and prerendered HTML that cannot.\n */\n router?: RouterAdapter\n /**\n * Absolute origin, e.g. 'https://loja.example.com'. Required for canonical\n * and OpenGraph URLs — without it they are omitted rather than emitted\n * relative, because a relative canonical is ignored.\n */\n origin?: string\n /** `<html lang>`. Defaults to the document's locale, then 'pt-BR'. */\n lang?: string\n /**\n * Stamp every block with its document path (`data-fayz-block`).\n *\n * Off by default, because a shopper's page must not carry it. On, the emitted\n * HTML says which document node produced which part of the page — which lets\n * an editor resolve a click to a path, and lets a test assert the identity\n * seam without a browser.\n */\n editor?: boolean\n}\n\nexport interface StoreRenderResult {\n /** True when the document validates, the path resolved, and nothing on the\n * page reported an error. The one field a gate should read. */\n ok: boolean\n path: string\n /** The title this route declared through `useStorefrontHead`. */\n title: string\n description?: string\n /** The path resolved to a real page (false = the 404 page rendered). */\n found: boolean\n html: string\n /** Visible text, tags stripped and whitespace collapsed — what a reader sees. */\n text: string\n /** h1–h6 in document order: the page's shape in one glance. */\n outline: StoreRenderHeading[]\n /** Every block that rendered, in order, including forced-layout repairs. */\n blocks: StoreRenderBlock[]\n /** Outbound hrefs, deduped — how an agent checks its nav actually links. */\n links: string[]\n images: number\n data: StoreRenderDataEntry[]\n diagnostics: StoreRenderDiagnostic[]\n validation: StoreValidationReport\n /** Render/resolve rounds actually run. */\n passes: number\n bytes: number\n}\n\n// --- HTML reading -------------------------------------------------------------\n\nconst VOID_TEXT_TAGS = /<(script|style)\\b[^>]*>[\\s\\S]*?<\\/\\1>/gi\n\nconst ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n '#39': \"'\",\n '#x27': \"'\",\n '#x2F': '/',\n}\n\nfunction decodeEntities(text: string): string {\n return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, name: string) => {\n const direct = ENTITIES[name]\n if (direct !== undefined) return direct\n if (name.startsWith('#x') || name.startsWith('#X')) {\n return String.fromCodePoint(Number.parseInt(name.slice(2), 16))\n }\n if (name.startsWith('#')) return String.fromCodePoint(Number(name.slice(1)))\n return match\n })\n}\n\n/** Visible text of a markup string. Regex rather than a DOM because the\n * workspace has no jsdom and the question — \"what words are on this page\" —\n * does not need one. */\nexport function htmlToText(html: string): string {\n return decodeEntities(html.replace(VOID_TEXT_TAGS, ' ').replace(/<[^>]*>/g, ' '))\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction readOutline(html: string): StoreRenderHeading[] {\n const found: StoreRenderHeading[] = []\n const pattern = /<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>/gi\n let match: RegExpExecArray | null\n while ((match = pattern.exec(html)) !== null) {\n const text = htmlToText(match[2] ?? '')\n if (text) found.push({ level: Number(match[1]), text })\n }\n return found\n}\n\nfunction readLinks(html: string): string[] {\n const found = new Set<string>()\n const pattern = /<a\\b[^>]*\\bhref=\"([^\"]*)\"/gi\n let match: RegExpExecArray | null\n while ((match = pattern.exec(html)) !== null) {\n const href = decodeEntities(match[1] ?? '')\n if (href) found.add(href)\n }\n return [...found]\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n}\n\n// --- Block inventory ----------------------------------------------------------\n\nfunction flattenBlocks(nodes: readonly BlockNode[], within: string[], out: StoreRenderBlock[]): void {\n for (const node of nodes) {\n out.push({ type: node.type, ...(node.id ? { id: node.id } : {}), ...(within.length ? { within: [...within] } : {}) })\n if (node.children?.length) flattenBlocks(node.children, [...within, node.type], out)\n }\n}\n\n// --- Console capture ----------------------------------------------------------\n\n/**\n * Run a synchronous render with console.error/warn captured.\n *\n * Everything the M2/M3 machinery reports about a broken page — a crashed\n * block, an unknown block type, a misplaced block, a forced-layout repair, a\n * page-body omission — is already logged, deliberately, and in production too.\n * Capturing it is what turns \"the console would have told a developer\" into a\n * field the agent that authored the page can read.\n */\nfunction captureConsole<T>(sink: StoreRenderDiagnostic[], render: () => T): T {\n const originalError = console.error\n const originalWarn = console.warn\n const record = (level: 'error' | 'warn') => (...args: unknown[]) => {\n const message = args\n .map((arg) => (arg instanceof Error ? arg.message : typeof arg === 'string' ? arg : safeStringify(arg)))\n .join(' ')\n .trim()\n if (!message) return\n const source = message.startsWith('[blocks]') ? 'blocks' : message.startsWith('[storefront]') ? 'storefront' : 'render'\n sink.push({ level, source, message })\n }\n console.error = record('error')\n console.warn = record('warn')\n try {\n return render()\n } finally {\n console.error = originalError\n console.warn = originalWarn\n }\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\n// --- The renderer -------------------------------------------------------------\n\nfunction providerFor(\n option: RenderStoreOptions['provider'],\n config: StorefrontConfig,\n doc: Record<string, unknown>,\n): ShopProvider {\n if (option && typeof option === 'object') return option\n if (option === 'document') {\n const catalog = doc.catalog as Record<string, unknown> | undefined\n const promotions = (doc.promotions as Record<string, unknown> | undefined)?.promotions\n const { version: _version, ...seed } = catalog ?? {}\n return createMockShopProvider({\n ...seed,\n ...(Array.isArray(promotions) ? { promotions } : {}),\n } as Parameters<typeof createMockShopProvider>[0])\n }\n return resolveStorefrontProvider(config)\n}\n\n/**\n * Render a Store Document to HTML, headless, plus everything an agent needs to\n * understand the result.\n *\n * const result = await renderStore(doc, { path: '/biography' })\n * result.ok // did anything on the page go wrong\n * result.outline // [{ level: 1, text: 'Biography' }, …]\n * result.data // [{ loader: 'products.list', status: 'ready', count: 12 }]\n * result.diagnostics\n */\nexport async function renderStore(\n input: StoreDocument | Record<string, unknown>,\n options: RenderStoreOptions = {},\n): Promise<StoreRenderResult> {\n const path = options.path ?? '/'\n const maxPasses = Math.max(1, options.maxPasses ?? 4)\n const doc = input as Record<string, unknown>\n\n const validation = validateStore(input)\n if (!validation.ok && (options.onError ?? 'report') === 'throw') {\n throw new Error(\n `renderStore: the document failed validation:\\n${validation.errors\n .map((e) => ` - ${e.path || '(document)'}: ${e.message}${e.valid ? ` (valid: ${e.valid.join(', ')})` : ''}`)\n .join('\\n')}`,\n )\n }\n\n const diagnostics: StoreRenderDiagnostic[] = []\n\n // Hydration reports rather than throws: a document with one unresolvable\n // handle should still render the other 95% of the page, which is the whole\n // point of looking at it (I7). Its validation echo is dropped — `validation`\n // already carries it, structured — but a dropped code handle is kept, because\n // nothing else reports that.\n const hydrationLog: StoreRenderDiagnostic[] = []\n const config = captureConsole(hydrationLog, () => hydrateStoreDocument(input, { onError: 'report' }))\n diagnostics.push(...hydrationLog.filter((d) => !d.message.includes('Store document failed validation')))\n const resolved = resolveConfig(\n (options.imageReveal ?? 'settled') === 'settled'\n ? { ...config, imageLoading: { ...config.imageLoading, mode: 'none' } }\n : config,\n )\n\n registerStorefrontBlocks()\n registerStorefrontEntities(config)\n\n const previousProvider = getShopProvider()\n setShopProvider(providerFor(options.provider, config, doc))\n // A preview is for the author, so a block that failed shows its error card\n // instead of vanishing — the shopper-facing 'silent' rule would hide exactly\n // what the loop exists to surface.\n setBlockErrorVisibility('visible')\n // Opt-in, and restored in the same `finally` as the provider — a render that\n // stamped and then threw must not leave the flag on for the next caller,\n // which in a preview server is the next request.\n if (options.editor) setBlockEditorMode(true)\n\n // Bound to the path being rendered, in the scheme the store is served under.\n // One adapter for the whole render: it is stateless here, and rebuilding it\n // per pass would only churn.\n const renderRouter = options.router\n ? staticRouterAdapter(path, { href: (to) => options.router!.href(to) })\n : staticRouterAdapter(path, { href: (to) => `#${to.startsWith('/') ? to : `/${to}`}` })\n\n const entries: Record<string, PageDataEntry> = {}\n let html = ''\n let passes = 0\n let head: StaticHeadInput = {}\n let blocks: StoreRenderBlock[] = []\n /** Needs the returned HTML still shows as loading — non-empty only when the\n * pass cap was reached, and reported rather than hidden. */\n let stale: PageDataNeed[] = []\n\n try {\n for (let round = 0; round < maxPasses; round++) {\n passes = round + 1\n const seenNeeds = new Map<string, PageDataNeed>()\n const trees: BlockNode[][] = []\n const heads: StaticHeadInput[] = []\n\n const pass: StaticRenderPass = {\n tree: (nodes) => void trees.push([...nodes]),\n needs: (needs) => {\n for (const need of needs) if (!seenNeeds.has(need.key)) seenNeeds.set(need.key, need)\n },\n head: (input_) => void heads.push(input_),\n entries,\n origin: options.origin,\n }\n\n // Reset PER PASS, not once. Page diagnostics are memoised per tree so a\n // shopper's console is not spammed by a re-render — but only the final\n // pass's console describes the page being returned, so without this a\n // multi-pass render would report a broken block on the pass whose output\n // was thrown away and stay silent on the one that was kept.\n resetPageDiagnostics()\n const roundDiagnostics: StoreRenderDiagnostic[] = []\n html = captureConsole(roundDiagnostics, () =>\n withStaticRenderPass(pass, () =>\n renderToStaticMarkup(\n <StorefrontConfigProvider value={resolved}>\n <StorefrontShell path={path} router={renderRouter} />\n </StorefrontConfigProvider>,\n ),\n ),\n )\n\n blocks = []\n for (const tree of trees) flattenBlocks(tree, [], blocks)\n // The LAST head declaration wins, matching the effect order a browser\n // would run: the route's own page declares after the chrome around it.\n head = heads.reduce<StaticHeadInput>(\n (acc, entry) => ({\n title: entry.title ?? acc.title,\n description: entry.description ?? acc.description,\n canonical: entry.canonical ?? acc.canonical,\n image: entry.image ?? acc.image,\n type: entry.type ?? acc.type,\n // Concatenated, not overwritten: a product page declares its Product\n // object and the chrome around it its BreadcrumbList, and a page is\n // allowed to carry both.\n jsonLd: [...(acc.jsonLd ?? []), ...(entry.jsonLd ?? [])],\n }),\n {},\n )\n\n const pending = [...seenNeeds.values()].filter((need) => !(need.key in entries))\n if (pending.length === 0) {\n // Only the final round's console output describes the page actually\n // being returned; earlier rounds are the same page with loading states,\n // and their diagnostics would double every message.\n diagnostics.push(...roundDiagnostics)\n break\n }\n if (round === maxPasses - 1) {\n // Resolving now would put answers in `entries` that this HTML does not\n // show. Report the gap instead of pretending the page is complete.\n stale = pending\n diagnostics.push(...roundDiagnostics)\n diagnostics.push({\n level: 'warn',\n source: 'render',\n message: `render stopped after ${maxPasses} passes with ${pending.length} data need(s) still loading — raise maxPasses if a page legitimately chains this deep`,\n })\n break\n }\n Object.assign(entries, await resolvePageData(pending))\n }\n } finally {\n setShopProvider(previousProvider)\n setBlockErrorVisibility(null)\n if (options.editor) setBlockEditorMode(false)\n }\n\n const data: StoreRenderDataEntry[] = Object.entries(entries).map(([key, entry]) => {\n const [loader, params] = splitNeedKey(key)\n return {\n key,\n loader,\n params,\n status: entry.status === 'ready' ? ('ready' as const) : ('error' as const),\n ...(Array.isArray(entry.data) ? { count: entry.data.length } : {}),\n ...(entry.error ? { error: entry.error } : {}),\n }\n })\n for (const need of stale) {\n data.push({ key: need.key, loader: need.loader, params: need.params, status: 'unresolved' })\n }\n\n const found = !html.includes('data-storefront-page=\"not-found\"')\n const title = head.title ?? resolved.name\n const text = htmlToText(html)\n const outline = readOutline(html)\n\n const body =\n (options.html ?? 'document') === 'fragment'\n ? html\n : wrapDocument(html + serializePageData({ entries, path }), {\n title,\n description: head.description ?? undefined,\n seo: { canonical: head.canonical, image: head.image, type: head.type, jsonLd: head.jsonLd },\n siteName: resolved.name,\n lang: options.lang ?? config.locale ?? 'pt-BR',\n themeCss: resolved.theme ? themeToCss(resolved.theme) : '',\n stylesheets: options.stylesheets ?? [],\n head: options.head ?? '',\n })\n\n return {\n ok:\n validation.ok &&\n found &&\n !diagnostics.some((d) => d.level === 'error') &&\n !data.some((d) => d.status !== 'ready'),\n path,\n title,\n ...(head.description ? { description: head.description } : {}),\n found,\n html: body,\n text,\n outline,\n blocks,\n links: readLinks(html),\n images: (html.match(/<img\\b/gi) ?? []).length,\n data,\n diagnostics,\n validation,\n passes,\n bytes: new TextEncoder().encode(body).length,\n }\n}\n\n/** `dataNeedKey` is `<loader> <canonical-json>`; recover both halves. */\nfunction splitNeedKey(key: string): [string, Record<string, unknown>] {\n const space = key.indexOf(' ')\n if (space === -1) return [key, {}]\n try {\n return [key.slice(0, space), JSON.parse(key.slice(space + 1)) as Record<string, unknown>]\n } catch {\n return [key.slice(0, space), {}]\n }\n}\n\ninterface WrapOptions {\n title: string\n description?: string\n lang: string\n themeCss: string\n stylesheets: readonly string[]\n head: string\n /** Canonical / OpenGraph / JSON-LD declared by the route being rendered. */\n seo?: Pick<StaticHeadInput, 'canonical' | 'image' | 'type' | 'jsonLd'>\n siteName?: string\n}\n\n/**\n * The HTML document around the shell markup.\n *\n * Deliberately minimal and self-contained: the theme's CSS variables ride\n * inline (they are already data — M2's brand tokens), and any real stylesheet\n * is LINKED rather than inlined, because the only thing that can produce the\n * app's utility CSS is the app's own build. A caller with no stylesheet gets\n * honest unstyled markup instead of a page that pretends to be styled.\n */\nexport function wrapDocument(markup: string, options: WrapOptions): string {\n const links = options.stylesheets.map((href) => `<link rel=\"stylesheet\" href=\"${escapeHtml(href)}\">`).join('')\n const themeStyle = options.themeCss ? `<style>${options.themeCss}</style>` : ''\n\n // Tag computation lives in core's `buildSeoTags`, shared with the client-side\n // `applySeo`, so a page's head is identical whichever side wrote it.\n const tags = buildSeoTags({\n title: options.title,\n description: options.description,\n canonical: options.seo?.canonical,\n image: options.seo?.image,\n type: options.seo?.type,\n siteName: options.siteName,\n jsonLd: options.seo?.jsonLd,\n })\n const meta = tags.meta\n .map((t) =>\n t.name\n ? `<meta name=\"${escapeHtml(t.name)}\" content=\"${escapeHtml(t.content)}\">`\n : `<meta property=\"${escapeHtml(t.property ?? '')}\" content=\"${escapeHtml(t.content)}\">`,\n )\n .join('')\n const seoLinks = tags.links\n .map((l) => `<link rel=\"${escapeHtml(l.rel)}\" href=\"${escapeHtml(l.href)}\">`)\n .join('')\n // JSON-LD is script content, not an attribute: `<` is escaped so a product\n // name containing markup cannot close the script tag early.\n const jsonLd = tags.jsonLd\n .map(\n (obj) =>\n `<script type=\"application/ld+json\">${JSON.stringify(obj).replace(/</g, '\\\\u003c')}</script>`,\n )\n .join('')\n\n return (\n `<!doctype html><html lang=\"${escapeHtml(options.lang)}\"><head><meta charset=\"utf-8\">` +\n `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">` +\n `<title>${escapeHtml(tags.title)}</title>${meta}${seoLinks}${links}${themeStyle}${jsonLd}${options.head}` +\n `</head><body>${markup}</body></html>`\n )\n}\n","import { historyRouterAdapter, staticRouterAdapter } from '@fayz-ai/core'\nimport type { ShopProvider } from '@fayz-ai/shop/provider'\nimport { renderStore } from '../document/render'\nimport type { RenderStoreOptions, StoreRenderResult } from '../document/render'\nimport { storefrontPaths, isPublicPath } from './serving'\nimport { resolveConfig } from '../document/config'\nimport { hydrateStoreDocument } from '../document/round-trip'\nimport type { StoreDocument } from '../document/sections'\n\n// ---------------------------------------------------------------------------\n// Every page of a store, rendered.\n//\n// `storefrontPaths` says which URLs exist and `renderStore` renders one; this\n// is the loop between them, plus the two files a crawler looks for before it\n// looks at any page. Kept here rather than in each host because the ordering\n// rules are not obvious: only public paths may be written (a prerendered\n// /checkout is one shopper's cart served to everyone), a page that rendered\n// not-found must not be written at all (it would be indexed as real content),\n// and concurrency has to be bounded or a 400-product catalogue opens 400\n// provider connections at once.\n// ---------------------------------------------------------------------------\n\nexport interface PrerenderPage {\n path: string\n html: string\n /** Where a file-writing host should put it: `/product/x` → `product/x/index.html`. */\n outputPath: string\n title: string\n /** False when the path rendered the not-found page — excluded from `pages`. */\n found: boolean\n ok: boolean\n}\n\nexport interface PrerenderResult {\n pages: PrerenderPage[]\n /** Paths that rendered not-found or errored, with the reason. */\n skipped: Array<{ path: string; reason: string }>\n sitemapXml: string\n robotsTxt: string\n}\n\nexport interface PrerenderOptions\n extends Omit<RenderStoreOptions, 'path' | 'router' | 'html'> {\n provider: ShopProvider\n /** Absolute origin. Required for a sitemap — its URLs must be absolute. */\n origin: string\n /** Defaults to every public path the store has. */\n paths?: readonly string[]\n /** Bounded so a large catalogue does not open one connection per product. */\n concurrency?: number\n /** Reported per page, so a long run is observable rather than silent. */\n onPage?: (page: PrerenderPage) => void\n}\n\n/** `/` → `index.html`; `/product/x` → `product/x/index.html`. */\nexport function outputPathFor(path: string): string {\n const clean = (path.split('?')[0] ?? '/').replace(/^\\/+|\\/+$/g, '')\n return clean === '' ? 'index.html' : `${clean}/index.html`\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nexport function buildSitemapXml(origin: string, paths: readonly string[]): string {\n const base = origin.replace(/\\/$/, '')\n const urls = paths\n .map((p) => ` <url><loc>${xmlEscape(`${base}${p}`)}</loc></url>`)\n .join('\\n')\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${urls}\\n</urlset>\\n`\n}\n\n/**\n * Disallows the per-shopper routes explicitly.\n *\n * They are not linked from anywhere crawlable, but a crawler that finds one\n * anyway would index a checkout — and crawl budget spent there is budget not\n * spent on products.\n */\nexport function buildRobotsTxt(origin: string): string {\n const base = origin.replace(/\\/$/, '')\n return [\n 'User-agent: *',\n 'Allow: /',\n 'Disallow: /checkout',\n 'Disallow: /account',\n 'Disallow: /order/',\n '',\n `Sitemap: ${base}/sitemap.xml`,\n '',\n ].join('\\n')\n}\n\nasync function mapWithLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n for (;;) {\n const i = next++\n if (i >= items.length) return\n results[i] = await fn(items[i]!)\n }\n })\n await Promise.all(workers)\n return results\n}\n\n/**\n * Render every public page of a store.\n *\n * The router is fixed to real-URL addressing: prerendering a hash-addressed\n * store would write files no URL can reach, which is the whole reason the\n * addressing seam exists.\n */\nexport async function prerenderStore(\n document: StoreDocument | Record<string, unknown>,\n options: PrerenderOptions,\n): Promise<PrerenderResult> {\n // Hydrated the same way renderStore does, so path enumeration and rendering\n // agree about what the store contains.\n const config = resolveConfig(hydrateStoreDocument(document, { onError: 'report' }))\n const paths =\n options.paths ??\n (await storefrontPaths({ config, provider: options.provider }))\n\n // Belt and braces: `storefrontPaths` already filters, but an explicit list\n // from a caller has not been through it, and a prerendered /checkout is one\n // shopper's cart served to everyone.\n const publicPaths = paths.filter((p) => isPublicPath(config, p))\n\n const skipped: Array<{ path: string; reason: string }> = []\n const rendered = await mapWithLimit(publicPaths, options.concurrency ?? 8, async (path) => {\n let result: StoreRenderResult\n try {\n result = await renderStore(document, {\n ...options,\n path,\n router: staticRouterAdapter(path),\n })\n } catch (error) {\n skipped.push({ path, reason: error instanceof Error ? error.message : String(error) })\n return null\n }\n const page: PrerenderPage = {\n path,\n html: result.html,\n outputPath: outputPathFor(path),\n title: result.title,\n found: result.found,\n ok: result.ok,\n }\n if (!result.found) {\n // Writing it would publish a not-found page at a real URL, which is then\n // indexed as content. Reported rather than silently dropped.\n skipped.push({ path, reason: 'rendered the not-found page' })\n return null\n }\n options.onPage?.(page)\n return page\n })\n\n const pages = rendered.filter((p): p is PrerenderPage => p !== null)\n return {\n pages,\n skipped,\n sitemapXml: buildSitemapXml(options.origin, pages.map((p) => p.path)),\n robotsTxt: buildRobotsTxt(options.origin),\n }\n}\n\n/** The adapter a browser app should use to serve a prerendered store. */\nexport const prerenderClientRouter = historyRouterAdapter\n"]}
1
+ {"version":3,"sources":["../src/document/render.tsx","../src/app/prerender.ts"],"names":["staticRouterAdapter"],"mappings":"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","file":"render.js","sourcesContent":["import React from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { buildSeoTags, setBlockEditorMode, setBlockErrorVisibility, staticRouterAdapter } from '@fayz-ai/core'\nimport { serializePageData } from '../app/hydration'\nimport type { RouterAdapter } from '@fayz-ai/core'\nimport type { BlockNode } from '@fayz-ai/core'\nimport { createMockShopProvider } from '@fayz-ai/shop/mock'\nimport { getShopProvider, setShopProvider } from '@fayz-ai/shop/runtime'\nimport type { ShopProvider } from '@fayz-ai/shop/provider'\nimport { registerStorefrontBlocks } from '../blocks/registry'\nimport { StorefrontConfigProvider, resolveConfig } from './config'\nimport type { StorefrontConfig } from './config'\nimport {\n StorefrontShell,\n registerStorefrontEntities,\n resolveStorefrontProvider,\n} from '../app/createStorefrontApp'\nimport { resetPageDiagnostics } from '../views/StorefrontPage'\nimport { resolvePageData } from '../blocks/page-data'\nimport type { PageDataEntry, PageDataNeed } from '../blocks/page-data'\nimport { withStaticRenderPass } from '../app/static-render'\nimport type { StaticHeadInput, StaticRenderPass } from '../app/static-render'\nimport { hydrateStoreDocument } from './round-trip'\nimport type { StoreDocument } from './sections'\nimport { themeToCss } from '../lib/theme'\nimport { validateStore } from './validate'\nimport type { StoreValidationReport } from './validate'\n\n// ---------------------------------------------------------------------------\n// renderStore — the third ability, and the one M8 exists for (spine §5).\n//\n// The bet the whole spine rests on is that an AI can author a store. An author\n// that cannot SEE what it authored is guessing: it can be told the document is\n// valid (validateStore) and what the vocabulary is (describeStore) and still\n// place a hero above a header, leave a rail empty because its loader returned\n// nothing, or ship a page whose only content is an error card. This closes\n// that loop without a human driving a browser.\n//\n// Three decisions worth stating, because each has a cheaper wrong version:\n//\n// 1. It renders the REAL shell, driven by path. Not a server-side\n// reimplementation of routing and page composition — that would be a\n// second mechanism silently drifting from the first, which is the exact\n// failure §4 lists for WooCommerce's template overrides (\"227 @version\n// headers, the loader never reads one\"). The components report what they\n// need through the static-render pass; nothing here knows the route table.\n//\n// 2. Data is resolved BETWEEN passes, not faked. `PageDataScope` publishes\n// the needs it would fetch, `resolvePageData` answers them through the\n// ShopProvider port (I11 — no backend is named here), and the next pass\n// renders with the answers seeded. So a rail that is empty in the output\n// is empty in the shopper's browser too, and the report says which loader\n// returned what.\n//\n// 3. The return value is a REPORT, not a string. HTML alone makes an agent\n// parse markup to answer \"did my change land\". `text`, `outline`,\n// `blocks`, `data` and `diagnostics` answer it directly, and\n// `diagnostics` is where the M2 error-isolation machinery (crashed block,\n// unknown block, misplaced block, forced-layout repair) finally becomes\n// readable by the thing that caused it.\n// ---------------------------------------------------------------------------\n\nexport interface StoreRenderDataEntry {\n /** Canonical `dataNeedKey` — the same key the browser would dedupe on. */\n key: string\n loader: string\n params: Record<string, unknown>\n status: 'ready' | 'error' | 'unresolved'\n /** Item count for an array result, so \"the rail is empty\" is one field. */\n count?: number\n error?: string\n}\n\nexport interface StoreRenderDiagnostic {\n level: 'error' | 'warn'\n /** Where it came from: 'blocks' (core), 'storefront', or 'render'. */\n source: string\n message: string\n}\n\nexport interface StoreRenderHeading {\n level: number\n text: string\n}\n\nexport interface StoreRenderBlock {\n type: string\n id?: string\n /** Ancestor block types, outermost first — empty for a top-level block. */\n within?: string[]\n}\n\nexport interface RenderStoreOptions {\n /** Route to render, in the storefront's own path space ('/', '/catalog',\n * '/product/anel-de-ouro', '/biography'). Default '/'. */\n path?: string\n /**\n * Where catalog data comes from.\n *\n * - `'config'` (default): the provider the config implies — its explicit\n * provider, or a mock seeded from its catalog. What the shopper sees.\n * - `'document'`: a mock seeded from the document's own `catalog` section.\n * Deterministic and network-free, which is what you want while iterating\n * on a document whose store is backed by a live database.\n * - a `ShopProvider`: bring your own.\n */\n provider?: ShopProvider | 'config' | 'document'\n /**\n * 'report' (default) renders an invalid document anyway and returns the\n * findings — an agent fixing a broken store needs to see the broken store.\n * 'throw' refuses, for a caller using this as a gate.\n */\n onError?: 'throw' | 'report'\n /** 'document' (default) wraps the markup in a full HTML document with the\n * theme CSS and the route's title; 'fragment' returns the shell markup. */\n html?: 'document' | 'fragment'\n /**\n * How many render/resolve rounds to run. One page's data can reveal the\n * next need (a route param feeding a rail), so the loop repeats until no new\n * need appears. Reaching the cap is reported as a diagnostic rather than\n * silently truncating the page. Default 4.\n */\n maxPasses?: number\n /** Stylesheet URLs to link from the emitted document — how a preview server\n * hands in the app's real (Tailwind) CSS. */\n stylesheets?: readonly string[]\n /** Extra markup for the emitted `<head>`. */\n head?: string\n /**\n * How the rendered store is ADDRESSED when served.\n *\n * Defaults to hash, matching how storefronts ship today, so a headless render\n * describes links that actually resolve. Pass `historyRouterAdapter()` (or any\n * adapter) for a store served at real URLs — that is what makes each page\n * come out with a crawlable href of its own, which is the difference between\n * prerendered HTML that can be indexed and prerendered HTML that cannot.\n */\n router?: RouterAdapter\n /**\n * Absolute origin, e.g. 'https://loja.example.com'. Required for canonical\n * and OpenGraph URLs — without it they are omitted rather than emitted\n * relative, because a relative canonical is ignored.\n */\n origin?: string\n /** `<html lang>`. Defaults to the document's locale, then 'pt-BR'. */\n lang?: string\n /**\n * Stamp every block with its document path (`data-fayz-block`).\n *\n * Off by default, because a shopper's page must not carry it. On, the emitted\n * HTML says which document node produced which part of the page — which lets\n * an editor resolve a click to a path, and lets a test assert the identity\n * seam without a browser.\n */\n editor?: boolean\n}\n\nexport interface StoreRenderResult {\n /** True when the document validates, the path resolved, and nothing on the\n * page reported an error. The one field a gate should read. */\n ok: boolean\n path: string\n /** The title this route declared through `useStorefrontHead`. */\n title: string\n description?: string\n /** The path resolved to a real page (false = the 404 page rendered). */\n found: boolean\n html: string\n /** Visible text, tags stripped and whitespace collapsed — what a reader sees. */\n text: string\n /** h1–h6 in document order: the page's shape in one glance. */\n outline: StoreRenderHeading[]\n /** Every block that rendered, in order, including forced-layout repairs. */\n blocks: StoreRenderBlock[]\n /** Outbound hrefs, deduped — how an agent checks its nav actually links. */\n links: string[]\n images: number\n data: StoreRenderDataEntry[]\n diagnostics: StoreRenderDiagnostic[]\n validation: StoreValidationReport\n /** Render/resolve rounds actually run. */\n passes: number\n bytes: number\n}\n\n// --- HTML reading -------------------------------------------------------------\n\nconst VOID_TEXT_TAGS = /<(script|style)\\b[^>]*>[\\s\\S]*?<\\/\\1>/gi\n\nconst ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n '#39': \"'\",\n '#x27': \"'\",\n '#x2F': '/',\n}\n\nfunction decodeEntities(text: string): string {\n return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, name: string) => {\n const direct = ENTITIES[name]\n if (direct !== undefined) return direct\n if (name.startsWith('#x') || name.startsWith('#X')) {\n return String.fromCodePoint(Number.parseInt(name.slice(2), 16))\n }\n if (name.startsWith('#')) return String.fromCodePoint(Number(name.slice(1)))\n return match\n })\n}\n\n/** Visible text of a markup string. Regex rather than a DOM because the\n * workspace has no jsdom and the question — \"what words are on this page\" —\n * does not need one. */\nexport function htmlToText(html: string): string {\n return decodeEntities(html.replace(VOID_TEXT_TAGS, ' ').replace(/<[^>]*>/g, ' '))\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction readOutline(html: string): StoreRenderHeading[] {\n const found: StoreRenderHeading[] = []\n const pattern = /<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>/gi\n let match: RegExpExecArray | null\n while ((match = pattern.exec(html)) !== null) {\n const text = htmlToText(match[2] ?? '')\n if (text) found.push({ level: Number(match[1]), text })\n }\n return found\n}\n\nfunction readLinks(html: string): string[] {\n const found = new Set<string>()\n const pattern = /<a\\b[^>]*\\bhref=\"([^\"]*)\"/gi\n let match: RegExpExecArray | null\n while ((match = pattern.exec(html)) !== null) {\n const href = decodeEntities(match[1] ?? '')\n if (href) found.add(href)\n }\n return [...found]\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n}\n\n// --- Block inventory ----------------------------------------------------------\n\nfunction flattenBlocks(nodes: readonly BlockNode[], within: string[], out: StoreRenderBlock[]): void {\n for (const node of nodes) {\n out.push({ type: node.type, ...(node.id ? { id: node.id } : {}), ...(within.length ? { within: [...within] } : {}) })\n if (node.children?.length) flattenBlocks(node.children, [...within, node.type], out)\n }\n}\n\n// --- Console capture ----------------------------------------------------------\n\n/**\n * Run a synchronous render with console.error/warn captured.\n *\n * Everything the M2/M3 machinery reports about a broken page — a crashed\n * block, an unknown block type, a misplaced block, a forced-layout repair, a\n * page-body omission — is already logged, deliberately, and in production too.\n * Capturing it is what turns \"the console would have told a developer\" into a\n * field the agent that authored the page can read.\n */\nfunction captureConsole<T>(sink: StoreRenderDiagnostic[], render: () => T): T {\n const originalError = console.error\n const originalWarn = console.warn\n const record = (level: 'error' | 'warn') => (...args: unknown[]) => {\n const message = args\n .map((arg) => (arg instanceof Error ? arg.message : typeof arg === 'string' ? arg : safeStringify(arg)))\n .join(' ')\n .trim()\n if (!message) return\n const source = message.startsWith('[blocks]') ? 'blocks' : message.startsWith('[storefront]') ? 'storefront' : 'render'\n sink.push({ level, source, message })\n }\n console.error = record('error')\n console.warn = record('warn')\n try {\n return render()\n } finally {\n console.error = originalError\n console.warn = originalWarn\n }\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\n// --- The renderer -------------------------------------------------------------\n\nfunction providerFor(\n option: RenderStoreOptions['provider'],\n config: StorefrontConfig,\n doc: Record<string, unknown>,\n): ShopProvider {\n if (option && typeof option === 'object') return option\n if (option === 'document') {\n const catalog = doc.catalog as Record<string, unknown> | undefined\n const promotions = (doc.promotions as Record<string, unknown> | undefined)?.promotions\n const { version: _version, ...seed } = catalog ?? {}\n return createMockShopProvider({\n ...seed,\n ...(Array.isArray(promotions) ? { promotions } : {}),\n } as Parameters<typeof createMockShopProvider>[0])\n }\n return resolveStorefrontProvider(config)\n}\n\n/**\n * Render a Store Document to HTML, headless, plus everything an agent needs to\n * understand the result.\n *\n * const result = await renderStore(doc, { path: '/biography' })\n * result.ok // did anything on the page go wrong\n * result.outline // [{ level: 1, text: 'Biography' }, …]\n * result.data // [{ loader: 'products.list', status: 'ready', count: 12 }]\n * result.diagnostics\n */\nexport async function renderStore(\n input: StoreDocument | Record<string, unknown>,\n options: RenderStoreOptions = {},\n): Promise<StoreRenderResult> {\n const path = options.path ?? '/'\n const maxPasses = Math.max(1, options.maxPasses ?? 4)\n const doc = input as Record<string, unknown>\n\n const validation = validateStore(input)\n if (!validation.ok && (options.onError ?? 'report') === 'throw') {\n throw new Error(\n `renderStore: the document failed validation:\\n${validation.errors\n .map((e) => ` - ${e.path || '(document)'}: ${e.message}${e.valid ? ` (valid: ${e.valid.join(', ')})` : ''}`)\n .join('\\n')}`,\n )\n }\n\n const diagnostics: StoreRenderDiagnostic[] = []\n\n // Hydration reports rather than throws: a document with one unresolvable\n // handle should still render the other 95% of the page, which is the whole\n // point of looking at it (I7). Its validation echo is dropped — `validation`\n // already carries it, structured — but a dropped code handle is kept, because\n // nothing else reports that.\n const hydrationLog: StoreRenderDiagnostic[] = []\n const config = captureConsole(hydrationLog, () => hydrateStoreDocument(input, { onError: 'report' }))\n diagnostics.push(...hydrationLog.filter((d) => !d.message.includes('Store document failed validation')))\n // Images at their settled frame. The reveal is a client entrance — a static\n // render has no load event to wait for, and `SmoothImage` no longer applies\n // the from-state on the server anyway; turning the mode off here keeps the\n // emitted HTML free of a transition nothing will ever run.\n const resolved = resolveConfig({ ...config, imageLoading: { ...config.imageLoading, mode: 'none' } })\n\n registerStorefrontBlocks()\n registerStorefrontEntities(config)\n\n const previousProvider = getShopProvider()\n setShopProvider(providerFor(options.provider, config, doc))\n // A preview is for the author, so a block that failed shows its error card\n // instead of vanishing — the shopper-facing 'silent' rule would hide exactly\n // what the loop exists to surface.\n setBlockErrorVisibility('visible')\n // Opt-in, and restored in the same `finally` as the provider — a render that\n // stamped and then threw must not leave the flag on for the next caller,\n // which in a preview server is the next request.\n if (options.editor) setBlockEditorMode(true)\n\n // Bound to the path being rendered, in the scheme the store is served under.\n // One adapter for the whole render: it is stateless here, and rebuilding it\n // per pass would only churn.\n const renderRouter = options.router\n ? staticRouterAdapter(path, { href: (to) => options.router!.href(to) })\n : staticRouterAdapter(path, { href: (to) => `#${to.startsWith('/') ? to : `/${to}`}` })\n\n const entries: Record<string, PageDataEntry> = {}\n let html = ''\n let passes = 0\n let head: StaticHeadInput = {}\n let blocks: StoreRenderBlock[] = []\n /** Needs the returned HTML still shows as loading — non-empty only when the\n * pass cap was reached, and reported rather than hidden. */\n let stale: PageDataNeed[] = []\n\n try {\n for (let round = 0; round < maxPasses; round++) {\n passes = round + 1\n const seenNeeds = new Map<string, PageDataNeed>()\n const trees: BlockNode[][] = []\n const heads: StaticHeadInput[] = []\n\n const pass: StaticRenderPass = {\n tree: (nodes) => void trees.push([...nodes]),\n needs: (needs) => {\n for (const need of needs) if (!seenNeeds.has(need.key)) seenNeeds.set(need.key, need)\n },\n head: (input_) => void heads.push(input_),\n entries,\n origin: options.origin,\n }\n\n // Reset PER PASS, not once. Page diagnostics are memoised per tree so a\n // shopper's console is not spammed by a re-render — but only the final\n // pass's console describes the page being returned, so without this a\n // multi-pass render would report a broken block on the pass whose output\n // was thrown away and stay silent on the one that was kept.\n resetPageDiagnostics()\n const roundDiagnostics: StoreRenderDiagnostic[] = []\n html = captureConsole(roundDiagnostics, () =>\n withStaticRenderPass(pass, () =>\n renderToStaticMarkup(\n <StorefrontConfigProvider value={resolved}>\n <StorefrontShell path={path} router={renderRouter} />\n </StorefrontConfigProvider>,\n ),\n ),\n )\n\n blocks = []\n for (const tree of trees) flattenBlocks(tree, [], blocks)\n // The LAST head declaration wins, matching the effect order a browser\n // would run: the route's own page declares after the chrome around it.\n head = heads.reduce<StaticHeadInput>(\n (acc, entry) => ({\n title: entry.title ?? acc.title,\n description: entry.description ?? acc.description,\n canonical: entry.canonical ?? acc.canonical,\n image: entry.image ?? acc.image,\n type: entry.type ?? acc.type,\n // Concatenated, not overwritten: a product page declares its Product\n // object and the chrome around it its BreadcrumbList, and a page is\n // allowed to carry both.\n jsonLd: [...(acc.jsonLd ?? []), ...(entry.jsonLd ?? [])],\n }),\n {},\n )\n\n const pending = [...seenNeeds.values()].filter((need) => !(need.key in entries))\n if (pending.length === 0) {\n // Only the final round's console output describes the page actually\n // being returned; earlier rounds are the same page with loading states,\n // and their diagnostics would double every message.\n diagnostics.push(...roundDiagnostics)\n break\n }\n if (round === maxPasses - 1) {\n // Resolving now would put answers in `entries` that this HTML does not\n // show. Report the gap instead of pretending the page is complete.\n stale = pending\n diagnostics.push(...roundDiagnostics)\n diagnostics.push({\n level: 'warn',\n source: 'render',\n message: `render stopped after ${maxPasses} passes with ${pending.length} data need(s) still loading — raise maxPasses if a page legitimately chains this deep`,\n })\n break\n }\n Object.assign(entries, await resolvePageData(pending))\n }\n } finally {\n setShopProvider(previousProvider)\n setBlockErrorVisibility(null)\n if (options.editor) setBlockEditorMode(false)\n }\n\n const data: StoreRenderDataEntry[] = Object.entries(entries).map(([key, entry]) => {\n const [loader, params] = splitNeedKey(key)\n return {\n key,\n loader,\n params,\n status: entry.status === 'ready' ? ('ready' as const) : ('error' as const),\n ...(Array.isArray(entry.data) ? { count: entry.data.length } : {}),\n ...(entry.error ? { error: entry.error } : {}),\n }\n })\n for (const need of stale) {\n data.push({ key: need.key, loader: need.loader, params: need.params, status: 'unresolved' })\n }\n\n const found = !html.includes('data-storefront-page=\"not-found\"')\n const title = head.title ?? resolved.name\n const text = htmlToText(html)\n const outline = readOutline(html)\n\n const body =\n (options.html ?? 'document') === 'fragment'\n ? html\n : wrapDocument(html + serializePageData({ entries, path }), {\n title,\n description: head.description ?? undefined,\n seo: { canonical: head.canonical, image: head.image, type: head.type, jsonLd: head.jsonLd },\n siteName: resolved.name,\n lang: options.lang ?? config.locale ?? 'pt-BR',\n themeCss: resolved.theme ? themeToCss(resolved.theme) : '',\n stylesheets: options.stylesheets ?? [],\n head: options.head ?? '',\n })\n\n return {\n ok:\n validation.ok &&\n found &&\n !diagnostics.some((d) => d.level === 'error') &&\n !data.some((d) => d.status !== 'ready'),\n path,\n title,\n ...(head.description ? { description: head.description } : {}),\n found,\n html: body,\n text,\n outline,\n blocks,\n links: readLinks(html),\n images: (html.match(/<img\\b/gi) ?? []).length,\n data,\n diagnostics,\n validation,\n passes,\n bytes: new TextEncoder().encode(body).length,\n }\n}\n\n/** `dataNeedKey` is `<loader> <canonical-json>`; recover both halves. */\nfunction splitNeedKey(key: string): [string, Record<string, unknown>] {\n const space = key.indexOf(' ')\n if (space === -1) return [key, {}]\n try {\n return [key.slice(0, space), JSON.parse(key.slice(space + 1)) as Record<string, unknown>]\n } catch {\n return [key.slice(0, space), {}]\n }\n}\n\ninterface WrapOptions {\n title: string\n description?: string\n lang: string\n themeCss: string\n stylesheets: readonly string[]\n head: string\n /** Canonical / OpenGraph / JSON-LD declared by the route being rendered. */\n seo?: Pick<StaticHeadInput, 'canonical' | 'image' | 'type' | 'jsonLd'>\n siteName?: string\n}\n\n/**\n * The HTML document around the shell markup.\n *\n * Deliberately minimal and self-contained: the theme's CSS variables ride\n * inline (they are already data — M2's brand tokens), and any real stylesheet\n * is LINKED rather than inlined, because the only thing that can produce the\n * app's utility CSS is the app's own build. A caller with no stylesheet gets\n * honest unstyled markup instead of a page that pretends to be styled.\n */\nexport function wrapDocument(markup: string, options: WrapOptions): string {\n const links = options.stylesheets.map((href) => `<link rel=\"stylesheet\" href=\"${escapeHtml(href)}\">`).join('')\n const themeStyle = options.themeCss ? `<style>${options.themeCss}</style>` : ''\n\n // Tag computation lives in core's `buildSeoTags`, shared with the client-side\n // `applySeo`, so a page's head is identical whichever side wrote it.\n const tags = buildSeoTags({\n title: options.title,\n description: options.description,\n canonical: options.seo?.canonical,\n image: options.seo?.image,\n type: options.seo?.type,\n siteName: options.siteName,\n jsonLd: options.seo?.jsonLd,\n })\n const meta = tags.meta\n .map((t) =>\n t.name\n ? `<meta name=\"${escapeHtml(t.name)}\" content=\"${escapeHtml(t.content)}\">`\n : `<meta property=\"${escapeHtml(t.property ?? '')}\" content=\"${escapeHtml(t.content)}\">`,\n )\n .join('')\n const seoLinks = tags.links\n .map((l) => `<link rel=\"${escapeHtml(l.rel)}\" href=\"${escapeHtml(l.href)}\">`)\n .join('')\n // JSON-LD is script content, not an attribute: `<` is escaped so a product\n // name containing markup cannot close the script tag early.\n const jsonLd = tags.jsonLd\n .map(\n (obj) =>\n `<script type=\"application/ld+json\">${JSON.stringify(obj).replace(/</g, '\\\\u003c')}</script>`,\n )\n .join('')\n\n return (\n `<!doctype html><html lang=\"${escapeHtml(options.lang)}\"><head><meta charset=\"utf-8\">` +\n `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">` +\n `<title>${escapeHtml(tags.title)}</title>${meta}${seoLinks}${links}${themeStyle}${jsonLd}${options.head}` +\n `</head><body>${markup}</body></html>`\n )\n}\n","import { historyRouterAdapter, staticRouterAdapter } from '@fayz-ai/core'\nimport type { ShopProvider } from '@fayz-ai/shop/provider'\nimport { renderStore } from '../document/render'\nimport type { RenderStoreOptions, StoreRenderResult } from '../document/render'\nimport { storefrontPaths, isPublicPath } from './serving'\nimport { resolveConfig } from '../document/config'\nimport { hydrateStoreDocument } from '../document/round-trip'\nimport type { StoreDocument } from '../document/sections'\n\n// ---------------------------------------------------------------------------\n// Every page of a store, rendered.\n//\n// `storefrontPaths` says which URLs exist and `renderStore` renders one; this\n// is the loop between them, plus the two files a crawler looks for before it\n// looks at any page. Kept here rather than in each host because the ordering\n// rules are not obvious: only public paths may be written (a prerendered\n// /checkout is one shopper's cart served to everyone), a page that rendered\n// not-found must not be written at all (it would be indexed as real content),\n// and concurrency has to be bounded or a 400-product catalogue opens 400\n// provider connections at once.\n// ---------------------------------------------------------------------------\n\nexport interface PrerenderPage {\n path: string\n html: string\n /** Where a file-writing host should put it: `/product/x` → `product/x/index.html`. */\n outputPath: string\n title: string\n /** False when the path rendered the not-found page — excluded from `pages`. */\n found: boolean\n ok: boolean\n}\n\nexport interface PrerenderResult {\n pages: PrerenderPage[]\n /** Paths that rendered not-found or errored, with the reason. */\n skipped: Array<{ path: string; reason: string }>\n sitemapXml: string\n robotsTxt: string\n}\n\nexport interface PrerenderOptions\n extends Omit<RenderStoreOptions, 'path' | 'router' | 'html'> {\n provider: ShopProvider\n /** Absolute origin. Required for a sitemap — its URLs must be absolute. */\n origin: string\n /** Defaults to every public path the store has. */\n paths?: readonly string[]\n /** Bounded so a large catalogue does not open one connection per product. */\n concurrency?: number\n /** Reported per page, so a long run is observable rather than silent. */\n onPage?: (page: PrerenderPage) => void\n}\n\n/** `/` → `index.html`; `/product/x` → `product/x/index.html`. */\nexport function outputPathFor(path: string): string {\n const clean = (path.split('?')[0] ?? '/').replace(/^\\/+|\\/+$/g, '')\n return clean === '' ? 'index.html' : `${clean}/index.html`\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nexport function buildSitemapXml(origin: string, paths: readonly string[]): string {\n const base = origin.replace(/\\/$/, '')\n const urls = paths\n .map((p) => ` <url><loc>${xmlEscape(`${base}${p}`)}</loc></url>`)\n .join('\\n')\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${urls}\\n</urlset>\\n`\n}\n\n/**\n * Disallows the per-shopper routes explicitly.\n *\n * They are not linked from anywhere crawlable, but a crawler that finds one\n * anyway would index a checkout — and crawl budget spent there is budget not\n * spent on products.\n */\nexport function buildRobotsTxt(origin: string): string {\n const base = origin.replace(/\\/$/, '')\n return [\n 'User-agent: *',\n 'Allow: /',\n 'Disallow: /checkout',\n 'Disallow: /account',\n 'Disallow: /order/',\n '',\n `Sitemap: ${base}/sitemap.xml`,\n '',\n ].join('\\n')\n}\n\nasync function mapWithLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n for (;;) {\n const i = next++\n if (i >= items.length) return\n results[i] = await fn(items[i]!)\n }\n })\n await Promise.all(workers)\n return results\n}\n\n/**\n * Render every public page of a store.\n *\n * The router is fixed to real-URL addressing: prerendering a hash-addressed\n * store would write files no URL can reach, which is the whole reason the\n * addressing seam exists.\n */\nexport async function prerenderStore(\n document: StoreDocument | Record<string, unknown>,\n options: PrerenderOptions,\n): Promise<PrerenderResult> {\n // Hydrated the same way renderStore does, so path enumeration and rendering\n // agree about what the store contains.\n const config = resolveConfig(hydrateStoreDocument(document, { onError: 'report' }))\n const paths =\n options.paths ??\n (await storefrontPaths({ config, provider: options.provider }))\n\n // Belt and braces: `storefrontPaths` already filters, but an explicit list\n // from a caller has not been through it, and a prerendered /checkout is one\n // shopper's cart served to everyone.\n const publicPaths = paths.filter((p) => isPublicPath(config, p))\n\n const skipped: Array<{ path: string; reason: string }> = []\n const rendered = await mapWithLimit(publicPaths, options.concurrency ?? 8, async (path) => {\n let result: StoreRenderResult\n try {\n result = await renderStore(document, {\n ...options,\n path,\n router: staticRouterAdapter(path),\n })\n } catch (error) {\n skipped.push({ path, reason: error instanceof Error ? error.message : String(error) })\n return null\n }\n const page: PrerenderPage = {\n path,\n html: result.html,\n outputPath: outputPathFor(path),\n title: result.title,\n found: result.found,\n ok: result.ok,\n }\n if (!result.found) {\n // Writing it would publish a not-found page at a real URL, which is then\n // indexed as content. Reported rather than silently dropped.\n skipped.push({ path, reason: 'rendered the not-found page' })\n return null\n }\n options.onPage?.(page)\n return page\n })\n\n const pages = rendered.filter((p): p is PrerenderPage => p !== null)\n return {\n pages,\n skipped,\n sitemapXml: buildSitemapXml(options.origin, pages.map((p) => p.path)),\n robotsTxt: buildRobotsTxt(options.origin),\n }\n}\n\n/** The adapter a browser app should use to serve a prerendered store. */\nexport const prerenderClientRouter = historyRouterAdapter\n"]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "fayz": {
4
4
  "status": "beta"
5
5
  },
6
- "version": "0.13.1",
6
+ "version": "0.14.0",
7
7
  "description": "Fayz SDK storefront kit — Shopify-style customer-facing ecommerce template components",
8
8
  "type": "module",
9
9
  "sideEffects": false,
@@ -40,12 +40,12 @@
40
40
  "dist"
41
41
  ],
42
42
  "dependencies": {
43
- "@fayz-ai/auth": "^0.12.0",
44
- "@fayz-ai/core": "^0.12.0",
45
- "@fayz-ai/plugin-auth": "^0.10.1",
43
+ "@fayz-ai/auth": "^0.14.0",
44
+ "@fayz-ai/core": "^0.14.0",
45
+ "@fayz-ai/plugin-auth": "^0.10.2",
46
46
  "@fayz-ai/sdk": "^0.12.0",
47
- "@fayz-ai/shop": "^0.13.1",
48
- "@fayz-ai/ui": "^0.12.0"
47
+ "@fayz-ai/shop": "^0.14.0",
48
+ "@fayz-ai/ui": "^0.14.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@supabase/supabase-js": "^2.45.0",