@cerios/xml-poto-codegen
v1.0.0
Published
Generate TypeScript classes with xml-poto decorators from XSD schemas. CLI tool with config-based multi-XSD support.
Downloads
376
Readme
@cerios/xml-poto-codegen
Generate TypeScript classes with @cerios/xml-poto decorators from XSD schemas. Turn your XML Schema definitions into fully decorated, type-safe TypeScript code — ready for bidirectional XML serialization.
✨ Key Features
- 🎯 Type-Safe Output — Generated classes with full TypeScript types and decorator metadata
- 📄 XSD Driven — Supports complex types, enumerations, inheritance, namespaces, groups, and more
- 🔧 Configurable — JSON or TypeScript config with per-source overrides
- 📁 Flexible Output — One file per class (
per-type) or all-in-one (per-xsd) - 🏷️ Enum Styles — Generate unions, TS enums, or const-object patterns
- 🔗 Multi-XSD — Process multiple schemas with cross-file
xs:importresolution - 🚀 CLI & Programmatic — Use from the command line or integrate into build scripts
- 📦 Zero Config Start — Interactive
initcommand to scaffold your config
📦 Installation
npm install -D @cerios/xml-poto-codegenPeer dependency:
@cerios/xml-potomust be installed in the project where generated code will be used.
🎯 Quick Start
1. Initialize config
npx xml-poto-codegen initThe init flow asks you to choose either a JSON or TypeScript config file and then scaffolds it in your project root.
Example xml-poto-codegen.config.json:
{
"sources": [
{
"xsdPath": "./schemas/my-schema.xsd",
"outputPath": "./src/generated",
"outputStyle": "per-type"
}
]
}2. Generate classes
npx xml-poto-codegen generate3. Use the generated code
Given this XSD:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="LastName" type="xs:string"/>
<xs:element name="Age" type="xs:integer"/>
<xs:element name="Email" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>The codegen produces:
// ──────────────────────────────────────────────
// AUTO-GENERATED — do not edit
// ──────────────────────────────────────────────
import { XmlAttribute, XmlElement, XmlRoot } from "@cerios/xml-poto";
@XmlRoot({ name: "Person" })
export class Person {
@XmlAttribute({ name: "id", required: true })
id: string = "";
@XmlElement({ name: "FirstName" })
firstName: string = "";
@XmlElement({ name: "LastName" })
lastName: string = "";
@XmlElement({ name: "Age" })
age: number = 0;
@XmlElement({ name: "Email" })
email?: string;
}You can then serialize and deserialize immediately with @cerios/xml-poto:
import { XmlSerializer } from "@cerios/xml-poto";
import { Person } from "./generated/person";
const serializer = new XmlSerializer();
const person = serializer.fromXml(xmlString, Person);
const xml = serializer.toXml(person);🛠️ CLI Commands
init
npx xml-poto-codegen initInteractively create a config file. Prompts for config format (json/ts, default: ts), validates XSD paths, asks for output style, then asks for a folder path (per-type) or file path (per-xsd) accordingly.
generate
npx xml-poto-codegen generate⚙️ Configuration
Create xml-poto-codegen.config.json or xml-poto-codegen.config.ts in your project root.
JSON config
{
"sources": [
{
"xsdPath": "./schemas/orders.xsd",
"outputPath": "./src/generated/orders",
"outputStyle": "per-type"
},
{
"xsdPath": "./schemas/products.xsd",
"outputPath": "./src/generated/products.ts",
"outputStyle": "per-xsd"
}
],
"defaultOutputStyle": "per-type"
}TypeScript config
import type { XmlPotoCodegenConfig } from "@cerios/xml-poto-codegen";
const config: XmlPotoCodegenConfig = {
sources: [
{
xsdPath: "./schemas/orders.xsd",
outputPath: "./src/generated/orders",
outputStyle: "per-type",
},
],
defaultOutputStyle: "per-type",
};
export default config;Global options
| Option | Type | Description |
| -------------------- | ------------------------------------- | ------------------------------------------------------------ |
| sources | XsdSource[] | Array of XSD sources to process |
| defaultOutputStyle | 'per-type' \| 'per-xsd' | Default output style for all sources (default: 'per-type') |
| enumStyle | 'union' \| 'enum' \| 'const-object' | Default enum generation style (default: 'union') |
Source options
| Option | Type | Description |
| ------------- | ------------------------------------- | -------------------------------------------------------------- |
| xsdPath | string | Path to the XSD file (required) |
| outputPath | string | Output path. per-type: directory. per-xsd: .ts file path |
| outputStyle | 'per-type' \| 'per-xsd' | 'per-type': one file per class. 'per-xsd': all in one file |
| enumStyle | 'union' \| 'enum' \| 'const-object' | Enum generation style for this source (overrides global) |
🏷️ Enum Styles
Choose how XSD enumerations are generated with the enumStyle option.
"union" (default)
export type StatusType = "active" | "inactive" | "pending";"enum"
export enum StatusType {
Active = "active",
Inactive = "inactive",
Pending = "pending",
}"const-object"
export const StatusType = {
Active: "active",
Inactive: "inactive",
Pending: "pending",
} as const;
export type StatusType = (typeof StatusType)[keyof typeof StatusType];🔧 XSD to Decorator Mapping
| XSD Concept | Generated Code |
| ---------------------------- | --------------------------------- |
| Root element + complexType | @XmlRoot({ name: '...' }) |
| Named complexType | @XmlElement() class |
| Element in sequence | @XmlElement({ name: '...' }) |
| Element with maxOccurs > 1 | @XmlArray({ itemName: '...' }) |
| Attribute | @XmlAttribute({ name: '...' }) |
| simpleContent | @XmlText() |
| Enumeration restriction | enumValues option |
| Pattern restriction | pattern option |
| nillable="true" | isNullable: true |
| xs:any | @XmlDynamic() |
| Extension base | TypeScript extends |
| xs:import | Cross-file type resolution |
| substitutionGroup | Resolved to concrete types |
| Groups / attributeGroups | Inlined into the containing class |
Coverage Notes
Codegen focuses on what can be inferred from XSD structure and constraints. The generated code covers core decorators and common options, but not every runtime-only xml-poto capability.
- Generated from XSD:
@XmlRoot,@XmlElement,@XmlAttribute,@XmlText,@XmlArray,@XmlDynamic - Not generated (manual only):
@XmlComment,@XmlIgnore - Partial option coverage by design: runtime tuning options such as custom converters/transforms, CDATA toggles, mixed-content behavior flags, and advanced
@XmlDynamicparse/cache/lazy settings are not inferred from XSD and must be added manually when needed.
📁 Output Styles
per-type (default)
One file per class/enum plus a barrel index.ts:
src/generated/
├── person.ts
├── address-type.ts
├── status-type.ts
└── index.tsper-xsd
All types in a single file:
src/generated/
└── my-schema.ts💡 Why Codegen?
Without codegen ❌
// Manually write decorated classes for every XSD type
@XmlRoot({ name: "Person" })
class Person {
@XmlAttribute({ name: "id", required: true })
id: string = "";
@XmlElement({ name: "FirstName" })
firstName: string = "";
// ... dozens more properties, easy to get wrong
}With codegen ✅
# One command, always in sync with your schema
npx xml-poto-codegen generateBenefits:
- ✅ Always matches the XSD — no manual drift
- ✅ Handles complex schemas with inheritance, groups, and namespaces
- ✅ Regenerate when schemas change
- ✅ Consistent decorator options and property types
🎓 Best Practices
Commit your config, not the generated code — Add
src/generated/to.gitignoreand run codegen as part of your build pipeline.Use
per-typefor large schemas — Keeps files small and enables tree-shaking.Pin your enum style per-source — Override
enumStyleat the source level when different schemas need different patterns.Regenerate after schema changes — Run
npx xml-poto-codegen generatewhenever your XSD files are updated.
🤝 Contributing
Contributions are welcome! Please see our Contributing Guide.
📄 License
MIT © Ronald Veth - Cerios
