🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@cerios/xml-poto-codegen

Package Overview
Dependencies
Maintainers
2
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cerios/xml-poto-codegen - npm Package Compare versions

Comparing version
1.0.0
to
1.0.1
+335
dist/cli.cjs
#!/usr/bin/env node
const require_xsd_resolver = require("./xsd-resolver-DLsEiJkG.cjs");
let node_fs = require("node:fs");
node_fs = require_xsd_resolver.__toESM(node_fs);
let node_path = require("node:path");
node_path = require_xsd_resolver.__toESM(node_path);
let commander = require("commander");
let node_readline = require("node:readline");
node_readline = require_xsd_resolver.__toESM(node_readline);
//#region package.json
var version = "1.0.1";
//#endregion
//#region src/commands/generate.ts
function registerGenerateCommand(program) {
program.command("generate").description("Generate TypeScript classes from XSD schemas defined in config").action(async () => {
await runGenerate();
});
}
async function runGenerate() {
const { config, configDir } = await require_xsd_resolver.loadConfig();
const parser = new require_xsd_resolver.XsdParser();
const resolver = new require_xsd_resolver.XsdResolver();
let totalFiles = 0;
let totalTypes = 0;
for (const source of config.sources) {
const xsdPath = node_path.default.resolve(configDir, source.xsdPath);
const outputPath = node_path.default.resolve(configDir, source.outputPath);
const outputStyle = source.outputStyle ?? config.defaultOutputStyle ?? "per-type";
const enumStyle = source.enumStyle ?? config.enumStyle ?? "union";
const useXmlRoot = source.useXmlRoot ?? config.useXmlRoot ?? true;
console.log(`\nProcessing: ${xsdPath}`);
const schema = parser.parseFile(xsdPath);
const resolved = resolver.resolve(schema);
reportCoverageWarnings(resolved);
const typeCount = resolved.types.length + resolved.enums.length;
console.log(` Found ${resolved.types.length} type(s), ${resolved.enums.length} enum(s)`);
const generator = new require_xsd_resolver.ClassGenerator({
xsdPath: source.xsdPath,
enumStyle,
useXmlRoot,
elementFormDefault: resolved.elementFormDefault
});
if (outputStyle === "per-xsd") {
assertPerXsdOutputPath(outputPath, source.outputPath);
const outputFileName = node_path.default.basename(outputPath, ".ts");
const writtenFile = require_xsd_resolver.writeGeneratedFile(outputPath, generator.generatePerXsd(resolved, outputFileName)[0]);
console.log(` Generated 1 file → ${writtenFile}`);
totalFiles += 1;
totalTypes += typeCount;
continue;
}
assertPerTypeOutputPath(outputPath, source.outputPath);
const { written } = require_xsd_resolver.writeGeneratedFiles(outputPath, generator.generatePerType(resolved));
console.log(` Generated ${written.length} file(s) → ${outputPath}`);
totalFiles += written.length;
totalTypes += typeCount;
}
console.log(`\nDone! ${totalTypes} type(s) → ${totalFiles} file(s)`);
}
function assertPerTypeOutputPath(resolvedPath, configuredPath) {
if (looksLikeTypeScriptFile(configuredPath)) throw new Error(`Invalid output path for outputStyle 'per-type': '${configuredPath}' looks like a file path. Use a directory path instead.`);
if (!node_fs.default.existsSync(resolvedPath)) return;
if (!node_fs.default.statSync(resolvedPath).isDirectory()) throw new Error(`Invalid output path for outputStyle 'per-type': '${configuredPath}' resolves to a file. Use a directory path instead.`);
}
function assertPerXsdOutputPath(resolvedPath, configuredPath) {
if (!looksLikeTypeScriptFile(configuredPath)) throw new Error(`Invalid output path for outputStyle 'per-xsd': '${configuredPath}' must be a TypeScript file path ending with '.ts'.`);
const outputDir = node_path.default.dirname(resolvedPath);
if (node_fs.default.existsSync(outputDir) && !node_fs.default.statSync(outputDir).isDirectory()) throw new Error(`Invalid output path for outputStyle 'per-xsd': parent path '${node_path.default.dirname(configuredPath)}' is not a directory.`);
if (!node_fs.default.existsSync(resolvedPath)) return;
if (node_fs.default.statSync(resolvedPath).isDirectory()) throw new Error(`Invalid output path for outputStyle 'per-xsd': '${configuredPath}' resolves to a directory. Use a file path instead.`);
}
function looksLikeTypeScriptFile(value) {
return node_path.default.extname(value).toLowerCase() === ".ts";
}
function reportCoverageWarnings(resolved) {
reportMultiRootAliasWarnings(resolved);
const { unsupportedFacetProps, fixedConstraintProps } = collectPropertyCoverageWarnings(resolved);
warnUnsupportedFacets(unsupportedFacetProps);
warnFixedConstraints(fixedConstraintProps);
}
function reportMultiRootAliasWarnings(resolved) {
const multiRootAliases = /* @__PURE__ */ new Map();
for (const root of resolved.rootElements) {
const names = multiRootAliases.get(root.typeName);
if (names) {
names.push(root.name);
continue;
}
multiRootAliases.set(root.typeName, [root.name]);
}
for (const [typeName, rootNames] of multiRootAliases) {
if (rootNames.length <= 1) continue;
console.warn(` Warning: Type '${typeName}' is referenced by multiple root elements (${rootNames.join(", ")}). Using '${rootNames[0]}' as the generated @XmlRoot name.`);
}
}
function collectPropertyCoverageWarnings(resolved) {
const unsupportedFacetProps = [];
const fixedConstraintProps = [];
for (const type of resolved.types) for (const prop of type.properties) {
if (hasUnsupportedFacet(prop)) unsupportedFacetProps.push(`${type.className}.${prop.propertyName}`);
if (prop.fixedValue !== void 0) fixedConstraintProps.push(`${type.className}.${prop.propertyName}`);
}
return {
unsupportedFacetProps,
fixedConstraintProps
};
}
function hasUnsupportedFacet(prop) {
return prop.minLength !== void 0 || prop.maxLength !== void 0 || prop.minInclusive !== void 0 || prop.maxInclusive !== void 0 || prop.minExclusive !== void 0 || prop.maxExclusive !== void 0 || prop.totalDigits !== void 0 || prop.fractionDigits !== void 0 || prop.whiteSpace !== void 0;
}
function warnUnsupportedFacets(unsupportedFacetProps) {
if (unsupportedFacetProps.length === 0) return;
console.warn(` Warning: ${unsupportedFacetProps.length} property(ies) use XSD facets not fully enforced by generated decorators (${unsupportedFacetProps.join(", ")}).`);
}
function warnFixedConstraints(fixedConstraintProps) {
if (fixedConstraintProps.length === 0) return;
console.warn(` Warning: ${fixedConstraintProps.length} property(ies) use XSD fixed constraints. Generated code applies defaults, but strict fixed-value enforcement may require manual validation (${fixedConstraintProps.join(", ")}).`);
}
//#endregion
//#region src/commands/cli-messages.ts
/**
* Fun branding messages for CLI output.
*/
const ceriosMessages = [
"Schemas just got Cerios!",
"Time to get Cerios about XML types!",
"Cerios codegen mode: enabled.",
"This is Cerios-ly a great schema setup!",
"Type generation? We are dead Cerios.",
"Cerios vibes, strongly typed output.",
"You are officially Cerios about XSD now.",
"Cerios business ahead: classes incoming!",
"Don't take XML too Cerios-ly... unless it's codegen.",
"Cerios-ly, you are all set!"
];
/**
* Get a random Cerios message for CLI output.
*/
function getRandomCeriosMessage() {
return ceriosMessages[Math.floor(Math.random() * ceriosMessages.length)];
}
//#endregion
//#region src/commands/init.ts
function registerInitCommand(program) {
program.command("init").description("Create an xml-poto-codegen config file interactively").action(async () => {
await runInit();
});
}
async function runInit() {
const format = await askForConfigFormat();
const configFile = format === "ts" ? "xml-poto-codegen.config.ts" : "xml-poto-codegen.config.json";
const configPath = node_path.default.resolve(process.cwd(), configFile);
if (node_fs.default.existsSync(configPath)) {
if ((await ask(`${configFile} already exists. Overwrite? (y/N): `)).toLowerCase() !== "y") {
console.log("Aborted.");
return;
}
}
const sources = [];
let addMore = true;
while (addMore) {
const xsdPath = await askForXsdPath();
const outputStyle = await askForOutputStyle();
const outputPath = await askForOutputPath(outputStyle, xsdPath);
sources.push({
xsdPath,
outputPath,
outputStyle
});
addMore = (await ask("Add another XSD source? (y/N): ")).toLowerCase() === "y";
}
if (sources.length === 0) {
console.log("No sources configured. Aborted.");
return;
}
const config = {
sources,
defaultOutputStyle: "per-type"
};
if (format === "ts") writeTsConfig(configPath, config);
else writeJsonConfig(configPath, config);
console.log(`\n✓ Created ${configFile}`);
console.log("\nNext steps:");
console.log(" 1. Review and customize your config file if needed");
console.log(" 2. Run 'xml-poto-codegen generate' to generate classes\n");
console.log(`${getRandomCeriosMessage()}\n`);
}
function toPosixPath(p) {
return p.replace(/\\/g, "/");
}
function writeJsonConfig(configPath, config) {
const normalized = {
...config,
sources: config.sources.map((s) => ({
...s,
xsdPath: toPosixPath(s.xsdPath),
outputPath: toPosixPath(s.outputPath)
}))
};
node_fs.default.writeFileSync(configPath, JSON.stringify(normalized, null, " ") + "\n", "utf-8");
}
function writeTsConfig(configPath, config) {
const content = `import type { XmlPotoCodegenConfig } from "@cerios/xml-poto-codegen";
const config: XmlPotoCodegenConfig = {
\tsources: [
${config.sources.map((s) => {
return `\t\t{\n\t\t\txsdPath: "${toPosixPath(s.xsdPath)}",\n\t\t\toutputPath: "${toPosixPath(s.outputPath)}"${s.outputStyle ? `,\n\t\t\toutputStyle: "${s.outputStyle}"` : ""}\n\t\t}`;
}).join(",\n")},
\t],
\tdefaultOutputStyle: "${config.defaultOutputStyle ?? "per-type"}",
};
export default config;
`;
node_fs.default.writeFileSync(configPath, content, "utf-8");
}
function ask(question) {
const rl = node_readline.default.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question(question, (answer) => {
rl.close();
resolve(answer.trim());
});
});
}
async function askForConfigFormat() {
console.log("Select config file format:");
console.log(" 1. TypeScript (xml-poto-codegen.config.ts) [default]");
console.log(" 2. JSON (xml-poto-codegen.config.json)");
while (true) {
const format = parseFormatChoice(await ask("Choose format (1/2, ts/json, Enter for ts): "));
if (format) return format;
console.log("Invalid choice. Please enter 1, 2, ts, or json.");
}
}
function parseFormatChoice(input) {
const normalized = input.trim().toLowerCase();
if (!normalized) return "ts";
if (normalized === "1" || normalized === "ts" || normalized === "typescript" || normalized === ".ts") return "ts";
if (normalized === "2" || normalized === "json" || normalized === ".json") return "json";
}
async function askForOutputStyle() {
console.log("\nSelect output style:");
console.log(" 1. per-type [default] - generates one file per class/enum into a folder");
console.log(" 2. per-xsd - generates all types into a single TypeScript file");
while (true) {
const style = parseOutputStyleChoice(await ask("Choose output style (1/2, per-type/per-xsd, Enter for per-type): "));
if (style) return style;
console.log("Invalid choice. Please enter 1, 2, per-type, or per-xsd.");
}
}
function parseOutputStyleChoice(input) {
const normalized = input.trim().toLowerCase();
if (!normalized) return "per-type";
if (normalized === "1" || normalized === "per-type") return "per-type";
if (normalized === "2" || normalized === "per-xsd") return "per-xsd";
}
async function askForOutputPath(outputStyle, xsdPath) {
if (outputStyle === "per-xsd") return askForOutputFilePath(xsdPath);
return askForOutputDirectoryPath();
}
async function askForOutputDirectoryPath() {
while (true) {
const output = await ask("Output folder (default: ./src/generated): ") || "./src/generated";
if (node_path.default.extname(output).toLowerCase() === ".ts") {
console.log("This looks like a file path. For 'per-type', enter a folder path (example: ./src/generated).");
continue;
}
const resolvedPath = node_path.default.resolve(process.cwd(), output);
if (!node_fs.default.existsSync(resolvedPath)) return output;
if (!node_fs.default.statSync(resolvedPath).isDirectory()) {
console.log("The selected path is an existing file. For 'per-type', choose a folder path.");
continue;
}
return output;
}
}
async function askForOutputFilePath(xsdPath) {
const defaultOutput = buildPerXsdDefaultOutputPath(xsdPath);
while (true) {
const output = await ask(`Output file (default: ${defaultOutput}): `) || defaultOutput;
const resolvedPath = node_path.default.resolve(process.cwd(), output);
if (node_path.default.extname(output).toLowerCase() !== ".ts") {
console.log("For 'per-xsd', enter a TypeScript file path ending in '.ts' (example: ./src/generated/schema.ts).");
continue;
}
if (node_fs.default.existsSync(resolvedPath) && node_fs.default.statSync(resolvedPath).isDirectory()) {
console.log("The selected path is an existing directory. For 'per-xsd', choose a file path.");
continue;
}
const parentPath = node_path.default.dirname(resolvedPath);
if (node_fs.default.existsSync(parentPath) && !node_fs.default.statSync(parentPath).isDirectory()) {
console.log("The parent path is not a directory. Please choose a valid file path.");
continue;
}
return output;
}
}
function buildPerXsdDefaultOutputPath(xsdPath) {
return `./src/generated/${node_path.default.basename(xsdPath, node_path.default.extname(xsdPath)).trim() || "generated"}.ts`;
}
async function askForXsdPath() {
while (true) {
const xsdPath = await ask("XSD file path: ");
if (!xsdPath) {
console.log("XSD path is required.");
continue;
}
const resolvedPath = node_path.default.resolve(process.cwd(), xsdPath);
if (!node_fs.default.existsSync(resolvedPath)) {
console.log(`Path does not exist yet: ${resolvedPath}`);
if ((await ask("Use this path anyway? (y/N): ")).toLowerCase() === "y") return xsdPath;
continue;
}
if (node_fs.default.statSync(resolvedPath).isDirectory()) {
console.log("The path points to a directory. Please enter a file path to an XSD file.");
continue;
}
return xsdPath;
}
}
//#endregion
//#region src/cli.ts
const program = new commander.Command();
program.name("xml-poto-codegen").description("Generate TypeScript classes with @cerios/xml-poto decorators from XSD schemas").version(version);
registerInitCommand(program);
registerGenerateCommand(program);
program.parse();
//#endregion
//# sourceMappingURL=cli.cjs.map
{"version":3,"file":"cli.cjs","names":["loadConfig","XsdParser","XsdResolver","path","ClassGenerator","writeGeneratedFile","writeGeneratedFiles","fs","path","fs","readline","Command"],"sources":["../package.json","../src/commands/generate.ts","../src/commands/cli-messages.ts","../src/commands/init.ts","../src/cli.ts"],"sourcesContent":["","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { Command } from \"commander\";\n\nimport { loadConfig } from \"../config/config-loader\";\nimport { ClassGenerator } from \"../generator/class-generator\";\nimport { writeGeneratedFile, writeGeneratedFiles } from \"../generator/file-writer\";\nimport { XsdParser } from \"../xsd/xsd-parser\";\nimport { XsdResolver } from \"../xsd/xsd-resolver\";\n\nexport function registerGenerateCommand(program: Command): void {\n\tprogram\n\t\t.command(\"generate\")\n\t\t.description(\"Generate TypeScript classes from XSD schemas defined in config\")\n\t\t.action(async () => {\n\t\t\tawait runGenerate();\n\t\t});\n}\n\nasync function runGenerate(): Promise<void> {\n\tconst { config, configDir } = await loadConfig();\n\n\tconst parser = new XsdParser();\n\tconst resolver = new XsdResolver();\n\n\tlet totalFiles = 0;\n\tlet totalTypes = 0;\n\n\tfor (const source of config.sources) {\n\t\tconst xsdPath = path.resolve(configDir, source.xsdPath);\n\t\tconst outputPath = path.resolve(configDir, source.outputPath);\n\t\tconst outputStyle = source.outputStyle ?? config.defaultOutputStyle ?? \"per-type\";\n\t\tconst enumStyle = source.enumStyle ?? config.enumStyle ?? \"union\";\n\t\tconst useXmlRoot = source.useXmlRoot ?? config.useXmlRoot ?? true;\n\n\t\tconsole.log(`\\nProcessing: ${xsdPath}`);\n\n\t\t// Parse XSD\n\t\tconst schema = parser.parseFile(xsdPath);\n\n\t\t// Resolve types\n\t\tconst resolved = resolver.resolve(schema);\n\t\treportCoverageWarnings(resolved);\n\n\t\tconst typeCount = resolved.types.length + resolved.enums.length;\n\t\tconsole.log(` Found ${resolved.types.length} type(s), ${resolved.enums.length} enum(s)`);\n\n\t\t// Generate code\n\t\tconst generator = new ClassGenerator({\n\t\t\txsdPath: source.xsdPath,\n\t\t\tenumStyle,\n\t\t\tuseXmlRoot,\n\t\t\telementFormDefault: resolved.elementFormDefault,\n\t\t});\n\n\t\tif (outputStyle === \"per-xsd\") {\n\t\t\tassertPerXsdOutputPath(outputPath, source.outputPath);\n\n\t\t\tconst outputFileName = path.basename(outputPath, \".ts\");\n\t\t\tconst files = generator.generatePerXsd(resolved, outputFileName);\n\t\t\tconst writtenFile = writeGeneratedFile(outputPath, files[0]);\n\n\t\t\tconsole.log(` Generated 1 file → ${writtenFile}`);\n\n\t\t\ttotalFiles += 1;\n\t\t\ttotalTypes += typeCount;\n\t\t\tcontinue;\n\t\t}\n\n\t\tassertPerTypeOutputPath(outputPath, source.outputPath);\n\t\tconst files = generator.generatePerType(resolved);\n\n\t\t// Write files\n\t\tconst { written } = writeGeneratedFiles(outputPath, files);\n\n\t\tconsole.log(` Generated ${written.length} file(s) → ${outputPath}`);\n\n\t\ttotalFiles += written.length;\n\t\ttotalTypes += typeCount;\n\t}\n\n\tconsole.log(`\\nDone! ${totalTypes} type(s) → ${totalFiles} file(s)`);\n}\n\nfunction assertPerTypeOutputPath(resolvedPath: string, configuredPath: string): void {\n\tif (looksLikeTypeScriptFile(configuredPath)) {\n\t\tthrow new Error(\n\t\t\t`Invalid output path for outputStyle 'per-type': '${configuredPath}' looks like a file path. Use a directory path instead.`,\n\t\t);\n\t}\n\n\tif (!fs.existsSync(resolvedPath)) {\n\t\treturn;\n\t}\n\n\tif (!fs.statSync(resolvedPath).isDirectory()) {\n\t\tthrow new Error(\n\t\t\t`Invalid output path for outputStyle 'per-type': '${configuredPath}' resolves to a file. Use a directory path instead.`,\n\t\t);\n\t}\n}\n\nfunction assertPerXsdOutputPath(resolvedPath: string, configuredPath: string): void {\n\tif (!looksLikeTypeScriptFile(configuredPath)) {\n\t\tthrow new Error(\n\t\t\t`Invalid output path for outputStyle 'per-xsd': '${configuredPath}' must be a TypeScript file path ending with '.ts'.`,\n\t\t);\n\t}\n\n\tconst outputDir = path.dirname(resolvedPath);\n\tif (fs.existsSync(outputDir) && !fs.statSync(outputDir).isDirectory()) {\n\t\tthrow new Error(\n\t\t\t`Invalid output path for outputStyle 'per-xsd': parent path '${path.dirname(configuredPath)}' is not a directory.`,\n\t\t);\n\t}\n\n\tif (!fs.existsSync(resolvedPath)) {\n\t\treturn;\n\t}\n\n\tif (fs.statSync(resolvedPath).isDirectory()) {\n\t\tthrow new Error(\n\t\t\t`Invalid output path for outputStyle 'per-xsd': '${configuredPath}' resolves to a directory. Use a file path instead.`,\n\t\t);\n\t}\n}\n\nfunction looksLikeTypeScriptFile(value: string): boolean {\n\treturn path.extname(value).toLowerCase() === \".ts\";\n}\n\nfunction reportCoverageWarnings(resolved: ReturnType<XsdResolver[\"resolve\"]>): void {\n\treportMultiRootAliasWarnings(resolved);\n\n\tconst { unsupportedFacetProps, fixedConstraintProps } = collectPropertyCoverageWarnings(resolved);\n\twarnUnsupportedFacets(unsupportedFacetProps);\n\twarnFixedConstraints(fixedConstraintProps);\n}\n\nfunction reportMultiRootAliasWarnings(resolved: ReturnType<XsdResolver[\"resolve\"]>): void {\n\tconst multiRootAliases = new Map<string, string[]>();\n\n\tfor (const root of resolved.rootElements) {\n\t\tconst names = multiRootAliases.get(root.typeName);\n\t\tif (names) {\n\t\t\tnames.push(root.name);\n\t\t\tcontinue;\n\t\t}\n\n\t\tmultiRootAliases.set(root.typeName, [root.name]);\n\t}\n\n\tfor (const [typeName, rootNames] of multiRootAliases) {\n\t\tif (rootNames.length <= 1) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconsole.warn(\n\t\t\t` Warning: Type '${typeName}' is referenced by multiple root elements (${rootNames.join(\", \")}). Using '${rootNames[0]}' as the generated @XmlRoot name.`,\n\t\t);\n\t}\n}\n\nfunction collectPropertyCoverageWarnings(resolved: ReturnType<XsdResolver[\"resolve\"]>): {\n\tunsupportedFacetProps: string[];\n\tfixedConstraintProps: string[];\n} {\n\tconst unsupportedFacetProps: string[] = [];\n\tconst fixedConstraintProps: string[] = [];\n\n\tfor (const type of resolved.types) {\n\t\tfor (const prop of type.properties) {\n\t\t\tif (hasUnsupportedFacet(prop)) {\n\t\t\t\tunsupportedFacetProps.push(`${type.className}.${prop.propertyName}`);\n\t\t\t}\n\n\t\t\tif (prop.fixedValue !== undefined) {\n\t\t\t\tfixedConstraintProps.push(`${type.className}.${prop.propertyName}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { unsupportedFacetProps, fixedConstraintProps };\n}\n\nfunction hasUnsupportedFacet(prop: ReturnType<XsdResolver[\"resolve\"]>[\"types\"][number][\"properties\"][number]): boolean {\n\treturn (\n\t\tprop.minLength !== undefined ||\n\t\tprop.maxLength !== undefined ||\n\t\tprop.minInclusive !== undefined ||\n\t\tprop.maxInclusive !== undefined ||\n\t\tprop.minExclusive !== undefined ||\n\t\tprop.maxExclusive !== undefined ||\n\t\tprop.totalDigits !== undefined ||\n\t\tprop.fractionDigits !== undefined ||\n\t\tprop.whiteSpace !== undefined\n\t);\n}\n\nfunction warnUnsupportedFacets(unsupportedFacetProps: string[]): void {\n\tif (unsupportedFacetProps.length === 0) {\n\t\treturn;\n\t}\n\n\tconsole.warn(\n\t\t` Warning: ${unsupportedFacetProps.length} property(ies) use XSD facets not fully enforced by generated decorators (${unsupportedFacetProps.join(\", \")}).`,\n\t);\n}\n\nfunction warnFixedConstraints(fixedConstraintProps: string[]): void {\n\tif (fixedConstraintProps.length === 0) {\n\t\treturn;\n\t}\n\n\tconsole.warn(\n\t\t` Warning: ${fixedConstraintProps.length} property(ies) use XSD fixed constraints. Generated code applies defaults, but strict fixed-value enforcement may require manual validation (${fixedConstraintProps.join(\", \")}).`,\n\t);\n}\n","/**\n * Fun branding messages for CLI output.\n */\nexport const ceriosMessages = [\n\t\"Schemas just got Cerios!\",\n\t\"Time to get Cerios about XML types!\",\n\t\"Cerios codegen mode: enabled.\",\n\t\"This is Cerios-ly a great schema setup!\",\n\t\"Type generation? We are dead Cerios.\",\n\t\"Cerios vibes, strongly typed output.\",\n\t\"You are officially Cerios about XSD now.\",\n\t\"Cerios business ahead: classes incoming!\",\n\t\"Don't take XML too Cerios-ly... unless it's codegen.\",\n\t\"Cerios-ly, you are all set!\",\n] as const;\n\n/**\n * Get a random Cerios message for CLI output.\n */\nexport function getRandomCeriosMessage(): string {\n\treturn ceriosMessages[Math.floor(Math.random() * ceriosMessages.length)];\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport readline from \"node:readline\";\n\nimport type { Command } from \"commander\";\n\nimport type { XmlPotoCodegenConfig, XsdSource } from \"../config/config-types\";\n\nimport { getRandomCeriosMessage } from \"./cli-messages\";\n\nexport function registerInitCommand(program: Command): void {\n\tprogram\n\t\t.command(\"init\")\n\t\t.description(\"Create an xml-poto-codegen config file interactively\")\n\t\t.action(async () => {\n\t\t\tawait runInit();\n\t\t});\n}\n\nasync function runInit(): Promise<void> {\n\tconst format = await askForConfigFormat();\n\tconst configFile = format === \"ts\" ? \"xml-poto-codegen.config.ts\" : \"xml-poto-codegen.config.json\";\n\tconst configPath = path.resolve(process.cwd(), configFile);\n\n\tif (fs.existsSync(configPath)) {\n\t\tconst overwrite = await ask(`${configFile} already exists. Overwrite? (y/N): `);\n\t\tif (overwrite.toLowerCase() !== \"y\") {\n\t\t\tconsole.log(\"Aborted.\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tconst sources: XsdSource[] = [];\n\tlet addMore = true;\n\n\twhile (addMore) {\n\t\tconst xsdPath = await askForXsdPath();\n\t\tconst outputStyle = await askForOutputStyle();\n\t\tconst outputPath = await askForOutputPath(outputStyle, xsdPath);\n\n\t\tsources.push({ xsdPath, outputPath, outputStyle });\n\n\t\tconst more = await ask(\"Add another XSD source? (y/N): \");\n\t\taddMore = more.toLowerCase() === \"y\";\n\t}\n\n\tif (sources.length === 0) {\n\t\tconsole.log(\"No sources configured. Aborted.\");\n\t\treturn;\n\t}\n\n\tconst config: XmlPotoCodegenConfig = {\n\t\tsources,\n\t\tdefaultOutputStyle: \"per-type\",\n\t};\n\n\tif (format === \"ts\") {\n\t\twriteTsConfig(configPath, config);\n\t} else {\n\t\twriteJsonConfig(configPath, config);\n\t}\n\n\tconsole.log(`\\n✓ Created ${configFile}`);\n\tconsole.log(\"\\nNext steps:\");\n\tconsole.log(\" 1. Review and customize your config file if needed\");\n\tconsole.log(\" 2. Run 'xml-poto-codegen generate' to generate classes\\n\");\n\n\tconsole.log(`${getRandomCeriosMessage()}\\n`);\n}\n\nfunction toPosixPath(p: string): string {\n\treturn p.replace(/\\\\/g, \"/\");\n}\n\nexport function writeJsonConfig(configPath: string, config: XmlPotoCodegenConfig): void {\n\tconst normalized = {\n\t\t...config,\n\t\tsources: config.sources.map((s) => ({\n\t\t\t...s,\n\t\t\txsdPath: toPosixPath(s.xsdPath),\n\t\t\toutputPath: toPosixPath(s.outputPath),\n\t\t})),\n\t};\n\tfs.writeFileSync(configPath, JSON.stringify(normalized, null, \"\\t\") + \"\\n\", \"utf-8\");\n}\n\nexport function writeTsConfig(configPath: string, config: XmlPotoCodegenConfig): void {\n\tconst sourcesStr = config.sources\n\t\t.map((s) => {\n\t\t\tconst xsdPath = toPosixPath(s.xsdPath);\n\t\t\tconst outputPath = toPosixPath(s.outputPath);\n\t\t\tconst styleLine = s.outputStyle ? `,\\n\\t\\t\\toutputStyle: \"${s.outputStyle}\"` : \"\";\n\t\t\treturn `\\t\\t{\\n\\t\\t\\txsdPath: \"${xsdPath}\",\\n\\t\\t\\toutputPath: \"${outputPath}\"${styleLine}\\n\\t\\t}`;\n\t\t})\n\t\t.join(\",\\n\");\n\n\tconst content = `import type { XmlPotoCodegenConfig } from \"@cerios/xml-poto-codegen\";\n\nconst config: XmlPotoCodegenConfig = {\n\\tsources: [\n${sourcesStr},\n\\t],\n\\tdefaultOutputStyle: \"${config.defaultOutputStyle ?? \"per-type\"}\",\n};\n\nexport default config;\n`;\n\n\tfs.writeFileSync(configPath, content, \"utf-8\");\n}\n\nfunction ask(question: string): Promise<string> {\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t});\n\n\treturn new Promise((resolve) => {\n\t\trl.question(question, (answer) => {\n\t\t\trl.close();\n\t\t\tresolve(answer.trim());\n\t\t});\n\t});\n}\n\nasync function askForConfigFormat(): Promise<\"json\" | \"ts\"> {\n\tconsole.log(\"Select config file format:\");\n\tconsole.log(\" 1. TypeScript (xml-poto-codegen.config.ts) [default]\");\n\tconsole.log(\" 2. JSON (xml-poto-codegen.config.json)\");\n\n\twhile (true) {\n\t\tconst answer = await ask(\"Choose format (1/2, ts/json, Enter for ts): \");\n\t\tconst format = parseFormatChoice(answer);\n\n\t\tif (format) {\n\t\t\treturn format;\n\t\t}\n\n\t\tconsole.log(\"Invalid choice. Please enter 1, 2, ts, or json.\");\n\t}\n}\n\nfunction parseFormatChoice(input: string): \"json\" | \"ts\" | undefined {\n\tconst normalized = input.trim().toLowerCase();\n\n\tif (!normalized) {\n\t\treturn \"ts\";\n\t}\n\n\tif (normalized === \"1\" || normalized === \"ts\" || normalized === \"typescript\" || normalized === \".ts\") {\n\t\treturn \"ts\";\n\t}\n\n\tif (normalized === \"2\" || normalized === \"json\" || normalized === \".json\") {\n\t\treturn \"json\";\n\t}\n\n\treturn undefined;\n}\n\nasync function askForOutputStyle(): Promise<\"per-type\" | \"per-xsd\"> {\n\tconsole.log(\"\\nSelect output style:\");\n\tconsole.log(\" 1. per-type [default] - generates one file per class/enum into a folder\");\n\tconsole.log(\" 2. per-xsd - generates all types into a single TypeScript file\");\n\n\twhile (true) {\n\t\tconst answer = await ask(\"Choose output style (1/2, per-type/per-xsd, Enter for per-type): \");\n\t\tconst style = parseOutputStyleChoice(answer);\n\n\t\tif (style) {\n\t\t\treturn style;\n\t\t}\n\n\t\tconsole.log(\"Invalid choice. Please enter 1, 2, per-type, or per-xsd.\");\n\t}\n}\n\nfunction parseOutputStyleChoice(input: string): \"per-type\" | \"per-xsd\" | undefined {\n\tconst normalized = input.trim().toLowerCase();\n\n\tif (!normalized) {\n\t\treturn \"per-type\";\n\t}\n\n\tif (normalized === \"1\" || normalized === \"per-type\") {\n\t\treturn \"per-type\";\n\t}\n\n\tif (normalized === \"2\" || normalized === \"per-xsd\") {\n\t\treturn \"per-xsd\";\n\t}\n\n\treturn undefined;\n}\n\nasync function askForOutputPath(outputStyle: \"per-type\" | \"per-xsd\", xsdPath: string): Promise<string> {\n\tif (outputStyle === \"per-xsd\") {\n\t\treturn askForOutputFilePath(xsdPath);\n\t}\n\n\treturn askForOutputDirectoryPath();\n}\n\nasync function askForOutputDirectoryPath(): Promise<string> {\n\twhile (true) {\n\t\tconst output = (await ask(\"Output folder (default: ./src/generated): \")) || \"./src/generated\";\n\n\t\tif (path.extname(output).toLowerCase() === \".ts\") {\n\t\t\tconsole.log(\"This looks like a file path. For 'per-type', enter a folder path (example: ./src/generated).\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst resolvedPath = path.resolve(process.cwd(), output);\n\t\tif (!fs.existsSync(resolvedPath)) {\n\t\t\treturn output;\n\t\t}\n\n\t\tif (!fs.statSync(resolvedPath).isDirectory()) {\n\t\t\tconsole.log(\"The selected path is an existing file. For 'per-type', choose a folder path.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn output;\n\t}\n}\n\nasync function askForOutputFilePath(xsdPath: string): Promise<string> {\n\tconst defaultOutput = buildPerXsdDefaultOutputPath(xsdPath);\n\n\twhile (true) {\n\t\tconst output = (await ask(`Output file (default: ${defaultOutput}): `)) || defaultOutput;\n\t\tconst resolvedPath = path.resolve(process.cwd(), output);\n\n\t\tif (path.extname(output).toLowerCase() !== \".ts\") {\n\t\t\tconsole.log(\"For 'per-xsd', enter a TypeScript file path ending in '.ts' (example: ./src/generated/schema.ts).\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isDirectory()) {\n\t\t\tconsole.log(\"The selected path is an existing directory. For 'per-xsd', choose a file path.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst parentPath = path.dirname(resolvedPath);\n\t\tif (fs.existsSync(parentPath) && !fs.statSync(parentPath).isDirectory()) {\n\t\t\tconsole.log(\"The parent path is not a directory. Please choose a valid file path.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn output;\n\t}\n}\n\nfunction buildPerXsdDefaultOutputPath(xsdPath: string): string {\n\tconst base = path.basename(xsdPath, path.extname(xsdPath)).trim();\n\tconst fileName = base || \"generated\";\n\treturn `./src/generated/${fileName}.ts`;\n}\n\nasync function askForXsdPath(): Promise<string> {\n\twhile (true) {\n\t\tconst xsdPath = await ask(\"XSD file path: \");\n\n\t\tif (!xsdPath) {\n\t\t\tconsole.log(\"XSD path is required.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst resolvedPath = path.resolve(process.cwd(), xsdPath);\n\n\t\tif (!fs.existsSync(resolvedPath)) {\n\t\t\tconsole.log(`Path does not exist yet: ${resolvedPath}`);\n\t\t\tconst useAnyway = await ask(\"Use this path anyway? (y/N): \");\n\t\t\tif (useAnyway.toLowerCase() === \"y\") {\n\t\t\t\treturn xsdPath;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (fs.statSync(resolvedPath).isDirectory()) {\n\t\t\tconsole.log(\"The path points to a directory. Please enter a file path to an XSD file.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn xsdPath;\n\t}\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\n\n// Read the CLI version from this package's package.json so it stays in sync.\nimport { version } from \"../package.json\";\n\nimport { registerGenerateCommand } from \"./commands/generate\";\nimport { registerInitCommand } from \"./commands/init\";\n\nconst program = new Command();\n\nprogram\n\t.name(\"xml-poto-codegen\")\n\t.description(\"Generate TypeScript classes with @cerios/xml-poto decorators from XSD schemas\")\n\t.version(version);\n\nregisterInitCommand(program);\nregisterGenerateCommand(program);\n\nprogram.parse();\n"],"mappings":";;;;;;;;;;;;;ACWA,SAAgB,wBAAwB,SAAwB;AAC/D,SACE,QAAQ,WAAW,CACnB,YAAY,iEAAiE,CAC7E,OAAO,YAAY;AACnB,QAAM,aAAa;GAClB;;AAGJ,eAAe,cAA6B;CAC3C,MAAM,EAAE,QAAQ,cAAc,MAAMA,qBAAAA,YAAY;CAEhD,MAAM,SAAS,IAAIC,qBAAAA,WAAW;CAC9B,MAAM,WAAW,IAAIC,qBAAAA,aAAa;CAElC,IAAI,aAAa;CACjB,IAAI,aAAa;AAEjB,MAAK,MAAM,UAAU,OAAO,SAAS;EACpC,MAAM,UAAUC,UAAAA,QAAK,QAAQ,WAAW,OAAO,QAAQ;EACvD,MAAM,aAAaA,UAAAA,QAAK,QAAQ,WAAW,OAAO,WAAW;EAC7D,MAAM,cAAc,OAAO,eAAe,OAAO,sBAAsB;EACvE,MAAM,YAAY,OAAO,aAAa,OAAO,aAAa;EAC1D,MAAM,aAAa,OAAO,cAAc,OAAO,cAAc;AAE7D,UAAQ,IAAI,iBAAiB,UAAU;EAGvC,MAAM,SAAS,OAAO,UAAU,QAAQ;EAGxC,MAAM,WAAW,SAAS,QAAQ,OAAO;AACzC,yBAAuB,SAAS;EAEhC,MAAM,YAAY,SAAS,MAAM,SAAS,SAAS,MAAM;AACzD,UAAQ,IAAI,WAAW,SAAS,MAAM,OAAO,YAAY,SAAS,MAAM,OAAO,UAAU;EAGzF,MAAM,YAAY,IAAIC,qBAAAA,eAAe;GACpC,SAAS,OAAO;GAChB;GACA;GACA,oBAAoB,SAAS;GAC7B,CAAC;AAEF,MAAI,gBAAgB,WAAW;AAC9B,0BAAuB,YAAY,OAAO,WAAW;GAErD,MAAM,iBAAiBD,UAAAA,QAAK,SAAS,YAAY,MAAM;GAEvD,MAAM,cAAcE,qBAAAA,mBAAmB,YADzB,UAAU,eAAe,UAAU,eACO,CAAC,GAAG;AAE5D,WAAQ,IAAI,wBAAwB,cAAc;AAElD,iBAAc;AACd,iBAAc;AACd;;AAGD,0BAAwB,YAAY,OAAO,WAAW;EAItD,MAAM,EAAE,YAAYC,qBAAAA,oBAAoB,YAH1B,UAAU,gBAAgB,SAGiB,CAAC;AAE1D,UAAQ,IAAI,eAAe,QAAQ,OAAO,aAAa,aAAa;AAEpE,gBAAc,QAAQ;AACtB,gBAAc;;AAGf,SAAQ,IAAI,WAAW,WAAW,aAAa,WAAW,UAAU;;AAGrE,SAAS,wBAAwB,cAAsB,gBAA8B;AACpF,KAAI,wBAAwB,eAAe,CAC1C,OAAM,IAAI,MACT,oDAAoD,eAAe,yDACnE;AAGF,KAAI,CAACC,QAAAA,QAAG,WAAW,aAAa,CAC/B;AAGD,KAAI,CAACA,QAAAA,QAAG,SAAS,aAAa,CAAC,aAAa,CAC3C,OAAM,IAAI,MACT,oDAAoD,eAAe,qDACnE;;AAIH,SAAS,uBAAuB,cAAsB,gBAA8B;AACnF,KAAI,CAAC,wBAAwB,eAAe,CAC3C,OAAM,IAAI,MACT,mDAAmD,eAAe,qDAClE;CAGF,MAAM,YAAYJ,UAAAA,QAAK,QAAQ,aAAa;AAC5C,KAAII,QAAAA,QAAG,WAAW,UAAU,IAAI,CAACA,QAAAA,QAAG,SAAS,UAAU,CAAC,aAAa,CACpE,OAAM,IAAI,MACT,+DAA+DJ,UAAAA,QAAK,QAAQ,eAAe,CAAC,uBAC5F;AAGF,KAAI,CAACI,QAAAA,QAAG,WAAW,aAAa,CAC/B;AAGD,KAAIA,QAAAA,QAAG,SAAS,aAAa,CAAC,aAAa,CAC1C,OAAM,IAAI,MACT,mDAAmD,eAAe,qDAClE;;AAIH,SAAS,wBAAwB,OAAwB;AACxD,QAAOJ,UAAAA,QAAK,QAAQ,MAAM,CAAC,aAAa,KAAK;;AAG9C,SAAS,uBAAuB,UAAoD;AACnF,8BAA6B,SAAS;CAEtC,MAAM,EAAE,uBAAuB,yBAAyB,gCAAgC,SAAS;AACjG,uBAAsB,sBAAsB;AAC5C,sBAAqB,qBAAqB;;AAG3C,SAAS,6BAA6B,UAAoD;CACzF,MAAM,mCAAmB,IAAI,KAAuB;AAEpD,MAAK,MAAM,QAAQ,SAAS,cAAc;EACzC,MAAM,QAAQ,iBAAiB,IAAI,KAAK,SAAS;AACjD,MAAI,OAAO;AACV,SAAM,KAAK,KAAK,KAAK;AACrB;;AAGD,mBAAiB,IAAI,KAAK,UAAU,CAAC,KAAK,KAAK,CAAC;;AAGjD,MAAK,MAAM,CAAC,UAAU,cAAc,kBAAkB;AACrD,MAAI,UAAU,UAAU,EACvB;AAGD,UAAQ,KACP,oBAAoB,SAAS,6CAA6C,UAAU,KAAK,KAAK,CAAC,YAAY,UAAU,GAAG,mCACxH;;;AAIH,SAAS,gCAAgC,UAGvC;CACD,MAAM,wBAAkC,EAAE;CAC1C,MAAM,uBAAiC,EAAE;AAEzC,MAAK,MAAM,QAAQ,SAAS,MAC3B,MAAK,MAAM,QAAQ,KAAK,YAAY;AACnC,MAAI,oBAAoB,KAAK,CAC5B,uBAAsB,KAAK,GAAG,KAAK,UAAU,GAAG,KAAK,eAAe;AAGrE,MAAI,KAAK,eAAe,KAAA,EACvB,sBAAqB,KAAK,GAAG,KAAK,UAAU,GAAG,KAAK,eAAe;;AAKtE,QAAO;EAAE;EAAuB;EAAsB;;AAGvD,SAAS,oBAAoB,MAA0F;AACtH,QACC,KAAK,cAAc,KAAA,KACnB,KAAK,cAAc,KAAA,KACnB,KAAK,iBAAiB,KAAA,KACtB,KAAK,iBAAiB,KAAA,KACtB,KAAK,iBAAiB,KAAA,KACtB,KAAK,iBAAiB,KAAA,KACtB,KAAK,gBAAgB,KAAA,KACrB,KAAK,mBAAmB,KAAA,KACxB,KAAK,eAAe,KAAA;;AAItB,SAAS,sBAAsB,uBAAuC;AACrE,KAAI,sBAAsB,WAAW,EACpC;AAGD,SAAQ,KACP,cAAc,sBAAsB,OAAO,4EAA4E,sBAAsB,KAAK,KAAK,CAAC,IACxJ;;AAGF,SAAS,qBAAqB,sBAAsC;AACnE,KAAI,qBAAqB,WAAW,EACnC;AAGD,SAAQ,KACP,cAAc,qBAAqB,OAAO,+IAA+I,qBAAqB,KAAK,KAAK,CAAC,IACzN;;;;;;;ACtNF,MAAa,iBAAiB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;AAKD,SAAgB,yBAAiC;AAChD,QAAO,eAAe,KAAK,MAAM,KAAK,QAAQ,GAAG,eAAe,OAAO;;;;ACVxE,SAAgB,oBAAoB,SAAwB;AAC3D,SACE,QAAQ,OAAO,CACf,YAAY,uDAAuD,CACnE,OAAO,YAAY;AACnB,QAAM,SAAS;GACd;;AAGJ,eAAe,UAAyB;CACvC,MAAM,SAAS,MAAM,oBAAoB;CACzC,MAAM,aAAa,WAAW,OAAO,+BAA+B;CACpE,MAAM,aAAaK,UAAAA,QAAK,QAAQ,QAAQ,KAAK,EAAE,WAAW;AAE1D,KAAIC,QAAAA,QAAG,WAAW,WAAW;OAExB,MADoB,IAAI,GAAG,WAAW,qCAAqC,EACjE,aAAa,KAAK,KAAK;AACpC,WAAQ,IAAI,WAAW;AACvB;;;CAIF,MAAM,UAAuB,EAAE;CAC/B,IAAI,UAAU;AAEd,QAAO,SAAS;EACf,MAAM,UAAU,MAAM,eAAe;EACrC,MAAM,cAAc,MAAM,mBAAmB;EAC7C,MAAM,aAAa,MAAM,iBAAiB,aAAa,QAAQ;AAE/D,UAAQ,KAAK;GAAE;GAAS;GAAY;GAAa,CAAC;AAGlD,aAAU,MADS,IAAI,kCAAkC,EAC1C,aAAa,KAAK;;AAGlC,KAAI,QAAQ,WAAW,GAAG;AACzB,UAAQ,IAAI,kCAAkC;AAC9C;;CAGD,MAAM,SAA+B;EACpC;EACA,oBAAoB;EACpB;AAED,KAAI,WAAW,KACd,eAAc,YAAY,OAAO;KAEjC,iBAAgB,YAAY,OAAO;AAGpC,SAAQ,IAAI,eAAe,aAAa;AACxC,SAAQ,IAAI,gBAAgB;AAC5B,SAAQ,IAAI,uDAAuD;AACnE,SAAQ,IAAI,6DAA6D;AAEzE,SAAQ,IAAI,GAAG,wBAAwB,CAAC,IAAI;;AAG7C,SAAS,YAAY,GAAmB;AACvC,QAAO,EAAE,QAAQ,OAAO,IAAI;;AAG7B,SAAgB,gBAAgB,YAAoB,QAAoC;CACvF,MAAM,aAAa;EAClB,GAAG;EACH,SAAS,OAAO,QAAQ,KAAK,OAAO;GACnC,GAAG;GACH,SAAS,YAAY,EAAE,QAAQ;GAC/B,YAAY,YAAY,EAAE,WAAW;GACrC,EAAE;EACH;AACD,SAAA,QAAG,cAAc,YAAY,KAAK,UAAU,YAAY,MAAM,IAAK,GAAG,MAAM,QAAQ;;AAGrF,SAAgB,cAAc,YAAoB,QAAoC;CAUrF,MAAM,UAAU;;;;EATG,OAAO,QACxB,KAAK,MAAM;AAIX,SAAO,0BAHS,YAAY,EAAE,QAGU,CAAC,yBAFtB,YAAY,EAAE,WAE2C,CAAC,GAD3D,EAAE,cAAc,0BAA0B,EAAE,YAAY,KAAK,GACW;GACzF,CACD,KAAK,MAMI,CAAC;;yBAEY,OAAO,sBAAsB,WAAW;;;;;AAMhE,SAAA,QAAG,cAAc,YAAY,SAAS,QAAQ;;AAG/C,SAAS,IAAI,UAAmC;CAC/C,MAAM,KAAKC,cAAAA,QAAS,gBAAgB;EACnC,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,CAAC;AAEF,QAAO,IAAI,SAAS,YAAY;AAC/B,KAAG,SAAS,WAAW,WAAW;AACjC,MAAG,OAAO;AACV,WAAQ,OAAO,MAAM,CAAC;IACrB;GACD;;AAGH,eAAe,qBAA6C;AAC3D,SAAQ,IAAI,6BAA6B;AACzC,SAAQ,IAAI,yDAAyD;AACrE,SAAQ,IAAI,2CAA2C;AAEvD,QAAO,MAAM;EAEZ,MAAM,SAAS,kBAAkB,MADZ,IAAI,+CAA+C,CAChC;AAExC,MAAI,OACH,QAAO;AAGR,UAAQ,IAAI,kDAAkD;;;AAIhE,SAAS,kBAAkB,OAA0C;CACpE,MAAM,aAAa,MAAM,MAAM,CAAC,aAAa;AAE7C,KAAI,CAAC,WACJ,QAAO;AAGR,KAAI,eAAe,OAAO,eAAe,QAAQ,eAAe,gBAAgB,eAAe,MAC9F,QAAO;AAGR,KAAI,eAAe,OAAO,eAAe,UAAU,eAAe,QACjE,QAAO;;AAMT,eAAe,oBAAqD;AACnE,SAAQ,IAAI,yBAAyB;AACrC,SAAQ,IAAI,4EAA4E;AACxF,SAAQ,IAAI,mEAAmE;AAE/E,QAAO,MAAM;EAEZ,MAAM,QAAQ,uBAAuB,MADhB,IAAI,oEAAoE,CACjD;AAE5C,MAAI,MACH,QAAO;AAGR,UAAQ,IAAI,2DAA2D;;;AAIzE,SAAS,uBAAuB,OAAmD;CAClF,MAAM,aAAa,MAAM,MAAM,CAAC,aAAa;AAE7C,KAAI,CAAC,WACJ,QAAO;AAGR,KAAI,eAAe,OAAO,eAAe,WACxC,QAAO;AAGR,KAAI,eAAe,OAAO,eAAe,UACxC,QAAO;;AAMT,eAAe,iBAAiB,aAAqC,SAAkC;AACtG,KAAI,gBAAgB,UACnB,QAAO,qBAAqB,QAAQ;AAGrC,QAAO,2BAA2B;;AAGnC,eAAe,4BAA6C;AAC3D,QAAO,MAAM;EACZ,MAAM,SAAU,MAAM,IAAI,6CAA6C,IAAK;AAE5E,MAAIF,UAAAA,QAAK,QAAQ,OAAO,CAAC,aAAa,KAAK,OAAO;AACjD,WAAQ,IAAI,+FAA+F;AAC3G;;EAGD,MAAM,eAAeA,UAAAA,QAAK,QAAQ,QAAQ,KAAK,EAAE,OAAO;AACxD,MAAI,CAACC,QAAAA,QAAG,WAAW,aAAa,CAC/B,QAAO;AAGR,MAAI,CAACA,QAAAA,QAAG,SAAS,aAAa,CAAC,aAAa,EAAE;AAC7C,WAAQ,IAAI,+EAA+E;AAC3F;;AAGD,SAAO;;;AAIT,eAAe,qBAAqB,SAAkC;CACrE,MAAM,gBAAgB,6BAA6B,QAAQ;AAE3D,QAAO,MAAM;EACZ,MAAM,SAAU,MAAM,IAAI,yBAAyB,cAAc,KAAK,IAAK;EAC3E,MAAM,eAAeD,UAAAA,QAAK,QAAQ,QAAQ,KAAK,EAAE,OAAO;AAExD,MAAIA,UAAAA,QAAK,QAAQ,OAAO,CAAC,aAAa,KAAK,OAAO;AACjD,WAAQ,IAAI,oGAAoG;AAChH;;AAGD,MAAIC,QAAAA,QAAG,WAAW,aAAa,IAAIA,QAAAA,QAAG,SAAS,aAAa,CAAC,aAAa,EAAE;AAC3E,WAAQ,IAAI,iFAAiF;AAC7F;;EAGD,MAAM,aAAaD,UAAAA,QAAK,QAAQ,aAAa;AAC7C,MAAIC,QAAAA,QAAG,WAAW,WAAW,IAAI,CAACA,QAAAA,QAAG,SAAS,WAAW,CAAC,aAAa,EAAE;AACxE,WAAQ,IAAI,uEAAuE;AACnF;;AAGD,SAAO;;;AAIT,SAAS,6BAA6B,SAAyB;AAG9D,QAAO,mBAFMD,UAAAA,QAAK,SAAS,SAASA,UAAAA,QAAK,QAAQ,QAAQ,CAAC,CAAC,MACtC,IAAI,YACU;;AAGpC,eAAe,gBAAiC;AAC/C,QAAO,MAAM;EACZ,MAAM,UAAU,MAAM,IAAI,kBAAkB;AAE5C,MAAI,CAAC,SAAS;AACb,WAAQ,IAAI,wBAAwB;AACpC;;EAGD,MAAM,eAAeA,UAAAA,QAAK,QAAQ,QAAQ,KAAK,EAAE,QAAQ;AAEzD,MAAI,CAACC,QAAAA,QAAG,WAAW,aAAa,EAAE;AACjC,WAAQ,IAAI,4BAA4B,eAAe;AAEvD,QAAI,MADoB,IAAI,gCAAgC,EAC9C,aAAa,KAAK,IAC/B,QAAO;AAER;;AAGD,MAAIA,QAAAA,QAAG,SAAS,aAAa,CAAC,aAAa,EAAE;AAC5C,WAAQ,IAAI,2EAA2E;AACvF;;AAGD,SAAO;;;;;ACnRT,MAAM,UAAU,IAAIE,UAAAA,SAAS;AAE7B,QACE,KAAK,mBAAmB,CACxB,YAAY,gFAAgF,CAC5F,QAAQ,QAAQ;AAElB,oBAAoB,QAAQ;AAC5B,wBAAwB,QAAQ;AAEhC,QAAQ,OAAO"}
export { };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_xsd_resolver = require("./xsd-resolver-DLsEiJkG.cjs");
exports.ClassGenerator = require_xsd_resolver.ClassGenerator;
exports.XsdParser = require_xsd_resolver.XsdParser;
exports.XsdResolver = require_xsd_resolver.XsdResolver;
exports.buildDecorator = require_xsd_resolver.buildDecorator;
exports.buildFileHeader = require_xsd_resolver.buildFileHeader;
exports.buildImport = require_xsd_resolver.buildImport;
exports.buildProperty = require_xsd_resolver.buildProperty;
exports.collectImports = require_xsd_resolver.collectImports;
exports.findConfigFile = require_xsd_resolver.findConfigFile;
exports.loadConfig = require_xsd_resolver.loadConfig;
exports.mapClassDecorator = require_xsd_resolver.mapClassDecorator;
exports.mapPropertyDecorator = require_xsd_resolver.mapPropertyDecorator;
exports.toCamelCase = require_xsd_resolver.toCamelCase;
exports.toKebabCase = require_xsd_resolver.toKebabCase;
exports.toPascalCase = require_xsd_resolver.toPascalCase;
exports.validateConfig = require_xsd_resolver.validateConfig;
exports.writeGeneratedFile = require_xsd_resolver.writeGeneratedFile;
exports.writeGeneratedFiles = require_xsd_resolver.writeGeneratedFiles;
//#region src/config/config-types.d.ts
/**
* Configuration for a single XSD source to process.
*/
type EnumStyle = "union" | "enum" | "const-object";
interface XsdSource {
/** Path to the XSD file (relative to config file or absolute). */
xsdPath: string;
/**
* Output path for generated TypeScript files.
* - per-type: directory path
* - per-xsd: file path
*/
outputPath: string;
/** Output style: 'per-type' generates one file per class, 'per-xsd' puts all types in one file. */
outputStyle?: "per-type" | "per-xsd";
/** Enum generation style for this source. Overrides the global setting. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Overrides the global setting. */
useXmlRoot?: boolean;
}
/**
* Root configuration for xml-poto-codegen.
*/
interface XmlPotoCodegenConfig {
/** Array of XSD sources to process. */
sources: XsdSource[];
/** Default output style when not specified per source. Defaults to 'per-type'. */
defaultOutputStyle?: "per-type" | "per-xsd";
/** Default enum generation style. Defaults to 'union'. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Defaults to true. */
useXmlRoot?: boolean;
}
//#endregion
//#region src/config/config-loader.d.ts
declare function validateConfig(config: unknown): XmlPotoCodegenConfig;
declare function findConfigFile(cwd: string): string | undefined;
declare function loadConfig(configPath?: string): Promise<{
config: XmlPotoCodegenConfig;
configDir: string;
}>;
//#endregion
//#region src/xsd/xsd-types.d.ts
interface XsdNamespace {
uri: string;
prefix?: string;
}
interface XsdSchema {
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
attributeFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
elements: XsdElement[];
complexTypes: XsdComplexType[];
simpleTypes: XsdSimpleType[];
groups: XsdGroup[];
attributeGroups: XsdAttributeGroup[];
imports: XsdImport[];
includes: XsdInclude[];
}
interface XsdElement {
name: string;
type?: string;
ref?: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
nillable?: boolean;
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
/** Substitution group head element name */
substitutionGroup?: string;
/** Inline complexType definition */
complexType?: XsdComplexType;
/** Inline simpleType definition */
simpleType?: XsdSimpleType;
}
interface XsdComplexType {
name?: string;
mixed?: boolean;
abstract?: boolean;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
simpleContent?: XsdSimpleContent;
complexContent?: XsdComplexContent;
/** Group references within this type */
groupRefs: XsdGroupRef[];
/** Attribute group references */
attributeGroupRefs: XsdAttributeGroupRef[];
/** xs:anyAttribute */
anyAttribute?: boolean;
}
interface XsdSimpleType {
name?: string;
restriction?: XsdRestriction;
list?: XsdList;
union?: XsdUnion;
}
interface XsdRestriction {
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
}
interface XsdList {
itemType: string;
}
interface XsdUnion {
memberTypes: string[];
}
interface XsdAttribute {
name: string;
type?: string;
use?: "required" | "optional" | "prohibited";
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
ref?: string;
simpleType?: XsdSimpleType;
}
interface XsdSequence {
elements: XsdElement[];
choices: XsdChoice[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
any: XsdAny[];
}
interface XsdChoice {
elements: XsdElement[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdAll {
elements: XsdElement[];
}
interface XsdAny {
namespace?: string;
processContents?: "strict" | "lax" | "skip";
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdSimpleContent {
extension?: XsdSimpleContentExtension;
restriction?: XsdSimpleContentRestriction;
}
interface XsdSimpleContentExtension {
base: string;
attributes: XsdAttribute[];
}
interface XsdSimpleContentRestriction {
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
attributes: XsdAttribute[];
}
interface XsdComplexContent {
extension?: XsdComplexContentExtension;
restriction?: XsdComplexContentRestriction;
mixed?: boolean;
}
interface XsdComplexContentExtension {
base: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
groupRefs: XsdGroupRef[];
attributeGroupRefs: XsdAttributeGroupRef[];
}
interface XsdComplexContentRestriction {
base: string;
sequence?: XsdSequence;
attributes: XsdAttribute[];
}
interface XsdGroup {
name: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
}
interface XsdGroupRef {
ref: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdAttributeGroup {
name: string;
attributes: XsdAttribute[];
attributeGroupRefs: XsdAttributeGroupRef[];
}
interface XsdAttributeGroupRef {
ref: string;
}
interface XsdImport {
namespace?: string;
schemaLocation?: string;
}
interface XsdInclude {
schemaLocation: string;
}
//#endregion
//#region src/xsd/xsd-resolver.d.ts
interface ResolvedSchema {
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
types: ResolvedType[];
enums: ResolvedEnum[];
/** Top-level elements that reference named types (root element candidates) */
rootElements: ResolvedRootElement[];
}
interface ResolvedRootElement {
name: string;
typeName: string;
nillable?: boolean;
}
interface ResolvedType {
/** Class name (PascalCase) */
className: string;
/** Original XML element/type name */
xmlName: string;
/** Properties of this type */
properties: ResolvedProperty[];
/** Base type name if this type extends another */
baseTypeName?: string;
/** Whether this is a root element (gets @XmlRoot instead of @XmlElement) */
isRootElement: boolean;
/** mixed content model */
mixed?: boolean;
/** Namespace info */
namespace?: {
uri: string;
prefix?: string;
};
/** Whether abstract (cannot be instantiated directly) */
abstract?: boolean;
/** Has simpleContent (text value + attributes) */
hasSimpleContent?: boolean;
/** Root-level nillable flag when promoted from top-level element reference */
rootNillable?: boolean;
/** Namespace form (qualified/unqualified) */
form?: "qualified" | "unqualified";
}
type PropertyKind = "element" | "attribute" | "text" | "array" | "dynamic";
interface ResolvedProperty {
/** TypeScript property name (camelCase) */
propertyName: string;
/** Original XML name */
xmlName: string;
/** Kind of decorator to apply */
kind: PropertyKind;
/** TypeScript type string */
tsType: string;
/** Default initializer expression */
initializer: string;
/** Whether required (minOccurs > 0 or use="required") */
required?: boolean;
/** Element order in sequence */
order?: number;
/** Whether nullable (xsi:nil) */
isNullable?: boolean;
/** Form qualification */
form?: "qualified" | "unqualified";
/** Default value from XSD */
defaultValue?: string;
/** For arrays: the item element name */
arrayItemName?: string;
/** For arrays: wrapper container name */
arrayContainerName?: string;
/** For arrays: the item type class name (if complex type) */
arrayItemType?: string;
/** For elements/arrays referencing a complex type: the class name */
complexTypeName?: string;
/** Enum values restriction */
enumValues?: string[];
/** Pattern restriction */
pattern?: string;
/** Referenced enum type name */
enumTypeName?: string;
/** Namespace for this property */
namespace?: {
uri: string;
prefix?: string;
};
/** XSD dataType (e.g. 'xs:dateTime') */
dataType?: string;
/** XSD fixed value constraint */
fixedValue?: string;
/** XSD restriction facets retained for diagnostics/manual post-processing */
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
}
interface ResolvedEnum {
/** TypeScript enum name (PascalCase) */
name: string;
/** Original XSD type name */
xmlName: string;
/** Enum values */
values: string[];
/** Base restriction type */
baseType: string;
}
/**
* Resolves an XsdSchema into a set of ResolvedTypes and ResolvedEnums,
* ready for code generation.
*/
declare class XsdResolver {
private schema;
private complexTypeMap;
private simpleTypeMap;
private groupMap;
private attributeGroupMap;
private resolvedTypeMap;
/** Maps head element name → list of substitute element names */
private substitutionMap;
resolve(schema: XsdSchema): ResolvedSchema;
private addResolvedType;
private buildLookups;
private buildTypeLookups;
private buildGroupLookups;
private buildAttributeGroupLookups;
private buildSubstitutionLookups;
private resolveComplexType;
private resolveSimpleContent;
private resolveComplexContent;
private resolveSequenceProperties;
private resolveChoiceProperties;
private resolveAllProperties;
private resolveGroupRef;
private resolveElementProperty;
private resolveAttributes;
private resolveTypeReference;
private resolveSimpleTypeInline;
private resolveSimpleRootElement;
private resolveElementForm;
private resolveAttributeForm;
private resolveNamespaceForForm;
private findPrefixForUri;
private buildDefaultInitializer;
}
/** Convert to PascalCase: "my-type_name" → "MyTypeName" */
declare function toPascalCase(name: string): string;
/** Convert to camelCase: "MyTypeName" → "myTypeName" */
declare function toCamelCase(name: string): string;
//#endregion
//#region src/generator/class-generator.d.ts
interface ClassGeneratorOptions {
xsdPath: string;
enumStyle?: EnumStyle;
useXmlRoot?: boolean;
elementFormDefault?: "qualified" | "unqualified";
}
interface GeneratedFile {
/** Filename (without directory) */
fileName: string;
/** Full TypeScript source content */
content: string;
/** Exported class/enum names */
exports: string[];
}
/**
* Generates TypeScript source files from a resolved XSD schema.
*/
declare class ClassGenerator {
private readonly importPath;
private xsdPath;
private enumStyle;
private useXmlRoot;
private elementFormDefault?;
constructor(options: ClassGeneratorOptions);
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema: ResolvedSchema): GeneratedFile[];
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema: ResolvedSchema, fileName?: string): GeneratedFile[];
private generateEnumFile;
private generateClassFile;
private generateBarrelExport;
private generateSingleFile;
private generateEnumSource;
private generateEnumAsUnion;
private generateEnumAsEnum;
private generateEnumAsConstObject;
private generateClassSource;
private collectLocalImports;
private applyRootElements;
}
//#endregion
//#region src/generator/decorator-mapper.d.ts
/**
* Maps resolved XSD types and properties to xml-poto decorator strings.
*/
/** Get the class-level decorator string for a resolved type */
declare function mapClassDecorator(type: ResolvedType): string;
/** Get the property-level decorator string for a resolved property */
declare function mapPropertyDecorator(prop: ResolvedProperty): string;
/** Collect all xml-poto import names needed for a type */
declare function collectImports(type: ResolvedType): Set<string>;
//#endregion
//#region src/generator/file-writer.d.ts
/**
* Writes generated files to the output directory.
*/
declare function writeGeneratedFiles(outputDir: string, files: GeneratedFile[]): {
written: string[];
};
/**
* Writes one generated file to an explicit output file path.
*/
declare function writeGeneratedFile(outputFilePath: string, file: GeneratedFile): string;
//#endregion
//#region src/generator/ts-builder.d.ts
/** Build an import statement */
declare function buildImport(names: string[], from: string, isType?: boolean): string;
/** Build a decorator call with options object */
declare function buildDecorator(name: string, options?: Record<string, unknown>): string;
/** Build a class property declaration line */
declare function buildProperty(name: string, type: string, initializer?: string, optional?: boolean): string;
/** Build the auto-generated file header */
declare function buildFileHeader(xsdPath: string): string;
/** Convert a class name to a kebab-case filename */
declare function toKebabCase(name: string): string;
//#endregion
//#region src/xsd/xsd-parser.d.ts
/**
* Parses XSD files into a structured XsdSchema model using @cerios/xml-poto's XML parser.
*/
declare class XsdParser {
private parser;
/** Detected XSD prefix in the current schema (e.g. 'xs', 'xsd', or '') */
private xsdPrefix;
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath: string): XsdSchema;
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent: string, baseDir?: string): XsdSchema;
private resolveExternalSchemas;
private findSchemaRootKey;
private detectXsdPrefix;
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
private xsd;
private parseSchema;
private extractNamespaces;
private parseElement;
private parseComplexType;
private parseSimpleType;
private parseRestriction;
private parseAttribute;
private parseSequence;
private parseChoice;
private parseAll;
private parseAny;
private parseSimpleContent;
private parseSimpleContentExtension;
private parseSimpleContentRestriction;
private parseComplexContent;
private parseComplexContentExtension;
private parseComplexContentRestriction;
private parseGroup;
private parseGroupRefs;
private parseAttributeGroup;
private parseAttributeGroupRefs;
private parseImport;
private parseInclude;
private mergeSchema;
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
private getChild;
/**
* Get all children with a given tag name as an array.
*/
private parseChildren;
}
//#endregion
export { ClassGenerator, type EnumStyle, type GeneratedFile, type ResolvedEnum, type ResolvedProperty, type ResolvedRootElement, type ResolvedSchema, type ResolvedType, type XmlPotoCodegenConfig, type XsdAll, type XsdAny, type XsdAttribute, type XsdAttributeGroup, type XsdAttributeGroupRef, type XsdChoice, type XsdComplexContent, type XsdComplexContentExtension, type XsdComplexContentRestriction, type XsdComplexType, type XsdElement, type XsdGroup, type XsdGroupRef, type XsdImport, type XsdInclude, type XsdNamespace, XsdParser, XsdResolver, type XsdRestriction, type XsdSchema, type XsdSequence, type XsdSimpleContent, type XsdSimpleContentExtension, type XsdSimpleContentRestriction, type XsdSimpleType, type XsdSource, buildDecorator, buildFileHeader, buildImport, buildProperty, collectImports, findConfigFile, loadConfig, mapClassDecorator, mapPropertyDecorator, toCamelCase, toKebabCase, toPascalCase, validateConfig, writeGeneratedFile, writeGeneratedFiles };
//# sourceMappingURL=index.d.cts.map
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let node_fs = require("node:fs");
node_fs = __toESM(node_fs);
let node_path = require("node:path");
node_path = __toESM(node_path);
let jiti = require("jiti");
let _cerios_xml_poto = require("@cerios/xml-poto");
//#region src/config/config-loader.ts
const CONFIG_NAMES = ["xml-poto-codegen.config.ts", "xml-poto-codegen.config.json"];
function validateConfig(config) {
if (!config || typeof config !== "object") throw new Error("Config must be an object.");
const cfg = config;
if (!Array.isArray(cfg.sources) || cfg.sources.length === 0) throw new Error("Config must have a non-empty 'sources' array.");
for (let i = 0; i < cfg.sources.length; i++) validateSourceConfig(cfg.sources[i], i);
if (!isValidOutputStyle(cfg.defaultOutputStyle)) throw new Error("defaultOutputStyle must be 'per-type' or 'per-xsd'.");
if (!isValidEnumStyle(cfg.enumStyle)) throw new Error("enumStyle must be 'union', 'enum', or 'const-object'.");
if (cfg.useXmlRoot !== void 0 && typeof cfg.useXmlRoot !== "boolean") throw new Error("useXmlRoot must be a boolean.");
return config;
}
function validateSourceConfig(source, index) {
if (!source || typeof source !== "object") throw new Error(`sources[${index}] must be an object.`);
const src = source;
if (!src.xsdPath || typeof src.xsdPath !== "string") throw new Error(`sources[${index}].xsdPath must be a non-empty string.`);
if (!src.outputPath || typeof src.outputPath !== "string") throw new Error(`sources[${index}].outputPath must be a non-empty string.`);
if (!isValidOutputStyle(src.outputStyle)) throw new Error(`sources[${index}].outputStyle must be 'per-type' or 'per-xsd'.`);
if (!isValidEnumStyle(src.enumStyle)) throw new Error(`sources[${index}].enumStyle must be 'union', 'enum', or 'const-object'.`);
if (src.useXmlRoot !== void 0 && typeof src.useXmlRoot !== "boolean") throw new Error(`sources[${index}].useXmlRoot must be a boolean.`);
}
function isValidOutputStyle(value) {
return value === void 0 || value === "per-type" || value === "per-xsd";
}
function isValidEnumStyle(value) {
return value === void 0 || value === "union" || value === "enum" || value === "const-object";
}
function findConfigFile(cwd) {
for (const name of CONFIG_NAMES) {
const fullPath = node_path.default.resolve(cwd, name);
if (node_fs.default.existsSync(fullPath)) return fullPath;
}
}
async function loadConfig(configPath) {
const resolvedPath = configPath ? node_path.default.resolve(configPath) : findConfigFile(process.cwd());
if (!resolvedPath) throw new Error("No config file found. Run 'xml-poto-codegen init' to create one.");
if (!node_fs.default.existsSync(resolvedPath)) throw new Error(`Config file not found: ${resolvedPath}`);
const configDir = node_path.default.dirname(resolvedPath);
let raw;
if (resolvedPath.endsWith(".json")) {
const content = node_fs.default.readFileSync(resolvedPath, "utf-8");
raw = JSON.parse(content);
} else if (resolvedPath.endsWith(".ts")) {
const mod = await (0, jiti.createJiti)(__filename).import(resolvedPath, { default: true });
if (mod && typeof mod === "object" && "default" in mod) raw = mod.default;
else raw = mod;
} else throw new Error(`Unsupported config file format: ${resolvedPath}`);
return {
config: validateConfig(raw),
configDir
};
}
//#endregion
//#region src/generator/ts-builder.ts
/** Build an import statement */
function buildImport(names, from, isType = false) {
if (names.length === 0) return "";
const sorted = [...new Set(names)].sort();
const typePrefix = isType ? "type " : "";
if (sorted.length <= 3) return `import ${typePrefix}{ ${sorted.join(", ")} } from "${from}";`;
return `import ${typePrefix}{\n${sorted.map((n) => `\t${n},`).join("\n")}\n} from "${from}";`;
}
/** Build a decorator call with options object */
function buildDecorator(name, options) {
if (!options || Object.keys(options).length === 0) return `@${name}()`;
const entries = Object.entries(options).filter(([, v]) => v !== void 0);
if (entries.length === 0) return `@${name}()`;
const optionStr = entries.map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
if (optionStr.length < 60) return `@${name}({ ${optionStr} })`;
return `@${name}({\n${entries.map(([k, v]) => `\t\t${k}: ${formatValue(v)},`).join("\n")}\n\t})`;
}
/** Format a value for use in generated code */
function formatValue(value) {
if (typeof value === "string") return value;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (value instanceof RegExp) return value.toString();
if (Array.isArray(value)) return `[${value.map((v) => formatValue(v)).join(", ")}]`;
if (typeof value === "object" && value !== null) return `{ ${Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ")} }`;
return String(value);
}
/** Build a class property declaration line */
function buildProperty(name, type, initializer, optional = false) {
const optionalMark = optional ? "?" : "";
if (initializer === void 0) return `${name}${optionalMark}: ${type};`;
return `${name}${optionalMark}: ${type} = ${initializer};`;
}
/** Build the auto-generated file header */
function buildFileHeader(xsdPath) {
return [
"// ──────────────────────────────────────────────────",
"// AUTO-GENERATED by @cerios/xml-poto-codegen",
`// Source: ${xsdPath}`,
"// Do not edit manually.",
"// ──────────────────────────────────────────────────",
""
].join("\n");
}
/** Convert a class name to a kebab-case filename */
function toKebabCase(name) {
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
}
//#endregion
//#region src/generator/decorator-mapper.ts
/**
* Maps resolved XSD types and properties to xml-poto decorator strings.
*/
/** Get the class-level decorator string for a resolved type */
function mapClassDecorator(type) {
if (type.isRootElement) {
const opts = { name: `'${type.xmlName}'` };
if (type.namespace) opts.namespace = buildNamespaceObj(type.namespace);
if (type.rootNillable) opts.isNullable = true;
return buildDecorator("XmlRoot", opts);
}
const opts = { name: `'${type.xmlName}'` };
if (type.namespace) opts.namespace = buildNamespaceObj(type.namespace);
if (type.rootNillable) opts.isNullable = true;
if (type.form) opts.form = `'${type.form}'`;
return buildDecorator("XmlElement", opts);
}
/** Get the property-level decorator string for a resolved property */
function mapPropertyDecorator(prop) {
switch (prop.kind) {
case "element": return buildElementDecorator(prop);
case "attribute": return buildAttributeDecorator(prop);
case "text": return buildTextDecorator(prop);
case "array": return buildArrayDecorator(prop);
case "dynamic": return buildDynamicDecorator(prop);
default: return buildDecorator("XmlElement", { name: `'${prop.xmlName}'` });
}
}
/** Collect all xml-poto import names needed for a type */
function collectImports(type) {
const imports = /* @__PURE__ */ new Set();
imports.add(type.isRootElement ? "XmlRoot" : "XmlElement");
for (const prop of type.properties) switch (prop.kind) {
case "element":
imports.add("XmlElement");
break;
case "attribute":
imports.add("XmlAttribute");
break;
case "text":
imports.add("XmlText");
break;
case "array":
imports.add("XmlArray");
break;
case "dynamic":
imports.add("XmlDynamic");
imports.add("DynamicElement");
break;
}
return imports;
}
function buildElementDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.complexTypeName) opts.type = prop.complexTypeName;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlElement", opts);
}
function buildAttributeDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.enumValues && prop.enumValues.length > 0) opts.enumValues = prop.enumValues.map((v) => `'${escapeString$1(v)}'`);
if (prop.pattern) opts.pattern = `new RegExp(${JSON.stringify(prop.pattern)})`;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
return buildDecorator("XmlAttribute", opts);
}
function buildTextDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlText", opts);
}
function buildArrayDecorator(prop) {
const opts = {};
if (prop.arrayItemName) opts.itemName = `'${prop.arrayItemName}'`;
if (prop.arrayContainerName) opts.containerName = `'${prop.arrayContainerName}'`;
if (prop.arrayItemType) opts.type = prop.arrayItemType;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlArray", opts);
}
function buildDynamicDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
return buildDecorator("XmlDynamic", opts);
}
function buildNamespaceObj(ns) {
if (ns.prefix) return `{ uri: '${ns.uri}', prefix: '${ns.prefix}' }`;
return `{ uri: '${ns.uri}' }`;
}
function formatDefault(tsType, value) {
if (tsType === "number") return value;
if (tsType === "boolean") return value === "true" ? "true" : "false";
return `'${escapeString$1(value)}'`;
}
function escapeString$1(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
//#endregion
//#region src/generator/class-generator.ts
/**
* Generates TypeScript source files from a resolved XSD schema.
*/
var ClassGenerator = class {
constructor(options) {
this.importPath = "@cerios/xml-poto";
this.xsdPath = options.xsdPath;
this.enumStyle = options.enumStyle ?? "union";
this.useXmlRoot = options.useXmlRoot ?? true;
this.elementFormDefault = options.elementFormDefault;
}
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema) {
const files = [];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const enumDef of schema.enums) files.push(this.generateEnumFile(enumDef));
for (const type of resolvedTypes) files.push(this.generateClassFile(type, resolvedTypes, schema.enums));
if (files.length > 0) files.push(this.generateBarrelExport(files));
return files;
}
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema, fileName) {
const output = fileName ?? "generated";
return [this.generateSingleFile(schema, `${toKebabCase(output)}.ts`)];
}
generateEnumFile(enumDef) {
return {
fileName: `${toKebabCase(enumDef.name)}.ts`,
content: [
buildFileHeader(this.xsdPath),
this.generateEnumSource(enumDef),
""
].join("\n"),
exports: [enumDef.name]
};
}
generateClassFile(type, allTypes, allEnums) {
const fileName = `${toKebabCase(type.className)}.ts`;
const imports = collectImports(type);
const localImports = this.collectLocalImports(type, allTypes, allEnums);
const lines = [buildFileHeader(this.xsdPath), buildImport([...imports], this.importPath)];
for (const [name, file] of localImports) lines.push(buildImport([name], `./${file.replace(".ts", "")}`));
lines.push("");
lines.push(this.generateClassSource(type));
lines.push("");
return {
fileName,
content: lines.join("\n"),
exports: [type.className]
};
}
generateBarrelExport(files) {
const exports = files.filter((f) => f.fileName !== "index.ts").map((f) => {
const moduleName = f.fileName.replace(".ts", "");
return `export { ${f.exports.join(", ")} } from "./${moduleName}";`;
});
return {
fileName: "index.ts",
content: buildFileHeader(this.xsdPath) + exports.join("\n") + "\n",
exports: files.flatMap((f) => f.exports)
};
}
generateSingleFile(schema, fileName) {
const allImports = /* @__PURE__ */ new Set();
const allExports = [];
const parts = [buildFileHeader(this.xsdPath)];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const type of resolvedTypes) for (const imp of collectImports(type)) allImports.add(imp);
if (resolvedTypes.some((t) => t.properties.some((p) => p.kind === "dynamic"))) allImports.add("DynamicElement");
parts.push(buildImport([...allImports], this.importPath));
parts.push("");
for (const enumDef of schema.enums) {
parts.push(this.generateEnumSource(enumDef));
parts.push("");
allExports.push(enumDef.name);
}
for (const type of resolvedTypes) {
parts.push(this.generateClassSource(type));
parts.push("");
allExports.push(type.className);
}
return {
fileName,
content: parts.join("\n"),
exports: allExports
};
}
generateEnumSource(enumDef) {
switch (this.enumStyle) {
case "enum": return this.generateEnumAsEnum(enumDef);
case "const-object": return this.generateEnumAsConstObject(enumDef);
default: return this.generateEnumAsUnion(enumDef);
}
}
generateEnumAsUnion(enumDef) {
const values = enumDef.values.map((v) => `"${v}"`).join(" | ");
return `export type ${enumDef.name} = ${values};`;
}
generateEnumAsEnum(enumDef) {
const members = enumDef.values.map((v) => {
return `\t${toEnumKey(v)} = "${v}",`;
}).join("\n");
return `export enum ${enumDef.name} {\n${members}\n}`;
}
generateEnumAsConstObject(enumDef) {
const members = enumDef.values.map((v) => {
return `\t${toEnumKey(v)}: "${v}",`;
}).join("\n");
return `${`export const ${enumDef.name} = {\n${members}\n} as const;`}\n${`export type ${enumDef.name} = (typeof ${enumDef.name})[keyof typeof ${enumDef.name}];`}`;
}
generateClassSource(type) {
const lines = [];
lines.push(mapClassDecorator(type));
const extendsClause = type.baseTypeName ? ` extends ${type.baseTypeName}` : "";
lines.push(`export class ${type.className}${extendsClause} {`);
for (const prop of type.properties) {
const decorator = mapPropertyDecorator(prop);
const isOptional = prop.required !== true;
const initializer = isOptional ? void 0 : prop.initializer;
lines.push(`\t${decorator}`);
lines.push(`\t${buildProperty(prop.propertyName, prop.tsType, initializer, isOptional)}`);
lines.push("");
}
if (lines[lines.length - 1] === "") lines.pop();
lines.push("}");
return lines.join("\n");
}
collectLocalImports(type, allTypes, allEnums) {
const imports = /* @__PURE__ */ new Map();
const typeNames = new Set(allTypes.map((t) => t.className));
const enumNames = new Set(allEnums.map((e) => e.name));
if (type.baseTypeName && typeNames.has(type.baseTypeName)) imports.set(type.baseTypeName, `${toKebabCase(type.baseTypeName)}.ts`);
for (const prop of type.properties) {
if (prop.complexTypeName && typeNames.has(prop.complexTypeName)) imports.set(prop.complexTypeName, `${toKebabCase(prop.complexTypeName)}.ts`);
if (prop.arrayItemType && typeNames.has(prop.arrayItemType)) imports.set(prop.arrayItemType, `${toKebabCase(prop.arrayItemType)}.ts`);
if (prop.enumTypeName && enumNames.has(prop.enumTypeName)) imports.set(prop.enumTypeName, `${toKebabCase(prop.enumTypeName)}.ts`);
}
imports.delete(type.className);
return imports;
}
applyRootElements(types, rootElements) {
if (!this.useXmlRoot) return types.map((type) => type.isRootElement ? {
...type,
isRootElement: false,
form: this.elementFormDefault
} : type);
if (rootElements.length === 0) return types;
const rootMap = /* @__PURE__ */ new Map();
for (const root of rootElements) {
const entries = rootMap.get(root.typeName);
if (entries) entries.push(root);
else rootMap.set(root.typeName, [root]);
}
return types.map((type) => {
if (type.isRootElement) return type;
const roots = rootMap.get(type.className);
if (!roots || roots.length === 0) return type;
const root = roots[0];
return {
...type,
isRootElement: true,
xmlName: root.name,
rootNillable: root.nillable
};
});
}
};
/** Convert an enum value to a valid TypeScript enum key */
function toEnumKey(value) {
let key = value.replace(/[^a-zA-Z0-9_]/g, "_");
if (/^[0-9]/.test(key)) key = `_${key}`;
const hadLeadingUnderscore = key.startsWith("_");
let result = key.split("_").filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
if (hadLeadingUnderscore && !result.startsWith("_")) result = `_${result}`;
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = result.replace(/^[^A-Za-z_]+/, "");
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) result = `_${result}`;
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) result = "_Value";
}
return result;
}
//#endregion
//#region src/generator/file-writer.ts
/**
* Writes generated files to the output directory.
*/
function writeGeneratedFiles(outputDir, files) {
const written = [];
node_fs.default.mkdirSync(outputDir, { recursive: true });
for (const file of files) {
const filePath = node_path.default.join(outputDir, file.fileName);
node_fs.default.writeFileSync(filePath, file.content, "utf-8");
written.push(filePath);
}
return { written };
}
/**
* Writes one generated file to an explicit output file path.
*/
function writeGeneratedFile(outputFilePath, file) {
const parentDir = node_path.default.dirname(outputFilePath);
node_fs.default.mkdirSync(parentDir, { recursive: true });
node_fs.default.writeFileSync(outputFilePath, file.content, "utf-8");
return outputFilePath;
}
//#endregion
//#region src/xsd/xsd-parser.ts
const XSD_NS = "http://www.w3.org/2001/XMLSchema";
/**
* Parses XSD files into a structured XsdSchema model using @cerios/xml-poto's XML parser.
*/
var XsdParser = class {
constructor() {
this.parser = new _cerios_xml_poto.XmlDecoratorParser({
trimValues: false,
parseTagValue: false
});
this.xsdPrefix = "xs";
}
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath) {
const absolutePath = node_path.default.resolve(xsdPath);
const content = node_fs.default.readFileSync(absolutePath, "utf-8");
return this.parseString(content, node_path.default.dirname(absolutePath));
}
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent, baseDir) {
const normalized = xsdContent.replace(/<\?xml[^?]*\?>/i, "").replace(/<!--[\s\S]*?-->/g, "").trim();
if (!/^<(?:[a-zA-Z_][\w.-]*:)?schema[\s/>]/i.test(normalized)) throw new Error("The provided content does not appear to be a valid XSD schema. Expected a root <xs:schema>, <xsd:schema>, or <schema> element.");
const parsed = this.parser.parse(normalized);
const rootKey = this.findSchemaRootKey(parsed);
if (!rootKey) throw new Error("No XSD schema root element found. Expected <xs:schema>, <xsd:schema>, or <schema>.");
const schemaObj = parsed[rootKey];
this.detectXsdPrefix(schemaObj);
const schema = this.parseSchema(schemaObj);
if (baseDir) this.resolveExternalSchemas(schema, baseDir);
return schema;
}
resolveExternalSchemas(schema, baseDir) {
for (const inc of schema.includes) if (inc.schemaLocation) {
const incPath = node_path.default.resolve(baseDir, inc.schemaLocation);
if (node_fs.default.existsSync(incPath)) this.mergeSchema(schema, this.parseFile(incPath));
}
for (const imp of schema.imports) if (imp.schemaLocation) {
const impPath = node_path.default.resolve(baseDir, imp.schemaLocation);
if (node_fs.default.existsSync(impPath)) {
const imported = this.parseFile(impPath);
this.mergeSchema(schema, imported);
if (imp.namespace && imported.targetNamespace) {
for (const [prefix, uri] of imported.namespaces) if (uri === imported.targetNamespace && prefix !== "" && !schema.namespaces.has(prefix)) schema.namespaces.set(prefix, uri);
}
}
}
}
findSchemaRootKey(parsed) {
return Object.keys(parsed).find((k) => k === "schema" || k.endsWith(":schema") || k === "xs:schema" || k === "xsd:schema");
}
detectXsdPrefix(schemaObj) {
for (const key of Object.keys(schemaObj)) if (key.startsWith("@_xmlns:")) {
const prefix = key.substring(8);
if (schemaObj[key] === XSD_NS) {
this.xsdPrefix = prefix;
return;
}
}
if (schemaObj["@_xmlns"] === XSD_NS) {
this.xsdPrefix = "";
return;
}
this.xsdPrefix = "xs";
}
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
xsd(localName) {
return this.xsdPrefix ? `${this.xsdPrefix}:${localName}` : localName;
}
parseSchema(obj) {
return {
targetNamespace: attr(obj, "targetNamespace"),
elementFormDefault: attr(obj, "elementFormDefault"),
attributeFormDefault: attr(obj, "attributeFormDefault"),
namespaces: this.extractNamespaces(obj),
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
complexTypes: this.parseChildren(obj, this.xsd("complexType")).map((e) => this.parseComplexType(e)),
simpleTypes: this.parseChildren(obj, this.xsd("simpleType")).map((e) => this.parseSimpleType(e)),
groups: this.parseChildren(obj, this.xsd("group")).map((e) => this.parseGroup(e)),
attributeGroups: this.parseChildren(obj, this.xsd("attributeGroup")).map((e) => this.parseAttributeGroup(e)),
imports: this.parseChildren(obj, this.xsd("import")).map((e) => this.parseImport(e)),
includes: this.parseChildren(obj, this.xsd("include")).map((e) => this.parseInclude(e))
};
}
extractNamespaces(obj) {
const ns = /* @__PURE__ */ new Map();
for (const key of Object.keys(obj)) if (key === "@_xmlns") ns.set("", obj[key]);
else if (key.startsWith("@_xmlns:")) ns.set(key.substring(8), obj[key]);
return ns;
}
parseElement(obj) {
const el = {
name: attr(obj, "name") ?? "",
type: attr(obj, "type"),
ref: attr(obj, "ref"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs"),
nillable: attr(obj, "nillable") === "true" || void 0,
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
substitutionGroup: attr(obj, "substitutionGroup")
};
const ct = this.getChild(obj, this.xsd("complexType"));
if (ct) el.complexType = this.parseComplexType(ct);
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) el.simpleType = this.parseSimpleType(st);
return el;
}
parseComplexType(obj) {
const ct = {
name: attr(obj, "name"),
mixed: attr(obj, "mixed") === "true" || void 0,
abstract: attr(obj, "abstract") === "true" || void 0,
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj),
anyAttribute: this.getChild(obj, this.xsd("anyAttribute")) !== void 0 || void 0
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ct.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ct.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ct.all = this.parseAll(all);
const sc = this.getChild(obj, this.xsd("simpleContent"));
if (sc) ct.simpleContent = this.parseSimpleContent(sc);
const cc = this.getChild(obj, this.xsd("complexContent"));
if (cc) ct.complexContent = this.parseComplexContent(cc);
return ct;
}
parseSimpleType(obj) {
const st = { name: attr(obj, "name") };
const restriction = this.getChild(obj, this.xsd("restriction"));
if (restriction) st.restriction = this.parseRestriction(restriction);
const list = this.getChild(obj, this.xsd("list"));
if (list) st.list = { itemType: attr(list, "itemType") ?? "" };
const union = this.getChild(obj, this.xsd("union"));
if (union) {
const memberTypes = attr(union, "memberTypes");
st.union = { memberTypes: memberTypes ? memberTypes.split(/\s+/) : [] };
}
return st;
}
parseRestriction(obj) {
return {
base: attr(obj, "base") ?? "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => attr(e, "value") ?? ""),
pattern: attr(this.getChild(obj, this.xsd("pattern")) ?? {}, "value"),
minLength: numAttr(this.getChild(obj, this.xsd("minLength")) ?? {}, "value"),
maxLength: numAttr(this.getChild(obj, this.xsd("maxLength")) ?? {}, "value"),
minInclusive: numAttr(this.getChild(obj, this.xsd("minInclusive")) ?? {}, "value"),
maxInclusive: numAttr(this.getChild(obj, this.xsd("maxInclusive")) ?? {}, "value"),
minExclusive: numAttr(this.getChild(obj, this.xsd("minExclusive")) ?? {}, "value"),
maxExclusive: numAttr(this.getChild(obj, this.xsd("maxExclusive")) ?? {}, "value"),
totalDigits: numAttr(this.getChild(obj, this.xsd("totalDigits")) ?? {}, "value"),
fractionDigits: numAttr(this.getChild(obj, this.xsd("fractionDigits")) ?? {}, "value"),
whiteSpace: attr(this.getChild(obj, this.xsd("whiteSpace")) ?? {}, "value")
};
}
parseAttribute(obj) {
const a = {
name: attr(obj, "name") ?? "",
type: attr(obj, "type"),
use: attr(obj, "use"),
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
ref: attr(obj, "ref")
};
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) a.simpleType = this.parseSimpleType(st);
return a;
}
parseSequence(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
choices: this.parseChildren(obj, this.xsd("choice")).map((c) => this.parseChoice(c)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
any: this.parseChildren(obj, this.xsd("any")).map((a) => this.parseAny(a))
};
}
parseChoice(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
parseAll(obj) {
return { elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)) };
}
parseAny(obj) {
return {
namespace: attr(obj, "namespace"),
processContents: attr(obj, "processContents"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
parseSimpleContent(obj) {
const sc = {};
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) sc.extension = this.parseSimpleContentExtension(ext);
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) sc.restriction = this.parseSimpleContentRestriction(rest);
return sc;
}
parseSimpleContentExtension(obj) {
return {
base: attr(obj, "base") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseSimpleContentRestriction(obj) {
return {
base: attr(obj, "base") ?? "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => attr(e, "value") ?? ""),
pattern: attr(this.getChild(obj, this.xsd("pattern")) ?? {}, "value"),
minLength: numAttr(this.getChild(obj, this.xsd("minLength")) ?? {}, "value"),
maxLength: numAttr(this.getChild(obj, this.xsd("maxLength")) ?? {}, "value"),
minInclusive: numAttr(this.getChild(obj, this.xsd("minInclusive")) ?? {}, "value"),
maxInclusive: numAttr(this.getChild(obj, this.xsd("maxInclusive")) ?? {}, "value"),
minExclusive: numAttr(this.getChild(obj, this.xsd("minExclusive")) ?? {}, "value"),
maxExclusive: numAttr(this.getChild(obj, this.xsd("maxExclusive")) ?? {}, "value"),
totalDigits: numAttr(this.getChild(obj, this.xsd("totalDigits")) ?? {}, "value"),
fractionDigits: numAttr(this.getChild(obj, this.xsd("fractionDigits")) ?? {}, "value"),
whiteSpace: attr(this.getChild(obj, this.xsd("whiteSpace")) ?? {}, "value"),
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseComplexContent(obj) {
const cc = { mixed: attr(obj, "mixed") === "true" || void 0 };
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) cc.extension = this.parseComplexContentExtension(ext);
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) cc.restriction = this.parseComplexContentRestriction(rest);
return cc;
}
parseComplexContentExtension(obj) {
const ext = {
base: attr(obj, "base") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ext.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ext.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ext.all = this.parseAll(all);
return ext;
}
parseComplexContentRestriction(obj) {
const rest = {
base: attr(obj, "base") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) rest.sequence = this.parseSequence(seq);
return rest;
}
parseGroup(obj) {
const g = { name: attr(obj, "name") ?? "" };
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) g.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) g.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) g.all = this.parseAll(all);
return g;
}
parseGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("group")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({
ref: attr(g, "ref"),
minOccurs: numAttr(g, "minOccurs"),
maxOccurs: occursAttr(g, "maxOccurs")
}));
}
parseAttributeGroup(obj) {
return {
name: attr(obj, "name") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
}
parseAttributeGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("attributeGroup")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({ ref: attr(g, "ref") }));
}
parseImport(obj) {
return {
namespace: attr(obj, "namespace"),
schemaLocation: attr(obj, "schemaLocation")
};
}
parseInclude(obj) {
return { schemaLocation: attr(obj, "schemaLocation") ?? "" };
}
mergeSchema(target, source) {
target.elements.push(...source.elements);
target.complexTypes.push(...source.complexTypes);
target.simpleTypes.push(...source.simpleTypes);
target.groups.push(...source.groups);
target.attributeGroups.push(...source.attributeGroups);
}
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
getChild(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return void 0;
if (Array.isArray(child)) return child[0];
if (typeof child === "object") return child;
}
/**
* Get all children with a given tag name as an array.
*/
parseChildren(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return [];
if (Array.isArray(child)) return child.map((c) => typeof c === "object" && c !== null ? c : {});
if (typeof child === "object") return [child];
return [];
}
};
/** Get an XML attribute value from a parsed object (attributes have @_ prefix) */
function attr(obj, name) {
const val = obj[`@_${name}`];
if (val === void 0 || val === null) return void 0;
if (typeof val === "string") return val;
if (typeof val === "number" || typeof val === "boolean" || typeof val === "bigint" || typeof val === "symbol") return String(val);
}
/** Get a numeric attribute value */
function numAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
/** Parse an occurs attribute that can be "unbounded" or a number */
function occursAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
if (val === "unbounded") return "unbounded";
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
//#endregion
//#region src/xsd/xsd-resolver.ts
const XSD_TYPE_MAP = {
string: {
tsType: "string",
initializer: "''"
},
normalizedString: {
tsType: "string",
initializer: "''"
},
token: {
tsType: "string",
initializer: "''"
},
language: {
tsType: "string",
initializer: "''"
},
Name: {
tsType: "string",
initializer: "''"
},
NCName: {
tsType: "string",
initializer: "''"
},
NMTOKEN: {
tsType: "string",
initializer: "''"
},
ID: {
tsType: "string",
initializer: "''"
},
IDREF: {
tsType: "string",
initializer: "''"
},
anyURI: {
tsType: "string",
initializer: "''"
},
QName: {
tsType: "string",
initializer: "''"
},
integer: {
tsType: "number",
initializer: "0"
},
int: {
tsType: "number",
initializer: "0"
},
long: {
tsType: "number",
initializer: "0"
},
short: {
tsType: "number",
initializer: "0"
},
byte: {
tsType: "number",
initializer: "0"
},
nonNegativeInteger: {
tsType: "number",
initializer: "0"
},
nonPositiveInteger: {
tsType: "number",
initializer: "0"
},
positiveInteger: {
tsType: "number",
initializer: "0"
},
negativeInteger: {
tsType: "number",
initializer: "0"
},
unsignedInt: {
tsType: "number",
initializer: "0"
},
unsignedLong: {
tsType: "number",
initializer: "0"
},
unsignedShort: {
tsType: "number",
initializer: "0"
},
unsignedByte: {
tsType: "number",
initializer: "0"
},
decimal: {
tsType: "number",
initializer: "0"
},
float: {
tsType: "number",
initializer: "0"
},
double: {
tsType: "number",
initializer: "0"
},
boolean: {
tsType: "boolean",
initializer: "false"
},
dateTime: {
tsType: "string",
initializer: "''",
dataType: "xs:dateTime"
},
date: {
tsType: "string",
initializer: "''",
dataType: "xs:date"
},
time: {
tsType: "string",
initializer: "''",
dataType: "xs:time"
},
duration: {
tsType: "string",
initializer: "''"
},
gYear: {
tsType: "string",
initializer: "''"
},
gMonth: {
tsType: "string",
initializer: "''"
},
gDay: {
tsType: "string",
initializer: "''"
},
gYearMonth: {
tsType: "string",
initializer: "''"
},
gMonthDay: {
tsType: "string",
initializer: "''"
},
base64Binary: {
tsType: "string",
initializer: "''"
},
hexBinary: {
tsType: "string",
initializer: "''"
},
anyType: {
tsType: "unknown",
initializer: "undefined"
},
anySimpleType: {
tsType: "string",
initializer: "''"
}
};
/**
* Resolves an XsdSchema into a set of ResolvedTypes and ResolvedEnums,
* ready for code generation.
*/
var XsdResolver = class {
constructor() {
this.complexTypeMap = /* @__PURE__ */ new Map();
this.simpleTypeMap = /* @__PURE__ */ new Map();
this.groupMap = /* @__PURE__ */ new Map();
this.attributeGroupMap = /* @__PURE__ */ new Map();
this.resolvedTypeMap = /* @__PURE__ */ new Map();
this.substitutionMap = /* @__PURE__ */ new Map();
}
resolve(schema) {
this.schema = schema;
this.buildLookups();
this.resolvedTypeMap.clear();
const resolved = {
targetNamespace: schema.targetNamespace,
elementFormDefault: schema.elementFormDefault,
namespaces: schema.namespaces,
types: [],
enums: [],
rootElements: []
};
for (const st of schema.simpleTypes) if (st.name && st.restriction && st.restriction.enumerations.length > 0) resolved.enums.push({
name: toPascalCase(st.name),
xmlName: st.name,
values: st.restriction.enumerations,
baseType: stripPrefix(st.restriction.base)
});
for (const ct of schema.complexTypes) if (ct.name) this.addResolvedType(this.resolveComplexType(ct, ct.name, false));
for (const el of schema.elements) if (el.complexType) this.addResolvedType(this.resolveComplexType(el.complexType, el.name, true));
else if (el.type) {
const localType = stripPrefix(el.type);
if (this.complexTypeMap.has(localType)) resolved.rootElements.push({
name: el.name,
typeName: toPascalCase(localType),
nillable: el.nillable
});
else this.addResolvedType(this.resolveSimpleRootElement(el));
} else if (el.simpleType) this.addResolvedType(this.resolveSimpleRootElement(el));
resolved.types = [...this.resolvedTypeMap.values()];
return resolved;
}
addResolvedType(type) {
if (!this.resolvedTypeMap.has(type.className)) this.resolvedTypeMap.set(type.className, type);
}
buildLookups() {
this.complexTypeMap.clear();
this.simpleTypeMap.clear();
this.groupMap.clear();
this.attributeGroupMap.clear();
this.substitutionMap.clear();
this.buildTypeLookups();
this.buildGroupLookups();
this.buildAttributeGroupLookups();
this.buildSubstitutionLookups();
}
buildTypeLookups() {
for (const ct of this.schema.complexTypes) if (ct.name) this.complexTypeMap.set(ct.name, ct);
for (const st of this.schema.simpleTypes) if (st.name) this.simpleTypeMap.set(st.name, st);
}
buildGroupLookups() {
for (const g of this.schema.groups) if (g.name) {
const compositor = g.sequence ?? g.choice ?? g.all;
if (compositor) this.groupMap.set(g.name, compositor);
}
}
buildAttributeGroupLookups() {
const groupDefs = /* @__PURE__ */ new Map();
for (const ag of this.schema.attributeGroups) if (ag.name) groupDefs.set(ag.name, ag);
const resolving = /* @__PURE__ */ new Set();
const resolveGroup = (name) => {
const cached = this.attributeGroupMap.get(name);
if (cached) return cached;
const def = groupDefs.get(name);
if (!def) return [];
if (resolving.has(name)) return [];
resolving.add(name);
const attrs = [...def.attributes];
for (const ref of def.attributeGroupRefs) {
const resolvedAttrs = resolveGroup(stripPrefix(ref.ref));
if (resolvedAttrs.length) attrs.push(...resolvedAttrs);
}
resolving.delete(name);
this.attributeGroupMap.set(name, attrs);
return attrs;
};
for (const name of groupDefs.keys()) resolveGroup(name);
}
buildSubstitutionLookups() {
for (const el of this.schema.elements) if (el.substitutionGroup) {
const headName = stripPrefix(el.substitutionGroup);
const substitutes = this.substitutionMap.get(headName);
if (substitutes) substitutes.push(el.name);
else this.substitutionMap.set(headName, [el.name]);
}
}
resolveComplexType(ct, name, isRoot, classNameOverride) {
const resolved = {
className: classNameOverride ?? toPascalCase(name),
xmlName: name,
properties: [],
isRootElement: isRoot,
mixed: ct.mixed,
abstract: ct.abstract
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix ?? void 0
};
}
if (ct.simpleContent) {
resolved.hasSimpleContent = true;
this.resolveSimpleContent(ct.simpleContent, resolved);
return resolved;
}
if (ct.complexContent) this.resolveComplexContent(ct.complexContent, resolved);
let order = 1;
if (ct.sequence) order = this.resolveSequenceProperties(ct.sequence, resolved.properties, order);
if (ct.choice) order = this.resolveChoiceProperties(ct.choice, resolved.properties, order);
if (ct.all) this.resolveAllProperties(ct.all, resolved.properties);
for (const gRef of ct.groupRefs) order = this.resolveGroupRef(gRef, resolved.properties, order);
this.resolveAttributes(ct.attributes, resolved.properties);
for (const agRef of ct.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
if (ct.anyAttribute) resolved.properties.push({
propertyName: "anyAttributes",
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!"
});
return resolved;
}
resolveSimpleContent(sc, resolved) {
if (sc.extension) {
const baseInfo = this.resolveTypeReference(sc.extension.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.extension.attributes, resolved.properties);
} else if (sc.restriction) {
const baseInfo = this.resolveTypeReference(sc.restriction.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
enumValues: sc.restriction.enumerations.length > 0 ? sc.restriction.enumerations : void 0,
pattern: sc.restriction.pattern,
minLength: sc.restriction.minLength,
maxLength: sc.restriction.maxLength,
minInclusive: sc.restriction.minInclusive,
maxInclusive: sc.restriction.maxInclusive,
minExclusive: sc.restriction.minExclusive,
maxExclusive: sc.restriction.maxExclusive,
totalDigits: sc.restriction.totalDigits,
fractionDigits: sc.restriction.fractionDigits,
whiteSpace: sc.restriction.whiteSpace,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.restriction.attributes, resolved.properties);
}
}
resolveComplexContent(cc, resolved) {
if (cc.extension) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.extension.base));
let order = 1;
if (cc.extension.sequence) order = this.resolveSequenceProperties(cc.extension.sequence, resolved.properties, order);
if (cc.extension.choice) order = this.resolveChoiceProperties(cc.extension.choice, resolved.properties, order);
if (cc.extension.all) this.resolveAllProperties(cc.extension.all, resolved.properties);
for (const gRef of cc.extension.groupRefs) order = this.resolveGroupRef(gRef, resolved.properties, order);
this.resolveAttributes(cc.extension.attributes, resolved.properties);
for (const agRef of cc.extension.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
} else if (cc.restriction) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.restriction.base));
if (cc.restriction.sequence) this.resolveSequenceProperties(cc.restriction.sequence, resolved.properties, 1);
this.resolveAttributes(cc.restriction.attributes, resolved.properties);
}
}
resolveSequenceProperties(seq, props, startOrder) {
let order = startOrder;
for (const el of seq.elements) props.push(this.resolveElementProperty(el, order++));
for (const choice of seq.choices) order = this.resolveChoiceProperties(choice, props, order);
for (const nested of seq.sequences) order = this.resolveSequenceProperties(nested, props, order);
for (const gRef of seq.groupRefs) order = this.resolveGroupRef(gRef, props, order);
for (const any of seq.any) {
props.push({
propertyName: `dynamicContent${order}`,
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
order: order++
});
if (any.minOccurs === void 0 || any.minOccurs > 0) props[props.length - 1].required = true;
}
return order;
}
resolveChoiceProperties(choice, props, startOrder) {
let order = startOrder;
for (const el of choice.elements) {
const prop = this.resolveElementProperty(el, order++);
prop.required = false;
props.push(prop);
}
for (const seq of choice.sequences) order = this.resolveSequenceProperties(seq, props, order);
for (const gRef of choice.groupRefs) order = this.resolveGroupRef(gRef, props, order);
return order;
}
resolveAllProperties(all, props) {
for (const el of all.elements) props.push(this.resolveElementProperty(el));
}
resolveGroupRef(gRef, props, startOrder) {
const refName = stripPrefix(gRef.ref);
const compositor = this.groupMap.get(refName);
if (!compositor) return startOrder;
if ("elements" in compositor && "choices" in compositor) return this.resolveSequenceProperties(compositor, props, startOrder);
if ("elements" in compositor && !("choices" in compositor)) {
if ("sequences" in compositor) return this.resolveChoiceProperties(compositor, props, startOrder);
this.resolveAllProperties(compositor, props);
}
return startOrder;
}
resolveElementProperty(el, order) {
const isArray = el.maxOccurs === "unbounded" || typeof el.maxOccurs === "number" && el.maxOccurs > 1;
const isRequired = el.minOccurs === void 0 || el.minOccurs > 0;
const form = el.form ?? this.resolveElementForm();
const name = el.ref ? stripPrefix(el.ref) : el.name;
if (this.substitutionMap.has(name)) return {
propertyName: toCamelCase(name),
xmlName: name,
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
required: isRequired,
order
};
let typeInfo;
if (el.complexType) {
const inlineTypeName = toPascalCase(name) + "Type";
this.addResolvedType(this.resolveComplexType(el.complexType, name, false, inlineTypeName));
typeInfo = {
tsType: inlineTypeName,
initializer: `new ${inlineTypeName}()`,
complexTypeName: inlineTypeName
};
} else if (el.simpleType) typeInfo = this.resolveSimpleTypeInline(el.simpleType);
else if (el.type) typeInfo = this.resolveTypeReference(el.type);
else typeInfo = {
tsType: "string",
initializer: "''"
};
const prop = {
propertyName: toCamelCase(name),
xmlName: name,
kind: isArray ? "array" : "element",
tsType: isArray ? `${typeInfo.tsType}[]` : typeInfo.tsType,
initializer: isArray ? "[]" : typeInfo.initializer,
required: isRequired,
order,
isNullable: el.nillable,
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: el.defaultValue ?? el.fixed,
fixedValue: el.fixed,
complexTypeName: typeInfo.complexTypeName,
enumValues: typeInfo.enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
};
if (isArray) {
prop.arrayItemName = name;
prop.arrayItemType = typeInfo.complexTypeName;
}
return prop;
}
resolveAttributes(attrs, props) {
for (const a of attrs) {
if (a.ref) {
const form = a.form ?? this.resolveAttributeForm();
const defaultOrFixed = a.defaultValue ?? a.fixed;
props.push({
propertyName: toCamelCase(stripPrefix(a.ref)),
xmlName: stripPrefix(a.ref),
kind: "attribute",
tsType: "string",
initializer: defaultOrFixed ? `'${escapeString(defaultOrFixed)}'` : "''",
required: a.use === "required",
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: defaultOrFixed,
fixedValue: a.fixed
});
continue;
}
let typeInfo;
if (a.simpleType) typeInfo = this.resolveSimpleTypeInline(a.simpleType);
else if (a.type) typeInfo = this.resolveTypeReference(a.type);
else typeInfo = {
tsType: "string",
initializer: "''"
};
const defaultOrFixed = a.defaultValue ?? a.fixed;
const initializer = defaultOrFixed ? this.buildDefaultInitializer(typeInfo.tsType, defaultOrFixed) : typeInfo.initializer;
const form = a.form ?? this.resolveAttributeForm();
const enumValues = typeInfo.enumValues ? [...typeInfo.enumValues] : a.fixed ? [a.fixed] : void 0;
props.push({
propertyName: toCamelCase(a.name),
xmlName: a.name,
kind: "attribute",
tsType: typeInfo.tsType,
initializer,
required: a.use === "required",
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: defaultOrFixed,
fixedValue: a.fixed,
enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
});
}
}
resolveTypeReference(typeRef) {
const localName = stripPrefix(typeRef);
const builtin = XSD_TYPE_MAP[localName];
if (builtin) return { ...builtin };
if (this.complexTypeMap.has(localName)) {
const className = toPascalCase(localName);
return {
tsType: className,
initializer: `new ${className}()`,
complexTypeName: className
};
}
const st = this.simpleTypeMap.get(localName);
if (st) return this.resolveSimpleTypeInline(st);
return {
tsType: "string",
initializer: "''"
};
}
resolveSimpleTypeInline(st) {
if (st.restriction) {
const result = { ...this.resolveTypeReference(st.restriction.base) };
if (st.restriction.enumerations.length > 0) if (st.name) {
result.enumTypeName = toPascalCase(st.name);
result.tsType = toPascalCase(st.name);
} else result.enumValues = st.restriction.enumerations;
if (st.restriction.pattern) result.pattern = st.restriction.pattern;
result.minLength = st.restriction.minLength;
result.maxLength = st.restriction.maxLength;
result.minInclusive = st.restriction.minInclusive;
result.maxInclusive = st.restriction.maxInclusive;
result.minExclusive = st.restriction.minExclusive;
result.maxExclusive = st.restriction.maxExclusive;
result.totalDigits = st.restriction.totalDigits;
result.fractionDigits = st.restriction.fractionDigits;
result.whiteSpace = st.restriction.whiteSpace;
return result;
}
if (st.list) return {
tsType: `${this.resolveTypeReference(st.list.itemType).tsType}[]`,
initializer: "[]"
};
if (st.union) {
if (st.union.memberTypes.length > 0) {
const memberInfos = st.union.memberTypes.map((mt) => this.resolveTypeReference(mt));
return {
tsType: [...new Set(memberInfos.map((m) => m.tsType))].join(" | "),
initializer: memberInfos[0].initializer
};
}
return {
tsType: "string",
initializer: "''"
};
}
return {
tsType: "string",
initializer: "''"
};
}
resolveSimpleRootElement(el) {
const typeInfo = el.simpleType ? this.resolveSimpleTypeInline(el.simpleType) : el.type ? this.resolveTypeReference(el.type) : {
tsType: "string",
initializer: "''"
};
const resolved = {
className: toPascalCase(el.name),
xmlName: el.name,
properties: [{
propertyName: "value",
xmlName: "",
kind: "text",
tsType: typeInfo.tsType,
initializer: typeInfo.initializer,
dataType: typeInfo.dataType
}],
isRootElement: true
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix ?? void 0
};
}
return resolved;
}
resolveElementForm() {
return this.schema.elementFormDefault;
}
resolveAttributeForm() {
return this.schema.attributeFormDefault;
}
resolveNamespaceForForm(form) {
if (form !== "qualified" || !this.schema.targetNamespace) return;
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
return {
uri: this.schema.targetNamespace,
prefix: prefix ?? void 0
};
}
findPrefixForUri(uri) {
for (const [prefix, nsUri] of this.schema.namespaces) if (nsUri === uri && prefix !== "") return prefix;
}
buildDefaultInitializer(tsType, defaultValue) {
if (tsType === "number") return defaultValue;
if (tsType === "boolean") return defaultValue === "true" ? "true" : "false";
return `'${escapeString(defaultValue)}'`;
}
};
/** Strip namespace prefix from a type reference (e.g. "xs:string" → "string", "tns:Foo" → "Foo") */
function stripPrefix(name) {
const idx = name.indexOf(":");
return idx >= 0 ? name.substring(idx + 1) : name;
}
/** Convert to PascalCase: "my-type_name" → "MyTypeName" */
function toPascalCase(name) {
return sanitizeIdentifier(name.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase()).replace(/^[a-z]/, (c) => c.toUpperCase()), true);
}
/** Convert to camelCase: "MyTypeName" → "myTypeName" */
function toCamelCase(name) {
const pascal = toPascalCase(name);
return sanitizeIdentifier(pascal.charAt(0).toLowerCase() + pascal.slice(1), false);
}
function sanitizeIdentifier(value, pascal) {
const normalized = value.replace(/[^a-zA-Z0-9_$]/g, "");
const nonEmpty = normalized.length > 0 ? normalized : pascal ? "GeneratedType" : "generatedField";
const withLeading = /^[A-Za-z_$]/.test(nonEmpty) ? nonEmpty : `_${nonEmpty}`;
if (RESERVED_TS_IDENTIFIERS.has(withLeading)) return `${withLeading}_`;
return withLeading;
}
const RESERVED_TS_IDENTIFIERS = new Set([
"abstract",
"any",
"as",
"asserts",
"async",
"await",
"boolean",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"declare",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"from",
"function",
"get",
"if",
"implements",
"import",
"in",
"infer",
"instanceof",
"interface",
"is",
"keyof",
"let",
"module",
"namespace",
"never",
"new",
"null",
"number",
"object",
"package",
"private",
"protected",
"public",
"readonly",
"require",
"return",
"set",
"static",
"string",
"super",
"switch",
"symbol",
"this",
"throw",
"true",
"try",
"type",
"typeof",
"undefined",
"unique",
"unknown",
"var",
"void",
"while",
"with",
"yield"
]);
/** Escape single quotes in a string for use in generated code */
function escapeString(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
//#endregion
Object.defineProperty(exports, "ClassGenerator", {
enumerable: true,
get: function() {
return ClassGenerator;
}
});
Object.defineProperty(exports, "XsdParser", {
enumerable: true,
get: function() {
return XsdParser;
}
});
Object.defineProperty(exports, "XsdResolver", {
enumerable: true,
get: function() {
return XsdResolver;
}
});
Object.defineProperty(exports, "__toESM", {
enumerable: true,
get: function() {
return __toESM;
}
});
Object.defineProperty(exports, "buildDecorator", {
enumerable: true,
get: function() {
return buildDecorator;
}
});
Object.defineProperty(exports, "buildFileHeader", {
enumerable: true,
get: function() {
return buildFileHeader;
}
});
Object.defineProperty(exports, "buildImport", {
enumerable: true,
get: function() {
return buildImport;
}
});
Object.defineProperty(exports, "buildProperty", {
enumerable: true,
get: function() {
return buildProperty;
}
});
Object.defineProperty(exports, "collectImports", {
enumerable: true,
get: function() {
return collectImports;
}
});
Object.defineProperty(exports, "findConfigFile", {
enumerable: true,
get: function() {
return findConfigFile;
}
});
Object.defineProperty(exports, "loadConfig", {
enumerable: true,
get: function() {
return loadConfig;
}
});
Object.defineProperty(exports, "mapClassDecorator", {
enumerable: true,
get: function() {
return mapClassDecorator;
}
});
Object.defineProperty(exports, "mapPropertyDecorator", {
enumerable: true,
get: function() {
return mapPropertyDecorator;
}
});
Object.defineProperty(exports, "toCamelCase", {
enumerable: true,
get: function() {
return toCamelCase;
}
});
Object.defineProperty(exports, "toKebabCase", {
enumerable: true,
get: function() {
return toKebabCase;
}
});
Object.defineProperty(exports, "toPascalCase", {
enumerable: true,
get: function() {
return toPascalCase;
}
});
Object.defineProperty(exports, "validateConfig", {
enumerable: true,
get: function() {
return validateConfig;
}
});
Object.defineProperty(exports, "writeGeneratedFile", {
enumerable: true,
get: function() {
return writeGeneratedFile;
}
});
Object.defineProperty(exports, "writeGeneratedFiles", {
enumerable: true,
get: function() {
return writeGeneratedFiles;
}
});
//# sourceMappingURL=xsd-resolver-DLsEiJkG.cjs.map

Sorry, the diff of this file is too big to display

import fs from "node:fs";
import path from "node:path";
import { createJiti } from "jiti";
import { XmlDecoratorParser } from "@cerios/xml-poto";
//#region \0rolldown/runtime.js
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
//#endregion
//#region src/config/config-loader.ts
function validateConfig(config) {
if (!config || typeof config !== "object") throw new Error("Config must be an object.");
const cfg = config;
if (!Array.isArray(cfg.sources) || cfg.sources.length === 0) throw new Error("Config must have a non-empty 'sources' array.");
for (let i = 0; i < cfg.sources.length; i++) validateSourceConfig(cfg.sources[i], i);
if (!isValidOutputStyle(cfg.defaultOutputStyle)) throw new Error("defaultOutputStyle must be 'per-type' or 'per-xsd'.");
if (!isValidEnumStyle(cfg.enumStyle)) throw new Error("enumStyle must be 'union', 'enum', or 'const-object'.");
if (cfg.useXmlRoot !== void 0 && typeof cfg.useXmlRoot !== "boolean") throw new Error("useXmlRoot must be a boolean.");
return config;
}
function validateSourceConfig(source, index) {
if (!source || typeof source !== "object") throw new Error(`sources[${index}] must be an object.`);
const src = source;
if (!src.xsdPath || typeof src.xsdPath !== "string") throw new Error(`sources[${index}].xsdPath must be a non-empty string.`);
if (!src.outputPath || typeof src.outputPath !== "string") throw new Error(`sources[${index}].outputPath must be a non-empty string.`);
if (!isValidOutputStyle(src.outputStyle)) throw new Error(`sources[${index}].outputStyle must be 'per-type' or 'per-xsd'.`);
if (!isValidEnumStyle(src.enumStyle)) throw new Error(`sources[${index}].enumStyle must be 'union', 'enum', or 'const-object'.`);
if (src.useXmlRoot !== void 0 && typeof src.useXmlRoot !== "boolean") throw new Error(`sources[${index}].useXmlRoot must be a boolean.`);
}
function isValidOutputStyle(value) {
return value === void 0 || value === "per-type" || value === "per-xsd";
}
function isValidEnumStyle(value) {
return value === void 0 || value === "union" || value === "enum" || value === "const-object";
}
function findConfigFile(cwd) {
for (const name of CONFIG_NAMES) {
const fullPath = path.resolve(cwd, name);
if (fs.existsSync(fullPath)) return fullPath;
}
}
async function loadConfig(configPath) {
const resolvedPath = configPath ? path.resolve(configPath) : findConfigFile(process.cwd());
if (!resolvedPath) throw new Error("No config file found. Run 'xml-poto-codegen init' to create one.");
if (!fs.existsSync(resolvedPath)) throw new Error(`Config file not found: ${resolvedPath}`);
const configDir = path.dirname(resolvedPath);
let raw;
if (resolvedPath.endsWith(".json")) {
const content = fs.readFileSync(resolvedPath, "utf-8");
raw = JSON.parse(content);
} else if (resolvedPath.endsWith(".ts")) {
const mod = await createJiti(__filename).import(resolvedPath, { default: true });
if (mod && typeof mod === "object" && "default" in mod) raw = mod.default;
else raw = mod;
} else throw new Error(`Unsupported config file format: ${resolvedPath}`);
return {
config: validateConfig(raw),
configDir
};
}
var CONFIG_NAMES;
var init_config_loader = __esmMin((() => {
CONFIG_NAMES = ["xml-poto-codegen.config.ts", "xml-poto-codegen.config.json"];
}));
//#endregion
//#region src/generator/ts-builder.ts
/** Build an import statement */
function buildImport(names, from, isType = false) {
if (names.length === 0) return "";
const sorted = [...new Set(names)].sort();
const typePrefix = isType ? "type " : "";
if (sorted.length <= 3) return `import ${typePrefix}{ ${sorted.join(", ")} } from "${from}";`;
return `import ${typePrefix}{\n${sorted.map((n) => `\t${n},`).join("\n")}\n} from "${from}";`;
}
/** Build a decorator call with options object */
function buildDecorator(name, options) {
if (!options || Object.keys(options).length === 0) return `@${name}()`;
const entries = Object.entries(options).filter(([, v]) => v !== void 0);
if (entries.length === 0) return `@${name}()`;
const optionStr = entries.map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
if (optionStr.length < 60) return `@${name}({ ${optionStr} })`;
return `@${name}({\n${entries.map(([k, v]) => `\t\t${k}: ${formatValue(v)},`).join("\n")}\n\t})`;
}
/** Format a value for use in generated code */
function formatValue(value) {
if (typeof value === "string") return value;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (value instanceof RegExp) return value.toString();
if (Array.isArray(value)) return `[${value.map((v) => formatValue(v)).join(", ")}]`;
if (typeof value === "object" && value !== null) return `{ ${Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ")} }`;
return String(value);
}
/** Build a class property declaration line */
function buildProperty(name, type, initializer, optional = false) {
const optionalMark = optional ? "?" : "";
if (initializer === void 0) return `${name}${optionalMark}: ${type};`;
return `${name}${optionalMark}: ${type} = ${initializer};`;
}
/** Build the auto-generated file header */
function buildFileHeader(xsdPath) {
return [
"// ──────────────────────────────────────────────────",
"// AUTO-GENERATED by @cerios/xml-poto-codegen",
`// Source: ${xsdPath}`,
"// Do not edit manually.",
"// ──────────────────────────────────────────────────",
""
].join("\n");
}
/** Convert a class name to a kebab-case filename */
function toKebabCase(name) {
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
}
var init_ts_builder = __esmMin((() => {}));
//#endregion
//#region src/generator/decorator-mapper.ts
/**
* Maps resolved XSD types and properties to xml-poto decorator strings.
*/
/** Get the class-level decorator string for a resolved type */
function mapClassDecorator(type) {
if (type.isRootElement) {
const opts = { name: `'${type.xmlName}'` };
if (type.namespace) opts.namespace = buildNamespaceObj(type.namespace);
if (type.rootNillable) opts.isNullable = true;
return buildDecorator("XmlRoot", opts);
}
const opts = { name: `'${type.xmlName}'` };
if (type.namespace) opts.namespace = buildNamespaceObj(type.namespace);
if (type.rootNillable) opts.isNullable = true;
if (type.form) opts.form = `'${type.form}'`;
return buildDecorator("XmlElement", opts);
}
/** Get the property-level decorator string for a resolved property */
function mapPropertyDecorator(prop) {
switch (prop.kind) {
case "element": return buildElementDecorator(prop);
case "attribute": return buildAttributeDecorator(prop);
case "text": return buildTextDecorator(prop);
case "array": return buildArrayDecorator(prop);
case "dynamic": return buildDynamicDecorator(prop);
default: return buildDecorator("XmlElement", { name: `'${prop.xmlName}'` });
}
}
/** Collect all xml-poto import names needed for a type */
function collectImports(type) {
const imports = /* @__PURE__ */ new Set();
imports.add(type.isRootElement ? "XmlRoot" : "XmlElement");
for (const prop of type.properties) switch (prop.kind) {
case "element":
imports.add("XmlElement");
break;
case "attribute":
imports.add("XmlAttribute");
break;
case "text":
imports.add("XmlText");
break;
case "array":
imports.add("XmlArray");
break;
case "dynamic":
imports.add("XmlDynamic");
imports.add("DynamicElement");
break;
}
return imports;
}
function buildElementDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.complexTypeName) opts.type = prop.complexTypeName;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlElement", opts);
}
function buildAttributeDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.enumValues && prop.enumValues.length > 0) opts.enumValues = prop.enumValues.map((v) => `'${escapeString$1(v)}'`);
if (prop.pattern) opts.pattern = `new RegExp(${JSON.stringify(prop.pattern)})`;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
return buildDecorator("XmlAttribute", opts);
}
function buildTextDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlText", opts);
}
function buildArrayDecorator(prop) {
const opts = {};
if (prop.arrayItemName) opts.itemName = `'${prop.arrayItemName}'`;
if (prop.arrayContainerName) opts.containerName = `'${prop.arrayContainerName}'`;
if (prop.arrayItemType) opts.type = prop.arrayItemType;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlArray", opts);
}
function buildDynamicDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
return buildDecorator("XmlDynamic", opts);
}
function buildNamespaceObj(ns) {
if (ns.prefix) return `{ uri: '${ns.uri}', prefix: '${ns.prefix}' }`;
return `{ uri: '${ns.uri}' }`;
}
function formatDefault(tsType, value) {
if (tsType === "number") return value;
if (tsType === "boolean") return value === "true" ? "true" : "false";
return `'${escapeString$1(value)}'`;
}
function escapeString$1(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
var init_decorator_mapper = __esmMin((() => {
init_ts_builder();
}));
//#endregion
//#region src/generator/class-generator.ts
/** Convert an enum value to a valid TypeScript enum key */
function toEnumKey(value) {
let key = value.replace(/[^a-zA-Z0-9_]/g, "_");
if (/^[0-9]/.test(key)) key = `_${key}`;
const hadLeadingUnderscore = key.startsWith("_");
let result = key.split("_").filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
if (hadLeadingUnderscore && !result.startsWith("_")) result = `_${result}`;
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = result.replace(/^[^A-Za-z_]+/, "");
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) result = `_${result}`;
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) result = "_Value";
}
return result;
}
var ClassGenerator;
var init_class_generator = __esmMin((() => {
init_decorator_mapper();
init_ts_builder();
ClassGenerator = class {
constructor(options) {
this.importPath = "@cerios/xml-poto";
this.xsdPath = options.xsdPath;
this.enumStyle = options.enumStyle ?? "union";
this.useXmlRoot = options.useXmlRoot ?? true;
this.elementFormDefault = options.elementFormDefault;
}
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema) {
const files = [];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const enumDef of schema.enums) files.push(this.generateEnumFile(enumDef));
for (const type of resolvedTypes) files.push(this.generateClassFile(type, resolvedTypes, schema.enums));
if (files.length > 0) files.push(this.generateBarrelExport(files));
return files;
}
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema, fileName) {
const output = fileName ?? "generated";
return [this.generateSingleFile(schema, `${toKebabCase(output)}.ts`)];
}
generateEnumFile(enumDef) {
return {
fileName: `${toKebabCase(enumDef.name)}.ts`,
content: [
buildFileHeader(this.xsdPath),
this.generateEnumSource(enumDef),
""
].join("\n"),
exports: [enumDef.name]
};
}
generateClassFile(type, allTypes, allEnums) {
const fileName = `${toKebabCase(type.className)}.ts`;
const imports = collectImports(type);
const localImports = this.collectLocalImports(type, allTypes, allEnums);
const lines = [buildFileHeader(this.xsdPath), buildImport([...imports], this.importPath)];
for (const [name, file] of localImports) lines.push(buildImport([name], `./${file.replace(".ts", "")}`));
lines.push("");
lines.push(this.generateClassSource(type));
lines.push("");
return {
fileName,
content: lines.join("\n"),
exports: [type.className]
};
}
generateBarrelExport(files) {
const exports = files.filter((f) => f.fileName !== "index.ts").map((f) => {
const moduleName = f.fileName.replace(".ts", "");
return `export { ${f.exports.join(", ")} } from "./${moduleName}";`;
});
return {
fileName: "index.ts",
content: buildFileHeader(this.xsdPath) + exports.join("\n") + "\n",
exports: files.flatMap((f) => f.exports)
};
}
generateSingleFile(schema, fileName) {
const allImports = /* @__PURE__ */ new Set();
const allExports = [];
const parts = [buildFileHeader(this.xsdPath)];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const type of resolvedTypes) for (const imp of collectImports(type)) allImports.add(imp);
if (resolvedTypes.some((t) => t.properties.some((p) => p.kind === "dynamic"))) allImports.add("DynamicElement");
parts.push(buildImport([...allImports], this.importPath));
parts.push("");
for (const enumDef of schema.enums) {
parts.push(this.generateEnumSource(enumDef));
parts.push("");
allExports.push(enumDef.name);
}
for (const type of resolvedTypes) {
parts.push(this.generateClassSource(type));
parts.push("");
allExports.push(type.className);
}
return {
fileName,
content: parts.join("\n"),
exports: allExports
};
}
generateEnumSource(enumDef) {
switch (this.enumStyle) {
case "enum": return this.generateEnumAsEnum(enumDef);
case "const-object": return this.generateEnumAsConstObject(enumDef);
default: return this.generateEnumAsUnion(enumDef);
}
}
generateEnumAsUnion(enumDef) {
const values = enumDef.values.map((v) => `"${v}"`).join(" | ");
return `export type ${enumDef.name} = ${values};`;
}
generateEnumAsEnum(enumDef) {
const members = enumDef.values.map((v) => {
return `\t${toEnumKey(v)} = "${v}",`;
}).join("\n");
return `export enum ${enumDef.name} {\n${members}\n}`;
}
generateEnumAsConstObject(enumDef) {
const members = enumDef.values.map((v) => {
return `\t${toEnumKey(v)}: "${v}",`;
}).join("\n");
return `${`export const ${enumDef.name} = {\n${members}\n} as const;`}\n${`export type ${enumDef.name} = (typeof ${enumDef.name})[keyof typeof ${enumDef.name}];`}`;
}
generateClassSource(type) {
const lines = [];
lines.push(mapClassDecorator(type));
const extendsClause = type.baseTypeName ? ` extends ${type.baseTypeName}` : "";
lines.push(`export class ${type.className}${extendsClause} {`);
for (const prop of type.properties) {
const decorator = mapPropertyDecorator(prop);
const isOptional = prop.required !== true;
const initializer = isOptional ? void 0 : prop.initializer;
lines.push(`\t${decorator}`);
lines.push(`\t${buildProperty(prop.propertyName, prop.tsType, initializer, isOptional)}`);
lines.push("");
}
if (lines[lines.length - 1] === "") lines.pop();
lines.push("}");
return lines.join("\n");
}
collectLocalImports(type, allTypes, allEnums) {
const imports = /* @__PURE__ */ new Map();
const typeNames = new Set(allTypes.map((t) => t.className));
const enumNames = new Set(allEnums.map((e) => e.name));
if (type.baseTypeName && typeNames.has(type.baseTypeName)) imports.set(type.baseTypeName, `${toKebabCase(type.baseTypeName)}.ts`);
for (const prop of type.properties) {
if (prop.complexTypeName && typeNames.has(prop.complexTypeName)) imports.set(prop.complexTypeName, `${toKebabCase(prop.complexTypeName)}.ts`);
if (prop.arrayItemType && typeNames.has(prop.arrayItemType)) imports.set(prop.arrayItemType, `${toKebabCase(prop.arrayItemType)}.ts`);
if (prop.enumTypeName && enumNames.has(prop.enumTypeName)) imports.set(prop.enumTypeName, `${toKebabCase(prop.enumTypeName)}.ts`);
}
imports.delete(type.className);
return imports;
}
applyRootElements(types, rootElements) {
if (!this.useXmlRoot) return types.map((type) => type.isRootElement ? {
...type,
isRootElement: false,
form: this.elementFormDefault
} : type);
if (rootElements.length === 0) return types;
const rootMap = /* @__PURE__ */ new Map();
for (const root of rootElements) {
const entries = rootMap.get(root.typeName);
if (entries) entries.push(root);
else rootMap.set(root.typeName, [root]);
}
return types.map((type) => {
if (type.isRootElement) return type;
const roots = rootMap.get(type.className);
if (!roots || roots.length === 0) return type;
const root = roots[0];
return {
...type,
isRootElement: true,
xmlName: root.name,
rootNillable: root.nillable
};
});
}
};
}));
//#endregion
//#region src/generator/file-writer.ts
/**
* Writes generated files to the output directory.
*/
function writeGeneratedFiles(outputDir, files) {
const written = [];
fs.mkdirSync(outputDir, { recursive: true });
for (const file of files) {
const filePath = path.join(outputDir, file.fileName);
fs.writeFileSync(filePath, file.content, "utf-8");
written.push(filePath);
}
return { written };
}
/**
* Writes one generated file to an explicit output file path.
*/
function writeGeneratedFile(outputFilePath, file) {
const parentDir = path.dirname(outputFilePath);
fs.mkdirSync(parentDir, { recursive: true });
fs.writeFileSync(outputFilePath, file.content, "utf-8");
return outputFilePath;
}
var init_file_writer = __esmMin((() => {}));
//#endregion
//#region src/xsd/xsd-parser.ts
/** Get an XML attribute value from a parsed object (attributes have @_ prefix) */
function attr(obj, name) {
const val = obj[`@_${name}`];
if (val === void 0 || val === null) return void 0;
if (typeof val === "string") return val;
if (typeof val === "number" || typeof val === "boolean" || typeof val === "bigint" || typeof val === "symbol") return String(val);
}
/** Get a numeric attribute value */
function numAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
/** Parse an occurs attribute that can be "unbounded" or a number */
function occursAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
if (val === "unbounded") return "unbounded";
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
var XSD_NS, XsdParser;
var init_xsd_parser = __esmMin((() => {
XSD_NS = "http://www.w3.org/2001/XMLSchema";
XsdParser = class {
constructor() {
this.parser = new XmlDecoratorParser({
trimValues: false,
parseTagValue: false
});
this.xsdPrefix = "xs";
}
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath) {
const absolutePath = path.resolve(xsdPath);
const content = fs.readFileSync(absolutePath, "utf-8");
return this.parseString(content, path.dirname(absolutePath));
}
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent, baseDir) {
const normalized = xsdContent.replace(/<\?xml[^?]*\?>/i, "").replace(/<!--[\s\S]*?-->/g, "").trim();
if (!/^<(?:[a-zA-Z_][\w.-]*:)?schema[\s/>]/i.test(normalized)) throw new Error("The provided content does not appear to be a valid XSD schema. Expected a root <xs:schema>, <xsd:schema>, or <schema> element.");
const parsed = this.parser.parse(normalized);
const rootKey = this.findSchemaRootKey(parsed);
if (!rootKey) throw new Error("No XSD schema root element found. Expected <xs:schema>, <xsd:schema>, or <schema>.");
const schemaObj = parsed[rootKey];
this.detectXsdPrefix(schemaObj);
const schema = this.parseSchema(schemaObj);
if (baseDir) this.resolveExternalSchemas(schema, baseDir);
return schema;
}
resolveExternalSchemas(schema, baseDir) {
for (const inc of schema.includes) if (inc.schemaLocation) {
const incPath = path.resolve(baseDir, inc.schemaLocation);
if (fs.existsSync(incPath)) this.mergeSchema(schema, this.parseFile(incPath));
}
for (const imp of schema.imports) if (imp.schemaLocation) {
const impPath = path.resolve(baseDir, imp.schemaLocation);
if (fs.existsSync(impPath)) {
const imported = this.parseFile(impPath);
this.mergeSchema(schema, imported);
if (imp.namespace && imported.targetNamespace) {
for (const [prefix, uri] of imported.namespaces) if (uri === imported.targetNamespace && prefix !== "" && !schema.namespaces.has(prefix)) schema.namespaces.set(prefix, uri);
}
}
}
}
findSchemaRootKey(parsed) {
return Object.keys(parsed).find((k) => k === "schema" || k.endsWith(":schema") || k === "xs:schema" || k === "xsd:schema");
}
detectXsdPrefix(schemaObj) {
for (const key of Object.keys(schemaObj)) if (key.startsWith("@_xmlns:")) {
const prefix = key.substring(8);
if (schemaObj[key] === XSD_NS) {
this.xsdPrefix = prefix;
return;
}
}
if (schemaObj["@_xmlns"] === XSD_NS) {
this.xsdPrefix = "";
return;
}
this.xsdPrefix = "xs";
}
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
xsd(localName) {
return this.xsdPrefix ? `${this.xsdPrefix}:${localName}` : localName;
}
parseSchema(obj) {
return {
targetNamespace: attr(obj, "targetNamespace"),
elementFormDefault: attr(obj, "elementFormDefault"),
attributeFormDefault: attr(obj, "attributeFormDefault"),
namespaces: this.extractNamespaces(obj),
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
complexTypes: this.parseChildren(obj, this.xsd("complexType")).map((e) => this.parseComplexType(e)),
simpleTypes: this.parseChildren(obj, this.xsd("simpleType")).map((e) => this.parseSimpleType(e)),
groups: this.parseChildren(obj, this.xsd("group")).map((e) => this.parseGroup(e)),
attributeGroups: this.parseChildren(obj, this.xsd("attributeGroup")).map((e) => this.parseAttributeGroup(e)),
imports: this.parseChildren(obj, this.xsd("import")).map((e) => this.parseImport(e)),
includes: this.parseChildren(obj, this.xsd("include")).map((e) => this.parseInclude(e))
};
}
extractNamespaces(obj) {
const ns = /* @__PURE__ */ new Map();
for (const key of Object.keys(obj)) if (key === "@_xmlns") ns.set("", obj[key]);
else if (key.startsWith("@_xmlns:")) ns.set(key.substring(8), obj[key]);
return ns;
}
parseElement(obj) {
const el = {
name: attr(obj, "name") ?? "",
type: attr(obj, "type"),
ref: attr(obj, "ref"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs"),
nillable: attr(obj, "nillable") === "true" || void 0,
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
substitutionGroup: attr(obj, "substitutionGroup")
};
const ct = this.getChild(obj, this.xsd("complexType"));
if (ct) el.complexType = this.parseComplexType(ct);
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) el.simpleType = this.parseSimpleType(st);
return el;
}
parseComplexType(obj) {
const ct = {
name: attr(obj, "name"),
mixed: attr(obj, "mixed") === "true" || void 0,
abstract: attr(obj, "abstract") === "true" || void 0,
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj),
anyAttribute: this.getChild(obj, this.xsd("anyAttribute")) !== void 0 || void 0
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ct.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ct.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ct.all = this.parseAll(all);
const sc = this.getChild(obj, this.xsd("simpleContent"));
if (sc) ct.simpleContent = this.parseSimpleContent(sc);
const cc = this.getChild(obj, this.xsd("complexContent"));
if (cc) ct.complexContent = this.parseComplexContent(cc);
return ct;
}
parseSimpleType(obj) {
const st = { name: attr(obj, "name") };
const restriction = this.getChild(obj, this.xsd("restriction"));
if (restriction) st.restriction = this.parseRestriction(restriction);
const list = this.getChild(obj, this.xsd("list"));
if (list) st.list = { itemType: attr(list, "itemType") ?? "" };
const union = this.getChild(obj, this.xsd("union"));
if (union) {
const memberTypes = attr(union, "memberTypes");
st.union = { memberTypes: memberTypes ? memberTypes.split(/\s+/) : [] };
}
return st;
}
parseRestriction(obj) {
return {
base: attr(obj, "base") ?? "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => attr(e, "value") ?? ""),
pattern: attr(this.getChild(obj, this.xsd("pattern")) ?? {}, "value"),
minLength: numAttr(this.getChild(obj, this.xsd("minLength")) ?? {}, "value"),
maxLength: numAttr(this.getChild(obj, this.xsd("maxLength")) ?? {}, "value"),
minInclusive: numAttr(this.getChild(obj, this.xsd("minInclusive")) ?? {}, "value"),
maxInclusive: numAttr(this.getChild(obj, this.xsd("maxInclusive")) ?? {}, "value"),
minExclusive: numAttr(this.getChild(obj, this.xsd("minExclusive")) ?? {}, "value"),
maxExclusive: numAttr(this.getChild(obj, this.xsd("maxExclusive")) ?? {}, "value"),
totalDigits: numAttr(this.getChild(obj, this.xsd("totalDigits")) ?? {}, "value"),
fractionDigits: numAttr(this.getChild(obj, this.xsd("fractionDigits")) ?? {}, "value"),
whiteSpace: attr(this.getChild(obj, this.xsd("whiteSpace")) ?? {}, "value")
};
}
parseAttribute(obj) {
const a = {
name: attr(obj, "name") ?? "",
type: attr(obj, "type"),
use: attr(obj, "use"),
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
ref: attr(obj, "ref")
};
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) a.simpleType = this.parseSimpleType(st);
return a;
}
parseSequence(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
choices: this.parseChildren(obj, this.xsd("choice")).map((c) => this.parseChoice(c)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
any: this.parseChildren(obj, this.xsd("any")).map((a) => this.parseAny(a))
};
}
parseChoice(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
parseAll(obj) {
return { elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)) };
}
parseAny(obj) {
return {
namespace: attr(obj, "namespace"),
processContents: attr(obj, "processContents"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
parseSimpleContent(obj) {
const sc = {};
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) sc.extension = this.parseSimpleContentExtension(ext);
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) sc.restriction = this.parseSimpleContentRestriction(rest);
return sc;
}
parseSimpleContentExtension(obj) {
return {
base: attr(obj, "base") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseSimpleContentRestriction(obj) {
return {
base: attr(obj, "base") ?? "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => attr(e, "value") ?? ""),
pattern: attr(this.getChild(obj, this.xsd("pattern")) ?? {}, "value"),
minLength: numAttr(this.getChild(obj, this.xsd("minLength")) ?? {}, "value"),
maxLength: numAttr(this.getChild(obj, this.xsd("maxLength")) ?? {}, "value"),
minInclusive: numAttr(this.getChild(obj, this.xsd("minInclusive")) ?? {}, "value"),
maxInclusive: numAttr(this.getChild(obj, this.xsd("maxInclusive")) ?? {}, "value"),
minExclusive: numAttr(this.getChild(obj, this.xsd("minExclusive")) ?? {}, "value"),
maxExclusive: numAttr(this.getChild(obj, this.xsd("maxExclusive")) ?? {}, "value"),
totalDigits: numAttr(this.getChild(obj, this.xsd("totalDigits")) ?? {}, "value"),
fractionDigits: numAttr(this.getChild(obj, this.xsd("fractionDigits")) ?? {}, "value"),
whiteSpace: attr(this.getChild(obj, this.xsd("whiteSpace")) ?? {}, "value"),
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseComplexContent(obj) {
const cc = { mixed: attr(obj, "mixed") === "true" || void 0 };
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) cc.extension = this.parseComplexContentExtension(ext);
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) cc.restriction = this.parseComplexContentRestriction(rest);
return cc;
}
parseComplexContentExtension(obj) {
const ext = {
base: attr(obj, "base") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ext.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ext.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ext.all = this.parseAll(all);
return ext;
}
parseComplexContentRestriction(obj) {
const rest = {
base: attr(obj, "base") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) rest.sequence = this.parseSequence(seq);
return rest;
}
parseGroup(obj) {
const g = { name: attr(obj, "name") ?? "" };
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) g.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) g.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) g.all = this.parseAll(all);
return g;
}
parseGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("group")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({
ref: attr(g, "ref"),
minOccurs: numAttr(g, "minOccurs"),
maxOccurs: occursAttr(g, "maxOccurs")
}));
}
parseAttributeGroup(obj) {
return {
name: attr(obj, "name") ?? "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
}
parseAttributeGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("attributeGroup")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({ ref: attr(g, "ref") }));
}
parseImport(obj) {
return {
namespace: attr(obj, "namespace"),
schemaLocation: attr(obj, "schemaLocation")
};
}
parseInclude(obj) {
return { schemaLocation: attr(obj, "schemaLocation") ?? "" };
}
mergeSchema(target, source) {
target.elements.push(...source.elements);
target.complexTypes.push(...source.complexTypes);
target.simpleTypes.push(...source.simpleTypes);
target.groups.push(...source.groups);
target.attributeGroups.push(...source.attributeGroups);
}
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
getChild(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return void 0;
if (Array.isArray(child)) return child[0];
if (typeof child === "object") return child;
}
/**
* Get all children with a given tag name as an array.
*/
parseChildren(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return [];
if (Array.isArray(child)) return child.map((c) => typeof c === "object" && c !== null ? c : {});
if (typeof child === "object") return [child];
return [];
}
};
}));
//#endregion
//#region src/xsd/xsd-resolver.ts
/** Strip namespace prefix from a type reference (e.g. "xs:string" → "string", "tns:Foo" → "Foo") */
function stripPrefix(name) {
const idx = name.indexOf(":");
return idx >= 0 ? name.substring(idx + 1) : name;
}
/** Convert to PascalCase: "my-type_name" → "MyTypeName" */
function toPascalCase(name) {
return sanitizeIdentifier(name.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase()).replace(/^[a-z]/, (c) => c.toUpperCase()), true);
}
/** Convert to camelCase: "MyTypeName" → "myTypeName" */
function toCamelCase(name) {
const pascal = toPascalCase(name);
return sanitizeIdentifier(pascal.charAt(0).toLowerCase() + pascal.slice(1), false);
}
function sanitizeIdentifier(value, pascal) {
const normalized = value.replace(/[^a-zA-Z0-9_$]/g, "");
const nonEmpty = normalized.length > 0 ? normalized : pascal ? "GeneratedType" : "generatedField";
const withLeading = /^[A-Za-z_$]/.test(nonEmpty) ? nonEmpty : `_${nonEmpty}`;
if (RESERVED_TS_IDENTIFIERS.has(withLeading)) return `${withLeading}_`;
return withLeading;
}
/** Escape single quotes in a string for use in generated code */
function escapeString(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
var XSD_TYPE_MAP, XsdResolver, RESERVED_TS_IDENTIFIERS;
var init_xsd_resolver = __esmMin((() => {
XSD_TYPE_MAP = {
string: {
tsType: "string",
initializer: "''"
},
normalizedString: {
tsType: "string",
initializer: "''"
},
token: {
tsType: "string",
initializer: "''"
},
language: {
tsType: "string",
initializer: "''"
},
Name: {
tsType: "string",
initializer: "''"
},
NCName: {
tsType: "string",
initializer: "''"
},
NMTOKEN: {
tsType: "string",
initializer: "''"
},
ID: {
tsType: "string",
initializer: "''"
},
IDREF: {
tsType: "string",
initializer: "''"
},
anyURI: {
tsType: "string",
initializer: "''"
},
QName: {
tsType: "string",
initializer: "''"
},
integer: {
tsType: "number",
initializer: "0"
},
int: {
tsType: "number",
initializer: "0"
},
long: {
tsType: "number",
initializer: "0"
},
short: {
tsType: "number",
initializer: "0"
},
byte: {
tsType: "number",
initializer: "0"
},
nonNegativeInteger: {
tsType: "number",
initializer: "0"
},
nonPositiveInteger: {
tsType: "number",
initializer: "0"
},
positiveInteger: {
tsType: "number",
initializer: "0"
},
negativeInteger: {
tsType: "number",
initializer: "0"
},
unsignedInt: {
tsType: "number",
initializer: "0"
},
unsignedLong: {
tsType: "number",
initializer: "0"
},
unsignedShort: {
tsType: "number",
initializer: "0"
},
unsignedByte: {
tsType: "number",
initializer: "0"
},
decimal: {
tsType: "number",
initializer: "0"
},
float: {
tsType: "number",
initializer: "0"
},
double: {
tsType: "number",
initializer: "0"
},
boolean: {
tsType: "boolean",
initializer: "false"
},
dateTime: {
tsType: "string",
initializer: "''",
dataType: "xs:dateTime"
},
date: {
tsType: "string",
initializer: "''",
dataType: "xs:date"
},
time: {
tsType: "string",
initializer: "''",
dataType: "xs:time"
},
duration: {
tsType: "string",
initializer: "''"
},
gYear: {
tsType: "string",
initializer: "''"
},
gMonth: {
tsType: "string",
initializer: "''"
},
gDay: {
tsType: "string",
initializer: "''"
},
gYearMonth: {
tsType: "string",
initializer: "''"
},
gMonthDay: {
tsType: "string",
initializer: "''"
},
base64Binary: {
tsType: "string",
initializer: "''"
},
hexBinary: {
tsType: "string",
initializer: "''"
},
anyType: {
tsType: "unknown",
initializer: "undefined"
},
anySimpleType: {
tsType: "string",
initializer: "''"
}
};
XsdResolver = class {
constructor() {
this.complexTypeMap = /* @__PURE__ */ new Map();
this.simpleTypeMap = /* @__PURE__ */ new Map();
this.groupMap = /* @__PURE__ */ new Map();
this.attributeGroupMap = /* @__PURE__ */ new Map();
this.resolvedTypeMap = /* @__PURE__ */ new Map();
this.substitutionMap = /* @__PURE__ */ new Map();
}
resolve(schema) {
this.schema = schema;
this.buildLookups();
this.resolvedTypeMap.clear();
const resolved = {
targetNamespace: schema.targetNamespace,
elementFormDefault: schema.elementFormDefault,
namespaces: schema.namespaces,
types: [],
enums: [],
rootElements: []
};
for (const st of schema.simpleTypes) if (st.name && st.restriction && st.restriction.enumerations.length > 0) resolved.enums.push({
name: toPascalCase(st.name),
xmlName: st.name,
values: st.restriction.enumerations,
baseType: stripPrefix(st.restriction.base)
});
for (const ct of schema.complexTypes) if (ct.name) this.addResolvedType(this.resolveComplexType(ct, ct.name, false));
for (const el of schema.elements) if (el.complexType) this.addResolvedType(this.resolveComplexType(el.complexType, el.name, true));
else if (el.type) {
const localType = stripPrefix(el.type);
if (this.complexTypeMap.has(localType)) resolved.rootElements.push({
name: el.name,
typeName: toPascalCase(localType),
nillable: el.nillable
});
else this.addResolvedType(this.resolveSimpleRootElement(el));
} else if (el.simpleType) this.addResolvedType(this.resolveSimpleRootElement(el));
resolved.types = [...this.resolvedTypeMap.values()];
return resolved;
}
addResolvedType(type) {
if (!this.resolvedTypeMap.has(type.className)) this.resolvedTypeMap.set(type.className, type);
}
buildLookups() {
this.complexTypeMap.clear();
this.simpleTypeMap.clear();
this.groupMap.clear();
this.attributeGroupMap.clear();
this.substitutionMap.clear();
this.buildTypeLookups();
this.buildGroupLookups();
this.buildAttributeGroupLookups();
this.buildSubstitutionLookups();
}
buildTypeLookups() {
for (const ct of this.schema.complexTypes) if (ct.name) this.complexTypeMap.set(ct.name, ct);
for (const st of this.schema.simpleTypes) if (st.name) this.simpleTypeMap.set(st.name, st);
}
buildGroupLookups() {
for (const g of this.schema.groups) if (g.name) {
const compositor = g.sequence ?? g.choice ?? g.all;
if (compositor) this.groupMap.set(g.name, compositor);
}
}
buildAttributeGroupLookups() {
const groupDefs = /* @__PURE__ */ new Map();
for (const ag of this.schema.attributeGroups) if (ag.name) groupDefs.set(ag.name, ag);
const resolving = /* @__PURE__ */ new Set();
const resolveGroup = (name) => {
const cached = this.attributeGroupMap.get(name);
if (cached) return cached;
const def = groupDefs.get(name);
if (!def) return [];
if (resolving.has(name)) return [];
resolving.add(name);
const attrs = [...def.attributes];
for (const ref of def.attributeGroupRefs) {
const resolvedAttrs = resolveGroup(stripPrefix(ref.ref));
if (resolvedAttrs.length) attrs.push(...resolvedAttrs);
}
resolving.delete(name);
this.attributeGroupMap.set(name, attrs);
return attrs;
};
for (const name of groupDefs.keys()) resolveGroup(name);
}
buildSubstitutionLookups() {
for (const el of this.schema.elements) if (el.substitutionGroup) {
const headName = stripPrefix(el.substitutionGroup);
const substitutes = this.substitutionMap.get(headName);
if (substitutes) substitutes.push(el.name);
else this.substitutionMap.set(headName, [el.name]);
}
}
resolveComplexType(ct, name, isRoot, classNameOverride) {
const resolved = {
className: classNameOverride ?? toPascalCase(name),
xmlName: name,
properties: [],
isRootElement: isRoot,
mixed: ct.mixed,
abstract: ct.abstract
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix ?? void 0
};
}
if (ct.simpleContent) {
resolved.hasSimpleContent = true;
this.resolveSimpleContent(ct.simpleContent, resolved);
return resolved;
}
if (ct.complexContent) this.resolveComplexContent(ct.complexContent, resolved);
let order = 1;
if (ct.sequence) order = this.resolveSequenceProperties(ct.sequence, resolved.properties, order);
if (ct.choice) order = this.resolveChoiceProperties(ct.choice, resolved.properties, order);
if (ct.all) this.resolveAllProperties(ct.all, resolved.properties);
for (const gRef of ct.groupRefs) order = this.resolveGroupRef(gRef, resolved.properties, order);
this.resolveAttributes(ct.attributes, resolved.properties);
for (const agRef of ct.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
if (ct.anyAttribute) resolved.properties.push({
propertyName: "anyAttributes",
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!"
});
return resolved;
}
resolveSimpleContent(sc, resolved) {
if (sc.extension) {
const baseInfo = this.resolveTypeReference(sc.extension.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.extension.attributes, resolved.properties);
} else if (sc.restriction) {
const baseInfo = this.resolveTypeReference(sc.restriction.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
enumValues: sc.restriction.enumerations.length > 0 ? sc.restriction.enumerations : void 0,
pattern: sc.restriction.pattern,
minLength: sc.restriction.minLength,
maxLength: sc.restriction.maxLength,
minInclusive: sc.restriction.minInclusive,
maxInclusive: sc.restriction.maxInclusive,
minExclusive: sc.restriction.minExclusive,
maxExclusive: sc.restriction.maxExclusive,
totalDigits: sc.restriction.totalDigits,
fractionDigits: sc.restriction.fractionDigits,
whiteSpace: sc.restriction.whiteSpace,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.restriction.attributes, resolved.properties);
}
}
resolveComplexContent(cc, resolved) {
if (cc.extension) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.extension.base));
let order = 1;
if (cc.extension.sequence) order = this.resolveSequenceProperties(cc.extension.sequence, resolved.properties, order);
if (cc.extension.choice) order = this.resolveChoiceProperties(cc.extension.choice, resolved.properties, order);
if (cc.extension.all) this.resolveAllProperties(cc.extension.all, resolved.properties);
for (const gRef of cc.extension.groupRefs) order = this.resolveGroupRef(gRef, resolved.properties, order);
this.resolveAttributes(cc.extension.attributes, resolved.properties);
for (const agRef of cc.extension.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
} else if (cc.restriction) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.restriction.base));
if (cc.restriction.sequence) this.resolveSequenceProperties(cc.restriction.sequence, resolved.properties, 1);
this.resolveAttributes(cc.restriction.attributes, resolved.properties);
}
}
resolveSequenceProperties(seq, props, startOrder) {
let order = startOrder;
for (const el of seq.elements) props.push(this.resolveElementProperty(el, order++));
for (const choice of seq.choices) order = this.resolveChoiceProperties(choice, props, order);
for (const nested of seq.sequences) order = this.resolveSequenceProperties(nested, props, order);
for (const gRef of seq.groupRefs) order = this.resolveGroupRef(gRef, props, order);
for (const any of seq.any) {
props.push({
propertyName: `dynamicContent${order}`,
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
order: order++
});
if (any.minOccurs === void 0 || any.minOccurs > 0) props[props.length - 1].required = true;
}
return order;
}
resolveChoiceProperties(choice, props, startOrder) {
let order = startOrder;
for (const el of choice.elements) {
const prop = this.resolveElementProperty(el, order++);
prop.required = false;
props.push(prop);
}
for (const seq of choice.sequences) order = this.resolveSequenceProperties(seq, props, order);
for (const gRef of choice.groupRefs) order = this.resolveGroupRef(gRef, props, order);
return order;
}
resolveAllProperties(all, props) {
for (const el of all.elements) props.push(this.resolveElementProperty(el));
}
resolveGroupRef(gRef, props, startOrder) {
const refName = stripPrefix(gRef.ref);
const compositor = this.groupMap.get(refName);
if (!compositor) return startOrder;
if ("elements" in compositor && "choices" in compositor) return this.resolveSequenceProperties(compositor, props, startOrder);
if ("elements" in compositor && !("choices" in compositor)) {
if ("sequences" in compositor) return this.resolveChoiceProperties(compositor, props, startOrder);
this.resolveAllProperties(compositor, props);
}
return startOrder;
}
resolveElementProperty(el, order) {
const isArray = el.maxOccurs === "unbounded" || typeof el.maxOccurs === "number" && el.maxOccurs > 1;
const isRequired = el.minOccurs === void 0 || el.minOccurs > 0;
const form = el.form ?? this.resolveElementForm();
const name = el.ref ? stripPrefix(el.ref) : el.name;
if (this.substitutionMap.has(name)) return {
propertyName: toCamelCase(name),
xmlName: name,
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
required: isRequired,
order
};
let typeInfo;
if (el.complexType) {
const inlineTypeName = toPascalCase(name) + "Type";
this.addResolvedType(this.resolveComplexType(el.complexType, name, false, inlineTypeName));
typeInfo = {
tsType: inlineTypeName,
initializer: `new ${inlineTypeName}()`,
complexTypeName: inlineTypeName
};
} else if (el.simpleType) typeInfo = this.resolveSimpleTypeInline(el.simpleType);
else if (el.type) typeInfo = this.resolveTypeReference(el.type);
else typeInfo = {
tsType: "string",
initializer: "''"
};
const prop = {
propertyName: toCamelCase(name),
xmlName: name,
kind: isArray ? "array" : "element",
tsType: isArray ? `${typeInfo.tsType}[]` : typeInfo.tsType,
initializer: isArray ? "[]" : typeInfo.initializer,
required: isRequired,
order,
isNullable: el.nillable,
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: el.defaultValue ?? el.fixed,
fixedValue: el.fixed,
complexTypeName: typeInfo.complexTypeName,
enumValues: typeInfo.enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
};
if (isArray) {
prop.arrayItemName = name;
prop.arrayItemType = typeInfo.complexTypeName;
}
return prop;
}
resolveAttributes(attrs, props) {
for (const a of attrs) {
if (a.ref) {
const form = a.form ?? this.resolveAttributeForm();
const defaultOrFixed = a.defaultValue ?? a.fixed;
props.push({
propertyName: toCamelCase(stripPrefix(a.ref)),
xmlName: stripPrefix(a.ref),
kind: "attribute",
tsType: "string",
initializer: defaultOrFixed ? `'${escapeString(defaultOrFixed)}'` : "''",
required: a.use === "required",
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: defaultOrFixed,
fixedValue: a.fixed
});
continue;
}
let typeInfo;
if (a.simpleType) typeInfo = this.resolveSimpleTypeInline(a.simpleType);
else if (a.type) typeInfo = this.resolveTypeReference(a.type);
else typeInfo = {
tsType: "string",
initializer: "''"
};
const defaultOrFixed = a.defaultValue ?? a.fixed;
const initializer = defaultOrFixed ? this.buildDefaultInitializer(typeInfo.tsType, defaultOrFixed) : typeInfo.initializer;
const form = a.form ?? this.resolveAttributeForm();
const enumValues = typeInfo.enumValues ? [...typeInfo.enumValues] : a.fixed ? [a.fixed] : void 0;
props.push({
propertyName: toCamelCase(a.name),
xmlName: a.name,
kind: "attribute",
tsType: typeInfo.tsType,
initializer,
required: a.use === "required",
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: defaultOrFixed,
fixedValue: a.fixed,
enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
});
}
}
resolveTypeReference(typeRef) {
const localName = stripPrefix(typeRef);
const builtin = XSD_TYPE_MAP[localName];
if (builtin) return { ...builtin };
if (this.complexTypeMap.has(localName)) {
const className = toPascalCase(localName);
return {
tsType: className,
initializer: `new ${className}()`,
complexTypeName: className
};
}
const st = this.simpleTypeMap.get(localName);
if (st) return this.resolveSimpleTypeInline(st);
return {
tsType: "string",
initializer: "''"
};
}
resolveSimpleTypeInline(st) {
if (st.restriction) {
const result = { ...this.resolveTypeReference(st.restriction.base) };
if (st.restriction.enumerations.length > 0) if (st.name) {
result.enumTypeName = toPascalCase(st.name);
result.tsType = toPascalCase(st.name);
} else result.enumValues = st.restriction.enumerations;
if (st.restriction.pattern) result.pattern = st.restriction.pattern;
result.minLength = st.restriction.minLength;
result.maxLength = st.restriction.maxLength;
result.minInclusive = st.restriction.minInclusive;
result.maxInclusive = st.restriction.maxInclusive;
result.minExclusive = st.restriction.minExclusive;
result.maxExclusive = st.restriction.maxExclusive;
result.totalDigits = st.restriction.totalDigits;
result.fractionDigits = st.restriction.fractionDigits;
result.whiteSpace = st.restriction.whiteSpace;
return result;
}
if (st.list) return {
tsType: `${this.resolveTypeReference(st.list.itemType).tsType}[]`,
initializer: "[]"
};
if (st.union) {
if (st.union.memberTypes.length > 0) {
const memberInfos = st.union.memberTypes.map((mt) => this.resolveTypeReference(mt));
return {
tsType: [...new Set(memberInfos.map((m) => m.tsType))].join(" | "),
initializer: memberInfos[0].initializer
};
}
return {
tsType: "string",
initializer: "''"
};
}
return {
tsType: "string",
initializer: "''"
};
}
resolveSimpleRootElement(el) {
const typeInfo = el.simpleType ? this.resolveSimpleTypeInline(el.simpleType) : el.type ? this.resolveTypeReference(el.type) : {
tsType: "string",
initializer: "''"
};
const resolved = {
className: toPascalCase(el.name),
xmlName: el.name,
properties: [{
propertyName: "value",
xmlName: "",
kind: "text",
tsType: typeInfo.tsType,
initializer: typeInfo.initializer,
dataType: typeInfo.dataType
}],
isRootElement: true
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix ?? void 0
};
}
return resolved;
}
resolveElementForm() {
return this.schema.elementFormDefault;
}
resolveAttributeForm() {
return this.schema.attributeFormDefault;
}
resolveNamespaceForForm(form) {
if (form !== "qualified" || !this.schema.targetNamespace) return;
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
return {
uri: this.schema.targetNamespace,
prefix: prefix ?? void 0
};
}
findPrefixForUri(uri) {
for (const [prefix, nsUri] of this.schema.namespaces) if (nsUri === uri && prefix !== "") return prefix;
}
buildDefaultInitializer(tsType, defaultValue) {
if (tsType === "number") return defaultValue;
if (tsType === "boolean") return defaultValue === "true" ? "true" : "false";
return `'${escapeString(defaultValue)}'`;
}
};
RESERVED_TS_IDENTIFIERS = new Set([
"abstract",
"any",
"as",
"asserts",
"async",
"await",
"boolean",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"declare",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"from",
"function",
"get",
"if",
"implements",
"import",
"in",
"infer",
"instanceof",
"interface",
"is",
"keyof",
"let",
"module",
"namespace",
"never",
"new",
"null",
"number",
"object",
"package",
"private",
"protected",
"public",
"readonly",
"require",
"return",
"set",
"static",
"string",
"super",
"switch",
"symbol",
"this",
"throw",
"true",
"try",
"type",
"typeof",
"undefined",
"unique",
"unknown",
"var",
"void",
"while",
"with",
"yield"
]);
}));
//#endregion
export { init_config_loader as C, __esmMin as D, __commonJSMin as E, findConfigFile as S, validateConfig as T, buildFileHeader as _, XsdParser as a, init_ts_builder as b, writeGeneratedFile as c, init_class_generator as d, collectImports as f, buildDecorator as g, mapPropertyDecorator as h, toPascalCase as i, writeGeneratedFiles as l, mapClassDecorator as m, init_xsd_resolver as n, init_xsd_parser as o, init_decorator_mapper as p, toCamelCase as r, init_file_writer as s, XsdResolver as t, ClassGenerator as u, buildImport as v, loadConfig as w, toKebabCase as x, buildProperty as y };
//# sourceMappingURL=xsd-resolver-DUAJQeCN.mjs.map

