nimbus-docs 0.1.3 → 0.1.5

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/dist/schemas.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { z } from "astro/zod";
2
+ import * as astro_content0 from "astro:content";
2
3
 
3
4
  //#region src/schemas.d.ts
4
5
  interface DocSchemaConfig {
@@ -9,89 +10,72 @@ interface DocSchemaConfig {
9
10
  * Build a customizable docs schema. Use this when composing schemas outside
10
11
  * the `docsCollection()` factory (e.g. multiple docs collections with
11
12
  * different shapes).
13
+ *
14
+ * For typed Astro `image()` fields or per-collection field narrowing, use
15
+ * the richer `defineSchema(ctx => ...)` factory instead.
12
16
  */
13
- declare function defineDocSchema(config?: DocSchemaConfig): z.ZodObject<{
14
- title: z.ZodString;
15
- description: z.ZodOptional<z.ZodString>;
16
- template: z.ZodDefault<z.ZodEnum<{
17
- doc: "doc";
18
- splash: "splash";
19
- }>>;
20
- sidebar: z.ZodOptional<z.ZodObject<{
21
- order: z.ZodOptional<z.ZodNumber>;
22
- label: z.ZodOptional<z.ZodString>;
23
- badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
24
- text: z.ZodString;
25
- variant: z.ZodDefault<z.ZodEnum<{
26
- success: "success";
27
- default: "default";
28
- info: "info";
29
- note: "note";
30
- tip: "tip";
31
- warning: "warning";
32
- caution: "caution";
33
- danger: "danger";
34
- }>>;
35
- }, z.core.$strip>]>>;
36
- hidden: z.ZodOptional<z.ZodBoolean>;
37
- hideChildren: z.ZodOptional<z.ZodBoolean>;
38
- }, z.core.$strip>>;
39
- hero: z.ZodOptional<z.ZodObject<{
40
- title: z.ZodOptional<z.ZodString>;
41
- tagline: z.ZodOptional<z.ZodString>;
42
- actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
43
- text: z.ZodString;
44
- link: z.ZodString;
45
- variant: z.ZodDefault<z.ZodEnum<{
46
- primary: "primary";
47
- secondary: "secondary";
48
- outline: "outline";
49
- }>>;
50
- icon: z.ZodOptional<z.ZodString>;
51
- }, z.core.$strip>>>;
52
- }, z.core.$strip>>;
53
- head: z.ZodDefault<z.ZodArray<z.ZodObject<{
54
- tag: z.ZodEnum<{
55
- link: "link";
56
- meta: "meta";
57
- script: "script";
58
- style: "style";
59
- }>;
60
- attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
61
- content: z.ZodOptional<z.ZodString>;
62
- }, z.core.$strip>>>;
63
- draft: z.ZodDefault<z.ZodBoolean>;
64
- noindex: z.ZodDefault<z.ZodBoolean>;
65
- llms: z.ZodDefault<z.ZodBoolean>;
66
- aiDeprioritize: z.ZodDefault<z.ZodBoolean>;
67
- pagefind: z.ZodDefault<z.ZodBoolean>;
68
- tableOfContents: z.ZodOptional<z.ZodObject<{
69
- minHeadingLevel: z.ZodDefault<z.ZodNumber>;
70
- maxHeadingLevel: z.ZodDefault<z.ZodNumber>;
71
- }, z.core.$strip>>;
72
- lastUpdated: z.ZodOptional<z.ZodCoercedDate<unknown>>;
73
- socialImage: z.ZodOptional<z.ZodString>;
74
- prev: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
75
- link: z.ZodOptional<z.ZodString>;
76
- label: z.ZodOptional<z.ZodString>;
77
- }, z.core.$strip>, z.ZodLiteral<false>]>>;
78
- next: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
79
- link: z.ZodOptional<z.ZodString>;
80
- label: z.ZodOptional<z.ZodString>;
81
- }, z.core.$strip>, z.ZodLiteral<false>]>>;
82
- previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
83
- }, z.core.$strip> | z.ZodObject<{
84
- [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
85
- }, z.core.$strip>;
17
+ declare function defineDocSchema(config?: DocSchemaConfig): z.ZodObject<Readonly<{
18
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
19
+ }>, z.core.$loose>;
20
+ /**
21
+ * Factory options for `defineSchema`.
22
+ *
23
+ * - `extend`: additional fields merged into the framework schema. Use
24
+ * this for user-defined frontmatter (`author`, `tags`, `cover`).
25
+ * - `narrow`: replaces framework fields with tighter types within this
26
+ * collection. Use when a collection has stricter rules — e.g.
27
+ * `{ mode: z.literal("doc") }` says no landing pages in this collection.
28
+ */
29
+ interface DefineSchemaOptions {
30
+ extend?: z.ZodTypeAny;
31
+ narrow?: Record<string, z.ZodTypeAny>;
32
+ }
33
+ /**
34
+ * Build a typed docs schema with access to the Astro `SchemaContext`.
35
+ * Use this when you want typed image fields (`ctx.image()`), per-
36
+ * collection narrowing of framework fields, or both. The simpler
37
+ * `defineDocSchema({ fields })` factory is still available for the
38
+ * common case of just adding fields.
39
+ *
40
+ * import { defineCollection } from "astro:content";
41
+ * import { z } from "astro/zod";
42
+ * import { defineSchema } from "nimbus-docs/schemas";
43
+ *
44
+ * export const collections = {
45
+ * docs: defineCollection({
46
+ * loader: ...,
47
+ * schema: defineSchema((ctx) => ({
48
+ * extend: z.object({
49
+ * cover: ctx.image().optional(),
50
+ * author: z.string().optional(),
51
+ * }),
52
+ * narrow: {
53
+ * mode: z.literal("doc"), // no landing pages here
54
+ * },
55
+ * })),
56
+ * }),
57
+ * };
58
+ */
59
+ declare function defineSchema(factory: (ctx: astro_content0.SchemaContext) => DefineSchemaOptions): (ctx: astro_content0.SchemaContext) => z.ZodObject<Readonly<{
60
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
61
+ }>, z.core.$loose> | z.ZodIntersection<z.ZodObject<any, z.core.$strip>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
86
62
  /** Default docs schema. Equivalent to `defineDocSchema()`. */
87
- declare const docsSchema: z.ZodObject<{
63
+ declare const docsSchema: z.ZodObject<Readonly<{
64
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
65
+ }>, z.core.$loose>;
66
+ /** Schema for partials (`<Render file="..." />` snippets). */
67
+ declare const partialsSchema: z.ZodDefault<z.ZodObject<{
68
+ params: z.ZodOptional<z.ZodArray<z.ZodString>>;
69
+ }, z.core.$strip>>;
70
+ /** Docs frontmatter, framework fields type-checked, extra keys allowed. */
71
+ declare const lenientDocsSchema: z.ZodObject<{
88
72
  title: z.ZodString;
89
73
  description: z.ZodOptional<z.ZodString>;
90
- template: z.ZodDefault<z.ZodEnum<{
74
+ mode: z.ZodDefault<z.ZodEnum<{
91
75
  doc: "doc";
92
- splash: "splash";
76
+ custom: "custom";
93
77
  }>>;
94
- sidebar: z.ZodOptional<z.ZodObject<{
78
+ sidebar: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
95
79
  order: z.ZodOptional<z.ZodNumber>;
96
80
  label: z.ZodOptional<z.ZodString>;
97
81
  badge: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -109,40 +93,37 @@ declare const docsSchema: z.ZodObject<{
109
93
  }, z.core.$strip>]>>;
110
94
  hidden: z.ZodOptional<z.ZodBoolean>;
111
95
  hideChildren: z.ZodOptional<z.ZodBoolean>;
112
- }, z.core.$strip>>;
113
- hero: z.ZodOptional<z.ZodObject<{
114
- title: z.ZodOptional<z.ZodString>;
115
- tagline: z.ZodOptional<z.ZodString>;
116
- actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
117
- text: z.ZodString;
118
- link: z.ZodString;
119
- variant: z.ZodDefault<z.ZodEnum<{
120
- primary: "primary";
121
- secondary: "secondary";
122
- outline: "outline";
123
- }>>;
124
- icon: z.ZodOptional<z.ZodString>;
125
- }, z.core.$strip>>>;
126
- }, z.core.$strip>>;
96
+ }, z.core.$strip>]>>;
127
97
  head: z.ZodDefault<z.ZodArray<z.ZodObject<{
128
98
  tag: z.ZodEnum<{
129
- link: "link";
130
99
  meta: "meta";
100
+ link: "link";
131
101
  script: "script";
132
102
  style: "style";
133
103
  }>;
134
104
  attrs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
135
105
  content: z.ZodOptional<z.ZodString>;
136
106
  }, z.core.$strip>>>;
