npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@contractkit/core

v0.14.0

Published

Core DSL compiler library: grammar-driven parser, codegen, and validation

Readme

@contractkit/core

The core compiler library for ContractKit — a domain-specific language for defining HTTP API contracts in .ck files. This package provides the parser, AST, validation passes, and plugin interface; it does not generate code on its own. Code generation is handled by separate plugin packages (TypeScript, Python, OpenAPI, Markdown, Bruno) consumed via the @contractkit/cli binary.

Installation

pnpm add @contractkit/core

You typically don't depend on @contractkit/core directly — it's a transitive dependency of the CLI and plugins. Depend on it explicitly only when writing your own plugin.

What's exported

import {
    parseCk,
    Diagnostics,
    applyOptionsDefaults,
    validateRefs,
    validateInheritance,
    validateOperation,
    type ContractKitPlugin,
    type PluginContext,
    type CkRootNode,
    type ContractTypeNode,
    type FieldNode,
    type ModelNode,
    type OpRouteNode,
    type OpOperationNode,
    type OpParamNode,
} from '@contractkit/core';

| Export | Purpose | | --- | --- | | parseCk(source, file, diag) | Parse a .ck source string into a typed AST. Errors and warnings are collected on the supplied Diagnostics instance. | | Diagnostics | Mutable error/warning collector passed through every parsing and validation pass. | | applyOptionsDefaults(root) | Normalization pass that merges file-level options { request/response: { headers } } into each operation. Run after parseCk, before downstream consumers. | | applyVariableSubstitution(root, diag, fallbackKeys?) | Normalization pass that expands {{name}} references in every string field of the AST using root.meta first, then the optional fallbackKeys map. Run after applyOptionsDefaults. | | validateRefs(roots) | Cross-file type-reference validation. Warns when a model is referenced but not declared anywhere. | | validateInheritance(roots) | Multi-base inheritance validation — cross-base conflicts, override requirement, cycle detection. | | validateOperation(route, root) | Validates an operation against config constraints (path-param coverage, service references, signature schemes). | | ContractKitPlugin / PluginContext | Interfaces a plugin author implements/consumes. See Plugin API. | | AST node types | CkRootNode, ContractTypeNode, FieldNode, ModelNode, OpRouteNode, OpOperationNode, OpParamNode, etc. |

The .ck language

See the root README for the full language reference. A short example:

options {
    keys: { area: payments }
    services: { PaymentsService: "#src/services/payments.service.js" }
}

contract Payment: {
    id: readonly uuid
    amount: number(min=0)
    currency: string(len=3)
    status: enum(pending, completed, failed) = pending
}

operation /payments/{id}: {
    params: { id: uuid }
    get: {
        sdk: getPayment
        service: PaymentsService.getById
        response: { 200: { application/json: Payment } }
    }
}

Plugin API

Plugins implement the ContractKitPlugin interface and are loaded by the CLI based on the plugins map in contractkit.config.json.

import type { ContractKitPlugin, PluginContext, CkRootNode } from '@contractkit/core';

export function createMyPlugin(options: MyOptions = {}): ContractKitPlugin {
    return {
        name: 'my-plugin',

        // Optional: mutate the AST per file before validation.
        transform(root: CkRootNode, ctx: PluginContext) {
            // ...
        },

        // Optional: throw to fail compilation.
        validate(root: CkRootNode, ctx: PluginContext) {
            // ...
        },

        // Required: emit output files. Called once with all parsed roots.
        async generateTargets(roots: CkRootNode[], ctx: PluginContext) {
            for (const root of roots) {
                ctx.emitFile('relative/path.ts', '// generated');
            }
        },

        // Optional: register a `contractkit <name>` CLI subcommand.
        command: {
            name: 'my-plugin',
            description: 'Does plugin-specific work',
            run: async (argv) => { /* ... */ },
        },
    };
}

PluginContext exposes options, rootDir, emitFile, emitFileIfChanged, and the Diagnostics collector.

Per-operation plugin files

An operation can declare plugins: { name: "path.yml" } in the source. The CLI resolves each path relative to the operation's .ck file and stores the content on the AST as op.pluginFiles[name] before plugins run. A plugin keyed by its own name can read its entry to override or augment generated output:

async generateTargets(roots, ctx) {
    for (const root of roots) {
        for (const route of root.routes) {
            for (const op of route.operations) {
                const override = op.pluginFiles?.['my-plugin'];
                if (override) {
                    ctx.emitFile(targetPath(op), override);
                    continue;
                }
                // ... normal generation
            }
        }
    }
}

The raw paths from the grammar are still available on op.plugins for round-trip use cases (e.g. the prettier plugin); op.pluginFiles is set only by the CLI resolver, never by the parser.

Programmatic parsing

import { parseCk, Diagnostics, applyOptionsDefaults } from '@contractkit/core';
import { readFileSync } from 'node:fs';

const diag = new Diagnostics();
const source = readFileSync('./contracts/payments.ck', 'utf8');
const root = parseCk(source, 'payments.ck', diag);

if (diag.hasErrors()) {
    diag.print();
    process.exit(1);
}

applyOptionsDefaults(root);
// `root` is now a fully-normalized `CkRootNode` ready for codegen.

Source layout

| Path | Purpose | | --- | --- | | src/contractkit.ohm | PEG grammar — source of truth for the language | | src/grammar.ts / src/semantics.ts | Compiled grammar loader + Ohm parse tree → AST | | src/parser.ts | parseCk entry point | | src/ast.ts | All AST node types | | src/type-builders.ts / src/type-utils.ts | AST construction and type-graph helpers | | src/decompose.ts | Splits a parsed file into per-decl groups (cache fingerprinting, codegen) | | src/apply-options-defaults.ts | Options-level header globals merge | | src/content-type.ts | Content-type parsing/normalization | | src/diagnostics.ts | Error/warning collector | | src/validate-refs.ts / src/validate-inheritance.ts / src/validate-operation.ts | Validation passes | | src/plugin.ts | ContractKitPlugin and PluginContext interface types |