Sorry, the diff of this file is too big to display

+1
-1

@@ -1,1 +0,1 @@

#!/usr/bin/env node
export { };

@@ -0,1 +1,2 @@

//#region src/config/config-types.d.ts
/**

@@ -6,16 +7,16 @@ * Configuration for a single XSD source to process.

interface XsdSource {
/** Path to the XSD file (relative to config file or absolute). */
xsdPath: string;
/**
* Output path for generated TypeScript files.
* - per-type: directory path
* - per-xsd: file path
*/
outputPath: string;
/** Output style: 'per-type' generates one file per class, 'per-xsd' puts all types in one file. */
outputStyle?: "per-type" | "per-xsd";
/** Enum generation style for this source. Overrides the global setting. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Overrides the global setting. */
useXmlRoot?: boolean;
/** Path to the XSD file (relative to config file or absolute). */
xsdPath: string;
/**
* Output path for generated TypeScript files.
* - per-type: directory path
* - per-xsd: file path
*/
outputPath: string;
/** Output style: 'per-type' generates one file per class, 'per-xsd' puts all types in one file. */
outputStyle?: "per-type" | "per-xsd";
/** Enum generation style for this source. Overrides the global setting. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Overrides the global setting. */
useXmlRoot?: boolean;
}

@@ -26,304 +27,307 @@ /**

interface XmlPotoCodegenConfig {
/** Array of XSD sources to process. */
sources: XsdSource[];
/** Default output style when not specified per source. Defaults to 'per-type'. */
defaultOutputStyle?: "per-type" | "per-xsd";
/** Default enum generation style. Defaults to 'union'. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Defaults to true. */
useXmlRoot?: boolean;
/** Array of XSD sources to process. */
sources: XsdSource[];
/** Default output style when not specified per source. Defaults to 'per-type'. */
defaultOutputStyle?: "per-type" | "per-xsd";
/** Default enum generation style. Defaults to 'union'. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Defaults to true. */
useXmlRoot?: boolean;
}
//#endregion
//#region src/config/config-loader.d.ts
declare function validateConfig(config: unknown): XmlPotoCodegenConfig;
declare function findConfigFile(cwd: string): string | undefined;
declare function loadConfig(configPath?: string): Promise<{
config: XmlPotoCodegenConfig;
configDir: string;
config: XmlPotoCodegenConfig;
configDir: string;
}>;
//#endregion
//#region src/xsd/xsd-types.d.ts
interface XsdNamespace {
uri: string;
prefix?: string;
uri: string;
prefix?: string;
}
interface XsdSchema {
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
attributeFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
elements: XsdElement[];
complexTypes: XsdComplexType[];
simpleTypes: XsdSimpleType[];
groups: XsdGroup[];
attributeGroups: XsdAttributeGroup[];
imports: XsdImport[];
includes: XsdInclude[];
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
attributeFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
elements: XsdElement[];
complexTypes: XsdComplexType[];
simpleTypes: XsdSimpleType[];
groups: XsdGroup[];
attributeGroups: XsdAttributeGroup[];
imports: XsdImport[];
includes: XsdInclude[];
}
interface XsdElement {
name: string;
type?: string;
ref?: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
nillable?: boolean;
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
/** Substitution group head element name */
substitutionGroup?: string;
/** Inline complexType definition */
complexType?: XsdComplexType;
/** Inline simpleType definition */
simpleType?: XsdSimpleType;
name: string;
type?: string;
ref?: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
nillable?: boolean;
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
/** Substitution group head element name */
substitutionGroup?: string;
/** Inline complexType definition */
complexType?: XsdComplexType;
/** Inline simpleType definition */
simpleType?: XsdSimpleType;
}
interface XsdComplexType {
name?: string;
mixed?: boolean;
abstract?: boolean;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
simpleContent?: XsdSimpleContent;
complexContent?: XsdComplexContent;
/** Group references within this type */
groupRefs: XsdGroupRef[];
/** Attribute group references */
attributeGroupRefs: XsdAttributeGroupRef[];
/** xs:anyAttribute */
anyAttribute?: boolean;
name?: string;
mixed?: boolean;
abstract?: boolean;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
simpleContent?: XsdSimpleContent;
complexContent?: XsdComplexContent;
/** Group references within this type */
groupRefs: XsdGroupRef[];
/** Attribute group references */
attributeGroupRefs: XsdAttributeGroupRef[];
/** xs:anyAttribute */
anyAttribute?: boolean;
}
interface XsdSimpleType {
name?: string;
restriction?: XsdRestriction;
list?: XsdList;
union?: XsdUnion;
name?: string;
restriction?: XsdRestriction;
list?: XsdList;
union?: XsdUnion;
}
interface XsdRestriction {
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
}
interface XsdList {
itemType: string;
itemType: string;
}
interface XsdUnion {
memberTypes: string[];
memberTypes: string[];
}
interface XsdAttribute {
name: string;
type?: string;
use?: "required" | "optional" | "prohibited";
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
ref?: string;
simpleType?: XsdSimpleType;
name: string;
type?: string;
use?: "required" | "optional" | "prohibited";
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
ref?: string;
simpleType?: XsdSimpleType;
}
interface XsdSequence {
elements: XsdElement[];
choices: XsdChoice[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
any: XsdAny[];
elements: XsdElement[];
choices: XsdChoice[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
any: XsdAny[];
}
interface XsdChoice {
elements: XsdElement[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
minOccurs?: number;
maxOccurs?: number | "unbounded";
elements: XsdElement[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdAll {
elements: XsdElement[];
elements: XsdElement[];
}
interface XsdAny {
namespace?: string;
processContents?: "strict" | "lax" | "skip";
minOccurs?: number;
maxOccurs?: number | "unbounded";
namespace?: string;
processContents?: "strict" | "lax" | "skip";
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdSimpleContent {
extension?: XsdSimpleContentExtension;
restriction?: XsdSimpleContentRestriction;
extension?: XsdSimpleContentExtension;
restriction?: XsdSimpleContentRestriction;
}
interface XsdSimpleContentExtension {
base: string;
attributes: XsdAttribute[];
base: string;
attributes: XsdAttribute[];
}
interface XsdSimpleContentRestriction {
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
attributes: XsdAttribute[];
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
attributes: XsdAttribute[];
}
interface XsdComplexContent {
extension?: XsdComplexContentExtension;
restriction?: XsdComplexContentRestriction;
mixed?: boolean;
extension?: XsdComplexContentExtension;
restriction?: XsdComplexContentRestriction;
mixed?: boolean;
}
interface XsdComplexContentExtension {
base: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
groupRefs: XsdGroupRef[];
attributeGroupRefs: XsdAttributeGroupRef[];
base: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
groupRefs: XsdGroupRef[];
attributeGroupRefs: XsdAttributeGroupRef[];
}
interface XsdComplexContentRestriction {
base: string;
sequence?: XsdSequence;
attributes: XsdAttribute[];
base: string;
sequence?: XsdSequence;
attributes: XsdAttribute[];
}
interface XsdGroup {
name: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
name: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
}
interface XsdGroupRef {
ref: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
ref: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdAttributeGroup {
name: string;
attributes: XsdAttribute[];
attributeGroupRefs: XsdAttributeGroupRef[];
name: string;
attributes: XsdAttribute[];
attributeGroupRefs: XsdAttributeGroupRef[];
}
interface XsdAttributeGroupRef {
ref: string;
ref: string;
}
interface XsdImport {
namespace?: string;
schemaLocation?: string;
namespace?: string;
schemaLocation?: string;
}
interface XsdInclude {
schemaLocation: string;
schemaLocation: string;
}
//#endregion
//#region src/xsd/xsd-resolver.d.ts
interface ResolvedSchema {
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
types: ResolvedType[];
enums: ResolvedEnum[];
/** Top-level elements that reference named types (root element candidates) */
rootElements: ResolvedRootElement[];
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
types: ResolvedType[];
enums: ResolvedEnum[];
/** Top-level elements that reference named types (root element candidates) */
rootElements: ResolvedRootElement[];
}
interface ResolvedRootElement {
name: string;
typeName: string;
nillable?: boolean;
name: string;
typeName: string;
nillable?: boolean;
}
interface ResolvedType {
/** Class name (PascalCase) */
className: string;
/** Original XML element/type name */
xmlName: string;
/** Properties of this type */
properties: ResolvedProperty[];
/** Base type name if this type extends another */
baseTypeName?: string;
/** Whether this is a root element (gets @XmlRoot instead of @XmlElement) */
isRootElement: boolean;
/** mixed content model */
mixed?: boolean;
/** Namespace info */
namespace?: {
uri: string;
prefix?: string;
};
/** Whether abstract (cannot be instantiated directly) */
abstract?: boolean;
/** Has simpleContent (text value + attributes) */
hasSimpleContent?: boolean;
/** Root-level nillable flag when promoted from top-level element reference */
rootNillable?: boolean;
/** Namespace form (qualified/unqualified) */
form?: "qualified" | "unqualified";
/** Class name (PascalCase) */
className: string;
/** Original XML element/type name */
xmlName: string;
/** Properties of this type */
properties: ResolvedProperty[];
/** Base type name if this type extends another */
baseTypeName?: string;
/** Whether this is a root element (gets @XmlRoot instead of @XmlElement) */
isRootElement: boolean;
/** mixed content model */
mixed?: boolean;
/** Namespace info */
namespace?: {
uri: string;
prefix?: string;
};
/** Whether abstract (cannot be instantiated directly) */
abstract?: boolean;
/** Has simpleContent (text value + attributes) */
hasSimpleContent?: boolean;
/** Root-level nillable flag when promoted from top-level element reference */
rootNillable?: boolean;
/** Namespace form (qualified/unqualified) */
form?: "qualified" | "unqualified";
}
type PropertyKind = "element" | "attribute" | "text" | "array" | "dynamic";
interface ResolvedProperty {
/** TypeScript property name (camelCase) */
propertyName: string;
/** Original XML name */
xmlName: string;
/** Kind of decorator to apply */
kind: PropertyKind;
/** TypeScript type string */
tsType: string;
/** Default initializer expression */
initializer: string;
/** Whether required (minOccurs > 0 or use="required") */
required?: boolean;
/** Element order in sequence */
order?: number;
/** Whether nullable (xsi:nil) */
isNullable?: boolean;
/** Form qualification */
form?: "qualified" | "unqualified";
/** Default value from XSD */
defaultValue?: string;
/** For arrays: the item element name */
arrayItemName?: string;
/** For arrays: wrapper container name */
arrayContainerName?: string;
/** For arrays: the item type class name (if complex type) */
arrayItemType?: string;
/** For elements/arrays referencing a complex type: the class name */
complexTypeName?: string;
/** Enum values restriction */
enumValues?: string[];
/** Pattern restriction */
pattern?: string;
/** Referenced enum type name */
enumTypeName?: string;
/** Namespace for this property */
namespace?: {
uri: string;
prefix?: string;
};
/** XSD dataType (e.g. 'xs:dateTime') */
dataType?: string;
/** XSD fixed value constraint */
fixedValue?: string;
/** XSD restriction facets retained for diagnostics/manual post-processing */
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
/** TypeScript property name (camelCase) */
propertyName: string;
/** Original XML name */
xmlName: string;
/** Kind of decorator to apply */
kind: PropertyKind;
/** TypeScript type string */
tsType: string;
/** Default initializer expression */
initializer: string;
/** Whether required (minOccurs > 0 or use="required") */
required?: boolean;
/** Element order in sequence */
order?: number;
/** Whether nullable (xsi:nil) */
isNullable?: boolean;
/** Form qualification */
form?: "qualified" | "unqualified";
/** Default value from XSD */
defaultValue?: string;
/** For arrays: the item element name */
arrayItemName?: string;
/** For arrays: wrapper container name */
arrayContainerName?: string;
/** For arrays: the item type class name (if complex type) */
arrayItemType?: string;
/** For elements/arrays referencing a complex type: the class name */
complexTypeName?: string;
/** Enum values restriction */
enumValues?: string[];
/** Pattern restriction */
pattern?: string;
/** Referenced enum type name */
enumTypeName?: string;
/** Namespace for this property */
namespace?: {
uri: string;
prefix?: string;
};
/** XSD dataType (e.g. 'xs:dateTime') */
dataType?: string;
/** XSD fixed value constraint */
fixedValue?: string;
/** XSD restriction facets retained for diagnostics/manual post-processing */
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
}
interface ResolvedEnum {
/** TypeScript enum name (PascalCase) */
name: string;
/** Original XSD type name */
xmlName: string;
/** Enum values */
values: string[];
/** Base restriction type */
baseType: string;
/** TypeScript enum name (PascalCase) */
name: string;
/** Original XSD type name */
xmlName: string;
/** Enum values */
values: string[];
/** Base restriction type */
baseType: string;
}

@@ -335,34 +339,34 @@ /**

declare class XsdResolver {
private schema;
private complexTypeMap;
private simpleTypeMap;
private groupMap;
private attributeGroupMap;
private resolvedTypeMap;
/** Maps head element name → list of substitute element names */
private substitutionMap;
resolve(schema: XsdSchema): ResolvedSchema;
private addResolvedType;
private buildLookups;
private buildTypeLookups;
private buildGroupLookups;
private buildAttributeGroupLookups;
private buildSubstitutionLookups;
private resolveComplexType;
private resolveSimpleContent;
private resolveComplexContent;
private resolveSequenceProperties;
private resolveChoiceProperties;
private resolveAllProperties;
private resolveGroupRef;
private resolveElementProperty;
private resolveAttributes;
private resolveTypeReference;
private resolveSimpleTypeInline;
private resolveSimpleRootElement;
private resolveElementForm;
private resolveAttributeForm;
private resolveNamespaceForForm;
private findPrefixForUri;
private buildDefaultInitializer;
private schema;
private complexTypeMap;
private simpleTypeMap;
private groupMap;
private attributeGroupMap;
private resolvedTypeMap;
/** Maps head element name → list of substitute element names */
private substitutionMap;
resolve(schema: XsdSchema): ResolvedSchema;
private addResolvedType;
private buildLookups;
private buildTypeLookups;
private buildGroupLookups;
private buildAttributeGroupLookups;
private buildSubstitutionLookups;
private resolveComplexType;
private resolveSimpleContent;
private resolveComplexContent;
private resolveSequenceProperties;
private resolveChoiceProperties;
private resolveAllProperties;
private resolveGroupRef;
private resolveElementProperty;
private resolveAttributes;
private resolveTypeReference;
private resolveSimpleTypeInline;
private resolveSimpleRootElement;
private resolveElementForm;
private resolveAttributeForm;
private resolveNamespaceForForm;
private findPrefixForUri;
private buildDefaultInitializer;
}

@@ -373,16 +377,17 @@ /** Convert to PascalCase: "my-type_name" → "MyTypeName" */

declare function toCamelCase(name: string): string;
//#endregion
//#region src/generator/class-generator.d.ts
interface ClassGeneratorOptions {
xsdPath: string;
enumStyle?: EnumStyle;
useXmlRoot?: boolean;
elementFormDefault?: "qualified" | "unqualified";
xsdPath: string;
enumStyle?: EnumStyle;
useXmlRoot?: boolean;
elementFormDefault?: "qualified" | "unqualified";
}
interface GeneratedFile {
/** Filename (without directory) */
fileName: string;
/** Full TypeScript source content */
content: string;
/** Exported class/enum names */
exports: string[];
/** Filename (without directory) */
fileName: string;
/** Full TypeScript source content */
content: string;
/** Exported class/enum names */
exports: string[];
}

@@ -393,29 +398,30 @@ /**

declare class ClassGenerator {
private readonly importPath;
private xsdPath;
private enumStyle;
private useXmlRoot;
private elementFormDefault?;
constructor(options: ClassGeneratorOptions);
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema: ResolvedSchema): GeneratedFile[];
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema: ResolvedSchema, fileName?: string): GeneratedFile[];
private generateEnumFile;
private generateClassFile;
private generateBarrelExport;
private generateSingleFile;
private generateEnumSource;
private generateEnumAsUnion;
private generateEnumAsEnum;
private generateEnumAsConstObject;
private generateClassSource;
private collectLocalImports;
private applyRootElements;
private readonly importPath;
private xsdPath;
private enumStyle;
private useXmlRoot;
private elementFormDefault?;
constructor(options: ClassGeneratorOptions);
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema: ResolvedSchema): GeneratedFile[];
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema: ResolvedSchema, fileName?: string): GeneratedFile[];
private generateEnumFile;
private generateClassFile;
private generateBarrelExport;
private generateSingleFile;
private generateEnumSource;
private generateEnumAsUnion;
private generateEnumAsEnum;
private generateEnumAsConstObject;
private generateClassSource;
private collectLocalImports;
private applyRootElements;
}
//#endregion
//#region src/generator/decorator-mapper.d.ts
/**

@@ -430,3 +436,4 @@ * Maps resolved XSD types and properties to xml-poto decorator strings.

declare function collectImports(type: ResolvedType): Set<string>;
//#endregion
//#region src/generator/file-writer.d.ts
/**

@@ -436,3 +443,3 @@ * Writes generated files to the output directory.

declare function writeGeneratedFiles(outputDir: string, files: GeneratedFile[]): {
written: string[];
written: string[];
};

@@ -443,3 +450,4 @@ /**

declare function writeGeneratedFile(outputFilePath: string, file: GeneratedFile): string;
//#endregion
//#region src/generator/ts-builder.d.ts
/** Build an import statement */

@@ -455,3 +463,4 @@ declare function buildImport(names: string[], from: string, isType?: boolean): string;

declare function toKebabCase(name: string): string;
//#endregion
//#region src/xsd/xsd-parser.d.ts
/**

@@ -461,53 +470,54 @@ * Parses XSD files into a structured XsdSchema model using @cerios/xml-poto's XML parser.

declare class XsdParser {
private parser;
/** Detected XSD prefix in the current schema (e.g. 'xs', 'xsd', or '') */
private xsdPrefix;
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath: string): XsdSchema;
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent: string, baseDir?: string): XsdSchema;
private resolveExternalSchemas;
private findSchemaRootKey;
private detectXsdPrefix;
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
private xsd;
private parseSchema;
private extractNamespaces;
private parseElement;
private parseComplexType;
private parseSimpleType;
private parseRestriction;
private parseAttribute;
private parseSequence;
private parseChoice;
private parseAll;
private parseAny;
private parseSimpleContent;
private parseSimpleContentExtension;
private parseSimpleContentRestriction;
private parseComplexContent;
private parseComplexContentExtension;
private parseComplexContentRestriction;
private parseGroup;
private parseGroupRefs;
private parseAttributeGroup;
private parseAttributeGroupRefs;
private parseImport;
private parseInclude;
private mergeSchema;
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
private getChild;
/**
* Get all children with a given tag name as an array.
*/
private parseChildren;
private parser;
/** Detected XSD prefix in the current schema (e.g. 'xs', 'xsd', or '') */
private xsdPrefix;
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath: string): XsdSchema;
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent: string, baseDir?: string): XsdSchema;
private resolveExternalSchemas;
private findSchemaRootKey;
private detectXsdPrefix;
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
private xsd;
private parseSchema;
private extractNamespaces;
private parseElement;
private parseComplexType;
private parseSimpleType;
private parseRestriction;
private parseAttribute;
private parseSequence;
private parseChoice;
private parseAll;
private parseAny;
private parseSimpleContent;
private parseSimpleContentExtension;
private parseSimpleContentRestriction;
private parseComplexContent;
private parseComplexContentExtension;
private parseComplexContentRestriction;
private parseGroup;
private parseGroupRefs;
private parseAttributeGroup;
private parseAttributeGroupRefs;
private parseImport;
private parseInclude;
private mergeSchema;
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
private getChild;
/**
* Get all children with a given tag name as an array.
*/
private parseChildren;
}
//#endregion
export { ClassGenerator, type EnumStyle, type GeneratedFile, type ResolvedEnum, type ResolvedProperty, type ResolvedRootElement, type ResolvedSchema, type ResolvedType, type XmlPotoCodegenConfig, type XsdAll, type XsdAny, type XsdAttribute, type XsdAttributeGroup, type XsdAttributeGroupRef, type XsdChoice, type XsdComplexContent, type XsdComplexContentExtension, type XsdComplexContentRestriction, type XsdComplexType, type XsdElement, type XsdGroup, type XsdGroupRef, type XsdImport, type XsdInclude, type XsdNamespace, XsdParser, XsdResolver, type XsdRestriction, type XsdSchema, type XsdSequence, type XsdSimpleContent, type XsdSimpleContentExtension, type XsdSimpleContentRestriction, type XsdSimpleType, type XsdSource, buildDecorator, buildFileHeader, buildImport, buildProperty, collectImports, findConfigFile, loadConfig, mapClassDecorator, mapPropertyDecorator, toCamelCase, toKebabCase, toPascalCase, validateConfig, writeGeneratedFile, writeGeneratedFiles };
//# sourceMappingURL=index.d.mts.map

@@ -1,1728 +0,13 @@

// src/config/config-loader.ts
import fs from "fs";
import path from "path";
import { createJiti } from "jiti";
var CONFIG_NAMES = ["xml-poto-codegen.config.ts", "xml-poto-codegen.config.json"];
function validateConfig(config) {
if (!config || typeof config !== "object") {
throw new Error("Config must be an object.");
}
const cfg = config;
if (!Array.isArray(cfg.sources) || cfg.sources.length === 0) {
throw new Error("Config must have a non-empty 'sources' array.");
}
for (let i = 0; i < cfg.sources.length; i++) {
validateSourceConfig(cfg.sources[i], i);
}
if (!isValidOutputStyle(cfg.defaultOutputStyle)) {
throw new Error("defaultOutputStyle must be 'per-type' or 'per-xsd'.");
}
if (!isValidEnumStyle(cfg.enumStyle)) {
throw new Error("enumStyle must be 'union', 'enum', or 'const-object'.");
}
if (cfg.useXmlRoot !== void 0 && typeof cfg.useXmlRoot !== "boolean") {
throw new Error("useXmlRoot must be a boolean.");
}
return config;
}
function validateSourceConfig(source, index) {
if (!source || typeof source !== "object") {
throw new Error(`sources[${index}] must be an object.`);
}
const src = source;
if (!src.xsdPath || typeof src.xsdPath !== "string") {
throw new Error(`sources[${index}].xsdPath must be a non-empty string.`);
}
if (!src.outputPath || typeof src.outputPath !== "string") {
throw new Error(`sources[${index}].outputPath must be a non-empty string.`);
}
if (!isValidOutputStyle(src.outputStyle)) {
throw new Error(`sources[${index}].outputStyle must be 'per-type' or 'per-xsd'.`);
}
if (!isValidEnumStyle(src.enumStyle)) {
throw new Error(`sources[${index}].enumStyle must be 'union', 'enum', or 'const-object'.`);
}
if (src.useXmlRoot !== void 0 && typeof src.useXmlRoot !== "boolean") {
throw new Error(`sources[${index}].useXmlRoot must be a boolean.`);
}
}
function isValidOutputStyle(value) {
return value === void 0 || value === "per-type" || value === "per-xsd";
}
function isValidEnumStyle(value) {
return value === void 0 || value === "union" || value === "enum" || value === "const-object";
}
function findConfigFile(cwd) {
for (const name of CONFIG_NAMES) {
const fullPath = path.resolve(cwd, name);
if (fs.existsSync(fullPath)) {
return fullPath;
}
}
return void 0;
}
async function loadConfig(configPath) {
const resolvedPath = configPath ? path.resolve(configPath) : findConfigFile(process.cwd());
if (!resolvedPath) {
throw new Error("No config file found. Run 'xml-poto-codegen init' to create one.");
}
if (!fs.existsSync(resolvedPath)) {
throw new Error(`Config file not found: ${resolvedPath}`);
}
const configDir = path.dirname(resolvedPath);
let raw;
if (resolvedPath.endsWith(".json")) {
const content = fs.readFileSync(resolvedPath, "utf-8");
raw = JSON.parse(content);
} else if (resolvedPath.endsWith(".ts")) {
const jiti = createJiti(__filename);
const mod = await jiti.import(resolvedPath, { default: true });
if (mod && typeof mod === "object" && "default" in mod) {
raw = mod.default;
} else {
raw = mod;
}
} else {
throw new Error(`Unsupported config file format: ${resolvedPath}`);
}
const config = validateConfig(raw);
return { config, configDir };
}
import { C as init_config_loader, S as findConfigFile, T as validateConfig, _ as buildFileHeader, a as XsdParser, b as init_ts_builder, c as writeGeneratedFile, d as init_class_generator, f as collectImports, g as buildDecorator, h as mapPropertyDecorator, i as toPascalCase, l as writeGeneratedFiles, m as mapClassDecorator, n as init_xsd_resolver, o as init_xsd_parser, p as init_decorator_mapper, r as toCamelCase, s as init_file_writer, t as XsdResolver, u as ClassGenerator, v as buildImport, w as loadConfig, x as toKebabCase, y as buildProperty } from "./xsd-resolver-DUAJQeCN.mjs";
//#region src/index.ts
init_config_loader();
init_class_generator();
init_decorator_mapper();
init_file_writer();
init_ts_builder();
init_xsd_parser();
init_xsd_resolver();
//#endregion
export { ClassGenerator, XsdParser, XsdResolver, buildDecorator, buildFileHeader, buildImport, buildProperty, collectImports, findConfigFile, loadConfig, mapClassDecorator, mapPropertyDecorator, toCamelCase, toKebabCase, toPascalCase, validateConfig, writeGeneratedFile, writeGeneratedFiles };
// src/generator/ts-builder.ts
function buildImport(names, from, isType = false) {
if (names.length === 0) return "";
const sorted = [...new Set(names)].sort();
const typePrefix = isType ? "type " : "";
if (sorted.length <= 3) {
return `import ${typePrefix}{ ${sorted.join(", ")} } from "${from}";`;
}
const items = sorted.map((n) => ` ${n},`).join("\n");
return `import ${typePrefix}{
${items}
} from "${from}";`;
}
function buildDecorator(name, options) {
if (!options || Object.keys(options).length === 0) {
return `@${name}()`;
}
const entries = Object.entries(options).filter(([, v]) => v !== void 0);
if (entries.length === 0) {
return `@${name}()`;
}
const optionStr = entries.map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
if (optionStr.length < 60) {
return `@${name}({ ${optionStr} })`;
}
const lines = entries.map(([k, v]) => ` ${k}: ${formatValue(v)},`).join("\n");
return `@${name}({
${lines}
})`;
}
function formatValue(value) {
if (typeof value === "string") return value;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (value instanceof RegExp) return value.toString();
if (Array.isArray(value)) {
const items = value.map((v) => formatValue(v)).join(", ");
return `[${items}]`;
}
if (typeof value === "object" && value !== null) {
const entries = Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}: ${formatValue(v)}`);
return `{ ${entries.join(", ")} }`;
}
return String(value);
}
function buildProperty(name, type, initializer, optional = false) {
const optionalMark = optional ? "?" : "";
if (initializer === void 0) {
return `${name}${optionalMark}: ${type};`;
}
return `${name}${optionalMark}: ${type} = ${initializer};`;
}
function buildFileHeader(xsdPath) {
return [
"// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
"// AUTO-GENERATED by @cerios/xml-poto-codegen",
`// Source: ${xsdPath}`,
"// Do not edit manually.",
"// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
""
].join("\n");
}
function toKebabCase(name) {
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
}
// src/generator/decorator-mapper.ts
function mapClassDecorator(type) {
if (type.isRootElement) {
const opts2 = { name: `'${type.xmlName}'` };
if (type.namespace) {
opts2.namespace = buildNamespaceObj(type.namespace);
}
if (type.rootNillable) {
opts2.isNullable = true;
}
return buildDecorator("XmlRoot", opts2);
}
const opts = { name: `'${type.xmlName}'` };
if (type.namespace) {
opts.namespace = buildNamespaceObj(type.namespace);
}
if (type.rootNillable) {
opts.isNullable = true;
}
if (type.form) {
opts.form = `'${type.form}'`;
}
return buildDecorator("XmlElement", opts);
}
function mapPropertyDecorator(prop) {
switch (prop.kind) {
case "element":
return buildElementDecorator(prop);
case "attribute":
return buildAttributeDecorator(prop);
case "text":
return buildTextDecorator(prop);
case "array":
return buildArrayDecorator(prop);
case "dynamic":
return buildDynamicDecorator(prop);
default:
return buildDecorator("XmlElement", { name: `'${prop.xmlName}'` });
}
}
function collectImports(type) {
const imports = /* @__PURE__ */ new Set();
imports.add(type.isRootElement ? "XmlRoot" : "XmlElement");
for (const prop of type.properties) {
switch (prop.kind) {
case "element":
imports.add("XmlElement");
break;
case "attribute":
imports.add("XmlAttribute");
break;
case "text":
imports.add("XmlText");
break;
case "array":
imports.add("XmlArray");
break;
case "dynamic":
imports.add("XmlDynamic");
imports.add("DynamicElement");
break;
}
}
return imports;
}
function buildElementDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.complexTypeName) opts.type = prop.complexTypeName;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlElement", opts);
}
function buildAttributeDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.enumValues && prop.enumValues.length > 0)
opts.enumValues = prop.enumValues.map((v) => `'${escapeString(v)}'`);
if (prop.pattern) opts.pattern = `new RegExp(${JSON.stringify(prop.pattern)})`;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
return buildDecorator("XmlAttribute", opts);
}
function buildTextDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlText", opts);
}
function buildArrayDecorator(prop) {
const opts = {};
if (prop.arrayItemName) opts.itemName = `'${prop.arrayItemName}'`;
if (prop.arrayContainerName) opts.containerName = `'${prop.arrayContainerName}'`;
if (prop.arrayItemType) opts.type = prop.arrayItemType;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlArray", opts);
}
function buildDynamicDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
return buildDecorator("XmlDynamic", opts);
}
function buildNamespaceObj(ns) {
if (ns.prefix) {
return `{ uri: '${ns.uri}', prefix: '${ns.prefix}' }`;
}
return `{ uri: '${ns.uri}' }`;
}
function formatDefault(tsType, value) {
if (tsType === "number") return value;
if (tsType === "boolean") return value === "true" ? "true" : "false";
return `'${escapeString(value)}'`;
}
function escapeString(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
// src/generator/class-generator.ts
var ClassGenerator = class {
constructor(options) {
this.importPath = "@cerios/xml-poto";
var _a, _b;
this.xsdPath = options.xsdPath;
this.enumStyle = (_a = options.enumStyle) != null ? _a : "union";
this.useXmlRoot = (_b = options.useXmlRoot) != null ? _b : true;
this.elementFormDefault = options.elementFormDefault;
}
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema) {
const files = [];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const enumDef of schema.enums) {
files.push(this.generateEnumFile(enumDef));
}
for (const type of resolvedTypes) {
files.push(this.generateClassFile(type, resolvedTypes, schema.enums));
}
if (files.length > 0) {
files.push(this.generateBarrelExport(files));
}
return files;
}
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema, fileName) {
const output = fileName != null ? fileName : "generated";
const file = this.generateSingleFile(schema, `${toKebabCase(output)}.ts`);
return [file];
}
// ── Per-type generation ──
generateEnumFile(enumDef) {
const fileName = `${toKebabCase(enumDef.name)}.ts`;
const lines = [buildFileHeader(this.xsdPath), this.generateEnumSource(enumDef), ""];
return {
fileName,
content: lines.join("\n"),
exports: [enumDef.name]
};
}
generateClassFile(type, allTypes, allEnums) {
const fileName = `${toKebabCase(type.className)}.ts`;
const imports = collectImports(type);
const localImports = this.collectLocalImports(type, allTypes, allEnums);
const lines = [buildFileHeader(this.xsdPath), buildImport([...imports], this.importPath)];
for (const [name, file] of localImports) {
lines.push(buildImport([name], `./${file.replace(".ts", "")}`));
}
lines.push("");
lines.push(this.generateClassSource(type));
lines.push("");
return {
fileName,
content: lines.join("\n"),
exports: [type.className]
};
}
generateBarrelExport(files) {
const exports = files.filter((f) => f.fileName !== "index.ts").map((f) => {
const moduleName = f.fileName.replace(".ts", "");
return `export { ${f.exports.join(", ")} } from "./${moduleName}";`;
});
return {
fileName: "index.ts",
content: buildFileHeader(this.xsdPath) + exports.join("\n") + "\n",
exports: files.flatMap((f) => f.exports)
};
}
// ── Single-file generation ──
generateSingleFile(schema, fileName) {
const allImports = /* @__PURE__ */ new Set();
const allExports = [];
const parts = [buildFileHeader(this.xsdPath)];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const type of resolvedTypes) {
for (const imp of collectImports(type)) {
allImports.add(imp);
}
}
const needsDynamic = resolvedTypes.some((t) => t.properties.some((p) => p.kind === "dynamic"));
if (needsDynamic) {
allImports.add("DynamicElement");
}
parts.push(buildImport([...allImports], this.importPath));
parts.push("");
for (const enumDef of schema.enums) {
parts.push(this.generateEnumSource(enumDef));
parts.push("");
allExports.push(enumDef.name);
}
for (const type of resolvedTypes) {
parts.push(this.generateClassSource(type));
parts.push("");
allExports.push(type.className);
}
return {
fileName,
content: parts.join("\n"),
exports: allExports
};
}
// ── Source generation ──
generateEnumSource(enumDef) {
switch (this.enumStyle) {
case "enum":
return this.generateEnumAsEnum(enumDef);
case "const-object":
return this.generateEnumAsConstObject(enumDef);
case "union":
default:
return this.generateEnumAsUnion(enumDef);
}
}
generateEnumAsUnion(enumDef) {
const values = enumDef.values.map((v) => `"${v}"`).join(" | ");
return `export type ${enumDef.name} = ${values};`;
}
generateEnumAsEnum(enumDef) {
const members = enumDef.values.map((v) => {
const key = toEnumKey(v);
return ` ${key} = "${v}",`;
}).join("\n");
return `export enum ${enumDef.name} {
${members}
}`;
}
generateEnumAsConstObject(enumDef) {
const members = enumDef.values.map((v) => {
const key = toEnumKey(v);
return ` ${key}: "${v}",`;
}).join("\n");
const constDecl = `export const ${enumDef.name} = {
${members}
} as const;`;
const typeDecl = `export type ${enumDef.name} = (typeof ${enumDef.name})[keyof typeof ${enumDef.name}];`;
return `${constDecl}
${typeDecl}`;
}
generateClassSource(type) {
const lines = [];
lines.push(mapClassDecorator(type));
const extendsClause = type.baseTypeName ? ` extends ${type.baseTypeName}` : "";
lines.push(`export class ${type.className}${extendsClause} {`);
for (const prop of type.properties) {
const decorator = mapPropertyDecorator(prop);
const isOptional = prop.required !== true;
const initializer = isOptional ? void 0 : prop.initializer;
lines.push(` ${decorator}`);
lines.push(` ${buildProperty(prop.propertyName, prop.tsType, initializer, isOptional)}`);
lines.push("");
}
if (lines[lines.length - 1] === "") {
lines.pop();
}
lines.push("}");
return lines.join("\n");
}
// ── Helpers ──
collectLocalImports(type, allTypes, allEnums) {
const imports = /* @__PURE__ */ new Map();
const typeNames = new Set(allTypes.map((t) => t.className));
const enumNames = new Set(allEnums.map((e) => e.name));
if (type.baseTypeName && typeNames.has(type.baseTypeName)) {
imports.set(type.baseTypeName, `${toKebabCase(type.baseTypeName)}.ts`);
}
for (const prop of type.properties) {
if (prop.complexTypeName && typeNames.has(prop.complexTypeName)) {
imports.set(prop.complexTypeName, `${toKebabCase(prop.complexTypeName)}.ts`);
}
if (prop.arrayItemType && typeNames.has(prop.arrayItemType)) {
imports.set(prop.arrayItemType, `${toKebabCase(prop.arrayItemType)}.ts`);
}
if (prop.enumTypeName && enumNames.has(prop.enumTypeName)) {
imports.set(prop.enumTypeName, `${toKebabCase(prop.enumTypeName)}.ts`);
}
}
imports.delete(type.className);
return imports;
}
applyRootElements(types, rootElements) {
if (!this.useXmlRoot) {
return types.map(
(type) => type.isRootElement ? { ...type, isRootElement: false, form: this.elementFormDefault } : type
);
}
if (rootElements.length === 0) {
return types;
}
const rootMap = /* @__PURE__ */ new Map();
for (const root of rootElements) {
const entries = rootMap.get(root.typeName);
if (entries) {
entries.push(root);
} else {
rootMap.set(root.typeName, [root]);
}
}
return types.map((type) => {
if (type.isRootElement) {
return type;
}
const roots = rootMap.get(type.className);
if (!roots || roots.length === 0) {
return type;
}
const root = roots[0];
return {
...type,
isRootElement: true,
xmlName: root.name,
rootNillable: root.nillable
};
});
}
};
function toEnumKey(value) {
let key = value.replace(/[^a-zA-Z0-9_]/g, "_");
if (/^[0-9]/.test(key)) {
key = `_${key}`;
}
const hadLeadingUnderscore = key.startsWith("_");
let result = key.split("_").filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
if (hadLeadingUnderscore && !result.startsWith("_")) {
result = `_${result}`;
}
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = result.replace(/^[^A-Za-z_]+/, "");
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = `_${result}`;
}
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = "_Value";
}
}
return result;
}
// src/generator/file-writer.ts
import fs2 from "fs";
import path2 from "path";
function writeGeneratedFiles(outputDir, files) {
const written = [];
fs2.mkdirSync(outputDir, { recursive: true });
for (const file of files) {
const filePath = path2.join(outputDir, file.fileName);
fs2.writeFileSync(filePath, file.content, "utf-8");
written.push(filePath);
}
return { written };
}
function writeGeneratedFile(outputFilePath, file) {
const parentDir = path2.dirname(outputFilePath);
fs2.mkdirSync(parentDir, { recursive: true });
fs2.writeFileSync(outputFilePath, file.content, "utf-8");
return outputFilePath;
}
// src/xsd/xsd-parser.ts
import fs3 from "fs";
import path3 from "path";
import { XmlDecoratorParser } from "@cerios/xml-poto";
var XSD_NS = "http://www.w3.org/2001/XMLSchema";
var XsdParser = class {
constructor() {
this.parser = new XmlDecoratorParser({
trimValues: false,
parseTagValue: false
});
/** Detected XSD prefix in the current schema (e.g. 'xs', 'xsd', or '') */
this.xsdPrefix = "xs";
}
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath) {
const absolutePath = path3.resolve(xsdPath);
const content = fs3.readFileSync(absolutePath, "utf-8");
return this.parseString(content, path3.dirname(absolutePath));
}
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent, baseDir) {
const normalized = xsdContent.replace(/<\?xml[^?]*\?>/i, "").replace(/<!--[\s\S]*?-->/g, "").trim();
if (!/^<(?:[a-zA-Z_][\w.-]*:)?schema[\s/>]/i.test(normalized)) {
throw new Error(
"The provided content does not appear to be a valid XSD schema. Expected a root <xs:schema>, <xsd:schema>, or <schema> element."
);
}
const parsed = this.parser.parse(normalized);
const rootKey = this.findSchemaRootKey(parsed);
if (!rootKey) {
throw new Error("No XSD schema root element found. Expected <xs:schema>, <xsd:schema>, or <schema>.");
}
const schemaObj = parsed[rootKey];
this.detectXsdPrefix(schemaObj);
const schema = this.parseSchema(schemaObj);
if (baseDir) {
this.resolveExternalSchemas(schema, baseDir);
}
return schema;
}
resolveExternalSchemas(schema, baseDir) {
for (const inc of schema.includes) {
if (inc.schemaLocation) {
const incPath = path3.resolve(baseDir, inc.schemaLocation);
if (fs3.existsSync(incPath)) {
this.mergeSchema(schema, this.parseFile(incPath));
}
}
}
for (const imp of schema.imports) {
if (imp.schemaLocation) {
const impPath = path3.resolve(baseDir, imp.schemaLocation);
if (fs3.existsSync(impPath)) {
const imported = this.parseFile(impPath);
this.mergeSchema(schema, imported);
if (imp.namespace && imported.targetNamespace) {
for (const [prefix, uri] of imported.namespaces) {
if (uri === imported.targetNamespace && prefix !== "" && !schema.namespaces.has(prefix)) {
schema.namespaces.set(prefix, uri);
}
}
}
}
}
}
}
findSchemaRootKey(parsed) {
return Object.keys(parsed).find(
(k) => k === "schema" || k.endsWith(":schema") || k === "xs:schema" || k === "xsd:schema"
);
}
detectXsdPrefix(schemaObj) {
for (const key of Object.keys(schemaObj)) {
if (key.startsWith("@_xmlns:")) {
const prefix = key.substring(8);
const uri = schemaObj[key];
if (uri === XSD_NS) {
this.xsdPrefix = prefix;
return;
}
}
}
if (schemaObj["@_xmlns"] === XSD_NS) {
this.xsdPrefix = "";
return;
}
this.xsdPrefix = "xs";
}
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
xsd(localName) {
return this.xsdPrefix ? `${this.xsdPrefix}:${localName}` : localName;
}
parseSchema(obj) {
const schema = {
targetNamespace: attr(obj, "targetNamespace"),
elementFormDefault: attr(obj, "elementFormDefault"),
attributeFormDefault: attr(obj, "attributeFormDefault"),
namespaces: this.extractNamespaces(obj),
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
complexTypes: this.parseChildren(obj, this.xsd("complexType")).map((e) => this.parseComplexType(e)),
simpleTypes: this.parseChildren(obj, this.xsd("simpleType")).map((e) => this.parseSimpleType(e)),
groups: this.parseChildren(obj, this.xsd("group")).map((e) => this.parseGroup(e)),
attributeGroups: this.parseChildren(obj, this.xsd("attributeGroup")).map((e) => this.parseAttributeGroup(e)),
imports: this.parseChildren(obj, this.xsd("import")).map((e) => this.parseImport(e)),
includes: this.parseChildren(obj, this.xsd("include")).map((e) => this.parseInclude(e))
};
return schema;
}
extractNamespaces(obj) {
const ns = /* @__PURE__ */ new Map();
for (const key of Object.keys(obj)) {
if (key === "@_xmlns") {
ns.set("", obj[key]);
} else if (key.startsWith("@_xmlns:")) {
ns.set(key.substring(8), obj[key]);
}
}
return ns;
}
// ── Element parsing ──
parseElement(obj) {
var _a;
const el = {
name: (_a = attr(obj, "name")) != null ? _a : "",
type: attr(obj, "type"),
ref: attr(obj, "ref"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs"),
nillable: attr(obj, "nillable") === "true" || void 0,
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
substitutionGroup: attr(obj, "substitutionGroup")
};
const ct = this.getChild(obj, this.xsd("complexType"));
if (ct) {
el.complexType = this.parseComplexType(ct);
}
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) {
el.simpleType = this.parseSimpleType(st);
}
return el;
}
// ── Complex Type parsing ──
parseComplexType(obj) {
const ct = {
name: attr(obj, "name"),
mixed: attr(obj, "mixed") === "true" || void 0,
abstract: attr(obj, "abstract") === "true" || void 0,
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj),
anyAttribute: this.getChild(obj, this.xsd("anyAttribute")) !== void 0 || void 0
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ct.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ct.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ct.all = this.parseAll(all);
const sc = this.getChild(obj, this.xsd("simpleContent"));
if (sc) ct.simpleContent = this.parseSimpleContent(sc);
const cc = this.getChild(obj, this.xsd("complexContent"));
if (cc) ct.complexContent = this.parseComplexContent(cc);
return ct;
}
// ── Simple Type parsing ──
parseSimpleType(obj) {
var _a;
const st = {
name: attr(obj, "name")
};
const restriction = this.getChild(obj, this.xsd("restriction"));
if (restriction) {
st.restriction = this.parseRestriction(restriction);
}
const list = this.getChild(obj, this.xsd("list"));
if (list) {
st.list = { itemType: (_a = attr(list, "itemType")) != null ? _a : "" };
}
const union = this.getChild(obj, this.xsd("union"));
if (union) {
const memberTypes = attr(union, "memberTypes");
st.union = {
memberTypes: memberTypes ? memberTypes.split(/\s+/) : []
};
}
return st;
}
parseRestriction(obj) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
return {
base: (_a = attr(obj, "base")) != null ? _a : "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => {
var _a2;
return (_a2 = attr(e, "value")) != null ? _a2 : "";
}),
pattern: attr((_b = this.getChild(obj, this.xsd("pattern"))) != null ? _b : {}, "value"),
minLength: numAttr((_c = this.getChild(obj, this.xsd("minLength"))) != null ? _c : {}, "value"),
maxLength: numAttr((_d = this.getChild(obj, this.xsd("maxLength"))) != null ? _d : {}, "value"),
minInclusive: numAttr((_e = this.getChild(obj, this.xsd("minInclusive"))) != null ? _e : {}, "value"),
maxInclusive: numAttr((_f = this.getChild(obj, this.xsd("maxInclusive"))) != null ? _f : {}, "value"),
minExclusive: numAttr((_g = this.getChild(obj, this.xsd("minExclusive"))) != null ? _g : {}, "value"),
maxExclusive: numAttr((_h = this.getChild(obj, this.xsd("maxExclusive"))) != null ? _h : {}, "value"),
totalDigits: numAttr((_i = this.getChild(obj, this.xsd("totalDigits"))) != null ? _i : {}, "value"),
fractionDigits: numAttr((_j = this.getChild(obj, this.xsd("fractionDigits"))) != null ? _j : {}, "value"),
whiteSpace: attr((_k = this.getChild(obj, this.xsd("whiteSpace"))) != null ? _k : {}, "value")
};
}
// ── Attribute parsing ──
parseAttribute(obj) {
var _a;
const a = {
name: (_a = attr(obj, "name")) != null ? _a : "",
type: attr(obj, "type"),
use: attr(obj, "use"),
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
ref: attr(obj, "ref")
};
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) {
a.simpleType = this.parseSimpleType(st);
}
return a;
}
// ── Compositor parsing ──
parseSequence(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
choices: this.parseChildren(obj, this.xsd("choice")).map((c) => this.parseChoice(c)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
any: this.parseChildren(obj, this.xsd("any")).map((a) => this.parseAny(a))
};
}
parseChoice(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
parseAll(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e))
};
}
parseAny(obj) {
return {
namespace: attr(obj, "namespace"),
processContents: attr(obj, "processContents"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
// ── Content model parsing ──
parseSimpleContent(obj) {
const sc = {};
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) {
sc.extension = this.parseSimpleContentExtension(ext);
}
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) {
sc.restriction = this.parseSimpleContentRestriction(rest);
}
return sc;
}
parseSimpleContentExtension(obj) {
var _a;
return {
base: (_a = attr(obj, "base")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseSimpleContentRestriction(obj) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
return {
base: (_a = attr(obj, "base")) != null ? _a : "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => {
var _a2;
return (_a2 = attr(e, "value")) != null ? _a2 : "";
}),
pattern: attr((_b = this.getChild(obj, this.xsd("pattern"))) != null ? _b : {}, "value"),
minLength: numAttr((_c = this.getChild(obj, this.xsd("minLength"))) != null ? _c : {}, "value"),
maxLength: numAttr((_d = this.getChild(obj, this.xsd("maxLength"))) != null ? _d : {}, "value"),
minInclusive: numAttr((_e = this.getChild(obj, this.xsd("minInclusive"))) != null ? _e : {}, "value"),
maxInclusive: numAttr((_f = this.getChild(obj, this.xsd("maxInclusive"))) != null ? _f : {}, "value"),
minExclusive: numAttr((_g = this.getChild(obj, this.xsd("minExclusive"))) != null ? _g : {}, "value"),
maxExclusive: numAttr((_h = this.getChild(obj, this.xsd("maxExclusive"))) != null ? _h : {}, "value"),
totalDigits: numAttr((_i = this.getChild(obj, this.xsd("totalDigits"))) != null ? _i : {}, "value"),
fractionDigits: numAttr((_j = this.getChild(obj, this.xsd("fractionDigits"))) != null ? _j : {}, "value"),
whiteSpace: attr((_k = this.getChild(obj, this.xsd("whiteSpace"))) != null ? _k : {}, "value"),
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseComplexContent(obj) {
const cc = {
mixed: attr(obj, "mixed") === "true" || void 0
};
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) {
cc.extension = this.parseComplexContentExtension(ext);
}
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) {
cc.restriction = this.parseComplexContentRestriction(rest);
}
return cc;
}
parseComplexContentExtension(obj) {
var _a;
const ext = {
base: (_a = attr(obj, "base")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ext.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ext.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ext.all = this.parseAll(all);
return ext;
}
parseComplexContentRestriction(obj) {
var _a;
const rest = {
base: (_a = attr(obj, "base")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) rest.sequence = this.parseSequence(seq);
return rest;
}
// ── Group parsing ──
parseGroup(obj) {
var _a;
const g = {
name: (_a = attr(obj, "name")) != null ? _a : ""
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) g.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) g.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) g.all = this.parseAll(all);
return g;
}
parseGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("group")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({
ref: attr(g, "ref"),
minOccurs: numAttr(g, "minOccurs"),
maxOccurs: occursAttr(g, "maxOccurs")
}));
}
parseAttributeGroup(obj) {
var _a;
return {
name: (_a = attr(obj, "name")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
}
parseAttributeGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("attributeGroup")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({ ref: attr(g, "ref") }));
}
// ── Import/Include ──
parseImport(obj) {
return {
namespace: attr(obj, "namespace"),
schemaLocation: attr(obj, "schemaLocation")
};
}
parseInclude(obj) {
var _a;
return {
schemaLocation: (_a = attr(obj, "schemaLocation")) != null ? _a : ""
};
}
// ── Schema merging (for includes) ──
mergeSchema(target, source) {
target.elements.push(...source.elements);
target.complexTypes.push(...source.complexTypes);
target.simpleTypes.push(...source.simpleTypes);
target.groups.push(...source.groups);
target.attributeGroups.push(...source.attributeGroups);
}
// ── Utility: child access in parsed XML object ──
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
getChild(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return void 0;
if (Array.isArray(child)) return child[0];
if (typeof child === "object") return child;
return void 0;
}
/**
* Get all children with a given tag name as an array.
*/
parseChildren(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return [];
if (Array.isArray(child))
return child.map((c) => typeof c === "object" && c !== null ? c : {});
if (typeof child === "object") return [child];
return [];
}
};
function attr(obj, name) {
const val = obj[`@_${name}`];
if (val === void 0 || val === null) return void 0;
if (typeof val === "string") return val;
if (typeof val === "number" || typeof val === "boolean" || typeof val === "bigint" || typeof val === "symbol") {
return String(val);
}
return void 0;
}
function numAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
function occursAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
if (val === "unbounded") return "unbounded";
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
// src/xsd/xsd-resolver.ts
var XSD_TYPE_MAP = {
string: { tsType: "string", initializer: "''" },
normalizedString: { tsType: "string", initializer: "''" },
token: { tsType: "string", initializer: "''" },
language: { tsType: "string", initializer: "''" },
Name: { tsType: "string", initializer: "''" },
NCName: { tsType: "string", initializer: "''" },
NMTOKEN: { tsType: "string", initializer: "''" },
ID: { tsType: "string", initializer: "''" },
IDREF: { tsType: "string", initializer: "''" },
anyURI: { tsType: "string", initializer: "''" },
QName: { tsType: "string", initializer: "''" },
integer: { tsType: "number", initializer: "0" },
int: { tsType: "number", initializer: "0" },
long: { tsType: "number", initializer: "0" },
short: { tsType: "number", initializer: "0" },
byte: { tsType: "number", initializer: "0" },
nonNegativeInteger: { tsType: "number", initializer: "0" },
nonPositiveInteger: { tsType: "number", initializer: "0" },
positiveInteger: { tsType: "number", initializer: "0" },
negativeInteger: { tsType: "number", initializer: "0" },
unsignedInt: { tsType: "number", initializer: "0" },
unsignedLong: { tsType: "number", initializer: "0" },
unsignedShort: { tsType: "number", initializer: "0" },
unsignedByte: { tsType: "number", initializer: "0" },
decimal: { tsType: "number", initializer: "0" },
float: { tsType: "number", initializer: "0" },
double: { tsType: "number", initializer: "0" },
boolean: { tsType: "boolean", initializer: "false" },
dateTime: {
tsType: "string",
initializer: "''",
dataType: "xs:dateTime"
},
date: { tsType: "string", initializer: "''", dataType: "xs:date" },
time: { tsType: "string", initializer: "''", dataType: "xs:time" },
duration: { tsType: "string", initializer: "''" },
gYear: { tsType: "string", initializer: "''" },
gMonth: { tsType: "string", initializer: "''" },
gDay: { tsType: "string", initializer: "''" },
gYearMonth: { tsType: "string", initializer: "''" },
gMonthDay: { tsType: "string", initializer: "''" },
base64Binary: { tsType: "string", initializer: "''" },
hexBinary: { tsType: "string", initializer: "''" },
anyType: { tsType: "unknown", initializer: "undefined" },
anySimpleType: { tsType: "string", initializer: "''" }
};
var XsdResolver = class {
constructor() {
this.complexTypeMap = /* @__PURE__ */ new Map();
this.simpleTypeMap = /* @__PURE__ */ new Map();
this.groupMap = /* @__PURE__ */ new Map();
this.attributeGroupMap = /* @__PURE__ */ new Map();
this.resolvedTypeMap = /* @__PURE__ */ new Map();
/** Maps head element name → list of substitute element names */
this.substitutionMap = /* @__PURE__ */ new Map();
}
resolve(schema) {
this.schema = schema;
this.buildLookups();
this.resolvedTypeMap.clear();
const resolved = {
targetNamespace: schema.targetNamespace,
elementFormDefault: schema.elementFormDefault,
namespaces: schema.namespaces,
types: [],
enums: [],
rootElements: []
};
for (const st of schema.simpleTypes) {
if (st.name && st.restriction && st.restriction.enumerations.length > 0) {
resolved.enums.push({
name: toPascalCase(st.name),
xmlName: st.name,
values: st.restriction.enumerations,
baseType: stripPrefix(st.restriction.base)
});
}
}
for (const ct of schema.complexTypes) {
if (ct.name) {
this.addResolvedType(this.resolveComplexType(ct, ct.name, false));
}
}
for (const el of schema.elements) {
if (el.complexType) {
this.addResolvedType(this.resolveComplexType(el.complexType, el.name, true));
} else if (el.type) {
const localType = stripPrefix(el.type);
if (this.complexTypeMap.has(localType)) {
resolved.rootElements.push({
name: el.name,
typeName: toPascalCase(localType),
nillable: el.nillable
});
} else {
this.addResolvedType(this.resolveSimpleRootElement(el));
}
} else if (el.simpleType) {
this.addResolvedType(this.resolveSimpleRootElement(el));
}
}
resolved.types = [...this.resolvedTypeMap.values()];
return resolved;
}
addResolvedType(type) {
if (!this.resolvedTypeMap.has(type.className)) {
this.resolvedTypeMap.set(type.className, type);
}
}
buildLookups() {
this.complexTypeMap.clear();
this.simpleTypeMap.clear();
this.groupMap.clear();
this.attributeGroupMap.clear();
this.substitutionMap.clear();
this.buildTypeLookups();
this.buildGroupLookups();
this.buildAttributeGroupLookups();
this.buildSubstitutionLookups();
}
buildTypeLookups() {
for (const ct of this.schema.complexTypes) {
if (ct.name) this.complexTypeMap.set(ct.name, ct);
}
for (const st of this.schema.simpleTypes) {
if (st.name) this.simpleTypeMap.set(st.name, st);
}
}
buildGroupLookups() {
var _a, _b;
for (const g of this.schema.groups) {
if (g.name) {
const compositor = (_b = (_a = g.sequence) != null ? _a : g.choice) != null ? _b : g.all;
if (compositor) this.groupMap.set(g.name, compositor);
}
}
}
buildAttributeGroupLookups() {
const groupDefs = /* @__PURE__ */ new Map();
for (const ag of this.schema.attributeGroups) {
if (ag.name) {
groupDefs.set(ag.name, ag);
}
}
const resolving = /* @__PURE__ */ new Set();
const resolveGroup = (name) => {
const cached = this.attributeGroupMap.get(name);
if (cached) return cached;
const def = groupDefs.get(name);
if (!def) {
return [];
}
if (resolving.has(name)) {
return [];
}
resolving.add(name);
const attrs = [...def.attributes];
for (const ref of def.attributeGroupRefs) {
const refName = stripPrefix(ref.ref);
const resolvedAttrs = resolveGroup(refName);
if (resolvedAttrs.length) {
attrs.push(...resolvedAttrs);
}
}
resolving.delete(name);
this.attributeGroupMap.set(name, attrs);
return attrs;
};
for (const name of groupDefs.keys()) {
resolveGroup(name);
}
}
buildSubstitutionLookups() {
for (const el of this.schema.elements) {
if (el.substitutionGroup) {
const headName = stripPrefix(el.substitutionGroup);
const substitutes = this.substitutionMap.get(headName);
if (substitutes) {
substitutes.push(el.name);
} else {
this.substitutionMap.set(headName, [el.name]);
}
}
}
}
resolveComplexType(ct, name, isRoot, classNameOverride) {
const resolved = {
className: classNameOverride != null ? classNameOverride : toPascalCase(name),
xmlName: name,
properties: [],
isRootElement: isRoot,
mixed: ct.mixed,
abstract: ct.abstract
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix != null ? prefix : void 0
};
}
if (ct.simpleContent) {
resolved.hasSimpleContent = true;
this.resolveSimpleContent(ct.simpleContent, resolved);
return resolved;
}
if (ct.complexContent) {
this.resolveComplexContent(ct.complexContent, resolved);
}
let order = 1;
if (ct.sequence) {
order = this.resolveSequenceProperties(ct.sequence, resolved.properties, order);
}
if (ct.choice) {
order = this.resolveChoiceProperties(ct.choice, resolved.properties, order);
}
if (ct.all) {
this.resolveAllProperties(ct.all, resolved.properties);
}
for (const gRef of ct.groupRefs) {
order = this.resolveGroupRef(gRef, resolved.properties, order);
}
this.resolveAttributes(ct.attributes, resolved.properties);
for (const agRef of ct.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
if (ct.anyAttribute) {
resolved.properties.push({
propertyName: "anyAttributes",
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!"
});
}
return resolved;
}
resolveSimpleContent(sc, resolved) {
if (sc.extension) {
const baseInfo = this.resolveTypeReference(sc.extension.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.extension.attributes, resolved.properties);
} else if (sc.restriction) {
const baseInfo = this.resolveTypeReference(sc.restriction.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
enumValues: sc.restriction.enumerations.length > 0 ? sc.restriction.enumerations : void 0,
pattern: sc.restriction.pattern,
minLength: sc.restriction.minLength,
maxLength: sc.restriction.maxLength,
minInclusive: sc.restriction.minInclusive,
maxInclusive: sc.restriction.maxInclusive,
minExclusive: sc.restriction.minExclusive,
maxExclusive: sc.restriction.maxExclusive,
totalDigits: sc.restriction.totalDigits,
fractionDigits: sc.restriction.fractionDigits,
whiteSpace: sc.restriction.whiteSpace,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.restriction.attributes, resolved.properties);
}
}
resolveComplexContent(cc, resolved) {
if (cc.extension) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.extension.base));
let order = 1;
if (cc.extension.sequence) {
order = this.resolveSequenceProperties(cc.extension.sequence, resolved.properties, order);
}
if (cc.extension.choice) {
order = this.resolveChoiceProperties(cc.extension.choice, resolved.properties, order);
}
if (cc.extension.all) {
this.resolveAllProperties(cc.extension.all, resolved.properties);
}
for (const gRef of cc.extension.groupRefs) {
order = this.resolveGroupRef(gRef, resolved.properties, order);
}
this.resolveAttributes(cc.extension.attributes, resolved.properties);
for (const agRef of cc.extension.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
} else if (cc.restriction) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.restriction.base));
if (cc.restriction.sequence) {
this.resolveSequenceProperties(cc.restriction.sequence, resolved.properties, 1);
}
this.resolveAttributes(cc.restriction.attributes, resolved.properties);
}
}
resolveSequenceProperties(seq, props, startOrder) {
let order = startOrder;
for (const el of seq.elements) {
props.push(this.resolveElementProperty(el, order++));
}
for (const choice of seq.choices) {
order = this.resolveChoiceProperties(choice, props, order);
}
for (const nested of seq.sequences) {
order = this.resolveSequenceProperties(nested, props, order);
}
for (const gRef of seq.groupRefs) {
order = this.resolveGroupRef(gRef, props, order);
}
for (const any of seq.any) {
props.push({
propertyName: `dynamicContent${order}`,
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
order: order++
});
if (any.minOccurs === void 0 || any.minOccurs > 0) {
props[props.length - 1].required = true;
}
}
return order;
}
resolveChoiceProperties(choice, props, startOrder) {
let order = startOrder;
for (const el of choice.elements) {
const prop = this.resolveElementProperty(el, order++);
prop.required = false;
props.push(prop);
}
for (const seq of choice.sequences) {
order = this.resolveSequenceProperties(seq, props, order);
}
for (const gRef of choice.groupRefs) {
order = this.resolveGroupRef(gRef, props, order);
}
return order;
}
resolveAllProperties(all, props) {
for (const el of all.elements) {
props.push(this.resolveElementProperty(el));
}
}
resolveGroupRef(gRef, props, startOrder) {
const refName = stripPrefix(gRef.ref);
const compositor = this.groupMap.get(refName);
if (!compositor) return startOrder;
if ("elements" in compositor && "choices" in compositor) {
return this.resolveSequenceProperties(compositor, props, startOrder);
}
if ("elements" in compositor && !("choices" in compositor)) {
if ("sequences" in compositor) {
return this.resolveChoiceProperties(compositor, props, startOrder);
}
this.resolveAllProperties(compositor, props);
}
return startOrder;
}
resolveElementProperty(el, order) {
var _a, _b;
const isArray = el.maxOccurs === "unbounded" || typeof el.maxOccurs === "number" && el.maxOccurs > 1;
const isRequired = el.minOccurs === void 0 || el.minOccurs > 0;
const form = (_a = el.form) != null ? _a : this.resolveElementForm();
const name = el.ref ? stripPrefix(el.ref) : el.name;
if (this.substitutionMap.has(name)) {
return {
propertyName: toCamelCase(name),
xmlName: name,
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
required: isRequired,
order
};
}
let typeInfo;
if (el.complexType) {
const inlineTypeName = toPascalCase(name) + "Type";
this.addResolvedType(this.resolveComplexType(el.complexType, name, false, inlineTypeName));
typeInfo = {
tsType: inlineTypeName,
initializer: `new ${inlineTypeName}()`,
complexTypeName: inlineTypeName
};
} else if (el.simpleType) {
typeInfo = this.resolveSimpleTypeInline(el.simpleType);
} else if (el.type) {
typeInfo = this.resolveTypeReference(el.type);
} else {
typeInfo = { tsType: "string", initializer: "''" };
}
const prop = {
propertyName: toCamelCase(name),
xmlName: name,
kind: isArray ? "array" : "element",
tsType: isArray ? `${typeInfo.tsType}[]` : typeInfo.tsType,
initializer: isArray ? "[]" : typeInfo.initializer,
required: isRequired,
order,
isNullable: el.nillable,
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: (_b = el.defaultValue) != null ? _b : el.fixed,
fixedValue: el.fixed,
complexTypeName: typeInfo.complexTypeName,
enumValues: typeInfo.enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
};
if (isArray) {
prop.arrayItemName = name;
prop.arrayItemType = typeInfo.complexTypeName;
}
return prop;
}
resolveAttributes(attrs, props) {
var _a, _b, _c, _d;
for (const a of attrs) {
if (a.ref) {
const form2 = (_a = a.form) != null ? _a : this.resolveAttributeForm();
const defaultOrFixed2 = (_b = a.defaultValue) != null ? _b : a.fixed;
props.push({
propertyName: toCamelCase(stripPrefix(a.ref)),
xmlName: stripPrefix(a.ref),
kind: "attribute",
tsType: "string",
initializer: defaultOrFixed2 ? `'${escapeString2(defaultOrFixed2)}'` : "''",
required: a.use === "required",
form: form2,
namespace: this.resolveNamespaceForForm(form2),
defaultValue: defaultOrFixed2,
fixedValue: a.fixed
});
continue;
}
let typeInfo;
if (a.simpleType) {
typeInfo = this.resolveSimpleTypeInline(a.simpleType);
} else if (a.type) {
typeInfo = this.resolveTypeReference(a.type);
} else {
typeInfo = { tsType: "string", initializer: "''" };
}
const defaultOrFixed = (_c = a.defaultValue) != null ? _c : a.fixed;
const initializer = defaultOrFixed ? this.buildDefaultInitializer(typeInfo.tsType, defaultOrFixed) : typeInfo.initializer;
const form = (_d = a.form) != null ? _d : this.resolveAttributeForm();
const enumValues = typeInfo.enumValues ? [...typeInfo.enumValues] : a.fixed ? [a.fixed] : void 0;
props.push({
propertyName: toCamelCase(a.name),
xmlName: a.name,
kind: "attribute",
tsType: typeInfo.tsType,
initializer,
required: a.use === "required",
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: defaultOrFixed,
fixedValue: a.fixed,
enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
});
}
}
resolveTypeReference(typeRef) {
const localName = stripPrefix(typeRef);
const builtin = XSD_TYPE_MAP[localName];
if (builtin) return { ...builtin };
if (this.complexTypeMap.has(localName)) {
const className = toPascalCase(localName);
return {
tsType: className,
initializer: `new ${className}()`,
complexTypeName: className
};
}
const st = this.simpleTypeMap.get(localName);
if (st) {
return this.resolveSimpleTypeInline(st);
}
return { tsType: "string", initializer: "''" };
}
resolveSimpleTypeInline(st) {
if (st.restriction) {
const baseInfo = this.resolveTypeReference(st.restriction.base);
const result = {
...baseInfo
};
if (st.restriction.enumerations.length > 0) {
if (st.name) {
result.enumTypeName = toPascalCase(st.name);
result.tsType = toPascalCase(st.name);
} else {
result.enumValues = st.restriction.enumerations;
}
}
if (st.restriction.pattern) {
result.pattern = st.restriction.pattern;
}
result.minLength = st.restriction.minLength;
result.maxLength = st.restriction.maxLength;
result.minInclusive = st.restriction.minInclusive;
result.maxInclusive = st.restriction.maxInclusive;
result.minExclusive = st.restriction.minExclusive;
result.maxExclusive = st.restriction.maxExclusive;
result.totalDigits = st.restriction.totalDigits;
result.fractionDigits = st.restriction.fractionDigits;
result.whiteSpace = st.restriction.whiteSpace;
return result;
}
if (st.list) {
const itemInfo = this.resolveTypeReference(st.list.itemType);
return {
tsType: `${itemInfo.tsType}[]`,
initializer: "[]"
};
}
if (st.union) {
if (st.union.memberTypes.length > 0) {
const memberInfos = st.union.memberTypes.map((mt) => this.resolveTypeReference(mt));
const uniqueTypes = [...new Set(memberInfos.map((m) => m.tsType))];
const tsType = uniqueTypes.join(" | ");
return { tsType, initializer: memberInfos[0].initializer };
}
return { tsType: "string", initializer: "''" };
}
return { tsType: "string", initializer: "''" };
}
resolveSimpleRootElement(el) {
const typeInfo = el.simpleType ? this.resolveSimpleTypeInline(el.simpleType) : el.type ? this.resolveTypeReference(el.type) : { tsType: "string", initializer: "''" };
const resolved = {
className: toPascalCase(el.name),
xmlName: el.name,
properties: [
{
propertyName: "value",
xmlName: "",
kind: "text",
tsType: typeInfo.tsType,
initializer: typeInfo.initializer,
dataType: typeInfo.dataType
}
],
isRootElement: true
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix != null ? prefix : void 0
};
}
return resolved;
}
resolveElementForm() {
return this.schema.elementFormDefault;
}
resolveAttributeForm() {
return this.schema.attributeFormDefault;
}
resolveNamespaceForForm(form) {
if (form !== "qualified" || !this.schema.targetNamespace) {
return void 0;
}
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
return {
uri: this.schema.targetNamespace,
prefix: prefix != null ? prefix : void 0
};
}
findPrefixForUri(uri) {
for (const [prefix, nsUri] of this.schema.namespaces) {
if (nsUri === uri && prefix !== "") return prefix;
}
return void 0;
}
buildDefaultInitializer(tsType, defaultValue) {
if (tsType === "number") return defaultValue;
if (tsType === "boolean") return defaultValue === "true" ? "true" : "false";
return `'${escapeString2(defaultValue)}'`;
}
};
function stripPrefix(name) {
const idx = name.indexOf(":");
return idx >= 0 ? name.substring(idx + 1) : name;
}
function toPascalCase(name) {
const converted = name.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase()).replace(/^[a-z]/, (c) => c.toUpperCase());
return sanitizeIdentifier(converted, true);
}
function toCamelCase(name) {
const pascal = toPascalCase(name);
return sanitizeIdentifier(pascal.charAt(0).toLowerCase() + pascal.slice(1), false);
}
function sanitizeIdentifier(value, pascal) {
const normalized = value.replace(/[^a-zA-Z0-9_$]/g, "");
const nonEmpty = normalized.length > 0 ? normalized : pascal ? "GeneratedType" : "generatedField";
const withLeading = /^[A-Za-z_$]/.test(nonEmpty) ? nonEmpty : `_${nonEmpty}`;
if (RESERVED_TS_IDENTIFIERS.has(withLeading)) {
return `${withLeading}_`;
}
return withLeading;
}
var RESERVED_TS_IDENTIFIERS = /* @__PURE__ */ new Set([
"abstract",
"any",
"as",
"asserts",
"async",
"await",
"boolean",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"declare",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"from",
"function",
"get",
"if",
"implements",
"import",
"in",
"infer",
"instanceof",
"interface",
"is",
"keyof",
"let",
"module",
"namespace",
"never",
"new",
"null",
"number",
"object",
"package",
"private",
"protected",
"public",
"readonly",
"require",
"return",
"set",
"static",
"string",
"super",
"switch",
"symbol",
"this",
"throw",
"true",
"try",
"type",
"typeof",
"undefined",
"unique",
"unknown",
"var",
"void",
"while",
"with",
"yield"
]);
function escapeString2(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
export {
ClassGenerator,
XsdParser,
XsdResolver,
buildDecorator,
buildFileHeader,
buildImport,
buildProperty,
collectImports,
findConfigFile,
loadConfig,
mapClassDecorator,
mapPropertyDecorator,
toCamelCase,
toKebabCase,
toPascalCase,
validateConfig,
writeGeneratedFile,
writeGeneratedFiles
};
//# sourceMappingURL=index.mjs.map
{
"name": "@cerios/xml-poto-codegen",
"version": "1.0.0",
"version": "1.0.1",
"description": "Generate TypeScript classes with xml-poto decorators from XSD schemas. CLI tool with config-based multi-XSD support.",

@@ -27,3 +27,3 @@ "keywords": [

"bin": {
"xml-poto-codegen": "dist/cli.js"
"xml-poto-codegen": "dist/cli.cjs"
},

@@ -35,5 +35,5 @@ "files": [

"sideEffects": false,
"main": "./dist/index.js",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"types": "./dist/index.d.cts",
"exports": {

@@ -46,4 +46,4 @@ ".": {

"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}

@@ -54,3 +54,3 @@ },

"scripts": {
"build": "tsup",
"build": "tsdown --config-loader bundle",
"test": "vitest --run",

@@ -63,18 +63,21 @@ "test:coverage": "vitest --coverage",

"dependencies": {
"commander": "^13.1.0",
"commander": "^14.0.3",
"jiti": "^2.6.1"
},
"devDependencies": {
"@cerios/xml-poto": "2.2.0",
"@types/node": "^25.4.0",
"oxfmt": "^0.38.0",
"oxlint": "^1.53.0",
"oxlint-tsgolint": "^0.16.0",
"tsup": "^8.5.1",
"typescript": "^5.9.3",
"@cerios/xml-poto": "2.2.1",
"@types/node": "^25.6.0",
"oxfmt": "^0.46.0",
"oxlint": "^1.61.0",
"oxlint-tsgolint": "^0.22.0",
"tsdown": "^0.21.10",
"typescript": "^6.0.3",
"vitest": "^4.0.18"
},
"peerDependencies": {
"@cerios/xml-poto": "^2.2.0"
"@cerios/xml-poto": "^2.2.1"
},
"engines": {
"node": ">=20.19.0"
}
}
#!/usr/bin/env node

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

/**
* Configuration for a single XSD source to process.
*/
type EnumStyle = "union" | "enum" | "const-object";
interface XsdSource {
/** Path to the XSD file (relative to config file or absolute). */
xsdPath: string;
/**
* Output path for generated TypeScript files.
* - per-type: directory path
* - per-xsd: file path
*/
outputPath: string;
/** Output style: 'per-type' generates one file per class, 'per-xsd' puts all types in one file. */
outputStyle?: "per-type" | "per-xsd";
/** Enum generation style for this source. Overrides the global setting. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Overrides the global setting. */
useXmlRoot?: boolean;
}
/**
* Root configuration for xml-poto-codegen.
*/
interface XmlPotoCodegenConfig {
/** Array of XSD sources to process. */
sources: XsdSource[];
/** Default output style when not specified per source. Defaults to 'per-type'. */
defaultOutputStyle?: "per-type" | "per-xsd";
/** Default enum generation style. Defaults to 'union'. */
enumStyle?: EnumStyle;
/** Whether to emit @XmlRoot for root elements. When false, @XmlElement is used instead. Defaults to true. */
useXmlRoot?: boolean;
}
declare function validateConfig(config: unknown): XmlPotoCodegenConfig;
declare function findConfigFile(cwd: string): string | undefined;
declare function loadConfig(configPath?: string): Promise<{
config: XmlPotoCodegenConfig;
configDir: string;
}>;
interface XsdNamespace {
uri: string;
prefix?: string;
}
interface XsdSchema {
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
attributeFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
elements: XsdElement[];
complexTypes: XsdComplexType[];
simpleTypes: XsdSimpleType[];
groups: XsdGroup[];
attributeGroups: XsdAttributeGroup[];
imports: XsdImport[];
includes: XsdInclude[];
}
interface XsdElement {
name: string;
type?: string;
ref?: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
nillable?: boolean;
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
/** Substitution group head element name */
substitutionGroup?: string;
/** Inline complexType definition */
complexType?: XsdComplexType;
/** Inline simpleType definition */
simpleType?: XsdSimpleType;
}
interface XsdComplexType {
name?: string;
mixed?: boolean;
abstract?: boolean;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
simpleContent?: XsdSimpleContent;
complexContent?: XsdComplexContent;
/** Group references within this type */
groupRefs: XsdGroupRef[];
/** Attribute group references */
attributeGroupRefs: XsdAttributeGroupRef[];
/** xs:anyAttribute */
anyAttribute?: boolean;
}
interface XsdSimpleType {
name?: string;
restriction?: XsdRestriction;
list?: XsdList;
union?: XsdUnion;
}
interface XsdRestriction {
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
}
interface XsdList {
itemType: string;
}
interface XsdUnion {
memberTypes: string[];
}
interface XsdAttribute {
name: string;
type?: string;
use?: "required" | "optional" | "prohibited";
defaultValue?: string;
fixed?: string;
form?: "qualified" | "unqualified";
ref?: string;
simpleType?: XsdSimpleType;
}
interface XsdSequence {
elements: XsdElement[];
choices: XsdChoice[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
any: XsdAny[];
}
interface XsdChoice {
elements: XsdElement[];
sequences: XsdSequence[];
groupRefs: XsdGroupRef[];
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdAll {
elements: XsdElement[];
}
interface XsdAny {
namespace?: string;
processContents?: "strict" | "lax" | "skip";
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdSimpleContent {
extension?: XsdSimpleContentExtension;
restriction?: XsdSimpleContentRestriction;
}
interface XsdSimpleContentExtension {
base: string;
attributes: XsdAttribute[];
}
interface XsdSimpleContentRestriction {
base: string;
enumerations: string[];
pattern?: string;
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
attributes: XsdAttribute[];
}
interface XsdComplexContent {
extension?: XsdComplexContentExtension;
restriction?: XsdComplexContentRestriction;
mixed?: boolean;
}
interface XsdComplexContentExtension {
base: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
attributes: XsdAttribute[];
groupRefs: XsdGroupRef[];
attributeGroupRefs: XsdAttributeGroupRef[];
}
interface XsdComplexContentRestriction {
base: string;
sequence?: XsdSequence;
attributes: XsdAttribute[];
}
interface XsdGroup {
name: string;
sequence?: XsdSequence;
choice?: XsdChoice;
all?: XsdAll;
}
interface XsdGroupRef {
ref: string;
minOccurs?: number;
maxOccurs?: number | "unbounded";
}
interface XsdAttributeGroup {
name: string;
attributes: XsdAttribute[];
attributeGroupRefs: XsdAttributeGroupRef[];
}
interface XsdAttributeGroupRef {
ref: string;
}
interface XsdImport {
namespace?: string;
schemaLocation?: string;
}
interface XsdInclude {
schemaLocation: string;
}
interface ResolvedSchema {
targetNamespace?: string;
elementFormDefault?: "qualified" | "unqualified";
namespaces: Map<string, string>;
types: ResolvedType[];
enums: ResolvedEnum[];
/** Top-level elements that reference named types (root element candidates) */
rootElements: ResolvedRootElement[];
}
interface ResolvedRootElement {
name: string;
typeName: string;
nillable?: boolean;
}
interface ResolvedType {
/** Class name (PascalCase) */
className: string;
/** Original XML element/type name */
xmlName: string;
/** Properties of this type */
properties: ResolvedProperty[];
/** Base type name if this type extends another */
baseTypeName?: string;
/** Whether this is a root element (gets @XmlRoot instead of @XmlElement) */
isRootElement: boolean;
/** mixed content model */
mixed?: boolean;
/** Namespace info */
namespace?: {
uri: string;
prefix?: string;
};
/** Whether abstract (cannot be instantiated directly) */
abstract?: boolean;
/** Has simpleContent (text value + attributes) */
hasSimpleContent?: boolean;
/** Root-level nillable flag when promoted from top-level element reference */
rootNillable?: boolean;
/** Namespace form (qualified/unqualified) */
form?: "qualified" | "unqualified";
}
type PropertyKind = "element" | "attribute" | "text" | "array" | "dynamic";
interface ResolvedProperty {
/** TypeScript property name (camelCase) */
propertyName: string;
/** Original XML name */
xmlName: string;
/** Kind of decorator to apply */
kind: PropertyKind;
/** TypeScript type string */
tsType: string;
/** Default initializer expression */
initializer: string;
/** Whether required (minOccurs > 0 or use="required") */
required?: boolean;
/** Element order in sequence */
order?: number;
/** Whether nullable (xsi:nil) */
isNullable?: boolean;
/** Form qualification */
form?: "qualified" | "unqualified";
/** Default value from XSD */
defaultValue?: string;
/** For arrays: the item element name */
arrayItemName?: string;
/** For arrays: wrapper container name */
arrayContainerName?: string;
/** For arrays: the item type class name (if complex type) */
arrayItemType?: string;
/** For elements/arrays referencing a complex type: the class name */
complexTypeName?: string;
/** Enum values restriction */
enumValues?: string[];
/** Pattern restriction */
pattern?: string;
/** Referenced enum type name */
enumTypeName?: string;
/** Namespace for this property */
namespace?: {
uri: string;
prefix?: string;
};
/** XSD dataType (e.g. 'xs:dateTime') */
dataType?: string;
/** XSD fixed value constraint */
fixedValue?: string;
/** XSD restriction facets retained for diagnostics/manual post-processing */
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
totalDigits?: number;
fractionDigits?: number;
whiteSpace?: "preserve" | "replace" | "collapse";
}
interface ResolvedEnum {
/** TypeScript enum name (PascalCase) */
name: string;
/** Original XSD type name */
xmlName: string;
/** Enum values */
values: string[];
/** Base restriction type */
baseType: string;
}
/**
* Resolves an XsdSchema into a set of ResolvedTypes and ResolvedEnums,
* ready for code generation.
*/
declare class XsdResolver {
private schema;
private complexTypeMap;
private simpleTypeMap;
private groupMap;
private attributeGroupMap;
private resolvedTypeMap;
/** Maps head element name → list of substitute element names */
private substitutionMap;
resolve(schema: XsdSchema): ResolvedSchema;
private addResolvedType;
private buildLookups;
private buildTypeLookups;
private buildGroupLookups;
private buildAttributeGroupLookups;
private buildSubstitutionLookups;
private resolveComplexType;
private resolveSimpleContent;
private resolveComplexContent;
private resolveSequenceProperties;
private resolveChoiceProperties;
private resolveAllProperties;
private resolveGroupRef;
private resolveElementProperty;
private resolveAttributes;
private resolveTypeReference;
private resolveSimpleTypeInline;
private resolveSimpleRootElement;
private resolveElementForm;
private resolveAttributeForm;
private resolveNamespaceForForm;
private findPrefixForUri;
private buildDefaultInitializer;
}
/** Convert to PascalCase: "my-type_name" → "MyTypeName" */
declare function toPascalCase(name: string): string;
/** Convert to camelCase: "MyTypeName" → "myTypeName" */
declare function toCamelCase(name: string): string;
interface ClassGeneratorOptions {
xsdPath: string;
enumStyle?: EnumStyle;
useXmlRoot?: boolean;
elementFormDefault?: "qualified" | "unqualified";
}
interface GeneratedFile {
/** Filename (without directory) */
fileName: string;
/** Full TypeScript source content */
content: string;
/** Exported class/enum names */
exports: string[];
}
/**
* Generates TypeScript source files from a resolved XSD schema.
*/
declare class ClassGenerator {
private readonly importPath;
private xsdPath;
private enumStyle;
private useXmlRoot;
private elementFormDefault?;
constructor(options: ClassGeneratorOptions);
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema: ResolvedSchema): GeneratedFile[];
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema: ResolvedSchema, fileName?: string): GeneratedFile[];
private generateEnumFile;
private generateClassFile;
private generateBarrelExport;
private generateSingleFile;
private generateEnumSource;
private generateEnumAsUnion;
private generateEnumAsEnum;
private generateEnumAsConstObject;
private generateClassSource;
private collectLocalImports;
private applyRootElements;
}
/**
* Maps resolved XSD types and properties to xml-poto decorator strings.
*/
/** Get the class-level decorator string for a resolved type */
declare function mapClassDecorator(type: ResolvedType): string;
/** Get the property-level decorator string for a resolved property */
declare function mapPropertyDecorator(prop: ResolvedProperty): string;
/** Collect all xml-poto import names needed for a type */
declare function collectImports(type: ResolvedType): Set<string>;
/**
* Writes generated files to the output directory.
*/
declare function writeGeneratedFiles(outputDir: string, files: GeneratedFile[]): {
written: string[];
};
/**
* Writes one generated file to an explicit output file path.
*/
declare function writeGeneratedFile(outputFilePath: string, file: GeneratedFile): string;
/** Build an import statement */
declare function buildImport(names: string[], from: string, isType?: boolean): string;
/** Build a decorator call with options object */
declare function buildDecorator(name: string, options?: Record<string, unknown>): string;
/** Build a class property declaration line */
declare function buildProperty(name: string, type: string, initializer?: string, optional?: boolean): string;
/** Build the auto-generated file header */
declare function buildFileHeader(xsdPath: string): string;
/** Convert a class name to a kebab-case filename */
declare function toKebabCase(name: string): string;
/**
* Parses XSD files into a structured XsdSchema model using @cerios/xml-poto's XML parser.
*/
declare class XsdParser {
private parser;
/** Detected XSD prefix in the current schema (e.g. 'xs', 'xsd', or '') */
private xsdPrefix;
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath: string): XsdSchema;
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent: string, baseDir?: string): XsdSchema;
private resolveExternalSchemas;
private findSchemaRootKey;
private detectXsdPrefix;
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
private xsd;
private parseSchema;
private extractNamespaces;
private parseElement;
private parseComplexType;
private parseSimpleType;
private parseRestriction;
private parseAttribute;
private parseSequence;
private parseChoice;
private parseAll;
private parseAny;
private parseSimpleContent;
private parseSimpleContentExtension;
private parseSimpleContentRestriction;
private parseComplexContent;
private parseComplexContentExtension;
private parseComplexContentRestriction;
private parseGroup;
private parseGroupRefs;
private parseAttributeGroup;
private parseAttributeGroupRefs;
private parseImport;
private parseInclude;
private mergeSchema;
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
private getChild;
/**
* Get all children with a given tag name as an array.
*/
private parseChildren;
}
export { ClassGenerator, type EnumStyle, type GeneratedFile, type ResolvedEnum, type ResolvedProperty, type ResolvedRootElement, type ResolvedSchema, type ResolvedType, type XmlPotoCodegenConfig, type XsdAll, type XsdAny, type XsdAttribute, type XsdAttributeGroup, type XsdAttributeGroupRef, type XsdChoice, type XsdComplexContent, type XsdComplexContentExtension, type XsdComplexContentRestriction, type XsdComplexType, type XsdElement, type XsdGroup, type XsdGroupRef, type XsdImport, type XsdInclude, type XsdNamespace, XsdParser, XsdResolver, type XsdRestriction, type XsdSchema, type XsdSequence, type XsdSimpleContent, type XsdSimpleContentExtension, type XsdSimpleContentRestriction, type XsdSimpleType, type XsdSource, buildDecorator, buildFileHeader, buildImport, buildProperty, collectImports, findConfigFile, loadConfig, mapClassDecorator, mapPropertyDecorator, toCamelCase, toKebabCase, toPascalCase, validateConfig, writeGeneratedFile, writeGeneratedFiles };
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
ClassGenerator: () => ClassGenerator,
XsdParser: () => XsdParser,
XsdResolver: () => XsdResolver,
buildDecorator: () => buildDecorator,
buildFileHeader: () => buildFileHeader,
buildImport: () => buildImport,
buildProperty: () => buildProperty,
collectImports: () => collectImports,
findConfigFile: () => findConfigFile,
loadConfig: () => loadConfig,
mapClassDecorator: () => mapClassDecorator,
mapPropertyDecorator: () => mapPropertyDecorator,
toCamelCase: () => toCamelCase,
toKebabCase: () => toKebabCase,
toPascalCase: () => toPascalCase,
validateConfig: () => validateConfig,
writeGeneratedFile: () => writeGeneratedFile,
writeGeneratedFiles: () => writeGeneratedFiles
});
module.exports = __toCommonJS(index_exports);
// src/config/config-loader.ts
var import_node_fs = __toESM(require("fs"));
var import_node_path = __toESM(require("path"));
var import_jiti = require("jiti");
var CONFIG_NAMES = ["xml-poto-codegen.config.ts", "xml-poto-codegen.config.json"];
function validateConfig(config) {
if (!config || typeof config !== "object") {
throw new Error("Config must be an object.");
}
const cfg = config;
if (!Array.isArray(cfg.sources) || cfg.sources.length === 0) {
throw new Error("Config must have a non-empty 'sources' array.");
}
for (let i = 0; i < cfg.sources.length; i++) {
validateSourceConfig(cfg.sources[i], i);
}
if (!isValidOutputStyle(cfg.defaultOutputStyle)) {
throw new Error("defaultOutputStyle must be 'per-type' or 'per-xsd'.");
}
if (!isValidEnumStyle(cfg.enumStyle)) {
throw new Error("enumStyle must be 'union', 'enum', or 'const-object'.");
}
if (cfg.useXmlRoot !== void 0 && typeof cfg.useXmlRoot !== "boolean") {
throw new Error("useXmlRoot must be a boolean.");
}
return config;
}
function validateSourceConfig(source, index) {
if (!source || typeof source !== "object") {
throw new Error(`sources[${index}] must be an object.`);
}
const src = source;
if (!src.xsdPath || typeof src.xsdPath !== "string") {
throw new Error(`sources[${index}].xsdPath must be a non-empty string.`);
}
if (!src.outputPath || typeof src.outputPath !== "string") {
throw new Error(`sources[${index}].outputPath must be a non-empty string.`);
}
if (!isValidOutputStyle(src.outputStyle)) {
throw new Error(`sources[${index}].outputStyle must be 'per-type' or 'per-xsd'.`);
}
if (!isValidEnumStyle(src.enumStyle)) {
throw new Error(`sources[${index}].enumStyle must be 'union', 'enum', or 'const-object'.`);
}
if (src.useXmlRoot !== void 0 && typeof src.useXmlRoot !== "boolean") {
throw new Error(`sources[${index}].useXmlRoot must be a boolean.`);
}
}
function isValidOutputStyle(value) {
return value === void 0 || value === "per-type" || value === "per-xsd";
}
function isValidEnumStyle(value) {
return value === void 0 || value === "union" || value === "enum" || value === "const-object";
}
function findConfigFile(cwd) {
for (const name of CONFIG_NAMES) {
const fullPath = import_node_path.default.resolve(cwd, name);
if (import_node_fs.default.existsSync(fullPath)) {
return fullPath;
}
}
return void 0;
}
async function loadConfig(configPath) {
const resolvedPath = configPath ? import_node_path.default.resolve(configPath) : findConfigFile(process.cwd());
if (!resolvedPath) {
throw new Error("No config file found. Run 'xml-poto-codegen init' to create one.");
}
if (!import_node_fs.default.existsSync(resolvedPath)) {
throw new Error(`Config file not found: ${resolvedPath}`);
}
const configDir = import_node_path.default.dirname(resolvedPath);
let raw;
if (resolvedPath.endsWith(".json")) {
const content = import_node_fs.default.readFileSync(resolvedPath, "utf-8");
raw = JSON.parse(content);
} else if (resolvedPath.endsWith(".ts")) {
const jiti = (0, import_jiti.createJiti)(__filename);
const mod = await jiti.import(resolvedPath, { default: true });
if (mod && typeof mod === "object" && "default" in mod) {
raw = mod.default;
} else {
raw = mod;
}
} else {
throw new Error(`Unsupported config file format: ${resolvedPath}`);
}
const config = validateConfig(raw);
return { config, configDir };
}
// src/generator/ts-builder.ts
function buildImport(names, from, isType = false) {
if (names.length === 0) return "";
const sorted = [...new Set(names)].sort();
const typePrefix = isType ? "type " : "";
if (sorted.length <= 3) {
return `import ${typePrefix}{ ${sorted.join(", ")} } from "${from}";`;
}
const items = sorted.map((n) => ` ${n},`).join("\n");
return `import ${typePrefix}{
${items}
} from "${from}";`;
}
function buildDecorator(name, options) {
if (!options || Object.keys(options).length === 0) {
return `@${name}()`;
}
const entries = Object.entries(options).filter(([, v]) => v !== void 0);
if (entries.length === 0) {
return `@${name}()`;
}
const optionStr = entries.map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
if (optionStr.length < 60) {
return `@${name}({ ${optionStr} })`;
}
const lines = entries.map(([k, v]) => ` ${k}: ${formatValue(v)},`).join("\n");
return `@${name}({
${lines}
})`;
}
function formatValue(value) {
if (typeof value === "string") return value;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (value instanceof RegExp) return value.toString();
if (Array.isArray(value)) {
const items = value.map((v) => formatValue(v)).join(", ");
return `[${items}]`;
}
if (typeof value === "object" && value !== null) {
const entries = Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}: ${formatValue(v)}`);
return `{ ${entries.join(", ")} }`;
}
return String(value);
}
function buildProperty(name, type, initializer, optional = false) {
const optionalMark = optional ? "?" : "";
if (initializer === void 0) {
return `${name}${optionalMark}: ${type};`;
}
return `${name}${optionalMark}: ${type} = ${initializer};`;
}
function buildFileHeader(xsdPath) {
return [
"// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
"// AUTO-GENERATED by @cerios/xml-poto-codegen",
`// Source: ${xsdPath}`,
"// Do not edit manually.",
"// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
""
].join("\n");
}
function toKebabCase(name) {
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
}
// src/generator/decorator-mapper.ts
function mapClassDecorator(type) {
if (type.isRootElement) {
const opts2 = { name: `'${type.xmlName}'` };
if (type.namespace) {
opts2.namespace = buildNamespaceObj(type.namespace);
}
if (type.rootNillable) {
opts2.isNullable = true;
}
return buildDecorator("XmlRoot", opts2);
}
const opts = { name: `'${type.xmlName}'` };
if (type.namespace) {
opts.namespace = buildNamespaceObj(type.namespace);
}
if (type.rootNillable) {
opts.isNullable = true;
}
if (type.form) {
opts.form = `'${type.form}'`;
}
return buildDecorator("XmlElement", opts);
}
function mapPropertyDecorator(prop) {
switch (prop.kind) {
case "element":
return buildElementDecorator(prop);
case "attribute":
return buildAttributeDecorator(prop);
case "text":
return buildTextDecorator(prop);
case "array":
return buildArrayDecorator(prop);
case "dynamic":
return buildDynamicDecorator(prop);
default:
return buildDecorator("XmlElement", { name: `'${prop.xmlName}'` });
}
}
function collectImports(type) {
const imports = /* @__PURE__ */ new Set();
imports.add(type.isRootElement ? "XmlRoot" : "XmlElement");
for (const prop of type.properties) {
switch (prop.kind) {
case "element":
imports.add("XmlElement");
break;
case "attribute":
imports.add("XmlAttribute");
break;
case "text":
imports.add("XmlText");
break;
case "array":
imports.add("XmlArray");
break;
case "dynamic":
imports.add("XmlDynamic");
imports.add("DynamicElement");
break;
}
}
return imports;
}
function buildElementDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.complexTypeName) opts.type = prop.complexTypeName;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlElement", opts);
}
function buildAttributeDecorator(prop) {
const opts = {};
opts.name = `'${prop.xmlName}'`;
if (prop.required) opts.required = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.defaultValue !== void 0) opts.defaultValue = formatDefault(prop.tsType, prop.defaultValue);
if (prop.enumValues && prop.enumValues.length > 0)
opts.enumValues = prop.enumValues.map((v) => `'${escapeString(v)}'`);
if (prop.pattern) opts.pattern = `new RegExp(${JSON.stringify(prop.pattern)})`;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
return buildDecorator("XmlAttribute", opts);
}
function buildTextDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlText", opts);
}
function buildArrayDecorator(prop) {
const opts = {};
if (prop.arrayItemName) opts.itemName = `'${prop.arrayItemName}'`;
if (prop.arrayContainerName) opts.containerName = `'${prop.arrayContainerName}'`;
if (prop.arrayItemType) opts.type = prop.arrayItemType;
if (prop.order !== void 0) opts.order = prop.order;
if (prop.isNullable) opts.isNullable = true;
if (prop.form) opts.form = `'${prop.form}'`;
if (prop.namespace) opts.namespace = buildNamespaceObj(prop.namespace);
if (prop.dataType) opts.dataType = `'${prop.dataType}'`;
return buildDecorator("XmlArray", opts);
}
function buildDynamicDecorator(prop) {
const opts = {};
if (prop.required) opts.required = true;
if (prop.order !== void 0) opts.order = prop.order;
return buildDecorator("XmlDynamic", opts);
}
function buildNamespaceObj(ns) {
if (ns.prefix) {
return `{ uri: '${ns.uri}', prefix: '${ns.prefix}' }`;
}
return `{ uri: '${ns.uri}' }`;
}
function formatDefault(tsType, value) {
if (tsType === "number") return value;
if (tsType === "boolean") return value === "true" ? "true" : "false";
return `'${escapeString(value)}'`;
}
function escapeString(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
// src/generator/class-generator.ts
var ClassGenerator = class {
constructor(options) {
this.importPath = "@cerios/xml-poto";
var _a, _b;
this.xsdPath = options.xsdPath;
this.enumStyle = (_a = options.enumStyle) != null ? _a : "union";
this.useXmlRoot = (_b = options.useXmlRoot) != null ? _b : true;
this.elementFormDefault = options.elementFormDefault;
}
/**
* Generate files in 'per-type' mode: one file per class/enum + barrel index.
*/
generatePerType(schema) {
const files = [];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const enumDef of schema.enums) {
files.push(this.generateEnumFile(enumDef));
}
for (const type of resolvedTypes) {
files.push(this.generateClassFile(type, resolvedTypes, schema.enums));
}
if (files.length > 0) {
files.push(this.generateBarrelExport(files));
}
return files;
}
/**
* Generate files in 'per-xsd' mode: all types in a single file.
*/
generatePerXsd(schema, fileName) {
const output = fileName != null ? fileName : "generated";
const file = this.generateSingleFile(schema, `${toKebabCase(output)}.ts`);
return [file];
}
// ── Per-type generation ──
generateEnumFile(enumDef) {
const fileName = `${toKebabCase(enumDef.name)}.ts`;
const lines = [buildFileHeader(this.xsdPath), this.generateEnumSource(enumDef), ""];
return {
fileName,
content: lines.join("\n"),
exports: [enumDef.name]
};
}
generateClassFile(type, allTypes, allEnums) {
const fileName = `${toKebabCase(type.className)}.ts`;
const imports = collectImports(type);
const localImports = this.collectLocalImports(type, allTypes, allEnums);
const lines = [buildFileHeader(this.xsdPath), buildImport([...imports], this.importPath)];
for (const [name, file] of localImports) {
lines.push(buildImport([name], `./${file.replace(".ts", "")}`));
}
lines.push("");
lines.push(this.generateClassSource(type));
lines.push("");
return {
fileName,
content: lines.join("\n"),
exports: [type.className]
};
}
generateBarrelExport(files) {
const exports2 = files.filter((f) => f.fileName !== "index.ts").map((f) => {
const moduleName = f.fileName.replace(".ts", "");
return `export { ${f.exports.join(", ")} } from "./${moduleName}";`;
});
return {
fileName: "index.ts",
content: buildFileHeader(this.xsdPath) + exports2.join("\n") + "\n",
exports: files.flatMap((f) => f.exports)
};
}
// ── Single-file generation ──
generateSingleFile(schema, fileName) {
const allImports = /* @__PURE__ */ new Set();
const allExports = [];
const parts = [buildFileHeader(this.xsdPath)];
const resolvedTypes = this.applyRootElements(schema.types, schema.rootElements);
for (const type of resolvedTypes) {
for (const imp of collectImports(type)) {
allImports.add(imp);
}
}
const needsDynamic = resolvedTypes.some((t) => t.properties.some((p) => p.kind === "dynamic"));
if (needsDynamic) {
allImports.add("DynamicElement");
}
parts.push(buildImport([...allImports], this.importPath));
parts.push("");
for (const enumDef of schema.enums) {
parts.push(this.generateEnumSource(enumDef));
parts.push("");
allExports.push(enumDef.name);
}
for (const type of resolvedTypes) {
parts.push(this.generateClassSource(type));
parts.push("");
allExports.push(type.className);
}
return {
fileName,
content: parts.join("\n"),
exports: allExports
};
}
// ── Source generation ──
generateEnumSource(enumDef) {
switch (this.enumStyle) {
case "enum":
return this.generateEnumAsEnum(enumDef);
case "const-object":
return this.generateEnumAsConstObject(enumDef);
case "union":
default:
return this.generateEnumAsUnion(enumDef);
}
}
generateEnumAsUnion(enumDef) {
const values = enumDef.values.map((v) => `"${v}"`).join(" | ");
return `export type ${enumDef.name} = ${values};`;
}
generateEnumAsEnum(enumDef) {
const members = enumDef.values.map((v) => {
const key = toEnumKey(v);
return ` ${key} = "${v}",`;
}).join("\n");
return `export enum ${enumDef.name} {
${members}
}`;
}
generateEnumAsConstObject(enumDef) {
const members = enumDef.values.map((v) => {
const key = toEnumKey(v);
return ` ${key}: "${v}",`;
}).join("\n");
const constDecl = `export const ${enumDef.name} = {
${members}
} as const;`;
const typeDecl = `export type ${enumDef.name} = (typeof ${enumDef.name})[keyof typeof ${enumDef.name}];`;
return `${constDecl}
${typeDecl}`;
}
generateClassSource(type) {
const lines = [];
lines.push(mapClassDecorator(type));
const extendsClause = type.baseTypeName ? ` extends ${type.baseTypeName}` : "";
lines.push(`export class ${type.className}${extendsClause} {`);
for (const prop of type.properties) {
const decorator = mapPropertyDecorator(prop);
const isOptional = prop.required !== true;
const initializer = isOptional ? void 0 : prop.initializer;
lines.push(` ${decorator}`);
lines.push(` ${buildProperty(prop.propertyName, prop.tsType, initializer, isOptional)}`);
lines.push("");
}
if (lines[lines.length - 1] === "") {
lines.pop();
}
lines.push("}");
return lines.join("\n");
}
// ── Helpers ──
collectLocalImports(type, allTypes, allEnums) {
const imports = /* @__PURE__ */ new Map();
const typeNames = new Set(allTypes.map((t) => t.className));
const enumNames = new Set(allEnums.map((e) => e.name));
if (type.baseTypeName && typeNames.has(type.baseTypeName)) {
imports.set(type.baseTypeName, `${toKebabCase(type.baseTypeName)}.ts`);
}
for (const prop of type.properties) {
if (prop.complexTypeName && typeNames.has(prop.complexTypeName)) {
imports.set(prop.complexTypeName, `${toKebabCase(prop.complexTypeName)}.ts`);
}
if (prop.arrayItemType && typeNames.has(prop.arrayItemType)) {
imports.set(prop.arrayItemType, `${toKebabCase(prop.arrayItemType)}.ts`);
}
if (prop.enumTypeName && enumNames.has(prop.enumTypeName)) {
imports.set(prop.enumTypeName, `${toKebabCase(prop.enumTypeName)}.ts`);
}
}
imports.delete(type.className);
return imports;
}
applyRootElements(types, rootElements) {
if (!this.useXmlRoot) {
return types.map(
(type) => type.isRootElement ? { ...type, isRootElement: false, form: this.elementFormDefault } : type
);
}
if (rootElements.length === 0) {
return types;
}
const rootMap = /* @__PURE__ */ new Map();
for (const root of rootElements) {
const entries = rootMap.get(root.typeName);
if (entries) {
entries.push(root);
} else {
rootMap.set(root.typeName, [root]);
}
}
return types.map((type) => {
if (type.isRootElement) {
return type;
}
const roots = rootMap.get(type.className);
if (!roots || roots.length === 0) {
return type;
}
const root = roots[0];
return {
...type,
isRootElement: true,
xmlName: root.name,
rootNillable: root.nillable
};
});
}
};
function toEnumKey(value) {
let key = value.replace(/[^a-zA-Z0-9_]/g, "_");
if (/^[0-9]/.test(key)) {
key = `_${key}`;
}
const hadLeadingUnderscore = key.startsWith("_");
let result = key.split("_").filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
if (hadLeadingUnderscore && !result.startsWith("_")) {
result = `_${result}`;
}
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = result.replace(/^[^A-Za-z_]+/, "");
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = `_${result}`;
}
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(result)) {
result = "_Value";
}
}
return result;
}
// src/generator/file-writer.ts
var import_node_fs2 = __toESM(require("fs"));
var import_node_path2 = __toESM(require("path"));
function writeGeneratedFiles(outputDir, files) {
const written = [];
import_node_fs2.default.mkdirSync(outputDir, { recursive: true });
for (const file of files) {
const filePath = import_node_path2.default.join(outputDir, file.fileName);
import_node_fs2.default.writeFileSync(filePath, file.content, "utf-8");
written.push(filePath);
}
return { written };
}
function writeGeneratedFile(outputFilePath, file) {
const parentDir = import_node_path2.default.dirname(outputFilePath);
import_node_fs2.default.mkdirSync(parentDir, { recursive: true });
import_node_fs2.default.writeFileSync(outputFilePath, file.content, "utf-8");
return outputFilePath;
}
// src/xsd/xsd-parser.ts
var import_node_fs3 = __toESM(require("fs"));
var import_node_path3 = __toESM(require("path"));
var import_xml_poto = require("@cerios/xml-poto");
var XSD_NS = "http://www.w3.org/2001/XMLSchema";
var XsdParser = class {
constructor() {
this.parser = new import_xml_poto.XmlDecoratorParser({
trimValues: false,
parseTagValue: false
});
/** Detected XSD prefix in the current schema (e.g. 'xs', 'xsd', or '') */
this.xsdPrefix = "xs";
}
/**
* Parse an XSD file at the given path, resolving includes/imports relative to it.
*/
parseFile(xsdPath) {
const absolutePath = import_node_path3.default.resolve(xsdPath);
const content = import_node_fs3.default.readFileSync(absolutePath, "utf-8");
return this.parseString(content, import_node_path3.default.dirname(absolutePath));
}
/**
* Parse an XSD string into a structured schema model.
*/
parseString(xsdContent, baseDir) {
const normalized = xsdContent.replace(/<\?xml[^?]*\?>/i, "").replace(/<!--[\s\S]*?-->/g, "").trim();
if (!/^<(?:[a-zA-Z_][\w.-]*:)?schema[\s/>]/i.test(normalized)) {
throw new Error(
"The provided content does not appear to be a valid XSD schema. Expected a root <xs:schema>, <xsd:schema>, or <schema> element."
);
}
const parsed = this.parser.parse(normalized);
const rootKey = this.findSchemaRootKey(parsed);
if (!rootKey) {
throw new Error("No XSD schema root element found. Expected <xs:schema>, <xsd:schema>, or <schema>.");
}
const schemaObj = parsed[rootKey];
this.detectXsdPrefix(schemaObj);
const schema = this.parseSchema(schemaObj);
if (baseDir) {
this.resolveExternalSchemas(schema, baseDir);
}
return schema;
}
resolveExternalSchemas(schema, baseDir) {
for (const inc of schema.includes) {
if (inc.schemaLocation) {
const incPath = import_node_path3.default.resolve(baseDir, inc.schemaLocation);
if (import_node_fs3.default.existsSync(incPath)) {
this.mergeSchema(schema, this.parseFile(incPath));
}
}
}
for (const imp of schema.imports) {
if (imp.schemaLocation) {
const impPath = import_node_path3.default.resolve(baseDir, imp.schemaLocation);
if (import_node_fs3.default.existsSync(impPath)) {
const imported = this.parseFile(impPath);
this.mergeSchema(schema, imported);
if (imp.namespace && imported.targetNamespace) {
for (const [prefix, uri] of imported.namespaces) {
if (uri === imported.targetNamespace && prefix !== "" && !schema.namespaces.has(prefix)) {
schema.namespaces.set(prefix, uri);
}
}
}
}
}
}
}
findSchemaRootKey(parsed) {
return Object.keys(parsed).find(
(k) => k === "schema" || k.endsWith(":schema") || k === "xs:schema" || k === "xsd:schema"
);
}
detectXsdPrefix(schemaObj) {
for (const key of Object.keys(schemaObj)) {
if (key.startsWith("@_xmlns:")) {
const prefix = key.substring(8);
const uri = schemaObj[key];
if (uri === XSD_NS) {
this.xsdPrefix = prefix;
return;
}
}
}
if (schemaObj["@_xmlns"] === XSD_NS) {
this.xsdPrefix = "";
return;
}
this.xsdPrefix = "xs";
}
/** Returns the full tag name for an XSD element, e.g. 'xs:element' */
xsd(localName) {
return this.xsdPrefix ? `${this.xsdPrefix}:${localName}` : localName;
}
parseSchema(obj) {
const schema = {
targetNamespace: attr(obj, "targetNamespace"),
elementFormDefault: attr(obj, "elementFormDefault"),
attributeFormDefault: attr(obj, "attributeFormDefault"),
namespaces: this.extractNamespaces(obj),
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
complexTypes: this.parseChildren(obj, this.xsd("complexType")).map((e) => this.parseComplexType(e)),
simpleTypes: this.parseChildren(obj, this.xsd("simpleType")).map((e) => this.parseSimpleType(e)),
groups: this.parseChildren(obj, this.xsd("group")).map((e) => this.parseGroup(e)),
attributeGroups: this.parseChildren(obj, this.xsd("attributeGroup")).map((e) => this.parseAttributeGroup(e)),
imports: this.parseChildren(obj, this.xsd("import")).map((e) => this.parseImport(e)),
includes: this.parseChildren(obj, this.xsd("include")).map((e) => this.parseInclude(e))
};
return schema;
}
extractNamespaces(obj) {
const ns = /* @__PURE__ */ new Map();
for (const key of Object.keys(obj)) {
if (key === "@_xmlns") {
ns.set("", obj[key]);
} else if (key.startsWith("@_xmlns:")) {
ns.set(key.substring(8), obj[key]);
}
}
return ns;
}
// ── Element parsing ──
parseElement(obj) {
var _a;
const el = {
name: (_a = attr(obj, "name")) != null ? _a : "",
type: attr(obj, "type"),
ref: attr(obj, "ref"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs"),
nillable: attr(obj, "nillable") === "true" || void 0,
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
substitutionGroup: attr(obj, "substitutionGroup")
};
const ct = this.getChild(obj, this.xsd("complexType"));
if (ct) {
el.complexType = this.parseComplexType(ct);
}
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) {
el.simpleType = this.parseSimpleType(st);
}
return el;
}
// ── Complex Type parsing ──
parseComplexType(obj) {
const ct = {
name: attr(obj, "name"),
mixed: attr(obj, "mixed") === "true" || void 0,
abstract: attr(obj, "abstract") === "true" || void 0,
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj),
anyAttribute: this.getChild(obj, this.xsd("anyAttribute")) !== void 0 || void 0
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ct.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ct.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ct.all = this.parseAll(all);
const sc = this.getChild(obj, this.xsd("simpleContent"));
if (sc) ct.simpleContent = this.parseSimpleContent(sc);
const cc = this.getChild(obj, this.xsd("complexContent"));
if (cc) ct.complexContent = this.parseComplexContent(cc);
return ct;
}
// ── Simple Type parsing ──
parseSimpleType(obj) {
var _a;
const st = {
name: attr(obj, "name")
};
const restriction = this.getChild(obj, this.xsd("restriction"));
if (restriction) {
st.restriction = this.parseRestriction(restriction);
}
const list = this.getChild(obj, this.xsd("list"));
if (list) {
st.list = { itemType: (_a = attr(list, "itemType")) != null ? _a : "" };
}
const union = this.getChild(obj, this.xsd("union"));
if (union) {
const memberTypes = attr(union, "memberTypes");
st.union = {
memberTypes: memberTypes ? memberTypes.split(/\s+/) : []
};
}
return st;
}
parseRestriction(obj) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
return {
base: (_a = attr(obj, "base")) != null ? _a : "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => {
var _a2;
return (_a2 = attr(e, "value")) != null ? _a2 : "";
}),
pattern: attr((_b = this.getChild(obj, this.xsd("pattern"))) != null ? _b : {}, "value"),
minLength: numAttr((_c = this.getChild(obj, this.xsd("minLength"))) != null ? _c : {}, "value"),
maxLength: numAttr((_d = this.getChild(obj, this.xsd("maxLength"))) != null ? _d : {}, "value"),
minInclusive: numAttr((_e = this.getChild(obj, this.xsd("minInclusive"))) != null ? _e : {}, "value"),
maxInclusive: numAttr((_f = this.getChild(obj, this.xsd("maxInclusive"))) != null ? _f : {}, "value"),
minExclusive: numAttr((_g = this.getChild(obj, this.xsd("minExclusive"))) != null ? _g : {}, "value"),
maxExclusive: numAttr((_h = this.getChild(obj, this.xsd("maxExclusive"))) != null ? _h : {}, "value"),
totalDigits: numAttr((_i = this.getChild(obj, this.xsd("totalDigits"))) != null ? _i : {}, "value"),
fractionDigits: numAttr((_j = this.getChild(obj, this.xsd("fractionDigits"))) != null ? _j : {}, "value"),
whiteSpace: attr((_k = this.getChild(obj, this.xsd("whiteSpace"))) != null ? _k : {}, "value")
};
}
// ── Attribute parsing ──
parseAttribute(obj) {
var _a;
const a = {
name: (_a = attr(obj, "name")) != null ? _a : "",
type: attr(obj, "type"),
use: attr(obj, "use"),
defaultValue: attr(obj, "default"),
fixed: attr(obj, "fixed"),
form: attr(obj, "form"),
ref: attr(obj, "ref")
};
const st = this.getChild(obj, this.xsd("simpleType"));
if (st) {
a.simpleType = this.parseSimpleType(st);
}
return a;
}
// ── Compositor parsing ──
parseSequence(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
choices: this.parseChildren(obj, this.xsd("choice")).map((c) => this.parseChoice(c)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
any: this.parseChildren(obj, this.xsd("any")).map((a) => this.parseAny(a))
};
}
parseChoice(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e)),
sequences: this.parseChildren(obj, this.xsd("sequence")).map((s) => this.parseSequence(s)),
groupRefs: this.parseGroupRefs(obj),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
parseAll(obj) {
return {
elements: this.parseChildren(obj, this.xsd("element")).map((e) => this.parseElement(e))
};
}
parseAny(obj) {
return {
namespace: attr(obj, "namespace"),
processContents: attr(obj, "processContents"),
minOccurs: numAttr(obj, "minOccurs"),
maxOccurs: occursAttr(obj, "maxOccurs")
};
}
// ── Content model parsing ──
parseSimpleContent(obj) {
const sc = {};
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) {
sc.extension = this.parseSimpleContentExtension(ext);
}
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) {
sc.restriction = this.parseSimpleContentRestriction(rest);
}
return sc;
}
parseSimpleContentExtension(obj) {
var _a;
return {
base: (_a = attr(obj, "base")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseSimpleContentRestriction(obj) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
return {
base: (_a = attr(obj, "base")) != null ? _a : "",
enumerations: this.parseChildren(obj, this.xsd("enumeration")).map((e) => {
var _a2;
return (_a2 = attr(e, "value")) != null ? _a2 : "";
}),
pattern: attr((_b = this.getChild(obj, this.xsd("pattern"))) != null ? _b : {}, "value"),
minLength: numAttr((_c = this.getChild(obj, this.xsd("minLength"))) != null ? _c : {}, "value"),
maxLength: numAttr((_d = this.getChild(obj, this.xsd("maxLength"))) != null ? _d : {}, "value"),
minInclusive: numAttr((_e = this.getChild(obj, this.xsd("minInclusive"))) != null ? _e : {}, "value"),
maxInclusive: numAttr((_f = this.getChild(obj, this.xsd("maxInclusive"))) != null ? _f : {}, "value"),
minExclusive: numAttr((_g = this.getChild(obj, this.xsd("minExclusive"))) != null ? _g : {}, "value"),
maxExclusive: numAttr((_h = this.getChild(obj, this.xsd("maxExclusive"))) != null ? _h : {}, "value"),
totalDigits: numAttr((_i = this.getChild(obj, this.xsd("totalDigits"))) != null ? _i : {}, "value"),
fractionDigits: numAttr((_j = this.getChild(obj, this.xsd("fractionDigits"))) != null ? _j : {}, "value"),
whiteSpace: attr((_k = this.getChild(obj, this.xsd("whiteSpace"))) != null ? _k : {}, "value"),
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
}
parseComplexContent(obj) {
const cc = {
mixed: attr(obj, "mixed") === "true" || void 0
};
const ext = this.getChild(obj, this.xsd("extension"));
if (ext) {
cc.extension = this.parseComplexContentExtension(ext);
}
const rest = this.getChild(obj, this.xsd("restriction"));
if (rest) {
cc.restriction = this.parseComplexContentRestriction(rest);
}
return cc;
}
parseComplexContentExtension(obj) {
var _a;
const ext = {
base: (_a = attr(obj, "base")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
groupRefs: this.parseGroupRefs(obj),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) ext.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) ext.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) ext.all = this.parseAll(all);
return ext;
}
parseComplexContentRestriction(obj) {
var _a;
const rest = {
base: (_a = attr(obj, "base")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a))
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) rest.sequence = this.parseSequence(seq);
return rest;
}
// ── Group parsing ──
parseGroup(obj) {
var _a;
const g = {
name: (_a = attr(obj, "name")) != null ? _a : ""
};
const seq = this.getChild(obj, this.xsd("sequence"));
if (seq) g.sequence = this.parseSequence(seq);
const choice = this.getChild(obj, this.xsd("choice"));
if (choice) g.choice = this.parseChoice(choice);
const all = this.getChild(obj, this.xsd("all"));
if (all) g.all = this.parseAll(all);
return g;
}
parseGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("group")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({
ref: attr(g, "ref"),
minOccurs: numAttr(g, "minOccurs"),
maxOccurs: occursAttr(g, "maxOccurs")
}));
}
parseAttributeGroup(obj) {
var _a;
return {
name: (_a = attr(obj, "name")) != null ? _a : "",
attributes: this.parseChildren(obj, this.xsd("attribute")).map((a) => this.parseAttribute(a)),
attributeGroupRefs: this.parseAttributeGroupRefs(obj)
};
}
parseAttributeGroupRefs(obj) {
return this.parseChildren(obj, this.xsd("attributeGroup")).filter((g) => attr(g, "ref") !== void 0).map((g) => ({ ref: attr(g, "ref") }));
}
// ── Import/Include ──
parseImport(obj) {
return {
namespace: attr(obj, "namespace"),
schemaLocation: attr(obj, "schemaLocation")
};
}
parseInclude(obj) {
var _a;
return {
schemaLocation: (_a = attr(obj, "schemaLocation")) != null ? _a : ""
};
}
// ── Schema merging (for includes) ──
mergeSchema(target, source) {
target.elements.push(...source.elements);
target.complexTypes.push(...source.complexTypes);
target.simpleTypes.push(...source.simpleTypes);
target.groups.push(...source.groups);
target.attributeGroups.push(...source.attributeGroups);
}
// ── Utility: child access in parsed XML object ──
/**
* Get a single child element by tag name from a parsed XML object.
* Returns the child as an object, or undefined if not found.
*/
getChild(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return void 0;
if (Array.isArray(child)) return child[0];
if (typeof child === "object") return child;
return void 0;
}
/**
* Get all children with a given tag name as an array.
*/
parseChildren(obj, tagName) {
const child = obj[tagName];
if (child === void 0 || child === null) return [];
if (Array.isArray(child))
return child.map((c) => typeof c === "object" && c !== null ? c : {});
if (typeof child === "object") return [child];
return [];
}
};
function attr(obj, name) {
const val = obj[`@_${name}`];
if (val === void 0 || val === null) return void 0;
if (typeof val === "string") return val;
if (typeof val === "number" || typeof val === "boolean" || typeof val === "bigint" || typeof val === "symbol") {
return String(val);
}
return void 0;
}
function numAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
function occursAttr(obj, name) {
const val = attr(obj, name);
if (val === void 0) return void 0;
if (val === "unbounded") return "unbounded";
const num = Number(val);
return Number.isNaN(num) ? void 0 : num;
}
// src/xsd/xsd-resolver.ts
var XSD_TYPE_MAP = {
string: { tsType: "string", initializer: "''" },
normalizedString: { tsType: "string", initializer: "''" },
token: { tsType: "string", initializer: "''" },
language: { tsType: "string", initializer: "''" },
Name: { tsType: "string", initializer: "''" },
NCName: { tsType: "string", initializer: "''" },
NMTOKEN: { tsType: "string", initializer: "''" },
ID: { tsType: "string", initializer: "''" },
IDREF: { tsType: "string", initializer: "''" },
anyURI: { tsType: "string", initializer: "''" },
QName: { tsType: "string", initializer: "''" },
integer: { tsType: "number", initializer: "0" },
int: { tsType: "number", initializer: "0" },
long: { tsType: "number", initializer: "0" },
short: { tsType: "number", initializer: "0" },
byte: { tsType: "number", initializer: "0" },
nonNegativeInteger: { tsType: "number", initializer: "0" },
nonPositiveInteger: { tsType: "number", initializer: "0" },
positiveInteger: { tsType: "number", initializer: "0" },
negativeInteger: { tsType: "number", initializer: "0" },
unsignedInt: { tsType: "number", initializer: "0" },
unsignedLong: { tsType: "number", initializer: "0" },
unsignedShort: { tsType: "number", initializer: "0" },
unsignedByte: { tsType: "number", initializer: "0" },
decimal: { tsType: "number", initializer: "0" },
float: { tsType: "number", initializer: "0" },
double: { tsType: "number", initializer: "0" },
boolean: { tsType: "boolean", initializer: "false" },
dateTime: {
tsType: "string",
initializer: "''",
dataType: "xs:dateTime"
},
date: { tsType: "string", initializer: "''", dataType: "xs:date" },
time: { tsType: "string", initializer: "''", dataType: "xs:time" },
duration: { tsType: "string", initializer: "''" },
gYear: { tsType: "string", initializer: "''" },
gMonth: { tsType: "string", initializer: "''" },
gDay: { tsType: "string", initializer: "''" },
gYearMonth: { tsType: "string", initializer: "''" },
gMonthDay: { tsType: "string", initializer: "''" },
base64Binary: { tsType: "string", initializer: "''" },
hexBinary: { tsType: "string", initializer: "''" },
anyType: { tsType: "unknown", initializer: "undefined" },
anySimpleType: { tsType: "string", initializer: "''" }
};
var XsdResolver = class {
constructor() {
this.complexTypeMap = /* @__PURE__ */ new Map();
this.simpleTypeMap = /* @__PURE__ */ new Map();
this.groupMap = /* @__PURE__ */ new Map();
this.attributeGroupMap = /* @__PURE__ */ new Map();
this.resolvedTypeMap = /* @__PURE__ */ new Map();
/** Maps head element name → list of substitute element names */
this.substitutionMap = /* @__PURE__ */ new Map();
}
resolve(schema) {
this.schema = schema;
this.buildLookups();
this.resolvedTypeMap.clear();
const resolved = {
targetNamespace: schema.targetNamespace,
elementFormDefault: schema.elementFormDefault,
namespaces: schema.namespaces,
types: [],
enums: [],
rootElements: []
};
for (const st of schema.simpleTypes) {
if (st.name && st.restriction && st.restriction.enumerations.length > 0) {
resolved.enums.push({
name: toPascalCase(st.name),
xmlName: st.name,
values: st.restriction.enumerations,
baseType: stripPrefix(st.restriction.base)
});
}
}
for (const ct of schema.complexTypes) {
if (ct.name) {
this.addResolvedType(this.resolveComplexType(ct, ct.name, false));
}
}
for (const el of schema.elements) {
if (el.complexType) {
this.addResolvedType(this.resolveComplexType(el.complexType, el.name, true));
} else if (el.type) {
const localType = stripPrefix(el.type);
if (this.complexTypeMap.has(localType)) {
resolved.rootElements.push({
name: el.name,
typeName: toPascalCase(localType),
nillable: el.nillable
});
} else {
this.addResolvedType(this.resolveSimpleRootElement(el));
}
} else if (el.simpleType) {
this.addResolvedType(this.resolveSimpleRootElement(el));
}
}
resolved.types = [...this.resolvedTypeMap.values()];
return resolved;
}
addResolvedType(type) {
if (!this.resolvedTypeMap.has(type.className)) {
this.resolvedTypeMap.set(type.className, type);
}
}
buildLookups() {
this.complexTypeMap.clear();
this.simpleTypeMap.clear();
this.groupMap.clear();
this.attributeGroupMap.clear();
this.substitutionMap.clear();
this.buildTypeLookups();
this.buildGroupLookups();
this.buildAttributeGroupLookups();
this.buildSubstitutionLookups();
}
buildTypeLookups() {
for (const ct of this.schema.complexTypes) {
if (ct.name) this.complexTypeMap.set(ct.name, ct);
}
for (const st of this.schema.simpleTypes) {
if (st.name) this.simpleTypeMap.set(st.name, st);
}
}
buildGroupLookups() {
var _a, _b;
for (const g of this.schema.groups) {
if (g.name) {
const compositor = (_b = (_a = g.sequence) != null ? _a : g.choice) != null ? _b : g.all;
if (compositor) this.groupMap.set(g.name, compositor);
}
}
}
buildAttributeGroupLookups() {
const groupDefs = /* @__PURE__ */ new Map();
for (const ag of this.schema.attributeGroups) {
if (ag.name) {
groupDefs.set(ag.name, ag);
}
}
const resolving = /* @__PURE__ */ new Set();
const resolveGroup = (name) => {
const cached = this.attributeGroupMap.get(name);
if (cached) return cached;
const def = groupDefs.get(name);
if (!def) {
return [];
}
if (resolving.has(name)) {
return [];
}
resolving.add(name);
const attrs = [...def.attributes];
for (const ref of def.attributeGroupRefs) {
const refName = stripPrefix(ref.ref);
const resolvedAttrs = resolveGroup(refName);
if (resolvedAttrs.length) {
attrs.push(...resolvedAttrs);
}
}
resolving.delete(name);
this.attributeGroupMap.set(name, attrs);
return attrs;
};
for (const name of groupDefs.keys()) {
resolveGroup(name);
}
}
buildSubstitutionLookups() {
for (const el of this.schema.elements) {
if (el.substitutionGroup) {
const headName = stripPrefix(el.substitutionGroup);
const substitutes = this.substitutionMap.get(headName);
if (substitutes) {
substitutes.push(el.name);
} else {
this.substitutionMap.set(headName, [el.name]);
}
}
}
}
resolveComplexType(ct, name, isRoot, classNameOverride) {
const resolved = {
className: classNameOverride != null ? classNameOverride : toPascalCase(name),
xmlName: name,
properties: [],
isRootElement: isRoot,
mixed: ct.mixed,
abstract: ct.abstract
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix != null ? prefix : void 0
};
}
if (ct.simpleContent) {
resolved.hasSimpleContent = true;
this.resolveSimpleContent(ct.simpleContent, resolved);
return resolved;
}
if (ct.complexContent) {
this.resolveComplexContent(ct.complexContent, resolved);
}
let order = 1;
if (ct.sequence) {
order = this.resolveSequenceProperties(ct.sequence, resolved.properties, order);
}
if (ct.choice) {
order = this.resolveChoiceProperties(ct.choice, resolved.properties, order);
}
if (ct.all) {
this.resolveAllProperties(ct.all, resolved.properties);
}
for (const gRef of ct.groupRefs) {
order = this.resolveGroupRef(gRef, resolved.properties, order);
}
this.resolveAttributes(ct.attributes, resolved.properties);
for (const agRef of ct.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
if (ct.anyAttribute) {
resolved.properties.push({
propertyName: "anyAttributes",
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!"
});
}
return resolved;
}
resolveSimpleContent(sc, resolved) {
if (sc.extension) {
const baseInfo = this.resolveTypeReference(sc.extension.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.extension.attributes, resolved.properties);
} else if (sc.restriction) {
const baseInfo = this.resolveTypeReference(sc.restriction.base);
resolved.properties.push({
propertyName: "value",
xmlName: "",
kind: "text",
tsType: baseInfo.tsType,
initializer: baseInfo.initializer,
enumValues: sc.restriction.enumerations.length > 0 ? sc.restriction.enumerations : void 0,
pattern: sc.restriction.pattern,
minLength: sc.restriction.minLength,
maxLength: sc.restriction.maxLength,
minInclusive: sc.restriction.minInclusive,
maxInclusive: sc.restriction.maxInclusive,
minExclusive: sc.restriction.minExclusive,
maxExclusive: sc.restriction.maxExclusive,
totalDigits: sc.restriction.totalDigits,
fractionDigits: sc.restriction.fractionDigits,
whiteSpace: sc.restriction.whiteSpace,
dataType: baseInfo.dataType
});
this.resolveAttributes(sc.restriction.attributes, resolved.properties);
}
}
resolveComplexContent(cc, resolved) {
if (cc.extension) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.extension.base));
let order = 1;
if (cc.extension.sequence) {
order = this.resolveSequenceProperties(cc.extension.sequence, resolved.properties, order);
}
if (cc.extension.choice) {
order = this.resolveChoiceProperties(cc.extension.choice, resolved.properties, order);
}
if (cc.extension.all) {
this.resolveAllProperties(cc.extension.all, resolved.properties);
}
for (const gRef of cc.extension.groupRefs) {
order = this.resolveGroupRef(gRef, resolved.properties, order);
}
this.resolveAttributes(cc.extension.attributes, resolved.properties);
for (const agRef of cc.extension.attributeGroupRefs) {
const refName = stripPrefix(agRef.ref);
const attrs = this.attributeGroupMap.get(refName);
if (attrs) this.resolveAttributes(attrs, resolved.properties);
}
} else if (cc.restriction) {
resolved.baseTypeName = toPascalCase(stripPrefix(cc.restriction.base));
if (cc.restriction.sequence) {
this.resolveSequenceProperties(cc.restriction.sequence, resolved.properties, 1);
}
this.resolveAttributes(cc.restriction.attributes, resolved.properties);
}
}
resolveSequenceProperties(seq, props, startOrder) {
let order = startOrder;
for (const el of seq.elements) {
props.push(this.resolveElementProperty(el, order++));
}
for (const choice of seq.choices) {
order = this.resolveChoiceProperties(choice, props, order);
}
for (const nested of seq.sequences) {
order = this.resolveSequenceProperties(nested, props, order);
}
for (const gRef of seq.groupRefs) {
order = this.resolveGroupRef(gRef, props, order);
}
for (const any of seq.any) {
props.push({
propertyName: `dynamicContent${order}`,
xmlName: "",
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
order: order++
});
if (any.minOccurs === void 0 || any.minOccurs > 0) {
props[props.length - 1].required = true;
}
}
return order;
}
resolveChoiceProperties(choice, props, startOrder) {
let order = startOrder;
for (const el of choice.elements) {
const prop = this.resolveElementProperty(el, order++);
prop.required = false;
props.push(prop);
}
for (const seq of choice.sequences) {
order = this.resolveSequenceProperties(seq, props, order);
}
for (const gRef of choice.groupRefs) {
order = this.resolveGroupRef(gRef, props, order);
}
return order;
}
resolveAllProperties(all, props) {
for (const el of all.elements) {
props.push(this.resolveElementProperty(el));
}
}
resolveGroupRef(gRef, props, startOrder) {
const refName = stripPrefix(gRef.ref);
const compositor = this.groupMap.get(refName);
if (!compositor) return startOrder;
if ("elements" in compositor && "choices" in compositor) {
return this.resolveSequenceProperties(compositor, props, startOrder);
}
if ("elements" in compositor && !("choices" in compositor)) {
if ("sequences" in compositor) {
return this.resolveChoiceProperties(compositor, props, startOrder);
}
this.resolveAllProperties(compositor, props);
}
return startOrder;
}
resolveElementProperty(el, order) {
var _a, _b;
const isArray = el.maxOccurs === "unbounded" || typeof el.maxOccurs === "number" && el.maxOccurs > 1;
const isRequired = el.minOccurs === void 0 || el.minOccurs > 0;
const form = (_a = el.form) != null ? _a : this.resolveElementForm();
const name = el.ref ? stripPrefix(el.ref) : el.name;
if (this.substitutionMap.has(name)) {
return {
propertyName: toCamelCase(name),
xmlName: name,
kind: "dynamic",
tsType: "DynamicElement",
initializer: "undefined!",
required: isRequired,
order
};
}
let typeInfo;
if (el.complexType) {
const inlineTypeName = toPascalCase(name) + "Type";
this.addResolvedType(this.resolveComplexType(el.complexType, name, false, inlineTypeName));
typeInfo = {
tsType: inlineTypeName,
initializer: `new ${inlineTypeName}()`,
complexTypeName: inlineTypeName
};
} else if (el.simpleType) {
typeInfo = this.resolveSimpleTypeInline(el.simpleType);
} else if (el.type) {
typeInfo = this.resolveTypeReference(el.type);
} else {
typeInfo = { tsType: "string", initializer: "''" };
}
const prop = {
propertyName: toCamelCase(name),
xmlName: name,
kind: isArray ? "array" : "element",
tsType: isArray ? `${typeInfo.tsType}[]` : typeInfo.tsType,
initializer: isArray ? "[]" : typeInfo.initializer,
required: isRequired,
order,
isNullable: el.nillable,
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: (_b = el.defaultValue) != null ? _b : el.fixed,
fixedValue: el.fixed,
complexTypeName: typeInfo.complexTypeName,
enumValues: typeInfo.enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
};
if (isArray) {
prop.arrayItemName = name;
prop.arrayItemType = typeInfo.complexTypeName;
}
return prop;
}
resolveAttributes(attrs, props) {
var _a, _b, _c, _d;
for (const a of attrs) {
if (a.ref) {
const form2 = (_a = a.form) != null ? _a : this.resolveAttributeForm();
const defaultOrFixed2 = (_b = a.defaultValue) != null ? _b : a.fixed;
props.push({
propertyName: toCamelCase(stripPrefix(a.ref)),
xmlName: stripPrefix(a.ref),
kind: "attribute",
tsType: "string",
initializer: defaultOrFixed2 ? `'${escapeString2(defaultOrFixed2)}'` : "''",
required: a.use === "required",
form: form2,
namespace: this.resolveNamespaceForForm(form2),
defaultValue: defaultOrFixed2,
fixedValue: a.fixed
});
continue;
}
let typeInfo;
if (a.simpleType) {
typeInfo = this.resolveSimpleTypeInline(a.simpleType);
} else if (a.type) {
typeInfo = this.resolveTypeReference(a.type);
} else {
typeInfo = { tsType: "string", initializer: "''" };
}
const defaultOrFixed = (_c = a.defaultValue) != null ? _c : a.fixed;
const initializer = defaultOrFixed ? this.buildDefaultInitializer(typeInfo.tsType, defaultOrFixed) : typeInfo.initializer;
const form = (_d = a.form) != null ? _d : this.resolveAttributeForm();
const enumValues = typeInfo.enumValues ? [...typeInfo.enumValues] : a.fixed ? [a.fixed] : void 0;
props.push({
propertyName: toCamelCase(a.name),
xmlName: a.name,
kind: "attribute",
tsType: typeInfo.tsType,
initializer,
required: a.use === "required",
form,
namespace: this.resolveNamespaceForForm(form),
defaultValue: defaultOrFixed,
fixedValue: a.fixed,
enumValues,
pattern: typeInfo.pattern,
enumTypeName: typeInfo.enumTypeName,
dataType: typeInfo.dataType,
minLength: typeInfo.minLength,
maxLength: typeInfo.maxLength,
minInclusive: typeInfo.minInclusive,
maxInclusive: typeInfo.maxInclusive,
minExclusive: typeInfo.minExclusive,
maxExclusive: typeInfo.maxExclusive,
totalDigits: typeInfo.totalDigits,
fractionDigits: typeInfo.fractionDigits,
whiteSpace: typeInfo.whiteSpace
});
}
}
resolveTypeReference(typeRef) {
const localName = stripPrefix(typeRef);
const builtin = XSD_TYPE_MAP[localName];
if (builtin) return { ...builtin };
if (this.complexTypeMap.has(localName)) {
const className = toPascalCase(localName);
return {
tsType: className,
initializer: `new ${className}()`,
complexTypeName: className
};
}
const st = this.simpleTypeMap.get(localName);
if (st) {
return this.resolveSimpleTypeInline(st);
}
return { tsType: "string", initializer: "''" };
}
resolveSimpleTypeInline(st) {
if (st.restriction) {
const baseInfo = this.resolveTypeReference(st.restriction.base);
const result = {
...baseInfo
};
if (st.restriction.enumerations.length > 0) {
if (st.name) {
result.enumTypeName = toPascalCase(st.name);
result.tsType = toPascalCase(st.name);
} else {
result.enumValues = st.restriction.enumerations;
}
}
if (st.restriction.pattern) {
result.pattern = st.restriction.pattern;
}
result.minLength = st.restriction.minLength;
result.maxLength = st.restriction.maxLength;
result.minInclusive = st.restriction.minInclusive;
result.maxInclusive = st.restriction.maxInclusive;
result.minExclusive = st.restriction.minExclusive;
result.maxExclusive = st.restriction.maxExclusive;
result.totalDigits = st.restriction.totalDigits;
result.fractionDigits = st.restriction.fractionDigits;
result.whiteSpace = st.restriction.whiteSpace;
return result;
}
if (st.list) {
const itemInfo = this.resolveTypeReference(st.list.itemType);
return {
tsType: `${itemInfo.tsType}[]`,
initializer: "[]"
};
}
if (st.union) {
if (st.union.memberTypes.length > 0) {
const memberInfos = st.union.memberTypes.map((mt) => this.resolveTypeReference(mt));
const uniqueTypes = [...new Set(memberInfos.map((m) => m.tsType))];
const tsType = uniqueTypes.join(" | ");
return { tsType, initializer: memberInfos[0].initializer };
}
return { tsType: "string", initializer: "''" };
}
return { tsType: "string", initializer: "''" };
}
resolveSimpleRootElement(el) {
const typeInfo = el.simpleType ? this.resolveSimpleTypeInline(el.simpleType) : el.type ? this.resolveTypeReference(el.type) : { tsType: "string", initializer: "''" };
const resolved = {
className: toPascalCase(el.name),
xmlName: el.name,
properties: [
{
propertyName: "value",
xmlName: "",
kind: "text",
tsType: typeInfo.tsType,
initializer: typeInfo.initializer,
dataType: typeInfo.dataType
}
],
isRootElement: true
};
if (this.schema.targetNamespace) {
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
resolved.namespace = {
uri: this.schema.targetNamespace,
prefix: prefix != null ? prefix : void 0
};
}
return resolved;
}
resolveElementForm() {
return this.schema.elementFormDefault;
}
resolveAttributeForm() {
return this.schema.attributeFormDefault;
}
resolveNamespaceForForm(form) {
if (form !== "qualified" || !this.schema.targetNamespace) {
return void 0;
}
const prefix = this.findPrefixForUri(this.schema.targetNamespace);
return {
uri: this.schema.targetNamespace,
prefix: prefix != null ? prefix : void 0
};
}
findPrefixForUri(uri) {
for (const [prefix, nsUri] of this.schema.namespaces) {
if (nsUri === uri && prefix !== "") return prefix;
}
return void 0;
}
buildDefaultInitializer(tsType, defaultValue) {
if (tsType === "number") return defaultValue;
if (tsType === "boolean") return defaultValue === "true" ? "true" : "false";
return `'${escapeString2(defaultValue)}'`;
}
};
function stripPrefix(name) {
const idx = name.indexOf(":");
return idx >= 0 ? name.substring(idx + 1) : name;
}
function toPascalCase(name) {
const converted = name.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase()).replace(/^[a-z]/, (c) => c.toUpperCase());
return sanitizeIdentifier(converted, true);
}
function toCamelCase(name) {
const pascal = toPascalCase(name);
return sanitizeIdentifier(pascal.charAt(0).toLowerCase() + pascal.slice(1), false);
}
function sanitizeIdentifier(value, pascal) {
const normalized = value.replace(/[^a-zA-Z0-9_$]/g, "");
const nonEmpty = normalized.length > 0 ? normalized : pascal ? "GeneratedType" : "generatedField";
const withLeading = /^[A-Za-z_$]/.test(nonEmpty) ? nonEmpty : `_${nonEmpty}`;
if (RESERVED_TS_IDENTIFIERS.has(withLeading)) {
return `${withLeading}_`;
}
return withLeading;
}
var RESERVED_TS_IDENTIFIERS = /* @__PURE__ */ new Set([
"abstract",
"any",
"as",
"asserts",
"async",
"await",
"boolean",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"declare",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"from",
"function",
"get",
"if",
"implements",
"import",
"in",
"infer",
"instanceof",
"interface",
"is",
"keyof",
"let",
"module",
"namespace",
"never",
"new",
"null",
"number",
"object",
"package",
"private",
"protected",
"public",
"readonly",
"require",
"return",
"set",
"static",
"string",
"super",
"switch",
"symbol",
"this",
"throw",
"true",
"try",
"type",
"typeof",
"undefined",
"unique",
"unknown",
"var",
"void",
"while",
"with",
"yield"
]);
function escapeString2(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ClassGenerator,
XsdParser,
XsdResolver,
buildDecorator,
buildFileHeader,
buildImport,
buildProperty,
collectImports,
findConfigFile,
loadConfig,
mapClassDecorator,
mapPropertyDecorator,
toCamelCase,
toKebabCase,
toPascalCase,
validateConfig,
writeGeneratedFile,
writeGeneratedFiles
});
//# sourceMappingURL=index.js.map

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display