@weatherboard/cms 0.3.0 → 0.4.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 CHANGED
@@ -19,12 +19,21 @@ The additive fields in 0.2.0 are:
19
19
  including when the local fallback selects rows.
20
20
  - `taglines`: `{ key: string, text: string }[]`. Keys are site-defined lowercase
21
21
  identifiers, 1–32 characters, starting with a letter; remaining characters
22
- may be letters, digits, short dashes or underscores. Duplicate keys refuse
23
- the whole field. Text uses the heading copy rules and is limited to
24
- `SITE_HERO_TAGLINE_MAX_LENGTH` (provisionally 36 Unicode code points).
22
+ may be letters, digits, short dashes or underscores. Text uses the heading
23
+ copy rules and is limited to `SITE_HERO_TAGLINE_MAX_LENGTH` (40 Unicode code
24
+ points). A tagline with at least two letters and no lowercase letter is
25
+ refused: `WARM HOMES ALL YEAR` fails; `HVAC for every room` and `A` pass.
25
26
  An empty array deliberately clears taglines; the site can continue using
26
- heading. A missing or invalid array uses the reviewed local array, or `[]`
27
- for a legacy fallback.
27
+ heading. A missing or non-list value uses the reviewed local array, or `[]`
28
+ for a legacy fallback. In a published list, invalid entries are dropped and
29
+ every valid sibling is kept, in order. The first valid occurrence of a key
30
+ wins; later duplicates are dropped. An invalid first occurrence does not
31
+ reserve its key. If no entry is valid, the parsed list is `[]`.
32
+
33
+ The 40-character limit is a CMS **safety cap**, not a two-line fit guarantee.
34
+ Each site enforces its own measured two-line limit in its own font (one Figtree
35
+ site measured 27 characters). The dashboard's separate live fit check validates
36
+ the rendered result with the site's font and layout.
28
37
 
29
38
  `SiteHero` accepts existing heading/intro-only fallbacks. `parseSiteHero` returns
30
39
  normalized `ParsedSiteHero` data with both new fields present. Invalid CMS fields
@@ -38,6 +47,13 @@ A defaulted CMS layout records `SITE_HERO_LAYOUT_WARNING`, whose value is
38
47
  Supply `onDiagnostic` to log diagnostics; without it the reader logs safe JSON
39
48
  through `console.warn`. Diagnostics contain paths and warning names, never copy.
40
49
 
