@weatherboard/cms 0.5.0 → 0.7.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.
Files changed (49) hide show
  1. package/README.md +117 -0
  2. package/dist/contracts/query.d.cts +3 -0
  3. package/dist/contracts/query.d.mts +3 -0
  4. package/dist/contracts/query.d.ts +3 -0
  5. package/dist/index.cjs +5 -1
  6. package/dist/index.cjs.map +4 -4
  7. package/dist/index.d.cts +3 -0
  8. package/dist/index.d.mts +3 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.mjs +5 -1
  11. package/dist/index.mjs.map +4 -4
  12. package/dist/next.cjs +5 -1
  13. package/dist/next.cjs.map +4 -4
  14. package/dist/next.d.cts +3 -0
  15. package/dist/next.d.mts +3 -0
  16. package/dist/next.d.ts +3 -0
  17. package/dist/next.mjs +5 -1
  18. package/dist/next.mjs.map +4 -4
  19. package/dist/portable/menu-options.d.cts +8 -0
  20. package/dist/portable/menu-options.d.mts +8 -0
  21. package/dist/portable/menu-options.d.ts +8 -0
  22. package/dist/portable/menu.d.cts +69 -0
  23. package/dist/portable/menu.d.mts +69 -0
  24. package/dist/portable/menu.d.ts +69 -0
  25. package/dist/portable/sections.d.cts +50 -7
  26. package/dist/portable/sections.d.mts +50 -7
  27. package/dist/portable/sections.d.ts +50 -7
  28. package/dist/portable/site-content.d.cts +41 -10
  29. package/dist/portable/site-content.d.mts +41 -10
  30. package/dist/portable/site-content.d.ts +41 -10
  31. package/dist/sanity.cjs +1 -1
  32. package/dist/sanity.cjs.map +2 -2
  33. package/dist/sanity.mjs +1 -1
  34. package/dist/sanity.mjs.map +2 -2
  35. package/dist/server.cjs +5 -1
  36. package/dist/server.cjs.map +4 -4
  37. package/dist/server.d.cts +3 -0
  38. package/dist/server.d.mts +3 -0
  39. package/dist/server.d.ts +3 -0
  40. package/dist/server.mjs +5 -1
  41. package/dist/server.mjs.map +4 -4
  42. package/dist/site-content.cjs +10 -3
  43. package/dist/site-content.cjs.map +4 -4
  44. package/dist/site-content.d.cts +2 -2
  45. package/dist/site-content.d.mts +2 -2
  46. package/dist/site-content.d.ts +2 -2
  47. package/dist/site-content.mjs +10 -3
  48. package/dist/site-content.mjs.map +4 -4
  49. package/package.json +2 -1
@@ -20,9 +20,9 @@
20
20
  * anything writing over the API skips them entirely. So every document is
21
21
  * checked here again, and a malformed one is refused BY NAME
22
22
  * (`MalformedContentError`, code `malformed-content`) listing every problem
23
- * with its path, rather than rendered half-empty. A page that renders with a
24
- * missing headline and a page whose content is broken look identical to a
25
- * visitor; a build that fails naming `hero.headline` does not.
23
+ * with its path, rather than rendered half-empty. A missing home headline
24
+ * uses siteHero only when the home document explicitly selects it and that
25
+ * document supplies a valid heading. Otherwise the home page is refused.
26
26
  *
27
27
  * Absent is not malformed: `null` from `home()` means nobody has created the
28
28
  * home page yet, and a site decides what to do about that.
@@ -60,7 +60,7 @@
60
60
  * kinds, the A-1876 layout names and the warning codes.
61
61
  *
62
62
  * Two places the composition cannot carry a proposed marker: a `cta` block's
63
- * plain strings, and the campaign's title and body (which travel as Markdown).
63
+ * plain strings, and the campaign's title and body (which travel as rich body content).
64
64
  * There the text is returned plain and the line is still listed in
65
65
  * `proposedCopy`, which is the list a dashboard and a site both read for
66
66
  * approval. Nothing is dropped silently.
@@ -71,6 +71,30 @@ export type CopyInput = string | {
71
71
  readonly text: string;
72
72
  readonly copySource: "captured" | "proposed";
73
73
  };
