@krantho/schema 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/dist/archetypes.d.ts +39 -0
- package/dist/archetypes.d.ts.map +1 -0
- package/dist/archetypes.js +139 -0
- package/dist/archetypes.js.map +1 -0
- package/dist/collection.d.ts +78 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +65 -0
- package/dist/collection.js.map +1 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/content-archetypes.d.ts +34 -0
- package/dist/content-archetypes.d.ts.map +1 -0
- package/dist/content-archetypes.js +64 -0
- package/dist/content-archetypes.js.map +1 -0
- package/dist/contract-codegen.d.ts +11 -0
- package/dist/contract-codegen.d.ts.map +1 -0
- package/dist/contract-codegen.js +29 -0
- package/dist/contract-codegen.js.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata-defaults.d.ts +10 -0
- package/dist/metadata-defaults.d.ts.map +1 -0
- package/dist/metadata-defaults.js +73 -0
- package/dist/metadata-defaults.js.map +1 -0
- package/dist/page/define-page.d.ts +21 -0
- package/dist/page/define-page.d.ts.map +1 -0
- package/dist/page/define-page.js +28 -0
- package/dist/page/define-page.js.map +1 -0
- package/dist/page/index.d.ts +4 -0
- package/dist/page/index.d.ts.map +1 -0
- package/dist/page/index.js +3 -0
- package/dist/page/index.js.map +1 -0
- package/dist/page/references.d.ts +24 -0
- package/dist/page/references.d.ts.map +1 -0
- package/dist/page/references.js +29 -0
- package/dist/page/references.js.map +1 -0
- package/dist/page/types.d.ts +50 -0
- package/dist/page/types.d.ts.map +1 -0
- package/dist/page/types.js +10 -0
- package/dist/page/types.js.map +1 -0
- package/dist/portable-schema.d.ts +6 -0
- package/dist/portable-schema.d.ts.map +1 -0
- package/dist/portable-schema.js +30 -0
- package/dist/portable-schema.js.map +1 -0
- package/dist/presets.d.ts +24 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +23 -0
- package/dist/presets.js.map +1 -0
- package/dist/repository-content.d.ts +17 -0
- package/dist/repository-content.d.ts.map +1 -0
- package/dist/repository-content.js +65 -0
- package/dist/repository-content.js.map +1 -0
- package/dist/resolved-contract.d.ts +5 -0
- package/dist/resolved-contract.d.ts.map +1 -0
- package/dist/resolved-contract.js +28 -0
- package/dist/resolved-contract.js.map +1 -0
- package/dist/runtime-schema.d.ts +24 -0
- package/dist/runtime-schema.d.ts.map +1 -0
- package/dist/runtime-schema.js +225 -0
- package/dist/runtime-schema.js.map +1 -0
- package/dist/schema-export.d.ts +13 -0
- package/dist/schema-export.d.ts.map +1 -0
- package/dist/schema-export.js +13 -0
- package/dist/schema-export.js.map +1 -0
- package/dist/validate-content.d.ts +30 -0
- package/dist/validate-content.d.ts.map +1 -0
- package/dist/validate-content.js +90 -0
- package/dist/validate-content.js.map +1 -0
- package/dist/validate-document.d.ts +11 -0
- package/dist/validate-document.d.ts.map +1 -0
- package/dist/validate-document.js +41 -0
- package/dist/validate-document.js.map +1 -0
- package/package.json +41 -3
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Descoped
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ContentContract } from '@krantho/persistence';
|
|
2
|
+
import type { ZodObject, ZodRawShape } from 'zod';
|
|
3
|
+
export interface MetadataArchetype<T extends ZodObject<ZodRawShape> = ZodObject<ZodRawShape>> {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly schema: T;
|
|
7
|
+
}
|
|
8
|
+
export interface MetadataSlot {
|
|
9
|
+
readonly archetype: MetadataArchetype;
|
|
10
|
+
readonly required?: boolean | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface DocumentArchetype<T extends ZodObject<ZodRawShape> = ZodObject<ZodRawShape>> {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly fields: T;
|
|
16
|
+
readonly metadata: Readonly<Record<string, MetadataSlot>>;
|
|
17
|
+
readonly body: 'none' | 'optional' | 'required';
|
|
18
|
+
readonly sections: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
export declare function assertAuthorProperty(name: string): void;
|
|
21
|
+
export declare function contentDigest(value: unknown): string;
|
|
22
|
+
export declare function documentChecksum(value: {
|
|
23
|
+
fields: Record<string, unknown>;
|
|
24
|
+
body: string;
|
|
25
|
+
metadata?: unknown;
|
|
26
|
+
defaults?: unknown;
|
|
27
|
+
contract?: {
|
|
28
|
+
id: string;
|
|
29
|
+
revision: string;
|
|
30
|
+
} | null | undefined;
|
|
31
|
+
}): string;
|
|
32
|
+
export declare function defineMetadataArchetype<T extends ZodObject<ZodRawShape>>(definition: MetadataArchetype<T>): MetadataArchetype<T>;
|
|
33
|
+
export declare function defineDocumentArchetype<T extends ZodObject<ZodRawShape>>(definition: Omit<DocumentArchetype<T>, 'metadata' | 'body' | 'sections'> & {
|
|
34
|
+
metadata?: Readonly<Record<string, MetadataSlot>> | undefined;
|
|
35
|
+
body?: DocumentArchetype['body'] | undefined;
|
|
36
|
+
sections?: readonly string[] | undefined;
|
|
37
|
+
}): DocumentArchetype<T>;
|
|
38
|
+
export declare function compileContentContract(archetype: DocumentArchetype, fields?: ZodObject<ZodRawShape>): ContentContract;
|
|
39
|
+
//# sourceMappingURL=archetypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archetypes.d.ts","sourceRoot":"","sources":["../src/archetypes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,sBAAsB,CAAA;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAGjD,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC;IAC1F,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CACxC;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC;IAC1F,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAClB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAA;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAAA;IAC/C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAwBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAA;CAC/D,GAAG,MAAM,CAQT;AAiCD,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,EACtE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC/B,iBAAiB,CAAC,CAAC,CAAC,CAKtB;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,EACtE,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,UAAU,CAAC,GAAG;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,GAAG,SAAS,CAAA;IAC7D,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5C,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACzC,GACA,iBAAiB,CAAC,CAAC,CAAC,CA2BtB;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,GAAE,SAAS,CAAC,WAAW,CAAoB,GAChD,eAAe,CAkCjB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalJson } from '@krantho/core';
|
|
3
|
+
import { portableJsonSchema } from './portable-schema.js';
|
|
4
|
+
const RESERVED = new Set([
|
|
5
|
+
'meta',
|
|
6
|
+
'identity',
|
|
7
|
+
'basis',
|
|
8
|
+
'metadata',
|
|
9
|
+
'contract',
|
|
10
|
+
'defaults',
|
|
11
|
+
'body',
|
|
12
|
+
'html',
|
|
13
|
+
'sections',
|
|
14
|
+
'collection',
|
|
15
|
+
'slug',
|
|
16
|
+
'locale',
|
|
17
|
+
'liveVersion',
|
|
18
|
+
'status',
|
|
19
|
+
'changedBy',
|
|
20
|
+
'createdAt',
|
|
21
|
+
'__proto__',
|
|
22
|
+
'prototype',
|
|
23
|
+
'constructor',
|
|
24
|
+
]);
|
|
25
|
+
export function assertAuthorProperty(name) {
|
|
26
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) || RESERVED.has(name)) {
|
|
27
|
+
throw new Error(`Property "${name}" is reserved or invalid`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function contentDigest(value) {
|
|
31
|
+
return createHash('sha256').update(canonicalJson(value)).digest('hex');
|
|
32
|
+
}
|
|
33
|
+
export function documentChecksum(value) {
|
|
34
|
+
return contentDigest({
|
|
35
|
+
fields: value.fields,
|
|
36
|
+
body: value.body,
|
|
37
|
+
metadata: value.metadata ?? {},
|
|
38
|
+
defaults: value.defaults ?? [],
|
|
39
|
+
contract: value.contract ? { id: value.contract.id, revision: value.contract.revision } : null,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function identity(id, label) {
|
|
43
|
+
if (!/^[a-zA-Z][a-zA-Z0-9._/-]*$/.test(id) || !label.trim()) {
|
|
44
|
+
throw new Error('Archetypes require a stable ID and a readable label');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function portableSchema(schema) {
|
|
48
|
+
const result = portableJsonSchema(schema);
|
|
49
|
+
result['additionalProperties'] = false;
|
|
50
|
+
strictObjects(result);
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/** Nested groups reject unknown values too, including objects inside arrays. */
|
|
54
|
+
function strictObjects(value) {
|
|
55
|
+
if (!value || typeof value !== 'object')
|
|
56
|
+
return;
|
|
57
|
+
if (Array.isArray(value)) {
|
|
58
|
+
value.forEach(strictObjects);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const record = value;
|
|
62
|
+
if (record['type'] === 'object' &&
|
|
63
|
+
record['properties'] &&
|
|
64
|
+
Object.keys(record['properties']).length > 0)
|
|
65
|
+
record['additionalProperties'] = false;
|
|
66
|
+
if (Array.isArray(record['required']))
|
|
67
|
+
record['required'].sort();
|
|
68
|
+
Object.values(record).forEach(strictObjects);
|
|
69
|
+
}
|
|
70
|
+
export function defineMetadataArchetype(definition) {
|
|
71
|
+
identity(definition.id, definition.label);
|
|
72
|
+
Object.keys(definition.schema.shape).forEach(assertAuthorProperty);
|
|
73
|
+
portableSchema(definition.schema);
|
|
74
|
+
return Object.freeze({ ...definition });
|
|
75
|
+
}
|
|
76
|
+
export function defineDocumentArchetype(definition) {
|
|
77
|
+
identity(definition.id, definition.label);
|
|
78
|
+
Object.keys(definition.fields.shape).forEach(assertAuthorProperty);
|
|
79
|
+
Object.keys(definition.metadata ?? {}).forEach(assertAuthorProperty);
|
|
80
|
+
const sections = (definition.sections ?? []).map((section) => section.trim());
|
|
81
|
+
if (sections.some((section) => !section) ||
|
|
82
|
+
new Set(sections.map((section) => section.toLowerCase())).size !== sections.length) {
|
|
83
|
+
throw new Error('Archetypes require distinct, non-empty section names');
|
|
84
|
+
}
|
|
85
|
+
const metadata = Object.freeze(Object.fromEntries(Object.entries(definition.metadata ?? {}).map(([slot, value]) => [
|
|
86
|
+
slot,
|
|
87
|
+
Object.freeze({ ...value }),
|
|
88
|
+
])));
|
|
89
|
+
const result = {
|
|
90
|
+
...definition,
|
|
91
|
+
metadata,
|
|
92
|
+
body: definition.body ?? 'optional',
|
|
93
|
+
sections: Object.freeze(sections),
|
|
94
|
+
};
|
|
95
|
+
compileContentContract(result);
|
|
96
|
+
return Object.freeze(result);
|
|
97
|
+
}
|
|
98
|
+
export function compileContentContract(archetype, fields = archetype.fields) {
|
|
99
|
+
const metadata = {};
|
|
100
|
+
for (const [slot, { archetype: group, required }] of Object.entries(archetype.metadata)) {
|
|
101
|
+
const schema = portableSchema(group.schema);
|
|
102
|
+
metadata[slot] = {
|
|
103
|
+
id: group.id,
|
|
104
|
+
label: group.label,
|
|
105
|
+
revision: contentDigest({ id: group.id, schema }),
|
|
106
|
+
required: required ?? false,
|
|
107
|
+
schema,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const resolved = {
|
|
111
|
+
id: archetype.id,
|
|
112
|
+
label: archetype.label,
|
|
113
|
+
fields: portableSchema(fields),
|
|
114
|
+
metadata,
|
|
115
|
+
body: archetype.body,
|
|
116
|
+
sections: [...archetype.sections],
|
|
117
|
+
};
|
|
118
|
+
// Labels are presentation: renaming one keeps saved snapshots on the same revision
|
|
119
|
+
const revision = contentDigest({
|
|
120
|
+
id: resolved.id,
|
|
121
|
+
fields: resolved.fields,
|
|
122
|
+
metadata: Object.fromEntries(Object.entries(metadata).map(([slot, group]) => [
|
|
123
|
+
slot,
|
|
124
|
+
{ id: group.id, required: group.required, schema: group.schema },
|
|
125
|
+
])),
|
|
126
|
+
body: resolved.body,
|
|
127
|
+
sections: resolved.sections,
|
|
128
|
+
});
|
|
129
|
+
return freezeContract({ ...resolved, revision });
|
|
130
|
+
}
|
|
131
|
+
/** Freeze the JSON contract only; Zod's internal caches remain usable. */
|
|
132
|
+
function freezeContract(value) {
|
|
133
|
+
if (value && typeof value === 'object') {
|
|
134
|
+
Object.values(value).forEach(freezeContract);
|
|
135
|
+
Object.freeze(value);
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=archetypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archetypes.js","sourceRoot":"","sources":["../src/archetypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ZodError, ZodObject, ZodRawShape, z } from 'zod';
|
|
2
|
+
import { type DocumentArchetype } from './archetypes.js';
|
|
3
|
+
import { type ParsedRepositoryContent } from './repository-content.js';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for a content collection.
|
|
6
|
+
*
|
|
7
|
+
* @typeParam T - Zod object schema describing content fields
|
|
8
|
+
*/
|
|
9
|
+
export interface CollectionConfig<T extends ZodObject<ZodRawShape>> {
|
|
10
|
+
/** Unique collection name — used as namespace for slugs */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Where the content is mastered */
|
|
13
|
+
source: 'filesystem' | 'database';
|
|
14
|
+
/** Directory path for filesystem-mastered collections (relative to project root) */
|
|
15
|
+
directory?: string | undefined;
|
|
16
|
+
/** Zod schema for fields validation and type inference */
|
|
17
|
+
schema?: T | undefined;
|
|
18
|
+
/** Explicit reusable contract; use schema for an inline collection contract. */
|
|
19
|
+
archetype?: DocumentArchetype<T> | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Where the collection's documents render as pages — read by the sitemap,
|
|
22
|
+
* **Preview on site**, page refresh and JSON-LD through `documentPath()` in
|
|
23
|
+
* `@krantho/core`. A pattern holding `:slug` (`'/deploy/:slug'`; the slug
|
|
24
|
+
* `index` renders at `'/deploy'`), a fixed path every document renders at
|
|
25
|
+
* (`'/'` for a landing singleton), or `false` when the documents have no page
|
|
26
|
+
* of their own. Unset: `pages` at the site root (`home` at `/`), `globals`
|
|
27
|
+
* without pages, any other collection at `/<name>/<slug>`.
|
|
28
|
+
*/
|
|
29
|
+
path?: string | false | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The `##` sections the collection's page template designs, in order — the
|
|
32
|
+
* template gives each its own treatment, renders other sections as prose and
|
|
33
|
+
* leaves missing ones out. Studio shows editors which ones a document has.
|
|
34
|
+
*/
|
|
35
|
+
sections?: readonly string[] | undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A defined content collection with typed fields.
|
|
39
|
+
*
|
|
40
|
+
* @typeParam T - Zod object schema for this collection's fields
|
|
41
|
+
*/
|
|
42
|
+
export interface Collection<T extends ZodObject<ZodRawShape> = ZodObject<ZodRawShape>> {
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly source: 'filesystem' | 'database';
|
|
45
|
+
readonly directory: string | undefined;
|
|
46
|
+
readonly schema: T;
|
|
47
|
+
readonly archetype: DocumentArchetype<T>;
|
|
48
|
+
readonly parseDocument: (slug: string, frontmatter: Record<string, unknown>, body: string) => {
|
|
49
|
+
success: true;
|
|
50
|
+
data: ParsedRepositoryContent;
|
|
51
|
+
} | {
|
|
52
|
+
success: false;
|
|
53
|
+
error: ZodError;
|
|
54
|
+
};
|
|
55
|
+
/** Where the documents render as pages; `undefined` when not declared */
|
|
56
|
+
readonly path: string | false | undefined;
|
|
57
|
+
/** The `##` sections the page template designs, in order; empty when it designs none */
|
|
58
|
+
readonly sections: readonly string[];
|
|
59
|
+
/** Inferred TypeScript type for validated fields (phantom — never assigned at runtime) */
|
|
60
|
+
readonly _fields: z.infer<T>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Define a content collection with a Zod schema for fields validation.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const pages = defineCollection({
|
|
68
|
+
* name: 'pages',
|
|
69
|
+
* source: 'filesystem',
|
|
70
|
+
* directory: 'content/pages',
|
|
71
|
+
* schema: z.object({
|
|
72
|
+
* title: z.string(),
|
|
73
|
+
* }),
|
|
74
|
+
* })
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function defineCollection<T extends ZodObject<ZodRawShape>>(config: CollectionConfig<T>): Collection<T>;
|
|
78
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC9D,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,iBAAiB,CAAA;AACjF,OAAO,EAAE,KAAK,uBAAuB,EAA0B,MAAM,yBAAyB,CAAA;AAE9F;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC;IAChE,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,oCAAoC;IACpC,MAAM,EAAE,YAAY,GAAG,UAAU,CAAA;IACjC,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,CAAA;IACtB,gFAAgF;IAChF,SAAS,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;IAC5C;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAAA;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAClB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAA;IACxC,QAAQ,CAAC,aAAa,EAAE,CACtB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,IAAI,EAAE,MAAM,KACT;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,uBAAuB,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAA;IAC3F,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IACzC,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;CAC7B;AAeD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,EAC/D,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC1B,UAAU,CAAC,CAAC,CAAC,CAwCf"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { defineDocumentArchetype } from './archetypes.js';
|
|
2
|
+
import { parseRepositoryContent } from './repository-content.js';
|
|
3
|
+
/** The designed sections, checked: each a non-empty heading, none repeated (case aside) */
|
|
4
|
+
function designedSections(collection, sections) {
|
|
5
|
+
const seen = new Set();
|
|
6
|
+
for (const section of sections) {
|
|
7
|
+
const key = section.trim().toLowerCase();
|
|
8
|
+
if (!key)
|
|
9
|
+
throw new Error(`Collection "${collection}" has an empty section name`);
|
|
10
|
+
if (seen.has(key))
|
|
11
|
+
throw new Error(`Collection "${collection}" lists section "${section}" twice`);
|
|
12
|
+
seen.add(key);
|
|
13
|
+
}
|
|
14
|
+
return sections.map((section) => section.trim());
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Define a content collection with a Zod schema for fields validation.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const pages = defineCollection({
|
|
22
|
+
* name: 'pages',
|
|
23
|
+
* source: 'filesystem',
|
|
24
|
+
* directory: 'content/pages',
|
|
25
|
+
* schema: z.object({
|
|
26
|
+
* title: z.string(),
|
|
27
|
+
* }),
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function defineCollection(config) {
|
|
32
|
+
if (!config.name) {
|
|
33
|
+
throw new Error('Collection name is required');
|
|
34
|
+
}
|
|
35
|
+
if (config.source === 'filesystem' && !config.directory) {
|
|
36
|
+
throw new Error(`Collection "${config.name}" with source "filesystem" requires a "directory" property`);
|
|
37
|
+
}
|
|
38
|
+
if (typeof config.path === 'string' && !config.path.startsWith('/')) {
|
|
39
|
+
throw new Error(`Collection "${config.name}" path "${config.path}" must start with "/"`);
|
|
40
|
+
}
|
|
41
|
+
if (Boolean(config.schema) === Boolean(config.archetype)) {
|
|
42
|
+
throw new Error('A collection requires either schema or archetype');
|
|
43
|
+
}
|
|
44
|
+
const archetype = config.archetype ??
|
|
45
|
+
defineDocumentArchetype({
|
|
46
|
+
id: `collection/${config.name}`,
|
|
47
|
+
label: config.name,
|
|
48
|
+
fields: config.schema,
|
|
49
|
+
sections: designedSections(config.name, config.sections ?? []),
|
|
50
|
+
});
|
|
51
|
+
const collection = {
|
|
52
|
+
name: config.name,
|
|
53
|
+
source: config.source,
|
|
54
|
+
directory: config.directory,
|
|
55
|
+
schema: archetype.fields,
|
|
56
|
+
archetype,
|
|
57
|
+
parseDocument: (slug, frontmatter, body) => parseRepositoryContent(collection, slug, frontmatter, body),
|
|
58
|
+
path: config.path,
|
|
59
|
+
sections: designedSections(config.name, config.sections ?? archetype.sections),
|
|
60
|
+
// Phantom type — never used at runtime, only for type inference
|
|
61
|
+
_fields: undefined,
|
|
62
|
+
};
|
|
63
|
+
return collection;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AACjF,OAAO,EAAgC,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AA4D9F,2FAA2F;AAC3F,SAAS,gBAAgB,CAAC,UAAkB,EAAE,QAA2B;IACvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QACxC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,6BAA6B,CAAC,CAAA;QACjF,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,oBAAoB,OAAO,SAAS,CAAC,CAAA;QAChF,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACf,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;AAClD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAA2B;IAE3B,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,eAAe,MAAM,CAAC,IAAI,4DAA4D,CACvF,CAAA;IACH,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,CAAC,IAAI,WAAW,MAAM,CAAC,IAAI,uBAAuB,CAAC,CAAA;IAC1F,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;IACrE,CAAC;IACD,MAAM,SAAS,GACb,MAAM,CAAC,SAAS;QAChB,uBAAuB,CAAC;YACtB,EAAE,EAAE,cAAc,MAAM,CAAC,IAAI,EAAE;YAC/B,KAAK,EAAE,MAAM,CAAC,IAAI;YAClB,MAAM,EAAE,MAAM,CAAC,MAAW;YAC1B,QAAQ,EAAE,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;SAC/D,CAAC,CAAA;IACJ,MAAM,UAAU,GAAkB;QAChC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,SAAS,CAAC,MAAM;QACxB,SAAS;QACT,aAAa,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CACzC,sBAAsB,CAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC;QAC7D,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,QAAQ,EAAE,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,IAAI,SAAS,CAAC,QAAQ,CAAC;QAC9E,gEAAgE;QAChE,OAAO,EAAE,SAAkC;KAC5C,CAAA;IACD,OAAO,UAAU,CAAA;AACnB,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ZodObject, ZodRawShape } from 'zod';
|
|
2
|
+
import type { Collection } from './collection.js';
|
|
3
|
+
/**
|
|
4
|
+
* Input to defineConfig — a record of named collections.
|
|
5
|
+
*/
|
|
6
|
+
export interface ContentConfigInput {
|
|
7
|
+
collections: Record<string, Collection<ZodObject<ZodRawShape>>>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolved content configuration. Carries the full collection map
|
|
11
|
+
* for use by the content engine and validation functions.
|
|
12
|
+
*/
|
|
13
|
+
export interface ContentConfig {
|
|
14
|
+
readonly collections: ReadonlyMap<string, Collection<ZodObject<ZodRawShape>>>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Define the project-level content configuration.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* export default defineConfig({
|
|
22
|
+
* collections: { pages, blog },
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function defineConfig(input: ContentConfigInput): ContentConfig;
|
|
27
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;CAChE;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;CAC9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CA8BrE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { compileContentContract } from './archetypes.js';
|
|
2
|
+
/**
|
|
3
|
+
* Define the project-level content configuration.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* export default defineConfig({
|
|
8
|
+
* collections: { pages, blog },
|
|
9
|
+
* })
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function defineConfig(input) {
|
|
13
|
+
const entries = Object.entries(input.collections);
|
|
14
|
+
if (entries.length === 0) {
|
|
15
|
+
throw new Error('defineConfig requires at least one collection');
|
|
16
|
+
}
|
|
17
|
+
const definitions = new Map();
|
|
18
|
+
const register = (id, revision) => {
|
|
19
|
+
const existing = definitions.get(id);
|
|
20
|
+
if (existing !== undefined && existing !== revision)
|
|
21
|
+
throw new Error(`Archetype "${id}" has incompatible definitions; give each variant its own identity`);
|
|
22
|
+
definitions.set(id, revision);
|
|
23
|
+
};
|
|
24
|
+
// Verify collection names match their record keys
|
|
25
|
+
for (const [key, collection] of entries) {
|
|
26
|
+
const contract = compileContentContract(collection.archetype);
|
|
27
|
+
register(contract.id, contract.revision);
|
|
28
|
+
for (const group of Object.values(contract.metadata))
|
|
29
|
+
register(group.id, group.revision);
|
|
30
|
+
if (key !== collection.name) {
|
|
31
|
+
throw new Error(`Collection key "${key}" does not match collection name "${collection.name}"`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
collections: new Map(entries),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAkBxD;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,KAAyB;IACpD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IAEjD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC7C,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,QAAgB,EAAQ,EAAE;QACtD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACpC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,QAAQ;YACjD,MAAM,IAAI,KAAK,CACb,cAAc,EAAE,oEAAoE,CACrF,CAAA;QACH,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IAC/B,CAAC,CAAA;IAED,kDAAkD;IAClD,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACxC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;QACxF,IAAI,GAAG,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,qCAAqC,UAAU,CAAC,IAAI,GAAG,CAAC,CAAA;QAChG,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC;KAC9B,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const editorialMetadata: import("./archetypes.js").MetadataArchetype<z.ZodObject<{
|
|
3
|
+
byline: z.ZodString;
|
|
4
|
+
}, z.core.$strip>>;
|
|
5
|
+
export declare const publicationMetadata: import("./archetypes.js").MetadataArchetype<z.ZodObject<{
|
|
6
|
+
date: z.ZodISODateTime;
|
|
7
|
+
}, z.core.$strip>>;
|
|
8
|
+
export declare const classificationMetadata: import("./archetypes.js").MetadataArchetype<z.ZodObject<{
|
|
9
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
+
category: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>>;
|
|
12
|
+
/** Sharing is optional authored content. A site may use it without enabling SEO. */
|
|
13
|
+
export declare const sharingMetadata: import("./archetypes.js").MetadataArchetype<z.ZodObject<{
|
|
14
|
+
title: z.ZodOptional<z.ZodString>;
|
|
15
|
+
description: z.ZodOptional<z.ZodString>;
|
|
16
|
+
image: z.ZodOptional<z.ZodString>;
|
|
17
|
+
canonicalUrl: z.ZodOptional<z.ZodURL>;
|
|
18
|
+
index: z.ZodOptional<z.ZodBoolean>;
|
|
19
|
+
follow: z.ZodOptional<z.ZodBoolean>;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
/**
|
|
22
|
+
* A page's own structured data: the Schema.org graph the editor's Data mode
|
|
23
|
+
* edits, versioned with the page. Declare it as the `seo` slot.
|
|
24
|
+
*/
|
|
25
|
+
export declare const structuredDataMetadata: import("./archetypes.js").MetadataArchetype<z.ZodObject<z.core.$ZodLooseShape, z.core.$strip>>;
|
|
26
|
+
export declare const websiteContent: import("./archetypes.js").DocumentArchetype<z.ZodObject<{
|
|
27
|
+
title: z.ZodString;
|
|
28
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
29
|
+
}, z.core.$strip>>;
|
|
30
|
+
export declare const blogContent: import("./archetypes.js").DocumentArchetype<z.ZodObject<{
|
|
31
|
+
title: z.ZodString;
|
|
32
|
+
excerpt: z.ZodOptional<z.ZodString>;
|
|
33
|
+
}, z.core.$strip>>;
|
|
34
|
+
//# sourceMappingURL=content-archetypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-archetypes.d.ts","sourceRoot":"","sources":["../src/content-archetypes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,iBAAiB;;kBAI5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;kBAM9B,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;kBAIjC,CAAA;AAEF,oFAAoF;AACpF,eAAO,MAAM,eAAe;;;;;;;kBAW1B,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,gGAIjC,CAAA;AAEF,eAAO,MAAM,cAAc;;;kBAQzB,CAAA;AAEF,eAAO,MAAM,WAAW;;;kBAWtB,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DOCUMENT_SEO_METADATA_SCHEMA } from '@krantho/seo-shared';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { defineDocumentArchetype, defineMetadataArchetype } from './archetypes.js';
|
|
4
|
+
export const editorialMetadata = defineMetadataArchetype({
|
|
5
|
+
id: 'krantho/editorial',
|
|
6
|
+
label: 'Editorial',
|
|
7
|
+
schema: z.object({ byline: z.string().min(1).describe('The name readers see as the author.') }),
|
|
8
|
+
});
|
|
9
|
+
export const publicationMetadata = defineMetadataArchetype({
|
|
10
|
+
id: 'krantho/publication',
|
|
11
|
+
label: 'Publication',
|
|
12
|
+
schema: z.object({
|
|
13
|
+
date: z.iso.datetime().describe('When the page is published.'),
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
export const classificationMetadata = defineMetadataArchetype({
|
|
17
|
+
id: 'krantho/classification',
|
|
18
|
+
label: 'Topics',
|
|
19
|
+
schema: z.object({ tags: z.array(z.string()).optional(), category: z.string().optional() }),
|
|
20
|
+
});
|
|
21
|
+
/** Sharing is optional authored content. A site may use it without enabling SEO. */
|
|
22
|
+
export const sharingMetadata = defineMetadataArchetype({
|
|
23
|
+
id: 'krantho/sharing',
|
|
24
|
+
label: 'Search and sharing',
|
|
25
|
+
schema: z.object({
|
|
26
|
+
title: z.string().optional(),
|
|
27
|
+
description: z.string().optional(),
|
|
28
|
+
image: z.string().describe('media').optional(),
|
|
29
|
+
canonicalUrl: z.url().optional(),
|
|
30
|
+
index: z.boolean().optional(),
|
|
31
|
+
follow: z.boolean().optional(),
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* A page's own structured data: the Schema.org graph the editor's Data mode
|
|
36
|
+
* edits, versioned with the page. Declare it as the `seo` slot.
|
|
37
|
+
*/
|
|
38
|
+
export const structuredDataMetadata = defineMetadataArchetype({
|
|
39
|
+
id: 'krantho/structured-data',
|
|
40
|
+
label: 'Structured data',
|
|
41
|
+
schema: z.fromJSONSchema(DOCUMENT_SEO_METADATA_SCHEMA),
|
|
42
|
+
});
|
|
43
|
+
export const websiteContent = defineDocumentArchetype({
|
|
44
|
+
id: 'krantho/website-content',
|
|
45
|
+
label: 'Website content',
|
|
46
|
+
fields: z.object({ title: z.string(), summary: z.string().optional() }),
|
|
47
|
+
metadata: {
|
|
48
|
+
classification: { archetype: classificationMetadata },
|
|
49
|
+
sharing: { archetype: sharingMetadata },
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
export const blogContent = defineDocumentArchetype({
|
|
53
|
+
id: 'krantho/blog-post',
|
|
54
|
+
label: 'Blog post',
|
|
55
|
+
fields: z.object({ title: z.string(), excerpt: z.string().optional() }),
|
|
56
|
+
body: 'required',
|
|
57
|
+
metadata: {
|
|
58
|
+
editorial: { archetype: editorialMetadata, required: true },
|
|
59
|
+
publication: { archetype: publicationMetadata },
|
|
60
|
+
classification: { archetype: classificationMetadata },
|
|
61
|
+
sharing: { archetype: sharingMetadata },
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=content-archetypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-archetypes.js","sourceRoot":"","sources":["../src/content-archetypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ContentContract } from '@krantho/persistence';
|
|
2
|
+
interface CollectionBinding {
|
|
3
|
+
name: string;
|
|
4
|
+
source: 'filesystem' | 'database';
|
|
5
|
+
directory?: string | undefined;
|
|
6
|
+
path?: string | false | undefined;
|
|
7
|
+
}
|
|
8
|
+
/** Code adoption retains the complete portable contract, including nested constraints and groups. */
|
|
9
|
+
export declare function exportContractAsZod(binding: CollectionBinding, contract: ContentContract): string;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=contract-codegen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-codegen.d.ts","sourceRoot":"","sources":["../src/contract-codegen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,GAAG,UAAU,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;CAClC;AAED,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,eAAe,GAAG,MAAM,CA8BjG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Code adoption retains the complete portable contract, including nested constraints and groups. */
|
|
2
|
+
export function exportContractAsZod(binding, contract) {
|
|
3
|
+
const groupEntries = Object.entries(contract.metadata);
|
|
4
|
+
const imports = groupEntries.length
|
|
5
|
+
? 'defineCollection, defineDocumentArchetype, defineMetadataArchetype, fromPortableJsonSchema'
|
|
6
|
+
: 'defineCollection, defineDocumentArchetype, fromPortableJsonSchema';
|
|
7
|
+
const groups = groupEntries.map(([slot, group]) => ` ${JSON.stringify(slot)}: { required: ${group.required}, archetype: defineMetadataArchetype({\n` +
|
|
8
|
+
` id: ${JSON.stringify(group.id)}, label: ${JSON.stringify(group.label)},\n` +
|
|
9
|
+
` schema: fromPortableJsonSchema(${JSON.stringify(group.schema, null, 2)}),\n` +
|
|
10
|
+
' }) },');
|
|
11
|
+
const routing = binding.path === undefined ? '' : ` path: ${JSON.stringify(binding.path)},\n`;
|
|
12
|
+
const directory = binding.directory === undefined ? '' : ` directory: ${JSON.stringify(binding.directory)},\n`;
|
|
13
|
+
return `import { ${imports} } from '@krantho/schema'
|
|
14
|
+
|
|
15
|
+
// Review the collection directory before adopting this definition in your repository.
|
|
16
|
+
export const collection_${binding.name.replace(/[^a-zA-Z0-9_$]/g, '_')} = defineCollection({
|
|
17
|
+
name: ${JSON.stringify(binding.name)}, source: ${JSON.stringify(binding.source)},
|
|
18
|
+
${directory}${routing} archetype: defineDocumentArchetype({
|
|
19
|
+
id: ${JSON.stringify(contract.id)}, label: ${JSON.stringify(contract.label)},
|
|
20
|
+
body: ${JSON.stringify(contract.body)}, sections: ${JSON.stringify(contract.sections)},
|
|
21
|
+
fields: fromPortableJsonSchema(${JSON.stringify(contract.fields, null, 2)}),
|
|
22
|
+
metadata: {
|
|
23
|
+
${groups.join('\n')}
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
})
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=contract-codegen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-codegen.js","sourceRoot":"","sources":["../src/contract-codegen.ts"],"names":[],"mappings":"AASA,qGAAqG;AACrG,MAAM,UAAU,mBAAmB,CAAC,OAA0B,EAAE,QAAyB;IACvF,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM;QACjC,CAAC,CAAC,4FAA4F;QAC9F,CAAC,CAAC,mEAAmE,CAAA;IACvE,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAC7B,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAChB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,KAAK,CAAC,QAAQ,0CAA0C;QACpG,aAAa,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;QACjF,wCAAwC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM;QACnF,WAAW,CACd,CAAA;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAA;IAC9F,MAAM,SAAS,GACb,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAA;IAC/F,OAAO,YAAY,OAAO;;;0BAGF,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC;UAC5D,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;EAC/E,SAAS,GAAG,OAAO;UACX,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;YACnE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;qCACpD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;;EAE3E,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;;;;CAIlB,CAAA;AACD,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single validation error with context for debugging.
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationError {
|
|
5
|
+
collection: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
field: string;
|
|
8
|
+
message: string;
|
|
9
|
+
expected: string;
|
|
10
|
+
received: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of validating all content across all collections.
|
|
14
|
+
*/
|
|
15
|
+
export interface ValidationResult {
|
|
16
|
+
valid: boolean;
|
|
17
|
+
errors: readonly ValidationError[];
|
|
18
|
+
summary: {
|
|
19
|
+
total: number;
|
|
20
|
+
valid: number;
|
|
21
|
+
invalid: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when content validation fails in strict mode.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ContentValidationError extends Error {
|
|
28
|
+
readonly errors: readonly ValidationError[];
|
|
29
|
+
constructor(errors: readonly ValidationError[]);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=errors.d.ts.map
|