@xdbml/parse
v0.7.1
Published
Parser for xDBML (eXtended Database Markup Language), a strict superset of DBML 10.3.1: tokenizer, parser, module resolver, and name resolver.
Readme
@xdbml/parse
The parser for xDBML (eXtended Database Markup Language), a strict superset of DBML 10.3.1 for describing the shape and meaning of structured and semi-structured data. It turns xDBML source into an abstract syntax tree, resolves module imports, and resolves names, with precise line and column diagnostics.
Framework-free and dependency-free, it runs anywhere JavaScript runs: the browser, Node, Cloudflare Workers. It powers the playground, the hosted render API, and the MCP server.
Install
npm install @xdbml/parseUsage
import { parse, flatten, resolveNames, ParseError } from '@xdbml/parse';
const source = `
Table users {
id int [pk]
email varchar [unique, not null]
}
Table orders {
id int [pk]
user_id int [ref: > users.id]
}
`;
try {
const doc = parse(source); // AST; throws ParseError on a syntax error
flatten(doc); // resolve imports and partials into one document
const { diagnostics } = resolveNames(doc); // unresolved references, duplicate declarations, ...
if (diagnostics.length === 0) {
console.log('valid');
} else {
for (const d of diagnostics) {
console.log(`[${d.severity}] ${d.message} (line ${d.span.start.line})`);
}
}
} catch (e) {
if (e instanceof ParseError) {
console.error(`Syntax error at line ${e.position.line}, column ${e.position.column}: ${e.message}`);
} else {
throw e;
}
}The package also exports tokenize, LexError, Parser, SymbolTable, and the AST types.
For diagram views (spec §18), diagramViews(doc) lists the DiagramView declarations, and diagramViewMembers(doc, name) returns the entities, database views and sticky notes a diagram view contains, with the Containers, EntityGroups (TableGroups) and supertype groups a renderer frames or draws around them.
import { parse, diagramViewMembers } from '@xdbml/parse';
const members = diagramViewMembers(parse(source), 'order_flow');
console.log(members?.entities); // ['sales.orders', 'billing.invoices', ...]For internal definitions (spec §15.8), an entity's definitions { } block parses into a DefinitionsBlock whose entries are TypeDeclaration nodes. entityDefinitions(body) returns them by name, the lookup a consumer needs to expand a field typed by an internal definition: inside the entity, a type name resolves among the entries first, and inside the body of a project Type, among the project's declarations only. isDefinitionsExcludedTarget(name) tells whether a target takes no internal definitions (§15.8.4).
import { parse, entityDefinitions } from '@xdbml/parse';
const entity = parse(source).statements.find((s) => s.kind === 'EntityDeclaration');
const local = entityDefinitions(entity.body);
console.log(local.get('Address')?.body); // the fields of the entry AddressLearn more
- xdbml.org, and the language in 5 minutes
- The specification and source
- The companion renderer,
@xdbml/render
License
Apache License 2.0. See LICENSE.