50
+ Tagline drops record `SITE_HERO_TAGLINE_DROPPED_WARNING`
51
+ (`siteHero.tagline.dropped`) and indexed `fallbackFields`, such as `taglines[1]`.
52
+ A non-list or missing field records `SITE_HERO_TAGLINES_DEFAULTED_WARNING`
53
+ (`siteHero.taglines.defaulted`) and `taglines` in `fallbackFields`. These warnings
54
+ travel through the same safe reader diagnostics. Authoring/schema validation and
55
+ local fallback configuration remain strict: any invalid entry refuses the list.
56
+
41
57
  ```ts
42
58
  import { parseSiteHero } from '@weatherboard/cms/site-content';
43
59
 
@@ -97,7 +113,7 @@ throws `MalformedContentError` naming the path. Page fallbacks that carry
97
113
  `sections` are validated against the same kinds.
98
114
 
99
115
  The warnings travel in the page data, not in the server reader's
100
- `CmsResolution.warnings`, which still names only the hero warning.
116
+ `CmsResolution.warnings`, which names the hero layout and tagline warnings.
101
117
 
102
118
  0.3.0 is an additive minor under the pilot semver policy: a new reader kind.
103
119
 
@@ -120,3 +136,6 @@ authorized content write; existing documents remain readable with defaults.
120
136
  merge through the registered release workflow; clients then need an exact package
121
137
  bump and deploy. The CI publish and trusted-publisher proof are release evidence
122
138
  that this source change alone cannot supply.
139
+
140
+ 0.4.0 raises the tagline safety cap to 40, refuses all-caps taglines and preserves
141
+ valid siblings in published lists. It is one minor above the npm 0.3.0 release.
@@ -7,7 +7,7 @@ export type CmsDependencies = {
7
7
  export type CmsResolution<T> = {
8
8
  readonly data: T;
9
9
  readonly fallbackFields: readonly string[];
10
- readonly warnings?: readonly "siteHero.layout.defaulted"[];
10
+ readonly warnings?: readonly ("siteHero.layout.defaulted" | "siteHero.tagline.dropped" | "siteHero.taglines.defaulted")[];
11
11
  };
12
12
  export type CmsQuery<T> = {
13
13
  readonly name: string;
@@ -7,7 +7,7 @@ export type CmsDependencies = {
7
7
  export type CmsResolution<T> = {
8
8
  readonly data: T;
9
9
  readonly fallbackFields: readonly string[];
10
- readonly warnings?: readonly "siteHero.layout.defaulted"[];
10
+ readonly warnings?: readonly ("siteHero.layout.defaulted" | "siteHero.tagline.dropped" | "siteHero.taglines.defaulted")[];
11
11
  };
12
12
  export type CmsQuery<T> = {
13
13
  readonly name: string;
@@ -7,7 +7,7 @@ export type CmsDependencies = {
7
7
  export type CmsResolution<T> = {
8
8
  readonly data: T;
9
9
  readonly fallbackFields: readonly string[];
10
- readonly warnings?: readonly "siteHero.layout.defaulted"[];
10
+ readonly warnings?: readonly ("siteHero.layout.defaulted" | "siteHero.tagline.dropped" | "siteHero.taglines.defaulted")[];
11
11
  };
12
12
  export type CmsQuery<T> = {
13
13
  readonly name: string;
@@ -1,7 +1,9 @@
1
1
  import { type CmsQuery, type CmsResolution } from "./query.cjs";
2
2
  export declare const SITE_HERO_LAYOUTS: readonly ["columns", "rows"];
3
- export declare const SITE_HERO_TAGLINE_MAX_LENGTH = 36;
3
+ export declare const SITE_HERO_TAGLINE_MAX_LENGTH = 40;
4
4
  export declare const SITE_HERO_LAYOUT_WARNING: "siteHero.layout.defaulted";
5
+ export declare const SITE_HERO_TAGLINE_DROPPED_WARNING: "siteHero.tagline.dropped";
6
+ export declare const SITE_HERO_TAGLINES_DEFAULTED_WARNING: "siteHero.taglines.defaulted";
5
7
  export type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];
6
8
  export type SiteHeroTagline = {
7
9
  readonly key: string;
@@ -52,7 +54,7 @@ export type TextValidation = {
52
54
  export declare const CMS_CONTRACT_VERSION = 1;
53
55
  export declare const SITE_HERO: TextDocumentDefinition;
54
56
  export declare function validateTextDocument(definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>): TextValidation;
55
- /** Shared with the schema adapter; no provider metadata is returned. */
57
+ /** Shared with the schema adapter; invalid authoring input is refused as a whole. */
56
58
  export declare function validateSiteHeroTaglines(raw: unknown): {
57
59
  readonly ok: true;
58
60
  readonly value: readonly SiteHeroTagline[];
@@ -60,6 +62,6 @@ export declare function validateSiteHeroTaglines(raw: unknown): {
60
62
  readonly ok: false;
61
63
  readonly error: string;
62
64
  };
63
- /** Strict per-field resolution: an invalid list never partially changes keyed copy. */
65
+ /** Invalid published entries are dropped without discarding valid keyed siblings. */
64
66
  export declare function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero>;
65
67
  export declare function siteHeroQuery(): CmsQuery<SiteHero>;
@@ -1,7 +1,9 @@
1
1
  import { type CmsQuery, type CmsResolution } from "./query.mjs";
2
2
  export declare const SITE_HERO_LAYOUTS: readonly ["columns", "rows"];
3
- export declare const SITE_HERO_TAGLINE_MAX_LENGTH = 36;
3
+ export declare const SITE_HERO_TAGLINE_MAX_LENGTH = 40;
4
4
  export declare const SITE_HERO_LAYOUT_WARNING: "siteHero.layout.defaulted";
5
+ export declare const SITE_HERO_TAGLINE_DROPPED_WARNING: "siteHero.tagline.dropped";
6
+ export declare const SITE_HERO_TAGLINES_DEFAULTED_WARNING: "siteHero.taglines.defaulted";
5
7
  export type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];
6
8
  export type SiteHeroTagline = {
7
9
  readonly key: string;
@@ -52,7 +54,7 @@ export type TextValidation = {
52
54
  export declare const CMS_CONTRACT_VERSION = 1;
53
55
  export declare const SITE_HERO: TextDocumentDefinition;
54
56
  export declare function validateTextDocument(definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>): TextValidation;
55
- /** Shared with the schema adapter; no provider metadata is returned. */
57
+ /** Shared with the schema adapter; invalid authoring input is refused as a whole. */
56
58
  export declare function validateSiteHeroTaglines(raw: unknown): {
57
59
  readonly ok: true;
58
60
  readonly value: readonly SiteHeroTagline[];
@@ -60,6 +62,6 @@ export declare function validateSiteHeroTaglines(raw: unknown): {
60
62
  readonly ok: false;
61
63
  readonly error: string;
62
64
  };
63
- /** Strict per-field resolution: an invalid list never partially changes keyed copy. */
65
+ /** Invalid published entries are dropped without discarding valid keyed siblings. */
64
66
  export declare function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero>;
65
67
  export declare function siteHeroQuery(): CmsQuery<SiteHero>;
@@ -1,7 +1,9 @@
1
1
  import { type CmsQuery, type CmsResolution } from "./query.js";
2
2
  export declare const SITE_HERO_LAYOUTS: readonly ["columns", "rows"];
3
- export declare const SITE_HERO_TAGLINE_MAX_LENGTH = 36;
3
+ export declare const SITE_HERO_TAGLINE_MAX_LENGTH = 40;
4
4
  export declare const SITE_HERO_LAYOUT_WARNING: "siteHero.layout.defaulted";
5
+ export declare const SITE_HERO_TAGLINE_DROPPED_WARNING: "siteHero.tagline.dropped";
6
+ export declare const SITE_HERO_TAGLINES_DEFAULTED_WARNING: "siteHero.taglines.defaulted";
5
7
  export type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];
6
8
  export type SiteHeroTagline = {
7
9
  readonly key: string;
@@ -52,7 +54,7 @@ export type TextValidation = {
52
54
  export declare const CMS_CONTRACT_VERSION = 1;
53
55
  export declare const SITE_HERO: TextDocumentDefinition;
54
56
  export declare function validateTextDocument(definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>): TextValidation;
55
- /** Shared with the schema adapter; no provider metadata is returned. */
57
+ /** Shared with the schema adapter; invalid authoring input is refused as a whole. */
56
58
  export declare function validateSiteHeroTaglines(raw: unknown): {
57
59
  readonly ok: true;
58
60
  readonly value: readonly SiteHeroTagline[];
@@ -60,6 +62,6 @@ export declare function validateSiteHeroTaglines(raw: unknown): {
60
62
  readonly ok: false;
61
63
  readonly error: string;
62
64
  };
63
- /** Strict per-field resolution: an invalid list never partially changes keyed copy. */
65
+ /** Invalid published entries are dropped without discarding valid keyed siblings. */
64
66
  export declare function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero>;
65
67
  export declare function siteHeroQuery(): CmsQuery<SiteHero>;
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var f=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var _=(e,t)=>{for(var o in t)f(e,o,{get:t[o],enumerable:!0})},A=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of R(t))!v.call(e,n)&&n!==o&&f(e,n,{get:()=>t[n],enumerable:!(r=C(t,n))||r.enumerable});return e};var I=e=>A(f({},"__esModule",{value:!0}),e);var z={};_(z,{CMS_CONTRACT_VERSION:()=>k,SITE_HERO:()=>l,SITE_HERO_LAYOUTS:()=>m,SITE_HERO_LAYOUT_WARNING:()=>h,SITE_HERO_TAGLINE_MAX_LENGTH:()=>T,cmsTags:()=>H,defineCmsQuery:()=>c,parseSiteHero:()=>S,siteHeroQuery:()=>E,validateSiteHeroTaglines:()=>p,validateTextDocument:()=>y});module.exports=I(z);var L=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,j=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,D=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function x(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"||!L.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 o=e.ids===void 0?void 0:[...e.ids];for(let r of o??[])if(typeof r!="string"||!j.test(r)||/^(drafts|versions)\./.test(r))throw new TypeError("Invalid CMS document ID");if(new Set(t).size+new Set(o).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(t),...o===void 0?{}:{ids:Object.freeze(o)}})}function c(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 o={};for(let r of Reflect.ownKeys(t)){let n=Object.getOwnPropertyDescriptor(t,r);if(typeof r!="string"||!n||!Object.hasOwn(n,"value")||!n.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=n.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(o,r,{value:i,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(o),dependencies:x(e.dependencies),resolve:e.resolve})}function H(e,t){if(typeof e!="string"||e.length>77||!D.test(e))throw new TypeError("Invalid CMS scope");let o=x(t),r=[...[...new Set(o.types)].sort().map(n=>`cms:${e}:type:${n}`),...[...new Set(o.ids??[])].sort().map(n=>`cms:${e}:id:${n}`)];return Object.freeze(r)}var m=["columns","rows"],T=36,h="siteHero.layout.defaulted",k=1,l={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 $(e,t){let{article:o,word:r}=e.noun;if(t.length===0)return e.required?`Enter ${o} ${r}.`:null;let n=[...t].length;return n<e.minLength?`Make the ${r} at least ${String(e.minLength)} characters. It is ${String(n)} now.`:n>e.maxLength?`Keep the ${r} to ${String(e.maxLength)} characters or fewer. It is ${String(n)} now.`:t.includes("\u2014")?`The ${r} contains a long dash. Use a comma, a colon or a short dash instead.`:e.kind==="single-line"&&/[\r\n]/.test(t)?`The ${r} must be a single line.`:e.noTrailingFullStop===!0&&t.endsWith(".")?`${r.charAt(0).toUpperCase()}${r.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`:null}function y(e,t){let o={},r={};for(let n of e.fields){let i=Object.hasOwn(t,n.name)?t[n.name]:void 0,a=typeof i=="string"?i.trim():"",s=$(n,a);Object.defineProperty(s===null?o:r,n.name,{value:s??a,enumerable:!0})}return Object.keys(r).length>0?{ok:!1,errors:r}:{ok:!0,value:o}}function p(e){if(!Array.isArray(e))return{ok:!1,error:"Enter a list of taglines."};let t=l.fields[0];if(!t)throw new TypeError("Missing siteHero heading definition");let o={...t,name:"text",noun:{article:"a",word:"tagline"},maxLength:T},r=[],n=new Set;for(let i of e){if(!i||typeof i!="object"||Array.isArray(i))return{ok:!1,error:"Enter a key and text for each tagline."};let a=i,s=Object.hasOwn(a,"key")?a.key:void 0;if(typeof s!="string"||!/^[a-z][a-z0-9_-]{0,31}$/.test(s))return{ok:!1,error:"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter."};if(n.has(s))return{ok:!1,error:"Use each tagline key only once."};let d=y({...l,fields:[o]},a);if(!d.ok)return{ok:!1,error:d.errors.text??"Invalid tagline."};n.add(s),r.push({key:s,text:d.value.text??""})}return{ok:!0,value:r}}function O(e){return m.some(t=>e===t)}function S(e,t){let o=y(l,t),r=p(t.taglines??[]);if(!o.ok||!r.ok||t.layout!==void 0&&!O(t.layout))throw new TypeError("Invalid siteHero fallback");let n={heading:o.value.heading??"",intro:o.value.intro??"",layout:t.layout??"columns",taglines:r.value};if(e===null||typeof e!="object"||Array.isArray(e))return{data:n,fallbackFields:["$"]};let i=e,a=y(l,i),s=a.ok?[]:Object.keys(a.errors);for(let u of l.fields)if(!s.includes(u.name)){let b=a.ok?a.value[u.name]:i[u.name];typeof b=="string"&&(u.name==="heading"||u.name==="intro")&&(n[u.name]=b.trim())}let d=Object.hasOwn(i,"layout")?i.layout:void 0,g=[];O(d)?n.layout=d:(n.layout="columns",s.push("layout"),g.push(h));let w=p(Object.hasOwn(i,"taglines")?i.taglines:void 0);return w.ok?n.taglines=w.value:s.push("taglines"),{data:n,fallbackFields:s.length===l.fields.length+2?["$"]:s,...g.length>0?{warnings:g}:{}}}function E(){return c({name:"siteHero.v1",query:'*[_id == $id && _type == "siteHero"][0]{heading,intro,layout,taglines}',params:{id:"siteHero"},dependencies:{types:["siteHero"],ids:["siteHero"]},resolve:S})}0&&(module.exports={CMS_CONTRACT_VERSION,SITE_HERO,SITE_HERO_LAYOUTS,SITE_HERO_LAYOUT_WARNING,SITE_HERO_TAGLINE_MAX_LENGTH,cmsTags,defineCmsQuery,parseSiteHero,siteHeroQuery,validateSiteHeroTaglines,validateTextDocument});
1
+ "use strict";var m=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var D=(e,t)=>{for(var o in t)m(e,o,{get:t[o],enumerable:!0})},N=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of A(t))!L.call(e,n)&&n!==o&&m(e,n,{get:()=>t[n],enumerable:!(r=v(t,n))||r.enumerable});return e};var $=e=>N(m({},"__esModule",{value:!0}),e);var F={};D(F,{CMS_CONTRACT_VERSION:()=>R,SITE_HERO:()=>y,SITE_HERO_LAYOUTS:()=>T,SITE_HERO_LAYOUT_WARNING:()=>S,SITE_HERO_TAGLINES_DEFAULTED_WARNING:()=>E,SITE_HERO_TAGLINE_DROPPED_WARNING:()=>H,SITE_HERO_TAGLINE_MAX_LENGTH:()=>h,cmsTags:()=>k,defineCmsQuery:()=>f,parseSiteHero:()=>x,siteHeroQuery:()=>I,validateSiteHeroTaglines:()=>w,validateTextDocument:()=>g});module.exports=$(F);var j=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,z=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,P=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function O(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"||!j.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 o=e.ids===void 0?void 0:[...e.ids];for(let r of o??[])if(typeof r!="string"||!z.test(r)||/^(drafts|versions)\./.test(r))throw new TypeError("Invalid CMS document ID");if(new Set(t).size+new Set(o).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(t),...o===void 0?{}:{ids:Object.freeze(o)}})}function f(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 o={};for(let r of Reflect.ownKeys(t)){let n=Object.getOwnPropertyDescriptor(t,r);if(typeof r!="string"||!n||!Object.hasOwn(n,"value")||!n.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=n.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(o,r,{value:i,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(o),dependencies:O(e.dependencies),resolve:e.resolve})}function k(e,t){if(typeof e!="string"||e.length>77||!P.test(e))throw new TypeError("Invalid CMS scope");let o=O(t),r=[...[...new Set(o.types)].sort().map(n=>`cms:${e}:type:${n}`),...[...new Set(o.ids??[])].sort().map(n=>`cms:${e}:id:${n}`)];return Object.freeze(r)}var T=["columns","rows"],h=40,S="siteHero.layout.defaulted",H="siteHero.tagline.dropped",E="siteHero.taglines.defaulted",R=1,y={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 M(e,t){let{article:o,word:r}=e.noun;if(t.length===0)return e.required?`Enter ${o} ${r}.`:null;let n=[...t].length;return n<e.minLength?`Make the ${r} at least ${String(e.minLength)} characters. It is ${String(n)} now.`:n>e.maxLength?`Keep the ${r} to ${String(e.maxLength)} characters or fewer. It is ${String(n)} now.`:t.includes("\u2014")?`The ${r} contains a long dash. Use a comma, a colon or a short dash instead.`:e.kind==="single-line"&&/[\r\n]/.test(t)?`The ${r} must be a single line.`:e.noTrailingFullStop===!0&&t.endsWith(".")?`${r.charAt(0).toUpperCase()}${r.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`:null}function g(e,t){let o={},r={};for(let n of e.fields){let i=Object.hasOwn(t,n.name)?t[n.name]:void 0,a=typeof i=="string"?i.trim():"",s=M(n,a);Object.defineProperty(s===null?o:r,n.name,{value:s??a,enumerable:!0})}return Object.keys(r).length>0?{ok:!1,errors:r}:{ok:!0,value:o}}function C(e){if(!Array.isArray(e))return{ok:!1,error:"Enter a list of taglines."};let t=y.fields[0];if(!t)throw new TypeError("Missing siteHero heading definition");let o={...t,name:"text",noun:{article:"a",word:"tagline"},maxLength:h},r=[],n=[],i=new Set;for(let[a,s]of e.entries()){if(!s||typeof s!="object"||Array.isArray(s)){n.push({index:a,error:"Enter a key and text for each tagline."});continue}let c=s,d=Object.hasOwn(c,"key")?c.key:void 0;if(typeof d!="string"||!/^[a-z][a-z0-9_-]{0,31}$/.test(d)){n.push({index:a,error:"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter."});continue}if(i.has(d)){n.push({index:a,error:"Use each tagline key only once."});continue}let u=g({...y,fields:[o]},c);if(!u.ok){n.push({index:a,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)){n.push({index:a,error:"Use sentence case for the tagline, rather than all capitals."});continue}i.add(d),r.push({key:d,text:p})}return{ok:!0,value:r,dropped:n}}function w(e){let t=C(e);if(!t.ok)return t;let o=t.dropped[0];return o?{ok:!1,error:o.error}:{ok:!0,value:t.value}}function _(e){return T.some(t=>e===t)}function x(e,t){let o=g(y,t),r=w(t.taglines??[]);if(!o.ok||!r.ok||t.layout!==void 0&&!_(t.layout))throw new TypeError("Invalid siteHero fallback");let n={heading:o.value.heading??"",intro:o.value.intro??"",layout:t.layout??"columns",taglines:r.value};if(e===null||typeof e!="object"||Array.isArray(e))return{data:n,fallbackFields:["$"]};let i=e,a=g(y,i),s=a.ok?[]:Object.keys(a.errors);for(let l of y.fields)if(!s.includes(l.name)){let b=a.ok?a.value[l.name]:i[l.name];typeof b=="string"&&(l.name==="heading"||l.name==="intro")&&(n[l.name]=b.trim())}let c=Object.hasOwn(i,"layout")?i.layout:void 0,d=[];_(c)?n.layout=c:(n.layout="columns",s.push("layout"),d.push(S));let u=C(Object.hasOwn(i,"taglines")?i.taglines:void 0);if(u.ok){n.taglines=u.value;for(let{index:l}of u.dropped)s.push(`taglines[${String(l)}]`);u.dropped.length>0&&d.push(H)}else s.push("taglines"),d.push(E);let p=[...y.fields.map(l=>l.name),"layout","taglines"].every(l=>s.includes(l));return{data:n,fallbackFields:p?["$"]:s,...d.length>0?{warnings:d}:{}}}function I(){return f({name:"siteHero.v1",query:'*[_id == $id && _type == "siteHero"][0]{heading,intro,layout,taglines}',params:{id:"siteHero"},dependencies:{types:["siteHero"],ids:["siteHero"]},resolve:x})}0&&(module.exports={CMS_CONTRACT_VERSION,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,parseSiteHero,siteHeroQuery,validateSiteHeroTaglines,validateTextDocument});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/contracts/query.ts", "../src/contracts/text.ts"],
4
- "sourcesContent": ["export { defineCmsQuery, cmsTags } from \"./contracts/query.js\";\nexport type { CmsParams, CmsDependencies, CmsResolution, CmsQuery } from \"./contracts/query.js\";\nexport { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, parseSiteHero, validateSiteHeroTaglines } from \"./contracts/text.js\";\nexport type { SiteHero, ParsedSiteHero, SiteHeroLayout, SiteHeroTagline, TextFieldDefinition, TextDocumentDefinition, TextValidation } from \"./contracts/text.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\"[];\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 { defineCmsQuery, type CmsQuery, type CmsResolution } from \"./query.js\";\n\nexport const SITE_HERO_LAYOUTS = [\"columns\", \"rows\"] as const;\nexport const SITE_HERO_TAGLINE_MAX_LENGTH = 36;\nexport const SITE_HERO_LAYOUT_WARNING = \"siteHero.layout.defaulted\" as const;\nexport type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];\nexport type SiteHeroTagline = { readonly key: string; readonly text: string };\n/** Optional additions preserve existing heading/intro-only consumer fallbacks. */\nexport type SiteHero = {\n readonly heading: string;\n readonly intro: string;\n readonly layout?: SiteHeroLayout;\n readonly taglines?: readonly SiteHeroTagline[];\n};\nexport type ParsedSiteHero = SiteHero & {\n readonly layout: SiteHeroLayout;\n readonly taglines: readonly SiteHeroTagline[];\n};\nexport type TextFieldDefinition = {\n readonly name: string;\n readonly label: string;\n readonly noun: { readonly article: \"a\" | \"an\"; readonly word: string };\n readonly kind: \"single-line\" | \"multi-line\";\n readonly required: boolean;\n readonly minLength: number;\n readonly maxLength: number;\n readonly noTrailingFullStop?: boolean;\n};\nexport type TextDocumentDefinition = {\n readonly key: string;\n readonly documentId: string;\n readonly documentType: string;\n readonly fields: readonly TextFieldDefinition[];\n readonly copy: {\n readonly currentTitle: string;\n readonly editTitle: string;\n readonly empty: string;\n };\n};\nexport type TextValidation =\n | { readonly ok: true; readonly value: Readonly<Record<string, string>> }\n | { readonly ok: false; readonly errors: Readonly<Record<string, string>> };\n\nexport const CMS_CONTRACT_VERSION = 1;\n\nexport const SITE_HERO: TextDocumentDefinition = {\n key: \"hero\",\n documentId: \"siteHero\",\n documentType: \"siteHero\",\n fields: [\n {\n name: \"heading\",\n label: \"Heading\",\n noun: { article: \"a\", word: \"heading\" },\n kind: \"single-line\",\n required: true,\n minLength: 1,\n maxLength: 80,\n noTrailingFullStop: true,\n },\n {\n name: \"intro\",\n label: \"Introduction\",\n noun: { article: \"an\", word: \"introduction\" },\n kind: \"multi-line\",\n required: true,\n minLength: 1,\n maxLength: 320,\n },\n ],\n copy: {\n currentTitle: \"On your site now\",\n editTitle: \"Edit and publish\",\n empty: \"Your site has no hero text yet. Whatever you publish below becomes its first version.\",\n },\n};\n\nfunction fieldError(field: TextFieldDefinition, text: string): string | null {\n const { article, word } = field.noun;\n if (text.length === 0) return field.required ? `Enter ${article} ${word}.` : null;\n const count = [...text].length;\n if (count < field.minLength) return `Make the ${word} at least ${String(field.minLength)} characters. It is ${String(count)} now.`;\n if (count > field.maxLength) return `Keep the ${word} to ${String(field.maxLength)} characters or fewer. It is ${String(count)} now.`;\n if (text.includes(\"\\u2014\")) return `The ${word} contains a long dash. Use a comma, a colon or a short dash instead.`;\n if (field.kind === \"single-line\" && /[\\r\\n]/.test(text)) return `The ${word} must be a single line.`;\n if (field.noTrailingFullStop === true && text.endsWith(\".\")) {\n return `${word.charAt(0).toUpperCase()}${word.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`;\n }\n return null;\n}\n\nexport function validateTextDocument(\n definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>,\n): TextValidation {\n const value: Record<string, string> = {};\n const errors: Record<string, string> = {};\n for (const field of definition.fields) {\n const submitted = Object.hasOwn(raw, field.name) ? raw[field.name] : undefined;\n const text = typeof submitted === \"string\" ? submitted.trim() : \"\";\n const error = fieldError(field, text);\n Object.defineProperty(error === null ? value : errors, field.name, { value: error ?? text, enumerable: true });\n }\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value };\n}\n\n/** Shared with the schema adapter; no provider metadata is returned. */\nexport function validateSiteHeroTaglines(raw: unknown):\n | { readonly ok: true; readonly value: readonly SiteHeroTagline[] }\n | { readonly ok: false; readonly error: string } {\n if (!Array.isArray(raw)) return { ok: false, error: \"Enter a list of taglines.\" };\n const heading = SITE_HERO.fields[0];\n if (!heading) throw new TypeError(\"Missing siteHero heading definition\");\n const field = { ...heading, name: \"text\", noun: { article: \"a\", word: \"tagline\" } as const,\n maxLength: SITE_HERO_TAGLINE_MAX_LENGTH };\n const value: SiteHeroTagline[] = [];\n const keys = new Set<string>();\n for (const item of raw as unknown[]) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { ok: false, error: \"Enter a key and text for each tagline.\" };\n const record = item as Record<string, unknown>;\n const key = Object.hasOwn(record, \"key\") ? record.key : undefined;\n if (typeof key !== \"string\" || !/^[a-z][a-z0-9_-]{0,31}$/.test(key)) {\n return { ok: false, error: \"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter.\" };\n }\n if (keys.has(key)) return { ok: false, error: \"Use each tagline key only once.\" };\n const text = validateTextDocument({ ...SITE_HERO, fields: [field] }, record);\n if (!text.ok) return { ok: false, error: text.errors.text ?? \"Invalid tagline.\" };\n keys.add(key);\n value.push({ key, text: text.value.text ?? \"\" });\n }\n return { ok: true, value };\n}\n\nfunction isLayout(value: unknown): value is SiteHeroLayout {\n return SITE_HERO_LAYOUTS.some((layout) => value === layout);\n}\n\n/** Strict per-field resolution: an invalid list never partially changes keyed copy. */\nexport function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero> {\n const local = validateTextDocument(SITE_HERO, fallback);\n const localTaglines = validateSiteHeroTaglines(fallback.taglines ?? []);\n if (!local.ok || !localTaglines.ok || (fallback.layout !== undefined && !isLayout(fallback.layout))) {\n throw new TypeError(\"Invalid siteHero fallback\");\n }\n const data: { heading: string; intro: string; layout: SiteHeroLayout; taglines: readonly SiteHeroTagline[] } = {\n heading: local.value.heading ?? \"\", intro: local.value.intro ?? \"\",\n layout: fallback.layout ?? \"columns\", taglines: localTaglines.value,\n };\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return { data, fallbackFields: [\"$\"] };\n const record = raw as Readonly<Record<string, unknown>>;\n const text = validateTextDocument(SITE_HERO, record);\n const fallbackFields: string[] = text.ok ? [] : Object.keys(text.errors);\n for (const field of SITE_HERO.fields) {\n if (!fallbackFields.includes(field.name)) {\n const value = text.ok ? text.value[field.name] : record[field.name];\n if (typeof value === \"string\" && (field.name === \"heading\" || field.name === \"intro\")) data[field.name] = value.trim();\n }\n }\n const layout = Object.hasOwn(record, \"layout\") ? record.layout : undefined;\n const warnings: (typeof SITE_HERO_LAYOUT_WARNING)[] = [];\n if (isLayout(layout)) data.layout = layout;\n else {\n data.layout = \"columns\";\n fallbackFields.push(\"layout\");\n warnings.push(SITE_HERO_LAYOUT_WARNING);\n }\n const taglines = validateSiteHeroTaglines(Object.hasOwn(record, \"taglines\") ? record.taglines : undefined);\n if (taglines.ok) data.taglines = taglines.value;\n else fallbackFields.push(\"taglines\");\n return { data, fallbackFields: fallbackFields.length === SITE_HERO.fields.length + 2 ? [\"$\"] : fallbackFields,\n ...(warnings.length > 0 ? { warnings } : {}) };\n}\n\nexport function siteHeroQuery(): CmsQuery<SiteHero> {\n return defineCmsQuery<SiteHero>({\n name: \"siteHero.v1\", query: '*[_id == $id && _type == \"siteHero\"][0]{heading,intro,layout,taglines}',\n params: { id: \"siteHero\" }, dependencies: { types: [\"siteHero\"], ids: [\"siteHero\"] },\n resolve: parseSiteHero,\n });\n}\n"],
5
- "mappings": "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",
6
- "names": ["index_exports", "__export", "CMS_CONTRACT_VERSION", "SITE_HERO", "SITE_HERO_LAYOUTS", "SITE_HERO_LAYOUT_WARNING", "SITE_HERO_TAGLINE_MAX_LENGTH", "cmsTags", "defineCmsQuery", "parseSiteHero", "siteHeroQuery", "validateSiteHeroTaglines", "validateTextDocument", "__toCommonJS", "TYPE", "ID", "SCOPE", "dependenciesCopy", "dependencies", "types", "type", "ids", "id", "defineCmsQuery", "query", "params", "copied", "key", "descriptor", "value", "cmsTags", "scope", "tags", "SITE_HERO_LAYOUTS", "SITE_HERO_TAGLINE_MAX_LENGTH", "SITE_HERO_LAYOUT_WARNING", "CMS_CONTRACT_VERSION", "SITE_HERO", "fieldError", "field", "text", "article", "word", "count", "validateTextDocument", "definition", "raw", "value", "errors", "submitted", "error", "validateSiteHeroTaglines", "heading", "keys", "item", "record", "key", "isLayout", "layout", "parseSiteHero", "fallback", "local", "localTaglines", "data", "fallbackFields", "warnings", "taglines", "siteHeroQuery", "defineCmsQuery"]
4
+ "sourcesContent": ["export { defineCmsQuery, cmsTags } from \"./contracts/query.js\";\nexport type { CmsParams, CmsDependencies, CmsResolution, CmsQuery } from \"./contracts/query.js\";\nexport { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, SITE_HERO_TAGLINE_DROPPED_WARNING, SITE_HERO_TAGLINES_DEFAULTED_WARNING, parseSiteHero, validateSiteHeroTaglines } from \"./contracts/text.js\";\nexport type { SiteHero, ParsedSiteHero, SiteHeroLayout, SiteHeroTagline, TextFieldDefinition, TextDocumentDefinition, TextValidation } from \"./contracts/text.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 { defineCmsQuery, type CmsQuery, type CmsResolution } from \"./query.js\";\n\nexport const SITE_HERO_LAYOUTS = [\"columns\", \"rows\"] as const;\nexport const SITE_HERO_TAGLINE_MAX_LENGTH = 40;\nexport const SITE_HERO_LAYOUT_WARNING = \"siteHero.layout.defaulted\" as const;\nexport const SITE_HERO_TAGLINE_DROPPED_WARNING = \"siteHero.tagline.dropped\" as const;\nexport const SITE_HERO_TAGLINES_DEFAULTED_WARNING = \"siteHero.taglines.defaulted\" as const;\nexport type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];\nexport type SiteHeroTagline = { readonly key: string; readonly text: string };\n/** Optional additions preserve existing heading/intro-only consumer fallbacks. */\nexport type SiteHero = {\n readonly heading: string;\n readonly intro: string;\n readonly layout?: SiteHeroLayout;\n readonly taglines?: readonly SiteHeroTagline[];\n};\nexport type ParsedSiteHero = SiteHero & {\n readonly layout: SiteHeroLayout;\n readonly taglines: readonly SiteHeroTagline[];\n};\nexport type TextFieldDefinition = {\n readonly name: string;\n readonly label: string;\n readonly noun: { readonly article: \"a\" | \"an\"; readonly word: string };\n readonly kind: \"single-line\" | \"multi-line\";\n readonly required: boolean;\n readonly minLength: number;\n readonly maxLength: number;\n readonly noTrailingFullStop?: boolean;\n};\nexport type TextDocumentDefinition = {\n readonly key: string;\n readonly documentId: string;\n readonly documentType: string;\n readonly fields: readonly TextFieldDefinition[];\n readonly copy: {\n readonly currentTitle: string;\n readonly editTitle: string;\n readonly empty: string;\n };\n};\nexport type TextValidation =\n | { readonly ok: true; readonly value: Readonly<Record<string, string>> }\n | { readonly ok: false; readonly errors: Readonly<Record<string, string>> };\n\nexport const CMS_CONTRACT_VERSION = 1;\n\nexport const SITE_HERO: TextDocumentDefinition = {\n key: \"hero\",\n documentId: \"siteHero\",\n documentType: \"siteHero\",\n fields: [\n {\n name: \"heading\",\n label: \"Heading\",\n noun: { article: \"a\", word: \"heading\" },\n kind: \"single-line\",\n required: true,\n minLength: 1,\n maxLength: 80,\n noTrailingFullStop: true,\n },\n {\n name: \"intro\",\n label: \"Introduction\",\n noun: { article: \"an\", word: \"introduction\" },\n kind: \"multi-line\",\n required: true,\n minLength: 1,\n maxLength: 320,\n },\n ],\n copy: {\n currentTitle: \"On your site now\",\n editTitle: \"Edit and publish\",\n empty: \"Your site has no hero text yet. Whatever you publish below becomes its first version.\",\n },\n};\n\nfunction fieldError(field: TextFieldDefinition, text: string): string | null {\n const { article, word } = field.noun;\n if (text.length === 0) return field.required ? `Enter ${article} ${word}.` : null;\n const count = [...text].length;\n if (count < field.minLength) return `Make the ${word} at least ${String(field.minLength)} characters. It is ${String(count)} now.`;\n if (count > field.maxLength) return `Keep the ${word} to ${String(field.maxLength)} characters or fewer. It is ${String(count)} now.`;\n if (text.includes(\"\\u2014\")) return `The ${word} contains a long dash. Use a comma, a colon or a short dash instead.`;\n if (field.kind === \"single-line\" && /[\\r\\n]/.test(text)) return `The ${word} must be a single line.`;\n if (field.noTrailingFullStop === true && text.endsWith(\".\")) {\n return `${word.charAt(0).toUpperCase()}${word.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`;\n }\n return null;\n}\n\nexport function validateTextDocument(\n definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>,\n): TextValidation {\n const value: Record<string, string> = {};\n const errors: Record<string, string> = {};\n for (const field of definition.fields) {\n const submitted = Object.hasOwn(raw, field.name) ? raw[field.name] : undefined;\n const text = typeof submitted === \"string\" ? submitted.trim() : \"\";\n const error = fieldError(field, text);\n Object.defineProperty(error === null ? value : errors, field.name, { value: error ?? text, enumerable: true });\n }\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value };\n}\n\n/** One rule set for strict authoring validation and resilient published reads. */\nfunction scanSiteHeroTaglines(raw: unknown):\n | { readonly ok: true; readonly value: readonly SiteHeroTagline[]; readonly dropped: readonly { index: number; error: string }[] }\n | { readonly ok: false; readonly error: string } {\n if (!Array.isArray(raw)) return { ok: false, error: \"Enter a list of taglines.\" };\n const heading = SITE_HERO.fields[0];\n if (!heading) throw new TypeError(\"Missing siteHero heading definition\");\n const field = { ...heading, name: \"text\", noun: { article: \"a\", word: \"tagline\" } as const,\n maxLength: SITE_HERO_TAGLINE_MAX_LENGTH };\n const value: SiteHeroTagline[] = [];\n const dropped: { index: number; error: string }[] = [];\n const keys = new Set<string>();\n for (const [index, item] of (raw as unknown[]).entries()) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n dropped.push({ index, error: \"Enter a key and text for each tagline.\" });\n continue;\n }\n const record = item as Record<string, unknown>;\n const key = Object.hasOwn(record, \"key\") ? record.key : undefined;\n if (typeof key !== \"string\" || !/^[a-z][a-z0-9_-]{0,31}$/.test(key)) {\n dropped.push({ index, error: \"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter.\" });\n continue;\n }\n if (keys.has(key)) {\n dropped.push({ index, error: \"Use each tagline key only once.\" });\n continue;\n }\n const text = validateTextDocument({ ...SITE_HERO, fields: [field] }, record);\n if (!text.ok) {\n dropped.push({ index, error: text.errors.text ?? \"Invalid tagline.\" });\n continue;\n }\n const copy = text.value.text ?? \"\";\n if ((copy.match(/\\p{L}/gu)?.length ?? 0) >= 2 && !/\\p{Ll}/u.test(copy)) {\n dropped.push({ index, error: \"Use sentence case for the tagline, rather than all capitals.\" });\n continue;\n }\n keys.add(key);\n value.push({ key, text: copy });\n }\n return { ok: true, value, dropped };\n}\n\n/** Shared with the schema adapter; invalid authoring input is refused as a whole. */\nexport function validateSiteHeroTaglines(raw: unknown):\n | { readonly ok: true; readonly value: readonly SiteHeroTagline[] }\n | { readonly ok: false; readonly error: string } {\n const result = scanSiteHeroTaglines(raw);\n if (!result.ok) return result;\n const first = result.dropped[0];\n return first ? { ok: false, error: first.error } : { ok: true, value: result.value };\n}\n\nfunction isLayout(value: unknown): value is SiteHeroLayout {\n return SITE_HERO_LAYOUTS.some((layout) => value === layout);\n}\n\n/** Invalid published entries are dropped without discarding valid keyed siblings. */\nexport function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero> {\n const local = validateTextDocument(SITE_HERO, fallback);\n const localTaglines = validateSiteHeroTaglines(fallback.taglines ?? []);\n if (!local.ok || !localTaglines.ok || (fallback.layout !== undefined && !isLayout(fallback.layout))) {\n throw new TypeError(\"Invalid siteHero fallback\");\n }\n const data: { heading: string; intro: string; layout: SiteHeroLayout; taglines: readonly SiteHeroTagline[] } = {\n heading: local.value.heading ?? \"\", intro: local.value.intro ?? \"\",\n layout: fallback.layout ?? \"columns\", taglines: localTaglines.value,\n };\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return { data, fallbackFields: [\"$\"] };\n const record = raw as Readonly<Record<string, unknown>>;\n const text = validateTextDocument(SITE_HERO, record);\n const fallbackFields: string[] = text.ok ? [] : Object.keys(text.errors);\n for (const field of SITE_HERO.fields) {\n if (!fallbackFields.includes(field.name)) {\n const value = text.ok ? text.value[field.name] : record[field.name];\n if (typeof value === \"string\" && (field.name === \"heading\" || field.name === \"intro\")) data[field.name] = value.trim();\n }\n }\n const layout = Object.hasOwn(record, \"layout\") ? record.layout : undefined;\n const warnings: NonNullable<CmsResolution<ParsedSiteHero>[\"warnings\"]>[number][] = [];\n if (isLayout(layout)) data.layout = layout;\n else {\n data.layout = \"columns\";\n fallbackFields.push(\"layout\");\n warnings.push(SITE_HERO_LAYOUT_WARNING);\n }\n const taglines = scanSiteHeroTaglines(Object.hasOwn(record, \"taglines\") ? record.taglines : undefined);\n if (taglines.ok) {\n data.taglines = taglines.value;\n for (const { index } of taglines.dropped) fallbackFields.push(`taglines[${String(index)}]`);\n if (taglines.dropped.length > 0) warnings.push(SITE_HERO_TAGLINE_DROPPED_WARNING);\n } else {\n fallbackFields.push(\"taglines\");\n warnings.push(SITE_HERO_TAGLINES_DEFAULTED_WARNING);\n }\n const wholeFallback = [...SITE_HERO.fields.map((field) => field.name), \"layout\", \"taglines\"].every((field) => fallbackFields.includes(field));\n return { data, fallbackFields: wholeFallback ? [\"$\"] : fallbackFields,\n ...(warnings.length > 0 ? { warnings } : {}) };\n}\n\nexport function siteHeroQuery(): CmsQuery<SiteHero> {\n return defineCmsQuery<SiteHero>({\n name: \"siteHero.v1\", query: '*[_id == $id && _type == \"siteHero\"][0]{heading,intro,layout,taglines}',\n params: { id: \"siteHero\" }, dependencies: { types: [\"siteHero\"], ids: [\"siteHero\"] },\n resolve: parseSiteHero,\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "CMS_CONTRACT_VERSION", "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", "parseSiteHero", "siteHeroQuery", "validateSiteHeroTaglines", "validateTextDocument", "__toCommonJS", "TYPE", "ID", "SCOPE", "dependenciesCopy", "dependencies", "types", "type", "ids", "id", "defineCmsQuery", "query", "params", "copied", "key", "descriptor", "value", "cmsTags", "scope", "tags", "SITE_HERO_LAYOUTS", "SITE_HERO_TAGLINE_MAX_LENGTH", "SITE_HERO_LAYOUT_WARNING", "SITE_HERO_TAGLINE_DROPPED_WARNING", "SITE_HERO_TAGLINES_DEFAULTED_WARNING", "CMS_CONTRACT_VERSION", "SITE_HERO", "fieldError", "field", "text", "article", "word", "count", "validateTextDocument", "definition", "raw", "value", "errors", "submitted", "error", "scanSiteHeroTaglines", "heading", "dropped", "keys", "index", "item", "record", "key", "copy", "validateSiteHeroTaglines", "result", "first", "isLayout", "layout", "parseSiteHero", "fallback", "local", "localTaglines", "data", "fallbackFields", "warnings", "taglines", "wholeFallback", "siteHeroQuery", "defineCmsQuery"]
7
7
  }
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { defineCmsQuery, cmsTags } from "./contracts/query.cjs";
2
2
  export type { CmsParams, CmsDependencies, CmsResolution, CmsQuery } from "./contracts/query.cjs";
3
- export { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, parseSiteHero, validateSiteHeroTaglines } from "./contracts/text.cjs";
3
+ export { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, SITE_HERO_TAGLINE_DROPPED_WARNING, SITE_HERO_TAGLINES_DEFAULTED_WARNING, parseSiteHero, validateSiteHeroTaglines } from "./contracts/text.cjs";
4
4
  export type { SiteHero, ParsedSiteHero, SiteHeroLayout, SiteHeroTagline, TextFieldDefinition, TextDocumentDefinition, TextValidation } from "./contracts/text.cjs";
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { defineCmsQuery, cmsTags } from "./contracts/query.mjs";
2
2
  export type { CmsParams, CmsDependencies, CmsResolution, CmsQuery } from "./contracts/query.mjs";
3
- export { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, parseSiteHero, validateSiteHeroTaglines } from "./contracts/text.mjs";
3
+ export { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, SITE_HERO_TAGLINE_DROPPED_WARNING, SITE_HERO_TAGLINES_DEFAULTED_WARNING, parseSiteHero, validateSiteHeroTaglines } from "./contracts/text.mjs";
4
4
  export type { SiteHero, ParsedSiteHero, SiteHeroLayout, SiteHeroTagline, TextFieldDefinition, TextDocumentDefinition, TextValidation } from "./contracts/text.mjs";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { defineCmsQuery, cmsTags } from "./contracts/query.js";
2
2
  export type { CmsParams, CmsDependencies, CmsResolution, CmsQuery } from "./contracts/query.js";
3
- export { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, parseSiteHero, validateSiteHeroTaglines } from "./contracts/text.js";
3
+ export { SITE_HERO, CMS_CONTRACT_VERSION, validateTextDocument, siteHeroQuery, SITE_HERO_LAYOUTS, SITE_HERO_TAGLINE_MAX_LENGTH, SITE_HERO_LAYOUT_WARNING, SITE_HERO_TAGLINE_DROPPED_WARNING, SITE_HERO_TAGLINES_DEFAULTED_WARNING, parseSiteHero, validateSiteHeroTaglines } from "./contracts/text.js";
4
4
  export type { SiteHero, ParsedSiteHero, SiteHeroLayout, SiteHeroTagline, TextFieldDefinition, TextDocumentDefinition, TextValidation } from "./contracts/text.js";
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var H=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,O=/^[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 t=[...e.types];for(let n of t)if(typeof n!="string"||!H.test(n))throw new TypeError("Invalid CMS document type");if(e.ids!==void 0&&!Array.isArray(e.ids))throw new TypeError("Invalid CMS document IDs");let o=e.ids===void 0?void 0:[...e.ids];for(let n of o??[])if(typeof n!="string"||!O.test(n)||/^(drafts|versions)\./.test(n))throw new TypeError("Invalid CMS document ID");if(new Set(t).size+new Set(o).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(t),...o===void 0?{}:{ids:Object.freeze(o)}})}function p(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 o={};for(let n of Reflect.ownKeys(t)){let r=Object.getOwnPropertyDescriptor(t,n);if(typeof n!="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(o,n,{value:i,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(o),dependencies:T(e.dependencies),resolve:e.resolve})}function E(e,t){if(typeof e!="string"||e.length>77||!k.test(e))throw new TypeError("Invalid CMS scope");let o=T(t),n=[...[...new Set(o.types)].sort().map(r=>`cms:${e}:type:${r}`),...[...new Set(o.ids??[])].sort().map(r=>`cms:${e}:id:${r}`)];return Object.freeze(n)}var S=["columns","rows"],w=36,b="siteHero.layout.defaulted",C=1,l={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 R(e,t){let{article:o,word:n}=e.noun;if(t.length===0)return e.required?`Enter ${o} ${n}.`:null;let r=[...t].length;return r<e.minLength?`Make the ${n} at least ${String(e.minLength)} characters. It is ${String(r)} now.`:r>e.maxLength?`Keep the ${n} to ${String(e.maxLength)} characters or fewer. It is ${String(r)} now.`:t.includes("\u2014")?`The ${n} contains a long dash. Use a comma, a colon or a short dash instead.`:e.kind==="single-line"&&/[\r\n]/.test(t)?`The ${n} must be a single line.`:e.noTrailingFullStop===!0&&t.endsWith(".")?`${n.charAt(0).toUpperCase()}${n.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`:null}function y(e,t){let o={},n={};for(let r of e.fields){let i=Object.hasOwn(t,r.name)?t[r.name]:void 0,a=typeof i=="string"?i.trim():"",s=R(r,a);Object.defineProperty(s===null?o:n,r.name,{value:s??a,enumerable:!0})}return Object.keys(n).length>0?{ok:!1,errors:n}:{ok:!0,value:o}}function g(e){if(!Array.isArray(e))return{ok:!1,error:"Enter a list of taglines."};let t=l.fields[0];if(!t)throw new TypeError("Missing siteHero heading definition");let o={...t,name:"text",noun:{article:"a",word:"tagline"},maxLength:w},n=[],r=new Set;for(let i of e){if(!i||typeof i!="object"||Array.isArray(i))return{ok:!1,error:"Enter a key and text for each tagline."};let a=i,s=Object.hasOwn(a,"key")?a.key:void 0;if(typeof s!="string"||!/^[a-z][a-z0-9_-]{0,31}$/.test(s))return{ok:!1,error:"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter."};if(r.has(s))return{ok:!1,error:"Use each tagline key only once."};let d=y({...l,fields:[o]},a);if(!d.ok)return{ok:!1,error:d.errors.text??"Invalid tagline."};r.add(s),n.push({key:s,text:d.value.text??""})}return{ok:!0,value:n}}function h(e){return S.some(t=>e===t)}function x(e,t){let o=y(l,t),n=g(t.taglines??[]);if(!o.ok||!n.ok||t.layout!==void 0&&!h(t.layout))throw new TypeError("Invalid siteHero fallback");let r={heading:o.value.heading??"",intro:o.value.intro??"",layout:t.layout??"columns",taglines:n.value};if(e===null||typeof e!="object"||Array.isArray(e))return{data:r,fallbackFields:["$"]};let i=e,a=y(l,i),s=a.ok?[]:Object.keys(a.errors);for(let u of l.fields)if(!s.includes(u.name)){let m=a.ok?a.value[u.name]:i[u.name];typeof m=="string"&&(u.name==="heading"||u.name==="intro")&&(r[u.name]=m.trim())}let d=Object.hasOwn(i,"layout")?i.layout:void 0,c=[];h(d)?r.layout=d:(r.layout="columns",s.push("layout"),c.push(b));let f=g(Object.hasOwn(i,"taglines")?i.taglines:void 0);return f.ok?r.taglines=f.value:s.push("taglines"),{data:r,fallbackFields:s.length===l.fields.length+2?["$"]:s,...c.length>0?{warnings:c}:{}}}function v(){return p({name:"siteHero.v1",query:'*[_id == $id && _type == "siteHero"][0]{heading,intro,layout,taglines}',params:{id:"siteHero"},dependencies:{types:["siteHero"],ids:["siteHero"]},resolve:x})}export{C as CMS_CONTRACT_VERSION,l as SITE_HERO,S as SITE_HERO_LAYOUTS,b as SITE_HERO_LAYOUT_WARNING,w as SITE_HERO_TAGLINE_MAX_LENGTH,E as cmsTags,p as defineCmsQuery,x as parseSiteHero,v as siteHeroQuery,g as validateSiteHeroTaglines,y as validateTextDocument};
1
+ var _=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,R=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,C=/^[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"||!_.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 o=e.ids===void 0?void 0:[...e.ids];for(let r of o??[])if(typeof r!="string"||!R.test(r)||/^(drafts|versions)\./.test(r))throw new TypeError("Invalid CMS document ID");if(new Set(t).size+new Set(o).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(t),...o===void 0?{}:{ids:Object.freeze(o)}})}function f(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 o={};for(let r of Reflect.ownKeys(t)){let n=Object.getOwnPropertyDescriptor(t,r);if(typeof r!="string"||!n||!Object.hasOwn(n,"value")||!n.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let i=n.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(o,r,{value:i,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(o),dependencies:T(e.dependencies),resolve:e.resolve})}function I(e,t){if(typeof e!="string"||e.length>77||!C.test(e))throw new TypeError("Invalid CMS scope");let o=T(t),r=[...[...new Set(o.types)].sort().map(n=>`cms:${e}:type:${n}`),...[...new Set(o.ids??[])].sort().map(n=>`cms:${e}:id:${n}`)];return Object.freeze(r)}var S=["columns","rows"],H=40,E="siteHero.layout.defaulted",w="siteHero.tagline.dropped",x="siteHero.taglines.defaulted",v=1,y={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 A(e,t){let{article:o,word:r}=e.noun;if(t.length===0)return e.required?`Enter ${o} ${r}.`:null;let n=[...t].length;return n<e.minLength?`Make the ${r} at least ${String(e.minLength)} characters. It is ${String(n)} now.`:n>e.maxLength?`Keep the ${r} to ${String(e.maxLength)} characters or fewer. It is ${String(n)} now.`:t.includes("\u2014")?`The ${r} contains a long dash. Use a comma, a colon or a short dash instead.`:e.kind==="single-line"&&/[\r\n]/.test(t)?`The ${r} must be a single line.`:e.noTrailingFullStop===!0&&t.endsWith(".")?`${r.charAt(0).toUpperCase()}${r.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`:null}function g(e,t){let o={},r={};for(let n of e.fields){let i=Object.hasOwn(t,n.name)?t[n.name]:void 0,a=typeof i=="string"?i.trim():"",s=A(n,a);Object.defineProperty(s===null?o:r,n.name,{value:s??a,enumerable:!0})}return Object.keys(r).length>0?{ok:!1,errors:r}:{ok:!0,value:o}}function b(e){if(!Array.isArray(e))return{ok:!1,error:"Enter a list of taglines."};let t=y.fields[0];if(!t)throw new TypeError("Missing siteHero heading definition");let o={...t,name:"text",noun:{article:"a",word:"tagline"},maxLength:H},r=[],n=[],i=new Set;for(let[a,s]of e.entries()){if(!s||typeof s!="object"||Array.isArray(s)){n.push({index:a,error:"Enter a key and text for each tagline."});continue}let c=s,d=Object.hasOwn(c,"key")?c.key:void 0;if(typeof d!="string"||!/^[a-z][a-z0-9_-]{0,31}$/.test(d)){n.push({index:a,error:"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter."});continue}if(i.has(d)){n.push({index:a,error:"Use each tagline key only once."});continue}let u=g({...y,fields:[o]},c);if(!u.ok){n.push({index:a,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)){n.push({index:a,error:"Use sentence case for the tagline, rather than all capitals."});continue}i.add(d),r.push({key:d,text:p})}return{ok:!0,value:r,dropped:n}}function O(e){let t=b(e);if(!t.ok)return t;let o=t.dropped[0];return o?{ok:!1,error:o.error}:{ok:!0,value:t.value}}function h(e){return S.some(t=>e===t)}function k(e,t){let o=g(y,t),r=O(t.taglines??[]);if(!o.ok||!r.ok||t.layout!==void 0&&!h(t.layout))throw new TypeError("Invalid siteHero fallback");let n={heading:o.value.heading??"",intro:o.value.intro??"",layout:t.layout??"columns",taglines:r.value};if(e===null||typeof e!="object"||Array.isArray(e))return{data:n,fallbackFields:["$"]};let i=e,a=g(y,i),s=a.ok?[]:Object.keys(a.errors);for(let l of y.fields)if(!s.includes(l.name)){let m=a.ok?a.value[l.name]:i[l.name];typeof m=="string"&&(l.name==="heading"||l.name==="intro")&&(n[l.name]=m.trim())}let c=Object.hasOwn(i,"layout")?i.layout:void 0,d=[];h(c)?n.layout=c:(n.layout="columns",s.push("layout"),d.push(E));let u=b(Object.hasOwn(i,"taglines")?i.taglines:void 0);if(u.ok){n.taglines=u.value;for(let{index:l}of u.dropped)s.push(`taglines[${String(l)}]`);u.dropped.length>0&&d.push(w)}else s.push("taglines"),d.push(x);let p=[...y.fields.map(l=>l.name),"layout","taglines"].every(l=>s.includes(l));return{data:n,fallbackFields:p?["$"]:s,...d.length>0?{warnings:d}:{}}}function L(){return f({name:"siteHero.v1",query:'*[_id == $id && _type == "siteHero"][0]{heading,intro,layout,taglines}',params:{id:"siteHero"},dependencies:{types:["siteHero"],ids:["siteHero"]},resolve:k})}export{v as CMS_CONTRACT_VERSION,y as SITE_HERO,S as SITE_HERO_LAYOUTS,E as SITE_HERO_LAYOUT_WARNING,x as SITE_HERO_TAGLINES_DEFAULTED_WARNING,w as SITE_HERO_TAGLINE_DROPPED_WARNING,H as SITE_HERO_TAGLINE_MAX_LENGTH,I as cmsTags,f as defineCmsQuery,k as parseSiteHero,L as siteHeroQuery,O as validateSiteHeroTaglines,g as validateTextDocument};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/contracts/query.ts", "../src/contracts/text.ts"],
4
- "sourcesContent": ["/** 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\"[];\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 { defineCmsQuery, type CmsQuery, type CmsResolution } from \"./query.js\";\n\nexport const SITE_HERO_LAYOUTS = [\"columns\", \"rows\"] as const;\nexport const SITE_HERO_TAGLINE_MAX_LENGTH = 36;\nexport const SITE_HERO_LAYOUT_WARNING = \"siteHero.layout.defaulted\" as const;\nexport type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];\nexport type SiteHeroTagline = { readonly key: string; readonly text: string };\n/** Optional additions preserve existing heading/intro-only consumer fallbacks. */\nexport type SiteHero = {\n readonly heading: string;\n readonly intro: string;\n readonly layout?: SiteHeroLayout;\n readonly taglines?: readonly SiteHeroTagline[];\n};\nexport type ParsedSiteHero = SiteHero & {\n readonly layout: SiteHeroLayout;\n readonly taglines: readonly SiteHeroTagline[];\n};\nexport type TextFieldDefinition = {\n readonly name: string;\n readonly label: string;\n readonly noun: { readonly article: \"a\" | \"an\"; readonly word: string };\n readonly kind: \"single-line\" | \"multi-line\";\n readonly required: boolean;\n readonly minLength: number;\n readonly maxLength: number;\n readonly noTrailingFullStop?: boolean;\n};\nexport type TextDocumentDefinition = {\n readonly key: string;\n readonly documentId: string;\n readonly documentType: string;\n readonly fields: readonly TextFieldDefinition[];\n readonly copy: {\n readonly currentTitle: string;\n readonly editTitle: string;\n readonly empty: string;\n };\n};\nexport type TextValidation =\n | { readonly ok: true; readonly value: Readonly<Record<string, string>> }\n | { readonly ok: false; readonly errors: Readonly<Record<string, string>> };\n\nexport const CMS_CONTRACT_VERSION = 1;\n\nexport const SITE_HERO: TextDocumentDefinition = {\n key: \"hero\",\n documentId: \"siteHero\",\n documentType: \"siteHero\",\n fields: [\n {\n name: \"heading\",\n label: \"Heading\",\n noun: { article: \"a\", word: \"heading\" },\n kind: \"single-line\",\n required: true,\n minLength: 1,\n maxLength: 80,\n noTrailingFullStop: true,\n },\n {\n name: \"intro\",\n label: \"Introduction\",\n noun: { article: \"an\", word: \"introduction\" },\n kind: \"multi-line\",\n required: true,\n minLength: 1,\n maxLength: 320,\n },\n ],\n copy: {\n currentTitle: \"On your site now\",\n editTitle: \"Edit and publish\",\n empty: \"Your site has no hero text yet. Whatever you publish below becomes its first version.\",\n },\n};\n\nfunction fieldError(field: TextFieldDefinition, text: string): string | null {\n const { article, word } = field.noun;\n if (text.length === 0) return field.required ? `Enter ${article} ${word}.` : null;\n const count = [...text].length;\n if (count < field.minLength) return `Make the ${word} at least ${String(field.minLength)} characters. It is ${String(count)} now.`;\n if (count > field.maxLength) return `Keep the ${word} to ${String(field.maxLength)} characters or fewer. It is ${String(count)} now.`;\n if (text.includes(\"\\u2014\")) return `The ${word} contains a long dash. Use a comma, a colon or a short dash instead.`;\n if (field.kind === \"single-line\" && /[\\r\\n]/.test(text)) return `The ${word} must be a single line.`;\n if (field.noTrailingFullStop === true && text.endsWith(\".\")) {\n return `${word.charAt(0).toUpperCase()}${word.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`;\n }\n return null;\n}\n\nexport function validateTextDocument(\n definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>,\n): TextValidation {\n const value: Record<string, string> = {};\n const errors: Record<string, string> = {};\n for (const field of definition.fields) {\n const submitted = Object.hasOwn(raw, field.name) ? raw[field.name] : undefined;\n const text = typeof submitted === \"string\" ? submitted.trim() : \"\";\n const error = fieldError(field, text);\n Object.defineProperty(error === null ? value : errors, field.name, { value: error ?? text, enumerable: true });\n }\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value };\n}\n\n/** Shared with the schema adapter; no provider metadata is returned. */\nexport function validateSiteHeroTaglines(raw: unknown):\n | { readonly ok: true; readonly value: readonly SiteHeroTagline[] }\n | { readonly ok: false; readonly error: string } {\n if (!Array.isArray(raw)) return { ok: false, error: \"Enter a list of taglines.\" };\n const heading = SITE_HERO.fields[0];\n if (!heading) throw new TypeError(\"Missing siteHero heading definition\");\n const field = { ...heading, name: \"text\", noun: { article: \"a\", word: \"tagline\" } as const,\n maxLength: SITE_HERO_TAGLINE_MAX_LENGTH };\n const value: SiteHeroTagline[] = [];\n const keys = new Set<string>();\n for (const item of raw as unknown[]) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) return { ok: false, error: \"Enter a key and text for each tagline.\" };\n const record = item as Record<string, unknown>;\n const key = Object.hasOwn(record, \"key\") ? record.key : undefined;\n if (typeof key !== \"string\" || !/^[a-z][a-z0-9_-]{0,31}$/.test(key)) {\n return { ok: false, error: \"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter.\" };\n }\n if (keys.has(key)) return { ok: false, error: \"Use each tagline key only once.\" };\n const text = validateTextDocument({ ...SITE_HERO, fields: [field] }, record);\n if (!text.ok) return { ok: false, error: text.errors.text ?? \"Invalid tagline.\" };\n keys.add(key);\n value.push({ key, text: text.value.text ?? \"\" });\n }\n return { ok: true, value };\n}\n\nfunction isLayout(value: unknown): value is SiteHeroLayout {\n return SITE_HERO_LAYOUTS.some((layout) => value === layout);\n}\n\n/** Strict per-field resolution: an invalid list never partially changes keyed copy. */\nexport function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero> {\n const local = validateTextDocument(SITE_HERO, fallback);\n const localTaglines = validateSiteHeroTaglines(fallback.taglines ?? []);\n if (!local.ok || !localTaglines.ok || (fallback.layout !== undefined && !isLayout(fallback.layout))) {\n throw new TypeError(\"Invalid siteHero fallback\");\n }\n const data: { heading: string; intro: string; layout: SiteHeroLayout; taglines: readonly SiteHeroTagline[] } = {\n heading: local.value.heading ?? \"\", intro: local.value.intro ?? \"\",\n layout: fallback.layout ?? \"columns\", taglines: localTaglines.value,\n };\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return { data, fallbackFields: [\"$\"] };\n const record = raw as Readonly<Record<string, unknown>>;\n const text = validateTextDocument(SITE_HERO, record);\n const fallbackFields: string[] = text.ok ? [] : Object.keys(text.errors);\n for (const field of SITE_HERO.fields) {\n if (!fallbackFields.includes(field.name)) {\n const value = text.ok ? text.value[field.name] : record[field.name];\n if (typeof value === \"string\" && (field.name === \"heading\" || field.name === \"intro\")) data[field.name] = value.trim();\n }\n }\n const layout = Object.hasOwn(record, \"layout\") ? record.layout : undefined;\n const warnings: (typeof SITE_HERO_LAYOUT_WARNING)[] = [];\n if (isLayout(layout)) data.layout = layout;\n else {\n data.layout = \"columns\";\n fallbackFields.push(\"layout\");\n warnings.push(SITE_HERO_LAYOUT_WARNING);\n }\n const taglines = validateSiteHeroTaglines(Object.hasOwn(record, \"taglines\") ? record.taglines : undefined);\n if (taglines.ok) data.taglines = taglines.value;\n else fallbackFields.push(\"taglines\");\n return { data, fallbackFields: fallbackFields.length === SITE_HERO.fields.length + 2 ? [\"$\"] : fallbackFields,\n ...(warnings.length > 0 ? { warnings } : {}) };\n}\n\nexport function siteHeroQuery(): CmsQuery<SiteHero> {\n return defineCmsQuery<SiteHero>({\n name: \"siteHero.v1\", query: '*[_id == $id && _type == \"siteHero\"][0]{heading,intro,layout,taglines}',\n params: { id: \"siteHero\" }, dependencies: { types: [\"siteHero\"], ids: [\"siteHero\"] },\n resolve: parseSiteHero,\n });\n}\n"],
5
- "mappings": "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",
6
- "names": ["TYPE", "ID", "SCOPE", "dependenciesCopy", "dependencies", "types", "type", "ids", "id", "defineCmsQuery", "query", "params", "copied", "key", "descriptor", "value", "cmsTags", "scope", "tags", "SITE_HERO_LAYOUTS", "SITE_HERO_TAGLINE_MAX_LENGTH", "SITE_HERO_LAYOUT_WARNING", "CMS_CONTRACT_VERSION", "SITE_HERO", "fieldError", "field", "text", "article", "word", "count", "validateTextDocument", "definition", "raw", "value", "errors", "submitted", "error", "validateSiteHeroTaglines", "heading", "keys", "item", "record", "key", "isLayout", "layout", "parseSiteHero", "fallback", "local", "localTaglines", "data", "fallbackFields", "warnings", "taglines", "siteHeroQuery", "defineCmsQuery"]
4
+ "sourcesContent": ["/** 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 { defineCmsQuery, type CmsQuery, type CmsResolution } from \"./query.js\";\n\nexport const SITE_HERO_LAYOUTS = [\"columns\", \"rows\"] as const;\nexport const SITE_HERO_TAGLINE_MAX_LENGTH = 40;\nexport const SITE_HERO_LAYOUT_WARNING = \"siteHero.layout.defaulted\" as const;\nexport const SITE_HERO_TAGLINE_DROPPED_WARNING = \"siteHero.tagline.dropped\" as const;\nexport const SITE_HERO_TAGLINES_DEFAULTED_WARNING = \"siteHero.taglines.defaulted\" as const;\nexport type SiteHeroLayout = typeof SITE_HERO_LAYOUTS[number];\nexport type SiteHeroTagline = { readonly key: string; readonly text: string };\n/** Optional additions preserve existing heading/intro-only consumer fallbacks. */\nexport type SiteHero = {\n readonly heading: string;\n readonly intro: string;\n readonly layout?: SiteHeroLayout;\n readonly taglines?: readonly SiteHeroTagline[];\n};\nexport type ParsedSiteHero = SiteHero & {\n readonly layout: SiteHeroLayout;\n readonly taglines: readonly SiteHeroTagline[];\n};\nexport type TextFieldDefinition = {\n readonly name: string;\n readonly label: string;\n readonly noun: { readonly article: \"a\" | \"an\"; readonly word: string };\n readonly kind: \"single-line\" | \"multi-line\";\n readonly required: boolean;\n readonly minLength: number;\n readonly maxLength: number;\n readonly noTrailingFullStop?: boolean;\n};\nexport type TextDocumentDefinition = {\n readonly key: string;\n readonly documentId: string;\n readonly documentType: string;\n readonly fields: readonly TextFieldDefinition[];\n readonly copy: {\n readonly currentTitle: string;\n readonly editTitle: string;\n readonly empty: string;\n };\n};\nexport type TextValidation =\n | { readonly ok: true; readonly value: Readonly<Record<string, string>> }\n | { readonly ok: false; readonly errors: Readonly<Record<string, string>> };\n\nexport const CMS_CONTRACT_VERSION = 1;\n\nexport const SITE_HERO: TextDocumentDefinition = {\n key: \"hero\",\n documentId: \"siteHero\",\n documentType: \"siteHero\",\n fields: [\n {\n name: \"heading\",\n label: \"Heading\",\n noun: { article: \"a\", word: \"heading\" },\n kind: \"single-line\",\n required: true,\n minLength: 1,\n maxLength: 80,\n noTrailingFullStop: true,\n },\n {\n name: \"intro\",\n label: \"Introduction\",\n noun: { article: \"an\", word: \"introduction\" },\n kind: \"multi-line\",\n required: true,\n minLength: 1,\n maxLength: 320,\n },\n ],\n copy: {\n currentTitle: \"On your site now\",\n editTitle: \"Edit and publish\",\n empty: \"Your site has no hero text yet. Whatever you publish below becomes its first version.\",\n },\n};\n\nfunction fieldError(field: TextFieldDefinition, text: string): string | null {\n const { article, word } = field.noun;\n if (text.length === 0) return field.required ? `Enter ${article} ${word}.` : null;\n const count = [...text].length;\n if (count < field.minLength) return `Make the ${word} at least ${String(field.minLength)} characters. It is ${String(count)} now.`;\n if (count > field.maxLength) return `Keep the ${word} to ${String(field.maxLength)} characters or fewer. It is ${String(count)} now.`;\n if (text.includes(\"\\u2014\")) return `The ${word} contains a long dash. Use a comma, a colon or a short dash instead.`;\n if (field.kind === \"single-line\" && /[\\r\\n]/.test(text)) return `The ${word} must be a single line.`;\n if (field.noTrailingFullStop === true && text.endsWith(\".\")) {\n return `${word.charAt(0).toUpperCase()}${word.slice(1)}s on your site do not end with a full stop. Remove the last full stop.`;\n }\n return null;\n}\n\nexport function validateTextDocument(\n definition: TextDocumentDefinition, raw: Readonly<Record<string, unknown>>,\n): TextValidation {\n const value: Record<string, string> = {};\n const errors: Record<string, string> = {};\n for (const field of definition.fields) {\n const submitted = Object.hasOwn(raw, field.name) ? raw[field.name] : undefined;\n const text = typeof submitted === \"string\" ? submitted.trim() : \"\";\n const error = fieldError(field, text);\n Object.defineProperty(error === null ? value : errors, field.name, { value: error ?? text, enumerable: true });\n }\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value };\n}\n\n/** One rule set for strict authoring validation and resilient published reads. */\nfunction scanSiteHeroTaglines(raw: unknown):\n | { readonly ok: true; readonly value: readonly SiteHeroTagline[]; readonly dropped: readonly { index: number; error: string }[] }\n | { readonly ok: false; readonly error: string } {\n if (!Array.isArray(raw)) return { ok: false, error: \"Enter a list of taglines.\" };\n const heading = SITE_HERO.fields[0];\n if (!heading) throw new TypeError(\"Missing siteHero heading definition\");\n const field = { ...heading, name: \"text\", noun: { article: \"a\", word: \"tagline\" } as const,\n maxLength: SITE_HERO_TAGLINE_MAX_LENGTH };\n const value: SiteHeroTagline[] = [];\n const dropped: { index: number; error: string }[] = [];\n const keys = new Set<string>();\n for (const [index, item] of (raw as unknown[]).entries()) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n dropped.push({ index, error: \"Enter a key and text for each tagline.\" });\n continue;\n }\n const record = item as Record<string, unknown>;\n const key = Object.hasOwn(record, \"key\") ? record.key : undefined;\n if (typeof key !== \"string\" || !/^[a-z][a-z0-9_-]{0,31}$/.test(key)) {\n dropped.push({ index, error: \"Use a lowercase key of 1 to 32 letters, numbers, short dashes or underscores, starting with a letter.\" });\n continue;\n }\n if (keys.has(key)) {\n dropped.push({ index, error: \"Use each tagline key only once.\" });\n continue;\n }\n const text = validateTextDocument({ ...SITE_HERO, fields: [field] }, record);\n if (!text.ok) {\n dropped.push({ index, error: text.errors.text ?? \"Invalid tagline.\" });\n continue;\n }\n const copy = text.value.text ?? \"\";\n if ((copy.match(/\\p{L}/gu)?.length ?? 0) >= 2 && !/\\p{Ll}/u.test(copy)) {\n dropped.push({ index, error: \"Use sentence case for the tagline, rather than all capitals.\" });\n continue;\n }\n keys.add(key);\n value.push({ key, text: copy });\n }\n return { ok: true, value, dropped };\n}\n\n/** Shared with the schema adapter; invalid authoring input is refused as a whole. */\nexport function validateSiteHeroTaglines(raw: unknown):\n | { readonly ok: true; readonly value: readonly SiteHeroTagline[] }\n | { readonly ok: false; readonly error: string } {\n const result = scanSiteHeroTaglines(raw);\n if (!result.ok) return result;\n const first = result.dropped[0];\n return first ? { ok: false, error: first.error } : { ok: true, value: result.value };\n}\n\nfunction isLayout(value: unknown): value is SiteHeroLayout {\n return SITE_HERO_LAYOUTS.some((layout) => value === layout);\n}\n\n/** Invalid published entries are dropped without discarding valid keyed siblings. */\nexport function parseSiteHero(raw: unknown, fallback: SiteHero): CmsResolution<ParsedSiteHero> {\n const local = validateTextDocument(SITE_HERO, fallback);\n const localTaglines = validateSiteHeroTaglines(fallback.taglines ?? []);\n if (!local.ok || !localTaglines.ok || (fallback.layout !== undefined && !isLayout(fallback.layout))) {\n throw new TypeError(\"Invalid siteHero fallback\");\n }\n const data: { heading: string; intro: string; layout: SiteHeroLayout; taglines: readonly SiteHeroTagline[] } = {\n heading: local.value.heading ?? \"\", intro: local.value.intro ?? \"\",\n layout: fallback.layout ?? \"columns\", taglines: localTaglines.value,\n };\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return { data, fallbackFields: [\"$\"] };\n const record = raw as Readonly<Record<string, unknown>>;\n const text = validateTextDocument(SITE_HERO, record);\n const fallbackFields: string[] = text.ok ? [] : Object.keys(text.errors);\n for (const field of SITE_HERO.fields) {\n if (!fallbackFields.includes(field.name)) {\n const value = text.ok ? text.value[field.name] : record[field.name];\n if (typeof value === \"string\" && (field.name === \"heading\" || field.name === \"intro\")) data[field.name] = value.trim();\n }\n }\n const layout = Object.hasOwn(record, \"layout\") ? record.layout : undefined;\n const warnings: NonNullable<CmsResolution<ParsedSiteHero>[\"warnings\"]>[number][] = [];\n if (isLayout(layout)) data.layout = layout;\n else {\n data.layout = \"columns\";\n fallbackFields.push(\"layout\");\n warnings.push(SITE_HERO_LAYOUT_WARNING);\n }\n const taglines = scanSiteHeroTaglines(Object.hasOwn(record, \"taglines\") ? record.taglines : undefined);\n if (taglines.ok) {\n data.taglines = taglines.value;\n for (const { index } of taglines.dropped) fallbackFields.push(`taglines[${String(index)}]`);\n if (taglines.dropped.length > 0) warnings.push(SITE_HERO_TAGLINE_DROPPED_WARNING);\n } else {\n fallbackFields.push(\"taglines\");\n warnings.push(SITE_HERO_TAGLINES_DEFAULTED_WARNING);\n }\n const wholeFallback = [...SITE_HERO.fields.map((field) => field.name), \"layout\", \"taglines\"].every((field) => fallbackFields.includes(field));\n return { data, fallbackFields: wholeFallback ? [\"$\"] : fallbackFields,\n ...(warnings.length > 0 ? { warnings } : {}) };\n}\n\nexport function siteHeroQuery(): CmsQuery<SiteHero> {\n return defineCmsQuery<SiteHero>({\n name: \"siteHero.v1\", query: '*[_id == $id && _type == \"siteHero\"][0]{heading,intro,layout,taglines}',\n params: { id: \"siteHero\" }, dependencies: { types: [\"siteHero\"], ids: [\"siteHero\"] },\n resolve: parseSiteHero,\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["TYPE", "ID", "SCOPE", "dependenciesCopy", "dependencies", "types", "type", "ids", "id", "defineCmsQuery", "query", "params", "copied", "key", "descriptor", "value", "cmsTags", "scope", "tags", "SITE_HERO_LAYOUTS", "SITE_HERO_TAGLINE_MAX_LENGTH", "SITE_HERO_LAYOUT_WARNING", "SITE_HERO_TAGLINE_DROPPED_WARNING", "SITE_HERO_TAGLINES_DEFAULTED_WARNING", "CMS_CONTRACT_VERSION", "SITE_HERO", "fieldError", "field", "text", "article", "word", "count", "validateTextDocument", "definition", "raw", "value", "errors", "submitted", "error", "scanSiteHeroTaglines", "heading", "dropped", "keys", "index", "item", "record", "key", "copy", "validateSiteHeroTaglines", "result", "first", "isLayout", "layout", "parseSiteHero", "fallback", "local", "localTaglines", "data", "fallbackFields", "warnings", "taglines", "wholeFallback", "siteHeroQuery", "defineCmsQuery"]
7
7
  }
package/dist/next.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var R=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var F=(e,r)=>{for(var t in r)R(e,t,{get:r[t],enumerable:!0})},$=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of z(r))!N.call(e,o)&&o!==t&&R(e,o,{get:()=>r[o],enumerable:!(n=j(r,o))||n.enumerable});return e};var U=e=>$(R({},"__esModule",{value:!0}),e);var K={};F(K,{createNextCmsReader:()=>O,createRevalidateRoute:()=>D});module.exports=U(K);var de=require("server-only");var H=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,L=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,Z=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function k(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 n of r)if(typeof n!="string"||!H.test(n))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 n of t??[])if(typeof n!="string"||!L.test(n)||/^(drafts|versions)\./.test(n))throw new TypeError("Invalid CMS document ID");if(new Set(r).size+new Set(t).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(r),...t===void 0?{}:{ids:Object.freeze(t)}})}function E(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 t={};for(let n of Reflect.ownKeys(r)){let o=Object.getOwnPropertyDescriptor(r,n);if(typeof n!="string"||!o||!Object.hasOwn(o,"value")||!o.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let a=o.value;if(!(a===null||typeof a=="string"||typeof a=="boolean"||typeof a=="number"&&Number.isFinite(a)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(t,n,{value:a,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(t),dependencies:k(e.dependencies),resolve:e.resolve})}function T(e,r){if(typeof e!="string"||e.length>77||!Z.test(e))throw new TypeError("Invalid CMS scope");let t=k(r),n=[...[...new Set(t.types)].sort().map(o=>`cms:${e}:type:${o}`),...[...new Set(t.ids??[])].sort().map(o=>`cms:${e}:id:${o}`)];return Object.freeze(n)}function A(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")))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 S(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 t=e.adapter;T(t.scope,{types:["ScopeValidation"]});let n=o=>{try{e.onDiagnostic?e.onDiagnostic(o):console.warn(JSON.stringify(o))}catch{}};return{async read(o,a){let s,l,d;try{if(s=E(o),d=T(t.scope,s.dependencies),!a||!Object.hasOwn(a,"fallback"))throw new TypeError;l=A(s.resolve(null,a.fallback))}catch{throw new TypeError("Invalid CMS query or fallback configuration")}let f=(g,u,m)=>(n({event:"cms.fallback",query:s.name,reason:g,fields:["$"],...u===void 0?{}:{status:u},...m?{warnings:m}:{}}),{data:l.data,source:"fallback",fallbackFields:["$"],reason:g,...m?{warnings:m}:{}}),i;try{i=await t.read({name:s.name,query:s.query,params:s.params},{tags:d,revalidateSeconds:r})}catch{return f("network")}if(!i.ok){let u=["configuration","network","timeout","rate-limit","upstream","plan-limit","permission","malformed"].includes(i.reason)?i.reason:"malformed",m=Number.isInteger(i.status)&&(i.status??0)>=100&&(i.status??0)<=599?i.status:void 0;return f(u,m)}if(i.value===null||i.value===void 0)return f("missing");let c;try{c=A(s.resolve(i.value,a.fallback))}catch{return f("malformed")}return c.fallbackFields.includes("$")?{...f("invalid-field",void 0,c.warnings),data:c.data}:c.fallbackFields.length>0?(n({event:"cms.partial-fallback",query:s.name,reason:"invalid-field",fields:c.fallbackFields,...c.warnings?{warnings:c.warnings}:{}}),{...c,source:"mixed",reason:"invalid-field"}):{...c,source:"cms"}}}}var O=S;var _=require("next/cache.js");var h="sanity-webhook-signature",Q=/^t=(\d+)[, ]+v1=([^, ]+)$/;var I=new TextEncoder;function V(e){return crypto.subtle.importKey("raw",I.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}function B(e){if(!/^[A-Za-z0-9_-]+={0,2}$/.test(e))return null;let r=e.replace(/-/g,"+").replace(/_/g,"/");try{let t=atob(r),n=new Uint8Array(t.length);for(let o=0;o<t.length;o+=1)n[o]=t.charCodeAt(o);return n}catch{return null}}async function x(e){let{secret:r,rawBody:t,headers:n}=e,o=e.now??Date.now(),a=e.toleranceMs??3e5;if(!r||r.length===0)return{ok:!1,reason:"no-secret"};let s=n.get(h);if(!s)return{ok:!1,reason:"no-signature"};let l=Q.exec(s.trim());if(l===null)return{ok:!1,reason:"malformed-signature"};let d=Number(l[1]),f=l[2]??"";if(!Number.isSafeInteger(d))return{ok:!1,reason:"malformed-signature"};if(d<16094592e5)return{ok:!1,reason:"stale-timestamp"};if(Math.abs(o-d)>a)return{ok:!1,reason:"stale-timestamp"};let i=B(f);if(i===null)return{ok:!1,reason:"malformed-signature"};let c=await V(r);return await crypto.subtle.verify("HMAC",c,i,I.encode(`${d}.${t}`))?{ok:!0}:{ok:!1,reason:"bad-signature"}}var q=16*1024,W=1500,Y=new TextEncoder;function y(e,r,t={},n=!1){return new Response(n?null:JSON.stringify(r),{status:e,headers:{"Content-Type":"application/json","Cache-Control":"no-store",...t}})}function J(e,r){if(!r||typeof r!="object"||Array.isArray(r)||Object.keys(r).length===0)throw new TypeError("Invalid CMS invalidation mapping");let t=Object.create(null);for(let n of Reflect.ownKeys(r)){let o=Object.getOwnPropertyDescriptor(r,n);if(typeof n!="string"||!o?.enumerable||!Object.hasOwn(o,"value"))throw new TypeError("Invalid CMS invalidation mapping");let a=o.value;if(!Array.isArray(a)||!a.includes(n))throw new TypeError("Invalid CMS invalidation mapping");T(e,{types:a,ids:["validation"]}),t[n]=Object.freeze([...a])}for(let n of Object.values(t))if(n.some(o=>!Object.hasOwn(t,o)))throw new TypeError("Invalid CMS invalidation mapping");return Object.freeze(t)}function M(e){return typeof e=="string"&&e.trim()!==""&&Y.encode(e).byteLength>=32}var b=class extends Error{constructor(t){super("Invalid CMS webhook body");this.status=t}status};async function G(e){let r=e.body?.getReader();if(!r)return"";let t=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}),n,o=new Promise((a,s)=>{n=setTimeout(()=>s(new b(400)),W)});try{let a=0,s="";for(;;){let{done:l,value:d}=await Promise.race([r.read(),o]);if(l)return s+t.decode();if(a+=d.byteLength,a>q)throw new b(413);s+=t.decode(d,{stream:!0})}}catch(a){throw r.cancel().catch(()=>{}),a}finally{clearTimeout(n),r.releaseLock()}}function D(e){let r=e.scope,t=J(r,e.typeToTags),n=e.secretEnv??"SANITY_REVALIDATE_SECRET",o=e.previousSecretEnv??"SANITY_REVALIDATE_SECRET_PREVIOUS",a=e.env??(()=>process.env),s=e.now??Date.now,l=async d=>{if(d.method!=="POST")return y(405,{error:"Method not allowed"},{Allow:"POST"},d.method==="HEAD");let f,i;try{let p=a(),v=p[n],w=p[o];if(!M(v)||w!==void 0&&!M(w))throw new Error;f=v,i=w}catch{return y(503,{error:"COULD NOT ANSWER: revalidation configuration unavailable"})}let c=d.headers.get(h);if(!c||c.length>512||!/^t=\d+[, ]+v1=[A-Za-z0-9_-]+={0,2}$/.test(c.trim()))return y(401,{error:"Unauthorized"});let g;try{g=await G(d)}catch(p){return p instanceof b&&p.status===413?y(413,{error:"Payload too large"}):y(400,{error:"Invalid body"})}try{let p=s();if(!Number.isFinite(p))throw new Error;if(!(await Promise.all([f,...i===void 0?[]:[i]].map(w=>x({secret:w,rawBody:g,headers:d.headers,now:p})))).some(w=>w.ok))return y(401,{error:"Unauthorized"})}catch{return y(401,{error:"Unauthorized"})}let u;try{u=JSON.parse(g)}catch{return y(400,{error:"Invalid payload"})}if(!u||typeof u!="object"||Array.isArray(u)||Object.keys(u).length!==2||!Object.hasOwn(u,"_type")||!Object.hasOwn(u,"_id"))return y(400,{error:"Invalid payload"});let{_type:m,_id:C}=u;if(typeof m!="string"||!/^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(m)||typeof C!="string"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(C))return y(400,{error:"Invalid payload"});if(!Object.hasOwn(t,m)||/^(drafts|versions)\./.test(C))return y(400,{error:"Unsupported document"});let P=T(r,{types:t[m],ids:[C]});try{for(let p of P)(0,_.revalidateTag)(p,{expire:0})}catch{return y(500,{error:"Could not revalidate"})}return y(200,{revalidated:!0})};return Object.freeze({POST:l,GET:l,HEAD:l,PUT:l,PATCH:l,DELETE:l,OPTIONS:l})}0&&(module.exports={createNextCmsReader,createRevalidateRoute});
1
+ "use strict";var R=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var F=(e,r)=>{for(var t in r)R(e,t,{get:r[t],enumerable:!0})},H=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of z(r))!N.call(e,o)&&o!==t&&R(e,o,{get:()=>r[o],enumerable:!(n=j(r,o))||n.enumerable});return e};var $=e=>H(R({},"__esModule",{value:!0}),e);var K={};F(K,{createNextCmsReader:()=>O,createRevalidateRoute:()=>D});module.exports=$(K);var de=require("server-only");var U=/^[A-Za-z][A-Za-z0-9_]{0,63}$/,L=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,Z=/^[a-z0-9]{6,12}\.[a-z][a-z0-9_-]{0,63}$/;function k(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 n of r)if(typeof n!="string"||!U.test(n))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 n of t??[])if(typeof n!="string"||!L.test(n)||/^(drafts|versions)\./.test(n))throw new TypeError("Invalid CMS document ID");if(new Set(r).size+new Set(t).size>128)throw new TypeError("Too many CMS tags");return Object.freeze({types:Object.freeze(r),...t===void 0?{}:{ids:Object.freeze(t)}})}function E(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 t={};for(let n of Reflect.ownKeys(r)){let o=Object.getOwnPropertyDescriptor(r,n);if(typeof n!="string"||!o||!Object.hasOwn(o,"value")||!o.enumerable)throw new TypeError("CMS params must be plain JSON scalars");let a=o.value;if(!(a===null||typeof a=="string"||typeof a=="boolean"||typeof a=="number"&&Number.isFinite(a)))throw new TypeError("CMS params must be plain JSON scalars");Object.defineProperty(t,n,{value:a,enumerable:!0})}return Object.freeze({name:e.name,query:e.query,params:Object.freeze(t),dependencies:k(e.dependencies),resolve:e.resolve})}function T(e,r){if(typeof e!="string"||e.length>77||!Z.test(e))throw new TypeError("Invalid CMS scope");let t=k(r),n=[...[...new Set(t.types)].sort().map(o=>`cms:${e}:type:${o}`),...[...new Set(t.ids??[])].sort().map(o=>`cms:${e}:id:${o}`)];return Object.freeze(n)}function A(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 S(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 t=e.adapter;T(t.scope,{types:["ScopeValidation"]});let n=o=>{try{e.onDiagnostic?e.onDiagnostic(o):console.warn(JSON.stringify(o))}catch{}};return{async read(o,a){let s,l,d;try{if(s=E(o),d=T(t.scope,s.dependencies),!a||!Object.hasOwn(a,"fallback"))throw new TypeError;l=A(s.resolve(null,a.fallback))}catch{throw new TypeError("Invalid CMS query or fallback configuration")}let p=(g,u,f)=>(n({event:"cms.fallback",query:s.name,reason:g,fields:["$"],...u===void 0?{}:{status:u},...f?{warnings:f}:{}}),{data:l.data,source:"fallback",fallbackFields:["$"],reason:g,...f?{warnings:f}:{}}),i;try{i=await t.read({name:s.name,query:s.query,params:s.params},{tags:d,revalidateSeconds:r})}catch{return p("network")}if(!i.ok){let u=["configuration","network","timeout","rate-limit","upstream","plan-limit","permission","malformed"].includes(i.reason)?i.reason:"malformed",f=Number.isInteger(i.status)&&(i.status??0)>=100&&(i.status??0)<=599?i.status:void 0;return p(u,f)}if(i.value===null||i.value===void 0)return p("missing");let c;try{c=A(s.resolve(i.value,a.fallback))}catch{return p("malformed")}return c.fallbackFields.includes("$")?{...p("invalid-field",void 0,c.warnings),data:c.data}:c.fallbackFields.length>0?(n({event:"cms.partial-fallback",query:s.name,reason:"invalid-field",fields:c.fallbackFields,...c.warnings?{warnings:c.warnings}:{}}),{...c,source:"mixed",reason:"invalid-field"}):{...c,source:"cms"}}}}var O=S;var _=require("next/cache.js");var h="sanity-webhook-signature",Q=/^t=(\d+)[, ]+v1=([^, ]+)$/;var I=new TextEncoder;function V(e){return crypto.subtle.importKey("raw",I.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}function B(e){if(!/^[A-Za-z0-9_-]+={0,2}$/.test(e))return null;let r=e.replace(/-/g,"+").replace(/_/g,"/");try{let t=atob(r),n=new Uint8Array(t.length);for(let o=0;o<t.length;o+=1)n[o]=t.charCodeAt(o);return n}catch{return null}}async function x(e){let{secret:r,rawBody:t,headers:n}=e,o=e.now??Date.now(),a=e.toleranceMs??3e5;if(!r||r.length===0)return{ok:!1,reason:"no-secret"};let s=n.get(h);if(!s)return{ok:!1,reason:"no-signature"};let l=Q.exec(s.trim());if(l===null)return{ok:!1,reason:"malformed-signature"};let d=Number(l[1]),p=l[2]??"";if(!Number.isSafeInteger(d))return{ok:!1,reason:"malformed-signature"};if(d<16094592e5)return{ok:!1,reason:"stale-timestamp"};if(Math.abs(o-d)>a)return{ok:!1,reason:"stale-timestamp"};let i=B(p);if(i===null)return{ok:!1,reason:"malformed-signature"};let c=await V(r);return await crypto.subtle.verify("HMAC",c,i,I.encode(`${d}.${t}`))?{ok:!0}:{ok:!1,reason:"bad-signature"}}var q=16*1024,W=1500,Y=new TextEncoder;function y(e,r,t={},n=!1){return new Response(n?null:JSON.stringify(r),{status:e,headers:{"Content-Type":"application/json","Cache-Control":"no-store",...t}})}function J(e,r){if(!r||typeof r!="object"||Array.isArray(r)||Object.keys(r).length===0)throw new TypeError("Invalid CMS invalidation mapping");let t=Object.create(null);for(let n of Reflect.ownKeys(r)){let o=Object.getOwnPropertyDescriptor(r,n);if(typeof n!="string"||!o?.enumerable||!Object.hasOwn(o,"value"))throw new TypeError("Invalid CMS invalidation mapping");let a=o.value;if(!Array.isArray(a)||!a.includes(n))throw new TypeError("Invalid CMS invalidation mapping");T(e,{types:a,ids:["validation"]}),t[n]=Object.freeze([...a])}for(let n of Object.values(t))if(n.some(o=>!Object.hasOwn(t,o)))throw new TypeError("Invalid CMS invalidation mapping");return Object.freeze(t)}function M(e){return typeof e=="string"&&e.trim()!==""&&Y.encode(e).byteLength>=32}var b=class extends Error{constructor(t){super("Invalid CMS webhook body");this.status=t}status};async function G(e){let r=e.body?.getReader();if(!r)return"";let t=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}),n,o=new Promise((a,s)=>{n=setTimeout(()=>s(new b(400)),W)});try{let a=0,s="";for(;;){let{done:l,value:d}=await Promise.race([r.read(),o]);if(l)return s+t.decode();if(a+=d.byteLength,a>q)throw new b(413);s+=t.decode(d,{stream:!0})}}catch(a){throw r.cancel().catch(()=>{}),a}finally{clearTimeout(n),r.releaseLock()}}function D(e){let r=e.scope,t=J(r,e.typeToTags),n=e.secretEnv??"SANITY_REVALIDATE_SECRET",o=e.previousSecretEnv??"SANITY_REVALIDATE_SECRET_PREVIOUS",a=e.env??(()=>process.env),s=e.now??Date.now,l=async d=>{if(d.method!=="POST")return y(405,{error:"Method not allowed"},{Allow:"POST"},d.method==="HEAD");let p,i;try{let m=a(),v=m[n],w=m[o];if(!M(v)||w!==void 0&&!M(w))throw new Error;p=v,i=w}catch{return y(503,{error:"COULD NOT ANSWER: revalidation configuration unavailable"})}let c=d.headers.get(h);if(!c||c.length>512||!/^t=\d+[, ]+v1=[A-Za-z0-9_-]+={0,2}$/.test(c.trim()))return y(401,{error:"Unauthorized"});let g;try{g=await G(d)}catch(m){return m instanceof b&&m.status===413?y(413,{error:"Payload too large"}):y(400,{error:"Invalid body"})}try{let m=s();if(!Number.isFinite(m))throw new Error;if(!(await Promise.all([p,...i===void 0?[]:[i]].map(w=>x({secret:w,rawBody:g,headers:d.headers,now:m})))).some(w=>w.ok))return y(401,{error:"Unauthorized"})}catch{return y(401,{error:"Unauthorized"})}let u;try{u=JSON.parse(g)}catch{return y(400,{error:"Invalid payload"})}if(!u||typeof u!="object"||Array.isArray(u)||Object.keys(u).length!==2||!Object.hasOwn(u,"_type")||!Object.hasOwn(u,"_id"))return y(400,{error:"Invalid payload"});let{_type:f,_id:C}=u;if(typeof f!="string"||!/^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(f)||typeof C!="string"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(C))return y(400,{error:"Invalid payload"});if(!Object.hasOwn(t,f)||/^(drafts|versions)\./.test(C))return y(400,{error:"Unsupported document"});let P=T(r,{types:t[f],ids:[C]});try{for(let m of P)(0,_.revalidateTag)(m,{expire:0})}catch{return y(500,{error:"Could not revalidate"})}return y(200,{revalidated:!0})};return Object.freeze({POST:l,GET:l,HEAD:l,PUT:l,PATCH:l,DELETE:l,OPTIONS:l})}0&&(module.exports={createNextCmsReader,createRevalidateRoute});
2
2
  //# sourceMappingURL=next.cjs.map