@replohq/sdk 0.8.0 → 0.10.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,4 +1,4 @@
1
- export type ReploScriptType = "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Cookiebot" | "snippet" | "custom" | "consentPlatform";
1
+ export type ReploScriptType = "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Gorgias" | "Cookiebot" | "snippet" | "custom" | "consentPlatform";
2
2
  export type ConsentCategory = "necessary" | "analytics" | "marketing" | "preferences" | "sale_of_data";
3
3
  export type ConsentMode = "off" | "simple" | "per-category";
4
4
  export type ScriptTagDescriptor = {
@@ -13,7 +13,7 @@ export type ScriptTagDescriptor = {
13
13
  module?: boolean;
14
14
  };
15
15
  export type ReploScriptEntry = {
16
- type: "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam";
16
+ type: "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Gorgias";
17
17
  identifier: string;
18
18
  requiredConsent?: ConsentCategory[];
19
19
  } | {
@@ -21,8 +21,8 @@ export declare const localeRoutingConfigSchema: z.ZodObject<{
21
21
  locales: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
22
22
  defaultLocale: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
23
23
  detection: z.ZodDefault<z.ZodEnum<{
24
- country: "country";
25
24
  language: "language";
25
+ country: "country";
26
26
  }>>;
27
27
  urlMode: z.ZodDefault<z.ZodEnum<{
28
28
  prefixed: "prefixed";
@@ -116,6 +116,20 @@ gtag('config', '${id}');`
116
116
  body: `(function(){var t;(n=t=t||{}).A="identify",n.B="trackPageView",n.C="fireEmailCaptureEvent",n.D="fireCustomGoal",n.E="firePurchaseEvent",n.F="trackPageViewInitial",n.G="fireSlimPurchaseEvent",n.H="identifyCustomerId";var n="https://j.northbeam.io/ota-sp/${id}.js";function r(n){for(var e=[],t=1;t<arguments.length;t++)e[t-1]=arguments[t];i.push({fnName:n,args:e})}var e,i=[],a=((e={})[t.F]=function(n){r(t.F,n)},(a={_q:i})[t.A]=function(n,e){return r(t.A,n,e)},a[t.B]=function(){return r(t.B)},a[t.C]=function(n,e){return r(t.C,n,e)},a[t.D]=function(n,e){return r(t.D,n,e)},a[t.E]=function(n){return r(t.E,n)},a[t.G]=function(n){return r(t.G,n)},a[t.H]=function(n,e){return r(t.H,n,e)},Object.assign(function(n){for(var e=[],t=1;t<arguments.length;t++)e.push(arguments[t]);return r.apply(null,[n].concat(e))},a));window.Northbeam=a,(a=document.createElement("script")).async=!0,a.src=n,document.head.appendChild(a),e.trackPageViewInitial(window.location.href);})()`
117
117
  }
118
118
  ]
119
+ },
120
+ Gorgias: {
121
+ // Support chat stores the visitor's chat session, which is a functional
122
+ // preference rather than analytics or ad tracking.
123
+ defaultConsent: ["preferences"],
124
+ // The id attribute matches Gorgias's official v3 install snippet; their
125
+ // customization scripts and support tooling look the tag up by that id.
126
+ buildTags: (id) => [
127
+ {
128
+ kind: "external",
129
+ src: `https://config.gorgias.chat/bundle-loader/${id}`,
130
+ attributes: { id: "gorgias-chat-widget-install-v3" }
131
+ }
132
+ ]
119
133
  }
120
134
  };