107
+ banner: z.ZodOptional<z.ZodObject<{
108
+ content: z.ZodString;
109
+ type: z.ZodOptional<z.ZodEnum<{
110
+ note: "note";
111
+ tip: "tip";
112
+ caution: "caution";
113
+ danger: "danger";
114
+ }>>;
115
+ dismissible: z.ZodOptional<z.ZodObject<{
116
+ id: z.ZodString;
117
+ days: z.ZodOptional<z.ZodNumber>;
118
+ }, z.core.$strip>>;
119
+ }, z.core.$strip>>;
137
120
  draft: z.ZodDefault<z.ZodBoolean>;
138
121
  noindex: z.ZodDefault<z.ZodBoolean>;
139
- llms: z.ZodDefault<z.ZodBoolean>;
140
- aiDeprioritize: z.ZodDefault<z.ZodBoolean>;
141
- pagefind: z.ZodDefault<z.ZodBoolean>;
142
- tableOfContents: z.ZodOptional<z.ZodObject<{
122
+ searchable: z.ZodOptional<z.ZodBoolean>;
123
+ tableOfContents: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
143
124
  minHeadingLevel: z.ZodDefault<z.ZodNumber>;
144
125
  maxHeadingLevel: z.ZodDefault<z.ZodNumber>;
145
- }, z.core.$strip>>;
126
+ }, z.core.$strip>]>>;
146
127
  lastUpdated: z.ZodOptional<z.ZodCoercedDate<unknown>>;
147
128
  socialImage: z.ZodOptional<z.ZodString>;
148
129
  prev: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -154,13 +135,11 @@ declare const docsSchema: z.ZodObject<{
154
135
  label: z.ZodOptional<z.ZodString>;
155
136
  }, z.core.$strip>, z.ZodLiteral<false>]>>;
156
137
  previousSlug: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
157
- }, z.core.$strip> | z.ZodObject<{
158
- [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
159
- }, z.core.$strip>;
160
- /** Schema for partials (`<Render file="..." />` snippets). */
161
- declare const partialsSchema: z.ZodDefault<z.ZodObject<{
138
+ }, z.core.$loose>;
139
+ /** Partials frontmatter, framework fields type-checked, extra keys allowed. */
140
+ declare const lenientPartialsSchema: z.ZodObject<{
162
141
  params: z.ZodOptional<z.ZodArray<z.ZodString>>;
163
- }, z.core.$strip>>;
142
+ }, z.core.$loose>;
164
143
  /** One row in a component's `props` frontmatter array. */
165
144
  declare const componentPropSchema: z.ZodObject<{
166
145
  name: z.ZodString;
@@ -183,5 +162,5 @@ declare const componentsSchema: z.ZodObject<{
183
162
  }, z.core.$strip>>>;
184
163
  }, z.core.$strip>;
185
164
  //#endregion
186
- export { ComponentProp, DocSchemaConfig, componentsSchema, defineDocSchema, docsSchema, partialsSchema };
165
+ export { ComponentProp, DefineSchemaOptions, DocSchemaConfig, componentsSchema, defineDocSchema, defineSchema, docsSchema, lenientDocsSchema, lenientPartialsSchema, partialsSchema };
187
166
  //# sourceMappingURL=schemas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","names":[],"sources":["../src/schemas.ts"],"mappings":";;;UAgBiB,eAAA;;EAEf,MAAA,GAAS,MAAA,SAAe,CAAA,CAAE,UAAA;AAAA;;;;;;iBA2KZ,eAAA,CAAgB,MAAA,GAAQ,eAAA,GAAoB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAS/C,UAAA,EAAU,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAGV,cAAA,EAAc,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;;;;cAkBrB,mBAAA,EAAmB,CAAA,CAAA,SAAA;;;;;;;KAQb,aAAA,GAAgB,CAAA,CAAE,KAAA,QAAa,mBAAA;;cAG9B,gBAAA,EAAgB,CAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"schemas.d.ts","names":[],"sources":["../src/schemas.ts"],"mappings":";;;;UAiBiB,eAAA;EA6Oc;EA3O7B,MAAA,GAAS,MAAA,SAAe,CAAA,CAAE,UAAA;AAAA;;;;;;;;;iBA2OZ,eAAA,CAAgB,MAAA,GAAQ,eAAA,GAAoB,CAAA,CAAA,SAAA,CAAA,QAAA;EAAA;;;;;;;;;;;UAkB3C,mBAAA;EACf,MAAA,GAAS,CAAA,CAAE,UAAA;EACX,MAAA,GAAS,MAAA,SAAe,CAAA,CAAE,UAAA;AAAA;AAF5B;;;;;;;;;;;;;;;;;AA+BA;;;;;;;;;AA/BA,iBA+BgB,YAAA,CACd,OAAA,GAAU,GAAA,EADgB,cAAA,CACa,aAAA,KAAkB,mBAAA,IAEjD,GAAA,EAFoE,cAAA,CAEvC,aAAA,KAAa,CAAA,CAAA,SAAA,CAAA,QAAA;EAAA;;;cA8BvC,UAAA,EAAU,CAAA,CAAA,SAAA,CAAA,QAAA;EAAA;;;cAWV,cAAA,EAAc,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;;;;cAad,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAGjB,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;cAU5B,mBAAA,EAAmB,CAAA,CAAA,SAAA;;;;;;;KAQb,aAAA,GAAgB,CAAA,CAAE,KAAA,QAAa,mBAAA;;cAG9B,gBAAA,EAAgB,CAAA,CAAA,SAAA"}
