@ahoo-wang/fetcher-generator 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +100 -96
- package/dist/index.js.map +1 -1
- package/dist/model/modelGenerator.d.ts +2 -0
- package/dist/model/modelGenerator.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/components.ts","../src/utils/naming.ts","../src/utils/resources.ts","../src/utils/openAPIParser.ts","../src/utils/references.ts","../src/utils/responses.ts","../src/utils/operations.ts","../src/utils/schemas.ts","../src/utils/sourceFiles.ts","../src/aggregate/utils.ts","../src/aggregate/aggregateResolver.ts","../src/model/wowTypeMapping.ts","../src/model/modelInfo.ts","../src/baseCodeGenerator.ts","../src/model/modelGenerator.ts","../src/client/utils.ts","../src/client/queryClientGenerator.ts","../src/client/commandClientGenerator.ts","../src/client/clientGenerator.ts","../src/index.ts"],"sourcesContent":["/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Components,\n Parameter,\n Reference,\n RequestBody,\n Response,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\n\n/** Prefix for OpenAPI components references */\nexport const COMPONENTS_PREFIX = '#/components/';\n/** Reference prefix for headers components */\nexport const COMPONENTS_HEADERS_REF = `${COMPONENTS_PREFIX}headers/`;\n/** Reference prefix for parameters components */\nexport const COMPONENTS_PARAMETERS_REF = `${COMPONENTS_PREFIX}parameters/`;\n/** Reference prefix for request bodies components */\nexport const COMPONENTS_REQUEST_BODIES_REF = `${COMPONENTS_PREFIX}requestBodies/`;\n/** Reference prefix for responses components */\nexport const COMPONENTS_RESPONSES_REF = `${COMPONENTS_PREFIX}responses/`;\n/** Reference prefix for schemas components */\nexport const COMPONENTS_SCHEMAS_REF = `${COMPONENTS_PREFIX}schemas/`;\n\n/**\n * Represents a schema with its key identifier.\n */\nexport interface KeySchema {\n /** The schema key */\n key: string;\n /** The schema definition */\n schema: Schema;\n}\n\n/**\n * Extracts the component key from an OpenAPI reference.\n * @param reference - The OpenAPI reference object\n * @returns The component key (last part of the reference path)\n */\nexport function extractComponentKey(reference: Reference): string {\n return reference.$ref.split('/').pop() as string;\n}\n\n/**\n * Extracts a schema from OpenAPI components using a reference.\n * @param reference - The reference to the schema\n * @param components - The OpenAPI components object\n * @returns The schema if found, undefined otherwise\n */\nexport function extractSchema(\n reference: Reference,\n components: Components,\n): Schema | undefined {\n const componentKey = extractComponentKey(reference);\n return components.schemas?.[componentKey];\n}\n\n/**\n * Extracts a response from OpenAPI components using a reference.\n * @param reference - The reference to the response\n * @param components - The OpenAPI components object\n * @returns The response if found, undefined otherwise\n */\nexport function extractResponse(\n reference: Reference,\n components: Components,\n): Response | undefined {\n const componentKey = extractComponentKey(reference);\n return components.responses?.[componentKey];\n}\n\n/**\n * Extracts a request body from OpenAPI components using a reference.\n * @param reference - The reference to the request body\n * @param components - The OpenAPI components object\n * @returns The request body if found, undefined otherwise\n */\nexport function extractRequestBody(\n reference: Reference,\n components: Components,\n): RequestBody | undefined {\n const componentKey = extractComponentKey(reference);\n return components.requestBodies?.[componentKey];\n}\n\n/**\n * Extracts a parameter from OpenAPI components using a reference.\n * @param reference - The reference to the parameter\n * @param components - The OpenAPI components object\n * @returns The parameter if found, undefined otherwise\n */\nexport function extractParameter(\n reference: Reference,\n components: Components,\n): Parameter | undefined {\n const componentKey = extractComponentKey(reference);\n return components.parameters?.[componentKey];\n}\n\n/**\n * Creates a KeySchema object from a reference and components.\n * @param reference - The reference to the schema\n * @param components - The OpenAPI components object\n * @returns A KeySchema containing the key and resolved schema\n */\nexport function keySchema(\n reference: Reference,\n components: Components,\n): KeySchema {\n const componentKey = extractComponentKey(reference);\n return {\n key: componentKey,\n schema: extractSchema(reference, components)!,\n };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst NAMING_SEPARATORS = /[-_\\s.]+|(?=[A-Z])/;\n\n/**\n * Converts a string or array of strings to PascalCase format.\n *\n * This function takes a string or array of strings and converts them to PascalCase format\n * by splitting the input based on common naming separators and capitalizing the first\n * letter of each part.\n *\n * @param name - A string or array of strings to convert to PascalCase\n * @returns The PascalCase formatted string\n */\nexport function pascalCase(name: string | string[]): string {\n if (name === '' || name.length === 0) {\n return '';\n }\n let names: string[];\n if (Array.isArray(name)) {\n // If input is an array, split each element by naming separators and flatten the result\n names = name.flatMap(part => part.split(NAMING_SEPARATORS));\n } else {\n // If input is a string, split it by naming separators\n names = name.split(NAMING_SEPARATORS);\n }\n return names\n .filter(part => part.length > 0)\n .map(part => {\n if (part.length === 0) return '';\n const firstChar = part.charAt(0);\n const rest = part.slice(1);\n return (\n (/[a-zA-Z]/.test(firstChar) ? firstChar.toUpperCase() : firstChar) +\n rest.toLowerCase()\n );\n })\n .join('');\n}\n\n/**\n * Converts a string or array of strings to camelCase format.\n *\n * This function first converts the input to PascalCase and then converts the first character to lowercase.\n *\n * @param name - A string or array of strings to convert to camelCase\n * @returns The camelCase formatted string\n */\nexport function camelCase(name: string | string[]): string {\n const pascalCaseName = pascalCase(name);\n return pascalCaseName.charAt(0).toLowerCase() + pascalCaseName.slice(1);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { readFile } from 'fs';\n\nexport function loadResource(path: string): Promise<string> {\n if (path.startsWith('http://') || path.startsWith('https://')) {\n return loadHttpResource(path);\n }\n return loadFile(path);\n}\n\nexport async function loadHttpResource(url: string): Promise<string> {\n const response = await fetch(url);\n return await response.text();\n}\n\nexport function loadFile(path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n readFile(path, 'utf-8', (err, data) => {\n if (err) {\n reject(err);\n } else {\n resolve(data);\n }\n });\n });\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { OpenAPI } from '@ahoo-wang/fetcher-openapi';\nimport { parse } from 'yaml';\nimport { loadResource } from './resources';\n\n/**\n * Parses an OpenAPI specification from a file path.\n *\n * @param inputPath - The path to the OpenAPI specification file\n * @returns A promise that resolves to the parsed OpenAPI object\n */\nexport async function parseOpenAPI(inputPath: string): Promise<OpenAPI> {\n const content = await loadResource(inputPath);\n const fileFormat = inferFileFormat(content);\n switch (fileFormat) {\n case FileFormat.JSON:\n return JSON.parse(content);\n case FileFormat.YAML:\n return parse(content);\n default:\n throw new Error(`Unsupported file format: ${inputPath}`);\n }\n}\n\nexport enum FileFormat {\n JSON = 'json',\n YAML = 'yaml',\n}\n\nexport function inferFileFormat(content: string): FileFormat {\n // Trim whitespace and BOM characters from the beginning\n const trimmedContent = content.trimStart();\n\n if (trimmedContent.startsWith('{') || trimmedContent.startsWith('[')) {\n return FileFormat.JSON;\n }\n\n // YAML can start with various characters, but commonly with '-' (for arrays) or '%YAML'\n // We'll check for common YAML indicators\n if (trimmedContent.startsWith('-') || trimmedContent.startsWith('%YAML')) {\n return FileFormat.YAML;\n }\n\n // Try to parse as JSON to see if it's valid JSON despite not starting with { or [\n try {\n JSON.parse(trimmedContent);\n return FileFormat.JSON;\n } catch {\n // If it's not valid JSON, we'll assume it's YAML if it's not empty\n if (trimmedContent.length > 0) {\n return FileFormat.YAML;\n }\n }\n\n throw new Error('Unable to infer file format');\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Reference } from '@ahoo-wang/fetcher-openapi';\n\nexport function isReference(schema: any): schema is Reference {\n return !!(schema && typeof schema === 'object' && '$ref' in schema);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Reference, Schema, Response } from '@ahoo-wang/fetcher-openapi';\nimport { ContentTypeValues } from '@ahoo-wang/fetcher';\nimport { isReference } from './references';\n\n/**\n * Extracts the JSON schema from an OK response.\n * @param okResponse - The response object or reference\n * @returns The JSON schema from the response content or undefined if not found\n */\nexport function extractOkResponseJsonSchema(\n okResponse?: Response | Reference,\n): Schema | Reference | undefined {\n if (!okResponse) {\n return;\n }\n if (isReference(okResponse)) {\n return undefined;\n }\n\n if (!okResponse.content) {\n return undefined;\n }\n const jsonContent = okResponse.content[ContentTypeValues.APPLICATION_JSON];\n return jsonContent?.schema;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n HTTPMethod,\n Operation,\n PathItem,\n Reference,\n Response,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\nimport { extractOkResponseJsonSchema } from './responses';\n\n/**\n * Represents an HTTP method and its associated operation.\n */\nexport interface MethodOperation {\n /** The HTTP method */\n method: HTTPMethod;\n /** The OpenAPI operation */\n operation: Operation;\n}\n\n/**\n * Extracts all operations from a path item.\n * @param pathItem - The OpenAPI path item\n * @returns Array of method-operation pairs\n */\nexport function extractOperations(pathItem: PathItem): MethodOperation[] {\n return [\n { method: 'get', operation: pathItem.get },\n { method: 'put', operation: pathItem.put },\n { method: 'post', operation: pathItem.post },\n { method: 'delete', operation: pathItem.delete },\n { method: 'options', operation: pathItem.options },\n { method: 'head', operation: pathItem.head },\n { method: 'patch', operation: pathItem.patch },\n { method: 'trace', operation: pathItem.trace },\n ].filter(({ operation }) => operation !== undefined) as Array<{\n method: HTTPMethod;\n operation: Operation;\n }>;\n}\n\n/**\n * Extracts the OK (200) response from an operation.\n * @param operation - The OpenAPI operation\n * @returns The 200 response or undefined if not found\n */\nexport function extractOkResponse(\n operation: Operation,\n): Response | Reference | undefined {\n return operation.responses['200'];\n}\n\n/**\n * Extracts the JSON schema from the OK response of an operation.\n * @param operation - The OpenAPI operation\n * @returns The JSON schema from the OK response or undefined if not found\n */\nexport function extractOperationOkResponseJsonSchema(\n operation: Operation,\n): Schema | Reference | undefined {\n const okResponse = extractOkResponse(operation);\n return extractOkResponseJsonSchema(okResponse);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Schema, SchemaType } from '@ahoo-wang/fetcher-openapi';\n\n/** List of primitive schema types */\nconst PRIMITIVE_TYPES: SchemaType[] = [\n 'string',\n 'number',\n 'integer',\n 'boolean',\n 'null',\n];\n\n/**\n * Checks if a schema type is primitive.\n * @param type - The schema type to check\n * @returns True if the type is primitive, false otherwise\n */\nexport function isPrimitive(type: SchemaType | SchemaType[]): boolean {\n if (Array.isArray(type)) {\n return true;\n }\n return PRIMITIVE_TYPES.includes(type);\n}\n\n/**\n * Checks if a schema is an array type.\n * @param schema - The schema to check\n * @returns True if the schema is an array type, false otherwise\n */\nexport function isArray(schema: Schema): schema is Schema & { type: 'array' } {\n return schema.type === 'array';\n}\n\nexport type EnumSchema = Schema & { enum: any[] };\n\n/**\n * Checks if a schema represents an enum.\n * @param schema - The schema to check\n * @returns True if the schema has an enum property, false otherwise\n */\nexport function isEnum(schema: Schema): schema is EnumSchema {\n return Array.isArray(schema.enum) && schema.enum.length > 0;\n}\n\nexport type AnyOfSchema = Schema & { anyOf: any[] };\n\n/**\n * Checks if a schema is an anyOf composition.\n * @param schema - The schema to check\n * @returns True if the schema has a non-empty anyOf property, false otherwise\n */\nexport function isAnyOf(schema: Schema): schema is AnyOfSchema {\n return Array.isArray(schema.anyOf) && schema.anyOf.length > 0;\n}\n\nexport type OneOfSchema = Schema & { oneOf: any[] };\n\n/**\n * Checks if a schema is a oneOf composition.\n * @param schema - The schema to check\n * @returns True if the schema has a non-empty oneOf property, false otherwise\n */\nexport function isOneOf(schema: Schema): schema is OneOfSchema {\n return Array.isArray(schema.oneOf) && schema.oneOf.length > 0;\n}\n\nexport type UnionSchema = Schema & ({ anyOf: any[] } | { oneOf: any[] });\n\n/**\n * Checks if a schema is a union (either anyOf or oneOf).\n * @param schema - The schema to check\n * @returns True if the schema is either an anyOf or oneOf composition, false otherwise\n */\nexport function isUnion(schema: Schema): schema is UnionSchema {\n return isAnyOf(schema) || isOneOf(schema);\n}\n\nexport type AllOfSchema = Schema & { allOf: any[] };\n\n/**\n * Checks if a schema is an allOf composition.\n * @param schema - The schema to check\n * @returns True if the schema has a non-empty allOf property, false otherwise\n */\nexport function isAllOf(schema: Schema): schema is AllOfSchema {\n return Array.isArray(schema.allOf) && schema.allOf.length > 0;\n}\n\nexport type CompositionSchema = AnyOfSchema | OneOfSchema | AllOfSchema;\n\n/**\n * Checks if a schema is a composition (anyOf, oneOf, or allOf).\n * @param schema - The schema to check\n * @returns True if the schema is anyOf, oneOf, or allOf composition, false otherwise\n */\nexport function isComposition(schema: Schema): schema is CompositionSchema {\n return isAnyOf(schema) || isOneOf(schema) || isAllOf(schema);\n}\n\n/**\n * Converts a type string to an array type.\n * Wraps complex types (containing | or &) in parentheses before adding array notation.\n * @param type - The type string to convert to an array type\n * @returns The array type string\n */\nexport function toArrayType(type: string): string {\n if (type.includes('|') || type.includes('&')) {\n return `(${type})[]`;\n }\n return `${type}[]`;\n}\n\n/**\n * Resolves a schema type to its TypeScript equivalent.\n * @param type - The schema type(s) to resolve\n * @returns The TypeScript type string\n */\nexport function resolvePrimitiveType(type: SchemaType | SchemaType[]): string {\n if (Array.isArray(type)) {\n return type.map(it => resolvePrimitiveType(it)).join(' | ');\n }\n switch (type) {\n case 'string':\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n default:\n return 'any';\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JSDocableNode, Project, SourceFile } from 'ts-morph';\nimport { combineURLs } from '@ahoo-wang/fetcher';\nimport { join, relative } from 'path';\nimport { ModelInfo } from '../model';\n\n/** Default file name for model files */\nconst MODEL_FILE_NAME = 'types.ts';\n/** Alias for import paths */\nconst IMPORT_ALIAS = '@';\n\n/**\n * Generates the file path for a model file.\n * @param modelInfo - The model information\n * @returns The full file path for the model\n */\nexport function getModelFileName(modelInfo: ModelInfo): string {\n return combineURLs(modelInfo.path, MODEL_FILE_NAME);\n}\n\n/**\n * Gets or creates a source file in the project.\n * @param project - The ts-morph project\n * @param outputDir - The output directory\n * @param filePath - The relative file path\n * @returns The source file\n */\nexport function getOrCreateSourceFile(\n project: Project,\n outputDir: string,\n filePath: string,\n): SourceFile {\n const fileName = combineURLs(outputDir, filePath);\n const file = project.getSourceFile(fileName);\n if (file) {\n return file;\n }\n return project.createSourceFile(fileName, '', {\n overwrite: true,\n });\n}\n\n/**\n * Adds named imports to a source file.\n * @param sourceFile - The source file to modify\n * @param moduleSpecifier - The module to import from\n * @param namedImports - Array of named imports to add\n */\nexport function addImport(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n namedImports: string[],\n) {\n let declaration = sourceFile.getImportDeclaration(\n importDeclaration =>\n importDeclaration.getModuleSpecifierValue() === moduleSpecifier,\n );\n if (!declaration) {\n declaration = sourceFile.addImportDeclaration({\n moduleSpecifier,\n });\n }\n namedImports.forEach(namedImport => {\n const exited = declaration\n .getNamedImports()\n .some(\n existingNamedImport => existingNamedImport.getName() === namedImport,\n );\n if (exited) {\n return;\n }\n declaration.addNamedImport(namedImport);\n });\n}\n\n/**\n * Adds an import for a referenced model.\n * @param sourceFile - The source file to modify\n * @param outputDir - The output directory\n * @param refModelInfo - The referenced model information\n */\nexport function addImportRefModel(\n sourceFile: SourceFile,\n outputDir: string,\n refModelInfo: ModelInfo,\n) {\n if (refModelInfo.path.startsWith(IMPORT_ALIAS)) {\n addImport(sourceFile, refModelInfo.path, [refModelInfo.name]);\n return;\n }\n\n const sourceDir = sourceFile.getDirectoryPath();\n const targetFilePath = join(outputDir, refModelInfo.path, MODEL_FILE_NAME);\n let relativePath = relative(sourceDir, targetFilePath);\n\n relativePath = relativePath.replace(/\\.ts$/, '');\n\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath;\n }\n\n addImport(sourceFile, relativePath, [refModelInfo.name]);\n}\n\n/**\n * Adds an import for a model if it's in a different path.\n * @param currentModel - The current model information\n * @param sourceFile - The source file to modify\n * @param outputDir - The output directory\n * @param refModel - The referenced model information\n */\nexport function addImportModelInfo(\n currentModel: ModelInfo,\n sourceFile: SourceFile,\n outputDir: string,\n refModel: ModelInfo,\n) {\n if (currentModel.path === refModel.path) {\n return;\n }\n addImportRefModel(sourceFile, outputDir, refModel);\n}\n\n/**\n * Generates a JSDoc comment string from a title and description.\n * @param title - The title for the JSDoc comment\n * @param description - The description for the JSDoc comment\n * @returns The formatted JSDoc string or undefined if both title and description are empty\n */\nexport function jsDoc(\n title?: string,\n description?: string,\n): string | undefined {\n const filtered = [title, description].filter(\n v => v !== undefined && v.length > 0,\n );\n return filtered.length > 0 ? filtered.join('\\n') : undefined;\n}\n\nexport function jsDocs(title?: string, description?: string): string[] {\n const jsdoc = jsDoc(title, description);\n return jsdoc ? [jsdoc] : [];\n}\n\n/**\n * Adds a JSDoc comment to a node with the provided title and description.\n * @param node - The node to add the JSDoc comment to\n * @param title - The title for the JSDoc comment\n * @param description - The description for the JSDoc comment\n */\nexport function addJSDoc(\n node: JSDocableNode,\n title?: string,\n description?: string,\n) {\n const jsdoc = jsDoc(title, description);\n if (!jsdoc) {\n return;\n }\n node.addJsDoc({\n description: jsdoc,\n });\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Tag } from '@ahoo-wang/fetcher-openapi';\nimport { PartialBy } from '@ahoo-wang/fetcher';\nimport { AggregateDefinition, TagAliasAggregate } from './aggregate';\n\n/**\n * Checks if a tag name follows the alias aggregate pattern and extracts its components.\n *\n * This function determines if a tag name follows the format \"contextAlias.aggregateName\"\n * and returns the components if it matches.\n *\n * @param tagName - The tag name to check\n * @returns A tuple with [contextAlias, aggregateName] if the pattern matches, null otherwise\n */\nexport function isAliasAggregate(tagName: string): [string, string] | null {\n const parts = tagName.split('.');\n if (parts.length != 2 || parts[0].length === 0 || parts[1].length === 0) {\n return null;\n }\n return parts as [string, string];\n}\n\n/**\n * Converts a Tag to a TagAliasAggregate if it follows the alias pattern.\n *\n * This function checks if a tag name follows the alias aggregate pattern and\n * creates a TagAliasAggregate object with the tag and its parsed components.\n *\n * @param tag - The Tag to convert\n * @returns A TagAliasAggregate if the tag name matches the pattern, null otherwise\n */\nexport function tagToAggregate(tag: Tag): TagAliasAggregate | null {\n const parts = isAliasAggregate(tag.name);\n if (!parts) {\n return null;\n }\n\n return {\n tag,\n contextAlias: parts[0],\n aggregateName: parts[1],\n };\n}\n\n/**\n * Converts an array of Tags to a map of aggregates.\n *\n * This function processes an array of tags, converts those that follow the alias pattern\n * to aggregates, and returns a map where keys are tag names and values are partial\n * aggregate definitions.\n *\n * @param tags - Optional array of Tags to process\n * @returns A map of aggregate definitions keyed by tag name\n */\nexport function tagsToAggregates(\n tags?: Tag[],\n): Map<string, PartialBy<AggregateDefinition, 'state' | 'fields'>> {\n const tagAliasAggregates = tags\n ?.map(tag => tagToAggregate(tag))\n .filter(tag => tag !== null);\n if (!tagAliasAggregates) {\n return new Map();\n }\n const aggregates = new Map<\n string,\n PartialBy<AggregateDefinition, 'state' | 'fields'>\n >();\n tagAliasAggregates.forEach(tagAliasAggregate => {\n aggregates.set(tagAliasAggregate.tag.name, {\n aggregate: tagAliasAggregate,\n commands: new Map(),\n events: new Map(),\n });\n });\n return aggregates;\n}\n\n/**\n * Extracts the command name from an operation ID.\n *\n * This function parses an operation ID expected to follow the format\n * \"context.aggregate.command\" and returns the command part.\n *\n * @param operationId - Optional operation ID to parse\n * @returns The command name if the operation ID follows the expected format, null otherwise\n */\nexport function operationIdToCommandName(operationId?: string): string | null {\n if (!operationId) {\n return null;\n }\n const parts = operationId.split('.');\n if (parts.length != 3) {\n return null;\n }\n return parts[2];\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n OpenAPI,\n Operation,\n Parameter,\n Reference,\n RequestBody,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\nimport {\n AggregateDefinition,\n BoundedContextAggregates,\n CommandDefinition,\n EventDefinition,\n} from './aggregate';\n\nimport { ContentTypeValues, PartialBy } from '@ahoo-wang/fetcher';\nimport { operationIdToCommandName, tagsToAggregates } from './utils';\nimport {\n extractOkResponse,\n extractOperationOkResponseJsonSchema,\n extractOperations,\n extractParameter,\n extractRequestBody,\n extractSchema,\n isReference,\n keySchema,\n MethodOperation,\n} from '../utils';\nimport { EventStreamSchema } from './types';\n\nconst CommandOkResponseRef = '#/components/responses/wow.CommandOk';\nconst IdParameterRef = '#/components/parameters/wow.id';\n\n/**\n * Resolves aggregate definitions from OpenAPI specifications.\n * Parses operations to extract commands, events, and state information for each aggregate.\n */\nexport class AggregateResolver {\n private readonly aggregates: Map<\n string,\n PartialBy<AggregateDefinition, 'state' | 'fields'>\n >;\n\n /**\n * Creates a new AggregateResolver instance.\n * @param openAPI - The OpenAPI specification to resolve aggregates from\n */\n constructor(private readonly openAPI: OpenAPI) {\n this.aggregates = tagsToAggregates(openAPI.tags);\n this.build();\n }\n\n /**\n * Builds the aggregate definitions by processing all operations in the OpenAPI spec.\n * @private\n */\n private build() {\n for (const [path, pathItem] of Object.entries(this.openAPI.paths)) {\n const methodOperations = extractOperations(pathItem);\n for (const methodOperation of methodOperations) {\n this.commands(path, methodOperation);\n this.state(methodOperation.operation);\n this.events(methodOperation.operation);\n this.fields(methodOperation.operation);\n }\n }\n }\n\n /**\n * Returns the resolved aggregate definitions.\n * @returns Map of aggregate definitions keyed by context alias\n */\n resolve(): BoundedContextAggregates {\n const resolvedContextAggregates = new Map<\n string,\n Set<AggregateDefinition>\n >();\n for (const aggregate of this.aggregates.values()) {\n if (!aggregate.state || !aggregate.fields) {\n continue;\n }\n const contextAlias = aggregate.aggregate.contextAlias;\n let aggregates = resolvedContextAggregates.get(contextAlias);\n if (!aggregates) {\n aggregates = new Set<AggregateDefinition>();\n resolvedContextAggregates.set(contextAlias, aggregates);\n }\n aggregates.add(aggregate as AggregateDefinition);\n }\n return resolvedContextAggregates;\n }\n\n /**\n * Processes command operations and adds them to the appropriate aggregates.\n * @param path - The API path\n * @param methodOperation - The HTTP method and operation details\n */\n commands(path: string, methodOperation: MethodOperation) {\n const operation = methodOperation.operation;\n if (operation.operationId === 'wow.command.send') {\n return;\n }\n const commandName = operationIdToCommandName(operation.operationId);\n if (!commandName) {\n return;\n }\n const okResponse = extractOkResponse(operation);\n if (!okResponse) {\n return;\n }\n if (!isReference(okResponse)) {\n return;\n }\n if (okResponse.$ref !== CommandOkResponseRef) {\n return;\n }\n if (!operation.requestBody) {\n return;\n }\n\n const parameters = operation.parameters ?? [];\n const idRefParameter = parameters\n .filter(p => isReference(p) && p.$ref === IdParameterRef)\n .at(0) as Reference | undefined;\n const pathParameters = parameters.filter(\n p => !isReference(p) && p.in === 'path',\n ) as Parameter[];\n if (idRefParameter) {\n const idParameter = extractParameter(\n idRefParameter,\n this.openAPI.components!,\n );\n pathParameters.push(idParameter!);\n }\n const requestBody = operation.requestBody as RequestBody;\n const commandRefSchema = requestBody.content[\n ContentTypeValues.APPLICATION_JSON\n ].schema as Reference;\n const commandKeyedSchema = keySchema(\n commandRefSchema,\n this.openAPI.components!,\n );\n commandKeyedSchema.schema.title =\n commandKeyedSchema.schema.title || operation.summary;\n commandKeyedSchema.schema.description =\n commandKeyedSchema.schema.description || operation.description;\n const commandDefinition: CommandDefinition = {\n name: commandName,\n method: methodOperation.method,\n path,\n pathParameters,\n summary: operation.summary,\n description: operation.description,\n schema: commandKeyedSchema,\n operation: operation,\n };\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n aggregate.commands.set(commandName, commandDefinition);\n });\n }\n\n /**\n * Processes state snapshot operations and associates them with aggregates.\n * @param operation - The OpenAPI operation\n */\n state(operation: Operation) {\n if (!operation.operationId?.endsWith('.snapshot_state.single')) {\n return;\n }\n const stateRefSchema = extractOperationOkResponseJsonSchema(operation);\n if (!isReference(stateRefSchema)) {\n return;\n }\n const stateKeyedSchema = keySchema(\n stateRefSchema,\n this.openAPI.components!,\n );\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n aggregate.state = stateKeyedSchema;\n });\n }\n\n /**\n * Processes event stream operations and extracts domain events for aggregates.\n * @param operation - The OpenAPI operation\n */\n events(operation: Operation) {\n if (!this.openAPI.components) {\n return;\n }\n if (!operation.operationId?.endsWith('.event.list_query')) {\n return;\n }\n const eventStreamArraySchema =\n extractOperationOkResponseJsonSchema(operation);\n if (isReference(eventStreamArraySchema)) {\n return;\n }\n const eventStreamRefSchema = eventStreamArraySchema?.items;\n if (!isReference(eventStreamRefSchema)) {\n return;\n }\n const eventStreamSchema = extractSchema(\n eventStreamRefSchema,\n this.openAPI.components,\n ) as EventStreamSchema;\n\n const events: EventDefinition[] =\n eventStreamSchema.properties.body.items.anyOf.map(domainEventSchema => {\n const eventTitle = domainEventSchema.title;\n const eventName = domainEventSchema.properties.name.const;\n const eventBodySchema = domainEventSchema.properties.body;\n const eventBodyKeyedSchema = keySchema(\n eventBodySchema,\n this.openAPI.components!,\n );\n eventBodyKeyedSchema.schema.title =\n eventBodyKeyedSchema.schema.title || domainEventSchema.title;\n return {\n title: eventTitle,\n name: eventName,\n schema: eventBodyKeyedSchema,\n };\n });\n\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n events.forEach(event => {\n aggregate.events.set(event.name, event);\n });\n });\n }\n\n /**\n * Processes field query operations and associates field schemas with aggregates.\n * @param operation - The OpenAPI operation\n */\n fields(operation: Operation): void {\n if (!this.openAPI.components) {\n return;\n }\n if (!operation.operationId?.endsWith('.snapshot.count')) {\n return;\n }\n const requestBody = extractRequestBody(\n operation.requestBody as Reference,\n this.openAPI.components,\n ) as RequestBody;\n const conditionRefSchema = requestBody.content[\n ContentTypeValues.APPLICATION_JSON\n ].schema as Reference;\n const conditionSchema = extractSchema(\n conditionRefSchema,\n this.openAPI.components,\n ) as Schema;\n const fieldRefSchema = conditionSchema.properties?.field as Reference;\n const fieldKeyedSchema = keySchema(fieldRefSchema, this.openAPI.components);\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n aggregate.fields = fieldKeyedSchema;\n });\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** Import path for the WOW framework types */\nexport const IMPORT_WOW_PATH = '@ahoo-wang/fetcher-wow';\n\n/** Mapping of OpenAPI schema keys to WOW framework types */\nexport const WOW_TYPE_MAPPING = {\n 'wow.command.CommandResult': 'CommandResult',\n 'wow.MessageHeaderSqlType': 'MessageHeaderSqlType',\n 'wow.api.BindingError': 'BindingError',\n 'wow.api.DefaultErrorInfo': 'ErrorInfo',\n 'wow.api.RecoverableType': 'RecoverableType',\n 'wow.api.command.DefaultDeleteAggregate': 'DeleteAggregate',\n 'wow.api.command.DefaultRecoverAggregate': 'RecoverAggregate',\n 'wow.api.messaging.FunctionInfoData': 'FunctionInfo',\n 'wow.api.messaging.FunctionKind': 'FunctionKind',\n 'wow.api.modeling.AggregateId': 'AggregateId',\n 'wow.api.query.Condition': 'Condition',\n 'wow.api.query.ConditionOptions': 'ConditionOptions',\n 'wow.api.query.ListQuery': 'ListQuery',\n 'wow.api.query.Operator': 'Operator',\n 'wow.api.query.PagedQuery': 'PagedQuery',\n 'wow.api.query.Pagination': 'Pagination',\n 'wow.api.query.Projection': 'Projection',\n 'wow.api.query.Sort': 'FieldSort',\n 'wow.api.query.Sort.Direction': 'SortDirection',\n 'wow.command.CommandStage': 'CommandStage',\n 'wow.command.SimpleWaitSignal': 'WaitSignal',\n 'wow.configuration.Aggregate': 'Aggregate',\n 'wow.configuration.BoundedContext': 'BoundedContext',\n 'wow.configuration.WowMetadata': 'WowMetadata',\n 'wow.modeling.DomainEvent': 'DomainEvent',\n 'wow.openapi.BatchResult': 'BatchResult',\n 'wow.messaging.CompensationTarget': 'CompensationTarget',\n};\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Named } from '@ahoo-wang/fetcher-wow';\nimport { IMPORT_WOW_PATH, WOW_TYPE_MAPPING } from './wowTypeMapping';\nimport { pascalCase } from '../utils';\n\n/**\n * Data Model Info\n */\nexport interface ModelInfo extends Named {\n name: string;\n path: string;\n}\n\n/**\n * Resolves model information from a schema key.\n *\n * This function parses a dot-separated schema key and extracts the model name and path.\n * It assumes that the model name is the first part that starts with an uppercase letter.\n * All parts before the model name are treated as the path.\n *\n * @example\n *\n * - \"wow.api.BindingError\" -> {path:'/wow/api',name:'BindingError'}\n * - \"compensation.ApiVersion\" -> {path:'/compensation',name:'ApiVersion'}\n * - \"ai.AiMessage.Assistant\" -> {path:'/ai',name:'AiMessageAssistant'}\n * - \"Result\" -> {path:'/',name:'Result'}\n *\n * @param schemaKey - The dot-separated schema key (e.g., \"com.example.User\")\n * @returns ModelInfo object containing the parsed name and path\n */\nexport function resolveModelInfo(schemaKey: string): ModelInfo {\n if (!schemaKey) {\n return { name: '', path: '/' };\n }\n const mappedType =\n WOW_TYPE_MAPPING[schemaKey as keyof typeof WOW_TYPE_MAPPING];\n if (mappedType) {\n return { name: mappedType, path: IMPORT_WOW_PATH };\n }\n\n const parts = schemaKey.split('.');\n let modelNameIndex = -1;\n\n // Find the first part that starts with an uppercase letter\n for (let i = 0; i < parts.length; i++) {\n if (parts[i] && /^[A-Z]/.test(parts[i])) {\n modelNameIndex = i;\n break;\n }\n }\n\n // If no part starts with uppercase letter, treat the whole thing as the name\n if (modelNameIndex === -1) {\n return { name: schemaKey, path: '/' };\n }\n\n // Construct the path from parts before the model name\n const pathParts = parts.slice(0, modelNameIndex);\n const path = pathParts.length > 0 ? `/${pathParts.join('/')}` : '/';\n\n // Construct the model name from the remaining parts\n const nameParts = parts.slice(modelNameIndex);\n const name = pascalCase(nameParts);\n\n return { name, path };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Project } from 'ts-morph';\nimport { OpenAPI } from '@ahoo-wang/fetcher-openapi';\nimport { GenerateContext, Logger } from './types';\nimport { BoundedContextAggregates } from './aggregate';\n\nexport abstract class BaseCodeGenerator implements GenerateContext {\n /** The ts-morph project instance used for code generation */\n readonly project: Project;\n /** The OpenAPI specification object */\n readonly openAPI: OpenAPI;\n /** The output directory path for generated files */\n readonly outputDir: string;\n /** Map of bounded context aggregates for domain modeling */\n readonly contextAggregates: BoundedContextAggregates;\n /** Optional logger for generation progress and errors */\n readonly logger: Logger;\n\n /**\n * Creates a new ClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n protected constructor(context: GenerateContext) {\n this.project = context.project;\n this.openAPI = context.openAPI;\n this.outputDir = context.outputDir;\n this.contextAggregates = context.contextAggregates;\n this.logger = context.logger;\n }\n\n /**\n * Generates code based on the provided context.\n * Subclasses must implement this method to define their specific generation logic.\n */\n abstract generate(): void;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Schema, Reference } from '@ahoo-wang/fetcher-openapi';\nimport { InterfaceDeclaration, JSDocableNode, SourceFile } from 'ts-morph';\nimport { GenerateContext } from '../types';\nimport { ModelInfo, resolveModelInfo } from './modelInfo';\nimport {\n addImportModelInfo,\n addJSDoc,\n CompositionSchema,\n extractComponentKey,\n getModelFileName,\n getOrCreateSourceFile,\n isArray,\n isComposition,\n isEnum,\n isPrimitive,\n isReference,\n isUnion,\n KeySchema,\n pascalCase,\n resolvePrimitiveType,\n toArrayType,\n} from '../utils';\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\n\n/**\n * Generates TypeScript models from OpenAPI schemas.\n * Handles enum, object, union, and type alias generation.\n *\n * @property project - The ts-morph project instance\n * @property openAPI - The OpenAPI specification\n * @property outputDir - The output directory for generated files\n * @property contextAggregates - Map of aggregate definitions\n */\nexport class ModelGenerator extends BaseCodeGenerator {\n constructor(context: GenerateContext) {\n super(context);\n }\n\n private getOrCreateSourceFile(modelInfo: ModelInfo): SourceFile {\n const fileName = getModelFileName(modelInfo);\n return getOrCreateSourceFile(this.project, this.outputDir, fileName);\n }\n\n /**\n * Generates models for all schemas in the OpenAPI specification.\n * Skips schemas with keys starting with 'wow.'.\n *\n * @remarks\n * This method iterates through all schemas in the OpenAPI specification\n * and generates corresponding TypeScript models for each one.\n */\n generate() {\n const schemas = this.openAPI.components?.schemas;\n if (!schemas) {\n this.logger.info('No schemas found in OpenAPI specification');\n return;\n }\n const schemaEntries = Object.entries(schemas).filter(\n ([schemaKey]) => !schemaKey.startsWith('wow.'),\n );\n this.logger.progress(\n `Generating models for ${schemaEntries.length} schemas`,\n );\n schemaEntries.forEach(([schemaKey, schema], index) => {\n this.logger.progressWithCount(\n index + 1,\n schemaEntries.length,\n `Processing schema: ${schemaKey}`,\n 2,\n );\n const keySchema: KeySchema = {\n key: schemaKey,\n schema,\n };\n this.generateKeyedSchema(keySchema);\n });\n this.logger.success('Model generation completed');\n }\n\n /**\n * Generates a model for a specific schema key.\n * Processes enums, objects, unions, and type aliases in order.\n *\n * @param schemaKey - The key of the schema to generate\n * @param schema - The schema definition\n *\n * @remarks\n * The generation process follows this order:\n * 1. Enum processing\n * 2. Object processing\n * 3. Union processing\n * 4. Type alias processing\n */\n generateKeyedSchema({ key, schema }: KeySchema) {\n const modelInfo = resolveModelInfo(key);\n const sourceFile = this.getOrCreateSourceFile(modelInfo);\n const node = this.process(modelInfo, sourceFile, schema);\n if (node) {\n addJSDoc(node, schema.title, schema.description);\n }\n }\n\n private process(\n modelInfo: ModelInfo,\n sourceFile: SourceFile,\n schema: Schema,\n ): JSDocableNode | undefined {\n if (isEnum(schema)) {\n return sourceFile.addEnum({\n name: modelInfo.name,\n isExported: true,\n members: schema.enum\n .filter(value => typeof value === 'string' && value.length > 0)\n .map(value => ({\n name: value,\n initializer: `'${value}'`,\n })),\n });\n }\n const interfaceDeclaration = sourceFile.addInterface({\n name: modelInfo.name,\n isExported: true,\n });\n if (schema.type === 'object' && schema.properties) {\n return this.processInterface(\n sourceFile,\n modelInfo,\n schema,\n interfaceDeclaration,\n );\n }\n\n if (isComposition(schema)) {\n const compositionTypes = schema.anyOf || schema.oneOf || schema.allOf;\n compositionTypes!.forEach(compositionTypeSchema => {\n if (isReference(compositionTypeSchema)) {\n const refModelInfo = resolveModelInfo(\n extractComponentKey(compositionTypeSchema),\n );\n addImportModelInfo(\n modelInfo,\n sourceFile,\n this.outputDir,\n refModelInfo,\n );\n interfaceDeclaration.addExtends(refModelInfo.name);\n return;\n }\n this.processInterface(\n sourceFile,\n modelInfo,\n compositionTypeSchema,\n interfaceDeclaration,\n );\n });\n }\n return interfaceDeclaration;\n }\n\n private processObject(\n sourceFile: SourceFile,\n modelInfo: ModelInfo,\n schema: Schema,\n ) {\n const interfaceDeclaration = sourceFile.addInterface({\n name: modelInfo.name,\n isExported: true,\n });\n return this.processInterface(\n sourceFile,\n modelInfo,\n schema,\n interfaceDeclaration,\n );\n }\n\n private processInterface(\n sourceFile: SourceFile,\n modelInfo: ModelInfo,\n schema: Schema,\n interfaceDeclaration: InterfaceDeclaration,\n ) {\n for (const [propName, propSchema] of Object.entries(schema.properties!)) {\n const propType: string = this.resolvePropertyType(\n modelInfo,\n sourceFile,\n propName,\n propSchema,\n );\n let propertySignature = interfaceDeclaration.getProperty(propName);\n if (propertySignature) {\n propertySignature.setType(propType);\n } else {\n propertySignature = interfaceDeclaration.addProperty({\n name: propName,\n type: propType,\n });\n }\n if (!isReference(propSchema)) {\n addJSDoc(propertySignature, propSchema.title, propSchema.description);\n }\n }\n return interfaceDeclaration;\n }\n\n private resolvePropertyType(\n currentModelInfo: ModelInfo,\n sourceFile: SourceFile,\n propName: string,\n propSchema: Schema | Reference,\n ): string {\n if (isReference(propSchema)) {\n const refModelInfo = resolveModelInfo(extractComponentKey(propSchema));\n addImportModelInfo(\n currentModelInfo,\n sourceFile,\n this.outputDir,\n refModelInfo,\n );\n return refModelInfo.name;\n }\n if (propSchema.const) {\n return `'${propSchema.const}'`;\n }\n if (isArray(propSchema)) {\n const itemsType = this.resolvePropertyType(\n currentModelInfo,\n sourceFile,\n propName,\n propSchema.items!,\n );\n return toArrayType(itemsType);\n }\n if (propSchema.type && isPrimitive(propSchema.type)) {\n return resolvePrimitiveType(propSchema.type!);\n }\n if (isComposition(propSchema)) {\n return this.resolvePropertyCompositionType(\n currentModelInfo,\n sourceFile,\n propSchema,\n );\n }\n /**\n * handle object\n */\n if (propSchema.type === 'object' && propSchema.properties) {\n const propModelInfo: ModelInfo = {\n path: currentModelInfo.path,\n name: `${currentModelInfo.name}${pascalCase(propName)}`,\n };\n const interfaceDeclaration = this.processObject(\n sourceFile,\n propModelInfo,\n propSchema,\n );\n addJSDoc(interfaceDeclaration, propSchema.title, propSchema.description);\n return propModelInfo.name;\n }\n return 'any';\n }\n\n private resolvePropertyCompositionType(\n currentModelInfo: ModelInfo,\n sourceFile: SourceFile,\n schema: CompositionSchema,\n ): string {\n const compositionTypes = schema.anyOf || schema.oneOf || schema.allOf;\n const types: Set<string> = new Set<string>();\n compositionTypes!.forEach(compositionTypeSchema => {\n if (isReference(compositionTypeSchema)) {\n const refModelInfo = resolveModelInfo(\n extractComponentKey(compositionTypeSchema),\n );\n addImportModelInfo(\n currentModelInfo,\n sourceFile,\n this.outputDir,\n refModelInfo,\n );\n types.add(refModelInfo.name);\n return;\n }\n types.add(resolvePrimitiveType(compositionTypeSchema.type ?? 'string'));\n });\n const separator = isUnion(schema) ? '|' : '&';\n return Array.from(types).join(separator);\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ResourceAttributionPathSpec } from '@ahoo-wang/fetcher-wow';\nimport { Project, SourceFile } from 'ts-morph';\nimport { AggregateDefinition, TagAliasAggregate } from '../aggregate';\nimport { getOrCreateSourceFile, pascalCase } from '../utils';\n\nexport function inferPathSpecType(\n aggregateDefinition: AggregateDefinition,\n): string {\n let tenantSpecCount = 0;\n let ownerSpecCount = 0;\n aggregateDefinition.commands.forEach(command => {\n if (command.path.startsWith(ResourceAttributionPathSpec.TENANT)) {\n tenantSpecCount += 1;\n }\n if (command.path.startsWith(ResourceAttributionPathSpec.OWNER)) {\n ownerSpecCount += 1;\n }\n });\n if (tenantSpecCount === 0 && ownerSpecCount === 0) {\n return 'ResourceAttributionPathSpec.NONE';\n }\n return tenantSpecCount > ownerSpecCount\n ? 'ResourceAttributionPathSpec.TENANT'\n : 'ResourceAttributionPathSpec.OWNER';\n}\n\nexport function createClientFilePath(\n project: Project,\n outputDir: string,\n aggregate: TagAliasAggregate,\n fileName: string,\n): SourceFile {\n const filePath = `${aggregate.contextAlias}/${aggregate.aggregateName}/${fileName}.ts`;\n return getOrCreateSourceFile(project, outputDir, filePath);\n}\n\n/**\n * Generates the client class name for an aggregate.\n * @param aggregate - The aggregate metadata\n * @param suffix - The suffix to append to the aggregate name\n * @returns The generated client class name\n */\nexport function getClientName(\n aggregate: TagAliasAggregate,\n suffix: string,\n): string {\n return `${pascalCase(aggregate.aggregateName)}${suffix}`;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SourceFile, VariableDeclarationKind } from 'ts-morph';\nimport { GenerateContext } from '../types';\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\nimport { AggregateDefinition, TagAliasAggregate } from '../aggregate';\nimport { IMPORT_WOW_PATH, ModelInfo, resolveModelInfo } from '../model';\nimport { createClientFilePath, inferPathSpecType } from './utils';\nimport { addImportRefModel, camelCase } from '../utils';\n\n/**\n * Generates TypeScript query client classes for aggregates.\n * Creates query clients that can perform state queries and event streaming.\n */\nexport class QueryClientGenerator extends BaseCodeGenerator {\n /**\n * Creates a new QueryClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(context: GenerateContext) {\n super(context);\n }\n\n /**\n * Generates query client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(this.contextAggregates.values()).reduce(\n (sum, set) => sum + set.size,\n 0,\n );\n this.logger.info('--- Generating Query Clients ---');\n this.logger.progress(\n `Generating query clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing query client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processQueryClient(aggregateDefinition);\n });\n }\n this.logger.success('Query client generation completed');\n }\n\n /**\n * Creates or retrieves a source file for client generation.\n * @param aggregate - The aggregate metadata\n * @param fileName - The name of the client file\n * @returns The source file for the client\n */\n createClientFilePath(\n aggregate: TagAliasAggregate,\n fileName: string,\n ): SourceFile {\n return createClientFilePath(\n this.project,\n this.outputDir,\n aggregate,\n fileName,\n );\n }\n\n /**\n * Processes and generates query client classes for an aggregate.\n * @param aggregate - The aggregate definition\n */\n processQueryClient(aggregate: AggregateDefinition) {\n const queryClientFile = this.createClientFilePath(\n aggregate.aggregate,\n 'queryClient',\n );\n this.logger.info(\n `Processing query client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n this.logger.info(\n `Adding imports from ${IMPORT_WOW_PATH}: QueryClientFactory, QueryClientOptions, ResourceAttributionPathSpec`,\n );\n queryClientFile.addImportDeclaration({\n moduleSpecifier: IMPORT_WOW_PATH,\n namedImports: [\n 'QueryClientFactory',\n 'QueryClientOptions',\n 'ResourceAttributionPathSpec',\n ],\n });\n\n const defaultClientOptionsName = 'DEFAULT_QUERY_CLIENT_OPTIONS';\n this.logger.info(\n `Creating default query client options: ${defaultClientOptionsName}`,\n );\n queryClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: defaultClientOptionsName,\n type: 'QueryClientOptions',\n initializer: `{\n contextAlias: '${aggregate.aggregate.contextAlias}',\n aggregateName: '${aggregate.aggregate.aggregateName}',\n resourceAttribution: ${inferPathSpecType(aggregate)},\n }`,\n },\n ],\n isExported: false,\n });\n\n const eventModelInfos: ModelInfo[] = [];\n this.logger.info(\n `Processing ${aggregate.events.size} domain events for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n for (const event of aggregate.events.values()) {\n const eventModelInfo = resolveModelInfo(event.schema.key);\n this.logger.info(\n `Adding import for event model: ${eventModelInfo.name} from path: ${eventModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.outputDir, eventModelInfo);\n eventModelInfos.push(eventModelInfo);\n }\n\n const domainEventTypesName = 'DOMAIN_EVENT_TYPES';\n const eventTypeUnion = eventModelInfos.map(it => it.name).join(' | ');\n this.logger.info(\n `Creating domain event types union: ${domainEventTypesName} = ${eventTypeUnion}`,\n );\n queryClientFile.addTypeAlias({\n name: domainEventTypesName,\n type: eventTypeUnion,\n });\n\n const clientFactoryName = `${camelCase(aggregate.aggregate.aggregateName)}QueryClientFactory`;\n const stateModelInfo = resolveModelInfo(aggregate.state.key);\n const fieldsModelInfo = resolveModelInfo(aggregate.fields.key);\n\n this.logger.info(\n `Adding import for state model: ${stateModelInfo.name} from path: ${stateModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.outputDir, stateModelInfo);\n this.logger.info(\n `Adding import for fields model: ${fieldsModelInfo.name} from path: ${fieldsModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.outputDir, fieldsModelInfo);\n\n this.logger.info(`Creating query client factory: ${clientFactoryName}`);\n queryClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: clientFactoryName,\n initializer: `new QueryClientFactory<${stateModelInfo.name}, ${fieldsModelInfo.name} | string, ${domainEventTypesName}>(${defaultClientOptionsName})`,\n },\n ],\n isExported: true,\n });\n\n this.logger.success(\n `Query client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\nimport { GenerateContext } from '../types';\nimport {\n ClassDeclaration,\n DecoratorStructure,\n OptionalKind,\n Scope,\n SourceFile,\n VariableDeclarationKind,\n} from 'ts-morph';\nimport { HTTPMethod } from '@ahoo-wang/fetcher-openapi';\nimport { AggregateDefinition, CommandDefinition } from '../aggregate';\nimport { createClientFilePath, getClientName } from './utils';\nimport { IMPORT_WOW_PATH, resolveModelInfo } from '../model';\nimport { addImport, addImportRefModel, addJSDoc, camelCase } from '../utils';\n\n/**\n * Generates TypeScript command client classes for aggregates.\n * Creates command clients that can send commands to aggregates.\n */\nexport class CommandClientGenerator extends BaseCodeGenerator {\n private readonly commandEndpointPathsName = 'COMMAND_ENDPOINT_PATHS';\n private readonly defaultCommandClientOptionsName =\n 'DEFAULT_COMMAND_CLIENT_OPTIONS';\n\n /**\n * Creates a new CommandClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(context: GenerateContext) {\n super(context);\n }\n\n /**\n * Generates command client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(this.contextAggregates.values()).reduce(\n (sum, set) => sum + set.size,\n 0,\n );\n this.logger.info('--- Generating Command Clients ---');\n this.logger.progress(\n `Generating command clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing command client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processAggregate(aggregateDefinition);\n });\n }\n this.logger.success('Command client generation completed');\n }\n\n /**\n * Processes and generates command client for an aggregate.\n * @param aggregate - The aggregate definition\n */\n processAggregate(aggregate: AggregateDefinition) {\n this.logger.info(\n `Processing command client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n const commandClientFile = createClientFilePath(\n this.project,\n this.outputDir,\n aggregate.aggregate,\n 'commandClient',\n );\n\n this.logger.info(\n `Processing command endpoint paths for ${aggregate.commands.size} commands`,\n );\n this.processCommandEndpointPaths(commandClientFile, aggregate);\n\n this.logger.info(\n `Creating default command client options: ${this.defaultCommandClientOptionsName}`,\n );\n commandClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: this.defaultCommandClientOptionsName,\n type: 'ApiMetadata',\n initializer: `{\n basePath: '${aggregate.aggregate.contextAlias}'\n }`,\n },\n ],\n isExported: false,\n });\n\n this.logger.info(\n `Adding imports from ${IMPORT_WOW_PATH}: CommandRequest, CommandResult, CommandResultEventStream, DeleteAggregate, RecoverAggregate`,\n );\n commandClientFile.addImportDeclaration({\n moduleSpecifier: IMPORT_WOW_PATH,\n namedImports: [\n 'CommandRequest',\n 'CommandResult',\n 'CommandResultEventStream',\n 'DeleteAggregate',\n 'RecoverAggregate',\n ],\n isTypeOnly: true,\n });\n\n this.logger.info(\n `Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor`,\n );\n commandClientFile.addImportDeclaration({\n moduleSpecifier: '@ahoo-wang/fetcher-eventstream',\n namedImports: ['JsonEventStreamResultExtractor'],\n });\n\n this.logger.info(\n `Adding import from @ahoo-wang/fetcher: ContentTypeValues`,\n );\n addImport(commandClientFile, '@ahoo-wang/fetcher', ['ContentTypeValues']);\n\n this.logger.info(\n `Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators`,\n );\n addImport(commandClientFile, '@ahoo-wang/fetcher-decorator', [\n 'type ApiMetadata',\n 'type ApiMetadataCapable',\n 'api',\n 'post',\n 'put',\n 'patch',\n 'del',\n 'request',\n 'attribute',\n 'path',\n 'autoGeneratedError',\n ]);\n\n this.logger.info(`Generating standard command client class`);\n this.processCommandClient(commandClientFile, aggregate);\n\n this.logger.info(`Generating stream command client class`);\n this.processCommandClient(commandClientFile, aggregate, true);\n\n this.logger.success(\n `Command client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n\n processCommandEndpointPaths(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ) {\n this.logger.info(\n `Creating command endpoint paths enum: ${this.commandEndpointPathsName}`,\n );\n const enumDeclaration = clientFile.addEnum({\n name: this.commandEndpointPathsName,\n });\n aggregateDefinition.commands.forEach(command => {\n this.logger.info(\n `Adding command endpoint: ${command.name.toUpperCase()} = '${command.path}'`,\n );\n enumDeclaration.addMember({\n name: command.name.toUpperCase(),\n initializer: `'${command.path}'`,\n });\n });\n this.logger.success(\n `Command endpoint paths enum created with ${aggregateDefinition.commands.size} entries`,\n );\n }\n\n getEndpointPath(command: CommandDefinition): string {\n return `${this.commandEndpointPathsName}.${command.name.toUpperCase()}`;\n }\n\n processCommandClient(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n isStream: boolean = false,\n ) {\n let suffix = 'CommandClient';\n let apiDecorator: OptionalKind<DecoratorStructure> = {\n name: 'api',\n arguments: [],\n };\n let returnType = `Promise<CommandResult>`;\n if (isStream) {\n suffix = 'Stream' + suffix;\n apiDecorator = {\n name: 'api',\n arguments: [\n `''`,\n `{\n headers: { Accept: ContentTypeValues.TEXT_EVENT_STREAM },\n resultExtractor: JsonEventStreamResultExtractor,\n}`,\n ],\n };\n returnType = `Promise<CommandResultEventStream>`;\n }\n const commandClientName = getClientName(\n aggregateDefinition.aggregate,\n suffix,\n );\n\n const commandClient = clientFile.addClass({\n name: commandClientName,\n isExported: true,\n decorators: [apiDecorator],\n implements: ['ApiMetadataCapable'],\n });\n commandClient.addConstructor({\n parameters: [\n {\n name: 'apiMetadata',\n type: 'ApiMetadata',\n scope: Scope.Public,\n isReadonly: true,\n initializer: `${this.defaultCommandClientOptionsName}`,\n },\n ],\n });\n aggregateDefinition.commands.forEach(command => {\n this.processCommandMethod(clientFile, commandClient, command, returnType);\n });\n }\n\n private methodToDecorator(method: HTTPMethod): string {\n if (method === 'delete') {\n return 'del';\n }\n return method;\n }\n\n /**\n * Processes and generates a command method for the command client.\n * @param sourceFile - The source file containing the client\n * @param client - The client class declaration\n * @param definition - The command definition\n */\n processCommandMethod(\n sourceFile: SourceFile,\n client: ClassDeclaration,\n definition: CommandDefinition,\n returnType: string,\n ) {\n const commandModelInfo = resolveModelInfo(definition.schema.key);\n this.logger.info(\n `Adding import for command model: ${commandModelInfo.name} from path: ${commandModelInfo.path}`,\n );\n addImportRefModel(sourceFile, this.outputDir, commandModelInfo);\n\n this.logger.info(\n `Generating command method: ${camelCase(definition.name)} for command: ${definition.name}`,\n );\n this.logger.info(\n `Command method details: HTTP ${definition.method}, path: ${definition.path}, return type: ${returnType}`,\n );\n\n const parameters = definition.pathParameters.map(parameter => {\n this.logger.info(\n `Adding path parameter: ${parameter.name} (type: string)`,\n );\n return {\n name: parameter.name,\n type: 'string',\n decorators: [\n {\n name: 'path',\n arguments: [`'${parameter.name}'`],\n },\n ],\n };\n });\n\n this.logger.info(\n `Adding command request parameter: commandRequest (type: CommandRequest<${commandModelInfo.name}>)`,\n );\n parameters.push({\n name: 'commandRequest',\n type: `CommandRequest<${commandModelInfo.name}>`,\n decorators: [\n {\n name: 'request',\n arguments: [],\n },\n ],\n });\n\n this.logger.info(\n `Adding attributes parameter: attributes (type: Record<string, any>)`,\n );\n parameters.push({\n name: 'attributes',\n type: 'Record<string, any>',\n decorators: [\n {\n name: 'attribute',\n arguments: [],\n },\n ],\n });\n\n const methodDeclaration = client.addMethod({\n name: camelCase(definition.name),\n decorators: [\n {\n name: this.methodToDecorator(definition.method),\n arguments: [`${this.getEndpointPath(definition)}`],\n },\n ],\n parameters: parameters,\n returnType: returnType,\n statements: [\n `throw autoGeneratedError(${parameters.map(parameter => parameter.name).join(',')});`,\n ],\n });\n\n if (definition.summary || definition.description) {\n this.logger.info(\n `Adding JSDoc documentation for method: ${camelCase(definition.name)}`,\n );\n }\n addJSDoc(methodDeclaration, definition.summary, definition.description);\n\n this.logger.success(\n `Command method generated: ${camelCase(definition.name)}`,\n );\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\nimport { QueryClientGenerator } from './queryClientGenerator';\nimport { CommandClientGenerator } from './commandClientGenerator';\nimport { GenerateContext } from '../types';\nimport { getOrCreateSourceFile } from '../utils';\n\n/**\n * Generates TypeScript client classes for aggregates.\n * Creates query clients and command clients based on aggregate definitions.\n */\nexport class ClientGenerator extends BaseCodeGenerator {\n private readonly queryClientGenerator: QueryClientGenerator;\n private readonly commandClientGenerator: CommandClientGenerator;\n\n /**\n * Creates a new ClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(context: GenerateContext) {\n super(context);\n this.queryClientGenerator = new QueryClientGenerator(context);\n this.commandClientGenerator = new CommandClientGenerator(context);\n }\n\n /**\n * Generates client classes for all aggregates.\n */\n generate(): void {\n this.logger.info('--- Generating Clients ---');\n this.logger.progress(\n `Generating clients for ${this.contextAggregates.size} bounded contexts`,\n );\n let currentIndex = 0;\n for (const [contextAlias] of this.contextAggregates) {\n currentIndex++;\n this.logger.progressWithCount(\n currentIndex,\n this.contextAggregates.size,\n `Processing bounded context: ${contextAlias}`,\n 1,\n );\n this.processBoundedContext(contextAlias);\n }\n this.queryClientGenerator.generate();\n this.commandClientGenerator.generate();\n this.logger.success('Client generation completed');\n }\n\n /**\n * Processes a bounded context by creating a file with the context alias constant.\n * @param contextAlias - The alias of the bounded context to process\n */\n processBoundedContext(contextAlias: string) {\n const filePath = `${contextAlias}/boundedContext.ts`;\n this.logger.info(`Creating bounded context file: ${filePath}`);\n const file = getOrCreateSourceFile(this.project, this.outputDir, filePath);\n this.logger.info(\n `Adding bounded context alias constant: BOUNDED_CONTEXT_ALIAS = '${contextAlias}'`,\n );\n file.addStatements(\n `export const BOUNDED_CONTEXT_ALIAS = '${contextAlias}';`,\n );\n this.logger.success(\n `Bounded context file created successfully: ${filePath}`,\n );\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Directory, Project, SourceFile } from 'ts-morph';\nimport { GenerateContext, GeneratorOptions } from './types';\nimport { parseOpenAPI } from './utils';\nimport { AggregateResolver } from './aggregate';\nimport { ModelGenerator } from './model';\nimport { ClientGenerator } from './client';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Main code generator class that orchestrates the generation of TypeScript code from OpenAPI specifications.\n * Handles model generation, client generation, and project formatting.\n */\nexport class CodeGenerator {\n private readonly project: Project;\n\n /**\n * Creates a new CodeGenerator instance.\n * @param options - Configuration options for code generation\n */\n constructor(private readonly options: GeneratorOptions) {\n this.project = options.project;\n this.options.logger.info('CodeGenerator instance created');\n }\n\n /**\n * Generates TypeScript code from the OpenAPI specification.\n * Parses the OpenAPI spec, resolves aggregates, generates models and clients,\n * and formats the output files.\n */\n async generate(): Promise<void> {\n this.options.logger.info(\n 'Starting code generation from OpenAPI specification',\n );\n this.options.logger.info(`Input path: ${this.options.inputPath}`);\n this.options.logger.info(`Output directory: ${this.options.outputDir}`);\n\n this.options.logger.info('Parsing OpenAPI specification');\n const openAPI = await parseOpenAPI(this.options.inputPath);\n this.options.logger.info('OpenAPI specification parsed successfully');\n\n this.options.logger.info('Resolving bounded context aggregates');\n const aggregateResolver = new AggregateResolver(openAPI);\n const boundedContextAggregates = aggregateResolver.resolve();\n this.options.logger.info(\n `Resolved ${boundedContextAggregates.size} bounded context aggregates`,\n );\n\n const context: GenerateContext = {\n openAPI: openAPI,\n project: this.project,\n outputDir: this.options.outputDir,\n contextAggregates: boundedContextAggregates,\n logger: this.options.logger,\n };\n\n this.options.logger.info('Generating models');\n const modelGenerator = new ModelGenerator(context);\n modelGenerator.generate();\n this.options.logger.info('Models generated successfully');\n\n this.options.logger.info('Generating clients');\n const clientGenerator = new ClientGenerator(context);\n clientGenerator.generate();\n this.options.logger.info('Clients generated successfully');\n\n this.options.logger.info('Generating index files');\n this.generateIndex();\n this.options.logger.info('Index files generated successfully');\n\n this.options.logger.info('Optimizing source files');\n this.optimizeSourceFiles();\n this.options.logger.info('Source files optimized successfully');\n\n this.options.logger.info('Saving project to disk');\n await this.project.save();\n this.options.logger.info('Code generation completed successfully');\n }\n\n /**\n * Generates index.ts files for all subdirectories in the output directory.\n * Scans all directories, gets all .ts files in each directory,\n * and creates index.ts files with export * from './xxx' statements.\n */\n generateIndex() {\n this.options.logger.info(\n `Generating index files for output directory: ${this.options.outputDir}`,\n );\n const outputDir = this.project.getDirectory(this.options.outputDir);\n if (!outputDir) {\n this.options.logger.info(\n 'Output directory not found, skipping index generation',\n );\n return;\n }\n this.processDirectory(outputDir);\n this.options.logger.info('Index file generation completed');\n }\n\n private processDirectory(dir: Directory) {\n const subDirs = dir.getDirectories();\n this.options.logger.info(`Processing ${subDirs.length} subdirectories`);\n for (const subDir of subDirs) {\n this.options.logger.info(`Processing subdirectory: ${subDir.getPath()}`);\n this.generateIndexForDirectory(subDir);\n this.processDirectory(subDir);\n }\n }\n\n /**\n * Generates an index.ts file for a specific directory.\n * @param dir - The directory to generate index.ts for\n */\n private generateIndexForDirectory(dir: Directory) {\n const dirPath = dir.getPath();\n this.options.logger.info(`Generating index for directory: ${dirPath}`);\n\n const tsFiles = dir\n .getSourceFiles()\n .filter(\n (file: SourceFile) =>\n file.getBaseName().endsWith('.ts') &&\n file.getBaseName() !== 'index.ts',\n );\n\n // Get subdirectories using fs\n let subDirNames: string[] = [];\n try {\n subDirNames = fs.readdirSync(dirPath).filter(item => {\n const itemPath = path.join(dirPath, item);\n return fs.statSync(itemPath).isDirectory();\n });\n } catch (error) {\n this.options.logger.error(\n `Failed to read subdirectories for ${dirPath}: ${error}`,\n );\n }\n\n this.options.logger.info(\n `Found ${tsFiles.length} TypeScript files and ${subDirNames.length} subdirectories in ${dirPath}`,\n );\n\n if (tsFiles.length === 0 && subDirNames.length === 0) {\n this.options.logger.info(\n `No files or subdirectories to export in ${dirPath}, skipping index generation`,\n );\n return; // No files or subdirs to export\n }\n\n const indexFilePath = `${dirPath}/index.ts`;\n this.options.logger.info(`Creating/updating index file: ${indexFilePath}`);\n const indexFile =\n this.project.getSourceFile(indexFilePath) ||\n this.project.createSourceFile(indexFilePath, '', { overwrite: true });\n\n // Clear existing content\n indexFile.removeText();\n\n // Add export statements for .ts files\n for (const tsFile of tsFiles) {\n const relativePath = `./${tsFile.getBaseNameWithoutExtension()}`;\n this.options.logger.info(`Adding export for file: ${relativePath}`);\n indexFile.addExportDeclaration({\n moduleSpecifier: relativePath,\n isTypeOnly: false,\n namedExports: [],\n });\n }\n\n // Add export statements for subdirectories\n for (const subDirName of subDirNames) {\n const relativePath = `./${subDirName}`;\n this.options.logger.info(\n `Adding export for subdirectory: ${relativePath}`,\n );\n indexFile.addExportDeclaration({\n moduleSpecifier: relativePath,\n isTypeOnly: false,\n namedExports: [],\n });\n }\n\n this.options.logger.info(\n `Index file generated for ${dirPath} with ${tsFiles.length + subDirNames.length} exports`,\n );\n }\n\n optimizeSourceFiles() {\n const sourceFiles = this.project.getSourceFiles();\n this.options.logger.info(`Optimizing ${sourceFiles.length} source files`);\n sourceFiles.forEach((sourceFile, index) => {\n this.options.logger.info(\n `Optimizing file ${index + 1}/${sourceFiles.length}`,\n );\n sourceFile.formatText();\n sourceFile.organizeImports();\n sourceFile.fixMissingImports();\n });\n this.options.logger.info('All source files optimized');\n }\n}\n"],"names":["extractComponentKey","reference","extractSchema","components","componentKey","extractRequestBody","extractParameter","keySchema","NAMING_SEPARATORS","pascalCase","name","names","part","firstChar","rest","camelCase","pascalCaseName","loadResource","path","loadHttpResource","loadFile","url","resolve","reject","readFile","err","data","parseOpenAPI","inputPath","content","inferFileFormat","parse","trimmedContent","isReference","schema","extractOkResponseJsonSchema","okResponse","ContentTypeValues","extractOperations","pathItem","operation","extractOkResponse","extractOperationOkResponseJsonSchema","PRIMITIVE_TYPES","isPrimitive","type","isArray","isEnum","isAnyOf","isOneOf","isUnion","isAllOf","isComposition","toArrayType","resolvePrimitiveType","it","MODEL_FILE_NAME","IMPORT_ALIAS","getModelFileName","modelInfo","combineURLs","getOrCreateSourceFile","project","outputDir","filePath","fileName","file","addImport","sourceFile","moduleSpecifier","namedImports","declaration","importDeclaration","namedImport","existingNamedImport","addImportRefModel","refModelInfo","sourceDir","targetFilePath","join","relativePath","relative","addImportModelInfo","currentModel","refModel","jsDoc","title","description","filtered","v","addJSDoc","node","jsdoc","isAliasAggregate","tagName","parts","tagToAggregate","tag","tagsToAggregates","tags","tagAliasAggregates","aggregates","tagAliasAggregate","operationIdToCommandName","operationId","CommandOkResponseRef","IdParameterRef","AggregateResolver","openAPI","methodOperations","methodOperation","resolvedContextAggregates","aggregate","contextAlias","commandName","parameters","idRefParameter","p","pathParameters","idParameter","commandRefSchema","commandKeyedSchema","commandDefinition","stateRefSchema","stateKeyedSchema","eventStreamArraySchema","eventStreamRefSchema","events","domainEventSchema","eventTitle","eventName","eventBodySchema","eventBodyKeyedSchema","event","conditionRefSchema","fieldRefSchema","fieldKeyedSchema","IMPORT_WOW_PATH","WOW_TYPE_MAPPING","resolveModelInfo","schemaKey","mappedType","modelNameIndex","i","pathParts","nameParts","BaseCodeGenerator","context","ModelGenerator","schemas","schemaEntries","index","key","value","interfaceDeclaration","compositionTypeSchema","propName","propSchema","propType","propertySignature","currentModelInfo","itemsType","propModelInfo","compositionTypes","types","separator","inferPathSpecType","aggregateDefinition","tenantSpecCount","ownerSpecCount","command","ResourceAttributionPathSpec","createClientFilePath","getClientName","suffix","QueryClientGenerator","totalAggregates","sum","set","currentIndex","queryClientFile","defaultClientOptionsName","VariableDeclarationKind","eventModelInfos","eventModelInfo","domainEventTypesName","eventTypeUnion","clientFactoryName","stateModelInfo","fieldsModelInfo","CommandClientGenerator","commandClientFile","clientFile","enumDeclaration","isStream","apiDecorator","returnType","commandClientName","commandClient","Scope","method","client","definition","commandModelInfo","parameter","methodDeclaration","ClientGenerator","CodeGenerator","options","boundedContextAggregates","dir","subDirs","subDir","dirPath","tsFiles","subDirNames","fs","item","itemPath","error","indexFilePath","indexFile","tsFile","subDirName","sourceFiles"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/components.ts","../src/utils/naming.ts","../src/utils/resources.ts","../src/utils/openAPIParser.ts","../src/utils/references.ts","../src/utils/responses.ts","../src/utils/operations.ts","../src/utils/schemas.ts","../src/utils/sourceFiles.ts","../src/aggregate/utils.ts","../src/aggregate/aggregateResolver.ts","../src/model/wowTypeMapping.ts","../src/model/modelInfo.ts","../src/baseCodeGenerator.ts","../src/model/modelGenerator.ts","../src/client/utils.ts","../src/client/queryClientGenerator.ts","../src/client/commandClientGenerator.ts","../src/client/clientGenerator.ts","../src/index.ts"],"sourcesContent":["/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Components,\n Parameter,\n Reference,\n RequestBody,\n Response,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\n\n/** Prefix for OpenAPI components references */\nexport const COMPONENTS_PREFIX = '#/components/';\n/** Reference prefix for headers components */\nexport const COMPONENTS_HEADERS_REF = `${COMPONENTS_PREFIX}headers/`;\n/** Reference prefix for parameters components */\nexport const COMPONENTS_PARAMETERS_REF = `${COMPONENTS_PREFIX}parameters/`;\n/** Reference prefix for request bodies components */\nexport const COMPONENTS_REQUEST_BODIES_REF = `${COMPONENTS_PREFIX}requestBodies/`;\n/** Reference prefix for responses components */\nexport const COMPONENTS_RESPONSES_REF = `${COMPONENTS_PREFIX}responses/`;\n/** Reference prefix for schemas components */\nexport const COMPONENTS_SCHEMAS_REF = `${COMPONENTS_PREFIX}schemas/`;\n\n/**\n * Represents a schema with its key identifier.\n */\nexport interface KeySchema {\n /** The schema key */\n key: string;\n /** The schema definition */\n schema: Schema;\n}\n\n/**\n * Extracts the component key from an OpenAPI reference.\n * @param reference - The OpenAPI reference object\n * @returns The component key (last part of the reference path)\n */\nexport function extractComponentKey(reference: Reference): string {\n return reference.$ref.split('/').pop() as string;\n}\n\n/**\n * Extracts a schema from OpenAPI components using a reference.\n * @param reference - The reference to the schema\n * @param components - The OpenAPI components object\n * @returns The schema if found, undefined otherwise\n */\nexport function extractSchema(\n reference: Reference,\n components: Components,\n): Schema | undefined {\n const componentKey = extractComponentKey(reference);\n return components.schemas?.[componentKey];\n}\n\n/**\n * Extracts a response from OpenAPI components using a reference.\n * @param reference - The reference to the response\n * @param components - The OpenAPI components object\n * @returns The response if found, undefined otherwise\n */\nexport function extractResponse(\n reference: Reference,\n components: Components,\n): Response | undefined {\n const componentKey = extractComponentKey(reference);\n return components.responses?.[componentKey];\n}\n\n/**\n * Extracts a request body from OpenAPI components using a reference.\n * @param reference - The reference to the request body\n * @param components - The OpenAPI components object\n * @returns The request body if found, undefined otherwise\n */\nexport function extractRequestBody(\n reference: Reference,\n components: Components,\n): RequestBody | undefined {\n const componentKey = extractComponentKey(reference);\n return components.requestBodies?.[componentKey];\n}\n\n/**\n * Extracts a parameter from OpenAPI components using a reference.\n * @param reference - The reference to the parameter\n * @param components - The OpenAPI components object\n * @returns The parameter if found, undefined otherwise\n */\nexport function extractParameter(\n reference: Reference,\n components: Components,\n): Parameter | undefined {\n const componentKey = extractComponentKey(reference);\n return components.parameters?.[componentKey];\n}\n\n/**\n * Creates a KeySchema object from a reference and components.\n * @param reference - The reference to the schema\n * @param components - The OpenAPI components object\n * @returns A KeySchema containing the key and resolved schema\n */\nexport function keySchema(\n reference: Reference,\n components: Components,\n): KeySchema {\n const componentKey = extractComponentKey(reference);\n return {\n key: componentKey,\n schema: extractSchema(reference, components)!,\n };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst NAMING_SEPARATORS = /[-_\\s.]+|(?=[A-Z])/;\n\n/**\n * Converts a string or array of strings to PascalCase format.\n *\n * This function takes a string or array of strings and converts them to PascalCase format\n * by splitting the input based on common naming separators and capitalizing the first\n * letter of each part.\n *\n * @param name - A string or array of strings to convert to PascalCase\n * @returns The PascalCase formatted string\n */\nexport function pascalCase(name: string | string[]): string {\n if (name === '' || name.length === 0) {\n return '';\n }\n let names: string[];\n if (Array.isArray(name)) {\n // If input is an array, split each element by naming separators and flatten the result\n names = name.flatMap(part => part.split(NAMING_SEPARATORS));\n } else {\n // If input is a string, split it by naming separators\n names = name.split(NAMING_SEPARATORS);\n }\n return names\n .filter(part => part.length > 0)\n .map(part => {\n if (part.length === 0) return '';\n const firstChar = part.charAt(0);\n const rest = part.slice(1);\n return (\n (/[a-zA-Z]/.test(firstChar) ? firstChar.toUpperCase() : firstChar) +\n rest.toLowerCase()\n );\n })\n .join('');\n}\n\n/**\n * Converts a string or array of strings to camelCase format.\n *\n * This function first converts the input to PascalCase and then converts the first character to lowercase.\n *\n * @param name - A string or array of strings to convert to camelCase\n * @returns The camelCase formatted string\n */\nexport function camelCase(name: string | string[]): string {\n const pascalCaseName = pascalCase(name);\n return pascalCaseName.charAt(0).toLowerCase() + pascalCaseName.slice(1);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { readFile } from 'fs';\n\nexport function loadResource(path: string): Promise<string> {\n if (path.startsWith('http://') || path.startsWith('https://')) {\n return loadHttpResource(path);\n }\n return loadFile(path);\n}\n\nexport async function loadHttpResource(url: string): Promise<string> {\n const response = await fetch(url);\n return await response.text();\n}\n\nexport function loadFile(path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n readFile(path, 'utf-8', (err, data) => {\n if (err) {\n reject(err);\n } else {\n resolve(data);\n }\n });\n });\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { OpenAPI } from '@ahoo-wang/fetcher-openapi';\nimport { parse } from 'yaml';\nimport { loadResource } from './resources';\n\n/**\n * Parses an OpenAPI specification from a file path.\n *\n * @param inputPath - The path to the OpenAPI specification file\n * @returns A promise that resolves to the parsed OpenAPI object\n */\nexport async function parseOpenAPI(inputPath: string): Promise<OpenAPI> {\n const content = await loadResource(inputPath);\n const fileFormat = inferFileFormat(content);\n switch (fileFormat) {\n case FileFormat.JSON:\n return JSON.parse(content);\n case FileFormat.YAML:\n return parse(content);\n default:\n throw new Error(`Unsupported file format: ${inputPath}`);\n }\n}\n\nexport enum FileFormat {\n JSON = 'json',\n YAML = 'yaml',\n}\n\nexport function inferFileFormat(content: string): FileFormat {\n // Trim whitespace and BOM characters from the beginning\n const trimmedContent = content.trimStart();\n\n if (trimmedContent.startsWith('{') || trimmedContent.startsWith('[')) {\n return FileFormat.JSON;\n }\n\n // YAML can start with various characters, but commonly with '-' (for arrays) or '%YAML'\n // We'll check for common YAML indicators\n if (trimmedContent.startsWith('-') || trimmedContent.startsWith('%YAML')) {\n return FileFormat.YAML;\n }\n\n // Try to parse as JSON to see if it's valid JSON despite not starting with { or [\n try {\n JSON.parse(trimmedContent);\n return FileFormat.JSON;\n } catch {\n // If it's not valid JSON, we'll assume it's YAML if it's not empty\n if (trimmedContent.length > 0) {\n return FileFormat.YAML;\n }\n }\n\n throw new Error('Unable to infer file format');\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Reference } from '@ahoo-wang/fetcher-openapi';\n\nexport function isReference(schema: any): schema is Reference {\n return !!(schema && typeof schema === 'object' && '$ref' in schema);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Reference, Schema, Response } from '@ahoo-wang/fetcher-openapi';\nimport { ContentTypeValues } from '@ahoo-wang/fetcher';\nimport { isReference } from './references';\n\n/**\n * Extracts the JSON schema from an OK response.\n * @param okResponse - The response object or reference\n * @returns The JSON schema from the response content or undefined if not found\n */\nexport function extractOkResponseJsonSchema(\n okResponse?: Response | Reference,\n): Schema | Reference | undefined {\n if (!okResponse) {\n return;\n }\n if (isReference(okResponse)) {\n return undefined;\n }\n\n if (!okResponse.content) {\n return undefined;\n }\n const jsonContent = okResponse.content[ContentTypeValues.APPLICATION_JSON];\n return jsonContent?.schema;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n HTTPMethod,\n Operation,\n PathItem,\n Reference,\n Response,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\nimport { extractOkResponseJsonSchema } from './responses';\n\n/**\n * Represents an HTTP method and its associated operation.\n */\nexport interface MethodOperation {\n /** The HTTP method */\n method: HTTPMethod;\n /** The OpenAPI operation */\n operation: Operation;\n}\n\n/**\n * Extracts all operations from a path item.\n * @param pathItem - The OpenAPI path item\n * @returns Array of method-operation pairs\n */\nexport function extractOperations(pathItem: PathItem): MethodOperation[] {\n return [\n { method: 'get', operation: pathItem.get },\n { method: 'put', operation: pathItem.put },\n { method: 'post', operation: pathItem.post },\n { method: 'delete', operation: pathItem.delete },\n { method: 'options', operation: pathItem.options },\n { method: 'head', operation: pathItem.head },\n { method: 'patch', operation: pathItem.patch },\n { method: 'trace', operation: pathItem.trace },\n ].filter(({ operation }) => operation !== undefined) as Array<{\n method: HTTPMethod;\n operation: Operation;\n }>;\n}\n\n/**\n * Extracts the OK (200) response from an operation.\n * @param operation - The OpenAPI operation\n * @returns The 200 response or undefined if not found\n */\nexport function extractOkResponse(\n operation: Operation,\n): Response | Reference | undefined {\n return operation.responses['200'];\n}\n\n/**\n * Extracts the JSON schema from the OK response of an operation.\n * @param operation - The OpenAPI operation\n * @returns The JSON schema from the OK response or undefined if not found\n */\nexport function extractOperationOkResponseJsonSchema(\n operation: Operation,\n): Schema | Reference | undefined {\n const okResponse = extractOkResponse(operation);\n return extractOkResponseJsonSchema(okResponse);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Schema, SchemaType } from '@ahoo-wang/fetcher-openapi';\n\n/** List of primitive schema types */\nconst PRIMITIVE_TYPES: SchemaType[] = [\n 'string',\n 'number',\n 'integer',\n 'boolean',\n 'null',\n];\n\n/**\n * Checks if a schema type is primitive.\n * @param type - The schema type to check\n * @returns True if the type is primitive, false otherwise\n */\nexport function isPrimitive(type: SchemaType | SchemaType[]): boolean {\n if (Array.isArray(type)) {\n return true;\n }\n return PRIMITIVE_TYPES.includes(type);\n}\n\n/**\n * Checks if a schema is an array type.\n * @param schema - The schema to check\n * @returns True if the schema is an array type, false otherwise\n */\nexport function isArray(schema: Schema): schema is Schema & { type: 'array' } {\n return schema.type === 'array';\n}\n\nexport type EnumSchema = Schema & { enum: any[] };\n\n/**\n * Checks if a schema represents an enum.\n * @param schema - The schema to check\n * @returns True if the schema has an enum property, false otherwise\n */\nexport function isEnum(schema: Schema): schema is EnumSchema {\n return Array.isArray(schema.enum) && schema.enum.length > 0;\n}\n\nexport type AnyOfSchema = Schema & { anyOf: any[] };\n\n/**\n * Checks if a schema is an anyOf composition.\n * @param schema - The schema to check\n * @returns True if the schema has a non-empty anyOf property, false otherwise\n */\nexport function isAnyOf(schema: Schema): schema is AnyOfSchema {\n return Array.isArray(schema.anyOf) && schema.anyOf.length > 0;\n}\n\nexport type OneOfSchema = Schema & { oneOf: any[] };\n\n/**\n * Checks if a schema is a oneOf composition.\n * @param schema - The schema to check\n * @returns True if the schema has a non-empty oneOf property, false otherwise\n */\nexport function isOneOf(schema: Schema): schema is OneOfSchema {\n return Array.isArray(schema.oneOf) && schema.oneOf.length > 0;\n}\n\nexport type UnionSchema = Schema & ({ anyOf: any[] } | { oneOf: any[] });\n\n/**\n * Checks if a schema is a union (either anyOf or oneOf).\n * @param schema - The schema to check\n * @returns True if the schema is either an anyOf or oneOf composition, false otherwise\n */\nexport function isUnion(schema: Schema): schema is UnionSchema {\n return isAnyOf(schema) || isOneOf(schema);\n}\n\nexport type AllOfSchema = Schema & { allOf: any[] };\n\n/**\n * Checks if a schema is an allOf composition.\n * @param schema - The schema to check\n * @returns True if the schema has a non-empty allOf property, false otherwise\n */\nexport function isAllOf(schema: Schema): schema is AllOfSchema {\n return Array.isArray(schema.allOf) && schema.allOf.length > 0;\n}\n\nexport type CompositionSchema = AnyOfSchema | OneOfSchema | AllOfSchema;\n\n/**\n * Checks if a schema is a composition (anyOf, oneOf, or allOf).\n * @param schema - The schema to check\n * @returns True if the schema is anyOf, oneOf, or allOf composition, false otherwise\n */\nexport function isComposition(schema: Schema): schema is CompositionSchema {\n return isAnyOf(schema) || isOneOf(schema) || isAllOf(schema);\n}\n\n/**\n * Converts a type string to an array type.\n * Wraps complex types (containing | or &) in parentheses before adding array notation.\n * @param type - The type string to convert to an array type\n * @returns The array type string\n */\nexport function toArrayType(type: string): string {\n if (type.includes('|') || type.includes('&')) {\n return `(${type})[]`;\n }\n return `${type}[]`;\n}\n\n/**\n * Resolves a schema type to its TypeScript equivalent.\n * @param type - The schema type(s) to resolve\n * @returns The TypeScript type string\n */\nexport function resolvePrimitiveType(type: SchemaType | SchemaType[]): string {\n if (Array.isArray(type)) {\n return type.map(it => resolvePrimitiveType(it)).join(' | ');\n }\n switch (type) {\n case 'string':\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n default:\n return 'any';\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JSDocableNode, Project, SourceFile } from 'ts-morph';\nimport { combineURLs } from '@ahoo-wang/fetcher';\nimport { join, relative } from 'path';\nimport { ModelInfo } from '../model';\n\n/** Default file name for model files */\nconst MODEL_FILE_NAME = 'types.ts';\n/** Alias for import paths */\nconst IMPORT_ALIAS = '@';\n\n/**\n * Generates the file path for a model file.\n * @param modelInfo - The model information\n * @returns The full file path for the model\n */\nexport function getModelFileName(modelInfo: ModelInfo): string {\n return combineURLs(modelInfo.path, MODEL_FILE_NAME);\n}\n\n/**\n * Gets or creates a source file in the project.\n * @param project - The ts-morph project\n * @param outputDir - The output directory\n * @param filePath - The relative file path\n * @returns The source file\n */\nexport function getOrCreateSourceFile(\n project: Project,\n outputDir: string,\n filePath: string,\n): SourceFile {\n const fileName = combineURLs(outputDir, filePath);\n const file = project.getSourceFile(fileName);\n if (file) {\n return file;\n }\n return project.createSourceFile(fileName, '', {\n overwrite: true,\n });\n}\n\n/**\n * Adds named imports to a source file.\n * @param sourceFile - The source file to modify\n * @param moduleSpecifier - The module to import from\n * @param namedImports - Array of named imports to add\n */\nexport function addImport(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n namedImports: string[],\n) {\n let declaration = sourceFile.getImportDeclaration(\n importDeclaration =>\n importDeclaration.getModuleSpecifierValue() === moduleSpecifier,\n );\n if (!declaration) {\n declaration = sourceFile.addImportDeclaration({\n moduleSpecifier,\n });\n }\n namedImports.forEach(namedImport => {\n const exited = declaration\n .getNamedImports()\n .some(\n existingNamedImport => existingNamedImport.getName() === namedImport,\n );\n if (exited) {\n return;\n }\n declaration.addNamedImport(namedImport);\n });\n}\n\n/**\n * Adds an import for a referenced model.\n * @param sourceFile - The source file to modify\n * @param outputDir - The output directory\n * @param refModelInfo - The referenced model information\n */\nexport function addImportRefModel(\n sourceFile: SourceFile,\n outputDir: string,\n refModelInfo: ModelInfo,\n) {\n if (refModelInfo.path.startsWith(IMPORT_ALIAS)) {\n addImport(sourceFile, refModelInfo.path, [refModelInfo.name]);\n return;\n }\n\n const sourceDir = sourceFile.getDirectoryPath();\n const targetFilePath = join(outputDir, refModelInfo.path, MODEL_FILE_NAME);\n let relativePath = relative(sourceDir, targetFilePath);\n\n relativePath = relativePath.replace(/\\.ts$/, '');\n\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath;\n }\n\n addImport(sourceFile, relativePath, [refModelInfo.name]);\n}\n\n/**\n * Adds an import for a model if it's in a different path.\n * @param currentModel - The current model information\n * @param sourceFile - The source file to modify\n * @param outputDir - The output directory\n * @param refModel - The referenced model information\n */\nexport function addImportModelInfo(\n currentModel: ModelInfo,\n sourceFile: SourceFile,\n outputDir: string,\n refModel: ModelInfo,\n) {\n if (currentModel.path === refModel.path) {\n return;\n }\n addImportRefModel(sourceFile, outputDir, refModel);\n}\n\n/**\n * Generates a JSDoc comment string from a title and description.\n * @param title - The title for the JSDoc comment\n * @param description - The description for the JSDoc comment\n * @returns The formatted JSDoc string or undefined if both title and description are empty\n */\nexport function jsDoc(\n title?: string,\n description?: string,\n): string | undefined {\n const filtered = [title, description].filter(\n v => v !== undefined && v.length > 0,\n );\n return filtered.length > 0 ? filtered.join('\\n') : undefined;\n}\n\nexport function jsDocs(title?: string, description?: string): string[] {\n const jsdoc = jsDoc(title, description);\n return jsdoc ? [jsdoc] : [];\n}\n\n/**\n * Adds a JSDoc comment to a node with the provided title and description.\n * @param node - The node to add the JSDoc comment to\n * @param title - The title for the JSDoc comment\n * @param description - The description for the JSDoc comment\n */\nexport function addJSDoc(\n node: JSDocableNode,\n title?: string,\n description?: string,\n) {\n const jsdoc = jsDoc(title, description);\n if (!jsdoc) {\n return;\n }\n node.addJsDoc({\n description: jsdoc,\n });\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Tag } from '@ahoo-wang/fetcher-openapi';\nimport { PartialBy } from '@ahoo-wang/fetcher';\nimport { AggregateDefinition, TagAliasAggregate } from './aggregate';\n\n/**\n * Checks if a tag name follows the alias aggregate pattern and extracts its components.\n *\n * This function determines if a tag name follows the format \"contextAlias.aggregateName\"\n * and returns the components if it matches.\n *\n * @param tagName - The tag name to check\n * @returns A tuple with [contextAlias, aggregateName] if the pattern matches, null otherwise\n */\nexport function isAliasAggregate(tagName: string): [string, string] | null {\n const parts = tagName.split('.');\n if (parts.length != 2 || parts[0].length === 0 || parts[1].length === 0) {\n return null;\n }\n return parts as [string, string];\n}\n\n/**\n * Converts a Tag to a TagAliasAggregate if it follows the alias pattern.\n *\n * This function checks if a tag name follows the alias aggregate pattern and\n * creates a TagAliasAggregate object with the tag and its parsed components.\n *\n * @param tag - The Tag to convert\n * @returns A TagAliasAggregate if the tag name matches the pattern, null otherwise\n */\nexport function tagToAggregate(tag: Tag): TagAliasAggregate | null {\n const parts = isAliasAggregate(tag.name);\n if (!parts) {\n return null;\n }\n\n return {\n tag,\n contextAlias: parts[0],\n aggregateName: parts[1],\n };\n}\n\n/**\n * Converts an array of Tags to a map of aggregates.\n *\n * This function processes an array of tags, converts those that follow the alias pattern\n * to aggregates, and returns a map where keys are tag names and values are partial\n * aggregate definitions.\n *\n * @param tags - Optional array of Tags to process\n * @returns A map of aggregate definitions keyed by tag name\n */\nexport function tagsToAggregates(\n tags?: Tag[],\n): Map<string, PartialBy<AggregateDefinition, 'state' | 'fields'>> {\n const tagAliasAggregates = tags\n ?.map(tag => tagToAggregate(tag))\n .filter(tag => tag !== null);\n if (!tagAliasAggregates) {\n return new Map();\n }\n const aggregates = new Map<\n string,\n PartialBy<AggregateDefinition, 'state' | 'fields'>\n >();\n tagAliasAggregates.forEach(tagAliasAggregate => {\n aggregates.set(tagAliasAggregate.tag.name, {\n aggregate: tagAliasAggregate,\n commands: new Map(),\n events: new Map(),\n });\n });\n return aggregates;\n}\n\n/**\n * Extracts the command name from an operation ID.\n *\n * This function parses an operation ID expected to follow the format\n * \"context.aggregate.command\" and returns the command part.\n *\n * @param operationId - Optional operation ID to parse\n * @returns The command name if the operation ID follows the expected format, null otherwise\n */\nexport function operationIdToCommandName(operationId?: string): string | null {\n if (!operationId) {\n return null;\n }\n const parts = operationId.split('.');\n if (parts.length != 3) {\n return null;\n }\n return parts[2];\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n OpenAPI,\n Operation,\n Parameter,\n Reference,\n RequestBody,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\nimport {\n AggregateDefinition,\n BoundedContextAggregates,\n CommandDefinition,\n EventDefinition,\n} from './aggregate';\n\nimport { ContentTypeValues, PartialBy } from '@ahoo-wang/fetcher';\nimport { operationIdToCommandName, tagsToAggregates } from './utils';\nimport {\n extractOkResponse,\n extractOperationOkResponseJsonSchema,\n extractOperations,\n extractParameter,\n extractRequestBody,\n extractSchema,\n isReference,\n keySchema,\n MethodOperation,\n} from '../utils';\nimport { EventStreamSchema } from './types';\n\nconst CommandOkResponseRef = '#/components/responses/wow.CommandOk';\nconst IdParameterRef = '#/components/parameters/wow.id';\n\n/**\n * Resolves aggregate definitions from OpenAPI specifications.\n * Parses operations to extract commands, events, and state information for each aggregate.\n */\nexport class AggregateResolver {\n private readonly aggregates: Map<\n string,\n PartialBy<AggregateDefinition, 'state' | 'fields'>\n >;\n\n /**\n * Creates a new AggregateResolver instance.\n * @param openAPI - The OpenAPI specification to resolve aggregates from\n */\n constructor(private readonly openAPI: OpenAPI) {\n this.aggregates = tagsToAggregates(openAPI.tags);\n this.build();\n }\n\n /**\n * Builds the aggregate definitions by processing all operations in the OpenAPI spec.\n * @private\n */\n private build() {\n for (const [path, pathItem] of Object.entries(this.openAPI.paths)) {\n const methodOperations = extractOperations(pathItem);\n for (const methodOperation of methodOperations) {\n this.commands(path, methodOperation);\n this.state(methodOperation.operation);\n this.events(methodOperation.operation);\n this.fields(methodOperation.operation);\n }\n }\n }\n\n /**\n * Returns the resolved aggregate definitions.\n * @returns Map of aggregate definitions keyed by context alias\n */\n resolve(): BoundedContextAggregates {\n const resolvedContextAggregates = new Map<\n string,\n Set<AggregateDefinition>\n >();\n for (const aggregate of this.aggregates.values()) {\n if (!aggregate.state || !aggregate.fields) {\n continue;\n }\n const contextAlias = aggregate.aggregate.contextAlias;\n let aggregates = resolvedContextAggregates.get(contextAlias);\n if (!aggregates) {\n aggregates = new Set<AggregateDefinition>();\n resolvedContextAggregates.set(contextAlias, aggregates);\n }\n aggregates.add(aggregate as AggregateDefinition);\n }\n return resolvedContextAggregates;\n }\n\n /**\n * Processes command operations and adds them to the appropriate aggregates.\n * @param path - The API path\n * @param methodOperation - The HTTP method and operation details\n */\n commands(path: string, methodOperation: MethodOperation) {\n const operation = methodOperation.operation;\n if (operation.operationId === 'wow.command.send') {\n return;\n }\n const commandName = operationIdToCommandName(operation.operationId);\n if (!commandName) {\n return;\n }\n const okResponse = extractOkResponse(operation);\n if (!okResponse) {\n return;\n }\n if (!isReference(okResponse)) {\n return;\n }\n if (okResponse.$ref !== CommandOkResponseRef) {\n return;\n }\n if (!operation.requestBody) {\n return;\n }\n\n const parameters = operation.parameters ?? [];\n const idRefParameter = parameters\n .filter(p => isReference(p) && p.$ref === IdParameterRef)\n .at(0) as Reference | undefined;\n const pathParameters = parameters.filter(\n p => !isReference(p) && p.in === 'path',\n ) as Parameter[];\n if (idRefParameter) {\n const idParameter = extractParameter(\n idRefParameter,\n this.openAPI.components!,\n );\n pathParameters.push(idParameter!);\n }\n const requestBody = operation.requestBody as RequestBody;\n const commandRefSchema = requestBody.content[\n ContentTypeValues.APPLICATION_JSON\n ].schema as Reference;\n const commandKeyedSchema = keySchema(\n commandRefSchema,\n this.openAPI.components!,\n );\n commandKeyedSchema.schema.title =\n commandKeyedSchema.schema.title || operation.summary;\n commandKeyedSchema.schema.description =\n commandKeyedSchema.schema.description || operation.description;\n const commandDefinition: CommandDefinition = {\n name: commandName,\n method: methodOperation.method,\n path,\n pathParameters,\n summary: operation.summary,\n description: operation.description,\n schema: commandKeyedSchema,\n operation: operation,\n };\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n aggregate.commands.set(commandName, commandDefinition);\n });\n }\n\n /**\n * Processes state snapshot operations and associates them with aggregates.\n * @param operation - The OpenAPI operation\n */\n state(operation: Operation) {\n if (!operation.operationId?.endsWith('.snapshot_state.single')) {\n return;\n }\n const stateRefSchema = extractOperationOkResponseJsonSchema(operation);\n if (!isReference(stateRefSchema)) {\n return;\n }\n const stateKeyedSchema = keySchema(\n stateRefSchema,\n this.openAPI.components!,\n );\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n aggregate.state = stateKeyedSchema;\n });\n }\n\n /**\n * Processes event stream operations and extracts domain events for aggregates.\n * @param operation - The OpenAPI operation\n */\n events(operation: Operation) {\n if (!this.openAPI.components) {\n return;\n }\n if (!operation.operationId?.endsWith('.event.list_query')) {\n return;\n }\n const eventStreamArraySchema =\n extractOperationOkResponseJsonSchema(operation);\n if (isReference(eventStreamArraySchema)) {\n return;\n }\n const eventStreamRefSchema = eventStreamArraySchema?.items;\n if (!isReference(eventStreamRefSchema)) {\n return;\n }\n const eventStreamSchema = extractSchema(\n eventStreamRefSchema,\n this.openAPI.components,\n ) as EventStreamSchema;\n\n const events: EventDefinition[] =\n eventStreamSchema.properties.body.items.anyOf.map(domainEventSchema => {\n const eventTitle = domainEventSchema.title;\n const eventName = domainEventSchema.properties.name.const;\n const eventBodySchema = domainEventSchema.properties.body;\n const eventBodyKeyedSchema = keySchema(\n eventBodySchema,\n this.openAPI.components!,\n );\n eventBodyKeyedSchema.schema.title =\n eventBodyKeyedSchema.schema.title || domainEventSchema.title;\n return {\n title: eventTitle,\n name: eventName,\n schema: eventBodyKeyedSchema,\n };\n });\n\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n events.forEach(event => {\n aggregate.events.set(event.name, event);\n });\n });\n }\n\n /**\n * Processes field query operations and associates field schemas with aggregates.\n * @param operation - The OpenAPI operation\n */\n fields(operation: Operation): void {\n if (!this.openAPI.components) {\n return;\n }\n if (!operation.operationId?.endsWith('.snapshot.count')) {\n return;\n }\n const requestBody = extractRequestBody(\n operation.requestBody as Reference,\n this.openAPI.components,\n ) as RequestBody;\n const conditionRefSchema = requestBody.content[\n ContentTypeValues.APPLICATION_JSON\n ].schema as Reference;\n const conditionSchema = extractSchema(\n conditionRefSchema,\n this.openAPI.components,\n ) as Schema;\n const fieldRefSchema = conditionSchema.properties?.field as Reference;\n const fieldKeyedSchema = keySchema(fieldRefSchema, this.openAPI.components);\n operation.tags?.forEach(tag => {\n const aggregate = this.aggregates.get(tag);\n if (!aggregate) {\n return;\n }\n aggregate.fields = fieldKeyedSchema;\n });\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** Import path for the WOW framework types */\nexport const IMPORT_WOW_PATH = '@ahoo-wang/fetcher-wow';\n\n/** Mapping of OpenAPI schema keys to WOW framework types */\nexport const WOW_TYPE_MAPPING = {\n 'wow.command.CommandResult': 'CommandResult',\n 'wow.MessageHeaderSqlType': 'MessageHeaderSqlType',\n 'wow.api.BindingError': 'BindingError',\n 'wow.api.DefaultErrorInfo': 'ErrorInfo',\n 'wow.api.RecoverableType': 'RecoverableType',\n 'wow.api.command.DefaultDeleteAggregate': 'DeleteAggregate',\n 'wow.api.command.DefaultRecoverAggregate': 'RecoverAggregate',\n 'wow.api.messaging.FunctionInfoData': 'FunctionInfo',\n 'wow.api.messaging.FunctionKind': 'FunctionKind',\n 'wow.api.modeling.AggregateId': 'AggregateId',\n 'wow.api.query.Condition': 'Condition',\n 'wow.api.query.ConditionOptions': 'ConditionOptions',\n 'wow.api.query.ListQuery': 'ListQuery',\n 'wow.api.query.Operator': 'Operator',\n 'wow.api.query.PagedQuery': 'PagedQuery',\n 'wow.api.query.Pagination': 'Pagination',\n 'wow.api.query.Projection': 'Projection',\n 'wow.api.query.Sort': 'FieldSort',\n 'wow.api.query.Sort.Direction': 'SortDirection',\n 'wow.command.CommandStage': 'CommandStage',\n 'wow.command.SimpleWaitSignal': 'WaitSignal',\n 'wow.configuration.Aggregate': 'Aggregate',\n 'wow.configuration.BoundedContext': 'BoundedContext',\n 'wow.configuration.WowMetadata': 'WowMetadata',\n 'wow.modeling.DomainEvent': 'DomainEvent',\n 'wow.openapi.BatchResult': 'BatchResult',\n 'wow.messaging.CompensationTarget': 'CompensationTarget',\n};\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Named } from '@ahoo-wang/fetcher-wow';\nimport { IMPORT_WOW_PATH, WOW_TYPE_MAPPING } from './wowTypeMapping';\nimport { pascalCase } from '../utils';\n\n/**\n * Data Model Info\n */\nexport interface ModelInfo extends Named {\n name: string;\n path: string;\n}\n\n/**\n * Resolves model information from a schema key.\n *\n * This function parses a dot-separated schema key and extracts the model name and path.\n * It assumes that the model name is the first part that starts with an uppercase letter.\n * All parts before the model name are treated as the path.\n *\n * @example\n *\n * - \"wow.api.BindingError\" -> {path:'/wow/api',name:'BindingError'}\n * - \"compensation.ApiVersion\" -> {path:'/compensation',name:'ApiVersion'}\n * - \"ai.AiMessage.Assistant\" -> {path:'/ai',name:'AiMessageAssistant'}\n * - \"Result\" -> {path:'/',name:'Result'}\n *\n * @param schemaKey - The dot-separated schema key (e.g., \"com.example.User\")\n * @returns ModelInfo object containing the parsed name and path\n */\nexport function resolveModelInfo(schemaKey: string): ModelInfo {\n if (!schemaKey) {\n return { name: '', path: '/' };\n }\n const mappedType =\n WOW_TYPE_MAPPING[schemaKey as keyof typeof WOW_TYPE_MAPPING];\n if (mappedType) {\n return { name: mappedType, path: IMPORT_WOW_PATH };\n }\n\n const parts = schemaKey.split('.');\n let modelNameIndex = -1;\n\n // Find the first part that starts with an uppercase letter\n for (let i = 0; i < parts.length; i++) {\n if (parts[i] && /^[A-Z]/.test(parts[i])) {\n modelNameIndex = i;\n break;\n }\n }\n\n // If no part starts with uppercase letter, treat the whole thing as the name\n if (modelNameIndex === -1) {\n return { name: schemaKey, path: '/' };\n }\n\n // Construct the path from parts before the model name\n const pathParts = parts.slice(0, modelNameIndex);\n const path = pathParts.length > 0 ? `/${pathParts.join('/')}` : '/';\n\n // Construct the model name from the remaining parts\n const nameParts = parts.slice(modelNameIndex);\n const name = pascalCase(nameParts);\n\n return { name, path };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Project } from 'ts-morph';\nimport { OpenAPI } from '@ahoo-wang/fetcher-openapi';\nimport { GenerateContext, Logger } from './types';\nimport { BoundedContextAggregates } from './aggregate';\n\nexport abstract class BaseCodeGenerator implements GenerateContext {\n /** The ts-morph project instance used for code generation */\n readonly project: Project;\n /** The OpenAPI specification object */\n readonly openAPI: OpenAPI;\n /** The output directory path for generated files */\n readonly outputDir: string;\n /** Map of bounded context aggregates for domain modeling */\n readonly contextAggregates: BoundedContextAggregates;\n /** Optional logger for generation progress and errors */\n readonly logger: Logger;\n\n /**\n * Creates a new ClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n protected constructor(context: GenerateContext) {\n this.project = context.project;\n this.openAPI = context.openAPI;\n this.outputDir = context.outputDir;\n this.contextAggregates = context.contextAggregates;\n this.logger = context.logger;\n }\n\n /**\n * Generates code based on the provided context.\n * Subclasses must implement this method to define their specific generation logic.\n */\n abstract generate(): void;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Schema, Reference } from '@ahoo-wang/fetcher-openapi';\nimport { InterfaceDeclaration, JSDocableNode, SourceFile } from 'ts-morph';\nimport { GenerateContext } from '../types';\nimport { ModelInfo, resolveModelInfo } from './modelInfo';\nimport {\n addImportModelInfo,\n addJSDoc,\n CompositionSchema,\n extractComponentKey,\n getModelFileName,\n getOrCreateSourceFile,\n isArray,\n isComposition,\n isEnum,\n isPrimitive,\n isReference,\n isUnion,\n KeySchema,\n pascalCase,\n resolvePrimitiveType,\n toArrayType,\n} from '../utils';\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\n\n/**\n * Generates TypeScript models from OpenAPI schemas.\n * Handles enum, object, union, and type alias generation.\n *\n * @property project - The ts-morph project instance\n * @property openAPI - The OpenAPI specification\n * @property outputDir - The output directory for generated files\n * @property contextAggregates - Map of aggregate definitions\n */\nexport class ModelGenerator extends BaseCodeGenerator {\n constructor(context: GenerateContext) {\n super(context);\n }\n\n private getOrCreateSourceFile(modelInfo: ModelInfo): SourceFile {\n const fileName = getModelFileName(modelInfo);\n return getOrCreateSourceFile(this.project, this.outputDir, fileName);\n }\n\n /**\n * Generates models for all schemas in the OpenAPI specification.\n * Skips schemas with keys starting with 'wow.'.\n *\n * @remarks\n * This method iterates through all schemas in the OpenAPI specification\n * and generates corresponding TypeScript models for each one.\n */\n generate() {\n const schemas = this.openAPI.components?.schemas;\n if (!schemas) {\n this.logger.info('No schemas found in OpenAPI specification');\n return;\n }\n const keySchemas = this.filterSchemas(schemas);\n this.logger.progress(\n `Generating models for ${keySchemas.length} schemas`,\n );\n keySchemas.forEach((keySchema, index) => {\n this.logger.progressWithCount(\n index + 1,\n keySchemas.length,\n `Processing schema: ${keySchema.key}`,\n 2,\n );\n this.generateKeyedSchema(keySchema);\n });\n this.logger.success('Model generation completed');\n }\n\n private filterSchemas(schemas: Record<string, Schema>): KeySchema[] {\n return Object.entries(schemas).map(\n ([schemaKey, schema]) => ({\n key: schemaKey,\n schema,\n }),\n ).filter(keySchema => !this.isWowSchema(keySchema.key));\n }\n\n private isWowSchema(schemaKey: string): boolean {\n return schemaKey.startsWith('wow.');\n }\n\n /**\n * Generates a model for a specific schema key.\n * Processes enums, objects, unions, and type aliases in order.\n *\n * @param schemaKey - The key of the schema to generate\n * @param schema - The schema definition\n *\n * @remarks\n * The generation process follows this order:\n * 1. Enum processing\n * 2. Object processing\n * 3. Union processing\n * 4. Type alias processing\n */\n generateKeyedSchema({ key, schema }: KeySchema) {\n const modelInfo = resolveModelInfo(key);\n const sourceFile = this.getOrCreateSourceFile(modelInfo);\n const node = this.process(modelInfo, sourceFile, schema);\n if (node) {\n addJSDoc(node, schema.title, schema.description);\n }\n }\n\n private process(\n modelInfo: ModelInfo,\n sourceFile: SourceFile,\n schema: Schema,\n ): JSDocableNode | undefined {\n if (isEnum(schema)) {\n return sourceFile.addEnum({\n name: modelInfo.name,\n isExported: true,\n members: schema.enum\n .filter(value => typeof value === 'string' && value.length > 0)\n .map(value => ({\n name: value,\n initializer: `'${value}'`,\n })),\n });\n }\n const interfaceDeclaration = sourceFile.addInterface({\n name: modelInfo.name,\n isExported: true,\n });\n if (schema.type === 'object' && schema.properties) {\n return this.processInterface(\n sourceFile,\n modelInfo,\n schema,\n interfaceDeclaration,\n );\n }\n\n if (isComposition(schema)) {\n const compositionTypes = schema.anyOf || schema.oneOf || schema.allOf;\n compositionTypes!.forEach(compositionTypeSchema => {\n if (isReference(compositionTypeSchema)) {\n const refModelInfo = resolveModelInfo(\n extractComponentKey(compositionTypeSchema),\n );\n addImportModelInfo(\n modelInfo,\n sourceFile,\n this.outputDir,\n refModelInfo,\n );\n interfaceDeclaration.addExtends(refModelInfo.name);\n return;\n }\n this.processInterface(\n sourceFile,\n modelInfo,\n compositionTypeSchema,\n interfaceDeclaration,\n );\n });\n }\n return interfaceDeclaration;\n }\n\n private processObject(\n sourceFile: SourceFile,\n modelInfo: ModelInfo,\n schema: Schema,\n ) {\n const interfaceDeclaration = sourceFile.addInterface({\n name: modelInfo.name,\n isExported: true,\n });\n return this.processInterface(\n sourceFile,\n modelInfo,\n schema,\n interfaceDeclaration,\n );\n }\n\n private processInterface(\n sourceFile: SourceFile,\n modelInfo: ModelInfo,\n schema: Schema,\n interfaceDeclaration: InterfaceDeclaration,\n ) {\n for (const [propName, propSchema] of Object.entries(schema.properties!)) {\n const propType: string = this.resolvePropertyType(\n modelInfo,\n sourceFile,\n propName,\n propSchema,\n );\n let propertySignature = interfaceDeclaration.getProperty(propName);\n if (propertySignature) {\n propertySignature.setType(propType);\n } else {\n propertySignature = interfaceDeclaration.addProperty({\n name: propName,\n type: propType,\n });\n }\n if (!isReference(propSchema)) {\n addJSDoc(propertySignature, propSchema.title, propSchema.description);\n }\n }\n return interfaceDeclaration;\n }\n\n private resolvePropertyType(\n currentModelInfo: ModelInfo,\n sourceFile: SourceFile,\n propName: string,\n propSchema: Schema | Reference,\n ): string {\n if (isReference(propSchema)) {\n const refModelInfo = resolveModelInfo(extractComponentKey(propSchema));\n addImportModelInfo(\n currentModelInfo,\n sourceFile,\n this.outputDir,\n refModelInfo,\n );\n return refModelInfo.name;\n }\n if (propSchema.const) {\n return `'${propSchema.const}'`;\n }\n if (isArray(propSchema)) {\n const itemsType = this.resolvePropertyType(\n currentModelInfo,\n sourceFile,\n propName,\n propSchema.items!,\n );\n return toArrayType(itemsType);\n }\n if (propSchema.type && isPrimitive(propSchema.type)) {\n return resolvePrimitiveType(propSchema.type!);\n }\n if (isComposition(propSchema)) {\n return this.resolvePropertyCompositionType(\n currentModelInfo,\n sourceFile,\n propSchema,\n );\n }\n /**\n * handle object\n */\n if (propSchema.type === 'object' && propSchema.properties) {\n const propModelInfo: ModelInfo = {\n path: currentModelInfo.path,\n name: `${currentModelInfo.name}${pascalCase(propName)}`,\n };\n const interfaceDeclaration = this.processObject(\n sourceFile,\n propModelInfo,\n propSchema,\n );\n addJSDoc(interfaceDeclaration, propSchema.title, propSchema.description);\n return propModelInfo.name;\n }\n return 'any';\n }\n\n private resolvePropertyCompositionType(\n currentModelInfo: ModelInfo,\n sourceFile: SourceFile,\n schema: CompositionSchema,\n ): string {\n const compositionTypes = schema.anyOf || schema.oneOf || schema.allOf;\n const types: Set<string> = new Set<string>();\n compositionTypes!.forEach(compositionTypeSchema => {\n if (isReference(compositionTypeSchema)) {\n const refModelInfo = resolveModelInfo(\n extractComponentKey(compositionTypeSchema),\n );\n addImportModelInfo(\n currentModelInfo,\n sourceFile,\n this.outputDir,\n refModelInfo,\n );\n types.add(refModelInfo.name);\n return;\n }\n types.add(resolvePrimitiveType(compositionTypeSchema.type ?? 'string'));\n });\n const separator = isUnion(schema) ? '|' : '&';\n return Array.from(types).join(separator);\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ResourceAttributionPathSpec } from '@ahoo-wang/fetcher-wow';\nimport { Project, SourceFile } from 'ts-morph';\nimport { AggregateDefinition, TagAliasAggregate } from '../aggregate';\nimport { getOrCreateSourceFile, pascalCase } from '../utils';\n\nexport function inferPathSpecType(\n aggregateDefinition: AggregateDefinition,\n): string {\n let tenantSpecCount = 0;\n let ownerSpecCount = 0;\n aggregateDefinition.commands.forEach(command => {\n if (command.path.startsWith(ResourceAttributionPathSpec.TENANT)) {\n tenantSpecCount += 1;\n }\n if (command.path.startsWith(ResourceAttributionPathSpec.OWNER)) {\n ownerSpecCount += 1;\n }\n });\n if (tenantSpecCount === 0 && ownerSpecCount === 0) {\n return 'ResourceAttributionPathSpec.NONE';\n }\n return tenantSpecCount > ownerSpecCount\n ? 'ResourceAttributionPathSpec.TENANT'\n : 'ResourceAttributionPathSpec.OWNER';\n}\n\nexport function createClientFilePath(\n project: Project,\n outputDir: string,\n aggregate: TagAliasAggregate,\n fileName: string,\n): SourceFile {\n const filePath = `${aggregate.contextAlias}/${aggregate.aggregateName}/${fileName}.ts`;\n return getOrCreateSourceFile(project, outputDir, filePath);\n}\n\n/**\n * Generates the client class name for an aggregate.\n * @param aggregate - The aggregate metadata\n * @param suffix - The suffix to append to the aggregate name\n * @returns The generated client class name\n */\nexport function getClientName(\n aggregate: TagAliasAggregate,\n suffix: string,\n): string {\n return `${pascalCase(aggregate.aggregateName)}${suffix}`;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SourceFile, VariableDeclarationKind } from 'ts-morph';\nimport { GenerateContext } from '../types';\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\nimport { AggregateDefinition, TagAliasAggregate } from '../aggregate';\nimport { IMPORT_WOW_PATH, ModelInfo, resolveModelInfo } from '../model';\nimport { createClientFilePath, inferPathSpecType } from './utils';\nimport { addImportRefModel, camelCase } from '../utils';\n\n/**\n * Generates TypeScript query client classes for aggregates.\n * Creates query clients that can perform state queries and event streaming.\n */\nexport class QueryClientGenerator extends BaseCodeGenerator {\n /**\n * Creates a new QueryClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(context: GenerateContext) {\n super(context);\n }\n\n /**\n * Generates query client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(this.contextAggregates.values()).reduce(\n (sum, set) => sum + set.size,\n 0,\n );\n this.logger.info('--- Generating Query Clients ---');\n this.logger.progress(\n `Generating query clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing query client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processQueryClient(aggregateDefinition);\n });\n }\n this.logger.success('Query client generation completed');\n }\n\n /**\n * Creates or retrieves a source file for client generation.\n * @param aggregate - The aggregate metadata\n * @param fileName - The name of the client file\n * @returns The source file for the client\n */\n createClientFilePath(\n aggregate: TagAliasAggregate,\n fileName: string,\n ): SourceFile {\n return createClientFilePath(\n this.project,\n this.outputDir,\n aggregate,\n fileName,\n );\n }\n\n /**\n * Processes and generates query client classes for an aggregate.\n * @param aggregate - The aggregate definition\n */\n processQueryClient(aggregate: AggregateDefinition) {\n const queryClientFile = this.createClientFilePath(\n aggregate.aggregate,\n 'queryClient',\n );\n this.logger.info(\n `Processing query client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n this.logger.info(\n `Adding imports from ${IMPORT_WOW_PATH}: QueryClientFactory, QueryClientOptions, ResourceAttributionPathSpec`,\n );\n queryClientFile.addImportDeclaration({\n moduleSpecifier: IMPORT_WOW_PATH,\n namedImports: [\n 'QueryClientFactory',\n 'QueryClientOptions',\n 'ResourceAttributionPathSpec',\n ],\n });\n\n const defaultClientOptionsName = 'DEFAULT_QUERY_CLIENT_OPTIONS';\n this.logger.info(\n `Creating default query client options: ${defaultClientOptionsName}`,\n );\n queryClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: defaultClientOptionsName,\n type: 'QueryClientOptions',\n initializer: `{\n contextAlias: '${aggregate.aggregate.contextAlias}',\n aggregateName: '${aggregate.aggregate.aggregateName}',\n resourceAttribution: ${inferPathSpecType(aggregate)},\n }`,\n },\n ],\n isExported: false,\n });\n\n const eventModelInfos: ModelInfo[] = [];\n this.logger.info(\n `Processing ${aggregate.events.size} domain events for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n for (const event of aggregate.events.values()) {\n const eventModelInfo = resolveModelInfo(event.schema.key);\n this.logger.info(\n `Adding import for event model: ${eventModelInfo.name} from path: ${eventModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.outputDir, eventModelInfo);\n eventModelInfos.push(eventModelInfo);\n }\n\n const domainEventTypesName = 'DOMAIN_EVENT_TYPES';\n const eventTypeUnion = eventModelInfos.map(it => it.name).join(' | ');\n this.logger.info(\n `Creating domain event types union: ${domainEventTypesName} = ${eventTypeUnion}`,\n );\n queryClientFile.addTypeAlias({\n name: domainEventTypesName,\n type: eventTypeUnion,\n });\n\n const clientFactoryName = `${camelCase(aggregate.aggregate.aggregateName)}QueryClientFactory`;\n const stateModelInfo = resolveModelInfo(aggregate.state.key);\n const fieldsModelInfo = resolveModelInfo(aggregate.fields.key);\n\n this.logger.info(\n `Adding import for state model: ${stateModelInfo.name} from path: ${stateModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.outputDir, stateModelInfo);\n this.logger.info(\n `Adding import for fields model: ${fieldsModelInfo.name} from path: ${fieldsModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.outputDir, fieldsModelInfo);\n\n this.logger.info(`Creating query client factory: ${clientFactoryName}`);\n queryClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: clientFactoryName,\n initializer: `new QueryClientFactory<${stateModelInfo.name}, ${fieldsModelInfo.name} | string, ${domainEventTypesName}>(${defaultClientOptionsName})`,\n },\n ],\n isExported: true,\n });\n\n this.logger.success(\n `Query client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\nimport { GenerateContext } from '../types';\nimport {\n ClassDeclaration,\n DecoratorStructure,\n OptionalKind,\n Scope,\n SourceFile,\n VariableDeclarationKind,\n} from 'ts-morph';\nimport { HTTPMethod } from '@ahoo-wang/fetcher-openapi';\nimport { AggregateDefinition, CommandDefinition } from '../aggregate';\nimport { createClientFilePath, getClientName } from './utils';\nimport { IMPORT_WOW_PATH, resolveModelInfo } from '../model';\nimport { addImport, addImportRefModel, addJSDoc, camelCase } from '../utils';\n\n/**\n * Generates TypeScript command client classes for aggregates.\n * Creates command clients that can send commands to aggregates.\n */\nexport class CommandClientGenerator extends BaseCodeGenerator {\n private readonly commandEndpointPathsName = 'COMMAND_ENDPOINT_PATHS';\n private readonly defaultCommandClientOptionsName =\n 'DEFAULT_COMMAND_CLIENT_OPTIONS';\n\n /**\n * Creates a new CommandClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(context: GenerateContext) {\n super(context);\n }\n\n /**\n * Generates command client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(this.contextAggregates.values()).reduce(\n (sum, set) => sum + set.size,\n 0,\n );\n this.logger.info('--- Generating Command Clients ---');\n this.logger.progress(\n `Generating command clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing command client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processAggregate(aggregateDefinition);\n });\n }\n this.logger.success('Command client generation completed');\n }\n\n /**\n * Processes and generates command client for an aggregate.\n * @param aggregate - The aggregate definition\n */\n processAggregate(aggregate: AggregateDefinition) {\n this.logger.info(\n `Processing command client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n const commandClientFile = createClientFilePath(\n this.project,\n this.outputDir,\n aggregate.aggregate,\n 'commandClient',\n );\n\n this.logger.info(\n `Processing command endpoint paths for ${aggregate.commands.size} commands`,\n );\n this.processCommandEndpointPaths(commandClientFile, aggregate);\n\n this.logger.info(\n `Creating default command client options: ${this.defaultCommandClientOptionsName}`,\n );\n commandClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: this.defaultCommandClientOptionsName,\n type: 'ApiMetadata',\n initializer: `{\n basePath: '${aggregate.aggregate.contextAlias}'\n }`,\n },\n ],\n isExported: false,\n });\n\n this.logger.info(\n `Adding imports from ${IMPORT_WOW_PATH}: CommandRequest, CommandResult, CommandResultEventStream, DeleteAggregate, RecoverAggregate`,\n );\n commandClientFile.addImportDeclaration({\n moduleSpecifier: IMPORT_WOW_PATH,\n namedImports: [\n 'CommandRequest',\n 'CommandResult',\n 'CommandResultEventStream',\n 'DeleteAggregate',\n 'RecoverAggregate',\n ],\n isTypeOnly: true,\n });\n\n this.logger.info(\n `Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor`,\n );\n commandClientFile.addImportDeclaration({\n moduleSpecifier: '@ahoo-wang/fetcher-eventstream',\n namedImports: ['JsonEventStreamResultExtractor'],\n });\n\n this.logger.info(\n `Adding import from @ahoo-wang/fetcher: ContentTypeValues`,\n );\n addImport(commandClientFile, '@ahoo-wang/fetcher', ['ContentTypeValues']);\n\n this.logger.info(\n `Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators`,\n );\n addImport(commandClientFile, '@ahoo-wang/fetcher-decorator', [\n 'type ApiMetadata',\n 'type ApiMetadataCapable',\n 'api',\n 'post',\n 'put',\n 'patch',\n 'del',\n 'request',\n 'attribute',\n 'path',\n 'autoGeneratedError',\n ]);\n\n this.logger.info(`Generating standard command client class`);\n this.processCommandClient(commandClientFile, aggregate);\n\n this.logger.info(`Generating stream command client class`);\n this.processCommandClient(commandClientFile, aggregate, true);\n\n this.logger.success(\n `Command client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n\n processCommandEndpointPaths(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ) {\n this.logger.info(\n `Creating command endpoint paths enum: ${this.commandEndpointPathsName}`,\n );\n const enumDeclaration = clientFile.addEnum({\n name: this.commandEndpointPathsName,\n });\n aggregateDefinition.commands.forEach(command => {\n this.logger.info(\n `Adding command endpoint: ${command.name.toUpperCase()} = '${command.path}'`,\n );\n enumDeclaration.addMember({\n name: command.name.toUpperCase(),\n initializer: `'${command.path}'`,\n });\n });\n this.logger.success(\n `Command endpoint paths enum created with ${aggregateDefinition.commands.size} entries`,\n );\n }\n\n getEndpointPath(command: CommandDefinition): string {\n return `${this.commandEndpointPathsName}.${command.name.toUpperCase()}`;\n }\n\n processCommandClient(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n isStream: boolean = false,\n ) {\n let suffix = 'CommandClient';\n let apiDecorator: OptionalKind<DecoratorStructure> = {\n name: 'api',\n arguments: [],\n };\n let returnType = `Promise<CommandResult>`;\n if (isStream) {\n suffix = 'Stream' + suffix;\n apiDecorator = {\n name: 'api',\n arguments: [\n `''`,\n `{\n headers: { Accept: ContentTypeValues.TEXT_EVENT_STREAM },\n resultExtractor: JsonEventStreamResultExtractor,\n}`,\n ],\n };\n returnType = `Promise<CommandResultEventStream>`;\n }\n const commandClientName = getClientName(\n aggregateDefinition.aggregate,\n suffix,\n );\n\n const commandClient = clientFile.addClass({\n name: commandClientName,\n isExported: true,\n decorators: [apiDecorator],\n implements: ['ApiMetadataCapable'],\n });\n commandClient.addConstructor({\n parameters: [\n {\n name: 'apiMetadata',\n type: 'ApiMetadata',\n scope: Scope.Public,\n isReadonly: true,\n initializer: `${this.defaultCommandClientOptionsName}`,\n },\n ],\n });\n aggregateDefinition.commands.forEach(command => {\n this.processCommandMethod(clientFile, commandClient, command, returnType);\n });\n }\n\n private methodToDecorator(method: HTTPMethod): string {\n if (method === 'delete') {\n return 'del';\n }\n return method;\n }\n\n /**\n * Processes and generates a command method for the command client.\n * @param sourceFile - The source file containing the client\n * @param client - The client class declaration\n * @param definition - The command definition\n */\n processCommandMethod(\n sourceFile: SourceFile,\n client: ClassDeclaration,\n definition: CommandDefinition,\n returnType: string,\n ) {\n const commandModelInfo = resolveModelInfo(definition.schema.key);\n this.logger.info(\n `Adding import for command model: ${commandModelInfo.name} from path: ${commandModelInfo.path}`,\n );\n addImportRefModel(sourceFile, this.outputDir, commandModelInfo);\n\n this.logger.info(\n `Generating command method: ${camelCase(definition.name)} for command: ${definition.name}`,\n );\n this.logger.info(\n `Command method details: HTTP ${definition.method}, path: ${definition.path}, return type: ${returnType}`,\n );\n\n const parameters = definition.pathParameters.map(parameter => {\n this.logger.info(\n `Adding path parameter: ${parameter.name} (type: string)`,\n );\n return {\n name: parameter.name,\n type: 'string',\n decorators: [\n {\n name: 'path',\n arguments: [`'${parameter.name}'`],\n },\n ],\n };\n });\n\n this.logger.info(\n `Adding command request parameter: commandRequest (type: CommandRequest<${commandModelInfo.name}>)`,\n );\n parameters.push({\n name: 'commandRequest',\n type: `CommandRequest<${commandModelInfo.name}>`,\n decorators: [\n {\n name: 'request',\n arguments: [],\n },\n ],\n });\n\n this.logger.info(\n `Adding attributes parameter: attributes (type: Record<string, any>)`,\n );\n parameters.push({\n name: 'attributes',\n type: 'Record<string, any>',\n decorators: [\n {\n name: 'attribute',\n arguments: [],\n },\n ],\n });\n\n const methodDeclaration = client.addMethod({\n name: camelCase(definition.name),\n decorators: [\n {\n name: this.methodToDecorator(definition.method),\n arguments: [`${this.getEndpointPath(definition)}`],\n },\n ],\n parameters: parameters,\n returnType: returnType,\n statements: [\n `throw autoGeneratedError(${parameters.map(parameter => parameter.name).join(',')});`,\n ],\n });\n\n if (definition.summary || definition.description) {\n this.logger.info(\n `Adding JSDoc documentation for method: ${camelCase(definition.name)}`,\n );\n }\n addJSDoc(methodDeclaration, definition.summary, definition.description);\n\n this.logger.success(\n `Command method generated: ${camelCase(definition.name)}`,\n );\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BaseCodeGenerator } from '../baseCodeGenerator';\nimport { QueryClientGenerator } from './queryClientGenerator';\nimport { CommandClientGenerator } from './commandClientGenerator';\nimport { GenerateContext } from '../types';\nimport { getOrCreateSourceFile } from '../utils';\n\n/**\n * Generates TypeScript client classes for aggregates.\n * Creates query clients and command clients based on aggregate definitions.\n */\nexport class ClientGenerator extends BaseCodeGenerator {\n private readonly queryClientGenerator: QueryClientGenerator;\n private readonly commandClientGenerator: CommandClientGenerator;\n\n /**\n * Creates a new ClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(context: GenerateContext) {\n super(context);\n this.queryClientGenerator = new QueryClientGenerator(context);\n this.commandClientGenerator = new CommandClientGenerator(context);\n }\n\n /**\n * Generates client classes for all aggregates.\n */\n generate(): void {\n this.logger.info('--- Generating Clients ---');\n this.logger.progress(\n `Generating clients for ${this.contextAggregates.size} bounded contexts`,\n );\n let currentIndex = 0;\n for (const [contextAlias] of this.contextAggregates) {\n currentIndex++;\n this.logger.progressWithCount(\n currentIndex,\n this.contextAggregates.size,\n `Processing bounded context: ${contextAlias}`,\n 1,\n );\n this.processBoundedContext(contextAlias);\n }\n this.queryClientGenerator.generate();\n this.commandClientGenerator.generate();\n this.logger.success('Client generation completed');\n }\n\n /**\n * Processes a bounded context by creating a file with the context alias constant.\n * @param contextAlias - The alias of the bounded context to process\n */\n processBoundedContext(contextAlias: string) {\n const filePath = `${contextAlias}/boundedContext.ts`;\n this.logger.info(`Creating bounded context file: ${filePath}`);\n const file = getOrCreateSourceFile(this.project, this.outputDir, filePath);\n this.logger.info(\n `Adding bounded context alias constant: BOUNDED_CONTEXT_ALIAS = '${contextAlias}'`,\n );\n file.addStatements(\n `export const BOUNDED_CONTEXT_ALIAS = '${contextAlias}';`,\n );\n this.logger.success(\n `Bounded context file created successfully: ${filePath}`,\n );\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Directory, Project, SourceFile } from 'ts-morph';\nimport { GenerateContext, GeneratorOptions } from './types';\nimport { parseOpenAPI } from './utils';\nimport { AggregateResolver } from './aggregate';\nimport { ModelGenerator } from './model';\nimport { ClientGenerator } from './client';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Main code generator class that orchestrates the generation of TypeScript code from OpenAPI specifications.\n * Handles model generation, client generation, and project formatting.\n */\nexport class CodeGenerator {\n private readonly project: Project;\n\n /**\n * Creates a new CodeGenerator instance.\n * @param options - Configuration options for code generation\n */\n constructor(private readonly options: GeneratorOptions) {\n this.project = options.project;\n this.options.logger.info('CodeGenerator instance created');\n }\n\n /**\n * Generates TypeScript code from the OpenAPI specification.\n * Parses the OpenAPI spec, resolves aggregates, generates models and clients,\n * and formats the output files.\n */\n async generate(): Promise<void> {\n this.options.logger.info(\n 'Starting code generation from OpenAPI specification',\n );\n this.options.logger.info(`Input path: ${this.options.inputPath}`);\n this.options.logger.info(`Output directory: ${this.options.outputDir}`);\n\n this.options.logger.info('Parsing OpenAPI specification');\n const openAPI = await parseOpenAPI(this.options.inputPath);\n this.options.logger.info('OpenAPI specification parsed successfully');\n\n this.options.logger.info('Resolving bounded context aggregates');\n const aggregateResolver = new AggregateResolver(openAPI);\n const boundedContextAggregates = aggregateResolver.resolve();\n this.options.logger.info(\n `Resolved ${boundedContextAggregates.size} bounded context aggregates`,\n );\n\n const context: GenerateContext = {\n openAPI: openAPI,\n project: this.project,\n outputDir: this.options.outputDir,\n contextAggregates: boundedContextAggregates,\n logger: this.options.logger,\n };\n\n this.options.logger.info('Generating models');\n const modelGenerator = new ModelGenerator(context);\n modelGenerator.generate();\n this.options.logger.info('Models generated successfully');\n\n this.options.logger.info('Generating clients');\n const clientGenerator = new ClientGenerator(context);\n clientGenerator.generate();\n this.options.logger.info('Clients generated successfully');\n\n this.options.logger.info('Generating index files');\n this.generateIndex();\n this.options.logger.info('Index files generated successfully');\n\n this.options.logger.info('Optimizing source files');\n this.optimizeSourceFiles();\n this.options.logger.info('Source files optimized successfully');\n\n this.options.logger.info('Saving project to disk');\n await this.project.save();\n this.options.logger.info('Code generation completed successfully');\n }\n\n /**\n * Generates index.ts files for all subdirectories in the output directory.\n * Scans all directories, gets all .ts files in each directory,\n * and creates index.ts files with export * from './xxx' statements.\n */\n generateIndex() {\n this.options.logger.info(\n `Generating index files for output directory: ${this.options.outputDir}`,\n );\n const outputDir = this.project.getDirectory(this.options.outputDir);\n if (!outputDir) {\n this.options.logger.info(\n 'Output directory not found, skipping index generation',\n );\n return;\n }\n this.processDirectory(outputDir);\n this.options.logger.info('Index file generation completed');\n }\n\n private processDirectory(dir: Directory) {\n const subDirs = dir.getDirectories();\n this.options.logger.info(`Processing ${subDirs.length} subdirectories`);\n for (const subDir of subDirs) {\n this.options.logger.info(`Processing subdirectory: ${subDir.getPath()}`);\n this.generateIndexForDirectory(subDir);\n this.processDirectory(subDir);\n }\n }\n\n /**\n * Generates an index.ts file for a specific directory.\n * @param dir - The directory to generate index.ts for\n */\n private generateIndexForDirectory(dir: Directory) {\n const dirPath = dir.getPath();\n this.options.logger.info(`Generating index for directory: ${dirPath}`);\n\n const tsFiles = dir\n .getSourceFiles()\n .filter(\n (file: SourceFile) =>\n file.getBaseName().endsWith('.ts') &&\n file.getBaseName() !== 'index.ts',\n );\n\n // Get subdirectories using fs\n let subDirNames: string[] = [];\n try {\n subDirNames = fs.readdirSync(dirPath).filter(item => {\n const itemPath = path.join(dirPath, item);\n return fs.statSync(itemPath).isDirectory();\n });\n } catch (error) {\n this.options.logger.error(\n `Failed to read subdirectories for ${dirPath}: ${error}`,\n );\n }\n\n this.options.logger.info(\n `Found ${tsFiles.length} TypeScript files and ${subDirNames.length} subdirectories in ${dirPath}`,\n );\n\n if (tsFiles.length === 0 && subDirNames.length === 0) {\n this.options.logger.info(\n `No files or subdirectories to export in ${dirPath}, skipping index generation`,\n );\n return; // No files or subdirs to export\n }\n\n const indexFilePath = `${dirPath}/index.ts`;\n this.options.logger.info(`Creating/updating index file: ${indexFilePath}`);\n const indexFile =\n this.project.getSourceFile(indexFilePath) ||\n this.project.createSourceFile(indexFilePath, '', { overwrite: true });\n\n // Clear existing content\n indexFile.removeText();\n\n // Add export statements for .ts files\n for (const tsFile of tsFiles) {\n const relativePath = `./${tsFile.getBaseNameWithoutExtension()}`;\n this.options.logger.info(`Adding export for file: ${relativePath}`);\n indexFile.addExportDeclaration({\n moduleSpecifier: relativePath,\n isTypeOnly: false,\n namedExports: [],\n });\n }\n\n // Add export statements for subdirectories\n for (const subDirName of subDirNames) {\n const relativePath = `./${subDirName}`;\n this.options.logger.info(\n `Adding export for subdirectory: ${relativePath}`,\n );\n indexFile.addExportDeclaration({\n moduleSpecifier: relativePath,\n isTypeOnly: false,\n namedExports: [],\n });\n }\n\n this.options.logger.info(\n `Index file generated for ${dirPath} with ${tsFiles.length + subDirNames.length} exports`,\n );\n }\n\n optimizeSourceFiles() {\n const sourceFiles = this.project.getSourceFiles();\n this.options.logger.info(`Optimizing ${sourceFiles.length} source files`);\n sourceFiles.forEach((sourceFile, index) => {\n this.options.logger.info(\n `Optimizing file ${index + 1}/${sourceFiles.length}`,\n );\n sourceFile.formatText();\n sourceFile.organizeImports();\n sourceFile.fixMissingImports();\n });\n this.options.logger.info('All source files optimized');\n }\n}\n"],"names":["extractComponentKey","reference","extractSchema","components","componentKey","extractRequestBody","extractParameter","keySchema","NAMING_SEPARATORS","pascalCase","name","names","part","firstChar","rest","camelCase","pascalCaseName","loadResource","path","loadHttpResource","loadFile","url","resolve","reject","readFile","err","data","parseOpenAPI","inputPath","content","inferFileFormat","parse","trimmedContent","isReference","schema","extractOkResponseJsonSchema","okResponse","ContentTypeValues","extractOperations","pathItem","operation","extractOkResponse","extractOperationOkResponseJsonSchema","PRIMITIVE_TYPES","isPrimitive","type","isArray","isEnum","isAnyOf","isOneOf","isUnion","isAllOf","isComposition","toArrayType","resolvePrimitiveType","it","MODEL_FILE_NAME","IMPORT_ALIAS","getModelFileName","modelInfo","combineURLs","getOrCreateSourceFile","project","outputDir","filePath","fileName","file","addImport","sourceFile","moduleSpecifier","namedImports","declaration","importDeclaration","namedImport","existingNamedImport","addImportRefModel","refModelInfo","sourceDir","targetFilePath","join","relativePath","relative","addImportModelInfo","currentModel","refModel","jsDoc","title","description","filtered","v","addJSDoc","node","jsdoc","isAliasAggregate","tagName","parts","tagToAggregate","tag","tagsToAggregates","tags","tagAliasAggregates","aggregates","tagAliasAggregate","operationIdToCommandName","operationId","CommandOkResponseRef","IdParameterRef","AggregateResolver","openAPI","methodOperations","methodOperation","resolvedContextAggregates","aggregate","contextAlias","commandName","parameters","idRefParameter","p","pathParameters","idParameter","commandRefSchema","commandKeyedSchema","commandDefinition","stateRefSchema","stateKeyedSchema","eventStreamArraySchema","eventStreamRefSchema","events","domainEventSchema","eventTitle","eventName","eventBodySchema","eventBodyKeyedSchema","event","conditionRefSchema","fieldRefSchema","fieldKeyedSchema","IMPORT_WOW_PATH","WOW_TYPE_MAPPING","resolveModelInfo","schemaKey","mappedType","modelNameIndex","pathParts","nameParts","BaseCodeGenerator","context","ModelGenerator","schemas","keySchemas","index","key","value","interfaceDeclaration","compositionTypeSchema","propName","propSchema","propType","propertySignature","currentModelInfo","itemsType","propModelInfo","compositionTypes","types","separator","inferPathSpecType","aggregateDefinition","tenantSpecCount","ownerSpecCount","command","ResourceAttributionPathSpec","createClientFilePath","getClientName","suffix","QueryClientGenerator","totalAggregates","sum","set","currentIndex","queryClientFile","defaultClientOptionsName","VariableDeclarationKind","eventModelInfos","eventModelInfo","domainEventTypesName","eventTypeUnion","clientFactoryName","stateModelInfo","fieldsModelInfo","CommandClientGenerator","commandClientFile","clientFile","enumDeclaration","isStream","apiDecorator","returnType","commandClientName","commandClient","Scope","method","client","definition","commandModelInfo","parameter","methodDeclaration","ClientGenerator","CodeGenerator","options","boundedContextAggregates","dir","subDirs","subDir","dirPath","tsFiles","subDirNames","fs","item","itemPath","error","indexFilePath","indexFile","tsFile","subDirName","sourceFiles"],"mappings":"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"}
|
|
@@ -22,6 +22,8 @@ export declare class ModelGenerator extends BaseCodeGenerator {
|
|
|
22
22
|
* and generates corresponding TypeScript models for each one.
|
|
23
23
|
*/
|
|
24
24
|
generate(): void;
|
|
25
|
+
private filterSchemas;
|
|
26
|
+
private isWowSchema;
|
|
25
27
|
/**
|
|
26
28
|
* Generates a model for a specific schema key.
|
|
27
29
|
* Processes enums, objects, unions, and type aliases in order.
|