@weatherboard/cms 0.6.0 → 0.8.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.
- package/README.md +68 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +4 -4
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +4 -4
- package/dist/next.cjs +4 -2
- package/dist/next.cjs.map +4 -4
- package/dist/next.d.cts +2 -0
- package/dist/next.d.mts +2 -0
- package/dist/next.d.ts +2 -0
- package/dist/next.mjs +4 -2
- package/dist/next.mjs.map +4 -4
- package/dist/portable/sections.d.cts +43 -6
- package/dist/portable/sections.d.mts +43 -6
- package/dist/portable/sections.d.ts +43 -6
- package/dist/portable/site-content.d.cts +41 -10
- package/dist/portable/site-content.d.mts +41 -10
- package/dist/portable/site-content.d.ts +41 -10
- package/dist/runtime/site-readers.d.cts +164 -0
- package/dist/runtime/site-readers.d.mts +164 -0
- package/dist/runtime/site-readers.d.ts +164 -0
- package/dist/runtime/test-fixtures/saved-documents.d.cts +81 -0
- package/dist/runtime/test-fixtures/saved-documents.d.mts +81 -0
- package/dist/runtime/test-fixtures/saved-documents.d.ts +81 -0
- package/dist/server.cjs +4 -2
- package/dist/server.cjs.map +4 -4
- package/dist/server.d.cts +2 -0
- package/dist/server.d.mts +2 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.mjs +4 -2
- package/dist/server.mjs.map +4 -4
- package/dist/site-content.cjs +7 -4
- package/dist/site-content.cjs.map +4 -4
- package/dist/site-content.d.cts +2 -2
- package/dist/site-content.d.mts +2 -2
- package/dist/site-content.d.ts +2 -2
- package/dist/site-content.mjs +7 -4
- package/dist/site-content.mjs.map +4 -4
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -6,6 +6,47 @@ hero types without a provider SDK or environment access. Server reads use
|
|
|
6
6
|
`@weatherboard/cms/server` or `/next`, with the `/sanity` adapter; `/webhook`
|
|
7
7
|
provides portable signature verification. `/testing` and `/guard` are tooling.
|
|
8
8
|
|
|
9
|
+
## Server site readers (0.8.0)
|
|
10
|
+
|
|
11
|
+
Import `openVacanciesQuery`, `locationsQuery`, `scheduleQuery`, their parsers and
|
|
12
|
+
tag helpers from `@weatherboard/cms/next` in a Next server component, or from
|
|
13
|
+
`@weatherboard/cms/server` in another server runtime. Supply a configured
|
|
14
|
+
`createNextCmsReader` reader and repository data to `resolveWithFallback`:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createNextCmsReader, openVacanciesQuery, resolveWithFallback } from '@weatherboard/cms/next';
|
|
18
|
+
|
|
19
|
+
const reader = createNextCmsReader({ adapter });
|
|
20
|
+
const validateVacancy = (entry: Record<string, unknown>): string | null =>
|
|
21
|
+
typeof entry.title === 'string' && entry.title.trim() ? null : 'missing title';
|
|
22
|
+
const result = await resolveWithFallback(reader, openVacanciesQuery('2026-10-19', validateVacancy), []);
|
|
23
|
+
// result.source is 'sanity', 'mixed' or 'fallback'.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The client supplies the validator; the package supplies the pipeline. All list
|
|
27
|
+
readers require a client validator with no default: `openVacanciesQuery` takes
|
|
28
|
+
one that returns a refusal reason or `null`, while `locationsQuery` and
|
|
29
|
+
`businessLocationsQuery` take one that returns a validated location or throws.
|
|
30
|
+
The package checks document types and shapes, then runs identity validation,
|
|
31
|
+
duplicate detection, full parsing with per-field fallback, repository merging
|
|
32
|
+
and source reporting in that order. The client decides business validity on
|
|
33
|
+
the merged result, including cross-field rules such as required contact details.
|
|
34
|
+
|
|
35
|
+
The existing Sanity adapter supplies the request timeout and forwards hourly
|
|
36
|
+
cache and scoped revalidation tags. `locationsQuery` merges each matching
|
|
37
|
+
published document into the supplied `LocationFields[]` fallback by slug and
|
|
38
|
+
records fallback fields. For a nested business-location shape,
|
|
39
|
+
`businessLocationsQuery` and `parseBusinessLocation` preserve repository-only
|
|
40
|
+
fields and require the host's validator for cross-field rules. `scheduleQuery` preserves repository-only stop fields
|
|
41
|
+
when names match. The host keeps its repository data and chooses how to display
|
|
42
|
+
the source. `menuQuery`, `parseMenuDocument` and `menuTags` remain the menu API.
|
|
43
|
+
|
|
44
|
+
`openVacanciesQuery`, `parseVacancies` and `parseVacancyDocument` require the
|
|
45
|
+
consumer's validator. The consumer can enforce its work-location choices and
|
|
46
|
+
the note required for an `Other` choice. The package supplies no site-specific
|
|
47
|
+
default. A-2463 will replace those choices with references to the client's
|
|
48
|
+
`location` documents.
|
|
49
|
+
|
|
9
50
|
## Site hero
|
|
10
51
|
|
|
11
52
|
The singleton `siteHero` keeps its existing heading (1–80 characters, single
|
|
@@ -79,6 +120,9 @@ optional `page.sections[]` that `@weatherboard/sanity-schema-base` declares
|
|
|
79
120
|
| `faqBlock` (items `faqItem`) | `faq` | HeadingList | `beside` |
|
|
80
121
|
| `galleryBlock` | `gallery` | StaggerRow | `staggered` |
|
|
81
122
|
| `contactBlock` | `contact` | Split | `media-end` |
|
|
123
|
+
| `textItemsBlock` | `text_items` | StaggerRow | `staggered` |
|
|
124
|
+
| `stepsBlock` | `steps` | HeadingList, numbered | `beside` |
|
|
125
|
+
| `linkListBlock` | `link_list` | HeadingList, page links | `beside` |
|
|
82
126
|
|
|
83
127
|
The four home kinds read exactly as they do on the home page. The new kinds
|
|
84
128
|
return every key, `null` where there is nothing, with images as
|
|
@@ -122,6 +166,30 @@ The warnings travel in the page data, not in the server reader's
|
|
|
122
166
|
|
|
123
167
|
0.3.0 is an additive minor under the pilot semver policy: a new reader kind.
|
|
124
168
|
|
|
169
|
+
### Schema extension (0.7.0)
|
|
170
|
+
|
|
171
|
+
Pages may supply `titleTail`; media sections may omit a photo. FAQ headings
|
|
172
|
+
may be absent, and answers can use `faqAnswer.content` Portable Text with links.
|
|
173
|
+
The reader also accepts saved plain string or `copyParagraph` answers, so no
|
|
174
|
+
content migration is needed. Rich FAQ answers carry an explicit rich body so
|
|
175
|
+
links render as links. Text-only bodies remain Markdown strings; bodies with
|
|
176
|
+
tables return ordered structured blocks and rows whose cells contain Portable
|
|
177
|
+
Text spans with marks and link annotations. The site renders the first row as
|
|
178
|
+
a header without parsing cell text as Markdown. Legacy string cells become
|
|
179
|
+
unmarked spans. Empty cells
|
|
180
|
+
and ragged rows are refused. A home
|
|
181
|
+
page may omit `hero.headline` when its site uses the separately validated
|
|
182
|
+
`siteHero` heading; in that case the home composition's `hero` contains that heading.
|
|
183
|
+
An explicitly supplied blank headline is refused.
|
|
184
|
+
|
|
185
|
+
The three new block kinds above read from `page.sections`. `linkListBlock`
|
|
186
|
+
references pages; the page queries project each target's title and slug.
|
|
187
|
+
The reader forms links as `/pages/<slug>/`, matching the shared action
|
|
188
|
+
contract's page path.
|
|
189
|
+
The existing `page` type dependency and site `typeToTags` entry cover both
|
|
190
|
+
the containing page and linked page updates. There is no new document type
|
|
191
|
+
to add to the tag map. Seasonal tiles remain in A-2258's scope.
|
|
192
|
+
|
|
125
193
|
## Food and drink menus (0.6.0)
|
|
126
194
|
|
|
127
195
|
0.6.0 is an additive minor: a new reader kind. `menuBlock` now reads as
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";var I=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var ee=Object.prototype.hasOwnProperty;var ne=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},te=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of X(e))!ee.call(n,r)&&r!==t&&I(n,r,{get:()=>e[r],enumerable:!(o=Z(e,r))||o.enumerable});return n};var oe=n=>te(I({},"__esModule",{value:!0}),n);var ge={};ne(ge,{CMS_CONTRACT_VERSION:()=>
|
|
1
|
+
"use strict";var I=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var ee=Object.prototype.hasOwnProperty;var ne=(n,e)=>{for(var t in e)I(n,t,{get:e[t],enumerable:!0})},te=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of X(e))!ee.call(n,r)&&r!==t&&I(n,r,{get:()=>e[r],enumerable:!(o=Z(e,r))||o.enumerable});return n};var oe=n=>te(I({},"__esModule",{value:!0}),n);var ge={};ne(ge,{CMS_CONTRACT_VERSION:()=>z,MENU_DECORATIONS:()=>E,MENU_LAYOUTS:()=>A,MENU_LAYOUT_DEFAULTS:()=>C,SITE_HERO:()=>g,SITE_HERO_LAYOUTS:()=>R,SITE_HERO_LAYOUT_WARNING:()=>D,SITE_HERO_TAGLINES_DEFAULTED_WARNING:()=>j,SITE_HERO_TAGLINE_DROPPED_WARNING:()=>N,SITE_HERO_TAGLINE_MAX_LENGTH:()=>M,cmsTags:()=>O,defineCmsQuery:()=>_,menuQuery:()=>K,menuTags:()=>U,parseMenuDocument:()=>$,parseSiteHero:()=>P,siteHeroQuery:()=>G,validateSiteHeroTaglines:()=>H,validateTextDocument:()=>S});module.exports=oe(ge);function L(n){if(!Array.isArray(n))return!1;for(let e=0;e<n.length;e+=1)if(!Object.hasOwn(n,e))return!1;return!0}var A=["stacked","columns"],E=["none","playful"],C={layout:"stacked",decoration:"none"},x=`_type, _id, _rev, _updatedAt, title, locationKeys, note, signOff,
|
|
2
2
|
variants[]{_key, label, note, sections[]{_key, title, service, items[]{
|
|
3
3
|
_key, name, description, priceNote, dietary, allergenNote, availability,
|
|
4
4
|
prices[]{_key, label, amount{minor, currency}}, extras[]{_key, name, amount{minor, currency}}
|
|
5
|
-
}}}`;function U(n,e){return x(n,{types:["menu"],...e===void 0?{}:{ids:[e]}})}function s(n,e){throw new S("menu",[`${n} ${e}`])}function v(n,e,t=new Set,o){if(n===null||typeof n=="string"||typeof n=="boolean"||typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="object"||n===null)return s(e,"is not plain JSON data");try{if(t.has(n))return s(e,"is not acyclic JSON data");let r=Array.isArray(n),i=Object.getPrototypeOf(n);if(r?i!==Array.prototype:i!==Object.prototype&&i!==null)return s(e,"is not an ordinary saved object");t.add(n);let d=Reflect.ownKeys(n),l=r?[]:{},f=0,y=0;for(let u of d){if(typeof u!="string")return s(e,"has a symbol key");let p=r&&u!=="length"?`${e}[${u}]`:`${e}.${u}`,a;try{a=u==="_id"&&o!==void 0?o:Object.getOwnPropertyDescriptor(n,u)}catch{return s(p,"could not be snapshotted as plain JSON data")}if(!a||!Object.hasOwn(a,"value"))return s(p,"is not a saved data property");if(r&&u==="length"){let T=a.value;if(typeof T!="number"||!Number.isSafeInteger(T)||T<0)return s(p,"is not a saved list length");f=T;continue}if(!a.enumerable||r&&!/^(0|[1-9]\d*)$/.test(u))return s(p,"is not a JSON data property");let w=a.value,V=v(w,p,t);Object.defineProperty(l,u,{value:V,enumerable:!0,writable:!0,configurable:!0}),y++}return r&&(y!==f||l.length!==f)?s(e,"is not a complete saved list"):l}catch(r){if(r instanceof S)throw r;return s(e,"could not be snapshotted as plain JSON data")}finally{t.delete(n)}}function b(n,e){return n===null||typeof n!="object"||Array.isArray(n)||Object.getPrototypeOf(n)!==Object.prototype&&Object.getPrototypeOf(n)!==null?s(e,"is not an ordinary saved object"):n}function c(n,e,t=!0){return typeof n!="string"||t&&n.trim()===""?s(e,"is not saved text"):n}function m(n,e,t){return n[e]===void 0||n[e]===null?{}:{[e]:c(n[e],`${t}.${e}`,!1)}}function h(n,e,t){return n==null?[]:L(n)?n.map((o,r)=>t(o,`${e}[${String(r)}]`)):s(e,"is not a complete saved list")}function q(n,e){let t=b(n,e);if(typeof t.minor!="number"||!Number.isSafeInteger(t.minor)||t.minor<0)return s(`${e}.minor`,"is not a whole non-negative safe amount");let o=c(t.currency,`${e}.currency`);return/^[A-Z]{3}$/.test(o)?{minor:t.minor,currency:o}:s(`${e}.currency`,"is not a three-letter currency code")}function re(n,e){let t=b(n,e);return{_key:c(t._key,`${e}._key`),amount:q(t.amount,`${e}.amount`),...m(t,"label",e)}}function ie(n,e){let t=b(n,e);return{_key:c(t._key,`${e}._key`),name:c(t.name,`${e}.name`),amount:q(t.amount,`${e}.amount`)}}function se(n,e){let t=b(n,e),o=t.availability??"available";return o!=="available"&&o!=="sold-out"&&o!=="hidden"?s(`${e}.availability`,"is not an availability choice"):{_key:c(t._key,`${e}._key`),name:c(t.name,`${e}.name`),...m(t,"description",e),...m(t,"priceNote",e),...m(t,"allergenNote",e),prices:h(t.prices,`${e}.prices`,re),extras:h(t.extras,`${e}.extras`,ie),dietary:h(t.dietary,`${e}.dietary`,c),availability:o}}function ae(n,e){let t=b(n,e);return{_key:c(t._key,`${e}._key`),title:c(t.title,`${e}.title`),...m(t,"service",e),items:h(t.items,`${e}.items`,se)}}function le(n,e){let t=b(n,e);return{_key:c(t._key,`${e}._key`),label:c(t.label,`${e}.label`),...m(t,"note",e),sections:h(t.sections,`${e}.sections`,ae)}}function ue(n){if(n===null||typeof n!="object"||Array.isArray(n))return!1;let e=n._id;return typeof e=="string"&&e.trim()!==""&&!/^(drafts|versions)\./.test(e)}function k(n,e="menu"){return ce(v(n,e),e)}function ce(n,e){let t=b(n,e);if(t._type!=="menu")return s(`${e}._type`,"is not menu");if(!ue(t))return s(`${e}._id`,"is not a published menu identity");let o=c(t._updatedAt,`${e}._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(`${e}._updatedAt`,"is not an update date");let r=h(t.variants,`${e}.variants`,le);return r.length===0?s(`${e}.variants`,"has no menu choices"):{_type:"menu",_id:c(t._id,`${e}._id`),_rev:c(t._rev,`${e}._rev`),_updatedAt:o,title:c(t.title,`${e}.title`),locationKeys:h(t.locationKeys,`${e}.locationKeys`,c),variants:r,...m(t,"note",e),...Object.hasOwn(t,"signOff")?{signOff:t.signOff}:{}}}function F(n){if(n===null)return!0;try{return k(n),!0}catch{return!1}}var Y="malformed-content",S=class extends Error{code=Y;documentId;problems;constructor(e,t){super(`${Y}: ${e}: ${t.join("; ")}`),this.name="MalformedContentError",this.documentId=e,this.problems=t}};var z=`{..., "sections": coalesce(sections[]{..., _type == "menuBlock" => {menu->{${E}}}}, sections)}`,Ce=`*[_type == "page" && defined(slug.current)]|order(slug.current asc)${z}`,Ae=`*[_type == "page" && slug.current == $slug][0]${z}`;var de=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,ye=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,pe=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function B(n){if(!n||!Array.isArray(n.types)||n.types.length===0)throw new TypeError("CMS dependencies require document types");let e=[...n.types];for(let o of e)if(typeof o!="string"||!de.test(o))throw new TypeError("Invalid CMS document type");if(n.ids!==void 0&&!Array.isArray(n.ids))throw new TypeError("Invalid CMS document IDs");let t=n.ids===void 0?void 0:[...n.ids];for(let o of t??[])if(typeof o!="string"||!ye.test(o)||/^(drafts|versions)\./.test(o))throw new TypeError("Invalid CMS document ID");if(new Set(e).size+new Set(t).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(e),...t===void 0?{}:{ids:Object.freeze(t)}})}function _(n){if(!n||typeof n.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(n.name)||typeof n.query!="string"||n.query.trim()===""||typeof n.resolve!="function")throw new TypeError("Invalid CMS query configuration");let e=n.params;if(!e||typeof e!="object"||Object.getPrototypeOf(e)!==Object.prototype&&Object.getPrototypeOf(e)!==null)throw new TypeError("CMS params must be plain JSON scalars");let t={};for(let o of Reflect.ownKeys(e)){let r=Object.getOwnPropertyDescriptor(e,o);if(typeof o!="string"||!r||!Object.hasOwn(r,"value")||!r.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=r.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(t,o,{value:i,enumerable:!0})}return Object.freeze({name:n.name,query:n.query,params:Object.freeze(t),dependencies:B(n.dependencies),resolve:n.resolve})}function x(n,e){if(typeof n!="string"||n.length>77||!pe.test(n))throw new TypeError("Invalid CMS scope");let t=B(e),o=[...[...new Set(t.types)].sort().map(r=>`cms:${n}:type:${r}`),...[...new Set(t.ids??[])].sort().map(r=>`cms:${n}:id:${r}`)];return Object.freeze(o)}function G(n){return _({name:"menu.v1",query:`*[_type == "menu" && _id == $id && !(_id in path("drafts.**")) && !(_id in path("versions.**"))][0]{${E}}`,params:{id:n},dependencies:{types:["menu"],ids:[n]},resolve:(e,t)=>{if(!F(t)||t!==null&&t._id!==n)throw new TypeError("Invalid CMS menu fallback");if(e==null)return{data:t,fallbackFields:["$"]};let o=k(e);if(o._id!==n)throw new S("menu",["menu._id does not match the requested document"]);return{data:o,fallbackFields:[]}}})}var R=["columns","rows"],M=40,N="siteHero.layout.defaulted",D="siteHero.tagline.dropped",j="siteHero.taglines.defaulted",Q=1,g={key:"hero",documentId:"siteHero",documentType:"siteHero",fields:[{name:"heading",label:"Heading",noun:{article:"a",word:"heading"},kind:"single-line",required:!0,minLength:1,maxLength:80,noTrailingFullStop:!0},{name:"intro",label:"Introduction",noun:{article:"an",word:"introduction"},kind:"multi-line",required:!0,minLength:1,maxLength:320}],copy:{currentTitle:"On your site now",editTitle:"Edit and publish",empty:"Your site has no hero text yet. Whatever you publish below becomes its first version."}};function fe(n,e){let{article:t,word:o}=n.noun;if(e.length===0)return n.required?`Enter ${t} ${o}.`:null;let r=[...e].length;return r<n.minLength?`Make the ${o} at least ${String(n.minLength)} characters. It is ${String(r)} now.`:r>n.maxLength?`Keep the ${o} to ${String(n.maxLength)} characters or fewer. It is ${String(r)} now.`:e.includes("\u2014")?`The ${o} contains a long dash. Use a comma, a colon or a short dash instead.`:n.kind==="single-line"&&/[\r\n]/.test(e)?`The ${o} must be a single line.`:n.noTrailingFullStop===!0&&e.endsWith(".")?`${o.charAt(0).toUpperCase()}${o.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`:null}function $(n,e){let t={},o={};for(let r of n.fields){let i=Object.hasOwn(e,r.name)?e[r.name]:void 0,d=typeof i=="string"?i.trim():"",l=fe(r,d);Object.defineProperty(l===null?t:o,r.name,{value:l??d,enumerable:!0})}return Object.keys(o).length>0?{ok:!1,errors:o}:{ok:!0,value:t}}function W(n){if(!Array.isArray(n))return{ok:!1,error:"Enter a list of taglines."};let e=g.fields[0];if(!e)throw new TypeError("Missing siteHero heading definition");let t={...e,name:"text",noun:{article:"a",word:"tagline"},maxLength:M},o=[],r=[],i=new Set;for(let[d,l]of n.entries()){if(!l||typeof l!="object"||Array.isArray(l)){r.push({index:d,error:"Enter a key and text for each tagline."});continue}let f=l,y=Object.hasOwn(f,"key")?f.key:void 0;if(typeof y!="string"||!/^[a-z][a-z0-9_-]{0,31}$/.test(y)){r.push({index:d,error:"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter."});continue}if(i.has(y)){r.push({index:d,error:"Use each tagline key only once."});continue}let u=$({...g,fields:[t]},f);if(!u.ok){r.push({index:d,error:u.errors.text??"Invalid tagline."});continue}let p=u.value.text??"";if((p.match(/\p{L}/gu)?.length??0)>=2&&!/\p{Ll}/u.test(p)){r.push({index:d,error:"Use sentence case for the tagline, rather than all capitals."});continue}i.add(y),o.push({key:y,text:p})}return{ok:!0,value:o,dropped:r}}function H(n){let e=W(n);if(!e.ok)return e;let t=e.dropped[0];return t?{ok:!1,error:t.error}:{ok:!0,value:e.value}}function J(n){return R.some(e=>n===e)}function P(n,e){let t=$(g,e),o=H(e.taglines??[]);if(!t.ok||!o.ok||e.layout!==void 0&&!J(e.layout))throw new TypeError("Invalid siteHero fallback");let r={heading:t.value.heading??"",intro:t.value.intro??"",layout:e.layout??"columns",taglines:o.value};if(n===null||typeof n!="object"||Array.isArray(n))return{data:r,fallbackFields:["$"]};let i=n,d=$(g,i),l=d.ok?[]:Object.keys(d.errors);for(let a of g.fields)if(!l.includes(a.name)){let w=d.ok?d.value[a.name]:i[a.name];typeof w=="string"&&(a.name==="heading"||a.name==="intro")&&(r[a.name]=w.trim())}let f=Object.hasOwn(i,"layout")?i.layout:void 0,y=[];J(f)?r.layout=f:(r.layout="columns",l.push("layout"),y.push(N));let u=W(Object.hasOwn(i,"taglines")?i.taglines:void 0);if(u.ok){r.taglines=u.value;for(let{index:a}of u.dropped)l.push(`taglines[${String(a)}]`);u.dropped.length>0&&y.push(D)}else l.push("taglines"),y.push(j);let p=[...g.fields.map(a=>a.name),"layout","taglines"].every(a=>l.includes(a));return{data:r,fallbackFields:p?["$"]:l,...y.length>0?{warnings:y}:{}}}function K(){return _({name:"siteHero.v1",query:'*[_id == $id && _type == "siteHero"][0]{heading,intro,layout,taglines}',params:{id:"siteHero"},dependencies:{types:["siteHero"],ids:["siteHero"]},resolve:P})}0&&(module.exports={CMS_CONTRACT_VERSION,MENU_DECORATIONS,MENU_LAYOUTS,MENU_LAYOUT_DEFAULTS,SITE_HERO,SITE_HERO_LAYOUTS,SITE_HERO_LAYOUT_WARNING,SITE_HERO_TAGLINES_DEFAULTED_WARNING,SITE_HERO_TAGLINE_DROPPED_WARNING,SITE_HERO_TAGLINE_MAX_LENGTH,cmsTags,defineCmsQuery,menuQuery,menuTags,parseMenuDocument,parseSiteHero,siteHeroQuery,validateSiteHeroTaglines,validateTextDocument});
|
|
5
|
+
}}}`;function U(n,e){return O(n,{types:["menu"],...e===void 0?{}:{ids:[e]}})}function s(n,e){throw new b("menu",[`${n} ${e}`])}function q(n,e,t=new Set,o){if(n===null||typeof n=="string"||typeof n=="boolean"||typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="object"||n===null)return s(e,"is not plain JSON data");try{if(t.has(n))return s(e,"is not acyclic JSON data");let r=Array.isArray(n),i=Object.getPrototypeOf(n);if(r?i!==Array.prototype:i!==Object.prototype&&i!==null)return s(e,"is not an ordinary saved object");t.add(n);let d=Reflect.ownKeys(n),a=r?[]:{},f=0,y=0;for(let u of d){if(typeof u!="string")return s(e,"has a symbol key");let p=r&&u!=="length"?`${e}[${u}]`:`${e}.${u}`,l;try{l=u==="_id"&&o!==void 0?o:Object.getOwnPropertyDescriptor(n,u)}catch{return s(p,"could not be snapshotted as plain JSON data")}if(!l||!Object.hasOwn(l,"value"))return s(p,"is not a saved data property");if(r&&u==="length"){let T=l.value;if(typeof T!="number"||!Number.isSafeInteger(T)||T<0)return s(p,"is not a saved list length");f=T;continue}if(!l.enumerable||r&&!/^(0|[1-9]\d*)$/.test(u))return s(p,"is not a JSON data property");let w=l.value,V=q(w,p,t);Object.defineProperty(a,u,{value:V,enumerable:!0,writable:!0,configurable:!0}),y++}return r&&(y!==f||a.length!==f)?s(e,"is not a complete saved list"):a}catch(r){if(r instanceof b)throw r;return s(e,"could not be snapshotted as plain JSON data")}finally{t.delete(n)}}function k(n,e){return n===null||typeof n!="object"||Array.isArray(n)||Object.getPrototypeOf(n)!==Object.prototype&&Object.getPrototypeOf(n)!==null?s(e,"is not an ordinary saved object"):n}function c(n,e,t=!0){return typeof n!="string"||t&&n.trim()===""?s(e,"is not saved text"):n}function m(n,e,t){return n[e]===void 0||n[e]===null?{}:{[e]:c(n[e],`${t}.${e}`,!1)}}function h(n,e,t){return n==null?[]:L(n)?n.map((o,r)=>t(o,`${e}[${String(r)}]`)):s(e,"is not a complete saved list")}function v(n,e){let t=k(n,e);if(typeof t.minor!="number"||!Number.isSafeInteger(t.minor)||t.minor<0)return s(`${e}.minor`,"is not a whole non-negative safe amount");let o=c(t.currency,`${e}.currency`);return/^[A-Z]{3}$/.test(o)?{minor:t.minor,currency:o}:s(`${e}.currency`,"is not a three-letter currency code")}function re(n,e){let t=k(n,e);return{_key:c(t._key,`${e}._key`),amount:v(t.amount,`${e}.amount`),...m(t,"label",e)}}function ie(n,e){let t=k(n,e);return{_key:c(t._key,`${e}._key`),name:c(t.name,`${e}.name`),amount:v(t.amount,`${e}.amount`)}}function se(n,e){let t=k(n,e),o=t.availability??"available";return o!=="available"&&o!=="sold-out"&&o!=="hidden"?s(`${e}.availability`,"is not an availability choice"):{_key:c(t._key,`${e}._key`),name:c(t.name,`${e}.name`),...m(t,"description",e),...m(t,"priceNote",e),...m(t,"allergenNote",e),prices:h(t.prices,`${e}.prices`,re),extras:h(t.extras,`${e}.extras`,ie),dietary:h(t.dietary,`${e}.dietary`,c),availability:o}}function le(n,e){let t=k(n,e);return{_key:c(t._key,`${e}._key`),title:c(t.title,`${e}.title`),...m(t,"service",e),items:h(t.items,`${e}.items`,se)}}function ae(n,e){let t=k(n,e);return{_key:c(t._key,`${e}._key`),label:c(t.label,`${e}.label`),...m(t,"note",e),sections:h(t.sections,`${e}.sections`,le)}}function ue(n){if(n===null||typeof n!="object"||Array.isArray(n))return!1;let e=n._id;return typeof e=="string"&&e.trim()!==""&&!/^(drafts|versions)\./.test(e)}function $(n,e="menu"){return ce(q(n,e),e)}function ce(n,e){let t=k(n,e);if(t._type!=="menu")return s(`${e}._type`,"is not menu");if(!ue(t))return s(`${e}._id`,"is not a published menu identity");let o=c(t._updatedAt,`${e}._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(`${e}._updatedAt`,"is not an update date");let r=h(t.variants,`${e}.variants`,ae);return r.length===0?s(`${e}.variants`,"has no menu choices"):{_type:"menu",_id:c(t._id,`${e}._id`),_rev:c(t._rev,`${e}._rev`),_updatedAt:o,title:c(t.title,`${e}.title`),locationKeys:h(t.locationKeys,`${e}.locationKeys`,c),variants:r,...m(t,"note",e),...Object.hasOwn(t,"signOff")?{signOff:t.signOff}:{}}}function B(n){if(n===null)return!0;try{return $(n),!0}catch{return!1}}var R=["columns","rows"],M=40,D="siteHero.layout.defaulted",N="siteHero.tagline.dropped",j="siteHero.taglines.defaulted",z=1,g={key:"hero",documentId:"siteHero",documentType:"siteHero",fields:[{name:"heading",label:"Heading",noun:{article:"a",word:"heading"},kind:"single-line",required:!0,minLength:1,maxLength:80,noTrailingFullStop:!0},{name:"intro",label:"Introduction",noun:{article:"an",word:"introduction"},kind:"multi-line",required:!0,minLength:1,maxLength:320}],copy:{currentTitle:"On your site now",editTitle:"Edit and publish",empty:"Your site has no hero text yet. Whatever you publish below becomes its first version."}};function de(n,e){let{article:t,word:o}=n.noun;if(e.length===0)return n.required?`Enter ${t} ${o}.`:null;let r=[...e].length;return r<n.minLength?`Make the ${o} at least ${String(n.minLength)} characters. It is ${String(r)} now.`:r>n.maxLength?`Keep the ${o} to ${String(n.maxLength)} characters or fewer. It is ${String(r)} now.`:e.includes("\u2014")?`The ${o} contains a long dash. Use a comma, a colon or a short dash instead.`:n.kind==="single-line"&&/[\r\n]/.test(e)?`The ${o} must be a single line.`:n.noTrailingFullStop===!0&&e.endsWith(".")?`${o.charAt(0).toUpperCase()}${o.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`:null}function S(n,e){let t={},o={};for(let r of n.fields){let i=Object.hasOwn(e,r.name)?e[r.name]:void 0,d=typeof i=="string"?i.trim():"",a=de(r,d);Object.defineProperty(a===null?t:o,r.name,{value:a??d,enumerable:!0})}return Object.keys(o).length>0?{ok:!1,errors:o}:{ok:!0,value:t}}function Y(n){if(!Array.isArray(n))return{ok:!1,error:"Enter a list of taglines."};let e=g.fields[0];if(!e)throw new TypeError("Missing siteHero heading definition");let t={...e,name:"text",noun:{article:"a",word:"tagline"},maxLength:M},o=[],r=[],i=new Set;for(let[d,a]of n.entries()){if(!a||typeof a!="object"||Array.isArray(a)){r.push({index:d,error:"Enter a key and text for each tagline."});continue}let f=a,y=Object.hasOwn(f,"key")?f.key:void 0;if(typeof y!="string"||!/^[a-z][a-z0-9_-]{0,31}$/.test(y)){r.push({index:d,error:"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter."});continue}if(i.has(y)){r.push({index:d,error:"Use each tagline key only once."});continue}let u=S({...g,fields:[t]},f);if(!u.ok){r.push({index:d,error:u.errors.text??"Invalid tagline."});continue}let p=u.value.text??"";if((p.match(/\p{L}/gu)?.length??0)>=2&&!/\p{Ll}/u.test(p)){r.push({index:d,error:"Use sentence case for the tagline, rather than all capitals."});continue}i.add(y),o.push({key:y,text:p})}return{ok:!0,value:o,dropped:r}}function H(n){let e=Y(n);if(!e.ok)return e;let t=e.dropped[0];return t?{ok:!1,error:t.error}:{ok:!0,value:e.value}}function F(n){return R.some(e=>n===e)}function P(n,e){let t=S(g,e),o=H(e.taglines??[]);if(!t.ok||!o.ok||e.layout!==void 0&&!F(e.layout))throw new TypeError("Invalid siteHero fallback");let r={heading:t.value.heading??"",intro:t.value.intro??"",layout:e.layout??"columns",taglines:o.value};if(n===null||typeof n!="object"||Array.isArray(n))return{data:r,fallbackFields:["$"]};let i=n,d=S(g,i),a=d.ok?[]:Object.keys(d.errors);for(let l of g.fields)if(!a.includes(l.name)){let w=d.ok?d.value[l.name]:i[l.name];typeof w=="string"&&(l.name==="heading"||l.name==="intro")&&(r[l.name]=w.trim())}let f=Object.hasOwn(i,"layout")?i.layout:void 0,y=[];F(f)?r.layout=f:(r.layout="columns",a.push("layout"),y.push(D));let u=Y(Object.hasOwn(i,"taglines")?i.taglines:void 0);if(u.ok){r.taglines=u.value;for(let{index:l}of u.dropped)a.push(`taglines[${String(l)}]`);u.dropped.length>0&&y.push(N)}else a.push("taglines"),y.push(j);let p=[...g.fields.map(l=>l.name),"layout","taglines"].every(l=>a.includes(l));return{data:r,fallbackFields:p?["$"]:a,...y.length>0?{warnings:y}:{}}}function G(){return _({name:"siteHero.v1",query:'*[_id == $id && _type == "siteHero"][0]{heading,intro,layout,taglines}',params:{id:"siteHero"},dependencies:{types:["siteHero"],ids:["siteHero"]},resolve:P})}var J="malformed-content",b=class extends Error{code=J;documentId;problems;constructor(e,t){super(`${J}: ${e}: ${t.join("; ")}`),this.name="MalformedContentError",this.documentId=e,this.problems=t}};var Q=`{..., "sections": coalesce(sections[]{..., _type == "menuBlock" => {menu->{${x}}}, _type == "linkListBlock" => {links[]{..., "page": page->{title, "slug": slug.current}}}}, sections)}`,Ce=`*[_type == "page" && defined(slug.current)]|order(slug.current asc)${Q}`,xe=`*[_type == "page" && slug.current == $slug][0]${Q}`;var ye=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,pe=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,fe=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function W(n){if(!n||!Array.isArray(n.types)||n.types.length===0)throw new TypeError("CMS dependencies require document types");let e=[...n.types];for(let o of e)if(typeof o!="string"||!ye.test(o))throw new TypeError("Invalid CMS document type");if(n.ids!==void 0&&!Array.isArray(n.ids))throw new TypeError("Invalid CMS document IDs");let t=n.ids===void 0?void 0:[...n.ids];for(let o of t??[])if(typeof o!="string"||!pe.test(o)||/^(drafts|versions)\./.test(o))throw new TypeError("Invalid CMS document ID");if(new Set(e).size+new Set(t).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(e),...t===void 0?{}:{ids:Object.freeze(t)}})}function _(n){if(!n||typeof n.name!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(n.name)||typeof n.query!="string"||n.query.trim()===""||typeof n.resolve!="function")throw new TypeError("Invalid CMS query configuration");let e=n.params;if(!e||typeof e!="object"||Object.getPrototypeOf(e)!==Object.prototype&&Object.getPrototypeOf(e)!==null)throw new TypeError("CMS params must be plain JSON scalars");let t={};for(let o of Reflect.ownKeys(e)){let r=Object.getOwnPropertyDescriptor(e,o);if(typeof o!="string"||!r||!Object.hasOwn(r,"value")||!r.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=r.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(t,o,{value:i,enumerable:!0})}return Object.freeze({name:n.name,query:n.query,params:Object.freeze(t),dependencies:W(n.dependencies),resolve:n.resolve})}function O(n,e){if(typeof n!="string"||n.length>77||!fe.test(n))throw new TypeError("Invalid CMS scope");let t=W(e),o=[...[...new Set(t.types)].sort().map(r=>`cms:${n}:type:${r}`),...[...new Set(t.ids??[])].sort().map(r=>`cms:${n}:id:${r}`)];return Object.freeze(o)}function K(n){return _({name:"menu.v1",query:`*[_type == "menu" && _id == $id && !(_id in path("drafts.**")) && !(_id in path("versions.**"))][0]{${x}}`,params:{id:n},dependencies:{types:["menu"],ids:[n]},resolve:(e,t)=>{if(!B(t)||t!==null&&t._id!==n)throw new TypeError("Invalid CMS menu fallback");if(e==null)return{data:t,fallbackFields:["$"]};let o=$(e);if(o._id!==n)throw new b("menu",["menu._id does not match the requested document"]);return{data:o,fallbackFields:[]}}})}0&&(module.exports={CMS_CONTRACT_VERSION,MENU_DECORATIONS,MENU_LAYOUTS,MENU_LAYOUT_DEFAULTS,SITE_HERO,SITE_HERO_LAYOUTS,SITE_HERO_LAYOUT_WARNING,SITE_HERO_TAGLINES_DEFAULTED_WARNING,SITE_HERO_TAGLINE_DROPPED_WARNING,SITE_HERO_TAGLINE_MAX_LENGTH,cmsTags,defineCmsQuery,menuQuery,menuTags,parseMenuDocument,parseSiteHero,siteHeroQuery,validateSiteHeroTaglines,validateTextDocument});
|
|
6
6
|
//# sourceMappingURL=index.cjs.map
|