121
135
  function buildScriptTags({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../consent/script-snippets.ts"],
4
- "sourcesContent": ["import type {\n ConsentCategory,\n ReploScriptType,\n ScriptTagDescriptor,\n} from \"schemas/generated/consent\";\n\n// Identifier providers: those whose script the runtime synthesizes from an ID.\n// `snippet` (pasted whole) and `custom` carry their own bodies instead.\n// Cookiebot's loader is built by its consent-platform preset, not here.\ntype ProviderType = Exclude<\n ReploScriptType,\n \"custom\" | \"snippet\" | \"consentPlatform\" | \"Cookiebot\"\n>;\n\n/**\n * Runtime-safe per-provider data for the consent system. This is the subset of\n * the website-builder miniapp's `scriptConstants.ts` that must ship in the\n * customer site bundle: how to materialize each provider's script tags, and the\n * default consent category that gates it. Miniapp-only concerns (LLM detection\n * schemas, logos, marketing copy) intentionally stay in the miniapp.\n *\n * Unlike the miniapp's `buildSnippet`, which returns a JSX *string* for the\n * agent to paste into `layout.tsx`, this returns structured descriptors so the\n * runtime can inject real DOM nodes (inline `<script>` bodies set via React's\n * `dangerouslySetInnerHTML` never execute).\n */\ntype ProviderSnippet = {\n defaultConsent: ConsentCategory[];\n buildTags: (identifier: string) => ScriptTagDescriptor[];\n};\n\n/**\n * NOTE (Ryan, 2026-05-28, REPL-27515): `defaultConsent` is net-new,\n * legally-sensitive categorization that does not exist elsewhere in the repo.\n * These are conservative defaults a customer can override per entry via\n * `requiredConsent`; container/CDP providers that fan out to multiple vendors\n * (GTM, Segment) require the union of categories they can serve.\n */\nconst PROVIDER_SNIPPETS: Record<ProviderType, ProviderSnippet> = {\n GA4: {\n defaultConsent: [\"analytics\"],\n buildTags: (id) => [\n {\n kind: \"external\",\n src: `https://www.googletagmanager.com/gtag/js?id=${id}`,\n },\n {\n kind: \"inline\",\n body: `window.dataLayer = window.dataLayer || [];\\nfunction gtag(){dataLayer.push(arguments);}\\ngtag('js', new Date());\\ngtag('config', '${id}');`,\n },\n ],\n },\n GoogleTagManager: {\n defaultConsent: [\"analytics\", \"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${id}');`,\n },\n ],\n },\n Meta: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');fbq('init','${id}');fbq('track','PageView');`,\n },\n ],\n },\n TikTok: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(w,d,t){w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=[\"page\",\"track\",\"identify\",\"instances\",\"debug\",\"on\",\"off\",\"once\",\"ready\",\"alias\",\"group\",\"enableCookie\",\"disableCookie\",\"holdConsent\",\"revokeConsent\",\"grantConsent\"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e};ttq.load=function(e,n){var r=\"https://analytics.tiktok.com/i18n/pixel/events.js\",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};var a=document.createElement(\"script\");a.type=\"text/javascript\",a.async=!0,a.src=r+\"?sdkid=\"+e+\"&lib=\"+t;var s=document.getElementsByTagName(\"script\")[0];s.parentNode.insertBefore(a,s)};ttq.load('${id}');ttq.page();}(window,document,'ttq');`,\n },\n ],\n },\n Pinterest: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(e){if(!window.pintrk){window.pintrk=function(){window.pintrk.queue.push(Array.prototype.slice.call(arguments))};var n=window.pintrk;n.queue=[],n.version=\"3.0\";var t=document.createElement(\"script\");t.async=!0,t.src=e;var r=document.getElementsByTagName(\"script\")[0];r.parentNode.insertBefore(t,r)}}(\"https://s.pinimg.com/ct/core.js\");pintrk('load','${id}');pintrk('page');`,\n },\n ],\n },\n Reddit: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];var t=d.createElement(\"script\");t.src=\"https://www.redditstatic.com/ads/pixel.js\",t.async=!0;var s=d.getElementsByTagName(\"script\")[0];s.parentNode.insertBefore(t,s)}}(window,document);rdt('init','${id}');rdt('track','PageVisit');`,\n },\n ],\n },\n Snapchat: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function(){a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)};a.queue=[];var s='script';var r=t.createElement(s);r.async=!0;r.src=n;var u=t.getElementsByTagName(s)[0];u.parentNode.insertBefore(r,u);})(window,document,'https://sc-static.net/scevent.min.js');snaptr('init','${id}',{});snaptr('track','PAGE_VIEW');`,\n },\n ],\n },\n Hotjar: {\n defaultConsent: [\"analytics\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(h,o,t,j,a,r){h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};h._hjSettings={hjid:${id},hjsv:6};a=o.getElementsByTagName('head')[0];r=o.createElement('script');r.async=1;r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;a.appendChild(r);})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');`,\n },\n ],\n },\n MicrosoftClarity: {\n defaultConsent: [\"analytics\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src=\"https://www.clarity.ms/tag/\"+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,\"clarity\",\"script\",\"${id}\");`,\n },\n ],\n },\n Contentsquare: {\n defaultConsent: [\"analytics\"],\n // The UXA tag is a single async external script keyed by the 13-char tag id;\n // it bootstraps the Contentsquare `_uxa` queue itself once loaded.\n buildTags: (id) => [\n {\n kind: \"external\",\n src: `https://t.contentsquare.net/uxa/${id}.js`,\n attributes: { async: \"true\" },\n },\n ],\n },\n Segment: {\n defaultConsent: [\"analytics\", \"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(){var i=\"analytics\",analytics=window[i]=window[i]||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error(\"Segment snippet included twice.\");else{analytics.invoked=!0;analytics.methods=[\"trackSubmit\",\"trackClick\",\"trackLink\",\"trackForm\",\"pageview\",\"identify\",\"reset\",\"group\",\"track\",\"ready\",\"alias\",\"debug\",\"page\",\"screen\",\"once\",\"off\",\"on\",\"addSourceMiddleware\",\"addIntegrationMiddleware\",\"setAnonymousId\",\"addDestinationMiddleware\",\"register\"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement(\"script\");t.type=\"text/javascript\";t.async=!0;t.src=\"https://cdn.segment.com/analytics.js/v1/\"+key+\"/analytics.min.js\";var n=document.getElementsByTagName(\"script\")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};analytics._writeKey=\"${id}\";analytics.SNIPPET_VERSION=\"5.2.0\";analytics.load(\"${id}\");analytics.page();}}();`,\n },\n ],\n },\n Northbeam: {\n defaultConsent: [\"analytics\", \"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(){var t;(n=t=t||{}).A=\"identify\",n.B=\"trackPageView\",n.C=\"fireEmailCaptureEvent\",n.D=\"fireCustomGoal\",n.E=\"firePurchaseEvent\",n.F=\"trackPageViewInitial\",n.G=\"fireSlimPurchaseEvent\",n.H=\"identifyCustomerId\";var n=\"https://j.northbeam.io/ota-sp/${id}.js\";function r(n){for(var e=[],t=1;t<arguments.length;t++)e[t-1]=arguments[t];i.push({fnName:n,args:e})}var e,i=[],a=((e={})[t.F]=function(n){r(t.F,n)},(a={_q:i})[t.A]=function(n,e){return r(t.A,n,e)},a[t.B]=function(){return r(t.B)},a[t.C]=function(n,e){return r(t.C,n,e)},a[t.D]=function(n,e){return r(t.D,n,e)},a[t.E]=function(n){return r(t.E,n)},a[t.G]=function(n){return r(t.G,n)},a[t.H]=function(n,e){return r(t.H,n,e)},Object.assign(function(n){for(var e=[],t=1;t<arguments.length;t++)e.push(arguments[t]);return r.apply(null,[n].concat(e))},a));window.Northbeam=a,(a=document.createElement(\"script\")).async=!0,a.src=n,document.head.appendChild(a),e.trackPageViewInitial(window.location.href);})()`,\n },\n ],\n },\n};\n\n/**\n * Snippet providers don't synthesize tags (the user pastes the provider-issued\n * snippet as the entry's `body`), but they still get a first-class default\n * consent categorization like identifier providers.\n */\n/**\n * Returns the structured tag descriptors for a named provider. A single provider\n * can produce multiple tags (e.g. GA4 = external loader + inline config), which\n * the runtime injects in order.\n */\nexport function buildScriptTags({\n type,\n identifier,\n}: {\n type: ProviderType;\n identifier: string;\n}): ScriptTagDescriptor[] {\n return PROVIDER_SNIPPETS[type].buildTags(identifier);\n}\n\n/**\n * The default consent categories that gate an identifier-provider script when an\n * entry does not specify `requiredConsent`. `snippet` and `custom` entries carry\n * `requiredConsent` explicitly (the runtime has no default for them), so this is\n * only consulted for identifier providers. Overridable per entry by the customer.\n */\nexport function defaultConsentFor(type: ProviderType): ConsentCategory[] {\n return PROVIDER_SNIPPETS[type].defaultConsent;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type {\n ConsentCategory,\n ReploScriptType,\n ScriptTagDescriptor,\n} from \"schemas/generated/consent\";\n\n// Identifier providers: those whose script the runtime synthesizes from an ID.\n// `snippet` (pasted whole) and `custom` carry their own bodies instead.\n// Cookiebot's loader is built by its consent-platform preset, not here.\ntype ProviderType = Exclude<\n ReploScriptType,\n \"custom\" | \"snippet\" | \"consentPlatform\" | \"Cookiebot\"\n>;\n\n/**\n * Runtime-safe per-provider data for the consent system. This is the subset of\n * the website-builder miniapp's `scriptConstants.ts` that must ship in the\n * customer site bundle: how to materialize each provider's script tags, and the\n * default consent category that gates it. Miniapp-only concerns (LLM detection\n * schemas, logos, marketing copy) intentionally stay in the miniapp.\n *\n * Unlike the miniapp's `buildSnippet`, which returns a JSX *string* for the\n * agent to paste into `layout.tsx`, this returns structured descriptors so the\n * runtime can inject real DOM nodes (inline `<script>` bodies set via React's\n * `dangerouslySetInnerHTML` never execute).\n */\ntype ProviderSnippet = {\n defaultConsent: ConsentCategory[];\n buildTags: (identifier: string) => ScriptTagDescriptor[];\n};\n\n/**\n * NOTE (Ryan, 2026-05-28, REPL-27515): `defaultConsent` is net-new,\n * legally-sensitive categorization that does not exist elsewhere in the repo.\n * These are conservative defaults a customer can override per entry via\n * `requiredConsent`; container/CDP providers that fan out to multiple vendors\n * (GTM, Segment) require the union of categories they can serve.\n */\nconst PROVIDER_SNIPPETS: Record<ProviderType, ProviderSnippet> = {\n GA4: {\n defaultConsent: [\"analytics\"],\n buildTags: (id) => [\n {\n kind: \"external\",\n src: `https://www.googletagmanager.com/gtag/js?id=${id}`,\n },\n {\n kind: \"inline\",\n body: `window.dataLayer = window.dataLayer || [];\\nfunction gtag(){dataLayer.push(arguments);}\\ngtag('js', new Date());\\ngtag('config', '${id}');`,\n },\n ],\n },\n GoogleTagManager: {\n defaultConsent: [\"analytics\", \"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${id}');`,\n },\n ],\n },\n Meta: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');fbq('init','${id}');fbq('track','PageView');`,\n },\n ],\n },\n TikTok: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(w,d,t){w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=[\"page\",\"track\",\"identify\",\"instances\",\"debug\",\"on\",\"off\",\"once\",\"ready\",\"alias\",\"group\",\"enableCookie\",\"disableCookie\",\"holdConsent\",\"revokeConsent\",\"grantConsent\"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e};ttq.load=function(e,n){var r=\"https://analytics.tiktok.com/i18n/pixel/events.js\",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};var a=document.createElement(\"script\");a.type=\"text/javascript\",a.async=!0,a.src=r+\"?sdkid=\"+e+\"&lib=\"+t;var s=document.getElementsByTagName(\"script\")[0];s.parentNode.insertBefore(a,s)};ttq.load('${id}');ttq.page();}(window,document,'ttq');`,\n },\n ],\n },\n Pinterest: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(e){if(!window.pintrk){window.pintrk=function(){window.pintrk.queue.push(Array.prototype.slice.call(arguments))};var n=window.pintrk;n.queue=[],n.version=\"3.0\";var t=document.createElement(\"script\");t.async=!0,t.src=e;var r=document.getElementsByTagName(\"script\")[0];r.parentNode.insertBefore(t,r)}}(\"https://s.pinimg.com/ct/core.js\");pintrk('load','${id}');pintrk('page');`,\n },\n ],\n },\n Reddit: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];var t=d.createElement(\"script\");t.src=\"https://www.redditstatic.com/ads/pixel.js\",t.async=!0;var s=d.getElementsByTagName(\"script\")[0];s.parentNode.insertBefore(t,s)}}(window,document);rdt('init','${id}');rdt('track','PageVisit');`,\n },\n ],\n },\n Snapchat: {\n defaultConsent: [\"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function(){a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)};a.queue=[];var s='script';var r=t.createElement(s);r.async=!0;r.src=n;var u=t.getElementsByTagName(s)[0];u.parentNode.insertBefore(r,u);})(window,document,'https://sc-static.net/scevent.min.js');snaptr('init','${id}',{});snaptr('track','PAGE_VIEW');`,\n },\n ],\n },\n Hotjar: {\n defaultConsent: [\"analytics\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(h,o,t,j,a,r){h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};h._hjSettings={hjid:${id},hjsv:6};a=o.getElementsByTagName('head')[0];r=o.createElement('script');r.async=1;r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;a.appendChild(r);})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');`,\n },\n ],\n },\n MicrosoftClarity: {\n defaultConsent: [\"analytics\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src=\"https://www.clarity.ms/tag/\"+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,\"clarity\",\"script\",\"${id}\");`,\n },\n ],\n },\n Contentsquare: {\n defaultConsent: [\"analytics\"],\n // The UXA tag is a single async external script keyed by the 13-char tag id;\n // it bootstraps the Contentsquare `_uxa` queue itself once loaded.\n buildTags: (id) => [\n {\n kind: \"external\",\n src: `https://t.contentsquare.net/uxa/${id}.js`,\n attributes: { async: \"true\" },\n },\n ],\n },\n Segment: {\n defaultConsent: [\"analytics\", \"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `!function(){var i=\"analytics\",analytics=window[i]=window[i]||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error(\"Segment snippet included twice.\");else{analytics.invoked=!0;analytics.methods=[\"trackSubmit\",\"trackClick\",\"trackLink\",\"trackForm\",\"pageview\",\"identify\",\"reset\",\"group\",\"track\",\"ready\",\"alias\",\"debug\",\"page\",\"screen\",\"once\",\"off\",\"on\",\"addSourceMiddleware\",\"addIntegrationMiddleware\",\"setAnonymousId\",\"addDestinationMiddleware\",\"register\"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement(\"script\");t.type=\"text/javascript\";t.async=!0;t.src=\"https://cdn.segment.com/analytics.js/v1/\"+key+\"/analytics.min.js\";var n=document.getElementsByTagName(\"script\")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};analytics._writeKey=\"${id}\";analytics.SNIPPET_VERSION=\"5.2.0\";analytics.load(\"${id}\");analytics.page();}}();`,\n },\n ],\n },\n Northbeam: {\n defaultConsent: [\"analytics\", \"marketing\"],\n buildTags: (id) => [\n {\n kind: \"inline\",\n body: `(function(){var t;(n=t=t||{}).A=\"identify\",n.B=\"trackPageView\",n.C=\"fireEmailCaptureEvent\",n.D=\"fireCustomGoal\",n.E=\"firePurchaseEvent\",n.F=\"trackPageViewInitial\",n.G=\"fireSlimPurchaseEvent\",n.H=\"identifyCustomerId\";var n=\"https://j.northbeam.io/ota-sp/${id}.js\";function r(n){for(var e=[],t=1;t<arguments.length;t++)e[t-1]=arguments[t];i.push({fnName:n,args:e})}var e,i=[],a=((e={})[t.F]=function(n){r(t.F,n)},(a={_q:i})[t.A]=function(n,e){return r(t.A,n,e)},a[t.B]=function(){return r(t.B)},a[t.C]=function(n,e){return r(t.C,n,e)},a[t.D]=function(n,e){return r(t.D,n,e)},a[t.E]=function(n){return r(t.E,n)},a[t.G]=function(n){return r(t.G,n)},a[t.H]=function(n,e){return r(t.H,n,e)},Object.assign(function(n){for(var e=[],t=1;t<arguments.length;t++)e.push(arguments[t]);return r.apply(null,[n].concat(e))},a));window.Northbeam=a,(a=document.createElement(\"script\")).async=!0,a.src=n,document.head.appendChild(a),e.trackPageViewInitial(window.location.href);})()`,\n },\n ],\n },\n Gorgias: {\n // Support chat stores the visitor's chat session, which is a functional\n // preference rather than analytics or ad tracking.\n defaultConsent: [\"preferences\"],\n // The id attribute matches Gorgias's official v3 install snippet; their\n // customization scripts and support tooling look the tag up by that id.\n buildTags: (id) => [\n {\n kind: \"external\",\n src: `https://config.gorgias.chat/bundle-loader/${id}`,\n attributes: { id: \"gorgias-chat-widget-install-v3\" },\n },\n ],\n },\n};\n\n/**\n * Snippet providers don't synthesize tags (the user pastes the provider-issued\n * snippet as the entry's `body`), but they still get a first-class default\n * consent categorization like identifier providers.\n */\n/**\n * Returns the structured tag descriptors for a named provider. A single provider\n * can produce multiple tags (e.g. GA4 = external loader + inline config), which\n * the runtime injects in order.\n */\nexport function buildScriptTags({\n type,\n identifier,\n}: {\n type: ProviderType;\n identifier: string;\n}): ScriptTagDescriptor[] {\n return PROVIDER_SNIPPETS[type].buildTags(identifier);\n}\n\n/**\n * The default consent categories that gate an identifier-provider script when an\n * entry does not specify `requiredConsent`. `snippet` and `custom` entries carry\n * `requiredConsent` explicitly (the runtime has no default for them), so this is\n * only consulted for identifier providers. Overridable per entry by the customer.\n */\nexport function defaultConsentFor(type: ProviderType): ConsentCategory[] {\n return PROVIDER_SNIPPETS[type].defaultConsent;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- export type ReploScriptType = "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Cookiebot" | "snippet" | "custom" | "consentPlatform";
1
+ export type ReploScriptType = "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Gorgias" | "Cookiebot" | "snippet" | "custom" | "consentPlatform";
2
2
  export type ConsentCategory = "necessary" | "analytics" | "marketing" | "preferences" | "sale_of_data";
3
3
  export type ConsentMode = "off" | "simple" | "per-category";
4
4
  declare module "react" {
@@ -17,7 +17,7 @@ export type ScriptTagDescriptor = {
17
17
  body: string;
18
18
  };
19
19
  export type ReploScriptEntry = {
20
- type: "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Cookiebot";
20
+ type: "GA4" | "GoogleTagManager" | "Meta" | "TikTok" | "Pinterest" | "Reddit" | "Snapchat" | "Hotjar" | "MicrosoftClarity" | "Contentsquare" | "Segment" | "Northbeam" | "Gorgias" | "Cookiebot";
21
21
  identifier: string;
22
22
  requiredConsent?: ConsentCategory[];
23
23
  } | {
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "branch": "HEAD",
5
- "commit": "5076021b33cfdcd5bddd4ee545268e6d34896ee2",
6
- "builtAt": "2026-08-20T20:41:16.929Z"
5
+ "commit": "ea63e9b4d8aa2ba26cbbf1809df8fbf4d26b4d82",
6
+ "builtAt": "2026-08-21T16:44:54.297Z"
7
7
  };
@@ -0,0 +1,15 @@
1
+ export type CollectionLoaderArgs = {
2
+ handle?: string;
3
+ collectionGid?: string;
4
+ language?: string;
5
+ };
6
+ /**
7
+ * Builds the single object used as BOTH the React Query key and the loader
8
+ * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under
9
+ * `[loaderKey, args]`, so an arg sent to the loader but missing from the key
10
+ * (or vice versa) silently misses the prefetch.
11
+ *
12
+ * Keys left `undefined` drop out of React Query's key hash, so omitting a field
13
+ * here hashes the same as a prefetch that never passed it.
14
+ */
15
+ export declare function buildCollectionLoaderArgs({ handle, collectionGid, language, }: CollectionLoaderArgs): CollectionLoaderArgs;
@@ -0,0 +1,15 @@
1
+ function buildCollectionLoaderArgs({
2
+ handle,
3
+ collectionGid,
4
+ language
5
+ }) {
6
+ return {
7
+ handle,
8
+ collectionGid,
9
+ language
10
+ };
11
+ }
12
+ export {
13
+ buildCollectionLoaderArgs
14
+ };
15
+ //# sourceMappingURL=collection-loader-args.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../loaders/collection-loader-args.ts"],
4
+ "sourcesContent": ["export type CollectionLoaderArgs = {\n handle?: string;\n collectionGid?: string;\n language?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildCollectionLoaderArgs({\n handle,\n collectionGid,\n language,\n}: CollectionLoaderArgs): CollectionLoaderArgs {\n return {\n handle,\n collectionGid,\n language,\n };\n}\n"],
5
+ "mappings": "AAeO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -1,11 +1,10 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { CollectionLoaderArgs } from "./collection-loader-args";
2
3
  import type { FullCollection } from "./loader-schemas";
3
- type CollectionLoaderProps = {
4
+ type CollectionLoaderProps = CollectionLoaderArgs & {
4
5
  loaderKey: string;
5
- handle?: string;
6
- collectionGid?: string;
7
6
  children: (data: FullCollection) => ReactNode;
8
7
  fallback?: ReactNode;
9
8
  };
10
- export declare function CollectionLoader({ loaderKey, handle, collectionGid, children, fallback, }: CollectionLoaderProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CollectionLoader({ loaderKey, handle, collectionGid, language, children, fallback, }: CollectionLoaderProps): import("react/jsx-runtime").JSX.Element;
11
10
  export {};
@@ -2,22 +2,22 @@
2
2
  import { Fragment, jsx } from "react/jsx-runtime";
3
3
  import { Suspense } from "react";
4
4
  import { useSuspenseQuery } from "@tanstack/react-query";
5
+ import { buildCollectionLoaderArgs } from "./collection-loader-args";
5
6
  import { invokeLoader } from "./invoke-loader";
6
7
  import { LoaderErrorBoundary } from "./loader-error-boundary";
7
8
  import { fullCollectionSchema } from "./loader-schemas";
8
9
  import { useReportPreviewPlaceholderRender } from "./preview-placeholder";
9
10
  function CollectionLoaderInner({
10
11
  loaderKey,
11
- handle,
12
- collectionGid,
12
+ args,
13
13
  children
14
14
  }) {
15
15
  const queryResult = useSuspenseQuery({
16
- queryKey: [loaderKey, { handle, collectionGid }],
16
+ queryKey: [loaderKey, args],
17
17
  queryFn: async () => {
18
18
  const loadedData = await invokeLoader({
19
19
  loaderKey,
20
- args: { handle, collectionGid }
20
+ args
21
21
  });
22
22
  return fullCollectionSchema.parse(loadedData);
23
23
  }
@@ -29,23 +29,21 @@ function CollectionLoader({
29
29
  loaderKey,
30
30
  handle,
31
31
  collectionGid,
32
+ language,
32
33
  children,
33
34
  fallback
34
35
  }) {
36
+ const args = buildCollectionLoaderArgs({
37
+ handle,
38
+ collectionGid,
39
+ language
40
+ });
35
41
  return /* @__PURE__ */ jsx(
36
42
  LoaderErrorBoundary,
37
43
  {
38
44
  fallback: fallback ?? null,
39
- resetKey: `${loaderKey}:${handle ?? ""}:${collectionGid ?? ""}`,
40
- children: /* @__PURE__ */ jsx(Suspense, { fallback: fallback ?? null, children: /* @__PURE__ */ jsx(
41
- CollectionLoaderInner,
42
- {
43
- loaderKey,
44
- handle,
45
- collectionGid,
46
- children
47
- }
48
- ) })
45
+ resetKey: `${loaderKey}:${JSON.stringify(args)}`,
46
+ children: /* @__PURE__ */ jsx(Suspense, { fallback: fallback ?? null, children: /* @__PURE__ */ jsx(CollectionLoaderInner, { loaderKey, args, children }) })
49
47
  }
50
48
  );
51
49
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/collection-loader.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { FullCollection } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullCollectionSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionLoaderProps = {\n loaderKey: string;\n handle?: string;\n collectionGid?: string;\n children: (data: FullCollection) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionLoaderInner({\n loaderKey,\n handle,\n collectionGid,\n children,\n}: Omit<CollectionLoaderProps, \"fallback\">) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, { handle, collectionGid }],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args: { handle, collectionGid },\n });\n return fullCollectionSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionLoader({\n loaderKey,\n handle,\n collectionGid,\n children,\n fallback,\n}: CollectionLoaderProps) {\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${handle ?? \"\"}:${collectionGid ?? \"\"}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionLoaderInner\n loaderKey={loaderKey}\n handle={handle}\n collectionGid={collectionGid}\n >\n {children}\n </CollectionLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
- "mappings": ";AAwCS;AAnCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AACrC,SAAS,yCAAyC;AAUlD,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4C;AAC1C,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,EAAE,QAAQ,cAAc,CAAC;AAAA,IAC/C,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA,MAAM,EAAE,QAAQ,cAAc;AAAA,MAChC,CAAC;AACD,aAAO,qBAAqB,MAAM,UAAU;AAAA,IAC9C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,UAAU,EAAE,IAAI,iBAAiB,EAAE;AAAA,MAE7D,8BAAC,YAAS,UAAU,YAAY,MAC9B;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UAEC;AAAA;AAAA,MACH,GACF;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { CollectionLoaderArgs } from \"./collection-loader-args\";\nimport type { FullCollection } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { buildCollectionLoaderArgs } from \"./collection-loader-args\";\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullCollectionSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionLoaderProps = CollectionLoaderArgs & {\n loaderKey: string;\n children: (data: FullCollection) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: CollectionLoaderArgs;\n children: (data: FullCollection) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args,\n });\n return fullCollectionSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionLoader({\n loaderKey,\n handle,\n collectionGid,\n language,\n children,\n fallback,\n}: CollectionLoaderProps) {\n const args = buildCollectionLoaderArgs({\n handle,\n collectionGid,\n language,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </CollectionLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
+ "mappings": ";AA2CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,iCAAiC;AAC1C,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AACrC,SAAS,yCAAyC;AAQlD,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,qBAAqB,MAAM,UAAU;AAAA,IAC9C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,OAAO,0BAA0B;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,yBAAsB,WAAsB,MAC1C,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,16 @@
1
+ export type CollectionProductsLoaderArgs = {
2
+ collectionGid: string;
3
+ first?: number;
4
+ after?: string;
5
+ language?: string;
6
+ };
7
+ /**
8
+ * Builds the single object used as BOTH the React Query key and the loader
9
+ * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under
10
+ * `[loaderKey, args]`, so an arg sent to the loader but missing from the key
11
+ * (or vice versa) silently misses the prefetch.
12
+ *
13
+ * Keys left `undefined` drop out of React Query's key hash, so omitting a field
14
+ * here hashes the same as a prefetch that never passed it.
15
+ */
16
+ export declare function buildCollectionProductsLoaderArgs({ collectionGid, first, after, language, }: CollectionProductsLoaderArgs): CollectionProductsLoaderArgs;
@@ -0,0 +1,17 @@
1
+ function buildCollectionProductsLoaderArgs({
2
+ collectionGid,
3
+ first,
4
+ after,
5
+ language
6
+ }) {
7
+ return {
8
+ collectionGid,
9
+ first,
10
+ after,
11
+ language
12
+ };
13
+ }
14
+ export {
15
+ buildCollectionProductsLoaderArgs
16
+ };
17
+ //# sourceMappingURL=collection-products-loader-args.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../loaders/collection-products-loader-args.ts"],
4
+ "sourcesContent": ["export type CollectionProductsLoaderArgs = {\n collectionGid: string;\n first?: number;\n after?: string;\n language?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildCollectionProductsLoaderArgs({\n collectionGid,\n first,\n after,\n language,\n}: CollectionProductsLoaderArgs): CollectionProductsLoaderArgs {\n return {\n collectionGid,\n first,\n after,\n language,\n };\n}\n"],
5
+ "mappings": "AAgBO,SAAS,kCAAkC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+D;AAC7D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -1,12 +1,10 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { CollectionProductsLoaderArgs } from "./collection-products-loader-args";
2
3
  import type { PaginatedProducts } from "./loader-schemas";
3
- type CollectionProductsLoaderProps = {
4
+ type CollectionProductsLoaderProps = CollectionProductsLoaderArgs & {
4
5
  loaderKey: string;
5
- collectionGid: string;
6
- first?: number;
7
- after?: string;
8
6
  children: (data: PaginatedProducts) => ReactNode;
9
7
  fallback?: ReactNode;
10
8
  };
11
- export declare function CollectionProductsLoader({ loaderKey, collectionGid, first, after, children, fallback, }: CollectionProductsLoaderProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CollectionProductsLoader({ loaderKey, collectionGid, first, after, language, children, fallback, }: CollectionProductsLoaderProps): import("react/jsx-runtime").JSX.Element;
12
10
  export {};
@@ -2,23 +2,22 @@
2
2
  import { Fragment, jsx } from "react/jsx-runtime";
3
3
  import { Suspense } from "react";
4
4
  import { useSuspenseQuery } from "@tanstack/react-query";
5
+ import { buildCollectionProductsLoaderArgs } from "./collection-products-loader-args";
5
6
  import { invokeLoader } from "./invoke-loader";
6
7
  import { LoaderErrorBoundary } from "./loader-error-boundary";
7
8
  import { paginatedProductsSchema } from "./loader-schemas";
8
9
  import { useReportPreviewPlaceholderRender } from "./preview-placeholder";
9
10
  function CollectionProductsLoaderInner({
10
11
  loaderKey,
11
- collectionGid,
12
- first,
13
- after,
12
+ args,
14
13
  children
15
14
  }) {
16
15
  const queryResult = useSuspenseQuery({
17
- queryKey: [loaderKey, { collectionGid, first, after }],
16
+ queryKey: [loaderKey, args],
18
17
  queryFn: async () => {
19
18
  const loadedData = await invokeLoader({
20
19
  loaderKey,
21
- args: { collectionGid, first, after }
20
+ args
22
21
  });
23
22
  return paginatedProductsSchema.parse(loadedData);
24
23
  }
@@ -31,24 +30,22 @@ function CollectionProductsLoader({
31
30
  collectionGid,
32
31
  first,
33
32
  after,
33
+ language,
34
34
  children,
35
35
  fallback
36
36
  }) {
37
+ const args = buildCollectionProductsLoaderArgs({
38
+ collectionGid,
39
+ first,
40
+ after,
41
+ language
42
+ });
37
43
  return /* @__PURE__ */ jsx(
38
44
  LoaderErrorBoundary,
39
45
  {
40
46
  fallback: fallback ?? null,
41
- resetKey: `${loaderKey}:${collectionGid}:${first ?? ""}:${after ?? ""}`,
42
- children: /* @__PURE__ */ jsx(Suspense, { fallback: fallback ?? null, children: /* @__PURE__ */ jsx(
43
- CollectionProductsLoaderInner,
44
- {
45
- loaderKey,
46
- collectionGid,
47
- first,
48
- after,
49
- children
50
- }
51
- ) })
47
+ resetKey: `${loaderKey}:${JSON.stringify(args)}`,
48
+ children: /* @__PURE__ */ jsx(Suspense, { fallback: fallback ?? null, children: /* @__PURE__ */ jsx(CollectionProductsLoaderInner, { loaderKey, args, children }) })
52
49
  }
53
50
  );
54
51
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/collection-products-loader.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { PaginatedProducts } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { paginatedProductsSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionProductsLoaderProps = {\n loaderKey: string;\n collectionGid: string;\n first?: number;\n after?: string;\n children: (data: PaginatedProducts) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionProductsLoaderInner({\n loaderKey,\n collectionGid,\n first,\n after,\n children,\n}: Omit<CollectionProductsLoaderProps, \"fallback\">) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, { collectionGid, first, after }],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args: { collectionGid, first, after },\n });\n return paginatedProductsSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionProductsLoader({\n loaderKey,\n collectionGid,\n first,\n after,\n children,\n fallback,\n}: CollectionProductsLoaderProps) {\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${collectionGid}:${first ?? \"\"}:${after ?? \"\"}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionProductsLoaderInner\n loaderKey={loaderKey}\n collectionGid={collectionGid}\n first={first}\n after={after}\n >\n {children}\n </CollectionProductsLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
- "mappings": ";AA0CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,+BAA+B;AACxC,SAAS,yCAAyC;AAWlD,SAAS,8BAA8B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoD;AAClD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,EAAE,eAAe,OAAO,MAAM,CAAC;AAAA,IACrD,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA,MAAM,EAAE,eAAe,OAAO,MAAM;AAAA,MACtC,CAAC;AACD,aAAO,wBAAwB,MAAM,UAAU;AAAA,IACjD;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,aAAa,IAAI,SAAS,EAAE,IAAI,SAAS,EAAE;AAAA,MAErE,8BAAC,YAAS,UAAU,YAAY,MAC9B;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UAEC;AAAA;AAAA,MACH,GACF;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { CollectionProductsLoaderArgs } from \"./collection-products-loader-args\";\nimport type { PaginatedProducts } from \"./loader-schemas\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { buildCollectionProductsLoaderArgs } from \"./collection-products-loader-args\";\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { paginatedProductsSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\n\ntype CollectionProductsLoaderProps = CollectionProductsLoaderArgs & {\n loaderKey: string;\n children: (data: PaginatedProducts) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction CollectionProductsLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: CollectionProductsLoaderArgs;\n children: (data: PaginatedProducts) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({\n loaderKey,\n args,\n });\n return paginatedProductsSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function CollectionProductsLoader({\n loaderKey,\n collectionGid,\n first,\n after,\n language,\n children,\n fallback,\n}: CollectionProductsLoaderProps) {\n const args = buildCollectionProductsLoaderArgs({\n collectionGid,\n first,\n after,\n language,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <CollectionProductsLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </CollectionProductsLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
+ "mappings": ";AA2CS;AArCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,yCAAyC;AAClD,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,+BAA+B;AACxC,SAAS,yCAAyC;AAQlD,SAAS,8BAA8B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa;AAAA,QACpC;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,wBAAwB,MAAM,UAAU;AAAA,IACjD;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,QAAM,OAAO,kCAAkC;AAAA,IAC7C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,iCAA8B,WAAsB,MAClD,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -7,6 +7,7 @@ export type ProductLoaderArgs = {
7
7
  productId?: string;
8
8
  productMetafieldIdentifiers?: MetafieldIdentifier[];
9
9
  variantMetafieldIdentifiers?: MetafieldIdentifier[];
10
+ language?: string;
10
11
  };
11
12
  /**
12
13
  * Builds the single object used as BOTH the React Query key and the loader
@@ -18,4 +19,4 @@ export type ProductLoaderArgs = {
18
19
  * Keys left `undefined` drop out of React Query's key hash, so omitting a field
19
20
  * here hashes the same as a prefetch that never passed it.
20
21
  */
21
- export declare function buildProductLoaderArgs({ handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, }: ProductLoaderArgs): ProductLoaderArgs;
22
+ export declare function buildProductLoaderArgs({ handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, language, }: ProductLoaderArgs): ProductLoaderArgs;
@@ -2,13 +2,15 @@ function buildProductLoaderArgs({
2
2
  handle,
3
3
  productId,
4
4
  productMetafieldIdentifiers,
5
- variantMetafieldIdentifiers
5
+ variantMetafieldIdentifiers,
6
+ language
6
7
  }) {
7
8
  return {
8
9
  handle,
9
10
  productId,
10
11
  productMetafieldIdentifiers,
11
- variantMetafieldIdentifiers
12
+ variantMetafieldIdentifiers,
13
+ language
12
14
  };
13
15
  }
14
16
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/product-loader-args.ts"],
4
- "sourcesContent": ["export type MetafieldIdentifier = {\n namespace: string;\n key: string;\n};\n\nexport type ProductLoaderArgs = {\n handle?: string;\n productId?: string;\n productMetafieldIdentifiers?: MetafieldIdentifier[];\n variantMetafieldIdentifiers?: MetafieldIdentifier[];\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch \u2014 the client refetches without\n * it and the page renders incomplete data instead of erroring.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n}: ProductLoaderArgs): ProductLoaderArgs {\n return {\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n };\n}\n"],
5
- "mappings": "AAsBO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AACvC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["export type MetafieldIdentifier = {\n namespace: string;\n key: string;\n};\n\nexport type ProductLoaderArgs = {\n handle?: string;\n productId?: string;\n productMetafieldIdentifiers?: MetafieldIdentifier[];\n variantMetafieldIdentifiers?: MetafieldIdentifier[];\n language?: string;\n};\n\n/**\n * Builds the single object used as BOTH the React Query key and the loader\n * payload. They must stay identical: `PrefetchedLoaders` seeds the cache under\n * `[loaderKey, args]`, so an arg sent to the loader but missing from the key\n * (or vice versa) silently misses the prefetch \u2014 the client refetches without\n * it and the page renders incomplete data instead of erroring.\n *\n * Keys left `undefined` drop out of React Query's key hash, so omitting a field\n * here hashes the same as a prefetch that never passed it.\n */\nexport function buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n}: ProductLoaderArgs): ProductLoaderArgs {\n return {\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n };\n}\n"],
5
+ "mappings": "AAuBO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AACvC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -6,5 +6,5 @@ type ProductLoaderProps = ProductLoaderArgs & {
6
6
  children: (data: FullProduct) => ReactNode;
7
7
  fallback?: ReactNode;
8
8
  };
9
- export declare function ProductLoader({ loaderKey, handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, children, fallback, }: ProductLoaderProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function ProductLoader({ loaderKey, handle, productId, productMetafieldIdentifiers, variantMetafieldIdentifiers, language, children, fallback, }: ProductLoaderProps): import("react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -28,6 +28,7 @@ function ProductLoader({
28
28
  productId,
29
29
  productMetafieldIdentifiers,
30
30
  variantMetafieldIdentifiers,
31
+ language,
31
32
  children,
32
33
  fallback
33
34
  }) {
@@ -35,7 +36,8 @@ function ProductLoader({
35
36
  handle,
36
37
  productId,
37
38
  productMetafieldIdentifiers,
38
- variantMetafieldIdentifiers
39
+ variantMetafieldIdentifiers,
40
+ language
39
41
  });
40
42
  return /* @__PURE__ */ jsx(
41
43
  LoaderErrorBoundary,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../loaders/product-loader.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { FullProduct } from \"./loader-schemas\";\nimport type { ProductLoaderArgs } from \"./product-loader-args\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullProductSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\nimport { buildProductLoaderArgs } from \"./product-loader-args\";\n\ntype ProductLoaderProps = ProductLoaderArgs & {\n loaderKey: string;\n children: (data: FullProduct) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction ProductLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: ProductLoaderArgs;\n children: (data: FullProduct) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({ loaderKey, args });\n return fullProductSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function ProductLoader({\n loaderKey,\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n children,\n fallback,\n}: ProductLoaderProps) {\n const args = buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <ProductLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </ProductLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
- "mappings": ";AAwCS;AAlCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,yCAAyC;AAClD,SAAS,8BAA8B;AAQvC,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AACzD,aAAO,kBAAkB,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,OAAO,uBAAuB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,sBAAmB,WAAsB,MACvC,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { FullProduct } from \"./loader-schemas\";\nimport type { ProductLoaderArgs } from \"./product-loader-args\";\n\nimport { Suspense } from \"react\";\n\nimport { useSuspenseQuery } from \"@tanstack/react-query\";\n\nimport { invokeLoader } from \"./invoke-loader\";\nimport { LoaderErrorBoundary } from \"./loader-error-boundary\";\nimport { fullProductSchema } from \"./loader-schemas\";\nimport { useReportPreviewPlaceholderRender } from \"./preview-placeholder\";\nimport { buildProductLoaderArgs } from \"./product-loader-args\";\n\ntype ProductLoaderProps = ProductLoaderArgs & {\n loaderKey: string;\n children: (data: FullProduct) => ReactNode;\n fallback?: ReactNode;\n};\n\nfunction ProductLoaderInner({\n loaderKey,\n args,\n children,\n}: {\n loaderKey: string;\n args: ProductLoaderArgs;\n children: (data: FullProduct) => ReactNode;\n}) {\n const queryResult = useSuspenseQuery({\n queryKey: [loaderKey, args],\n queryFn: async () => {\n const loadedData = await invokeLoader({ loaderKey, args });\n return fullProductSchema.parse(loadedData);\n },\n });\n useReportPreviewPlaceholderRender(queryResult.data);\n\n return <>{children(queryResult.data)}</>;\n}\n\nexport function ProductLoader({\n loaderKey,\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n children,\n fallback,\n}: ProductLoaderProps) {\n const args = buildProductLoaderArgs({\n handle,\n productId,\n productMetafieldIdentifiers,\n variantMetafieldIdentifiers,\n language,\n });\n\n return (\n <LoaderErrorBoundary\n fallback={fallback ?? null}\n resetKey={`${loaderKey}:${JSON.stringify(args)}`}\n >\n <Suspense fallback={fallback ?? null}>\n <ProductLoaderInner loaderKey={loaderKey} args={args}>\n {children}\n </ProductLoaderInner>\n </Suspense>\n </LoaderErrorBoundary>\n );\n}\n"],
5
+ "mappings": ";AAwCS;AAlCT,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,yCAAyC;AAClD,SAAS,8BAA8B;AAQvC,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,iBAAiB;AAAA,IACnC,UAAU,CAAC,WAAW,IAAI;AAAA,IAC1B,SAAS,YAAY;AACnB,YAAM,aAAa,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AACzD,aAAO,kBAAkB,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,oCAAkC,YAAY,IAAI;AAElD,SAAO,gCAAG,mBAAS,YAAY,IAAI,GAAE;AACvC;AAEO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,OAAO,uBAAuB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB,UAAU,GAAG,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,MAE9C,8BAAC,YAAS,UAAU,YAAY,MAC9B,8BAAC,sBAAmB,WAAsB,MACvC,UACH,GACF;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@replohq/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "reploBuild": {
5
5
  "packageName": "@replohq/sdk",
6
- "version": "0.8.0",
6
+ "version": "0.10.0",
7
7
  "branch": "HEAD",
8
- "commit": "5076021b33cfdcd5bddd4ee545268e6d34896ee2",
9
- "builtAt": "2026-08-20T20:41:16.929Z"
8
+ "commit": "ea63e9b4d8aa2ba26cbbf1809df8fbf4d26b4d82",
9
+ "builtAt": "2026-08-21T16:44:54.297Z"
10
10
  },
11
11
  "description": "Replo SDK — cart, analytics, and data loaders for agent-built Next.js sites.",
12
12
  "license": "SEE LICENSE IN LICENSE",
@@ -181,6 +181,14 @@
181
181
  "types": "./loaders/product-loader-args.d.ts",
182
182
  "default": "./loaders/product-loader-args.js"
183
183
  },
184
+ "./loaders/collection-loader-args": {
185
+ "types": "./loaders/collection-loader-args.d.ts",
186
+ "default": "./loaders/collection-loader-args.js"
187
+ },
188
+ "./loaders/collection-products-loader-args": {
189
+ "types": "./loaders/collection-products-loader-args.d.ts",
190
+ "default": "./loaders/collection-products-loader-args.js"
191
+ },
184
192
  "./orders/order-status": {
185
193
  "types": "./orders/order-status.d.ts",
186
194
  "default": "./orders/order-status.js"