74
+ export type RichInline = {
75
+ readonly children: readonly {
76
+ readonly text: string;
77
+ readonly marks: readonly string[];
78
+ }[];
79
+ readonly markDefs: readonly {
80
+ readonly key: string;
81
+ readonly href: string;
82
+ }[];
83
+ };
84
+ export type RichBodyPart = {
85
+ readonly kind: "block";
86
+ readonly style: "normal" | "h2" | "h3" | "blockquote";
87
+ readonly listItem: "bullet" | "number" | null;
88
+ readonly level: number;
89
+ readonly content: RichInline;
90
+ } | {
91
+ readonly kind: "heading";
92
+ readonly text: string;
93
+ } | {
94
+ readonly kind: "table";
95
+ readonly rows: readonly (readonly RichInline[])[];
96
+ };
97
+ export type RichBody = string | readonly RichBodyPart[];
74
98
  export type ActionInput = {
75
99
  readonly label: CopyInput;
76
100
  readonly href: string;
@@ -110,12 +134,14 @@ export type CompositionBlockInput = {
110
134
  } | {
111
135
  readonly kind: "accent_band";
112
136
  readonly heading: CopyInput;
137
+ readonly tail?: CopyInput | null;
113
138
  readonly body: CopyInput;
114
139
  readonly action: ActionInput | null;
115
140
  readonly image: string | null;
116
141
  } | {
117
142
  readonly kind: "cta";
118
143
  readonly heading: string;
144
+ readonly image?: string | null;
119
145
  readonly body: string | null;
120
146
  readonly link: {
121
147
  readonly label: string;
@@ -136,16 +162,17 @@ export type ProposedCopy = {
136
162
  export type CampaignState = "shown" | "off" | "not-started" | "ended" | "none";
137
163
  export type HomeContent = {
138
164
  readonly composition: CompositionInput;
139
- /** The page body as Markdown: the campaign's title and text when it is shown, otherwise empty. */
140
- readonly body: string;
165
+ /** Campaign text as Markdown, or structured blocks and tables when it contains a table. */
166
+ readonly body: RichBody;
141
167
  readonly campaign: CampaignState;
142
168
  readonly proposedCopy: readonly ProposedCopy[];
143
169
  };
144
170
  export type PageContent = {
145
171
  readonly slug: string;
146
172
  readonly title: string;
173
+ readonly titleTail?: string;
147
174
  readonly composition: CompositionInput;
148
- readonly body: string;
175
+ readonly body: RichBody;
149
176
  readonly migrated: boolean;
150
177
  readonly proposedCopy: readonly ProposedCopy[];
151
178
  /**
@@ -191,8 +218,10 @@ export declare const READER_SITE_SETTINGS_ID = "siteSettings";
191
218
  * upload one yet (the dashboard slice decides how), so one arriving means
192
219
  * something wrote the document by hand, and a page silently missing a picture
193
220
  * is the failure this reader exists to prevent.
221
+ * Text-only input remains a Markdown string. Input with a table produces
222
+ * ordered structured blocks and cells that never enter a Markdown parser.
194
223
  */
195
- export declare function portableTextToMarkdown(value: unknown): string;
224
+ export declare function portableTextToMarkdown(value: unknown): RichBody;
196
225
  /** Whether a campaign is shown at `now`, and if not, why not. */
197
226
  export declare function campaignState(campaign: unknown, now: Date): CampaignState;
198
227
  /**
@@ -208,8 +237,10 @@ export declare function parseContentPage(document: unknown): PageContent;
208
237
  export declare function parseSiteSettings(document: unknown): SiteSettingsContent;
209
238
  /** By fixed id: a second home page at a random id is never read. */
210
239
  export declare const HOME_PAGE_DOCUMENT_QUERY = "*[_id == $id][0]";
211
- export declare const CONTENT_PAGES_QUERY = "*[_type == \"page\" && defined(slug.current)]|order(slug.current asc)";
212
- export declare const CONTENT_PAGE_BY_SLUG_QUERY = "*[_type == \"page\" && slug.current == $slug][0]";
240
+ /** One snapshot contains both possible headline sources. */
241
+ export declare const HOME_PAGE_WITH_SITE_HERO_QUERY = "*[_id == $id][0]{..., \"_siteHero\": *[_id == \"siteHero\" && _type == \"siteHero\"][0]{heading}}";
242
+ export declare const CONTENT_PAGES_QUERY = "*[_type == \"page\" && defined(slug.current)]|order(slug.current asc){..., \"sections\": coalesce(sections[]{..., _type == \"menuBlock\" => {menu->{_type, _id, _rev, _updatedAt, title, locationKeys, note, signOff,\n variants[]{_key, label, note, sections[]{_key, title, service, items[]{\n _key, name, description, priceNote, dietary, allergenNote, availability,\n prices[]{_key, label, amount{minor, currency}}, extras[]{_key, name, amount{minor, currency}}\n }}}}}, _type == \"linkListBlock\" => {links[]{..., \"page\": page->{title, \"slug\": slug.current}}}}, sections)}";
243
+ export declare const CONTENT_PAGE_BY_SLUG_QUERY = "*[_type == \"page\" && slug.current == $slug][0]{..., \"sections\": coalesce(sections[]{..., _type == \"menuBlock\" => {menu->{_type, _id, _rev, _updatedAt, title, locationKeys, note, signOff,\n variants[]{_key, label, note, sections[]{_key, title, service, items[]{\n _key, name, description, priceNote, dietary, allergenNote, availability,\n prices[]{_key, label, amount{minor, currency}}, extras[]{_key, name, amount{minor, currency}}\n }}}}}, _type == \"linkListBlock\" => {links[]{..., \"page\": page->{title, \"slug\": slug.current}}}}, sections)}";
213
244
  export interface SiteContentReader {
214
245
  /** `null` when no home page document exists yet. */
215
246
  home: (options: {
package/dist/sanity.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var w=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var R=(e,t)=>{for(var n in t)w(e,n,{get:t[n],enumerable:!0})},x=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of z(t))!$.call(e,s)&&s!==n&&w(e,s,{get:()=>t[s],enumerable:!(r=E(t,s))||r.enumerable});return e};var P=e=>x(w({},"__esModule",{value:!0}),e);var B={};R(B,{createSanityAdapter:()=>v,sanityBindingFromEnv:()=>I});module.exports=P(B);var Y=require("server-only");var M=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,D=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,N=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function T(e){if(!e||!Array.isArray(e.types)||e.types.length===0)throw new TypeError("CMS dependencies require document types");let t=[...e.types];for(let r of t)if(typeof r!="string"||!M.test(r))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let n=e.ids===void 0?void 0:[...e.ids];for(let r of n??[])if(typeof r!="string"||!D.test(r)||/^(drafts|versions)\./.test(r))throw new TypeError("Invalid CMS document ID");if(new Set(t).size+new Set(n).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(t),...n===void 0?{}:{ids:Object.freeze(n)}})}function b(e){if(!e||typeof e.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(e.name)||typeof e.query!="string"||e.query.trim()===""||typeof e.resolve!="function")throw new TypeError("Invalid CMS query configuration");let t=e.params;if(!t||typeof t!="object"||Object.getPrototypeOf(t)!==Object.prototype&&Object.getPrototypeOf(t)!==null)throw new TypeError("CMS params must be plain JSON scalars");let n={};for(let r of Reflect.ownKeys(t)){let s=Object.getOwnPropertyDescriptor(t,r);if(typeof r!="string"||!s||!Object.hasOwn(s,"value")||!s.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=s.value;if(!(i===null||typeof i=="string"||typeof i=="boolean"||typeof i=="number"&&Number.isFinite(i)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(n,r,{value:i,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(n),dependencies:T(e.dependencies),resolve:e.resolve})}function C(e,t){if(typeof e!="string"||e.length>77||!N.test(e))throw new TypeError("Invalid CMS scope");let n=T(t),r=[...[...new Set(n.types)].sort().map(s=>`cms:${e}:type:${s}`),...[...new Set(n.ids??[])].sort().map(s=>`cms:${e}:id:${s}`)];return Object.freeze(r)}var _=2*1024*1024;function A(e){if(!e||typeof e.projectId!="string"||!/^[a-z0-9]{6,12}$/.test(e.projectId)||typeof e.dataset!="string"||!/^[a-z][a-z0-9_-]{0,63}$/.test(e.dataset)||typeof e.apiVersion!="string"||!/^v?\d{4}-\d{2}-\d{2}$/.test(e.apiVersion))throw new TypeError("Invalid Sanity binding configuration");return Object.freeze({projectId:e.projectId,dataset:e.dataset,apiVersion:e.apiVersion.replace(/^v/,"")})}function v(e){let t=A(e?.binding),n=e.timeoutMs??1500,r=e.readToken;if(!Number.isSafeInteger(n)||n<=0||n>2147483647||e.fetchImpl!==void 0&&typeof e.fetchImpl!="function"||r!==void 0&&(typeof r!="string"||r.trim()===""||/[\r\n]/.test(r)))throw new TypeError("Invalid Sanity adapter configuration");let s=e.fetchImpl,i=`${t.projectId}.${t.dataset}`;return Object.freeze({scope:i,async read(O,c){let y;try{if(!c||!Number.isSafeInteger(c.revalidateSeconds)||c.revalidateSeconds<3600||!Array.isArray(c.tags))throw new TypeError;let o=[],p=[];for(let d of c.tags){if(typeof d!="string")throw new TypeError;if(d.startsWith(`cms:${i}:type:`))o.push(d.slice(`cms:${i}:type:`.length));else if(d.startsWith(`cms:${i}:id:`))p.push(d.slice(`cms:${i}:id:`.length));else throw new TypeError}let l=C(i,{types:o,ids:p});if(l.length!==c.tags.length||l.some((d,a)=>d!==c.tags[a]))throw new TypeError;y=b({...O,dependencies:{types:o,ids:p},resolve:d=>({data:d,fallbackFields:[]})})}catch{throw new TypeError("Invalid Sanity read configuration")}let f=new URL(`https://${t.projectId}.api.sanity.io/v${t.apiVersion}/data/query/${t.dataset}`);f.searchParams.set("query",y.query),f.searchParams.set("perspective","published");for(let o of Object.keys(y.params).sort())f.searchParams.set(`$${o}`,JSON.stringify(y.params[o]));let h=new AbortController,m,u=!1,g=()=>{h.abort(),m&&m.cancel().catch(()=>{})},S,k=new Promise(o=>{S=setTimeout(()=>{u=!0,g(),o({ok:!1,reason:"timeout"})},n)}),j=async()=>{try{let o=await(s??globalThis.fetch)(f.href,{method:"GET",redirect:"error",signal:h.signal,headers:r===void 0?{}:{Authorization:`Bearer ${r}`},next:{revalidate:c.revalidateSeconds,tags:[...c.tags]}});if(u)return o.body?.cancel().catch(()=>{}),{ok:!1,reason:"timeout"};if(!o.ok){o.body?.cancel().catch(()=>{});let a=o.status;return{ok:!1,reason:a===402?"plan-limit":a===401||a===403?"permission":a===429?"rate-limit":"upstream",status:a}}if(!o.body)return{ok:!1,reason:"malformed"};m=o.body.getReader();let p=0,l="",d=new TextDecoder("utf-8",{fatal:!0});for(;;){let a=await m.read();if(u)return{ok:!1,reason:"timeout"};if(a.done)break;if(p+=a.value.byteLength,p>_)return g(),{ok:!1,reason:"malformed"};try{l+=d.decode(a.value,{stream:!0})}catch{return g(),{ok:!1,reason:"malformed"}}}try{l+=d.decode();let a=JSON.parse(l);return!a||typeof a!="object"||Array.isArray(a)||!Object.hasOwn(a,"result")?{ok:!1,reason:"malformed"}:{ok:!0,value:a.result}}catch{return{ok:!1,reason:"malformed"}}}catch{return{ok:!1,reason:u?"timeout":"network"}}};try{return await Promise.race([j(),k])}finally{clearTimeout(S)}}})}function I(e){return A({projectId:e.SANITY_PROJECT_ID,dataset:e.SANITY_DATASET,apiVersion:e.SANITY_API_VERSION})}0&&(module.exports={createSanityAdapter,sanityBindingFromEnv});
1
+ "use strict";var h=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var M=(e,t)=>{for(var n in t)h(e,n,{get:t[n],enumerable:!0})},R=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $(t))!z.call(e,o)&&o!==n&&h(e,o,{get:()=>t[o],enumerable:!(r=j(t,o))||r.enumerable});return e};var _=e=>R(h({},"__esModule",{value:!0}),e);var B={};M(B,{createSanityAdapter:()=>I,sanityBindingFromEnv:()=>O});module.exports=_(B);var U=require("server-only");var x=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,P=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,D=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function S(e){if(!e||!Array.isArray(e.types)||e.types.length===0)throw new TypeError("CMS dependencies require document types");let t=[...e.types];for(let r of t)if(typeof r!="string"||!x.test(r))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let n=e.ids===void 0?void 0:[...e.ids];for(let r of n??[])if(typeof r!="string"||!P.test(r)||/^(drafts|versions)\./.test(r))throw new TypeError("Invalid CMS document ID");if(new Set(t).size+new Set(n).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(t),...n===void 0?{}:{ids:Object.freeze(n)}})}function b(e){if(!e||typeof e.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(e.name)||typeof e.query!="string"||e.query.trim()===""||typeof e.resolve!="function")throw new TypeError("Invalid CMS query configuration");let t=e.params;if(!t||typeof t!="object"||Object.getPrototypeOf(t)!==Object.prototype&&Object.getPrototypeOf(t)!==null)throw new TypeError("CMS params must be plain JSON scalars");let n={};for(let r of Reflect.ownKeys(t)){let o=Object.getOwnPropertyDescriptor(t,r);if(typeof r!="string"||!o||!Object.hasOwn(o,"value")||!o.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=o.value;if(!(i===null||typeof i=="string"||typeof i=="boolean"||typeof i=="number"&&Number.isFinite(i)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(n,r,{value:i,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(n),dependencies:S(e.dependencies),resolve:e.resolve})}function C(e,t){if(typeof e!="string"||e.length>77||!D.test(e))throw new TypeError("Invalid CMS scope");let n=S(t),r=[...[...new Set(n.types)].sort().map(o=>`cms:${e}:type:${o}`),...[...new Set(n.ids??[])].sort().map(o=>`cms:${e}:id:${o}`)];return Object.freeze(r)}var N=2*1024*1024;function v(e){if(!e||typeof e.projectId!="string"||!/^[a-z0-9]{6,12}$/.test(e.projectId)||typeof e.dataset!="string"||!/^[a-z][a-z0-9_-]{0,63}$/.test(e.dataset)||typeof e.apiVersion!="string"||!/^v?\d{4}-\d{2}-\d{2}$/.test(e.apiVersion))throw new TypeError("Invalid Sanity binding configuration");return Object.freeze({projectId:e.projectId,dataset:e.dataset,apiVersion:e.apiVersion.replace(/^v/,"")})}function I(e){let t=v(e?.binding),n=e.timeoutMs??1500,r=e.readToken;if(!Number.isSafeInteger(n)||n<=0||n>2147483647||e.fetchImpl!==void 0&&typeof e.fetchImpl!="function"||r!==void 0&&(typeof r!="string"||r.trim()===""||/[\r\n]/.test(r)))throw new TypeError("Invalid Sanity adapter configuration");let o=e.fetchImpl,i=`${t.projectId}.${t.dataset}`;return Object.freeze({scope:i,async read(A,c){let y;try{if(!c||!Number.isSafeInteger(c.revalidateSeconds)||c.revalidateSeconds<3600||!Array.isArray(c.tags))throw new TypeError;let s=[],p=[];for(let d of c.tags){if(typeof d!="string")throw new TypeError;if(d.startsWith(`cms:${i}:type:`))s.push(d.slice(`cms:${i}:type:`.length));else if(d.startsWith(`cms:${i}:id:`))p.push(d.slice(`cms:${i}:id:`.length));else throw new TypeError}let l=C(i,{types:s,ids:p});if(l.length!==c.tags.length||l.some((d,a)=>d!==c.tags[a]))throw new TypeError;y=b({...A,dependencies:{types:s,ids:p},resolve:d=>({data:d,fallbackFields:[]})})}catch{throw new TypeError("Invalid Sanity read configuration")}let f=new URL(`https://${t.projectId}.api.sanity.io/v${t.apiVersion}/data/query/${t.dataset}`);f.searchParams.set("query",y.query),f.searchParams.set("perspective","published");for(let s of Object.keys(y.params).sort())f.searchParams.set(`$${s}`,JSON.stringify(y.params[s]));let w=new AbortController,u,m=!1,g=()=>{w.abort(),u&&u.cancel().catch(()=>{})},T,E=new Promise(s=>{T=setTimeout(()=>{m=!0,g(),s({ok:!1,reason:"timeout"})},n)}),k=async()=>{try{let s=await(o??globalThis.fetch)(f.href,{method:"GET",redirect:"error",signal:w.signal,headers:r===void 0?{}:{Authorization:`Bearer ${r}`},next:{revalidate:c.revalidateSeconds,tags:[...c.tags]}});if(m)return s.body?.cancel().catch(()=>{}),{ok:!1,reason:"timeout"};if(!s.ok){s.body?.cancel().catch(()=>{});let a=s.status;return{ok:!1,reason:a===402?"plan-limit":a===401||a===403?"permission":a===429?"rate-limit":"upstream",status:a}}if(!s.body)return{ok:!1,reason:"malformed"};u=s.body.getReader();let p=0,l="",d=new TextDecoder("utf-8",{fatal:!0});for(;;){let a=await u.read();if(m)return{ok:!1,reason:"timeout"};if(a.done)break;if(p+=a.value.byteLength,p>N)return g(),{ok:!1,reason:"malformed"};try{l+=d.decode(a.value,{stream:!0})}catch{return g(),{ok:!1,reason:"malformed"}}}try{l+=d.decode();let a=JSON.parse(l);return!a||typeof a!="object"||Array.isArray(a)||!Object.hasOwn(a,"result")?{ok:!1,reason:"malformed"}:{ok:!0,value:a.result}}catch{return{ok:!1,reason:"malformed"}}}catch{return{ok:!1,reason:m?"timeout":"network"}}};try{return await Promise.race([k(),E])}finally{clearTimeout(T)}}})}function O(e){return v({projectId:e.SANITY_PROJECT_ID,dataset:e.SANITY_DATASET,apiVersion:e.SANITY_API_VERSION})}0&&(module.exports={createSanityAdapter,sanityBindingFromEnv});
2
2
  //# sourceMappingURL=sanity.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/sanity.ts", "../src/contracts/query.ts", "../src/adapters/sanity/adapter.ts"],
4
- "sourcesContent": ["import \"server-only\";\nexport { createSanityAdapter, sanityBindingFromEnv } from \"./adapters/sanity/adapter.js\";\nexport type { SanityBinding, SanityAdapterOptions } from \"./adapters/sanity/adapter.js\";\n", "/** A-1822 S1 owns this implementation. S0 registers the public signatures. */\nexport type CmsParams = Readonly<Record<string, string | number | boolean | null>>;\nexport type CmsDependencies = {\n readonly types: readonly string[];\n readonly ids?: readonly string[];\n};\nexport type CmsResolution<T> = {\n readonly data: T;\n readonly fallbackFields: readonly string[];\n readonly warnings?: readonly (\"siteHero.layout.defaulted\" | \"siteHero.tagline.dropped\" | \"siteHero.taglines.defaulted\")[];\n};\nexport type CmsQuery<T> = {\n readonly name: string;\n readonly query: string;\n readonly params: CmsParams;\n readonly dependencies: CmsDependencies;\n readonly resolve: (raw: unknown, fallback: T) => CmsResolution<T>;\n};\n\nconst TYPE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;\nconst ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst SCOPE = /^[a-z0-9]{6,12}\\.[a-z][a-z0-9_-]{0,63}$/;\n\nfunction dependenciesCopy(dependencies: CmsDependencies): CmsDependencies {\n if (!dependencies || !Array.isArray(dependencies.types) || dependencies.types.length === 0) {\n throw new TypeError(\"CMS dependencies require document types\");\n }\n const types = [...dependencies.types];\n for (const type of types) {\n if (typeof type !== \"string\" || !TYPE.test(type)) throw new TypeError(\"Invalid CMS document type\");\n }\n if (dependencies.ids !== undefined && !Array.isArray(dependencies.ids)) throw new TypeError(\"Invalid CMS document IDs\");\n const ids = dependencies.ids === undefined ? undefined : [...dependencies.ids];\n for (const id of ids ?? []) {\n if (typeof id !== \"string\" || !ID.test(id) || /^(drafts|versions)\\./.test(id)) {\n throw new TypeError(\"Invalid CMS document ID\");\n }\n }\n if (new Set(types).size + new Set(ids).size > 128) throw new TypeError(\"Too many CMS tags\");\n return Object.freeze({ types: Object.freeze(types), ...(ids === undefined ? {} : { ids: Object.freeze(ids) }) });\n}\n\nexport function defineCmsQuery<T>(query: CmsQuery<T>): CmsQuery<T> {\n if (!query || typeof query.name !== \"string\" || !/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(query.name)\n || typeof query.query !== \"string\" || query.query.trim() === \"\" || typeof query.resolve !== \"function\") {\n throw new TypeError(\"Invalid CMS query configuration\");\n }\n const params = query.params;\n if (!params || typeof params !== \"object\" || (Object.getPrototypeOf(params) !== Object.prototype && Object.getPrototypeOf(params) !== null)) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const copied: Record<string, string | number | boolean | null> = {};\n for (const key of Reflect.ownKeys(params)) {\n const descriptor = Object.getOwnPropertyDescriptor(params, key);\n if (typeof key !== \"string\" || !descriptor || !Object.hasOwn(descriptor, \"value\") || !descriptor.enumerable) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const value: unknown = descriptor.value;\n if (!(value === null || typeof value === \"string\" || typeof value === \"boolean\" || (typeof value === \"number\" && Number.isFinite(value)))) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n Object.defineProperty(copied, key, { value, enumerable: true });\n }\n return Object.freeze({ name: query.name, query: query.query, params: Object.freeze(copied), dependencies: dependenciesCopy(query.dependencies), resolve: query.resolve });\n}\n\nexport function cmsTags(scope: string, dependencies: CmsDependencies): readonly string[] {\n if (typeof scope !== \"string\" || scope.length > 77 || !SCOPE.test(scope)) throw new TypeError(\"Invalid CMS scope\");\n const copied = dependenciesCopy(dependencies);\n const tags = [\n ...[...new Set(copied.types)].sort().map((type) => `cms:${scope}:type:${type}`),\n ...[...new Set(copied.ids ?? [])].sort().map((id) => `cms:${scope}:id:${id}`),\n ];\n return Object.freeze(tags);\n}\n", "import type { CmsAdapter, CmsFetch } from \"../../runtime/reader.js\";\nimport { cmsTags, defineCmsQuery } from \"../../contracts/query.js\";\n\nexport type SanityBinding = {\n readonly projectId: string;\n readonly dataset: string;\n readonly apiVersion: string;\n};\nexport type SanityAdapterOptions = {\n readonly binding: SanityBinding;\n readonly readToken?: string;\n readonly fetchImpl?: CmsFetch;\n readonly timeoutMs?: number;\n};\n\nconst RESPONSE_LIMIT = 2 * 1024 * 1024;\n\nfunction bindingCopy(binding: SanityBinding): SanityBinding {\n if (!binding || typeof binding.projectId !== \"string\" || !/^[a-z0-9]{6,12}$/.test(binding.projectId)\n || typeof binding.dataset !== \"string\" || !/^[a-z][a-z0-9_-]{0,63}$/.test(binding.dataset)\n || typeof binding.apiVersion !== \"string\" || !/^v?\\d{4}-\\d{2}-\\d{2}$/.test(binding.apiVersion)) {\n throw new TypeError(\"Invalid Sanity binding configuration\");\n }\n return Object.freeze({ projectId: binding.projectId, dataset: binding.dataset, apiVersion: binding.apiVersion.replace(/^v/, \"\") });\n}\n\n/** Applies policy via fetch's Next metadata. Standard fetch has no persistent cache or HTML invalidation. */\nexport function createSanityAdapter(options: SanityAdapterOptions): CmsAdapter {\n const binding = bindingCopy(options?.binding);\n const timeoutMs = options.timeoutMs ?? 1500;\n const token = options.readToken;\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647\n || (options.fetchImpl !== undefined && typeof options.fetchImpl !== \"function\")\n || (token !== undefined && (typeof token !== \"string\" || token.trim() === \"\" || /[\\r\\n]/.test(token)))) {\n throw new TypeError(\"Invalid Sanity adapter configuration\");\n }\n const fetchImpl = options.fetchImpl;\n const scope = `${binding.projectId}.${binding.dataset}`;\n return Object.freeze({\n scope,\n async read(query, policy) {\n // Direct structural callers receive the same configuration refusals.\n let validated;\n try {\n if (!policy || !Number.isSafeInteger(policy.revalidateSeconds) || policy.revalidateSeconds < 3600 || !Array.isArray(policy.tags)) throw new TypeError();\n const types: string[] = [];\n const ids: string[] = [];\n for (const tag of policy.tags) {\n if (typeof tag !== \"string\") throw new TypeError();\n if (tag.startsWith(`cms:${scope}:type:`)) types.push(tag.slice(`cms:${scope}:type:`.length));\n else if (tag.startsWith(`cms:${scope}:id:`)) ids.push(tag.slice(`cms:${scope}:id:`.length));\n else throw new TypeError();\n }\n const expected = cmsTags(scope, { types, ids });\n if (expected.length !== policy.tags.length || expected.some((tag, i) => tag !== policy.tags[i])) throw new TypeError();\n validated = defineCmsQuery({ ...query, dependencies: { types, ids }, resolve: (raw: unknown) => ({ data: raw, fallbackFields: [] }) });\n } catch { throw new TypeError(\"Invalid Sanity read configuration\"); }\n const url = new URL(`https://${binding.projectId}.api.sanity.io/v${binding.apiVersion}/data/query/${binding.dataset}`);\n url.searchParams.set(\"query\", validated.query);\n url.searchParams.set(\"perspective\", \"published\");\n for (const key of Object.keys(validated.params).sort()) url.searchParams.set(`$${key}`, JSON.stringify(validated.params[key]));\n const controller = new AbortController();\n let bodyReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let expired = false;\n const cancel = (): void => {\n controller.abort();\n if (bodyReader) void bodyReader.cancel().catch(() => {});\n };\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>>((resolve) => {\n timer = setTimeout(() => {\n expired = true;\n cancel();\n resolve({ ok: false, reason: \"timeout\" });\n }, timeoutMs);\n });\n const work = async (): Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>> => {\n try {\n // Look up global fetch at read time so Next's patched fetch is retained.\n const response = await (fetchImpl ?? globalThis.fetch)(url.href, {\n method: \"GET\", redirect: \"error\", signal: controller.signal,\n headers: token === undefined ? {} : { Authorization: `Bearer ${token}` },\n next: { revalidate: policy.revalidateSeconds, tags: [...policy.tags] },\n });\n if (expired) { void response.body?.cancel().catch(() => {}); return { ok: false, reason: \"timeout\" }; }\n if (!response.ok) {\n void response.body?.cancel().catch(() => {});\n const status = response.status;\n const reason = status === 402 ? \"plan-limit\" : status === 401 || status === 403 ? \"permission\"\n : status === 429 ? \"rate-limit\" : \"upstream\";\n return { ok: false, reason, status };\n }\n if (!response.body) return { ok: false, reason: \"malformed\" };\n bodyReader = response.body.getReader();\n let bytes = 0;\n let text = \"\";\n const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n while (true) {\n const chunk = await bodyReader.read();\n if (expired) return { ok: false, reason: \"timeout\" };\n if (chunk.done) break;\n bytes += chunk.value.byteLength;\n if (bytes > RESPONSE_LIMIT) { cancel(); return { ok: false, reason: \"malformed\" }; }\n try { text += decoder.decode(chunk.value, { stream: true }); }\n catch { cancel(); return { ok: false, reason: \"malformed\" }; }\n }\n try {\n text += decoder.decode();\n const envelope: unknown = JSON.parse(text);\n if (!envelope || typeof envelope !== \"object\" || Array.isArray(envelope) || !Object.hasOwn(envelope, \"result\")) return { ok: false, reason: \"malformed\" };\n return { ok: true, value: (envelope as Record<string, unknown>).result };\n } catch { return { ok: false, reason: \"malformed\" }; }\n } catch { return { ok: false, reason: expired ? \"timeout\" : \"network\" }; }\n };\n try { return await Promise.race([work(), deadline]); }\n finally { clearTimeout(timer); }\n },\n } satisfies CmsAdapter);\n}\n\nexport function sanityBindingFromEnv(env: Readonly<Record<string, string | undefined>>): SanityBinding {\n return bindingCopy({ projectId: env.SANITY_PROJECT_ID, dataset: env.SANITY_DATASET, apiVersion: env.SANITY_API_VERSION } as SanityBinding);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import \"server-only\";\nexport { createSanityAdapter, sanityBindingFromEnv } from \"./adapters/sanity/adapter.js\";\nexport type { SanityBinding, SanityAdapterOptions } from \"./adapters/sanity/adapter.js\";\n", "import { MalformedContentError } from \"../portable/site-content.js\";\nimport { MENU_DOCUMENT_PROJECTION } from \"../portable/menu-options.js\";\nimport { parseMenuDocument, validMenuFallback, type MenuDocument } from \"../portable/menu.js\";\n\n/** A-1822 S1 owns this implementation. S0 registers the public signatures. */\nexport type CmsParams = Readonly<Record<string, string | number | boolean | null>>;\nexport type CmsDependencies = {\n readonly types: readonly string[];\n readonly ids?: readonly string[];\n};\nexport type CmsResolution<T> = {\n readonly data: T;\n readonly fallbackFields: readonly string[];\n readonly warnings?: readonly (\"siteHero.layout.defaulted\" | \"siteHero.tagline.dropped\" | \"siteHero.taglines.defaulted\")[];\n};\nexport type CmsQuery<T> = {\n readonly name: string;\n readonly query: string;\n readonly params: CmsParams;\n readonly dependencies: CmsDependencies;\n readonly resolve: (raw: unknown, fallback: T) => CmsResolution<T>;\n};\n\nconst TYPE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;\nconst ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst SCOPE = /^[a-z0-9]{6,12}\\.[a-z][a-z0-9_-]{0,63}$/;\n\nfunction dependenciesCopy(dependencies: CmsDependencies): CmsDependencies {\n if (!dependencies || !Array.isArray(dependencies.types) || dependencies.types.length === 0) {\n throw new TypeError(\"CMS dependencies require document types\");\n }\n const types = [...dependencies.types];\n for (const type of types) {\n if (typeof type !== \"string\" || !TYPE.test(type)) throw new TypeError(\"Invalid CMS document type\");\n }\n if (dependencies.ids !== undefined && !Array.isArray(dependencies.ids)) throw new TypeError(\"Invalid CMS document IDs\");\n const ids = dependencies.ids === undefined ? undefined : [...dependencies.ids];\n for (const id of ids ?? []) {\n if (typeof id !== \"string\" || !ID.test(id) || /^(drafts|versions)\\./.test(id)) {\n throw new TypeError(\"Invalid CMS document ID\");\n }\n }\n if (new Set(types).size + new Set(ids).size > 128) throw new TypeError(\"Too many CMS tags\");\n return Object.freeze({ types: Object.freeze(types), ...(ids === undefined ? {} : { ids: Object.freeze(ids) }) });\n}\n\nexport function defineCmsQuery<T>(query: CmsQuery<T>): CmsQuery<T> {\n if (!query || typeof query.name !== \"string\" || !/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(query.name)\n || typeof query.query !== \"string\" || query.query.trim() === \"\" || typeof query.resolve !== \"function\") {\n throw new TypeError(\"Invalid CMS query configuration\");\n }\n const params = query.params;\n if (!params || typeof params !== \"object\" || (Object.getPrototypeOf(params) !== Object.prototype && Object.getPrototypeOf(params) !== null)) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const copied: Record<string, string | number | boolean | null> = {};\n for (const key of Reflect.ownKeys(params)) {\n const descriptor = Object.getOwnPropertyDescriptor(params, key);\n if (typeof key !== \"string\" || !descriptor || !Object.hasOwn(descriptor, \"value\") || !descriptor.enumerable) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const value: unknown = descriptor.value;\n if (!(value === null || typeof value === \"string\" || typeof value === \"boolean\" || (typeof value === \"number\" && Number.isFinite(value)))) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n Object.defineProperty(copied, key, { value, enumerable: true });\n }\n return Object.freeze({ name: query.name, query: query.query, params: Object.freeze(copied), dependencies: dependenciesCopy(query.dependencies), resolve: query.resolve });\n}\n\nexport function cmsTags(scope: string, dependencies: CmsDependencies): readonly string[] {\n if (typeof scope !== \"string\" || scope.length > 77 || !SCOPE.test(scope)) throw new TypeError(\"Invalid CMS scope\");\n const copied = dependenciesCopy(dependencies);\n const tags = [\n ...[...new Set(copied.types)].sort().map((type) => `cms:${scope}:type:${type}`),\n ...[...new Set(copied.ids ?? [])].sort().map((id) => `cms:${scope}:id:${id}`),\n ];\n return Object.freeze(tags);\n}\n\n/** Read one published menu by its document id; host supplies the last good snapshot. */\nexport function menuQuery(id: string): CmsQuery<MenuDocument | null> {\n return defineCmsQuery({\n name: \"menu.v1\",\n query: `*[_type == \"menu\" && _id == $id && !(_id in path(\"drafts.**\")) && !(_id in path(\"versions.**\"))][0]{${MENU_DOCUMENT_PROJECTION}}`,\n params: { id }, dependencies: { types: [\"menu\"], ids: [id] },\n resolve: (raw, fallback) => {\n if (!validMenuFallback(fallback) || (fallback !== null && fallback._id !== id)) throw new TypeError(\"Invalid CMS menu fallback\");\n if (raw === null || raw === undefined) return { data: fallback, fallbackFields: [\"$\"] };\n const data = parseMenuDocument(raw);\n if (data._id !== id) throw new MalformedContentError(\"menu\", [\"menu._id does not match the requested document\"]);\n return { data, fallbackFields: [] };\n },\n });\n}\n", "import type { CmsAdapter, CmsFetch } from \"../../runtime/reader.js\";\nimport { cmsTags, defineCmsQuery } from \"../../contracts/query.js\";\n\nexport type SanityBinding = {\n readonly projectId: string;\n readonly dataset: string;\n readonly apiVersion: string;\n};\nexport type SanityAdapterOptions = {\n readonly binding: SanityBinding;\n readonly readToken?: string;\n readonly fetchImpl?: CmsFetch;\n readonly timeoutMs?: number;\n};\n\nconst RESPONSE_LIMIT = 2 * 1024 * 1024;\n\nfunction bindingCopy(binding: SanityBinding): SanityBinding {\n if (!binding || typeof binding.projectId !== \"string\" || !/^[a-z0-9]{6,12}$/.test(binding.projectId)\n || typeof binding.dataset !== \"string\" || !/^[a-z][a-z0-9_-]{0,63}$/.test(binding.dataset)\n || typeof binding.apiVersion !== \"string\" || !/^v?\\d{4}-\\d{2}-\\d{2}$/.test(binding.apiVersion)) {\n throw new TypeError(\"Invalid Sanity binding configuration\");\n }\n return Object.freeze({ projectId: binding.projectId, dataset: binding.dataset, apiVersion: binding.apiVersion.replace(/^v/, \"\") });\n}\n\n/** Applies policy via fetch's Next metadata. Standard fetch has no persistent cache or HTML invalidation. */\nexport function createSanityAdapter(options: SanityAdapterOptions): CmsAdapter {\n const binding = bindingCopy(options?.binding);\n const timeoutMs = options.timeoutMs ?? 1500;\n const token = options.readToken;\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647\n || (options.fetchImpl !== undefined && typeof options.fetchImpl !== \"function\")\n || (token !== undefined && (typeof token !== \"string\" || token.trim() === \"\" || /[\\r\\n]/.test(token)))) {\n throw new TypeError(\"Invalid Sanity adapter configuration\");\n }\n const fetchImpl = options.fetchImpl;\n const scope = `${binding.projectId}.${binding.dataset}`;\n return Object.freeze({\n scope,\n async read(query, policy) {\n // Direct structural callers receive the same configuration refusals.\n let validated;\n try {\n if (!policy || !Number.isSafeInteger(policy.revalidateSeconds) || policy.revalidateSeconds < 3600 || !Array.isArray(policy.tags)) throw new TypeError();\n const types: string[] = [];\n const ids: string[] = [];\n for (const tag of policy.tags) {\n if (typeof tag !== \"string\") throw new TypeError();\n if (tag.startsWith(`cms:${scope}:type:`)) types.push(tag.slice(`cms:${scope}:type:`.length));\n else if (tag.startsWith(`cms:${scope}:id:`)) ids.push(tag.slice(`cms:${scope}:id:`.length));\n else throw new TypeError();\n }\n const expected = cmsTags(scope, { types, ids });\n if (expected.length !== policy.tags.length || expected.some((tag, i) => tag !== policy.tags[i])) throw new TypeError();\n validated = defineCmsQuery({ ...query, dependencies: { types, ids }, resolve: (raw: unknown) => ({ data: raw, fallbackFields: [] }) });\n } catch { throw new TypeError(\"Invalid Sanity read configuration\"); }\n const url = new URL(`https://${binding.projectId}.api.sanity.io/v${binding.apiVersion}/data/query/${binding.dataset}`);\n url.searchParams.set(\"query\", validated.query);\n url.searchParams.set(\"perspective\", \"published\");\n for (const key of Object.keys(validated.params).sort()) url.searchParams.set(`$${key}`, JSON.stringify(validated.params[key]));\n const controller = new AbortController();\n let bodyReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let expired = false;\n const cancel = (): void => {\n controller.abort();\n if (bodyReader) void bodyReader.cancel().catch(() => {});\n };\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>>((resolve) => {\n timer = setTimeout(() => {\n expired = true;\n cancel();\n resolve({ ok: false, reason: \"timeout\" });\n }, timeoutMs);\n });\n const work = async (): Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>> => {\n try {\n // Look up global fetch at read time so Next's patched fetch is retained.\n const response = await (fetchImpl ?? globalThis.fetch)(url.href, {\n method: \"GET\", redirect: \"error\", signal: controller.signal,\n headers: token === undefined ? {} : { Authorization: `Bearer ${token}` },\n next: { revalidate: policy.revalidateSeconds, tags: [...policy.tags] },\n });\n if (expired) { void response.body?.cancel().catch(() => {}); return { ok: false, reason: \"timeout\" }; }\n if (!response.ok) {\n void response.body?.cancel().catch(() => {});\n const status = response.status;\n const reason = status === 402 ? \"plan-limit\" : status === 401 || status === 403 ? \"permission\"\n : status === 429 ? \"rate-limit\" : \"upstream\";\n return { ok: false, reason, status };\n }\n if (!response.body) return { ok: false, reason: \"malformed\" };\n bodyReader = response.body.getReader();\n let bytes = 0;\n let text = \"\";\n const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n while (true) {\n const chunk = await bodyReader.read();\n if (expired) return { ok: false, reason: \"timeout\" };\n if (chunk.done) break;\n bytes += chunk.value.byteLength;\n if (bytes > RESPONSE_LIMIT) { cancel(); return { ok: false, reason: \"malformed\" }; }\n try { text += decoder.decode(chunk.value, { stream: true }); }\n catch { cancel(); return { ok: false, reason: \"malformed\" }; }\n }\n try {\n text += decoder.decode();\n const envelope: unknown = JSON.parse(text);\n if (!envelope || typeof envelope !== \"object\" || Array.isArray(envelope) || !Object.hasOwn(envelope, \"result\")) return { ok: false, reason: \"malformed\" };\n return { ok: true, value: (envelope as Record<string, unknown>).result };\n } catch { return { ok: false, reason: \"malformed\" }; }\n } catch { return { ok: false, reason: expired ? \"timeout\" : \"network\" }; }\n };\n try { return await Promise.race([work(), deadline]); }\n finally { clearTimeout(timer); }\n },\n } satisfies CmsAdapter);\n}\n\nexport function sanityBindingFromEnv(env: Readonly<Record<string, string | undefined>>): SanityBinding {\n return bindingCopy({ projectId: env.SANITY_PROJECT_ID, dataset: env.SANITY_DATASET, apiVersion: env.SANITY_API_VERSION } as SanityBinding);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["sanity_exports", "__export", "createSanityAdapter", "sanityBindingFromEnv", "__toCommonJS", "import_server_only", "TYPE", "ID", "SCOPE", "dependenciesCopy", "dependencies", "types", "type", "ids", "id", "defineCmsQuery", "query", "params", "copied", "key", "descriptor", "value", "cmsTags", "scope", "tags", "RESPONSE_LIMIT", "bindingCopy", "binding", "createSanityAdapter", "options", "timeoutMs", "token", "fetchImpl", "scope", "query", "policy", "validated", "types", "ids", "tag", "expected", "cmsTags", "i", "defineCmsQuery", "raw", "url", "key", "controller", "bodyReader", "expired", "cancel", "timer", "deadline", "resolve", "work", "response", "status", "bytes", "text", "decoder", "chunk", "envelope", "sanityBindingFromEnv", "env"]
7
7
  }
package/dist/sanity.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import"server-only";var O=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,k=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,j=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function S(e){if(!e||!Array.isArray(e.types)||e.types.length===0)throw new TypeError("CMS dependencies require document types");let r=[...e.types];for(let t of r)if(typeof t!="string"||!O.test(t))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let a=e.ids===void 0?void 0:[...e.ids];for(let t of a??[])if(typeof t!="string"||!k.test(t)||/^(drafts|versions)\./.test(t))throw new TypeError("Invalid CMS document ID");if(new Set(r).size+new Set(a).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(r),...a===void 0?{}:{ids:Object.freeze(a)}})}function T(e){if(!e||typeof e.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(e.name)||typeof e.query!="string"||e.query.trim()===""||typeof e.resolve!="function")throw new TypeError("Invalid CMS query configuration");let r=e.params;if(!r||typeof r!="object"||Object.getPrototypeOf(r)!==Object.prototype&&Object.getPrototypeOf(r)!==null)throw new TypeError("CMS params must be plain JSON scalars");let a={};for(let t of Reflect.ownKeys(r)){let d=Object.getOwnPropertyDescriptor(r,t);if(typeof t!="string"||!d||!Object.hasOwn(d,"value")||!d.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let o=d.value;if(!(o===null||typeof o=="string"||typeof o=="boolean"||typeof o=="number"&&Number.isFinite(o)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(a,t,{value:o,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(a),dependencies:S(e.dependencies),resolve:e.resolve})}function b(e,r){if(typeof e!="string"||e.length>77||!j.test(e))throw new TypeError("Invalid CMS scope");let a=S(r),t=[...[...new Set(a.types)].sort().map(d=>`cms:${e}:type:${d}`),...[...new Set(a.ids??[])].sort().map(d=>`cms:${e}:id:${d}`)];return Object.freeze(t)}var E=2*1024*1024;function C(e){if(!e||typeof e.projectId!="string"||!/^[a-z0-9]{6,12}$/.test(e.projectId)||typeof e.dataset!="string"||!/^[a-z][a-z0-9_-]{0,63}$/.test(e.dataset)||typeof e.apiVersion!="string"||!/^v?\d{4}-\d{2}-\d{2}$/.test(e.apiVersion))throw new TypeError("Invalid Sanity binding configuration");return Object.freeze({projectId:e.projectId,dataset:e.dataset,apiVersion:e.apiVersion.replace(/^v/,"")})}function z(e){let r=C(e?.binding),a=e.timeoutMs??1500,t=e.readToken;if(!Number.isSafeInteger(a)||a<=0||a>2147483647||e.fetchImpl!==void 0&&typeof e.fetchImpl!="function"||t!==void 0&&(typeof t!="string"||t.trim()===""||/[\r\n]/.test(t)))throw new TypeError("Invalid Sanity adapter configuration");let d=e.fetchImpl,o=`${r.projectId}.${r.dataset}`;return Object.freeze({scope:o,async read(A,c){let y;try{if(!c||!Number.isSafeInteger(c.revalidateSeconds)||c.revalidateSeconds<3600||!Array.isArray(c.tags))throw new TypeError;let s=[],p=[];for(let i of c.tags){if(typeof i!="string")throw new TypeError;if(i.startsWith(`cms:${o}:type:`))s.push(i.slice(`cms:${o}:type:`.length));else if(i.startsWith(`cms:${o}:id:`))p.push(i.slice(`cms:${o}:id:`.length));else throw new TypeError}let l=b(o,{types:s,ids:p});if(l.length!==c.tags.length||l.some((i,n)=>i!==c.tags[n]))throw new TypeError;y=T({...A,dependencies:{types:s,ids:p},resolve:i=>({data:i,fallbackFields:[]})})}catch{throw new TypeError("Invalid Sanity read configuration")}let f=new URL(`https://${r.projectId}.api.sanity.io/v${r.apiVersion}/data/query/${r.dataset}`);f.searchParams.set("query",y.query),f.searchParams.set("perspective","published");for(let s of Object.keys(y.params).sort())f.searchParams.set(`$${s}`,JSON.stringify(y.params[s]));let w=new AbortController,m,u=!1,g=()=>{w.abort(),m&&m.cancel().catch(()=>{})},h,v=new Promise(s=>{h=setTimeout(()=>{u=!0,g(),s({ok:!1,reason:"timeout"})},a)}),I=async()=>{try{let s=await(d??globalThis.fetch)(f.href,{method:"GET",redirect:"error",signal:w.signal,headers:t===void 0?{}:{Authorization:`Bearer ${t}`},next:{revalidate:c.revalidateSeconds,tags:[...c.tags]}});if(u)return s.body?.cancel().catch(()=>{}),{ok:!1,reason:"timeout"};if(!s.ok){s.body?.cancel().catch(()=>{});let n=s.status;return{ok:!1,reason:n===402?"plan-limit":n===401||n===403?"permission":n===429?"rate-limit":"upstream",status:n}}if(!s.body)return{ok:!1,reason:"malformed"};m=s.body.getReader();let p=0,l="",i=new TextDecoder("utf-8",{fatal:!0});for(;;){let n=await m.read();if(u)return{ok:!1,reason:"timeout"};if(n.done)break;if(p+=n.value.byteLength,p>E)return g(),{ok:!1,reason:"malformed"};try{l+=i.decode(n.value,{stream:!0})}catch{return g(),{ok:!1,reason:"malformed"}}}try{l+=i.decode();let n=JSON.parse(l);return!n||typeof n!="object"||Array.isArray(n)||!Object.hasOwn(n,"result")?{ok:!1,reason:"malformed"}:{ok:!0,value:n.result}}catch{return{ok:!1,reason:"malformed"}}}catch{return{ok:!1,reason:u?"timeout":"network"}}};try{return await Promise.race([I(),v])}finally{clearTimeout(h)}}})}function $(e){return C({projectId:e.SANITY_PROJECT_ID,dataset:e.SANITY_DATASET,apiVersion:e.SANITY_API_VERSION})}export{z as createSanityAdapter,$ as sanityBindingFromEnv};
1
+ import"server-only";var A=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,E=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,k=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function T(e){if(!e||!Array.isArray(e.types)||e.types.length===0)throw new TypeError("CMS dependencies require document types");let r=[...e.types];for(let t of r)if(typeof t!="string"||!A.test(t))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let a=e.ids===void 0?void 0:[...e.ids];for(let t of a??[])if(typeof t!="string"||!E.test(t)||/^(drafts|versions)\./.test(t))throw new TypeError("Invalid CMS document ID");if(new Set(r).size+new Set(a).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(r),...a===void 0?{}:{ids:Object.freeze(a)}})}function S(e){if(!e||typeof e.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(e.name)||typeof e.query!="string"||e.query.trim()===""||typeof e.resolve!="function")throw new TypeError("Invalid CMS query configuration");let r=e.params;if(!r||typeof r!="object"||Object.getPrototypeOf(r)!==Object.prototype&&Object.getPrototypeOf(r)!==null)throw new TypeError("CMS params must be plain JSON scalars");let a={};for(let t of Reflect.ownKeys(r)){let d=Object.getOwnPropertyDescriptor(r,t);if(typeof t!="string"||!d||!Object.hasOwn(d,"value")||!d.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let s=d.value;if(!(s===null||typeof s=="string"||typeof s=="boolean"||typeof s=="number"&&Number.isFinite(s)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(a,t,{value:s,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(a),dependencies:T(e.dependencies),resolve:e.resolve})}function b(e,r){if(typeof e!="string"||e.length>77||!k.test(e))throw new TypeError("Invalid CMS scope");let a=T(r),t=[...[...new Set(a.types)].sort().map(d=>`cms:${e}:type:${d}`),...[...new Set(a.ids??[])].sort().map(d=>`cms:${e}:id:${d}`)];return Object.freeze(t)}var j=2*1024*1024;function C(e){if(!e||typeof e.projectId!="string"||!/^[a-z0-9]{6,12}$/.test(e.projectId)||typeof e.dataset!="string"||!/^[a-z][a-z0-9_-]{0,63}$/.test(e.dataset)||typeof e.apiVersion!="string"||!/^v?\d{4}-\d{2}-\d{2}$/.test(e.apiVersion))throw new TypeError("Invalid Sanity binding configuration");return Object.freeze({projectId:e.projectId,dataset:e.dataset,apiVersion:e.apiVersion.replace(/^v/,"")})}function $(e){let r=C(e?.binding),a=e.timeoutMs??1500,t=e.readToken;if(!Number.isSafeInteger(a)||a<=0||a>2147483647||e.fetchImpl!==void 0&&typeof e.fetchImpl!="function"||t!==void 0&&(typeof t!="string"||t.trim()===""||/[\r\n]/.test(t)))throw new TypeError("Invalid Sanity adapter configuration");let d=e.fetchImpl,s=`${r.projectId}.${r.dataset}`;return Object.freeze({scope:s,async read(v,c){let y;try{if(!c||!Number.isSafeInteger(c.revalidateSeconds)||c.revalidateSeconds<3600||!Array.isArray(c.tags))throw new TypeError;let o=[],p=[];for(let i of c.tags){if(typeof i!="string")throw new TypeError;if(i.startsWith(`cms:${s}:type:`))o.push(i.slice(`cms:${s}:type:`.length));else if(i.startsWith(`cms:${s}:id:`))p.push(i.slice(`cms:${s}:id:`.length));else throw new TypeError}let l=b(s,{types:o,ids:p});if(l.length!==c.tags.length||l.some((i,n)=>i!==c.tags[n]))throw new TypeError;y=S({...v,dependencies:{types:o,ids:p},resolve:i=>({data:i,fallbackFields:[]})})}catch{throw new TypeError("Invalid Sanity read configuration")}let f=new URL(`https://${r.projectId}.api.sanity.io/v${r.apiVersion}/data/query/${r.dataset}`);f.searchParams.set("query",y.query),f.searchParams.set("perspective","published");for(let o of Object.keys(y.params).sort())f.searchParams.set(`$${o}`,JSON.stringify(y.params[o]));let h=new AbortController,u,m=!1,g=()=>{h.abort(),u&&u.cancel().catch(()=>{})},w,I=new Promise(o=>{w=setTimeout(()=>{m=!0,g(),o({ok:!1,reason:"timeout"})},a)}),O=async()=>{try{let o=await(d??globalThis.fetch)(f.href,{method:"GET",redirect:"error",signal:h.signal,headers:t===void 0?{}:{Authorization:`Bearer ${t}`},next:{revalidate:c.revalidateSeconds,tags:[...c.tags]}});if(m)return o.body?.cancel().catch(()=>{}),{ok:!1,reason:"timeout"};if(!o.ok){o.body?.cancel().catch(()=>{});let n=o.status;return{ok:!1,reason:n===402?"plan-limit":n===401||n===403?"permission":n===429?"rate-limit":"upstream",status:n}}if(!o.body)return{ok:!1,reason:"malformed"};u=o.body.getReader();let p=0,l="",i=new TextDecoder("utf-8",{fatal:!0});for(;;){let n=await u.read();if(m)return{ok:!1,reason:"timeout"};if(n.done)break;if(p+=n.value.byteLength,p>j)return g(),{ok:!1,reason:"malformed"};try{l+=i.decode(n.value,{stream:!0})}catch{return g(),{ok:!1,reason:"malformed"}}}try{l+=i.decode();let n=JSON.parse(l);return!n||typeof n!="object"||Array.isArray(n)||!Object.hasOwn(n,"result")?{ok:!1,reason:"malformed"}:{ok:!0,value:n.result}}catch{return{ok:!1,reason:"malformed"}}}catch{return{ok:!1,reason:m?"timeout":"network"}}};try{return await Promise.race([O(),I])}finally{clearTimeout(w)}}})}function z(e){return C({projectId:e.SANITY_PROJECT_ID,dataset:e.SANITY_DATASET,apiVersion:e.SANITY_API_VERSION})}export{$ as createSanityAdapter,z as sanityBindingFromEnv};
2
2
  //# sourceMappingURL=sanity.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/sanity.ts", "../src/contracts/query.ts", "../src/adapters/sanity/adapter.ts"],
4
- "sourcesContent": ["import \"server-only\";\nexport { createSanityAdapter, sanityBindingFromEnv } from \"./adapters/sanity/adapter.js\";\nexport type { SanityBinding, SanityAdapterOptions } from \"./adapters/sanity/adapter.js\";\n", "/** A-1822 S1 owns this implementation. S0 registers the public signatures. */\nexport type CmsParams = Readonly<Record<string, string | number | boolean | null>>;\nexport type CmsDependencies = {\n readonly types: readonly string[];\n readonly ids?: readonly string[];\n};\nexport type CmsResolution<T> = {\n readonly data: T;\n readonly fallbackFields: readonly string[];\n readonly warnings?: readonly (\"siteHero.layout.defaulted\" | \"siteHero.tagline.dropped\" | \"siteHero.taglines.defaulted\")[];\n};\nexport type CmsQuery<T> = {\n readonly name: string;\n readonly query: string;\n readonly params: CmsParams;\n readonly dependencies: CmsDependencies;\n readonly resolve: (raw: unknown, fallback: T) => CmsResolution<T>;\n};\n\nconst TYPE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;\nconst ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst SCOPE = /^[a-z0-9]{6,12}\\.[a-z][a-z0-9_-]{0,63}$/;\n\nfunction dependenciesCopy(dependencies: CmsDependencies): CmsDependencies {\n if (!dependencies || !Array.isArray(dependencies.types) || dependencies.types.length === 0) {\n throw new TypeError(\"CMS dependencies require document types\");\n }\n const types = [...dependencies.types];\n for (const type of types) {\n if (typeof type !== \"string\" || !TYPE.test(type)) throw new TypeError(\"Invalid CMS document type\");\n }\n if (dependencies.ids !== undefined && !Array.isArray(dependencies.ids)) throw new TypeError(\"Invalid CMS document IDs\");\n const ids = dependencies.ids === undefined ? undefined : [...dependencies.ids];\n for (const id of ids ?? []) {\n if (typeof id !== \"string\" || !ID.test(id) || /^(drafts|versions)\\./.test(id)) {\n throw new TypeError(\"Invalid CMS document ID\");\n }\n }\n if (new Set(types).size + new Set(ids).size > 128) throw new TypeError(\"Too many CMS tags\");\n return Object.freeze({ types: Object.freeze(types), ...(ids === undefined ? {} : { ids: Object.freeze(ids) }) });\n}\n\nexport function defineCmsQuery<T>(query: CmsQuery<T>): CmsQuery<T> {\n if (!query || typeof query.name !== \"string\" || !/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(query.name)\n || typeof query.query !== \"string\" || query.query.trim() === \"\" || typeof query.resolve !== \"function\") {\n throw new TypeError(\"Invalid CMS query configuration\");\n }\n const params = query.params;\n if (!params || typeof params !== \"object\" || (Object.getPrototypeOf(params) !== Object.prototype && Object.getPrototypeOf(params) !== null)) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const copied: Record<string, string | number | boolean | null> = {};\n for (const key of Reflect.ownKeys(params)) {\n const descriptor = Object.getOwnPropertyDescriptor(params, key);\n if (typeof key !== \"string\" || !descriptor || !Object.hasOwn(descriptor, \"value\") || !descriptor.enumerable) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const value: unknown = descriptor.value;\n if (!(value === null || typeof value === \"string\" || typeof value === \"boolean\" || (typeof value === \"number\" && Number.isFinite(value)))) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n Object.defineProperty(copied, key, { value, enumerable: true });\n }\n return Object.freeze({ name: query.name, query: query.query, params: Object.freeze(copied), dependencies: dependenciesCopy(query.dependencies), resolve: query.resolve });\n}\n\nexport function cmsTags(scope: string, dependencies: CmsDependencies): readonly string[] {\n if (typeof scope !== \"string\" || scope.length > 77 || !SCOPE.test(scope)) throw new TypeError(\"Invalid CMS scope\");\n const copied = dependenciesCopy(dependencies);\n const tags = [\n ...[...new Set(copied.types)].sort().map((type) => `cms:${scope}:type:${type}`),\n ...[...new Set(copied.ids ?? [])].sort().map((id) => `cms:${scope}:id:${id}`),\n ];\n return Object.freeze(tags);\n}\n", "import type { CmsAdapter, CmsFetch } from \"../../runtime/reader.js\";\nimport { cmsTags, defineCmsQuery } from \"../../contracts/query.js\";\n\nexport type SanityBinding = {\n readonly projectId: string;\n readonly dataset: string;\n readonly apiVersion: string;\n};\nexport type SanityAdapterOptions = {\n readonly binding: SanityBinding;\n readonly readToken?: string;\n readonly fetchImpl?: CmsFetch;\n readonly timeoutMs?: number;\n};\n\nconst RESPONSE_LIMIT = 2 * 1024 * 1024;\n\nfunction bindingCopy(binding: SanityBinding): SanityBinding {\n if (!binding || typeof binding.projectId !== \"string\" || !/^[a-z0-9]{6,12}$/.test(binding.projectId)\n || typeof binding.dataset !== \"string\" || !/^[a-z][a-z0-9_-]{0,63}$/.test(binding.dataset)\n || typeof binding.apiVersion !== \"string\" || !/^v?\\d{4}-\\d{2}-\\d{2}$/.test(binding.apiVersion)) {\n throw new TypeError(\"Invalid Sanity binding configuration\");\n }\n return Object.freeze({ projectId: binding.projectId, dataset: binding.dataset, apiVersion: binding.apiVersion.replace(/^v/, \"\") });\n}\n\n/** Applies policy via fetch's Next metadata. Standard fetch has no persistent cache or HTML invalidation. */\nexport function createSanityAdapter(options: SanityAdapterOptions): CmsAdapter {\n const binding = bindingCopy(options?.binding);\n const timeoutMs = options.timeoutMs ?? 1500;\n const token = options.readToken;\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647\n || (options.fetchImpl !== undefined && typeof options.fetchImpl !== \"function\")\n || (token !== undefined && (typeof token !== \"string\" || token.trim() === \"\" || /[\\r\\n]/.test(token)))) {\n throw new TypeError(\"Invalid Sanity adapter configuration\");\n }\n const fetchImpl = options.fetchImpl;\n const scope = `${binding.projectId}.${binding.dataset}`;\n return Object.freeze({\n scope,\n async read(query, policy) {\n // Direct structural callers receive the same configuration refusals.\n let validated;\n try {\n if (!policy || !Number.isSafeInteger(policy.revalidateSeconds) || policy.revalidateSeconds < 3600 || !Array.isArray(policy.tags)) throw new TypeError();\n const types: string[] = [];\n const ids: string[] = [];\n for (const tag of policy.tags) {\n if (typeof tag !== \"string\") throw new TypeError();\n if (tag.startsWith(`cms:${scope}:type:`)) types.push(tag.slice(`cms:${scope}:type:`.length));\n else if (tag.startsWith(`cms:${scope}:id:`)) ids.push(tag.slice(`cms:${scope}:id:`.length));\n else throw new TypeError();\n }\n const expected = cmsTags(scope, { types, ids });\n if (expected.length !== policy.tags.length || expected.some((tag, i) => tag !== policy.tags[i])) throw new TypeError();\n validated = defineCmsQuery({ ...query, dependencies: { types, ids }, resolve: (raw: unknown) => ({ data: raw, fallbackFields: [] }) });\n } catch { throw new TypeError(\"Invalid Sanity read configuration\"); }\n const url = new URL(`https://${binding.projectId}.api.sanity.io/v${binding.apiVersion}/data/query/${binding.dataset}`);\n url.searchParams.set(\"query\", validated.query);\n url.searchParams.set(\"perspective\", \"published\");\n for (const key of Object.keys(validated.params).sort()) url.searchParams.set(`$${key}`, JSON.stringify(validated.params[key]));\n const controller = new AbortController();\n let bodyReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let expired = false;\n const cancel = (): void => {\n controller.abort();\n if (bodyReader) void bodyReader.cancel().catch(() => {});\n };\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>>((resolve) => {\n timer = setTimeout(() => {\n expired = true;\n cancel();\n resolve({ ok: false, reason: \"timeout\" });\n }, timeoutMs);\n });\n const work = async (): Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>> => {\n try {\n // Look up global fetch at read time so Next's patched fetch is retained.\n const response = await (fetchImpl ?? globalThis.fetch)(url.href, {\n method: \"GET\", redirect: \"error\", signal: controller.signal,\n headers: token === undefined ? {} : { Authorization: `Bearer ${token}` },\n next: { revalidate: policy.revalidateSeconds, tags: [...policy.tags] },\n });\n if (expired) { void response.body?.cancel().catch(() => {}); return { ok: false, reason: \"timeout\" }; }\n if (!response.ok) {\n void response.body?.cancel().catch(() => {});\n const status = response.status;\n const reason = status === 402 ? \"plan-limit\" : status === 401 || status === 403 ? \"permission\"\n : status === 429 ? \"rate-limit\" : \"upstream\";\n return { ok: false, reason, status };\n }\n if (!response.body) return { ok: false, reason: \"malformed\" };\n bodyReader = response.body.getReader();\n let bytes = 0;\n let text = \"\";\n const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n while (true) {\n const chunk = await bodyReader.read();\n if (expired) return { ok: false, reason: \"timeout\" };\n if (chunk.done) break;\n bytes += chunk.value.byteLength;\n if (bytes > RESPONSE_LIMIT) { cancel(); return { ok: false, reason: \"malformed\" }; }\n try { text += decoder.decode(chunk.value, { stream: true }); }\n catch { cancel(); return { ok: false, reason: \"malformed\" }; }\n }\n try {\n text += decoder.decode();\n const envelope: unknown = JSON.parse(text);\n if (!envelope || typeof envelope !== \"object\" || Array.isArray(envelope) || !Object.hasOwn(envelope, \"result\")) return { ok: false, reason: \"malformed\" };\n return { ok: true, value: (envelope as Record<string, unknown>).result };\n } catch { return { ok: false, reason: \"malformed\" }; }\n } catch { return { ok: false, reason: expired ? \"timeout\" : \"network\" }; }\n };\n try { return await Promise.race([work(), deadline]); }\n finally { clearTimeout(timer); }\n },\n } satisfies CmsAdapter);\n}\n\nexport function sanityBindingFromEnv(env: Readonly<Record<string, string | undefined>>): SanityBinding {\n return bindingCopy({ projectId: env.SANITY_PROJECT_ID, dataset: env.SANITY_DATASET, apiVersion: env.SANITY_API_VERSION } as SanityBinding);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import \"server-only\";\nexport { createSanityAdapter, sanityBindingFromEnv } from \"./adapters/sanity/adapter.js\";\nexport type { SanityBinding, SanityAdapterOptions } from \"./adapters/sanity/adapter.js\";\n", "import { MalformedContentError } from \"../portable/site-content.js\";\nimport { MENU_DOCUMENT_PROJECTION } from \"../portable/menu-options.js\";\nimport { parseMenuDocument, validMenuFallback, type MenuDocument } from \"../portable/menu.js\";\n\n/** A-1822 S1 owns this implementation. S0 registers the public signatures. */\nexport type CmsParams = Readonly<Record<string, string | number | boolean | null>>;\nexport type CmsDependencies = {\n readonly types: readonly string[];\n readonly ids?: readonly string[];\n};\nexport type CmsResolution<T> = {\n readonly data: T;\n readonly fallbackFields: readonly string[];\n readonly warnings?: readonly (\"siteHero.layout.defaulted\" | \"siteHero.tagline.dropped\" | \"siteHero.taglines.defaulted\")[];\n};\nexport type CmsQuery<T> = {\n readonly name: string;\n readonly query: string;\n readonly params: CmsParams;\n readonly dependencies: CmsDependencies;\n readonly resolve: (raw: unknown, fallback: T) => CmsResolution<T>;\n};\n\nconst TYPE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;\nconst ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst SCOPE = /^[a-z0-9]{6,12}\\.[a-z][a-z0-9_-]{0,63}$/;\n\nfunction dependenciesCopy(dependencies: CmsDependencies): CmsDependencies {\n if (!dependencies || !Array.isArray(dependencies.types) || dependencies.types.length === 0) {\n throw new TypeError(\"CMS dependencies require document types\");\n }\n const types = [...dependencies.types];\n for (const type of types) {\n if (typeof type !== \"string\" || !TYPE.test(type)) throw new TypeError(\"Invalid CMS document type\");\n }\n if (dependencies.ids !== undefined && !Array.isArray(dependencies.ids)) throw new TypeError(\"Invalid CMS document IDs\");\n const ids = dependencies.ids === undefined ? undefined : [...dependencies.ids];\n for (const id of ids ?? []) {\n if (typeof id !== \"string\" || !ID.test(id) || /^(drafts|versions)\\./.test(id)) {\n throw new TypeError(\"Invalid CMS document ID\");\n }\n }\n if (new Set(types).size + new Set(ids).size > 128) throw new TypeError(\"Too many CMS tags\");\n return Object.freeze({ types: Object.freeze(types), ...(ids === undefined ? {} : { ids: Object.freeze(ids) }) });\n}\n\nexport function defineCmsQuery<T>(query: CmsQuery<T>): CmsQuery<T> {\n if (!query || typeof query.name !== \"string\" || !/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(query.name)\n || typeof query.query !== \"string\" || query.query.trim() === \"\" || typeof query.resolve !== \"function\") {\n throw new TypeError(\"Invalid CMS query configuration\");\n }\n const params = query.params;\n if (!params || typeof params !== \"object\" || (Object.getPrototypeOf(params) !== Object.prototype && Object.getPrototypeOf(params) !== null)) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const copied: Record<string, string | number | boolean | null> = {};\n for (const key of Reflect.ownKeys(params)) {\n const descriptor = Object.getOwnPropertyDescriptor(params, key);\n if (typeof key !== \"string\" || !descriptor || !Object.hasOwn(descriptor, \"value\") || !descriptor.enumerable) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n const value: unknown = descriptor.value;\n if (!(value === null || typeof value === \"string\" || typeof value === \"boolean\" || (typeof value === \"number\" && Number.isFinite(value)))) {\n throw new TypeError(\"CMS params must be plain JSON scalars\");\n }\n Object.defineProperty(copied, key, { value, enumerable: true });\n }\n return Object.freeze({ name: query.name, query: query.query, params: Object.freeze(copied), dependencies: dependenciesCopy(query.dependencies), resolve: query.resolve });\n}\n\nexport function cmsTags(scope: string, dependencies: CmsDependencies): readonly string[] {\n if (typeof scope !== \"string\" || scope.length > 77 || !SCOPE.test(scope)) throw new TypeError(\"Invalid CMS scope\");\n const copied = dependenciesCopy(dependencies);\n const tags = [\n ...[...new Set(copied.types)].sort().map((type) => `cms:${scope}:type:${type}`),\n ...[...new Set(copied.ids ?? [])].sort().map((id) => `cms:${scope}:id:${id}`),\n ];\n return Object.freeze(tags);\n}\n\n/** Read one published menu by its document id; host supplies the last good snapshot. */\nexport function menuQuery(id: string): CmsQuery<MenuDocument | null> {\n return defineCmsQuery({\n name: \"menu.v1\",\n query: `*[_type == \"menu\" && _id == $id && !(_id in path(\"drafts.**\")) && !(_id in path(\"versions.**\"))][0]{${MENU_DOCUMENT_PROJECTION}}`,\n params: { id }, dependencies: { types: [\"menu\"], ids: [id] },\n resolve: (raw, fallback) => {\n if (!validMenuFallback(fallback) || (fallback !== null && fallback._id !== id)) throw new TypeError(\"Invalid CMS menu fallback\");\n if (raw === null || raw === undefined) return { data: fallback, fallbackFields: [\"$\"] };\n const data = parseMenuDocument(raw);\n if (data._id !== id) throw new MalformedContentError(\"menu\", [\"menu._id does not match the requested document\"]);\n return { data, fallbackFields: [] };\n },\n });\n}\n", "import type { CmsAdapter, CmsFetch } from \"../../runtime/reader.js\";\nimport { cmsTags, defineCmsQuery } from \"../../contracts/query.js\";\n\nexport type SanityBinding = {\n readonly projectId: string;\n readonly dataset: string;\n readonly apiVersion: string;\n};\nexport type SanityAdapterOptions = {\n readonly binding: SanityBinding;\n readonly readToken?: string;\n readonly fetchImpl?: CmsFetch;\n readonly timeoutMs?: number;\n};\n\nconst RESPONSE_LIMIT = 2 * 1024 * 1024;\n\nfunction bindingCopy(binding: SanityBinding): SanityBinding {\n if (!binding || typeof binding.projectId !== \"string\" || !/^[a-z0-9]{6,12}$/.test(binding.projectId)\n || typeof binding.dataset !== \"string\" || !/^[a-z][a-z0-9_-]{0,63}$/.test(binding.dataset)\n || typeof binding.apiVersion !== \"string\" || !/^v?\\d{4}-\\d{2}-\\d{2}$/.test(binding.apiVersion)) {\n throw new TypeError(\"Invalid Sanity binding configuration\");\n }\n return Object.freeze({ projectId: binding.projectId, dataset: binding.dataset, apiVersion: binding.apiVersion.replace(/^v/, \"\") });\n}\n\n/** Applies policy via fetch's Next metadata. Standard fetch has no persistent cache or HTML invalidation. */\nexport function createSanityAdapter(options: SanityAdapterOptions): CmsAdapter {\n const binding = bindingCopy(options?.binding);\n const timeoutMs = options.timeoutMs ?? 1500;\n const token = options.readToken;\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647\n || (options.fetchImpl !== undefined && typeof options.fetchImpl !== \"function\")\n || (token !== undefined && (typeof token !== \"string\" || token.trim() === \"\" || /[\\r\\n]/.test(token)))) {\n throw new TypeError(\"Invalid Sanity adapter configuration\");\n }\n const fetchImpl = options.fetchImpl;\n const scope = `${binding.projectId}.${binding.dataset}`;\n return Object.freeze({\n scope,\n async read(query, policy) {\n // Direct structural callers receive the same configuration refusals.\n let validated;\n try {\n if (!policy || !Number.isSafeInteger(policy.revalidateSeconds) || policy.revalidateSeconds < 3600 || !Array.isArray(policy.tags)) throw new TypeError();\n const types: string[] = [];\n const ids: string[] = [];\n for (const tag of policy.tags) {\n if (typeof tag !== \"string\") throw new TypeError();\n if (tag.startsWith(`cms:${scope}:type:`)) types.push(tag.slice(`cms:${scope}:type:`.length));\n else if (tag.startsWith(`cms:${scope}:id:`)) ids.push(tag.slice(`cms:${scope}:id:`.length));\n else throw new TypeError();\n }\n const expected = cmsTags(scope, { types, ids });\n if (expected.length !== policy.tags.length || expected.some((tag, i) => tag !== policy.tags[i])) throw new TypeError();\n validated = defineCmsQuery({ ...query, dependencies: { types, ids }, resolve: (raw: unknown) => ({ data: raw, fallbackFields: [] }) });\n } catch { throw new TypeError(\"Invalid Sanity read configuration\"); }\n const url = new URL(`https://${binding.projectId}.api.sanity.io/v${binding.apiVersion}/data/query/${binding.dataset}`);\n url.searchParams.set(\"query\", validated.query);\n url.searchParams.set(\"perspective\", \"published\");\n for (const key of Object.keys(validated.params).sort()) url.searchParams.set(`$${key}`, JSON.stringify(validated.params[key]));\n const controller = new AbortController();\n let bodyReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let expired = false;\n const cancel = (): void => {\n controller.abort();\n if (bodyReader) void bodyReader.cancel().catch(() => {});\n };\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>>((resolve) => {\n timer = setTimeout(() => {\n expired = true;\n cancel();\n resolve({ ok: false, reason: \"timeout\" });\n }, timeoutMs);\n });\n const work = async (): Promise<Awaited<ReturnType<CmsAdapter[\"read\"]>>> => {\n try {\n // Look up global fetch at read time so Next's patched fetch is retained.\n const response = await (fetchImpl ?? globalThis.fetch)(url.href, {\n method: \"GET\", redirect: \"error\", signal: controller.signal,\n headers: token === undefined ? {} : { Authorization: `Bearer ${token}` },\n next: { revalidate: policy.revalidateSeconds, tags: [...policy.tags] },\n });\n if (expired) { void response.body?.cancel().catch(() => {}); return { ok: false, reason: \"timeout\" }; }\n if (!response.ok) {\n void response.body?.cancel().catch(() => {});\n const status = response.status;\n const reason = status === 402 ? \"plan-limit\" : status === 401 || status === 403 ? \"permission\"\n : status === 429 ? \"rate-limit\" : \"upstream\";\n return { ok: false, reason, status };\n }\n if (!response.body) return { ok: false, reason: \"malformed\" };\n bodyReader = response.body.getReader();\n let bytes = 0;\n let text = \"\";\n const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n while (true) {\n const chunk = await bodyReader.read();\n if (expired) return { ok: false, reason: \"timeout\" };\n if (chunk.done) break;\n bytes += chunk.value.byteLength;\n if (bytes > RESPONSE_LIMIT) { cancel(); return { ok: false, reason: \"malformed\" }; }\n try { text += decoder.decode(chunk.value, { stream: true }); }\n catch { cancel(); return { ok: false, reason: \"malformed\" }; }\n }\n try {\n text += decoder.decode();\n const envelope: unknown = JSON.parse(text);\n if (!envelope || typeof envelope !== \"object\" || Array.isArray(envelope) || !Object.hasOwn(envelope, \"result\")) return { ok: false, reason: \"malformed\" };\n return { ok: true, value: (envelope as Record<string, unknown>).result };\n } catch { return { ok: false, reason: \"malformed\" }; }\n } catch { return { ok: false, reason: expired ? \"timeout\" : \"network\" }; }\n };\n try { return await Promise.race([work(), deadline]); }\n finally { clearTimeout(timer); }\n },\n } satisfies CmsAdapter);\n}\n\nexport function sanityBindingFromEnv(env: Readonly<Record<string, string | undefined>>): SanityBinding {\n return bindingCopy({ projectId: env.SANITY_PROJECT_ID, dataset: env.SANITY_DATASET, apiVersion: env.SANITY_API_VERSION } as SanityBinding);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["TYPE", "ID", "SCOPE", "dependenciesCopy", "dependencies", "types", "type", "ids", "id", "defineCmsQuery", "query", "params", "copied", "key", "descriptor", "value", "cmsTags", "scope", "tags", "RESPONSE_LIMIT", "bindingCopy", "binding", "createSanityAdapter", "options", "timeoutMs", "token", "fetchImpl", "scope", "query", "policy", "validated", "types", "ids", "tag", "expected", "cmsTags", "i", "defineCmsQuery", "raw", "url", "key", "controller", "bodyReader", "expired", "cancel", "timer", "deadline", "resolve", "work", "response", "status", "bytes", "text", "decoder", "chunk", "envelope", "sanityBindingFromEnv", "env"]
7
7
  }
package/dist/server.cjs CHANGED
@@ -1,2 +1,6 @@
1
- "use strict";var u=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var S=(e,r)=>{for(var n in r)u(e,n,{get:r[n],enumerable:!0})},h=(e,r,n,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let t of k(r))!v.call(e,t)&&t!==n&&u(e,t,{get:()=>r[t],enumerable:!(a=R(r,t))||a.enumerable});return e};var O=e=>h(u({},"__esModule",{value:!0}),e);var F={};S(F,{createCmsReader:()=>T});module.exports=O(F);var I=require("server-only");var A=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,x=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,z=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function g(e){if(!e||!Array.isArray(e.types)||e.types.length===0)throw new TypeError("CMS dependencies require document types");let r=[...e.types];for(let a of r)if(typeof a!="string"||!A.test(a))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let n=e.ids===void 0?void 0:[...e.ids];for(let a of n??[])if(typeof a!="string"||!x.test(a)||/^(drafts|versions)\./.test(a))throw new TypeError("Invalid CMS document ID");if(new Set(r).size+new Set(n).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(r),...n===void 0?{}:{ids:Object.freeze(n)}})}function w(e){if(!e||typeof e.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(e.name)||typeof e.query!="string"||e.query.trim()===""||typeof e.resolve!="function")throw new TypeError("Invalid CMS query configuration");let r=e.params;if(!r||typeof r!="object"||Object.getPrototypeOf(r)!==Object.prototype&&Object.getPrototypeOf(r)!==null)throw new TypeError("CMS params must be plain JSON scalars");let n={};for(let a of Reflect.ownKeys(r)){let t=Object.getOwnPropertyDescriptor(r,a);if(typeof a!="string"||!t||!Object.hasOwn(t,"value")||!t.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let s=t.value;if(!(s===null||typeof s=="string"||typeof s=="boolean"||typeof s=="number"&&Number.isFinite(s)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(n,a,{value:s,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(n),dependencies:g(e.dependencies),resolve:e.resolve})}function p(e,r){if(typeof e!="string"||e.length>77||!z.test(e))throw new TypeError("Invalid CMS scope");let n=g(r),a=[...[...new Set(n.types)].sort().map(t=>`cms:${e}:type:${t}`),...[...new Set(n.ids??[])].sort().map(t=>`cms:${e}:id:${t}`)];return Object.freeze(a)}function b(e){if(!e||!Object.hasOwn(e,"data")||!Array.isArray(e.fallbackFields)||![...e.fallbackFields].every(r=>typeof r=="string"&&(r==="$"||/^[A-Za-z][A-Za-z0-9_.[\]-]{0,127}$/.test(r))))throw new TypeError("Invalid CMS resolution");if(e.warnings!==void 0&&(!Array.isArray(e.warnings)||![...e.warnings].every(r=>r==="siteHero.layout.defaulted"||r==="siteHero.tagline.dropped"||r==="siteHero.taglines.defaulted")))throw new TypeError("Invalid CMS resolution warnings");return{data:e.data,fallbackFields:Object.freeze([...new Set(e.fallbackFields)]),...e.warnings?.length?{warnings:Object.freeze([...new Set(e.warnings)])}:{}}}function T(e){let r=e?.revalidateSeconds??3600;if(!Number.isSafeInteger(r)||r<3600||!e?.adapter||typeof e.adapter.read!="function"||e.onDiagnostic!==void 0&&typeof e.onDiagnostic!="function")throw new TypeError("Invalid CMS reader configuration");let n=e.adapter;p(n.scope,{types:["ScopeValidation"]});let a=t=>{try{e.onDiagnostic?e.onDiagnostic(t):console.warn(JSON.stringify(t))}catch{}};return{async read(t,s){let l,f,C;try{if(l=w(t),C=p(n.scope,l.dependencies),!s||!Object.hasOwn(s,"fallback"))throw new TypeError;f=b(l.resolve(null,s.fallback))}catch{throw new TypeError("Invalid CMS query or fallback configuration")}let m=(c,y,d)=>(a({event:"cms.fallback",query:l.name,reason:c,fields:["$"],...y===void 0?{}:{status:y},...d?{warnings:d}:{}}),{data:f.data,source:"fallback",fallbackFields:["$"],reason:c,...d?{warnings:d}:{}}),o;try{o=await n.read({name:l.name,query:l.query,params:l.params},{tags:C,revalidateSeconds:r})}catch{return m("network")}if(!o.ok){let y=["configuration","network","timeout","rate-limit","upstream","plan-limit","permission","malformed"].includes(o.reason)?o.reason:"malformed",d=Number.isInteger(o.status)&&(o.status??0)>=100&&(o.status??0)<=599?o.status:void 0;return m(y,d)}if(o.value===null||o.value===void 0)return m("missing");let i;try{i=b(l.resolve(o.value,s.fallback))}catch{return m("malformed")}return i.fallbackFields.includes("$")?{...m("invalid-field",void 0,i.warnings),data:i.data}:i.fallbackFields.length>0?(a({event:"cms.partial-fallback",query:l.name,reason:"invalid-field",fields:i.fallbackFields,...i.warnings?{warnings:i.warnings}:{}}),{...i,source:"mixed",reason:"invalid-field"}):{...i,source:"cms"}}}}0&&(module.exports={createCmsReader});
1
+ "use strict";var O=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var z=(e,n)=>{for(var t in n)O(e,t,{get:n[t],enumerable:!0})},J=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of H(n))!F.call(e,r)&&r!==t&&O(e,r,{get:()=>n[r],enumerable:!(o=B(n,r))||o.enumerable});return e};var Q=e=>J(O({},"__esModule",{value:!0}),e);var oe={};z(oe,{MENU_DECORATIONS:()=>A,MENU_LAYOUTS:()=>_,MENU_LAYOUT_DEFAULTS:()=>R,createCmsReader:()=>L,menuQuery:()=>U,menuTags:()=>E,parseMenuDocument:()=>w});module.exports=Q(oe);var Se=require("server-only");function x(e){if(!Array.isArray(e))return!1;for(let n=0;n<e.length;n+=1)if(!Object.hasOwn(e,n))return!1;return!0}var _=["stacked","columns"],A=["none","playful"],R={layout:"stacked",decoration:"none"},T=`_type, _id, _rev, _updatedAt, title, locationKeys, note, signOff,
2
+ variants[]{_key, label, note, sections[]{_key, title, service, items[]{
3
+ _key, name, description, priceNote, dietary, allergenNote, availability,
4
+ prices[]{_key, label, amount{minor, currency}}, extras[]{_key, name, amount{minor, currency}}
5
+ }}}`;function E(e,n){return S(e,{types:["menu"],...n===void 0?{}:{ids:[n]}})}function s(e,n){throw new h("menu",[`${e} ${n}`])}function M(e,n,t=new Set,o){if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(typeof e!="object"||e===null)return s(n,"is not plain JSON data");try{if(t.has(e))return s(n,"is not acyclic JSON data");let r=Array.isArray(e),u=Object.getPrototypeOf(e);if(r?u!==Array.prototype:u!==Object.prototype&&u!==null)return s(n,"is not an ordinary saved object");t.add(e);let c=Reflect.ownKeys(e),k=r?[]:{},b=0,y=0;for(let i of c){if(typeof i!="string")return s(n,"has a symbol key");let a=r&&i!=="length"?`${n}[${i}]`:`${n}.${i}`,d;try{d=i==="_id"&&o!==void 0?o:Object.getOwnPropertyDescriptor(e,i)}catch{return s(a,"could not be snapshotted as plain JSON data")}if(!d||!Object.hasOwn(d,"value"))return s(a,"is not a saved data property");if(r&&i==="length"){let C=d.value;if(typeof C!="number"||!Number.isSafeInteger(C)||C<0)return s(a,"is not a saved list length");b=C;continue}if(!d.enumerable||r&&!/^(0|[1-9]\d*)$/.test(i))return s(a,"is not a JSON data property");let $=d.value,p=M($,a,t);Object.defineProperty(k,i,{value:p,enumerable:!0,writable:!0,configurable:!0}),y++}return r&&(y!==b||k.length!==b)?s(n,"is not a complete saved list"):k}catch(r){if(r instanceof h)throw r;return s(n,"could not be snapshotted as plain JSON data")}finally{t.delete(e)}}function g(e,n){return e===null||typeof e!="object"||Array.isArray(e)||Object.getPrototypeOf(e)!==Object.prototype&&Object.getPrototypeOf(e)!==null?s(n,"is not an ordinary saved object"):e}function l(e,n,t=!0){return typeof e!="string"||t&&e.trim()===""?s(n,"is not saved text"):e}function f(e,n,t){return e[n]===void 0||e[n]===null?{}:{[n]:l(e[n],`${t}.${n}`,!1)}}function m(e,n,t){return e==null?[]:x(e)?e.map((o,r)=>t(o,`${n}[${String(r)}]`)):s(n,"is not a complete saved list")}function D(e,n){let t=g(e,n);if(typeof t.minor!="number"||!Number.isSafeInteger(t.minor)||t.minor<0)return s(`${n}.minor`,"is not a whole non-negative safe amount");let o=l(t.currency,`${n}.currency`);return/^[A-Z]{3}$/.test(o)?{minor:t.minor,currency:o}:s(`${n}.currency`,"is not a three-letter currency code")}function Y(e,n){let t=g(e,n);return{_key:l(t._key,`${n}._key`),amount:D(t.amount,`${n}.amount`),...f(t,"label",n)}}function G(e,n){let t=g(e,n);return{_key:l(t._key,`${n}._key`),name:l(t.name,`${n}.name`),amount:D(t.amount,`${n}.amount`)}}function W(e,n){let t=g(e,n),o=t.availability??"available";return o!=="available"&&o!=="sold-out"&&o!=="hidden"?s(`${n}.availability`,"is not an availability choice"):{_key:l(t._key,`${n}._key`),name:l(t.name,`${n}.name`),...f(t,"description",n),...f(t,"priceNote",n),...f(t,"allergenNote",n),prices:m(t.prices,`${n}.prices`,Y),extras:m(t.extras,`${n}.extras`,G),dietary:m(t.dietary,`${n}.dietary`,l),availability:o}}function Z(e,n){let t=g(e,n);return{_key:l(t._key,`${n}._key`),title:l(t.title,`${n}.title`),...f(t,"service",n),items:m(t.items,`${n}.items`,W)}}function K(e,n){let t=g(e,n);return{_key:l(t._key,`${n}._key`),label:l(t.label,`${n}.label`),...f(t,"note",n),sections:m(t.sections,`${n}.sections`,Z)}}function V(e){if(e===null||typeof e!="object"||Array.isArray(e))return!1;let n=e._id;return typeof n=="string"&&n.trim()!==""&&!/^(drafts|versions)\./.test(n)}function w(e,n="menu"){return X(M(e,n),n)}function X(e,n){let t=g(e,n);if(t._type!=="menu")return s(`${n}._type`,"is not menu");if(!V(t))return s(`${n}._id`,"is not a published menu identity");let o=l(t._updatedAt,`${n}._updatedAt`);if(!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(o)||!Number.isFinite(Date.parse(o)))return s(`${n}._updatedAt`,"is not an update date");let r=m(t.variants,`${n}.variants`,K);return r.length===0?s(`${n}.variants`,"has no menu choices"):{_type:"menu",_id:l(t._id,`${n}._id`),_rev:l(t._rev,`${n}._rev`),_updatedAt:o,title:l(t.title,`${n}.title`),locationKeys:m(t.locationKeys,`${n}.locationKeys`,l),variants:r,...f(t,"note",n),...Object.hasOwn(t,"signOff")?{signOff:t.signOff}:{}}}function j(e){if(e===null)return!0;try{return w(e),!0}catch{return!1}}var P="malformed-content",h=class extends Error{code=P;documentId;problems;constructor(n,t){super(`${P}: ${n}: ${t.join("; ")}`),this.name="MalformedContentError",this.documentId=n,this.problems=t}};var N=`{..., "sections": coalesce(sections[]{..., _type == "menuBlock" => {menu->{${T}}}, _type == "linkListBlock" => {links[]{..., "page": page->{title, "slug": slug.current}}}}, sections)}`,pe=`*[_type == "page" && defined(slug.current)]|order(slug.current asc)${N}`,fe=`*[_type == "page" && slug.current == $slug][0]${N}`;var ee=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,ne=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,te=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function q(e){if(!e||!Array.isArray(e.types)||e.types.length===0)throw new TypeError("CMS dependencies require document types");let n=[...e.types];for(let o of n)if(typeof o!="string"||!ee.test(o))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let t=e.ids===void 0?void 0:[...e.ids];for(let o of t??[])if(typeof o!="string"||!ne.test(o)||/^(drafts|versions)\./.test(o))throw new TypeError("Invalid CMS document ID");if(new Set(n).size+new Set(t).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(n),...t===void 0?{}:{ids:Object.freeze(t)}})}function I(e){if(!e||typeof e.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(e.name)||typeof e.query!="string"||e.query.trim()===""||typeof e.resolve!="function")throw new TypeError("Invalid CMS query configuration");let n=e.params;if(!n||typeof n!="object"||Object.getPrototypeOf(n)!==Object.prototype&&Object.getPrototypeOf(n)!==null)throw new TypeError("CMS params must be plain JSON scalars");let t={};for(let o of Reflect.ownKeys(n)){let r=Object.getOwnPropertyDescriptor(n,o);if(typeof o!="string"||!r||!Object.hasOwn(r,"value")||!r.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let u=r.value;if(!(u===null||typeof u=="string"||typeof u=="boolean"||typeof u=="number"&&Number.isFinite(u)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(t,o,{value:u,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(t),dependencies:q(e.dependencies),resolve:e.resolve})}function S(e,n){if(typeof e!="string"||e.length>77||!te.test(e))throw new TypeError("Invalid CMS scope");let t=q(n),o=[...[...new Set(t.types)].sort().map(r=>`cms:${e}:type:${r}`),...[...new Set(t.ids??[])].sort().map(r=>`cms:${e}:id:${r}`)];return Object.freeze(o)}function U(e){return I({name:"menu.v1",query:`*[_type == "menu" && _id == $id && !(_id in path("drafts.**")) && !(_id in path("versions.**"))][0]{${T}}`,params:{id:e},dependencies:{types:["menu"],ids:[e]},resolve:(n,t)=>{if(!j(t)||t!==null&&t._id!==e)throw new TypeError("Invalid CMS menu fallback");if(n==null)return{data:t,fallbackFields:["$"]};let o=w(n);if(o._id!==e)throw new h("menu",["menu._id does not match the requested document"]);return{data:o,fallbackFields:[]}}})}function v(e){if(!e||!Object.hasOwn(e,"data")||!Array.isArray(e.fallbackFields)||![...e.fallbackFields].every(n=>typeof n=="string"&&(n==="$"||/^[A-Za-z][A-Za-z0-9_.[\]-]{0,127}$/.test(n))))throw new TypeError("Invalid CMS resolution");if(e.warnings!==void 0&&(!Array.isArray(e.warnings)||![...e.warnings].every(n=>n==="siteHero.layout.defaulted"||n==="siteHero.tagline.dropped"||n==="siteHero.taglines.defaulted")))throw new TypeError("Invalid CMS resolution warnings");return{data:e.data,fallbackFields:Object.freeze([...new Set(e.fallbackFields)]),...e.warnings?.length?{warnings:Object.freeze([...new Set(e.warnings)])}:{}}}function L(e){let n=e?.revalidateSeconds??3600;if(!Number.isSafeInteger(n)||n<3600||!e?.adapter||typeof e.adapter.read!="function"||e.onDiagnostic!==void 0&&typeof e.onDiagnostic!="function")throw new TypeError("Invalid CMS reader configuration");let t=e.adapter;S(t.scope,{types:["ScopeValidation"]});let o=r=>{try{e.onDiagnostic?e.onDiagnostic(r):console.warn(JSON.stringify(r))}catch{}};return{async read(r,u){let c,k,b;try{if(c=I(r),b=S(t.scope,c.dependencies),!u||!Object.hasOwn(u,"fallback"))throw new TypeError;k=v(c.resolve(null,u.fallback))}catch{throw new TypeError("Invalid CMS query or fallback configuration")}let y=(d,$,p)=>(o({event:"cms.fallback",query:c.name,reason:d,fields:["$"],...$===void 0?{}:{status:$},...p?{warnings:p}:{}}),{data:k.data,source:"fallback",fallbackFields:["$"],reason:d,...p?{warnings:p}:{}}),i;try{i=await t.read({name:c.name,query:c.query,params:c.params},{tags:b,revalidateSeconds:n})}catch{return y("network")}if(!i.ok){let $=["configuration","network","timeout","rate-limit","upstream","plan-limit","permission","malformed"].includes(i.reason)?i.reason:"malformed",p=Number.isInteger(i.status)&&(i.status??0)>=100&&(i.status??0)<=599?i.status:void 0;return y($,p)}if(i.value===null||i.value===void 0)return y("missing");let a;try{a=v(c.resolve(i.value,u.fallback))}catch{return y("malformed")}return a.fallbackFields.includes("$")?{...y("invalid-field",void 0,a.warnings),data:a.data}:a.fallbackFields.length>0?(o({event:"cms.partial-fallback",query:c.name,reason:"invalid-field",fields:a.fallbackFields,...a.warnings?{warnings:a.warnings}:{}}),{...a,source:"mixed",reason:"invalid-field"}):{...a,source:"cms"}}}}0&&(module.exports={MENU_DECORATIONS,MENU_LAYOUTS,MENU_LAYOUT_DEFAULTS,createCmsReader,menuQuery,menuTags,parseMenuDocument});
2
6
  //# sourceMappingURL=server.cjs.map