Structured Datamdxld
Validation
Validate MDXLD documents with ArkType schemas
Document Validation
mdxld integrates with ArkType for powerful runtime validation of your documents.
Installation
ArkType is an optional peer dependency:
npm install arktypeBasic Validation
import { parse } from 'mdxld'
import { createValidator } from 'mdxld/validate'
import { type } from 'arktype'
// Define your schema
const ArticleSchema = type({
'$type': '"Article"',
'title': 'string',
'author': 'string',
'publishedAt?': 'string',
'draft?': 'boolean',
})
// Create a validator
const validateArticle = createValidator(ArticleSchema)
// Validate a document
const doc = parse(content)
const result = validateArticle(doc)
if (result.success) {
console.log('Valid article:', result.data)
} else {
console.error('Validation errors:', result.errors)
}Schema Examples
Blog Post Schema
const BlogPost = type({
'$type': '"BlogPost"',
'title': 'string',
'slug': 'string',
'author': {
'name': 'string',
'email?': 'string.email',
'url?': 'string.url',
},
'publishedAt': 'string',
'updatedAt?': 'string',
'tags?': 'string[]',
'draft?': 'boolean',
'featured?': 'boolean',
})Documentation Page Schema
const DocPage = type({
'$type': '"Documentation"',
'title': 'string',
'description?': 'string',
'order?': 'number',
'category?': 'string',
'keywords?': 'string[]',
})API Reference Schema
const APIReference = type({
'$type': '"APIReference"',
'title': 'string',
'method': '"GET" | "POST" | "PUT" | "DELETE" | "PATCH"',
'endpoint': 'string',
'authentication?': '"none" | "api-key" | "oauth"',
'parameters?': [{
'name': 'string',
'type': 'string',
'required': 'boolean',
'description?': 'string',
}],
})Union Types
Validate different document types:
const Content = type({
'$type': '"Article" | "BlogPost" | "Tutorial"',
'title': 'string',
'content': 'string',
})
// Or use discriminated unions
const Document = type([
{
'$type': '"Article"',
'title': 'string',
'author': 'string',
},
'|',
{
'$type': '"Tutorial"',
'title': 'string',
'steps': 'string[]',
},
])Custom Validators
Create reusable validators:
import { type } from 'arktype'
// Reusable person type
const Person = type({
'name': 'string',
'email?': 'string.email',
'url?': 'string.url',
})
// Reusable metadata
const ContentMeta = type({
'title': 'string',
'description?': 'string',
'keywords?': 'string[]',
})
// Compose into document schemas
const Article = type({
'$type': '"Article"',
...ContentMeta.infer,
'author': Person,
'publishedAt': 'string',
})Validation with Defaults
import { createValidator } from 'mdxld/validate'
import { type } from 'arktype'
const schema = type({
'title': 'string',
'draft': 'boolean = false',
'order': 'number = 0',
})
const validate = createValidator(schema)
const result = validate(doc)
// Missing draft and order will use defaults
console.log(result.data.draft) // false
console.log(result.data.order) // 0Error Messages
const result = validateArticle(doc)
if (!result.success) {
for (const error of result.errors) {
console.log(`${error.path}: ${error.message}`)
// Example output:
// author: must be a string
// publishedAt: required but missing
}
}Conditional Validation
const conditionalSchema = type({
'$type': 'string',
'title': 'string',
// Require author only for published content
'author': (data) => {
if (data.draft === false) {
return 'string'
}
return 'string | undefined'
},
'draft?': 'boolean',
})Integration with mdxdb
import { createDatabase } from '@mdxdb/fs'
import { createValidator } from 'mdxld/validate'
import { type } from 'arktype'
const db = createDatabase({ path: './content' })
const validateArticle = createValidator(ArticleSchema)
// Validate before storing
async function saveArticle(doc) {
const result = validateArticle(doc)
if (!result.success) {
throw new Error(`Invalid article: ${result.errors.join(', ')}`)
}
await db.set(`articles/${doc.data.slug}`, doc)
}