@airdraft/core
v0.1.14
Published
Airdraft core engine — schema, collections, slug/publish semantics
Downloads
3,043
Readme
@airdraft/core
Runtime engine for Airdraft — the git-native headless CMS. Provides the storage adapters, collection engine, field validation, plugin system, and all shared TypeScript types used across the monorepo.
Installation
npm install @airdraft/coreExports
Engine
| Export | Description |
|---|---|
| createEngine(config) | Creates a CMS engine instance from an AirdraftConfig. Returns { listEntries, getEntry, createEntry, updateEntry, deleteEntry, listCollections, getSchema }. |
Configuration
| Export | Description |
|---|---|
| defineConfig(config) | Type-safe helper to define an AirdraftConfig. Pass your collections, adapter, and plugins here. |
Field Validation
| Export | Description |
|---|---|
| validateFields(data, fields) | Validates a record against a FieldMap. Returns ValidationError[]. |
| validateField(name, value, config) | Validates a single field value against its FieldConfig. |
Supported field types
string · number · boolean · date · richtext · image · media · url · list · multiselect · relations · relation · object · select · blocks
mediasupportsmultiple: truefor multi-file fields andacceptfor MIME filtering.urlvalidates absolute URLs (https://…) and root-relative paths (/…).blocksembeds a named sub-schema as a single structured object or a repeatable array of items (withmultiple: true). Sub-fields are defined viafields: Record<string, FieldConfig>.
Storage Adapters
| Export | Description |
|---|---|
| LocalAdapter | Reads/writes MDX+YAML files on the local filesystem. Used in development. |
| GitHubAdapter | Reads/writes via the GitHub Contents API. Used in production/serverless. |
Errors
| Export | Description |
|---|---|
| ValidationError | Thrown when field validation fails. Carries details: Array<{ field, message }>. |
| NotFoundError | Thrown when an entry or collection does not exist. |
| ConflictError | Thrown on SHA mismatch (optimistic concurrency). |
Types
All shared TypeScript types are exported from this package:
AirdraftConfig · CollectionConfig · FieldConfig · FieldMap · AuditEvent · AuditEventError · Plugin · StorageAdapter · Entry · EntryMeta · MediaItem · CmsSchema · CollectionMap
AuditEvent.error includes an optional details array (Array<{ field: string; message: string }>) that carries per-field validation failures.
Rich entry types
| Type | Description |
|---|---|
| RichEntry<TData> | Extends Entry with wordCount, readTime, and prev/next sibling navigation. Returned by all read paths. |
| EntrySibling<TData> | Lightweight stub returned as prev/next on RichEntry. Contains slug, a subset of data fields, wordCount, and readTime. |
| RichListResult<TData> | Returned by listEntries. Includes entries, total, page, pages, hasNext, hasPrev. |
| ListEntriesResult | Deprecated. Alias for RichListResult. |
CollectionConfig additions
| Option | Type | Default | Description |
|---|---|---|---|
| wordCountFields | string[] | all rich-text fields (+ body for MDX) | Fields whose text content is summed for wordCount. |
| siblingFields | string[] | all non-rich-text, non-text fields | Fields included in sibling stubs. |
| calculateReadTime | (wc: number) => string | 200 wpm | Custom read-time estimator. |
| storeComputedFields | boolean | false | When true, createEntry/updateEntry write _computed: { wordCount, readTime } to the file's frontmatter so external tools can read pre-computed values without running the engine. |
ListOptions additions
| Option | Type | Description |
|---|---|---|
| page | number | 1-based page number. Converted to offset = (page - 1) * limit. Takes precedence over offset when both are provided. |
GetOptions additions
| Option | Type | Description |
|---|---|---|
| siblings | boolean \| SiblingsOptions | When true, resolves prev/next adjacent entries in the collection. Pass an object to override sort, status, filter, or fields. |
SiblingsOptions shape:
{
sort?: SortField | SortField[]
status?: 'published' | 'draft' | 'all'
filter?: Record<string, unknown | FilterOperator>
fields?: string[] // per-call override of CollectionConfig.siblingFields
}Content utilities
| Export | Description |
|---|---|
| countWords(markdown) | Counts words in a Markdown/MDX string (strips code blocks, images, links, and headings before counting). |
| defaultReadTime(wordCount) | Returns a read-time string at 200 wpm, e.g. "3 min read". |
Plugin API
import { defineConfig } from '@airdraft/core'
defineConfig({
plugins: [
{
name: 'my-plugin',
middleware(req) {
// runs before routing — throw UnauthorizedError / ForbiddenError to block
},
transformResponse(req, res) {
// called after every successful response; may mutate headers (e.g. Set-Cookie)
return res
},
hooks: {
onAuditEvent(event) {
// event.error?.details contains per-field validation errors
console.log(event)
},
},
},
],
})Plugin hooks:
| Hook | When | Usage |
|---|---|---|
| middleware(req) | Before routing, on every request | Auth enforcement — throw UnauthorizedError / ForbiddenError to block |
| transformResponse(req, res) | After response is built (success paths only) | Mutate response headers, e.g. append Set-Cookie for silent token refresh |
| hooks.transformEntry | After every entry read | Enrich entries — used by @airdraft/plugin-media to inject _url / _media fields |
| hooks.onAuditEvent | After every CMS request completes | Audit logging with per-field error details |
Changelog
See CHANGELOG.md.
