- TypeScript 99.4%
- Makefile 0.3%
- JavaScript 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
CI / lint + typecheck + test (push) Successful in 25s
Reviewed-on: #10 |
||
| .claude | ||
| .forgejo/workflows | ||
| docs | ||
| openspec | ||
| src | ||
| test | ||
| .editorconfig | ||
| .gitignore | ||
| .node-version | ||
| .prettierignore | ||
| .prettierrc.mjs | ||
| AGENTS.md | ||
| architecture-reference.md | ||
| CONTEXT.md | ||
| eslint.config.js | ||
| Makefile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
| vitest.config.ts | ||
| vitest.integration.config.ts | ||
Directus Development Kit (DDK)
A TypeScript DSL and apply engine for Directus schemas with programmatic authoring, stable identity, drift detection, and a safe plan/apply workflow.
Status: 0.x — under active development, breaking changes expected.
Quickstart
npm install @pienter-tech/directus-development-kit @directus/sdk
npx ddk init
ddk init writes a starter ddk.config.ts with a small worked example,
which looks roughly like this:
// ddk.config.ts
import {
Schema,
Collection,
StringField,
UuidField,
TimestampField,
M2OField,
EnvAuthProvider,
directusUsers,
} from '@pienter-tech/directus-development-kit';
const articles = new Collection('articles', {
id: 'col_articles',
fields: {
id: new UuidField({ primary: true, auto: true }),
title: new StringField({ id: 'fld_articles_title' }),
body: new StringField({ id: 'fld_articles_body', length: 65535 }),
author: new M2OField({ id: 'fld_articles_author', to: directusUsers }),
date_created: new TimestampField({ id: 'fld_articles_created' }),
},
});
export default {
schema: new Schema([articles]),
auth: new EnvAuthProvider({
urlEnv: 'DIRECTUS_URL',
tokenEnv: 'DIRECTUS_TOKEN',
}),
vendor: 'postgres',
};
npx ddk diff # preview the plan
npx ddk apply # plan + confirm + execute
npx ddk apply --auto-approve # CI
CLI
| Command | Purpose |
|---|---|
ddk init |
Scaffold a starter ddk.config.ts in the current directory |
ddk synth |
Emit the desired schema state (DDK or Directus snapshot format) |
ddk diff |
Print the apply plan without executing |
ddk apply |
Run plan + confirm + execute |
ddk sync-state |
Rebuild .ddk/state.json from live Directus |
ddk types |
Emit a typed Schema TypeScript file for SDK consumers |
Run ddk <command> --help for command-specific options.
Consuming the schema from the Directus SDK
Cross-package consumers (a Next.js app, a mobile client, a separate
microservice) get a typed Schema via a static .ts file:
npx ddk types --out ./directus-schema.ts
Or auto-emit on every successful apply by setting typesOut in
ddk.config.ts:
export default {
schema: new Schema([articles]),
auth: new EnvAuthProvider({ ... }),
vendor: 'postgres',
typesOut: './directus-schema.ts',
};
Then in the consumer package:
import { createDirectus, rest } from '@directus/sdk';
import type { DirectusSchema } from './directus-schema';
const client = createDirectus<DirectusSchema>('https://cms.example.com').with(
rest(),
);
The emitted file has no runtime DDK dependency — it's pure
import type, so consumer bundlers tree-shake it to a type-only
artifact. Commit the file and gate CI on ddk types --check to catch
drift. See Concepts §4
for the full story.
Documentation
License
MIT