@setzkasten-cms/core 0.4.2
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 +37 -0
- package/dist/chunk-IL2PWN4R.js +142 -0
- package/dist/define-config-bJ65Zaui.d.ts +209 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.js +314 -0
- package/dist/testing.d.ts +28 -0
- package/dist/testing.js +69 -0
- package/package.json +32 -0
- package/src/commands/command.test.ts +85 -0
- package/src/commands/command.ts +65 -0
- package/src/errors/errors.ts +112 -0
- package/src/events/content-event-bus.test.ts +59 -0
- package/src/events/content-event-bus.ts +55 -0
- package/src/fields/factories.test.ts +168 -0
- package/src/fields/factories.ts +166 -0
- package/src/fields/field-definition.ts +215 -0
- package/src/index.ts +85 -0
- package/src/ports/asset-store.ts +36 -0
- package/src/ports/auth-provider.ts +32 -0
- package/src/ports/content-repository.ts +59 -0
- package/src/schema/define-config.ts +96 -0
- package/src/serialization/json-serializer.ts +87 -0
- package/src/serialization/serializer.ts +65 -0
- package/src/testing/index.ts +72 -0
- package/src/validation/schema-to-zod.test.ts +133 -0
- package/src/validation/schema-to-zod.ts +126 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import type {
|
|
3
|
+
AnyFieldDef,
|
|
4
|
+
ArrayFieldDef,
|
|
5
|
+
FieldDefinition,
|
|
6
|
+
FieldRecord,
|
|
7
|
+
ObjectFieldDef,
|
|
8
|
+
OverrideFieldDef,
|
|
9
|
+
} from '../fields/field-definition'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates a Zod schema from a FieldDefinition.
|
|
13
|
+
* This is the single source of truth for validation – Zod schemas are derived
|
|
14
|
+
* from field definitions, never written by hand.
|
|
15
|
+
*/
|
|
16
|
+
export function fieldToZod(field: FieldDefinition): z.ZodType {
|
|
17
|
+
switch (field.type) {
|
|
18
|
+
case 'text':
|
|
19
|
+
return textToZod(field as AnyFieldDef & { type: 'text' })
|
|
20
|
+
case 'number':
|
|
21
|
+
return numberToZod(field as AnyFieldDef & { type: 'number' })
|
|
22
|
+
case 'boolean':
|
|
23
|
+
return z.boolean()
|
|
24
|
+
case 'select':
|
|
25
|
+
return selectToZod(field as AnyFieldDef & { type: 'select' })
|
|
26
|
+
case 'icon':
|
|
27
|
+
return field.required ? z.string().min(1, `${field.label} ist erforderlich`) : z.string()
|
|
28
|
+
case 'image':
|
|
29
|
+
return imageToZod(field as AnyFieldDef & { type: 'image' })
|
|
30
|
+
case 'array':
|
|
31
|
+
return arrayToZod(field as ArrayFieldDef)
|
|
32
|
+
case 'object':
|
|
33
|
+
return objectToZod(field as ObjectFieldDef)
|
|
34
|
+
case 'color':
|
|
35
|
+
return z.string().regex(/^#[0-9a-fA-F]{6}$/, 'Invalid hex color')
|
|
36
|
+
case 'override':
|
|
37
|
+
return overrideToZod(field as OverrideFieldDef)
|
|
38
|
+
default:
|
|
39
|
+
return z.unknown()
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function textToZod(field: AnyFieldDef & { type: 'text' }): z.ZodType {
|
|
44
|
+
let schema = z.string()
|
|
45
|
+
|
|
46
|
+
if (field.required) {
|
|
47
|
+
schema = schema.min(1, `${field.label} ist erforderlich`)
|
|
48
|
+
}
|
|
49
|
+
if (field.maxLength) {
|
|
50
|
+
schema = schema.max(field.maxLength, `${field.label} darf max. ${field.maxLength} Zeichen haben`)
|
|
51
|
+
}
|
|
52
|
+
if (field.pattern) {
|
|
53
|
+
schema = schema.regex(field.pattern, `${field.label} hat ein ungültiges Format`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return schema
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function numberToZod(field: AnyFieldDef & { type: 'number' }): z.ZodType {
|
|
60
|
+
let schema = z.number()
|
|
61
|
+
|
|
62
|
+
if (field.min !== undefined) {
|
|
63
|
+
schema = schema.min(field.min)
|
|
64
|
+
}
|
|
65
|
+
if (field.max !== undefined) {
|
|
66
|
+
schema = schema.max(field.max)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return schema
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function selectToZod(field: AnyFieldDef & { type: 'select' }): z.ZodType {
|
|
73
|
+
const values = field.options.map((o) => o.value)
|
|
74
|
+
if (values.length === 0) return z.string()
|
|
75
|
+
|
|
76
|
+
const [first, ...rest] = values
|
|
77
|
+
return z.enum([first!, ...rest])
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function imageToZod(field: AnyFieldDef & { type: 'image' }): z.ZodType {
|
|
81
|
+
const schema = z.object({
|
|
82
|
+
path: z.string(),
|
|
83
|
+
alt: z.string().optional(),
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return field.required ? schema.refine((v) => v.path.length > 0, `${field.label} ist erforderlich`) : schema
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function arrayToZod(field: ArrayFieldDef): z.ZodType {
|
|
90
|
+
const itemSchema = fieldToZod(field.itemField)
|
|
91
|
+
let schema = z.array(itemSchema)
|
|
92
|
+
|
|
93
|
+
if (field.minItems !== undefined) {
|
|
94
|
+
schema = schema.min(field.minItems)
|
|
95
|
+
}
|
|
96
|
+
if (field.maxItems !== undefined) {
|
|
97
|
+
schema = schema.max(field.maxItems)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return schema
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function objectToZod(field: ObjectFieldDef): z.ZodType {
|
|
104
|
+
return schemaToZod(field.fields)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function overrideToZod(field: OverrideFieldDef): z.ZodType {
|
|
108
|
+
const innerSchema = schemaToZod(field.fields)
|
|
109
|
+
return z.object({
|
|
110
|
+
active: z.boolean(),
|
|
111
|
+
}).and(innerSchema.partial())
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Convert an entire field record (schema) to a Zod object schema.
|
|
116
|
+
*/
|
|
117
|
+
export function schemaToZod(fields: FieldRecord): z.ZodObject<Record<string, z.ZodType>> {
|
|
118
|
+
const shape: Record<string, z.ZodType> = {}
|
|
119
|
+
|
|
120
|
+
for (const [key, field] of Object.entries(fields)) {
|
|
121
|
+
const zodField = fieldToZod(field)
|
|
122
|
+
shape[key] = field.required ? zodField : zodField.optional()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return z.object(shape)
|
|
126
|
+
}
|