UNPKG

@dpml/core

Version:

DPML Core: Implementations of base compiler, and provide a simple framework for domain developers.

1,693 lines (1,680 loc) 177 kB
import { Command } from 'commander'; import * as xml2js from 'xml2js'; import fs from 'fs/promises'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/core/cli/commandUtils.ts function mergeDefaultOptions(options) { return { defaultDomain: "core", ...options }; } __name(mergeDefaultOptions, "mergeDefaultOptions"); function getCommandPath(command, parentPath) { let path = command.name; if (parentPath) { path = `${parentPath} ${path}`; } if (command.category && !parentPath) { path = `${command.category} ${path}`; } return path; } __name(getCommandPath, "getCommandPath"); function validateCommands(commands) { const pathSet = /* @__PURE__ */ new Set(); const crossDomainMap = /* @__PURE__ */ new Map(); function validateCommandTree(command, parentPath) { const path = getCommandPath(command, parentPath); if (pathSet.has(path)) { throw new Error(`\u91CD\u590D\u7684\u547D\u4EE4\u5B9A\u4E49: ${path}`); } pathSet.add(path); if (!parentPath && command.name) { const domain = command.category || "default"; const registeredDomains = crossDomainMap.get(command.name) || []; if (registeredDomains.length > 0 && !registeredDomains.includes(domain)) { const conflictDomains = registeredDomains.join(", "); console.warn(`\u8B66\u544A: \u547D\u4EE4 "${command.name}" \u5728\u591A\u4E2A\u9886\u57DF\u4E2D\u5B9A\u4E49: ${conflictDomains} \u548C ${domain}`); } if (!registeredDomains.includes(domain)) { crossDomainMap.set(command.name, [ ...registeredDomains, domain ]); } } if (command.subcommands && command.subcommands.length > 0) { for (const subcommand of command.subcommands) { validateCommandTree(subcommand, path); } } } __name(validateCommandTree, "validateCommandTree"); for (const command of commands) { validateCommandTree(command); } } __name(validateCommands, "validateCommands"); // src/core/cli/CLIAdapter.ts var _CLIAdapter = class _CLIAdapter { /** * 创建CLI适配器 * * @param name CLI名称 * @param version CLI版本 * @param description CLI描述 */ constructor(name, version, description) { /** * Commander程序实例 */ __publicField(this, "program"); /** * 已注册的命令路径集合 */ __publicField(this, "commandPaths"); this.program = new Command(name).version(version).description(description); this.commandPaths = /* @__PURE__ */ new Set(); if (typeof this.program.exitOverride === "function" && process.env.NODE_ENV !== "test" && !process.env.VITEST) { this.program.exitOverride(); } } /** * 注册命令 * * @param command 命令定义 * @param parentPath 父命令路径 */ setupCommand(command, parentPath) { const path = getCommandPath(command, parentPath); if (this.commandPaths.has(path)) { throw new Error(`\u91CD\u590D\u7684\u547D\u4EE4\u5B9A\u4E49: ${path}`); } this.commandPaths.add(path); const parentCommand = parentPath ? this.findParentCommand(parentPath) : this.program; const cmd = parentCommand.command(command.name); if (command.description) { cmd.description(command.description); } if (command.arguments && command.arguments.length > 0) { for (const arg of command.arguments) { const name = arg.required ? arg.name : `${arg.name} [value]`; cmd.argument(name, arg.description, arg.defaultValue); } } if (command.options && command.options.length > 0) { for (const opt of command.options) { if (opt.defaultValue !== void 0) { if (typeof opt.defaultValue === "number") { cmd.option(opt.flags, opt.description || "", (value) => Number(value), opt.defaultValue); } else { cmd.option(opt.flags, opt.description || "", opt.defaultValue); } } else { cmd.option(opt.flags, opt.description || ""); } } } if (command.action) { cmd.action(async (...args) => { try { await command.action(...args); } catch (err) { this.handleError(err, command); throw err; } }); } if (command.subcommands && command.subcommands.length > 0) { for (const subcommand of command.subcommands) { this.setupCommand(subcommand, path); } } } /** * 注册领域命令 * * @deprecated 此方法已弃用,请使用setupCommand直接注册命令。提供此方法仅为向后兼容。 * @param domain 领域名称 * @param commands 命令定义数组 */ setupDomainCommands(domain, commands) { for (const command of commands) { this.setupCommand({ ...command, category: domain }); } } /** * 显示CLI帮助信息 */ showHelp() { console.log(`dpml - Deepractice\u63D0\u793A\u8BCD\u6807\u8BB0\u8BED\u8A00`); console.log(`\u7248\u672C: ${this.program.version()}`); console.log(`\u7528\u6CD5: dpml [\u9009\u9879] [\u547D\u4EE4]`); console.log(` \u53EF\u7528\u547D\u4EE4:`); const domainCommands = /* @__PURE__ */ new Map(); const standaloneCommands = []; this.program.commands.forEach((cmd) => { const isDomainCommand = this.program.commands.some((otherCmd) => otherCmd.commands && otherCmd.commands.some((subCmd) => subCmd.name() === cmd.name())); if (!isDomainCommand && cmd.commands && cmd.commands.length > 0) { domainCommands.set(cmd.name(), cmd.commands); } else if (cmd.name() !== "help") { standaloneCommands.push(cmd); } }); if (domainCommands.size > 0) { console.log(` \u9886\u57DF\u547D\u4EE4:`); for (const [domain, commands] of domainCommands.entries()) { console.log(` ${domain.padEnd(12)} ${domain}\u9886\u57DF\u547D\u4EE4\u96C6\u5408`); } console.log(""); } for (const [domain, commands] of domainCommands.entries()) { console.log(` ${domain}\u9886\u57DF\u547D\u4EE4:`); for (const cmd of commands) { console.log(` ${domain} ${cmd.name().padEnd(10)} ${cmd.description()}`); } console.log(""); } if (standaloneCommands.length > 0) { console.log(` \u901A\u7528\u547D\u4EE4:`); for (const cmd of standaloneCommands) { console.log(` ${cmd.name().padEnd(15)} ${cmd.description()}`); } console.log(""); } const helpCommand = this.program.commands.find((cmd) => cmd.name() === "help"); if (helpCommand) { console.log(` ${helpCommand.name().padEnd(15)} ${helpCommand.description()}`); } console.log(` \u83B7\u53D6\u547D\u4EE4\u5E2E\u52A9: dpml <\u547D\u4EE4> --help dpml <\u9886\u57DF> <\u547D\u4EE4> --help`); } /** * 显示版本信息 */ showVersion() { const version = this.program.version(); console.log(`dpml \u7248\u672C: ${version}`); console.log(`Node.js \u7248\u672C: ${process.version}`); console.log(`\u5E73\u53F0: ${process.platform} ${process.arch}`); } /** * 解析命令行参数 * * @param argv 命令行参数数组,默认为process.argv */ async parse(argv) { try { await this.program.parseAsync(argv || process.argv); } catch (err) { if (err && typeof err === "object" && "code" in err) { const code = err.code; if (code === "commander.helpDisplayed" || code === "commander.version") { return; } } if (process.env.NODE_ENV === "test" || process.env.VITEST) { return; } throw err; } } /** * 查找父命令 * * @param parentPath 父命令路径 * @returns 父命令对象 * @private */ findParentCommand(parentPath) { const parts = parentPath.split(" "); let currentCommand = this.program; for (const part of parts) { if (!part) continue; const found = currentCommand.commands.find((cmd) => cmd.name() === part); if (!found) { throw new Error(`\u627E\u4E0D\u5230\u547D\u4EE4: ${part} (\u5728\u8DEF\u5F84 ${parentPath} \u4E2D)`); } currentCommand = found; } return currentCommand; } /** * 处理命令执行错误 * * @param error 捕获的错误 * @param command 相关的命令定义(可选) */ handleError(error, command) { console.error(`\u6267\u884C\u9519\u8BEF: ${error.message}`); if (error.name === "ValidationError") { console.error("\u9A8C\u8BC1\u9519\u8BEF: \u8BF7\u68C0\u67E5\u8F93\u5165\u53C2\u6570\u662F\u5426\u7B26\u5408\u8981\u6C42"); } else if (error.name === "CommandError") { console.error("\u547D\u4EE4\u9519\u8BEF: \u547D\u4EE4\u6267\u884C\u5931\u8D25"); } else if (error.message.includes("Missing required argument")) { console.error("\u53C2\u6570\u9519\u8BEF: \u7F3A\u5C11\u5FC5\u9700\u7684\u53C2\u6570"); if (command) { console.error(`\u547D\u4EE4 "${command.name}" \u9700\u8981\u4EE5\u4E0B\u53C2\u6570:`); command.arguments?.filter((arg) => arg.required).forEach((arg) => { console.error(` - ${arg.name}: ${arg.description}`); }); } } else if (error.message.includes("option")) { console.error("\u9009\u9879\u9519\u8BEF: \u9009\u9879\u683C\u5F0F\u6216\u503C\u65E0\u6548"); } if (command) { console.error(` \u5C1D\u8BD5\u4F7F\u7528 --help \u9009\u9879\u67E5\u770B\u547D\u4EE4 "${command.name}" \u7684\u5E2E\u52A9\u4FE1\u606F`); } else { console.error("\n\u5C1D\u8BD5\u4F7F\u7528 --help \u9009\u9879\u67E5\u770B\u53EF\u7528\u547D\u4EE4"); } if (process.env.NODE_ENV !== "test" && !process.env.VITEST) { process.exit(1); } } }; __name(_CLIAdapter, "CLIAdapter"); var CLIAdapter = _CLIAdapter; // src/core/cli/cliService.ts function createCLI(options, commands) { const mergedOptions = mergeDefaultOptions(options); validateCommands(commands); const adapter = new CLIAdapter(mergedOptions.name, mergedOptions.version, mergedOptions.description); setupGlobalOptions(adapter, mergedOptions); setupUserCommands(adapter, commands); return { execute: /* @__PURE__ */ __name(async (argv) => { try { await adapter.parse(argv); } catch (error) { if (error && typeof error === "object" && "code" in error) { const code = error.code; if (code === "commander.helpDisplayed" || code === "commander.help" || code === "commander.version") { return; } } console.error("Command execution error:", error); if (process.env.NODE_ENV !== "test" && !process.env.VITEST) { process.exit(1); } throw error; } }, "execute"), showHelp: /* @__PURE__ */ __name(() => adapter.showHelp(), "showHelp"), showVersion: /* @__PURE__ */ __name(() => adapter.showVersion(), "showVersion"), registerCommands: /* @__PURE__ */ __name((externalCommands) => { validateCommands(externalCommands); registerExternalCommands(adapter, externalCommands); }, "registerCommands") }; } __name(createCLI, "createCLI"); function setupGlobalOptions(adapter, options) { console.log(`CLI initialized: ${options.name} v${options.version}`); console.log(`Default domain: ${options.defaultDomain}`); } __name(setupGlobalOptions, "setupGlobalOptions"); function setupUserCommands(adapter, commands) { const domainCommands = /* @__PURE__ */ new Map(); commands.forEach((command) => { const domain = command.category || "default"; if (!domainCommands.has(domain)) { domainCommands.set(domain, []); } domainCommands.get(domain).push(command); }); domainCommands.forEach((cmds, domain) => { if (domain === "default") { cmds.forEach((cmd) => adapter.setupCommand(cmd)); return; } const domainCommand = { name: domain, description: `Commands for ${domain} domain`, action: /* @__PURE__ */ __name(() => { console.log(` Available commands for ${domain} domain:`); cmds.forEach((cmd) => { console.log(` ${domain} ${cmd.name.padEnd(10)} ${cmd.description}`); }); console.log(` Use 'dpml ${domain} --help' for more information`); }, "action") }; adapter.setupCommand(domainCommand); cmds.forEach((cmd) => { const { category, ...cmdWithoutCategory } = cmd; adapter.setupCommand(cmdWithoutCategory, domain); }); if (domain === "core") { cmds.forEach((cmd) => { cmd.name; adapter.setupCommand({ ...cmd, category: void 0, description: `${cmd.description} (Alias for core domain command)` }); }); } }); } __name(setupUserCommands, "setupUserCommands"); function registerExternalCommands(adapter, commands) { const domainCommands = /* @__PURE__ */ new Map(); commands.forEach((command) => { const domain = command.category || "default"; if (!domainCommands.has(domain)) { domainCommands.set(domain, []); } domainCommands.get(domain).push(command); }); domainCommands.forEach((cmds, domain) => { if (domain === "default") { cmds.forEach((cmd) => adapter.setupCommand(cmd)); return; } cmds.forEach((cmd) => { const { category, ...cmdWithoutCategory } = cmd; adapter.setupCommand(cmdWithoutCategory, domain); }); }); } __name(registerExternalCommands, "registerExternalCommands"); // src/api/cli.ts function createCLI2(options, commands) { return createCLI(options, commands); } __name(createCLI2, "createCLI"); // src/types/ParseError.ts var ParseErrorCode = /* @__PURE__ */ function(ParseErrorCode2) { ParseErrorCode2["UNKNOWN_ERROR"] = "PARSE_UNKNOWN_ERROR"; ParseErrorCode2["INVALID_CONTENT"] = "PARSE_INVALID_CONTENT"; ParseErrorCode2["XML_SYNTAX_ERROR"] = "PARSE_XML_SYNTAX_ERROR"; ParseErrorCode2["XML_INVALID_TAG"] = "PARSE_XML_INVALID_TAG"; ParseErrorCode2["XML_MISSING_CLOSING_TAG"] = "PARSE_XML_MISSING_CLOSING_TAG"; ParseErrorCode2["XML_INVALID_ATTRIBUTE"] = "PARSE_XML_INVALID_ATTRIBUTE"; ParseErrorCode2["DPML_INVALID_STRUCTURE"] = "PARSE_DPML_INVALID_STRUCTURE"; ParseErrorCode2["DPML_INVALID_TAG"] = "PARSE_DPML_INVALID_TAG"; ParseErrorCode2["DPML_INVALID_ATTRIBUTE"] = "PARSE_DPML_INVALID_ATTRIBUTE"; ParseErrorCode2["DPML_MISSING_REQUIRED_TAG"] = "PARSE_DPML_MISSING_REQUIRED_TAG"; ParseErrorCode2["DPML_MISSING_REQUIRED_ATTRIBUTE"] = "PARSE_DPML_MISSING_REQUIRED_ATTRIBUTE"; return ParseErrorCode2; }({}); var _ParseError = class _ParseError extends Error { /** * 创建解析错误实例 * @param message 错误消息 * @param code 错误代码 * @param position 位置信息 * @param source 源代码片段 * @param cause 原始错误 */ constructor(message, code = "PARSE_UNKNOWN_ERROR", position, source, cause) { super(message); /** * 错误代码 */ __publicField(this, "code"); /** * 错误位置信息 */ __publicField(this, "position"); /** * 源代码片段 */ __publicField(this, "source"); /** * 原始错误 */ __publicField(this, "cause"); this.name = this.constructor.name; this.code = code; this.position = position; this.source = source; this.cause = cause; Object.setPrototypeOf(this, _ParseError.prototype); } /** * 格式化错误信息,包含位置和上下文 * @returns 格式化的错误信息 */ formatMessage() { let formattedMessage = `[${this.code}] ${this.message}`; if (this.position) { const { startLine, startColumn, fileName } = this.position; const location = fileName ? `${fileName}:${startLine}:${startColumn}` : `\u884C ${startLine}, \u5217 ${startColumn}`; formattedMessage += ` \u4F4D\u7F6E: ${location}`; } if (this.source) { formattedMessage += ` \u6E90\u7801: "${this.source}"`; } if (this.cause instanceof Error) { formattedMessage += ` \u539F\u56E0: ${this.cause.message}`; } return formattedMessage; } /** * 重写toString方法,提供更详细的错误信息 * @returns 格式化的错误字符串 */ toString() { return this.formatMessage(); } }; __name(_ParseError, "ParseError"); var ParseError = _ParseError; var _XMLParseError = class _XMLParseError extends ParseError { /** * 创建XML解析错误实例 * @param message 错误消息 * @param code 错误代码 * @param position 位置信息 * @param source 源代码片段 * @param cause 原始错误 */ constructor(message, code = "PARSE_XML_SYNTAX_ERROR", position, source, cause) { super(message, code, position, source, cause); /** * 错误上下文片段 * 包含错误位置附近的内容 */ __publicField(this, "contextFragment"); Object.setPrototypeOf(this, _XMLParseError.prototype); } /** * 从原始XML解析错误创建XMLParseError * @param error 原始错误 * @param content XML内容 * @param fileName 文件名 * @returns XML解析错误 */ static fromError(error, content, fileName) { const message = error instanceof Error ? error.message : String(error); const position = _XMLParseError.extractPositionFromMessage(message, fileName); const source = content ? position ? _XMLParseError.extractSourceSnippet(content, position.startLine, position.startColumn) : content.substring(0, Math.min(30, content.length)) : void 0; return new _XMLParseError(message, "PARSE_XML_SYNTAX_ERROR", position, source, error); } /** * 从错误消息中提取位置信息 * @param message 错误消息 * @param fileName 文件名 * @returns 源码位置信息或undefined */ static extractPositionFromMessage(message, fileName) { const lineColMatch = message.match(/[Ll]ine[:\s]+(\d+)[\s,]+[Cc]olumn[:\s]+(\d+)/); if (lineColMatch) { const startLine = parseInt(lineColMatch[1], 10); const startColumn = parseInt(lineColMatch[2], 10); return { startLine, startColumn, endLine: startLine, endColumn: startColumn + 1, fileName }; } return void 0; } /** * 从内容中提取源代码片段 * @param content 完整内容 * @param line 行号 * @param column 列号 * @returns 源代码片段 */ static extractSourceSnippet(content, line, column) { const lines = content.split("\n"); if (line <= 0 || line > lines.length) { return ""; } const errorLine = lines[line - 1]; const start = Math.max(0, column - 15); const end = Math.min(errorLine.length, column + 15); return errorLine.substring(start, end); } /** * 格式化错误信息,包含位置和上下文 * @returns 格式化的错误信息 */ formatMessage() { let formattedMessage = super.formatMessage(); if (this.contextFragment) { formattedMessage += ` \u4E0A\u4E0B\u6587: "${this.contextFragment}"`; } return formattedMessage; } }; __name(_XMLParseError, "XMLParseError"); var XMLParseError = _XMLParseError; var _DPMLParseError = class _DPMLParseError extends ParseError { /** * 创建DPML解析错误实例 * @param message 错误消息 * @param code 错误代码 * @param position 位置信息 * @param source 源代码片段 * @param cause 原始错误 */ constructor(message, code = "PARSE_DPML_INVALID_STRUCTURE", position, source, cause) { super(message, code, position, source, cause); Object.setPrototypeOf(this, _DPMLParseError.prototype); } /** * 创建缺少必需标签的错误 * @param tagName 标签名 * @param position 位置信息 * @returns DPML解析错误 */ static createMissingRequiredTagError(tagName, position) { return new _DPMLParseError(`\u7F3A\u5C11\u5FC5\u9700\u7684\u6807\u7B7E: ${tagName}`, "PARSE_DPML_MISSING_REQUIRED_TAG", position); } /** * 创建缺少必需属性的错误 * @param attributeName 属性名 * @param tagName 标签名 * @param position 位置信息 * @returns DPML解析错误 */ static createMissingRequiredAttributeError(attributeName, tagName, position) { return new _DPMLParseError(`\u6807\u7B7E <${tagName}> \u7F3A\u5C11\u5FC5\u9700\u7684\u5C5E\u6027: ${attributeName}`, "PARSE_DPML_MISSING_REQUIRED_ATTRIBUTE", position); } /** * 创建无效标签错误 * @param tagName 标签名 * @param position 位置信息 * @returns DPML解析错误 */ static createInvalidTagError(tagName, position) { return new _DPMLParseError(`\u65E0\u6548\u7684DPML\u6807\u7B7E: ${tagName}`, "PARSE_DPML_INVALID_TAG", position); } /** * 创建无效属性错误 * @param attributeName 属性名 * @param tagName 标签名 * @param position 位置信息 * @returns DPML解析错误 */ static createInvalidAttributeError(attributeName, tagName, position) { return new _DPMLParseError(`\u6807\u7B7E <${tagName}> \u5305\u542B\u65E0\u6548\u7684\u5C5E\u6027: ${attributeName}`, "PARSE_DPML_INVALID_ATTRIBUTE", position); } }; __name(_DPMLParseError, "DPMLParseError"); var DPMLParseError = _DPMLParseError; // src/types/TransformContext.ts var _TransformContext = class _TransformContext { /** * 创建上下文实例 * @param processingResult 原始处理结果 * @param initialData 可选的初始数据 */ constructor(processingResult, initialData) { /** * 存储上下文数据的内部Map */ __publicField(this, "data"); /** * 原始处理结果引用 */ __publicField(this, "processingResult"); this.processingResult = processingResult; this.data = /* @__PURE__ */ new Map(); if (initialData) { Object.entries(initialData).forEach(([key, value]) => { this.data.set(key, value); }); } } /** * 类型安全的数据存储 * @template T 值的类型 * @param key 存储键 * @param value 存储值 */ set(key, value) { this.data.set(key, value); } /** * 类型安全的数据获取 * @template T 期望的返回类型 * @param key 获取键 * @returns 获取的值,若不存在则返回undefined */ get(key) { return this.data.get(key); } /** * 检查键是否存在 * @param key 检查键 * @returns 是否存在 */ has(key) { return this.data.has(key); } /** * 获取原始文档 * @returns 文档对象 */ getDocument() { return this.processingResult.document; } /** * 获取引用关系 * @returns 引用映射 */ getReferences() { return this.processingResult.references; } /** * 获取验证结果 * @returns 验证结果对象 */ getValidation() { return this.processingResult.validation; } /** * 检查文档有效性 * @returns 是否有效 */ isDocumentValid() { return this.processingResult.isValid; } /** * 获取所有结果 * @returns 所有存储的数据 */ getAllResults() { const results = {}; this.data.forEach((value, key) => { results[key] = value; }); return results; } }; __name(_TransformContext, "TransformContext"); var TransformContext = _TransformContext; // src/types/FrameworkError.ts var _ConfigurationError = class _ConfigurationError extends Error { /** * 创建配置错误实例 * @param message 错误消息 */ constructor(message) { super(message); this.name = "ConfigurationError"; Object.setPrototypeOf(this, _ConfigurationError.prototype); } }; __name(_ConfigurationError, "ConfigurationError"); var ConfigurationError = _ConfigurationError; var _CompilationError = class _CompilationError extends Error { /** * 创建编译错误实例 * @param message 错误消息 * @param cause 可选的原始错误 */ constructor(message, cause) { super(message); __publicField(this, "cause"); this.cause = cause; this.name = "CompilationError"; Object.setPrototypeOf(this, _CompilationError.prototype); } }; __name(_CompilationError, "CompilationError"); var CompilationError = _CompilationError; // src/types/log.ts var LogLevel = /* @__PURE__ */ function(LogLevel2) { LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG"; LogLevel2[LogLevel2["INFO"] = 1] = "INFO"; LogLevel2[LogLevel2["WARN"] = 2] = "WARN"; LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR"; LogLevel2[LogLevel2["FATAL"] = 4] = "FATAL"; return LogLevel2; }({}); // src/types/CLIErrors.ts var _DuplicateCommandError = class _DuplicateCommandError extends Error { /** * 创建命令重复错误实例 * @param commandPath 重复命令的路径 */ constructor(commandPath) { super(`Duplicate command definition: ${commandPath}`); __publicField(this, "commandPath"); this.commandPath = commandPath; this.name = "DuplicateCommandError"; Object.setPrototypeOf(this, _DuplicateCommandError.prototype); } }; __name(_DuplicateCommandError, "DuplicateCommandError"); var DuplicateCommandError = _DuplicateCommandError; var _InvalidCommandError = class _InvalidCommandError extends Error { /** * 创建无效命令错误实例 * @param message 错误消息 * @param commandName 命令名称 */ constructor(message, commandName) { super(commandName ? `Invalid command "${commandName}": ${message}` : message); __publicField(this, "commandName"); this.commandName = commandName; this.name = "InvalidCommandError"; Object.setPrototypeOf(this, _InvalidCommandError.prototype); } }; __name(_InvalidCommandError, "InvalidCommandError"); var InvalidCommandError = _InvalidCommandError; var _CommandExecutionError = class _CommandExecutionError extends Error { /** * 创建命令执行错误实例 * @param message 错误消息 * @param commandPath 命令路径 * @param cause 原始错误 */ constructor(message, commandPath, cause) { super(`Error executing command "${commandPath}": ${message}`); __publicField(this, "commandPath"); __publicField(this, "cause"); this.commandPath = commandPath, this.cause = cause; this.name = "CommandExecutionError"; Object.setPrototypeOf(this, _CommandExecutionError.prototype); } }; __name(_CommandExecutionError, "CommandExecutionError"); var CommandExecutionError = _CommandExecutionError; // src/core/parsing/errors.ts function createSuccessResult(data, warnings = []) { return { success: true, data, warnings: warnings.length > 0 ? warnings : void 0 }; } __name(createSuccessResult, "createSuccessResult"); function createErrorResult(error) { return { success: false, error }; } __name(createErrorResult, "createErrorResult"); // src/core/parsing/DPMLAdapter.ts var _DPMLAdapter = class _DPMLAdapter { /** * 创建适配器并注入依赖 * @param options 解析配置选项 * @param xmlAdapter XML适配器实例 */ constructor(options, xmlAdapter) { /** * XML适配器实例 */ __publicField(this, "xmlAdapter"); /** * 解析配置选项 */ __publicField(this, "options"); this.options = options || {}; this.xmlAdapter = xmlAdapter; } /** * 解析DPML内容,构建文档对象模型 * @param content DPML内容字符串 * @returns DPML文档对象 * @throws {DPMLParseError|XMLParseError} 当解析失败时抛出 */ parse(content) { try { this.prevalidateXML(content); const isLargeContent = this.isLargeContent(content); const xmlResult = this.xmlAdapter.parse(content); this.validateXMLResult(xmlResult, content); const rootNode = isLargeContent ? this.convertToDPMLOptimized(xmlResult) : this.convertToDPML(xmlResult); const document = this.createDPMLDocument(rootNode); return document; } catch (error) { throw this.enhanceError(error, content); } } /** * 异步解析DPML内容 * @param content DPML内容字符串 * @returns DPML文档对象Promise * @throws {DPMLParseError|XMLParseError} 当解析失败时抛出 */ async parseAsync(content) { try { this.prevalidateXML(content); const isLargeContent = this.isLargeContent(content); const xmlResult = await this.xmlAdapter.parseAsync(content); this.validateXMLResult(xmlResult, content); let rootNode; if (isLargeContent) { rootNode = await this.convertToDPMLAsyncOptimized(xmlResult); } else { rootNode = await new Promise((resolve) => { setTimeout(() => { resolve(this.convertToDPML(xmlResult)); }, 0); }); } const document = this.createDPMLDocument(rootNode); return document; } catch (error) { throw this.enhanceError(error, content); } } /** * 预验证XML有效性 * 检查常见的XML语法错误,如未关闭的标签 * @param content XML内容 */ prevalidateXML(content) { if (!content || content.trim() === "") { throw new DPMLParseError("\u7A7A\u7684DPML\u5185\u5BB9", ParseErrorCode.DPML_INVALID_STRUCTURE, { startLine: 1, startColumn: 1, endLine: 1, endColumn: 1, fileName: this.options.fileName }, content); } const openTagPattern = /<([a-zA-Z][\w:\-\.]*)[^>]*?>/g; const closeTagPattern = /<\/([a-zA-Z][\w:\-\.]*)[^>]*?>/g; const selfClosingPattern = /<([a-zA-Z][\w:\-\.]*)[^>]*?\/>/g; const openTags = []; const closeTags = []; const selfClosingTags = []; let match; while ((match = openTagPattern.exec(content)) !== null) { const tagName = match[1]; if (tagName) openTags.push(tagName); } while ((match = closeTagPattern.exec(content)) !== null) { const tagName = match[1]; if (tagName) closeTags.push(tagName); } while ((match = selfClosingPattern.exec(content)) !== null) { const tagName = match[1]; if (tagName) selfClosingTags.push(tagName); } if (openTags.length - selfClosingTags.length > closeTags.length) { const unclosedTags = [ ...openTags ]; for (const tag of [ ...closeTags, ...selfClosingTags ]) { const index = unclosedTags.indexOf(tag); if (index !== -1) { unclosedTags.splice(index, 1); } } if (unclosedTags.length > 0) { throw new DPMLParseError(`\u672A\u5173\u95ED\u7684\u6807\u7B7E: <${unclosedTags[0]}>`, ParseErrorCode.DPML_INVALID_STRUCTURE, void 0, content.substring(0, 100)); } } } /** * 检查内容是否为大型文档 * @param content DPML内容 * @returns 是否为大型文档 */ isLargeContent(content) { const threshold = this.options.memoryOptimization?.largeFileThreshold || 2 * 1024 * 1024; if (this.options.memoryOptimization?.enabled) { return content.length > threshold; } if (content.length > 10 * 1024 * 1024) { return true; } return content.length > threshold; } /** * 创建DPML文档对象 * @param rootNode 根节点 * @returns DPML文档对象 */ createDPMLDocument(rootNode) { const metadata = { sourceFileName: this.options.fileName, createdAt: /* @__PURE__ */ new Date(), size: this.calculateDocumentSize(rootNode) }; const nodesById = this.buildNodeMap(rootNode); this.validateReferences(rootNode, nodesById); const document = {}; Object.defineProperties(document, { rootNode: { value: rootNode, writable: false, enumerable: true, configurable: false }, nodesById: { value: nodesById, writable: false, enumerable: true, configurable: false }, metadata: { value: metadata, writable: false, enumerable: true, configurable: false } }); return document; } /** * 计算文档大小 * @param rootNode 根节点 * @returns 文档大小(节点数) */ calculateDocumentSize(rootNode) { let size = 1; const countNodes = /* @__PURE__ */ __name((node) => { if (node.children && node.children.length > 0) { size += node.children.length; node.children.forEach(countNodes); } }, "countNodes"); countNodes(rootNode); return size; } /** * 将XML节点转换为DPML节点(针对大文件优化版本) * 使用递归分批处理以避免调用栈溢出 * @param xmlNode XML节点 * @returns DPML节点 */ convertToDPMLOptimized(xmlNode) { const rootDPMLNode = this.createDPMLNode(xmlNode); const queue = []; if (xmlNode.children && xmlNode.children.length > 0) { xmlNode.children.forEach((childXml) => { const childDPML = this.createDPMLNode(childXml); rootDPMLNode.children.push(childDPML); Object.defineProperty(childDPML, "parent", { value: rootDPMLNode, writable: false, enumerable: true, configurable: false }); queue.push({ xmlNode: childXml, dpmlNode: childDPML }); }); } while (queue.length > 0) { const { xmlNode: currentXmlNode, dpmlNode: currentDPMLNode } = queue.shift(); if (currentXmlNode.children && currentXmlNode.children.length > 0) { currentXmlNode.children.forEach((childXml) => { const childDPML = this.createDPMLNode(childXml); currentDPMLNode.children.push(childDPML); Object.defineProperty(childDPML, "parent", { value: currentDPMLNode, writable: false, enumerable: true, configurable: false }); queue.push({ xmlNode: childXml, dpmlNode: childDPML }); }); } } return rootDPMLNode; } /** * 创建单个DPML节点(不递归处理子节点) * @param xmlNode XML节点 * @returns DPML节点 */ createDPMLNode(xmlNode) { const attributes = /* @__PURE__ */ new Map(); if (xmlNode.attributes) { Object.entries(xmlNode.attributes).forEach(([key, value]) => { if (value === null || value === void 0) { attributes.set(key, ""); } else { attributes.set(key, String(value)); } }); } const content = xmlNode.text !== void 0 ? String(xmlNode.text) : ""; const node = {}; Object.defineProperties(node, { tagName: { value: xmlNode.name, writable: false, enumerable: true, configurable: false }, attributes: { value: attributes, writable: false, enumerable: true, configurable: false }, children: { value: [], writable: false, enumerable: true, configurable: false }, content: { value: content, writable: false, enumerable: true, configurable: false }, parent: { value: null, writable: false, enumerable: true, configurable: true // 允许子节点重新配置该属性 }, sourceLocation: { value: xmlNode.position ? this.createSourceLocation(xmlNode.position) : void 0, writable: false, enumerable: true, configurable: false } }); return node; } /** * 异步转换XML节点到DPML节点,针对大文件优化 * @param xmlNode XML节点 * @returns Promise<DPMLNode> */ async convertToDPMLAsyncOptimized(xmlNode) { const rootDPMLNode = this.createDPMLNode(xmlNode); const queue = []; if (xmlNode.children && xmlNode.children.length > 0) { xmlNode.children.forEach((childXml) => { const childDPML = this.createDPMLNode(childXml); rootDPMLNode.children.push(childDPML); Object.defineProperty(childDPML, "parent", { value: rootDPMLNode, writable: false, enumerable: true, configurable: false }); queue.push({ xmlNode: childXml, dpmlNode: childDPML }); }); } const batchSize = 500; while (queue.length > 0) { const batch = queue.splice(0, Math.min(batchSize, queue.length)); for (const { xmlNode: currentXmlNode, dpmlNode: currentDPMLNode } of batch) { if (currentXmlNode.children && currentXmlNode.children.length > 0) { currentXmlNode.children.forEach((childXml) => { const childDPML = this.createDPMLNode(childXml); currentDPMLNode.children.push(childDPML); Object.defineProperty(childDPML, "parent", { value: currentDPMLNode, writable: false, enumerable: true, configurable: false }); queue.push({ xmlNode: childXml, dpmlNode: childDPML }); }); } } if (queue.length > 0) { await new Promise((resolve) => setTimeout(resolve, 0)); } } return rootDPMLNode; } /** * 将XML节点转换为DPML节点 * @param xmlNode XML节点 * @returns DPML节点 */ convertToDPML(xmlNode) { const dpmlNode = this.createDPMLNode(xmlNode); if (xmlNode.children && xmlNode.children.length > 0) { xmlNode.children.forEach((childXml) => { const childDPML = this.convertToDPML(childXml); dpmlNode.children.push(childDPML); Object.defineProperty(childDPML, "parent", { value: dpmlNode, writable: false, enumerable: true, configurable: false }); }); } return dpmlNode; } /** * 构建节点ID映射 * @param rootNode 根节点 * @returns 节点ID到节点的映射 */ buildNodeMap(rootNode) { const nodeMap = /* @__PURE__ */ new Map(); const traverseNode = /* @__PURE__ */ __name((node) => { const nodeId = node.attributes.get("id"); if (nodeId) { nodeMap.set(nodeId, node); } node.attributes.get("ref"); if (node.children && node.children.length > 0) { node.children.forEach(traverseNode); } }, "traverseNode"); traverseNode(rootNode); return nodeMap; } /** * 验证节点引用完整性 * @param rootNode 根节点 * @param nodeMap 节点ID映射 */ validateReferences(rootNode, nodeMap) { if (this.options.xmlParserOptions?.validateReferences === false) { return; } const checkReferences = /* @__PURE__ */ __name((node) => { const nodeRef = node.attributes.get("ref"); if (nodeRef && !nodeMap.has(nodeRef)) { throw new DPMLParseError(`\u5F15\u7528\u9519\u8BEF: \u627E\u4E0D\u5230ID\u4E3A"${nodeRef}"\u7684\u8282\u70B9`, ParseErrorCode.DPML_INVALID_ATTRIBUTE, node.sourceLocation, void 0); } if (node.children && node.children.length > 0) { node.children.forEach(checkReferences); } }, "checkReferences"); checkReferences(rootNode); } /** * 创建源代码位置信息 * @param position XML位置信息 * @returns DPML源代码位置信息 */ createSourceLocation(position) { return { startLine: position.start.line, startColumn: position.start.column, endLine: position.end.line, endColumn: position.end.column, fileName: this.options.fileName }; } /** * 验证XML解析结果 * @param xmlNode XML节点 * @param content 原始内容 */ validateXMLResult(xmlNode, content) { if (!xmlNode) { throw new DPMLParseError("\u65E0\u6CD5\u89E3\u6790DPML\u5185\u5BB9", ParseErrorCode.DPML_INVALID_STRUCTURE, void 0, content.substring(0, 100)); } if (!xmlNode.name) { throw new DPMLParseError("\u7F3A\u5C11\u6839\u5143\u7D20", ParseErrorCode.DPML_MISSING_REQUIRED_TAG, void 0, content.substring(0, 100)); } if (this.options.xmlParserOptions?.validateStructure) ; } /** * 增强错误信息 * @param error 原始错误 * @param content 原始内容 * @returns 增强后的错误 */ enhanceError(error, content) { if (error instanceof ParseError) { return error; } if (error instanceof XMLParseError) { let locationInfo = void 0; if (error.position) { const pos = error.position; locationInfo = { startLine: pos.start.line, startColumn: pos.start.column, endLine: pos.end.line, endColumn: pos.end.column, fileName: this.options.fileName }; } return new DPMLParseError(error.message, ParseErrorCode.DPML_INVALID_STRUCTURE, locationInfo, error.source, error); } return new DPMLParseError(error instanceof Error ? error.message : String(error), ParseErrorCode.UNKNOWN_ERROR, void 0, content.substring(0, 100), error instanceof Error ? error : void 0); } }; __name(_DPMLAdapter, "DPMLAdapter"); var DPMLAdapter = _DPMLAdapter; // src/core/parsing/XMLAdapter.ts var _XMLAdapter = class _XMLAdapter { /** * 创建适配器并配置选项 * @param options 解析配置选项 * @param xmlParser XML解析器实例 */ constructor(options, xmlParser) { /** * 底层XML解析器实例 */ __publicField(this, "xmlParser"); /** * 解析配置选项 */ __publicField(this, "options"); this.options = options; this.xmlParser = xmlParser; this.configureParser(); } /** * 同步解析XML内容 * @param content XML内容字符串 * @returns 解析结果 * @throws {XMLParseError} 当解析失败时抛出 */ parse(content) { try { if (this.shouldApplyLargeContentOptimization(content)) { this.applyLargeContentOptimization(); } const xmlNode = this.xmlParser.parse(content); return this.processResult(xmlNode); } catch (error) { throw this.enhanceError(error, content); } } /** * 异步解析XML内容 * @param content XML内容字符串 * @returns 解析结果Promise * @throws {XMLParseError} 当解析失败时抛出 */ async parseAsync(content) { try { if (this.shouldApplyLargeContentOptimization(content)) { this.applyLargeContentOptimization(); } const xmlNode = await this.xmlParser.parseAsync(content); return this.processResult(xmlNode); } catch (error) { throw this.enhanceError(error, content); } } /** * 检查是否应该应用大文件优化 * @param content XML内容 * @returns 是否应用优化 */ shouldApplyLargeContentOptimization(content) { const contentSizeThreshold = this.options.memoryOptimization?.largeFileThreshold || 1024 * 1024; return content.length > contentSizeThreshold; } /** * 应用大文件处理优化 */ applyLargeContentOptimization() { const optimizationOptions = { // xml2js优化选项 explicitArray: true, normalizeTags: false, trim: true, explicitRoot: true, explicitChildren: true, preserveChildrenOrder: true, mergeAttrs: false, charsAsChildren: false, includeWhiteChars: false }; if (this.options.memoryOptimization) { const { batchSize, useStreaming } = this.options.memoryOptimization; if (useStreaming) { optimizationOptions.preserveChildrenOrder = false; optimizationOptions.charsAsChildren = false; } } this.xmlParser.configure(optimizationOptions); if (typeof global !== "undefined" && global.gc) { try { global.gc(); } catch { } } } /** * 配置底层解析器行为 */ configureParser() { const xmlOptions = {}; if (this.options.xmlParserOptions) { const { preserveWhitespace, parseComments, enableNamespaces, maxDepth } = this.options.xmlParserOptions; if (preserveWhitespace !== void 0) { xmlOptions.trim = !preserveWhitespace; xmlOptions.includeWhiteChars = preserveWhitespace; } if (parseComments !== void 0) { xmlOptions.includeWhiteChars = parseComments; } if (enableNamespaces !== void 0) { xmlOptions.xmlns = enableNamespaces; } } this.xmlParser.configure(xmlOptions); } /** * 处理解析结果 * @param xmlNode XML节点结果 * @returns 处理后的结果 */ processResult(xmlNode) { try { this.validateNode(xmlNode); const processedNode = this.postProcessNode(xmlNode); return processedNode; } catch (error) { throw error instanceof Error ? error : new Error(String(error)); } } /** * 验证XML节点 * @param node XML节点 */ validateNode(node) { if (!node) { throw new Error("\u89E3\u6790\u7ED3\u679C\u4E3A\u7A7A"); } if (node.type !== "element") { throw new Error(`\u65E0\u6548\u7684XML\u8282\u70B9\u7C7B\u578B\uFF1A${node.type}`); } } /** * 后处理XML节点 * @param node XML节点 * @returns 处理后的节点 */ postProcessNode(node) { const clone = this.cloneNode(node); this.normalizeAttributes(clone); this.normalizeTextContent(clone); return clone; } /** * 深度克隆XML节点 * @param node 原始节点 * @returns 克隆的节点 */ cloneNode(node) { if (!node) return node; const clone = { type: node.type, name: node.name, attributes: { ...node.attributes }, children: node.children ? node.children.map((child) => this.cloneNode(child)) : [], text: node.text, position: node.position ? { start: { ...node.position.start }, end: { ...node.position.end } } : void 0 }; return clone; } /** * 规范化属性值 * @param node XML节点 */ normalizeAttributes(node) { if (!node.attributes) node.attributes = {}; Object.keys(node.attributes).forEach((key) => { if (node.attributes[key] === null || node.attributes[key] === void 0) { node.attributes[key] = ""; } else if (typeof node.attributes[key] !== "string") { node.attributes[key] = String(node.attributes[key]); } }); if (node.children && node.children.length > 0) { node.children.forEach((child) => this.normalizeAttributes(child)); } } /** * 规范化文本内容 * @param node XML节点 */ normalizeTextContent(node) { if (node.text !== void 0 && node.text !== null && typeof node.text !== "string") { node.text = String(node.text); } if (node.children && node.children.length > 0) { node.children.forEach((child) => this.normalizeTextContent(child)); } } /** * 增强错误信息 * @param error 原始错误 * @param content XML内容 * @returns 增强后的错误 */ enhanceError(error, content) { if (error instanceof XMLParseError) { return error; } const enhancedError = XMLParseError.fromError(error, content, this.options.fileName); if (content && content.length > 0) { try { let errorPosition = 0; if (error instanceof Error) { const posMatch = error.message.match(/line\s*(\d+)(?:,|\s+column\s+)(\d+)/i); if (posMatch) { const line = parseInt(posMatch[1], 10); const column = parseInt(posMatch[2], 10); const lines = content.split("\n"); let offset = 0; for (let i = 0; i < Math.min(line - 1, lines.length); i++) { offset += lines[i].length + 1; } errorPosition = offset + Math.min(column, lines[Math.min(line - 1, lines.length - 1)].length); } } const start = Math.max(0, errorPosition - 40); const end = Math.min(content.length, errorPosition + 40); const snippet = content.substring(start, end); enhancedError.contextFragment = snippet; } catch { } } return enhancedError; } }; __name(_XMLAdapter, "XMLAdapter"); var XMLAdapter = _XMLAdapter; var _XMLParser = class _XMLParser { /** * 创建XML解析器 */ constructor() { /** * 底层XML解析器实例 */ __publicField(this, "parser"); /** * 解析器选项 */ __publicField(this, "parserOptions", { explicitArray: true, explicitChildren: false, mergeAttrs: false, attrkey: "$", charkey: "_", includeWhiteChars: false, trim: true, explicitRoot: true, preserveChildrenOrder: true, charsAsChildren: true, normalizeTags: false, normalize: true, xmlns: false, // @ts-expect-error - 类型定义中可能没有这个属性,但实际支持 emptyTag: null }); this.parser = new xml2js.Parser(this.parserOptions); } /** * 同步解析XML内容 * @param content XML内容字符串 * @returns 解析结果 */ parse(content) { try { let result; xml2js.parseString(content, this.parserOptions, (err, parsed) => { if (err) throw err; result = parsed; }); if (!result) { throw new Error("XML\u89E3\u6790\u5931\u8D25"); } return this.transformToXMLNode(result, content); } catch (error) { throw this.enhanceError(error, content); } } /** * 异步解析XML内容 * @param content XML内容字符串 * @returns 解析结果Promise */ async parseAsync(content) { try { const result = await this.parser.parseStringPromise(content); return this.transformToXMLNode(result, content); } catch (error) { throw this.enhanceError(error, content); } } /** * 配置解析器行为 * @param options 配置选项 */ configure(options) { const xml2jsOptions = {}; if (options.trimValues !== void 0) { xml2jsOptions.trim = options.trimValues; } if (options.ignoreAttributes !== void 0) { xml2jsOptions.ignoreAttrs = options.ignoreAttributes; } if (options.parseTagValue !== void 0) { xml2jsOptions.explicitChildren = !options.parseTagValue; } if (options.processEntities !== void 0) { xml2jsOptions.normalize = options.processEntities; } this.parserOptions = { ...this.parserOptions, ...xml2jsOptions }; this.parser = new xml2js.Parser(this.parserOptions); } /** * 将xml2js解析结果转换为统一的XMLNode格式 * @param parseResult xml2js解析结果 * @param originalContent 原始XML内容(用于位置计算) * @returns XMLNode格式的解析结果 */ transformToXMLNode(parseResult, originalContent) { const rootTagName = Object.keys(parseResult)[0]; const rootContent = parseResult[rootTagName]; return this.processNode(rootTagName, rootContent, originalContent); } /** * 处理单个节点及其子节点 * @param tagName 标签名 * @param nodeContent 节点内容 * @param originalContent 原始XML内容 * @returns 处理后的XMLNode */ processNode(tagName, nodeContent, originalContent) { const attributes = {}; let text = ""; const children = []; const content = Array.isArray(nodeContent) ? nodeContent[0] : nodeContent; if (!content) { return { type: "element", name: tagName, attributes, children: [], text: "", position: this.calculatePosition(tagName, originalContent) }; } if (content && typeof content === "object" && "$" in content) { const attrs = content.$; if (attrs && typeof attrs === "object") { Object.entries(attrs).forEach(([key, value]) => { attributes[key] = String(value); }); } } if (content && typeof content === "object" && "_" in content) { text = String(content._); } else if (typeof content === "string") { text = content; } if (!text && Array.isArray(content) && content.length > 0) { const firstItem = content[0]; if (typeof firstItem === "string") { text = firstItem; } else if (firstItem && typeof firstItem === "object" && "_" in firstItem) { text = String(firstItem._); } } if (content && typeof content === "object") { Object.keys(content).forEach((key) => { if (key === "$" || key === "_") return; const childItems = content[key]; if (Array.isArray(childItems)) { childItems.forEach((childItem) => { const childNode = this.processNode(key, [ childItem ], originalContent); children.push(childNode); }); } }); } return { type: "element", name: tagName, attributes, children, text, position: th