@damatjs/module
v0.3.6
Published
Damatjs module system — manifest contract, standalone dev/test harness, and registry tooling for self-contained modules
Readme
@damatjs/module
The Damat module system in one package: authoring surface, the portable
module.jsoncontract, a standalone dev/test harness, module-as-app runtime, and registry tooling.
A Damat module is a self-contained vertical slice — models + migrations +
service + config + workflows + routes. This package is the heart of Damat's
composability: it lets you author, run, and test a module on its own (no
backend app), ship it with a module.json manifest, and install it into any
Damat app with damat module add (and, later, straight from a module registry).
It is the single dependency a module package needs — it re-exports everything
from defining a module to running it as a live HTTP app.
Part of the Damat monorepo · Full guide · Internals
Install
bun add @damatjs/moduleInside the Damat monorepo it is a workspace package — depend on it with the * version range:
{ "dependencies": { "@damatjs/module": "*" } }When to use
Use it when:
- You are authoring a module package — import the contract/config/runtime/tooling from here; the authoring symbols come from their real packages (
defineModule/ModuleServicefrom@damatjs/services,model/columnsfrom@damatjs/orm-model,createStep/… from@damatjs/workflow-engine,zfrom@damatjs/deps/zod). - You are relating modules to each other —
defineLink/collectLinkModels/defineLinkModuleare re-exported here so the app'ssrc/links/can declare cross-module relationships from the same surface (the runtime service isgetModule("link")). See@damatjs/link. - You want to develop or test a module standalone against a real Postgres, without spinning up a backend (
bootModule/withModule). - You want to run one module as a live app — full framework HTTP stack, just this module registered (
startModuleApp, whatdamat module devboots). - You build tooling: generate a module's types or create a diff migration with no
damat.config.ts(generateModuleTypes,createModuleMigration). - You implement module distribution: parse/format module refs, read & validate
module.json, check registry-readiness, resolve & verify entries against a registry index.
Skip it when:
- You're building app-level wiring that isn't a module — use
@damatjs/frameworkdirectly. - You only need workflows — depend on
@damatjs/workflow-enginedirectly.
Quick start
Author a module (import each symbol from its real package):
// src/index.ts
import { defineModule, ModuleService } from "@damatjs/services";
import { model, columns } from "@damatjs/orm-model";
import { loadCredentials } from "./credentials";
const models = { users: model("users", { id: columns.uuid().primaryKey() }) };
export class UserModuleService extends ModuleService({ models }) {}
export default defineModule("user", {
service: UserModuleService,
credentials: loadCredentials,
});Develop & test it standalone (real Postgres, no server):
import { bootModule, withModule } from "@damatjs/module";
import userModule from "./index";
// playground / scripts
const booted = await bootModule(userModule, { moduleDir: import.meta.dir });
const user = await booted.service.user.create({ data: { email: "[email protected]" } });
await booted.teardown();
// tests — boot, run, always tear down
await withModule(userModule, { moduleDir: import.meta.dir }, async ({ service }) => {
expect(await service.user.exists({ where: { email: "[email protected]" } })).toBe(true);
});Run it as a live app, or address it for a registry:
import { startModuleApp, parseModuleRef, validateModuleDir } from "@damatjs/module";
const app = await startModuleApp({ port: 0 }); // full HTTP stack, this module only
await app.stop();
parseModuleRef("damatjs/[email protected]"); // → { namespace: "damatjs", name: "user", version: "0.2.0" }
validateModuleDir("./src"); // → { valid, errors, warnings, manifest }Requires Postgres (DATABASE_URL, or { databaseUrl } / { database }) for the
harness and for the runtime when serving. In test suites gate DB tests with
describe.skipIf(!process.env.DATABASE_URL).
API
| Export | Kind | Summary |
| --- | --- | --- |
| defineModule, ModuleService | re-export | Define a module and its service base (from @damatjs/services). |
| model, columns | re-export | ORM model DSL (from @damatjs/orm-model). |
| createStep, createWorkflow, executeStep, parallel, when, ifElse, RetryPolicies, Effect, … | re-export | Workflow engine (from @damatjs/workflow-engine). |
| getModule, hasModule, registerModule | re-export | App-side registry access (from @damatjs/framework). |
| defineLink, collectLinkModels, defineLinkModule | re-export | Cross-module links: relate this module to another through a junction table; getModule("link") exposes create/dismiss/fetch/graph. |
| z | re-export | Zod validation. |
| defineModuleConfig | function | Type-safe helper for module.config.ts. |
| loadModuleConfig | function | Load a package's module.config.ts (empty config if absent). |
| readModuleManifest, validateModuleManifest | function | Read / validate a module.json into a ModuleManifest. |
| bootModule, withModule | function | Boot a module standalone (with migrations) for dev/test; auto-teardown variant. |
| startModuleApp, runModuleEntry | function | Run one module as a live HTTP app; damat module dev entry. |
| createModuleMigration, generateModuleTypes | function | Diff-migration & codegen for a standalone module package. |
| parseModuleRef, formatModuleRef | function | Parse / format refs like damatjs/[email protected]. |
| validateModuleDir | function | Registry-readiness report (errors block install, warnings block publish). |
| resolveRegistryEntry, resolveRegistryRef | function | Resolve a ref against a registry index → source + owner + verification. |
| evaluateVerification, verificationPolicy | function | Install-time trust gate (DAMAT_MODULE_VERIFY / DAMAT_MODULE_REGISTRY). |
| normalizeVersionEntry | function | Coerce a registry version value (string or object) to RegistryVersionEntry. |
| MODULE_MANIFEST_FILENAME, DEFAULT_MODULE_PATHS, DEFAULT_MODULE_PORT, VERIFICATION_STATUSES | const | Constants for the contract / runtime / registry. |
Key types: ModuleManifest (+ ModuleEnvVar, ModuleAuthor, ModuleManifestPaths, ModuleRegistryMeta), ModuleAppConfig, BootModuleOptions / BootedModule, StartModuleAppOptions / RunningModuleApp, ModuleRef, ModuleValidationReport, RegistryIndex / RegistryModuleEntry (back-compat alias RegistryIndexEntry) / RegistryVersionEntry / RegistryOwner / RegistryAuthor / RegistryVerification, ResolvedRegistryModule, VerificationStatus / VerificationPolicy, LinkService / LinkDefinition / LinkEndpoint / LinkOptions / LinkRowRef / LinkModelRef.
See the module.json reference for the full manifest contract.
How it fits
Depends on (all @damatjs/* workspace packages):
@damatjs/services—defineModule,ModuleService,PoolManager.@damatjs/framework— bootstrap,initializeServices, app-side module registry.@damatjs/orm-connector/orm-migration/orm-model/codegen/orm-type— connection, migrations, model DSL, codegen.@damatjs/workflow-engine— workflow authoring surface.@damatjs/logger,@damatjs/deps— logging, bundled deps (Hono, Zod).
Depended on by (in-repo):
@damatjs/damat-cli— thedamatCLI (module add/module dev/ migrations / codegen).
Documentation
License
MIT