package/dist/schemas.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { t as withStrictKeys } from "./strict-keys-BiXiT3pq.js";
1
2
  import { z } from "astro/zod";
2
3
 
3
4
  //#region src/schemas.ts
@@ -27,29 +28,14 @@ const sidebarBadgeSchema = z.union([z.string(), z.object({
27
28
  "danger"
28
29
  ], { error: "\"variant\" must be one of: default, info, note, success, tip, warning, caution, danger" }).default("default")
29
30
  })]);
30
- const sidebarFrontmatterSchema = z.object({
31
+ const sidebarSchema = z.object({
31
32
  order: z.number({ error: "\"sidebar.order\" must be a number" }).optional(),
32
33
  label: z.string({ error: "\"sidebar.label\" must be a string" }).optional(),
33
34
  badge: sidebarBadgeSchema.optional(),
34
35
  hidden: z.boolean({ error: "\"sidebar.hidden\" must be true or false" }).optional(),
35
36
  hideChildren: z.boolean({ error: "\"sidebar.hideChildren\" must be true or false" }).optional()
36
- }).optional();
37
- const heroActionSchema = z.object({
38
- text: z.string({ error: "hero action needs a \"text\" field" }),
39
- link: z.string({ error: "hero action needs a \"link\" field" }),
40
- variant: z.enum([
41
- "primary",
42
- "secondary",
43
- "outline"
44
- ], { error: "hero action \"variant\" must be \"primary\", \"secondary\", or \"outline\"" }).default("primary"),
45
- icon: z.string().optional()
46
37
  });
47
- const heroSchema = z.object({
48
- title: z.string().optional(),
49
- tagline: z.string().optional(),
50
- actions: z.array(heroActionSchema).optional()
51
- }).optional();
52
- const prevNextFrontmatterSchema = z.union([
38
+ const prevNextSchema = z.union([
53
39
  z.string(),
54
40
  z.object({
55
41
  link: z.string().optional(),
@@ -67,27 +53,81 @@ const headElementSchema = z.object({
67
53
  attrs: z.record(z.string(), z.string()).default({}),
68
54
  content: z.string().optional()
69
55
  });
56
+ const bannerSchema = z.object({
57
+ content: z.string({ error: "banner \"content\" must be a string" }),
58
+ type: z.enum([
59
+ "note",
60
+ "tip",
61
+ "caution",
62
+ "danger"
63
+ ], { error: "banner \"type\" must be one of: note, tip, caution, danger" }).optional(),
64
+ dismissible: z.object({
65
+ id: z.string({ error: "banner \"dismissible.id\" must be a string — a stable identifier you bump when banner content meaningfully changes" }),
66
+ days: z.number({ error: "banner \"dismissible.days\" must be a number" }).optional()
67
+ }).optional()
68
+ });
69
+ /**
70
+ * Frontmatter keys that used to exist but no longer do. When user content
71
+ * still carries one of these, Zod's default `.strip()` behavior would
72
+ * silently drop it — the page would build, but with subtly different
73
+ * behavior (the old toggle just disappears). That's a confusing failure
74
+ * mode for an authoring contract.
75
+ *
76
+ * `withUnknownKeyCheck` (below) consults this map. Hits get the friendly
77
+ * migration message verbatim; everything else falls through to a generic
78
+ * "Unknown frontmatter key" error so typos don't sneak past either.
79
+ *
80
+ * Entries removed in the v0 → v1 cleanup:
81
+ *
82
+ * - `template` → `mode`: same shape, but `"splash"` is now `"custom"`.
83
+ * - `pagefind` → `searchable`: same boolean; default now derives from
84
+ * `noindex` (a non-crawlable page is non-searchable by default).
85
+ * - `llms`: removed. All published pages are listed in `/llms.txt`; the
86
+ * escape hatch is `noindex: true`.
87
+ * - `aiDeprioritize`: removed. The framework no longer emits an
88
+ * agent-downrank signal.
89
+ * - `hero`: removed. Compose the hero in MDX body with user-owned
90
+ * components instead of a frontmatter contract.
91
+ */
92
+ const REMOVED_FRONTMATTER_KEYS = {
93
+ template: "was renamed to \"mode\". Replace `template: \"doc\"` with `mode: \"doc\"`, and `template: \"splash\"` with `mode: \"custom\"`.",
94
+ pagefind: "was renamed to \"searchable\". Same boolean shape; the default now derives from `noindex` (a non-crawlable page is non-searchable unless you set `searchable: true` explicitly).",
95
+ llms: "was removed. Every published page is now listed in /llms.txt; use `noindex: true` to keep a page out of both search engines and the LLM index.",
96
+ aiDeprioritize: "was removed. The framework no longer emits an agent-downrank signal. If you want a page hidden from agents, use `noindex: true`.",
97
+ hero: "was removed. Compose your hero in the MDX body using user-owned components; there is no longer a `hero` frontmatter contract."
98
+ };
99
+ /**
100
+ * Apply this AFTER any `.extend()` so user-added fields are recognized
101
+ * as valid. Wraps the schema in `.passthrough().superRefine()` so removed
102
+ * keys raise a guided migration error; other unknown keys raise a
103
+ * generic error pointing at `defineSchema({ extend: ... })`.
104
+ */
105
+ function withFrontmatterKeyCheck(schema) {
106
+ return withStrictKeys(schema, {
107
+ removedKeys: REMOVED_FRONTMATTER_KEYS,
108
+ contextLabel: "Frontmatter key",
109
+ unknownHint: (key) => `If you meant to add a custom field, declare it in your collection's schema via \`defineSchema({ extend: z.object({ ${key}: ... }) })\`.`
110
+ });
111
+ }
70
112
  function baseDocSchema() {
71
113
  return z.object({
72
114
  title: z.string({ error: (iss) => iss.input === void 0 ? "Missing required \"title\" in frontmatter. Every doc needs:\n\n ---\n title: \"Your Page Title\"\n ---" : `"title" must be a string, received ${typeof iss.input}` }),
73
115
  description: z.string({ error: "\"description\" must be a string" }).optional(),
74
- template: z.enum(["doc", "splash"], { error: "\"template\" must be \"doc\" or \"splash\"" }).default("doc"),
75
- sidebar: sidebarFrontmatterSchema,
76
- hero: heroSchema,
116
+ mode: z.enum(["doc", "custom"], { error: "\"mode\" must be \"doc\" or \"custom\"" }).default("doc"),
117
+ sidebar: z.union([z.literal(false), sidebarSchema]).optional(),
77
118
  head: z.array(headElementSchema).default([]),
119
+ banner: bannerSchema.optional(),
78
120
  draft: z.boolean({ error: "\"draft\" must be true or false" }).default(false),
79
121
  noindex: z.boolean({ error: "\"noindex\" must be true or false" }).default(false),
80
- llms: z.boolean({ error: "\"llms\" must be true or false" }).default(true),
81
- aiDeprioritize: z.boolean({ error: "\"aiDeprioritize\" must be true or false" }).default(false),
82
- pagefind: z.boolean({ error: "\"pagefind\" must be true or false" }).default(true),
83
- tableOfContents: z.object({
122
+ searchable: z.boolean({ error: "\"searchable\" must be true or false" }).optional(),
123
+ tableOfContents: z.union([z.literal(false), z.object({
84
124
  minHeadingLevel: z.number({ error: "\"minHeadingLevel\" must be a number (1-6)" }).int().min(1).max(6).default(2),
85
125
  maxHeadingLevel: z.number({ error: "\"maxHeadingLevel\" must be a number (1-6)" }).int().min(1).max(6).default(3)
86
- }).refine((v) => v.minHeadingLevel <= v.maxHeadingLevel, { message: "minHeadingLevel must be <= maxHeadingLevel" }).optional(),
126
+ }).refine((v) => v.minHeadingLevel <= v.maxHeadingLevel, { message: "minHeadingLevel must be <= maxHeadingLevel" })]).optional(),
87
127
  lastUpdated: z.coerce.date({ error: "\"lastUpdated\" must be a valid date (e.g. 2024-01-15)" }).optional(),
88
128
  socialImage: z.string({ error: "\"socialImage\" must be a string (path or URL)" }).optional(),
89
- prev: prevNextFrontmatterSchema,
90
- next: prevNextFrontmatterSchema,
129
+ prev: prevNextSchema,
130
+ next: prevNextSchema,
91
131
  previousSlug: z.union([z.string(), z.array(z.string())], { error: "\"previousSlug\" must be a string or array of strings" }).optional()
92
132
  });
93
133
  }
@@ -95,16 +135,59 @@ function baseDocSchema() {
95
135
  * Build a customizable docs schema. Use this when composing schemas outside
96
136
  * the `docsCollection()` factory (e.g. multiple docs collections with
97
137
  * different shapes).
138
+ *
139
+ * For typed Astro `image()` fields or per-collection field narrowing, use
140
+ * the richer `defineSchema(ctx => ...)` factory instead.
98
141
  */
99
142
  function defineDocSchema(config = {}) {
100
143
  const base = baseDocSchema();
101
- if (config.fields) return base.extend(config.fields);
102
- return base;
144
+ return withFrontmatterKeyCheck(config.fields ? base.extend(config.fields) : base);
145
+ }
146
+ /**
147
+ * Build a typed docs schema with access to the Astro `SchemaContext`.
148
+ * Use this when you want typed image fields (`ctx.image()`), per-
149
+ * collection narrowing of framework fields, or both. The simpler
150
+ * `defineDocSchema({ fields })` factory is still available for the
151
+ * common case of just adding fields.
152
+ *
153
+ * import { defineCollection } from "astro:content";
154
+ * import { z } from "astro/zod";
155
+ * import { defineSchema } from "nimbus-docs/schemas";
156
+ *
157
+ * export const collections = {
158
+ * docs: defineCollection({
159
+ * loader: ...,
160
+ * schema: defineSchema((ctx) => ({
161
+ * extend: z.object({
162
+ * cover: ctx.image().optional(),
163
+ * author: z.string().optional(),
164
+ * }),
165
+ * narrow: {
166
+ * mode: z.literal("doc"), // no landing pages here
167
+ * },
168
+ * })),
169
+ * }),
170
+ * };
171
+ */
172
+ function defineSchema(factory) {
173
+ return (ctx) => {
174
+ const { extend, narrow } = factory(ctx);
175
+ let schema = baseDocSchema();
176
+ if (narrow) schema = schema.extend(narrow);
177
+ if (extend) if (extend instanceof z.ZodObject) schema = schema.merge(extend);
178
+ else return schema.and(extend);
179
+ return withFrontmatterKeyCheck(schema);
180
+ };
103
181
  }
104
182
  /** Default docs schema. Equivalent to `defineDocSchema()`. */
105
183
  const docsSchema = defineDocSchema();
184
+ const partialsObjectSchema = z.object({ params: z.array(z.string()).optional() });
106
185
  /** Schema for partials (`<Render file="..." />` snippets). */
107
- const partialsSchema = z.object({ params: z.array(z.string()).optional() }).default({});
186
+ const partialsSchema = partialsObjectSchema.default({});
187
+ /** Docs frontmatter, framework fields type-checked, extra keys allowed. */
188
+ const lenientDocsSchema = baseDocSchema().passthrough();
189
+ /** Partials frontmatter, framework fields type-checked, extra keys allowed. */
190
+ const lenientPartialsSchema = partialsObjectSchema.passthrough();
108
191
  /** One row in a component's `props` frontmatter array. */
109
192
  const componentPropSchema = z.object({
110
193
  name: z.string({ error: "prop needs a \"name\"" }),
@@ -121,5 +204,5 @@ const componentsSchema = z.object({
121
204
  });
122
205
 
123
206
  //#endregion
124
- export { componentsSchema, defineDocSchema, docsSchema, partialsSchema };
207
+ export { componentsSchema, defineDocSchema, defineSchema, docsSchema, lenientDocsSchema, lenientPartialsSchema, partialsSchema };
125
208
  //# sourceMappingURL=schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["/**\n * Content schemas for Nimbus.\n *\n * `docsSchema` is the default frontmatter contract for the `docs` collection.\n * `partialsSchema` is the contract for `<Render file=\"...\" />` partials.\n * `defineDocSchema(config)` returns a customizable schema for advanced users\n * composing schemas outside the `docsCollection()` factory.\n *\n * Error messages target content authors, not framework developers.\n * Astro 6 ships Zod v4 via `astro/zod`. The v4 API uses a single `error`\n * field on every schema constructor — NOT v3's `required_error` /\n * `invalid_type_error` / `errorMap`.\n */\n\nimport { z } from \"astro/zod\";\n\nexport interface DocSchemaConfig {\n /** Additional frontmatter fields merged into the default schema. */\n fields?: Record<string, z.ZodTypeAny>;\n}\n\n// ---------------------------------------------------------------------------\n// Building blocks\n// ---------------------------------------------------------------------------\n\nconst sidebarBadgeSchema = z.union([\n z.string(),\n z.object({\n text: z.string({ error: 'sidebar badge needs a \"text\" field' }),\n variant: z\n .enum(\n [\"default\", \"info\", \"note\", \"success\", \"tip\", \"warning\", \"caution\", \"danger\"],\n {\n error:\n '\"variant\" must be one of: default, info, note, success, tip, warning, caution, danger',\n },\n )\n .default(\"default\"),\n }),\n]);\n\nconst sidebarFrontmatterSchema = z\n .object({\n order: z.number({ error: '\"sidebar.order\" must be a number' }).optional(),\n label: z.string({ error: '\"sidebar.label\" must be a string' }).optional(),\n badge: sidebarBadgeSchema.optional(),\n hidden: z.boolean({ error: '\"sidebar.hidden\" must be true or false' }).optional(),\n hideChildren: z\n .boolean({ error: '\"sidebar.hideChildren\" must be true or false' })\n .optional(),\n })\n .optional();\n\nconst heroActionSchema = z.object({\n text: z.string({ error: 'hero action needs a \"text\" field' }),\n link: z.string({ error: 'hero action needs a \"link\" field' }),\n variant: z\n .enum([\"primary\", \"secondary\", \"outline\"], {\n error: 'hero action \"variant\" must be \"primary\", \"secondary\", or \"outline\"',\n })\n .default(\"primary\"),\n icon: z.string().optional(),\n});\n\nconst heroSchema = z\n .object({\n title: z.string().optional(),\n tagline: z.string().optional(),\n actions: z.array(heroActionSchema).optional(),\n })\n .optional();\n\nconst prevNextFrontmatterSchema = z\n .union([\n z.string(),\n z.object({ link: z.string().optional(), label: z.string().optional() }),\n z.literal(false),\n ])\n .optional();\n\nconst headElementSchema = z.object({\n tag: z.enum([\"meta\", \"link\", \"script\", \"style\"], {\n error: 'head element \"tag\" must be \"meta\", \"link\", \"script\", or \"style\"',\n }),\n attrs: z.record(z.string(), z.string()).default({}),\n content: z.string().optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Base docs schema\n// ---------------------------------------------------------------------------\n\nfunction baseDocSchema() {\n return z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing required \"title\" in frontmatter. Every doc needs:\\n\\n ---\\n title: \"Your Page Title\"\\n ---'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n description: z.string({ error: '\"description\" must be a string' }).optional(),\n template: z\n .enum([\"doc\", \"splash\"], {\n error: '\"template\" must be \"doc\" or \"splash\"',\n })\n .default(\"doc\"),\n sidebar: sidebarFrontmatterSchema,\n hero: heroSchema,\n head: z.array(headElementSchema).default([]),\n draft: z.boolean({ error: '\"draft\" must be true or false' }).default(false),\n noindex: z.boolean({ error: '\"noindex\" must be true or false' }).default(false),\n /** Include this page in llms.txt and AI consumption indexes */\n llms: z.boolean({ error: '\"llms\" must be true or false' }).default(true),\n /** Signal AI crawlers to deprioritize this page */\n aiDeprioritize: z\n .boolean({ error: '\"aiDeprioritize\" must be true or false' })\n .default(false),\n pagefind: z.boolean({ error: '\"pagefind\" must be true or false' }).default(true),\n tableOfContents: z\n .object({\n minHeadingLevel: z\n .number({ error: '\"minHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(2),\n maxHeadingLevel: z\n .number({ error: '\"maxHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(3),\n })\n .refine((v) => v.minHeadingLevel <= v.maxHeadingLevel, {\n message: \"minHeadingLevel must be <= maxHeadingLevel\",\n })\n .optional(),\n lastUpdated: z.coerce\n .date({ error: '\"lastUpdated\" must be a valid date (e.g. 2024-01-15)' })\n .optional(),\n /**\n * Explicit per-page social/OG image override (path or absolute URL).\n * When omitted, the page route is expected to fall back to a\n * programmatically-generated card or the site-wide `config.socialImage`.\n */\n socialImage: z\n .string({ error: '\"socialImage\" must be a string (path or URL)' })\n .optional(),\n prev: prevNextFrontmatterSchema,\n next: prevNextFrontmatterSchema,\n /**\n * Versioning rename escape hatch.\n *\n * When a page is renamed between versions (the URL slug changes), the\n * newer version's frontmatter declares the slug it had in an older\n * version. The framework uses this to link the pages as cross-version\n * alternates and to emit a `<link rel=\"canonical\">` to the current\n * version's URL.\n *\n * Example: `docs-v1/old-name.mdx` was renamed in v2 to `new-name.mdx`.\n * On the new page (`docs/new-name.mdx`, current version), set:\n *\n * previousSlug: old-name\n *\n * Now `/new-name` and `/v1/old-name` are linked as the same logical\n * page in `<head>` alternates, and the v1 page's canonical points to\n * `/new-name`.\n *\n * Accepts a single slug string (the page's id in the older version)\n * or an array of strings when the page has been renamed across more\n * than one version.\n */\n previousSlug: z\n .union([z.string(), z.array(z.string())], {\n error: '\"previousSlug\" must be a string or array of strings',\n })\n .optional(),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Build a customizable docs schema. Use this when composing schemas outside\n * the `docsCollection()` factory (e.g. multiple docs collections with\n * different shapes).\n */\nexport function defineDocSchema(config: DocSchemaConfig = {}) {\n const base = baseDocSchema();\n if (config.fields) {\n return base.extend(config.fields);\n }\n return base;\n}\n\n/** Default docs schema. Equivalent to `defineDocSchema()`. */\nexport const docsSchema = defineDocSchema();\n\n/** Schema for partials (`<Render file=\"...\" />` snippets). */\nexport const partialsSchema = z\n .object({\n /**\n * Declared parameters this partial accepts.\n * Suffix with `?` for optional params: `[\"name\", \"deprecated?\"]`\n */\n params: z.array(z.string()).optional(),\n })\n .default({});\n\n// ---------------------------------------------------------------------------\n// Components collection — used by sites documenting their own UI components.\n// Pair with `componentsCollection()` from `nimbus-docs/content`. Authoring\n// pattern: hero `<Showcase>` block + `<Example>` blocks in the MDX body, with\n// `props` declared in frontmatter for a generated prop table.\n// ---------------------------------------------------------------------------\n\n/** One row in a component's `props` frontmatter array. */\nconst componentPropSchema = z.object({\n name: z.string({ error: 'prop needs a \"name\"' }),\n type: z.string({ error: 'prop needs a \"type\"' }),\n defaultValue: z.string().optional(),\n required: z.boolean().default(false),\n description: z.string({ error: 'prop needs a \"description\"' }),\n});\n\nexport type ComponentProp = z.infer<typeof componentPropSchema>;\n\n/** Default schema for the components collection. */\nexport const componentsSchema = z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"title\" in frontmatter — display name used in the sidebar and page header.'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n tagline: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"tagline\" in frontmatter — one-sentence summary shown under the title.'\n : `\"tagline\" must be a string, received ${typeof iss.input}`,\n }),\n props: z.array(componentPropSchema).default([]),\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["/**\n * Content schemas for Nimbus.\n *\n * `docsSchema` is the default frontmatter contract for the `docs` collection.\n * `partialsSchema` is the contract for `<Render file=\"...\" />` partials.\n * `defineDocSchema(config)` returns a customizable schema for advanced users\n * composing schemas outside the `docsCollection()` factory.\n *\n * Error messages target content authors, not framework developers.\n * Astro 6 ships Zod v4 via `astro/zod`. The v4 API uses a single `error`\n * field on every schema constructor — NOT v3's `required_error` /\n * `invalid_type_error` / `errorMap`.\n */\n\nimport { z } from \"astro/zod\";\nimport { withStrictKeys } from \"./_internal/strict-keys.js\";\n\nexport interface DocSchemaConfig {\n /** Additional frontmatter fields merged into the default schema. */\n fields?: Record<string, z.ZodTypeAny>;\n}\n\n// ---------------------------------------------------------------------------\n// Building blocks\n// ---------------------------------------------------------------------------\n\nconst sidebarBadgeSchema = z.union([\n z.string(),\n z.object({\n text: z.string({ error: 'sidebar badge needs a \"text\" field' }),\n variant: z\n .enum(\n [\"default\", \"info\", \"note\", \"success\", \"tip\", \"warning\", \"caution\", \"danger\"],\n {\n error:\n '\"variant\" must be one of: default, info, note, success, tip, warning, caution, danger',\n },\n )\n .default(\"default\"),\n }),\n]);\n\nconst sidebarSchema = z.object({\n order: z.number({ error: '\"sidebar.order\" must be a number' }).optional(),\n label: z.string({ error: '\"sidebar.label\" must be a string' }).optional(),\n badge: sidebarBadgeSchema.optional(),\n hidden: z.boolean({ error: '\"sidebar.hidden\" must be true or false' }).optional(),\n hideChildren: z\n .boolean({ error: '\"sidebar.hideChildren\" must be true or false' })\n .optional(),\n});\n\nconst prevNextSchema = z\n .union([\n z.string(),\n z.object({ link: z.string().optional(), label: z.string().optional() }),\n z.literal(false),\n ])\n .optional();\n\nconst headElementSchema = z.object({\n tag: z.enum([\"meta\", \"link\", \"script\", \"style\"], {\n error: 'head element \"tag\" must be \"meta\", \"link\", \"script\", or \"style\"',\n }),\n attrs: z.record(z.string(), z.string()).default({}),\n content: z.string().optional(),\n});\n\n// Mirrors `BannerProps` in types.ts. Layouts consume this directly off\n// `entry.data.banner` and render the `<Banner>` component with it, so the\n// schema is framework-owned (not user-extensible territory).\nconst bannerSchema = z.object({\n content: z.string({ error: 'banner \"content\" must be a string' }),\n type: z\n .enum([\"note\", \"tip\", \"caution\", \"danger\"], {\n error: 'banner \"type\" must be one of: note, tip, caution, danger',\n })\n .optional(),\n dismissible: z\n .object({\n id: z.string({\n error: 'banner \"dismissible.id\" must be a string — a stable identifier you bump when banner content meaningfully changes',\n }),\n days: z.number({ error: 'banner \"dismissible.days\" must be a number' }).optional(),\n })\n .optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Removed/renamed frontmatter keys — surface migration errors loudly\n// ---------------------------------------------------------------------------\n\n/**\n * Frontmatter keys that used to exist but no longer do. When user content\n * still carries one of these, Zod's default `.strip()` behavior would\n * silently drop it — the page would build, but with subtly different\n * behavior (the old toggle just disappears). That's a confusing failure\n * mode for an authoring contract.\n *\n * `withUnknownKeyCheck` (below) consults this map. Hits get the friendly\n * migration message verbatim; everything else falls through to a generic\n * \"Unknown frontmatter key\" error so typos don't sneak past either.\n *\n * Entries removed in the v0 → v1 cleanup:\n *\n * - `template` → `mode`: same shape, but `\"splash\"` is now `\"custom\"`.\n * - `pagefind` → `searchable`: same boolean; default now derives from\n * `noindex` (a non-crawlable page is non-searchable by default).\n * - `llms`: removed. All published pages are listed in `/llms.txt`; the\n * escape hatch is `noindex: true`.\n * - `aiDeprioritize`: removed. The framework no longer emits an\n * agent-downrank signal.\n * - `hero`: removed. Compose the hero in MDX body with user-owned\n * components instead of a frontmatter contract.\n */\nconst REMOVED_FRONTMATTER_KEYS: Record<string, string> = {\n template:\n 'was renamed to \"mode\". Replace `template: \"doc\"` with `mode: \"doc\"`, and `template: \"splash\"` with `mode: \"custom\"`.',\n pagefind:\n 'was renamed to \"searchable\". Same boolean shape; the default now derives from `noindex` (a non-crawlable page is non-searchable unless you set `searchable: true` explicitly).',\n llms:\n \"was removed. Every published page is now listed in /llms.txt; use `noindex: true` to keep a page out of both search engines and the LLM index.\",\n aiDeprioritize:\n \"was removed. The framework no longer emits an agent-downrank signal. If you want a page hidden from agents, use `noindex: true`.\",\n hero:\n \"was removed. Compose your hero in the MDX body using user-owned components; there is no longer a `hero` frontmatter contract.\",\n};\n\n/**\n * Apply this AFTER any `.extend()` so user-added fields are recognized\n * as valid. Wraps the schema in `.passthrough().superRefine()` so removed\n * keys raise a guided migration error; other unknown keys raise a\n * generic error pointing at `defineSchema({ extend: ... })`.\n */\nfunction withFrontmatterKeyCheck<T extends z.ZodObject<z.ZodRawShape>>(schema: T) {\n return withStrictKeys(schema, {\n removedKeys: REMOVED_FRONTMATTER_KEYS,\n contextLabel: \"Frontmatter key\",\n unknownHint: (key) =>\n `If you meant to add a custom field, declare it in your collection's schema via \\`defineSchema({ extend: z.object({ ${key}: ... }) })\\`.`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Base docs schema\n// ---------------------------------------------------------------------------\n\nfunction baseDocSchema() {\n return z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing required \"title\" in frontmatter. Every doc needs:\\n\\n ---\\n title: \"Your Page Title\"\\n ---'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n description: z.string({ error: '\"description\" must be a string' }).optional(),\n mode: z\n .enum([\"doc\", \"custom\"], {\n error: '\"mode\" must be \"doc\" or \"custom\"',\n })\n .default(\"doc\"),\n sidebar: z.union([z.literal(false), sidebarSchema]).optional(),\n head: z.array(headElementSchema).default([]),\n banner: bannerSchema.optional(),\n draft: z.boolean({ error: '\"draft\" must be true or false' }).default(false),\n noindex: z.boolean({ error: '\"noindex\" must be true or false' }).default(false),\n /**\n * Whether this page is included in the site search index. When omitted,\n * derives from `noindex` (a page that's not crawlable is by default not\n * searchable). Set explicitly to override — e.g. `{ noindex: true,\n * searchable: true }` keeps the page out of search engines but findable\n * in the site's own search.\n */\n searchable: z\n .boolean({ error: '\"searchable\" must be true or false' })\n .optional(),\n tableOfContents: z\n .union([\n z.literal(false),\n z\n .object({\n minHeadingLevel: z\n .number({ error: '\"minHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(2),\n maxHeadingLevel: z\n .number({ error: '\"maxHeadingLevel\" must be a number (1-6)' })\n .int()\n .min(1)\n .max(6)\n .default(3),\n })\n .refine((v) => v.minHeadingLevel <= v.maxHeadingLevel, {\n message: \"minHeadingLevel must be <= maxHeadingLevel\",\n }),\n ])\n .optional(),\n lastUpdated: z.coerce\n .date({ error: '\"lastUpdated\" must be a valid date (e.g. 2024-01-15)' })\n .optional(),\n /**\n * Explicit per-page social/OG image override (path or absolute URL).\n * When omitted, the page route is expected to fall back to a\n * programmatically-generated card or the site-wide `config.socialImage`.\n */\n socialImage: z\n .string({ error: '\"socialImage\" must be a string (path or URL)' })\n .optional(),\n prev: prevNextSchema,\n next: prevNextSchema,\n /**\n * Versioning rename escape hatch.\n *\n * When a page is renamed between versions (the URL slug changes), the\n * newer version's frontmatter declares the slug it had in an older\n * version. The framework uses this to link the pages as cross-version\n * alternates and to emit a `<link rel=\"canonical\">` to the current\n * version's URL.\n *\n * Example: `docs-v1/old-name.mdx` was renamed in v2 to `new-name.mdx`.\n * On the new page (`docs/new-name.mdx`, current version), set:\n *\n * previousSlug: old-name\n *\n * Now `/new-name` and `/v1/old-name` are linked as the same logical\n * page in `<head>` alternates, and the v1 page's canonical points to\n * `/new-name`.\n *\n * Accepts a single slug string (the page's id in the older version)\n * or an array of strings when the page has been renamed across more\n * than one version.\n */\n previousSlug: z\n .union([z.string(), z.array(z.string())], {\n error: '\"previousSlug\" must be a string or array of strings',\n })\n .optional(),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Build a customizable docs schema. Use this when composing schemas outside\n * the `docsCollection()` factory (e.g. multiple docs collections with\n * different shapes).\n *\n * For typed Astro `image()` fields or per-collection field narrowing, use\n * the richer `defineSchema(ctx => ...)` factory instead.\n */\nexport function defineDocSchema(config: DocSchemaConfig = {}) {\n const base = baseDocSchema();\n // Apply the unknown-key check AFTER extends so user-added fields are\n // recognized as valid. Order matters — `.passthrough().superRefine()`\n // returns a ZodEffects, which can't be further `.extend()`-ed.\n const merged = config.fields ? base.extend(config.fields) : base;\n return withFrontmatterKeyCheck(merged);\n}\n\n/**\n * Factory options for `defineSchema`.\n *\n * - `extend`: additional fields merged into the framework schema. Use\n * this for user-defined frontmatter (`author`, `tags`, `cover`).\n * - `narrow`: replaces framework fields with tighter types within this\n * collection. Use when a collection has stricter rules — e.g.\n * `{ mode: z.literal(\"doc\") }` says no landing pages in this collection.\n */\nexport interface DefineSchemaOptions {\n extend?: z.ZodTypeAny;\n narrow?: Record<string, z.ZodTypeAny>;\n}\n\n/**\n * Build a typed docs schema with access to the Astro `SchemaContext`.\n * Use this when you want typed image fields (`ctx.image()`), per-\n * collection narrowing of framework fields, or both. The simpler\n * `defineDocSchema({ fields })` factory is still available for the\n * common case of just adding fields.\n *\n * import { defineCollection } from \"astro:content\";\n * import { z } from \"astro/zod\";\n * import { defineSchema } from \"nimbus-docs/schemas\";\n *\n * export const collections = {\n * docs: defineCollection({\n * loader: ...,\n * schema: defineSchema((ctx) => ({\n * extend: z.object({\n * cover: ctx.image().optional(),\n * author: z.string().optional(),\n * }),\n * narrow: {\n * mode: z.literal(\"doc\"), // no landing pages here\n * },\n * })),\n * }),\n * };\n */\nexport function defineSchema(\n factory: (ctx: import(\"astro:content\").SchemaContext) => DefineSchemaOptions,\n) {\n return (ctx: import(\"astro:content\").SchemaContext) => {\n const { extend, narrow } = factory(ctx);\n let schema = baseDocSchema() as z.ZodObject<any>;\n\n // narrowing first (overrides framework fields)\n if (narrow) {\n schema = schema.extend(narrow);\n }\n\n // additive extension (new user fields). Prefer .merge for ZodObject\n // (preserves object-ness for downstream .extend); fall back to .and\n // for any other Zod type (intersection, union, etc.).\n if (extend) {\n if (extend instanceof z.ZodObject) {\n schema = schema.merge(extend);\n } else {\n // Intersection path — `.and()` returns ZodIntersection, on which\n // we can't run `withUnknownKeyCheck` (it operates on ZodObject's\n // `.shape`). Users on this path lose the removed-key migration\n // diagnostic; they own that trade-off by reaching for the\n // non-object extend.\n return schema.and(extend);\n }\n }\n\n return withFrontmatterKeyCheck(schema);\n };\n}\n\n/** Default docs schema. Equivalent to `defineDocSchema()`. */\nexport const docsSchema = defineDocSchema();\n\nconst partialsObjectSchema = z.object({\n /**\n * Declared parameters this partial accepts.\n * Suffix with `?` for optional params: `[\"name\", \"deprecated?\"]`\n */\n params: z.array(z.string()).optional(),\n});\n\n/** Schema for partials (`<Render file=\"...\" />` snippets). */\nexport const partialsSchema = partialsObjectSchema.default({});\n\n// ---------------------------------------------------------------------------\n// Lenient variants — used by `nimbus-docs lint` (`nimbus/frontmatter-shape`).\n//\n// The standalone lint CLI can't yet see a site's extended\n// `content.config.ts` schema, so it validates the *types* of the fields\n// the framework owns while tolerating user-added fields (passthrough).\n// Unknown-key detection is deferred to when the engine can load the real\n// per-collection schema.\n// ---------------------------------------------------------------------------\n\n/** Docs frontmatter, framework fields type-checked, extra keys allowed. */\nexport const lenientDocsSchema = baseDocSchema().passthrough();\n\n/** Partials frontmatter, framework fields type-checked, extra keys allowed. */\nexport const lenientPartialsSchema = partialsObjectSchema.passthrough();\n\n// ---------------------------------------------------------------------------\n// Components collection — used by sites documenting their own UI components.\n// Pair with `componentsCollection()` from `nimbus-docs/content`. Authoring\n// pattern: hero `<Showcase>` block + `<Example>` blocks in the MDX body, with\n// `props` declared in frontmatter for a generated prop table.\n// ---------------------------------------------------------------------------\n\n/** One row in a component's `props` frontmatter array. */\nconst componentPropSchema = z.object({\n name: z.string({ error: 'prop needs a \"name\"' }),\n type: z.string({ error: 'prop needs a \"type\"' }),\n defaultValue: z.string().optional(),\n required: z.boolean().default(false),\n description: z.string({ error: 'prop needs a \"description\"' }),\n});\n\nexport type ComponentProp = z.infer<typeof componentPropSchema>;\n\n/** Default schema for the components collection. */\nexport const componentsSchema = z.object({\n title: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"title\" in frontmatter — display name used in the sidebar and page header.'\n : `\"title\" must be a string, received ${typeof iss.input}`,\n }),\n tagline: z.string({\n error: (iss) =>\n iss.input === undefined\n ? 'Missing \"tagline\" in frontmatter — one-sentence summary shown under the title.'\n : `\"tagline\" must be a string, received ${typeof iss.input}`,\n }),\n props: z.array(componentPropSchema).default([]),\n});\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ //#region src/_internal/strict-keys.ts
2
+ /**
3
+ * Wrap `schema` so unknown keys raise issues at parse time. Captures
4
+ * `Object.keys(schema.shape)` eagerly (before turning the schema into a
5
+ * `ZodEffects` via `superRefine`) so the known-key set reflects the
6
+ * schema as passed in. Call this AFTER any `.extend()` / `.merge()` so
7
+ * user-added fields are recognized.
8
+ */
9
+ function withStrictKeys(schema, options) {
10
+ const knownKeys = new Set(Object.keys(schema.shape));
11
+ return schema.passthrough().superRefine((data, ctx) => {
12
+ if (!data || typeof data !== "object") return;
13
+ for (const key of Object.keys(data)) {
14
+ if (knownKeys.has(key)) continue;
15
+ const removal = options.removedKeys[key];
16
+ if (removal) ctx.addIssue({
17
+ code: "custom",
18
+ path: [key],
19
+ message: `${options.contextLabel} "${key}" ${removal}`
20
+ });
21
+ else {
22
+ const hint = options.unknownHint?.(key);
23
+ ctx.addIssue({
24
+ code: "custom",
25
+ path: [key],
26
+ message: hint ? `Unknown ${options.contextLabel.toLowerCase()} "${key}". ${hint}` : `Unknown ${options.contextLabel.toLowerCase()} "${key}".`
27
+ });
28
+ }
29
+ }
30
+ });
31
+ }
32
+
33
+ //#endregion
34
+ export { withStrictKeys as t };
35
+ //# sourceMappingURL=strict-keys-BiXiT3pq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strict-keys-BiXiT3pq.js","names":[],"sources":["../src/_internal/strict-keys.ts"],"sourcesContent":["/**\n * Strict-key validation helper for Zod object schemas.\n *\n * Zod's default `.strip()` behavior silently drops unknown keys, which is\n * the wrong default for an authoring contract: a stale frontmatter or\n * config field that's been renamed or removed should fail loudly, not\n * vanish at parse time and produce subtly different behavior.\n *\n * This module wraps a `ZodObject` with `.passthrough().superRefine()` so\n * unknown keys survive the parse and get rejected with one issue per\n * key. Known-removed keys (passed via `removedKeys`) emit a friendly\n * migration message; everything else emits a generic \"unknown key\"\n * error with an actionable hint.\n *\n * Used by both the frontmatter schema (`src/schemas.ts`) and the config\n * schema (`src/_internal/validate.ts`). Each call site provides its own\n * `removedKeys` map and a `contextLabel` (\"Frontmatter key\" vs \"Config\n * field\" vs \"features.<key>\") so error messages read naturally.\n */\n\nimport type { z } from \"astro/zod\";\n\nexport interface StrictKeyOptions {\n /**\n * Map of removed-or-renamed keys → migration message. The message\n * follows the contextLabel + key prefix; phrase it as the back-half of\n * the sentence. Example: `'was renamed to \"mode\". Replace ...'`.\n */\n removedKeys: Record<string, string>;\n /**\n * Sentence-start label for the issue message. Examples: `Frontmatter\n * key`, `Config field`, `features sub-key`. The key name (quoted) is\n * appended automatically.\n */\n contextLabel: string;\n /**\n * Optional hint appended to the generic \"unknown key\" message for\n * keys NOT in `removedKeys`. Receives the offending key. Use this to\n * point users at the right escape hatch (e.g. how to add a custom\n * field in their schema).\n */\n unknownHint?: (key: string) => string;\n}\n\n/**\n * Wrap `schema` so unknown keys raise issues at parse time. Captures\n * `Object.keys(schema.shape)` eagerly (before turning the schema into a\n * `ZodEffects` via `superRefine`) so the known-key set reflects the\n * schema as passed in. Call this AFTER any `.extend()` / `.merge()` so\n * user-added fields are recognized.\n */\nexport function withStrictKeys<T extends z.ZodObject<z.ZodRawShape>>(\n schema: T,\n options: StrictKeyOptions,\n) {\n const knownKeys = new Set(Object.keys(schema.shape));\n return schema.passthrough().superRefine((data, ctx) => {\n if (!data || typeof data !== \"object\") return;\n for (const key of Object.keys(data as Record<string, unknown>)) {\n if (knownKeys.has(key)) continue;\n const removal = options.removedKeys[key];\n if (removal) {\n ctx.addIssue({\n code: \"custom\",\n path: [key],\n message: `${options.contextLabel} \"${key}\" ${removal}`,\n });\n } else {\n const hint = options.unknownHint?.(key);\n ctx.addIssue({\n code: \"custom\",\n path: [key],\n message: hint\n ? `Unknown ${options.contextLabel.toLowerCase()} \"${key}\". ${hint}`\n : `Unknown ${options.contextLabel.toLowerCase()} \"${key}\".`,\n });\n }\n }\n });\n}\n"],"mappings":";;;;;;;;AAmDA,SAAgB,eACd,QACA,SACA;CACA,MAAM,YAAY,IAAI,IAAI,OAAO,KAAK,OAAO,MAAM,CAAC;AACpD,QAAO,OAAO,aAAa,CAAC,aAAa,MAAM,QAAQ;AACrD,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,OAAK,MAAM,OAAO,OAAO,KAAK,KAAgC,EAAE;AAC9D,OAAI,UAAU,IAAI,IAAI,CAAE;GACxB,MAAM,UAAU,QAAQ,YAAY;AACpC,OAAI,QACF,KAAI,SAAS;IACX,MAAM;IACN,MAAM,CAAC,IAAI;IACX,SAAS,GAAG,QAAQ,aAAa,IAAI,IAAI,IAAI;IAC9C,CAAC;QACG;IACL,MAAM,OAAO,QAAQ,cAAc,IAAI;AACvC,QAAI,SAAS;KACX,MAAM;KACN,MAAM,CAAC,IAAI;KACX,SAAS,OACL,WAAW,QAAQ,aAAa,aAAa,CAAC,IAAI,IAAI,KAAK,SAC3D,WAAW,QAAQ,aAAa,aAAa,CAAC,IAAI,IAAI;KAC3D,CAAC;;;GAGN"}