@strifeapp/schema
v0.5.0
Published
Template schema merge logic using json-merge-patch (RFC 7396).
Keywords
Readme
@strifeapp/schema
Typed schema-as-code for Strife. Declare templates with defineType + fields.*, register them with defineConfig + glob, infer content shapes with Infer<typeof X>.
Status: alpha. The DSL surface is stabilising in v1.x. Pin the
0.0.1-alpha.xline if you depend on it from CI.
Install
npm install @strifeapp/schemaRequires Node >=22 and ESM-compatible tooling.
Declaring a template
import { defineType, fields } from '@strifeapp/schema';
export const article = defineType({
name: 'articles',
title: 'Article',
type: 'document',
fields: {
heading: fields.text({ label: 'Heading', localizable: true }),
body: fields.html({ label: 'Body' }),
publishedAt: fields.date({ label: 'Published' }),
archived: fields.switch({ label: 'Archived' }),
},
});The result is a runtime no-op — defineType returns its input unchanged. The work happens at the type level: Infer<typeof article> walks the field shape.
Inferring content types
import type { Infer } from '@strifeapp/schema';
type Article = Infer<typeof article>;
// ^? {
// heading: Record<string, string>; // localizable → keyed by locale
// body: string; // non-localizable → scalar
// publishedAt: string;
// archived: boolean;
// }Use Article as the type for content stored against the articles template.
Registering schemas with defineConfig + glob
The Strife CLI loads schemas via a strife.config.ts (or .tsx, .mts, .js, .mjs) at the project root:
// strife.config.ts
import { defineConfig, glob } from '@strifeapp/schema';
export default defineConfig({
schema: glob('./schemas/**/*.ts'),
});defineConfig and glob are runtime no-ops — they return their input. The CLI consumes the descriptor at push time, resolves the pattern via tinyglobby, and imports each matched file.
glob() paths resolve relative to the config file's directory (not the cwd). Pass base to pin a different root:
defineConfig({
schema: glob('*.ts', { base: './content/types' }),
});Future scale-space
defineConfig's type intentionally leaves room for v2 fields like plugins, tools, and environments. v1.x accepts only schema; future additions are non-breaking via TypeScript structural typing.
What compile() produces
compile(definition) is the wire-format translator the CLI uses internally. It maps the DSL to Strife's RavenDB Template JSON. You won't usually call it directly — the CLI does that during strife push — but it's exported for tooling and tests.
Pushing a schema
See @strifeapp/cli for the full strife push flow.
