@ahoo-wang/fetcher-generator 3.8.3 → 3.8.6
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.js +1 -1
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +101 -91
- package/dist/index.js.map +1 -1
- package/dist/model/modelGenerator.d.ts.map +1 -1
- package/dist/model/typeGenerator.d.ts +2 -0
- package/dist/model/typeGenerator.d.ts.map +1 -1
- package/dist/utils/schemas.d.ts +1 -0
- package/dist/utils/schemas.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/utils/components.ts","../src/utils/naming.ts","../src/utils/references.ts","../src/utils/responses.ts","../src/utils/schemas.ts","../src/utils/operations.ts","../src/utils/resources.ts","../src/utils/parsers.ts","../src/utils/sourceFiles.ts","../src/aggregate/utils.ts","../src/aggregate/aggregateResolver.ts","../src/model/wowTypeMapping.ts","../src/model/modelInfo.ts","../src/model/typeGenerator.ts","../src/model/modelGenerator.ts","../src/client/decorators.ts","../src/client/utils.ts","../src/client/apiClientGenerator.ts","../src/client/commandClientGenerator.ts","../src/client/queryClientGenerator.ts","../src/client/clientGenerator.ts","../src/generateContext.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./?;:,()[\\]{}|\\\\]+/;\n\nexport function splitName(name: string) {\n return name.split(NAMING_SEPARATORS);\n}\n\n/**\n * Splits a name string or array of strings by common naming separators.\n *\n * This function takes a string or array of strings and splits them based on common naming\n * separators including hyphens, underscores, spaces, dots, and before uppercase letters.\n * If an array is provided, each element is split individually and the results are flattened.\n *\n * @param name - A string or array of strings to split by naming separators\n * @returns An array of string parts split by naming separators\n */\nexport function tokenizeName(name: string | string[]): string[] {\n if (Array.isArray(name)) {\n // If input is an array, split each element by naming separators and flatten the result\n return name.flatMap(part => splitCamelCase(splitName(part)));\n }\n return splitCamelCase(splitName(name));\n}\n\n/**\n * Splits camelCase strings properly, keeping consecutive uppercase letters together.\n *\n * @param parts - Array of string parts to process\n * @returns Array of properly split parts\n */\nexport function splitCamelCase(parts: string[]): string[] {\n return parts.flatMap(part => {\n if (part.length === 0) {\n return [];\n }\n\n // Split on uppercase letters that follow lowercase letters\n const result: string[] = [];\n let current = '';\n\n for (let i = 0; i < part.length; i++) {\n const char = part[i];\n const isUpper = /[A-Z]/.test(char);\n const prevIsLower = i > 0 && /[a-z]/.test(part[i - 1]);\n\n if (isUpper && prevIsLower && current) {\n result.push(current);\n current = char;\n } else {\n current += char;\n }\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n });\n}\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 const names: string[] = tokenizeName(name);\n return names\n .filter(part => part.length > 0)\n .map(part => {\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/**\n * Converts a string or array of strings to UPPER_SNAKE_CASE format.\n *\n * This function takes a string or array of strings and converts them to UPPER_SNAKE_CASE format\n * by splitting the input based on common naming separators, converting each part to uppercase,\n * and joining them with underscores. It properly handles consecutive uppercase letters\n * (like acronyms) by treating them as single units.\n *\n * @param name - A string or array of strings to convert to UPPER_SNAKE_CASE\n * @returns The UPPER_SNAKE_CASE formatted string\n */\nexport function upperSnakeCase(name: string | string[]): string {\n if (name === '' || (Array.isArray(name) && name.length === 0)) {\n return '';\n }\n\n const names = tokenizeName(name);\n return names\n .filter(part => part.length > 0)\n .map(part => part.toUpperCase())\n .join('_');\n}\n\nexport function resolvePropertyName(name: string): string {\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)) {\n return name;\n }\n\n return `'${name}'`;\n}\n\nexport function resolveEnumMemberName(name: string): string {\n if (/^\\d+$/.test(name)) {\n return `NUM_${name}`;\n }\n return resolvePropertyName(upperSnakeCase(name));\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 { ContentTypeValues } from '@ahoo-wang/fetcher';\nimport { Reference, Response, Schema } from '@ahoo-wang/fetcher-openapi';\nimport { isReference } from './references';\n\nexport function extractResponseSchema(\n contentType: string,\n response?: Response | Reference,\n): Schema | Reference | undefined {\n if (!response) {\n return;\n }\n if (isReference(response)) {\n return undefined;\n }\n\n if (!response.content) {\n return undefined;\n }\n return response.content[contentType]?.schema;\n}\n\n/**\n * Extracts the JSON schema from an OK response.\n * @param response - The response object or reference\n * @returns The JSON schema from the response content or undefined if not found\n */\nexport function extractResponseJsonSchema(\n response?: Response | Reference,\n): Schema | Reference | undefined {\n return extractResponseSchema(ContentTypeValues.APPLICATION_JSON, response);\n}\n\nexport function extractResponseEventStreamSchema(\n response?: Response | Reference,\n): Schema | Reference | undefined {\n return extractResponseSchema(ContentTypeValues.TEXT_EVENT_STREAM, response);\n}\n\nexport function extractResponseWildcardSchema(\n response?: Response | Reference,\n): Schema | Reference | undefined {\n return extractResponseSchema('*/*', response);\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, 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\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 ObjectSchema = Schema & {\n type: 'object';\n properties: Record<string, Schema | Reference>;\n};\n\nexport function isObject(schema: Schema): schema is ObjectSchema {\n return schema.type === 'object' && !!schema.properties;\n}\n\nexport type ArraySchema = Schema & { type: 'array'; items: Schema | Reference };\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 ArraySchema {\n return schema.type === 'array' && !!schema.items;\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\nexport type MapSchema = Schema & {\n type: 'object';\n additionalProperties: boolean | Schema | Reference;\n};\n\nexport function isMap(schema: Schema): schema is MapSchema {\n return (\n schema.type === 'object' &&\n !schema.properties &&\n schema.additionalProperties !== undefined\n );\n}\n\n/**\n * Checks if a schema represents an empty object.\n * @param schema - The schema to check\n * @returns True if the schema represents an empty object, false otherwise\n */\nexport function isEmptyObject(schema: Schema): boolean {\n if (schema.type !== 'object') {\n return false;\n }\n if (!schema.properties) {\n return true;\n }\n return Object.keys(schema.properties).length === 0;\n}\n\nexport function isReadOnly(schema: Schema | Reference): boolean {\n return (schema as Schema).readOnly === true;\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\nexport function resolveOptionalFields(schema: Schema): string[] {\n if (!isObject(schema)) {\n return [];\n }\n const required = schema.required || [];\n return Object.keys(schema.properties).filter(it => !required.includes(it));\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 Components,\n HTTPMethod,\n Operation,\n Parameter,\n PathItem,\n Paths,\n Reference,\n Response,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\nimport { extractParameter } from './components';\nimport { isReference } from './references';\nimport { extractResponseJsonSchema } from './responses';\nimport { isPrimitive, resolvePrimitiveType } from './schemas';\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\nexport interface OperationEndpoint extends MethodOperation {\n path: string;\n}\n\nexport function operationEndpointComparator(\n left: OperationEndpoint,\n right: OperationEndpoint,\n): number {\n if (left.operation.operationId && right.operation.operationId) {\n return left.operation.operationId.localeCompare(\n right.operation.operationId,\n );\n }\n if (left.path && right.path) {\n return left.path.localeCompare(right.path);\n }\n if (left.method && right.method) {\n return left.method.localeCompare(right.method);\n }\n return 0;\n}\n\nexport function extractOperationEndpoints(\n paths: Paths,\n): Array<OperationEndpoint> {\n const operationEndpoints: OperationEndpoint[] = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n extractOperations(pathItem).forEach(methodOperation => {\n operationEndpoints.push({\n method: methodOperation.method,\n operation: methodOperation.operation,\n path,\n });\n });\n }\n return operationEndpoints.sort(operationEndpointComparator);\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 extractResponseJsonSchema(okResponse);\n}\n\n/**\n * Extracts path parameters from an operation.\n * @param operation - The OpenAPI operation to extract path parameters from\n * @param components - The OpenAPI components object used to resolve references\n * @returns Array of path parameters\n */\nexport function extractPathParameters(\n operation: Operation,\n components: Components,\n): Parameter[] {\n if (!operation.parameters) {\n return [];\n }\n return operation.parameters\n .map(parameter => {\n if (isReference(parameter)) {\n return extractParameter(parameter, components)!;\n }\n return parameter;\n })\n .filter(parameter => parameter.in === 'path');\n}\n\nconst DEFAULT_PATH_PARAMETER_TYPE = 'string';\n\n/**\n * Resolves the type of a path parameter.\n * @param parameter - The path parameter to resolve the type for\n * @returns The resolved primitive type as a string, or the default path parameter type if the schema is missing,\n * is a reference, lacks a type, or the type is not primitive\n */\nexport function resolvePathParameterType(parameter: Parameter): string {\n if (\n !parameter.schema ||\n isReference(parameter.schema) ||\n !parameter.schema.type ||\n !isPrimitive(parameter.schema.type)\n ) {\n return DEFAULT_PATH_PARAMETER_TYPE;\n }\n return resolvePrimitiveType(parameter.schema.type);\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 { GeneratorConfiguration } from '../types';\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 async function parseConfiguration(\n configPath: string,\n): Promise<GeneratorConfiguration> {\n const content = await loadResource(configPath);\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: ${configPath}`);\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 { combineURLs } from '@ahoo-wang/fetcher';\nimport { join, relative, sep } from 'path';\nimport { JSDocableNode, Project, SourceFile } from 'ts-morph';\nimport { ModelInfo } from '../model';\nimport { Reference, Schema } from '@ahoo-wang/fetcher-openapi';\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 const sourceDir = sourceFile.getDirectoryPath();\n const targetFilePath = join(outputDir, refModelInfo.path, MODEL_FILE_NAME);\n let relativePath = relative(sourceDir, targetFilePath);\n relativePath = relativePath.replace(/\\.ts$/, '');\n // Normalize path separators to forward slashes for cross-platform compatibility\n relativePath = relativePath.split(sep).join('/');\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath;\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 * @returns The formatted JSDoc string or undefined if both title and description are empty\n */\nexport function jsDoc(\n descriptions: (string | undefined)[],\n separator = '\\n',\n): string | undefined {\n if (!Array.isArray(descriptions)) {\n return undefined;\n }\n const filtered = descriptions.filter(\n v => typeof v === 'string' && v.length > 0,\n );\n return filtered.length > 0 ? filtered.join(separator) : undefined;\n}\n\n/**\n * Adds a JSDoc comment to a node with the provided title and description.\n */\nexport function addJSDoc(\n node: JSDocableNode,\n descriptions: (string | undefined)[],\n) {\n const jsdoc = jsDoc(descriptions);\n if (!jsdoc) {\n return;\n }\n node.addJsDoc(jsdoc);\n}\n\nexport function schemaJSDoc(schema: Schema, key?: string) {\n const descriptions: (string | undefined)[] = [\n schema.title,\n schema.description,\n ];\n if (key) {\n descriptions.push(`- key: ${key}`);\n }\n if (schema.format) {\n descriptions.push(`- format: ${schema.format}`);\n }\n\n addJsonJsDoc(descriptions, schema, 'default');\n addJsonJsDoc(descriptions, schema, 'example');\n addNumericConstraintsJsDoc(descriptions, schema);\n addStringConstraintsJsDoc(descriptions, schema);\n addArrayConstraintsJsDoc(descriptions, schema);\n return descriptions;\n}\n\n/**\n * Adds a JSDoc comment to a node based on the schema's title and description.\n * @param node - The node to add the JSDoc comment to\n * @param schema - The schema containing title and description\n * @param key - The key associated with the schema\n */\nexport function addSchemaJSDoc(\n node: JSDocableNode,\n schema: Schema | Reference,\n key?: string,\n) {\n const descriptions = schemaJSDoc(schema as Schema, key);\n addJSDoc(node, descriptions);\n}\n\nexport function addMainSchemaJSDoc(\n node: JSDocableNode,\n schema: Schema | Reference,\n key?: string,\n) {\n const descriptions = schemaJSDoc(schema as Schema, key);\n jsonJsDoc(descriptions, 'schema', schema);\n addJSDoc(node, descriptions);\n}\n\nfunction addJsonJsDoc(\n descriptions: (string | undefined)[],\n schema: any,\n propertyName: keyof Schema,\n) {\n const json = schema[propertyName];\n if (!json) {\n return;\n }\n if (typeof json !== 'object') {\n descriptions.push(`- ${propertyName}: \\`${json}\\``);\n return;\n }\n jsonJsDoc(descriptions, propertyName, json);\n}\n\nfunction jsonJsDoc(\n descriptions: (string | undefined)[],\n name: string,\n json: any,\n) {\n descriptions.push(`- ${name}: `);\n descriptions.push('```json');\n descriptions.push(JSON.stringify(json, null, 2));\n descriptions.push('```');\n}\n\nfunction addNumericConstraintsJsDoc(\n descriptions: (string | undefined)[],\n schema: Schema,\n) {\n const constraintsDescriptions = ['- Numeric Constraints'];\n if (schema.minimum !== undefined) {\n constraintsDescriptions.push(` - minimum: ${schema.minimum}`);\n }\n if (schema.maximum !== undefined) {\n constraintsDescriptions.push(` - maximum: ${schema.maximum}`);\n }\n if (schema.exclusiveMinimum !== undefined) {\n constraintsDescriptions.push(\n ` - exclusiveMinimum: ${schema.exclusiveMinimum}`,\n );\n }\n if (schema.exclusiveMaximum !== undefined) {\n constraintsDescriptions.push(\n ` - exclusiveMaximum: ${schema.exclusiveMaximum}`,\n );\n }\n if (schema.multipleOf !== undefined) {\n constraintsDescriptions.push(` - multipleOf: ${schema.multipleOf}`);\n }\n if (constraintsDescriptions.length === 1) {\n return;\n }\n descriptions.push(...constraintsDescriptions);\n}\n\nfunction addStringConstraintsJsDoc(\n descriptions: (string | undefined)[],\n schema: Schema,\n) {\n const constraintsDescriptions = ['- String Constraints'];\n if (schema.minLength !== undefined) {\n constraintsDescriptions.push(` - minLength: ${schema.minLength}`);\n }\n if (schema.maxLength !== undefined) {\n constraintsDescriptions.push(` - maxLength: ${schema.maxLength}`);\n }\n if (schema.pattern !== undefined) {\n constraintsDescriptions.push(` - pattern: ${schema.pattern}`);\n }\n if (constraintsDescriptions.length === 1) {\n return;\n }\n descriptions.push(...constraintsDescriptions);\n}\n\nfunction addArrayConstraintsJsDoc(\n descriptions: (string | undefined)[],\n schema: Schema,\n) {\n const constraintsDescriptions = ['- Array Constraints'];\n if (schema.minItems !== undefined) {\n constraintsDescriptions.push(` - minItems: ${schema.minItems}`);\n }\n if (schema.maxItems !== undefined) {\n constraintsDescriptions.push(` - maxItems: ${schema.maxItems}`);\n }\n if (schema.uniqueItems !== undefined) {\n constraintsDescriptions.push(` - uniqueItems: ${schema.uniqueItems}`);\n }\n if (constraintsDescriptions.length === 1) {\n return;\n }\n descriptions.push(...constraintsDescriptions);\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 { PartialBy } from '@ahoo-wang/fetcher';\nimport { Tag } from '@ahoo-wang/fetcher-openapi';\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 {\n extractOkResponse,\n extractOperationEndpoints,\n extractOperationOkResponseJsonSchema,\n extractParameter,\n extractRequestBody,\n extractSchema,\n isReference,\n keySchema,\n MethodOperation,\n} from '../utils';\nimport { EventStreamSchema } from './types';\nimport { operationIdToCommandName, tagsToAggregates } from './utils';\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 const endpoints = extractOperationEndpoints(this.openAPI.paths);\n for (const endpoint of endpoints) {\n this.commands(endpoint.path, endpoint);\n this.state(endpoint.operation);\n this.events(endpoint.operation);\n this.fields(endpoint.operation);\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.command.CommandResultArray': 'CommandResultArray',\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.api.query.DynamicDocument': 'DynamicDocument',\n 'wow.api.query.DynamicDocumentArray': 'DynamicDocumentArray',\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 { Reference } from '@ahoo-wang/fetcher-openapi';\nimport { Named } from '@ahoo-wang/fetcher-wow';\nimport { extractComponentKey, pascalCase, upperSnakeCase } from '../utils';\nimport { IMPORT_WOW_PATH, WOW_TYPE_MAPPING } from './wowTypeMapping';\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 // 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\nexport function resolveReferenceModelInfo(reference: Reference): ModelInfo {\n const componentKey = extractComponentKey(reference);\n return resolveModelInfo(componentKey);\n}\n\nexport function resolveContextDeclarationName(contextAlias: string): string {\n const contextUpperName = upperSnakeCase(contextAlias);\n return `${contextUpperName}_BOUNDED_CONTEXT_ALIAS`;\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 { ModelInfo, resolveReferenceModelInfo } from './modelInfo';\nimport { InterfaceDeclaration, JSDocableNode, SourceFile } from 'ts-morph';\nimport { Reference, Schema } from '@ahoo-wang/fetcher-openapi';\nimport {\n addImportModelInfo,\n addMainSchemaJSDoc,\n addSchemaJSDoc,\n AllOfSchema,\n ArraySchema,\n CompositionSchema,\n EnumSchema,\n isAllOf,\n isArray,\n isComposition,\n isEnum,\n isMap,\n isObject,\n isReadOnly,\n isReference,\n jsDoc,\n KeySchema,\n MapSchema,\n ObjectSchema, resolveEnumMemberName,\n resolvePrimitiveType, resolvePropertyName,\n schemaJSDoc,\n toArrayType,\n} from '../utils';\nimport { Generator } from '../generateContext';\n\nexport class TypeGenerator implements Generator {\n constructor(\n private readonly modelInfo: ModelInfo,\n private readonly sourceFile: SourceFile,\n private readonly keySchema: KeySchema,\n private readonly outputDir: string,\n ) {\n }\n\n generate(): void {\n const node = this.process();\n if (node) {\n addMainSchemaJSDoc(node, this.keySchema.schema, this.keySchema.key);\n }\n }\n\n private process(): JSDocableNode | undefined {\n const { schema } = this.keySchema;\n if (isEnum(schema)) {\n return this.processEnum(schema);\n }\n if (isObject(schema)) {\n return this.processInterface(schema);\n }\n if (isArray(schema)) {\n return this.processArray(schema);\n }\n if (isAllOf(schema)) {\n return this.processIntersection(schema);\n }\n if (isComposition(schema)) {\n return this.processComposition(schema);\n }\n return this.processTypeAlias(schema);\n }\n\n private resolveReference(schema: Reference) {\n const refModelInfo = resolveReferenceModelInfo(schema);\n addImportModelInfo(\n this.modelInfo,\n this.sourceFile,\n this.outputDir,\n refModelInfo,\n );\n return refModelInfo;\n }\n\n private resolveAdditionalProperties(schema: Schema): string {\n if (\n schema.additionalProperties === undefined ||\n schema.additionalProperties === false\n ) {\n return '';\n }\n\n if (schema.additionalProperties === true) {\n return '[key: string]: any';\n }\n\n const valueType = this.resolveType(schema.additionalProperties);\n return `[key: string]: ${valueType}`;\n }\n\n private resolvePropertyDefinitions(schema: ObjectSchema): string[] {\n const { properties } = schema;\n return Object.entries(properties).map(([propName, propSchema]) => {\n const type = this.resolveType(propSchema);\n const resolvedPropName = resolvePropertyName(propName);\n if (!isReference(propSchema)) {\n const jsDocDescriptions = schemaJSDoc(propSchema);\n const doc = jsDoc(jsDocDescriptions, '\\n * ');\n if (doc) {\n return `\n /**\n * ${doc}\n */\n ${resolvedPropName}: ${type}\n `;\n }\n }\n return `${resolvedPropName}: ${type}`;\n });\n }\n\n private resolveObjectType(schema: Schema): string {\n const parts: string[] = [];\n if (isObject(schema)) {\n const propertyDefs = this.resolvePropertyDefinitions(schema);\n parts.push(...propertyDefs);\n }\n\n const additionalProps = this.resolveAdditionalProperties(schema);\n if (additionalProps) {\n parts.push(additionalProps);\n }\n\n if (parts.length === 0) {\n return 'Record<string, any>';\n }\n\n return `{\\n ${parts.join(';\\n ')}; \\n}`;\n }\n\n private resolveMapValueType(schema: MapSchema): string {\n if (\n schema.additionalProperties === undefined ||\n schema.additionalProperties === false ||\n schema.additionalProperties === true\n ) {\n return 'any';\n }\n return this.resolveType(schema.additionalProperties);\n }\n\n resolveType(schema: Schema | Reference): string {\n if (isReference(schema)) {\n return this.resolveReference(schema).name;\n }\n if (isMap(schema)) {\n const valueType = this.resolveMapValueType(schema);\n return `Record<string,${valueType}>`;\n }\n if (schema.const) {\n return `'${schema.const}'`;\n }\n if (isEnum(schema)) {\n return schema.enum.map(val => `\\`${val}\\``).join(' | ');\n }\n\n if (isComposition(schema)) {\n const schemas = schema.oneOf || schema.anyOf || schema.allOf || [];\n const types = schemas.map(s => this.resolveType(s));\n const separator = isAllOf(schema) ? ' & ' : ' | ';\n return `(${types.join(separator)})`;\n }\n\n if (isArray(schema)) {\n const itemType = this.resolveType(schema.items);\n return toArrayType(itemType);\n }\n if (schema.type === 'object') {\n return this.resolveObjectType(schema);\n }\n if (!schema.type) {\n return 'any';\n }\n return resolvePrimitiveType(schema.type);\n }\n\n private processEnum(schema: EnumSchema): JSDocableNode | undefined {\n return this.sourceFile.addEnum({\n name: this.modelInfo.name,\n isExported: true,\n members: schema.enum\n .filter(value => typeof value === 'string' && value.length > 0)\n .map(value => ({\n name: resolveEnumMemberName(value),\n initializer: `\\`${value}\\``,\n })),\n });\n }\n\n private addPropertyToInterface(\n interfaceDeclaration: InterfaceDeclaration,\n propName: string,\n propSchema: Schema | Reference,\n ): void {\n const propType = this.resolveType(propSchema);\n const resolvedPropName = resolvePropertyName(propName);\n let propertySignature = interfaceDeclaration.getProperty(resolvedPropName);\n if (propertySignature) {\n propertySignature.setType(propType);\n } else {\n propertySignature = interfaceDeclaration.addProperty({\n name: resolvedPropName,\n type: propType,\n isReadonly: isReadOnly(propSchema),\n });\n }\n addSchemaJSDoc(propertySignature, propSchema);\n }\n\n private processInterface(schema: ObjectSchema): JSDocableNode | undefined {\n const interfaceDeclaration = this.sourceFile.addInterface({\n name: this.modelInfo.name,\n isExported: true,\n });\n\n const properties = schema.properties || {};\n\n Object.entries(properties).forEach(([propName, propSchema]) => {\n this.addPropertyToInterface(interfaceDeclaration, propName, propSchema);\n });\n\n if (schema.additionalProperties) {\n const indexSignature = interfaceDeclaration.addIndexSignature({\n keyName: 'key',\n keyType: 'string',\n returnType: this.resolveType(\n schema.additionalProperties === true\n ? {}\n : (schema.additionalProperties as Schema | Reference),\n ),\n });\n indexSignature.addJsDoc('Additional properties');\n }\n return interfaceDeclaration;\n }\n\n private processArray(schema: ArraySchema): JSDocableNode | undefined {\n const itemType = this.resolveType(schema.items);\n return this.sourceFile.addTypeAlias({\n name: this.modelInfo.name,\n type: `Array<${itemType}>`,\n isExported: true,\n });\n }\n\n private processComposition(\n schema: CompositionSchema,\n ): JSDocableNode | undefined {\n return this.sourceFile.addTypeAlias({\n name: this.modelInfo.name,\n type: this.resolveType(schema),\n isExported: true,\n });\n }\n\n private processIntersection(schema: AllOfSchema): JSDocableNode | undefined {\n const interfaceDeclaration = this.sourceFile.addInterface({\n name: this.modelInfo.name,\n isExported: true,\n });\n schema.allOf.forEach(allOfSchema => {\n if (isReference(allOfSchema)) {\n const resolvedType = this.resolveType(allOfSchema);\n interfaceDeclaration.addExtends(resolvedType);\n return;\n }\n if (isObject(allOfSchema)) {\n Object.entries(allOfSchema.properties).forEach(\n ([propName, propSchema]) => {\n this.addPropertyToInterface(\n interfaceDeclaration,\n propName,\n propSchema,\n );\n },\n );\n }\n });\n\n return interfaceDeclaration;\n }\n\n private processTypeAlias(schema: Schema): JSDocableNode | undefined {\n return this.sourceFile.addTypeAlias({\n name: this.modelInfo.name,\n type: this.resolveType(schema),\n isExported: true,\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 { Schema } from '@ahoo-wang/fetcher-openapi';\nimport { SourceFile } from 'ts-morph';\n\nimport { GenerateContext, Generator } from '../generateContext';\nimport { getModelFileName, KeySchema, pascalCase } from '../utils';\nimport {\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n} from './modelInfo';\nimport { TypeGenerator } from './typeGenerator';\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 implements Generator {\n constructor(public readonly context: GenerateContext) {}\n\n private getOrCreateSourceFile(modelInfo: ModelInfo): SourceFile {\n const fileName = getModelFileName(modelInfo);\n return this.context.getOrCreateSourceFile(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.context.openAPI.components?.schemas;\n if (!schemas) {\n this.context.logger.info('No schemas found in OpenAPI specification');\n return;\n }\n const stateAggregatedTypeNames = this.stateAggregatedTypeNames();\n const keySchemas = this.filterSchemas(schemas, stateAggregatedTypeNames);\n this.context.logger.progress(\n `Generating models for ${keySchemas.length} schemas`,\n );\n keySchemas.forEach((keySchema, index) => {\n this.context.logger.progressWithCount(\n index + 1,\n keySchemas.length,\n `Processing schema: ${keySchema.key}`,\n 2,\n );\n this.generateKeyedSchema(keySchema);\n });\n this.context.logger.success('Model generation completed');\n }\n\n private filterSchemas(\n schemas: Record<string, Schema>,\n aggregatedTypeNames: Set<string>,\n ): KeySchema[] {\n return Object.entries(schemas)\n .map(([schemaKey, schema]) => ({\n key: schemaKey,\n schema,\n }))\n .filter(\n keySchema => !this.isWowSchema(keySchema.key, aggregatedTypeNames),\n );\n }\n\n private isWowSchema(\n schemaKey: string,\n stateAggregatedTypeNames: Set<string>,\n ): boolean {\n if (\n schemaKey !== 'wow.api.query.PagedList' &&\n schemaKey.startsWith('wow.api.query.') &&\n schemaKey.endsWith('PagedList')\n ) {\n return false;\n }\n\n if (\n schemaKey.startsWith('wow.') ||\n schemaKey.endsWith('AggregatedCondition') ||\n schemaKey.endsWith('AggregatedDomainEventStream') ||\n schemaKey.endsWith('AggregatedDomainEventStreamPagedList') ||\n schemaKey.endsWith(\n 'AggregatedDomainEventStreamServerSentEventNonNullData',\n ) ||\n schemaKey.endsWith('AggregatedListQuery') ||\n schemaKey.endsWith('AggregatedPagedQuery') ||\n schemaKey.endsWith('AggregatedSingleQuery')\n ) {\n return true;\n }\n const modelInfo = resolveModelInfo(schemaKey);\n return stateAggregatedTypeNames.has(modelInfo.name);\n }\n\n private aggregatedSchemaSuffix = [\n 'MaterializedSnapshot',\n 'MaterializedSnapshotPagedList',\n 'MaterializedSnapshotServerSentEventNonNullData',\n 'PagedList',\n 'ServerSentEventNonNullData',\n 'Snapshot',\n 'StateEvent',\n ];\n\n private stateAggregatedTypeNames() {\n const typeNames = new Set<string>();\n for (const [boundedContext, aggregates] of this.context.contextAggregates) {\n this.generateBoundedContext(boundedContext);\n for (const aggregate of aggregates) {\n this.aggregatedSchemaSuffix.forEach(suffix => {\n const modelInfo = resolveModelInfo(aggregate.state.key);\n const typeName = pascalCase(modelInfo.name) + suffix;\n typeNames.add(typeName);\n });\n }\n }\n return typeNames;\n }\n\n /**\n * Generates a model for a specific schema key.\n * Processes enums, objects, unions, and type aliases in order.\n *\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(keySchema: KeySchema) {\n const modelInfo = resolveModelInfo(keySchema.key);\n const sourceFile = this.getOrCreateSourceFile(modelInfo);\n const typeGenerator = new TypeGenerator(\n modelInfo,\n sourceFile,\n keySchema,\n this.context.outputDir,\n );\n typeGenerator.generate();\n }\n\n generateBoundedContext(contextAlias: string) {\n const filePath = `${contextAlias}/boundedContext.ts`;\n this.context.logger.info(`Creating bounded context file: ${filePath}`);\n const file = this.context.getOrCreateSourceFile(filePath);\n const contextName = resolveContextDeclarationName(contextAlias);\n file.addStatements(`export const ${contextName} = '${contextAlias}';`);\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 {\n ClassDeclaration,\n OptionalKind,\n ParameterDeclarationStructure,\n Scope,\n SourceFile,\n} from 'ts-morph';\nimport { addImport } from '../utils';\n\nexport const FETCHER_MODULE_SPECIFIER = '@ahoo-wang/fetcher';\nexport const FETCHER_NAMED_IMPORTS = [\n 'ResultExtractors'\n];\n\n/**\n * The module specifier for the fetcher-decorator package.\n */\nexport const DECORATOR_MODULE_SPECIFIER = '@ahoo-wang/fetcher-decorator';\n\n/**\n * Named imports from the fetcher-decorator package.\n */\nexport const DECORATOR_NAMED_IMPORTS = [\n 'type ApiMetadata',\n 'type ApiMetadataCapable',\n 'type ParameterRequest',\n 'api',\n 'get',\n 'post',\n 'put',\n 'patch',\n 'del',\n 'request',\n 'attribute',\n 'path',\n 'autoGeneratedError',\n];\n\nexport interface MethodReturnType {\n type: string;\n metadata?: string;\n}\n\nexport const DEFAULT_RETURN_TYPE: MethodReturnType = {\n type: 'Promise<Response>',\n metadata: `{resultExtractor: ResultExtractors.Response }`,\n};\n\nexport const STRING_RETURN_TYPE: MethodReturnType = {\n type: 'Promise<string>',\n metadata: `{resultExtractor: ResultExtractors.Text }`,\n};\n\n/**\n * Metadata configuration for stream result extraction.\n */\nexport const STREAM_RESULT_EXTRACTOR_METADATA = `{\n headers: { Accept: ContentTypeValues.TEXT_EVENT_STREAM },\n resultExtractor: JsonEventStreamResultExtractor,\n}`;\n\nexport function addImportFetcher(sourceFile: SourceFile) {\n addImport(sourceFile, FETCHER_MODULE_SPECIFIER, FETCHER_NAMED_IMPORTS);\n}\n/**\n * Adds the necessary imports for decorator functionality to the source file.\n *\n * @param sourceFile - The source file to add imports to\n *\n * @example\n * ```typescript\n * const sourceFile = project.createSourceFile('api.ts');\n * addImportDecorator(sourceFile);\n * ```\n */\nexport function addImportDecorator(sourceFile: SourceFile) {\n addImport(sourceFile, DECORATOR_MODULE_SPECIFIER, DECORATOR_NAMED_IMPORTS);\n}\n\n/**\n * Creates a new class declaration with the @api decorator.\n *\n * @param className - The name of the class to create\n * @param sourceFile - The source file to add the class to\n * @param apiArgs - Optional arguments for the @api decorator\n * @param typeParameters - Optional type parameters for the class\n * @param extendsClass - Optional class to extend\n * @returns The created class declaration\n *\n * @example\n * ```typescript\n * const sourceFile = project.createSourceFile('UserApi.ts');\n * const classDecl = createDecoratorClass('UserApi', sourceFile, ['baseUrl']);\n * ```\n */\nexport function createDecoratorClass(\n className: string,\n sourceFile: SourceFile,\n apiArgs: string[] = [],\n typeParameters: string[] = [],\n extendsClass?: string,\n): ClassDeclaration {\n return sourceFile.addClass({\n name: className,\n isExported: true,\n typeParameters: typeParameters,\n extends: extendsClass,\n decorators: [\n {\n name: 'api',\n arguments: apiArgs,\n },\n ],\n });\n}\n\n/**\n * Adds the ApiMetadataCapable interface implementation and constructor to a class declaration.\n *\n * @param classDeclaration - The class declaration to modify\n * @param initializer - Optional initializer for the apiMetadata parameter\n *\n * @example\n * ```typescript\n * const classDecl = createDecoratorClass('UserApi', sourceFile);\n * addApiMetadataCtor(classDecl, '{}');\n * ```\n */\nexport function addApiMetadataCtor(\n classDeclaration: ClassDeclaration,\n initializer?: string,\n) {\n classDeclaration.addImplements('ApiMetadataCapable');\n classDeclaration.addConstructor({\n parameters: [\n {\n name: 'apiMetadata',\n type: 'ApiMetadata',\n hasQuestionToken: initializer === undefined,\n scope: Scope.Public,\n isReadonly: true,\n initializer: initializer,\n } as OptionalKind<ParameterDeclarationStructure>,\n ],\n });\n}\n\nexport const EVENTSTREAM_MODULE_SPECIFIER = '@ahoo-wang/fetcher-eventstream';\n\nexport function addImportEventStream(sourceFile: SourceFile) {\n addImport(sourceFile, EVENTSTREAM_MODULE_SPECIFIER, [\n 'JsonEventStreamResultExtractor',\n 'type JsonServerSentEventStream',\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 {\n camelCase,\n getOrCreateSourceFile,\n pascalCase,\n splitName,\n} from '../utils';\nimport { Operation } from '@ahoo-wang/fetcher-openapi';\n\n/**\n * Infers the appropriate resource attribution path specification type based on command paths in an aggregate definition.\n *\n * This function analyzes the command paths within an aggregate to determine whether the aggregate primarily uses\n * tenant-based or owner-based resource attribution. It counts occurrences of tenant and owner path prefixes\n * and returns the most prevalent type.\n *\n * @param aggregateDefinition - The aggregate definition containing commands with path specifications\n * @returns The inferred path specification type as a string constant:\n * - 'ResourceAttributionPathSpec.NONE' if no tenant or owner paths are found\n * - 'ResourceAttributionPathSpec.TENANT' if tenant paths are more prevalent\n * - 'ResourceAttributionPathSpec.OWNER' if owner paths are more prevalent or equal\n *\n * @example\n * ```typescript\n * const aggregateDef = {\n * commands: [\n * { path: '/tenant/{tenantId}/users' },\n * { path: '/tenant/{tenantId}/orders' },\n * { path: '/owner/{ownerId}/profile' }\n * ]\n * };\n * const pathSpec = inferPathSpecType(aggregateDef);\n * // Returns: 'ResourceAttributionPathSpec.TENANT'\n * ```\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\n/**\n * Creates or retrieves a source file for a client within an aggregate's directory structure.\n *\n * This function generates the appropriate file path based on the aggregate's context alias and name,\n * then uses the project's file management utilities to create or get the source file.\n *\n * @param project - The TypeScript project instance managing the source files\n * @param outputDir - The base output directory where generated files will be placed\n * @param aggregate - The aggregate metadata containing context alias and aggregate name\n * @param fileName - The name of the file to create (without extension)\n * @returns The created or retrieved SourceFile instance\n *\n * @throws Will throw an error if the file cannot be created or retrieved\n *\n * @example\n * ```typescript\n * const project = new Project();\n * const aggregate = { contextAlias: 'user', aggregateName: 'profile' };\n * const sourceFile = createClientFilePath(project, '/output', aggregate, 'UserProfileClient');\n * // Creates/retrieves file at: /output/user/profile/UserProfileClient.ts\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\nexport function resolveClassName(\n aggregate: TagAliasAggregate,\n suffix: string,\n): string {\n return `${pascalCase(aggregate.aggregateName)}${suffix}`;\n}\n\n/**\n * Converts HTTP method names to their corresponding decorator names.\n *\n * This function handles special cases where HTTP method names need to be mapped to different\n * decorator names for compatibility with the decorator framework.\n *\n * @param method - The HTTP method name (e.g., 'get', 'post', 'delete')\n * @returns The corresponding decorator name, with 'delete' mapped to 'del'\n *\n * @example\n * ```typescript\n * methodToDecorator('get'); // Returns: 'get'\n * methodToDecorator('post'); // Returns: 'post'\n * methodToDecorator('delete'); // Returns: 'del'\n * ```\n */\nexport function methodToDecorator(method: string): string {\n if (method === 'delete') {\n return 'del';\n }\n return method;\n}\n\nconst OPERATION_METHOD_NAME_KEY = 'x-fetcher-method';\n\n/**\n * Resolves a unique method name for an OpenAPI operation.\n *\n * This function attempts to generate a unique method name for an operation by:\n * 1. Using the custom 'x-fetcher-method' extension if present\n * 2. Deriving from the operationId by trying progressively shorter suffixes\n * 3. Falling back to the full camelCase operationId if no unique name is found\n *\n * The function splits the operationId by common separators and tries to find the shortest\n * unique method name by checking from the end of the name parts.\n *\n * @param operation - The OpenAPI operation object containing operationId and other metadata\n * @param isExists - A function that checks if a method name already exists in the target class\n * @returns A unique method name string, or undefined if the operation has no operationId\n *\n * @throws Will not throw, but returns undefined for operations without operationId\n *\n * @example\n * ```typescript\n * const operation = { operationId: 'user.getProfile' };\n * const isExists = (name) => name === 'getProfile'; // Assume getProfile exists\n * const methodName = resolveMethodName(operation, isExists);\n * // Returns: 'user.getProfile' (fallback since getProfile exists)\n *\n * const operation2 = { operationId: 'user.create' };\n * const methodName2 = resolveMethodName(operation2, isExists);\n * // Returns: 'create' (unique method name found)\n * ```\n */\nexport function resolveMethodName(\n operation: Operation,\n isExists: (methodName: string) => boolean,\n): string | undefined {\n const methodName = operation[OPERATION_METHOD_NAME_KEY];\n if (methodName) {\n return methodName;\n }\n if (!operation.operationId) {\n return undefined;\n }\n\n const nameParts = splitName(operation.operationId);\n for (let i = nameParts.length - 1; i >= 0; i--) {\n const operationName = camelCase(nameParts.slice(i));\n if (isExists(operationName)) {\n continue;\n }\n return operationName;\n }\n return camelCase(nameParts);\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 { combineURLs } from '@ahoo-wang/fetcher';\nimport {\n Operation,\n Reference,\n RequestBody,\n Schema,\n Tag,\n} from '@ahoo-wang/fetcher-openapi';\nimport {\n ClassDeclaration,\n OptionalKind,\n ParameterDeclarationStructure,\n SourceFile,\n} from 'ts-morph';\nimport { GenerateContext, Generator } from '../generateContext';\nimport {\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n resolveReferenceModelInfo,\n} from '../model';\nimport {\n addImportRefModel,\n addJSDoc,\n extractOkResponse,\n extractOperationEndpoints,\n extractOperations,\n extractPathParameters,\n extractRequestBody,\n extractResponseEventStreamSchema,\n extractResponseJsonSchema,\n extractResponseWildcardSchema,\n extractSchema,\n isArray, isMap,\n isPrimitive,\n isReference,\n OperationEndpoint,\n resolvePathParameterType,\n resolvePrimitiveType, toArrayType,\n} from '../utils';\nimport {\n addApiMetadataCtor,\n addImportDecorator,\n addImportEventStream, addImportFetcher,\n createDecoratorClass,\n DEFAULT_RETURN_TYPE,\n MethodReturnType,\n STREAM_RESULT_EXTRACTOR_METADATA,\n STRING_RETURN_TYPE,\n} from './decorators';\nimport { methodToDecorator, resolveMethodName } from './utils';\n\n/**\n * Generator for creating TypeScript API client classes from OpenAPI specifications.\n * Generates client classes with proper decorators, type annotations, and method signatures.\n */\nexport class ApiClientGenerator implements Generator {\n private defaultParameterRequestType = 'ParameterRequest';\n private defaultReturnType = DEFAULT_RETURN_TYPE;\n\n private readonly apiMetadataCtorInitializer: string | undefined;\n\n /**\n * Creates a new ApiClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and configuration\n */\n constructor(public readonly context: GenerateContext) {\n this.apiMetadataCtorInitializer = this.context.currentContextAlias\n ? `{basePath:${resolveContextDeclarationName(this.context.currentContextAlias)}}`\n : undefined;\n }\n\n /**\n * Generates API client classes for all valid tags in the OpenAPI specification.\n * Processes tags, groups operations, and creates client classes with methods.\n */\n generate() {\n this.context.logger.info('Starting API client generation');\n const apiClientTags: Map<string, Tag> = this.resolveApiTags();\n this.context.logger.info(\n `Resolved ${apiClientTags.size} API client tags: ${Array.from(apiClientTags.keys()).join(', ')}`,\n );\n\n const groupOperations = this.groupOperations(apiClientTags);\n this.context.logger.info(\n `Grouped operations into ${groupOperations.size} tag groups`,\n );\n\n this.generateApiClients(apiClientTags, groupOperations);\n this.context.logger.success('API client generation completed');\n }\n\n /**\n * Generates API client classes for each tag group.\n * @param apiClientTags - Map of valid API client tags\n * @param groupOperations - Map of operations grouped by tag\n */\n private generateApiClients(\n apiClientTags: Map<string, Tag>,\n groupOperations: Map<string, Set<OperationEndpoint>>,\n ) {\n this.context.logger.info(\n `Generating ${groupOperations.size} API client classes`,\n );\n let clientCount = 0;\n for (const [tagName, operations] of groupOperations) {\n clientCount++;\n this.context.logger.progressWithCount(\n clientCount,\n groupOperations.size,\n `Generating API client for tag: ${tagName}`,\n );\n const tag = apiClientTags.get(tagName)!;\n this.generateApiClient(tag, operations);\n }\n }\n\n /**\n * Creates a new source file for the API client.\n * @param modelInfo - The model information for the client\n * @returns The created source file\n */\n private createApiClientFile(modelInfo: ModelInfo): SourceFile {\n let filePath = modelInfo.path;\n if (this.context.currentContextAlias) {\n filePath = combineURLs(this.context.currentContextAlias, filePath);\n }\n filePath = combineURLs(filePath, `${modelInfo.name}ApiClient.ts`);\n this.context.logger.info(`Creating API client file: ${filePath}`);\n return this.context.getOrCreateSourceFile(filePath);\n }\n\n /**\n * Generates a single API client class for the given tag and operations.\n * @param tag - The OpenAPI tag for the client\n * @param operations - Set of operations for this client\n */\n private generateApiClient(tag: Tag, operations: Set<OperationEndpoint>) {\n const modelInfo = resolveModelInfo(tag.name);\n this.context.logger.info(\n `Generating API client class: ${modelInfo.name}ApiClient with ${operations.size} operations`,\n );\n const apiClientFile = this.createApiClientFile(modelInfo);\n addImportFetcher(apiClientFile);\n addImportDecorator(apiClientFile);\n addImportEventStream(apiClientFile);\n const apiClientClass = createDecoratorClass(\n modelInfo.name + 'ApiClient',\n apiClientFile,\n );\n addJSDoc(apiClientClass, [tag.description]);\n addApiMetadataCtor(apiClientClass, this.apiMetadataCtorInitializer);\n this.context.logger.info(\n `Processing ${operations.size} operations for ${modelInfo.name}ApiClient`,\n );\n operations.forEach(operation => {\n this.processOperation(tag, apiClientFile, apiClientClass, operation);\n });\n this.context.logger.success(\n `Completed API client: ${modelInfo.name}ApiClient`,\n );\n }\n\n /**\n * Generates a unique method name for the operation.\n * @param apiClientClass - The client class to check for existing methods\n * @param operation - The operation to generate a name for\n * @returns A unique camelCase method name\n */\n private getMethodName(\n apiClientClass: ClassDeclaration,\n operation: Operation,\n ): string {\n const methodName = resolveMethodName(operation, name => {\n return apiClientClass.getMethod(name) !== undefined;\n });\n if (!methodName) {\n throw new Error(\n `Unable to resolve method name for apiClientClass:${apiClientClass.getName()}.`,\n );\n }\n return methodName;\n }\n\n /**\n * Resolves the request type for an operation based on its request body.\n * @param sourceFile - The source file to add imports to\n * @param operation - The operation to resolve the request type for\n * @returns The resolved request type string\n */\n private resolveRequestType(\n sourceFile: SourceFile,\n operation: Operation,\n ): string {\n if (!operation.requestBody) {\n this.context.logger.info(\n `No request body found for operation ${operation.operationId}, using default: ${this.defaultParameterRequestType}`,\n );\n return this.defaultParameterRequestType;\n }\n let requestBody: RequestBody | undefined;\n if (isReference(operation.requestBody)) {\n this.context.logger.info(\n `Extracting request body from reference for operation: ${operation.operationId}`,\n );\n requestBody = extractRequestBody(\n operation.requestBody,\n this.context.openAPI.components!,\n );\n } else {\n requestBody = operation.requestBody;\n }\n if (!requestBody) {\n this.context.logger.info(\n `Request body extraction failed for operation ${operation.operationId}, using default: ${this.defaultParameterRequestType}`,\n );\n return this.defaultParameterRequestType;\n }\n if (requestBody.content['multipart/form-data']) {\n this.context.logger.info(\n `Detected multipart/form-data content for operation ${operation.operationId}, using ParameterRequest<FormData>`,\n );\n return 'ParameterRequest<FormData>';\n }\n if (requestBody.content['application/json']) {\n const requestBodySchema = requestBody.content['application/json'].schema;\n if (isReference(requestBodySchema)) {\n const modelInfo = resolveReferenceModelInfo(requestBodySchema);\n this.context.logger.info(\n `Adding import for request body model: ${modelInfo.name} from ${modelInfo.path}`,\n );\n addImportRefModel(sourceFile, this.context.outputDir, modelInfo);\n const requestType = `ParameterRequest<${modelInfo.name}>`;\n this.context.logger.info(\n `Resolved request type for operation ${operation.operationId}: ${requestType}`,\n );\n return requestType;\n }\n }\n this.context.logger.info(\n `Using default request type for operation ${operation.operationId}: ${this.defaultParameterRequestType}`,\n );\n return this.defaultParameterRequestType;\n }\n\n /**\n * Resolves method parameters for an operation.\n * @param tag - The tag for parameter filtering\n * @param sourceFile - The source file to add imports to\n * @param operation - The operation to resolve parameters for\n * @returns Array of parameter declarations\n */\n private resolveParameters(\n tag: Tag,\n sourceFile: SourceFile,\n operation: Operation,\n ): OptionalKind<ParameterDeclarationStructure>[] {\n const pathParameters = extractPathParameters(\n operation,\n this.context.openAPI.components!,\n ).filter(parameter => {\n return !this.context.isIgnoreApiClientPathParameters(\n tag.name,\n parameter.name,\n );\n });\n this.context.logger.info(\n `Found ${pathParameters.length} path parameters for operation ${operation.operationId}`,\n );\n const parameters = pathParameters.map(parameter => {\n const parameterType = resolvePathParameterType(parameter);\n this.context.logger.info(\n `Adding path parameter: ${parameter.name} (type: ${parameterType})`,\n );\n return {\n name: parameter.name,\n type: parameterType,\n hasQuestionToken: false,\n decorators: [\n {\n name: 'path',\n arguments: [`'${parameter.name}'`],\n },\n ],\n };\n });\n const requestType = this.resolveRequestType(sourceFile, operation);\n this.context.logger.info(`Adding httpRequest parameter: ${requestType}`);\n parameters.push({\n name: 'httpRequest',\n hasQuestionToken: requestType === this.defaultParameterRequestType,\n type: `${requestType}`,\n decorators: [\n {\n name: 'request',\n arguments: [],\n },\n ],\n });\n this.context.logger.info(\n `Adding attributes parameter: Record<string, any>`,\n );\n parameters.push({\n name: 'attributes',\n hasQuestionToken: true,\n type: 'Record<string, any>',\n decorators: [\n {\n name: 'attribute',\n arguments: [],\n },\n ],\n });\n return parameters;\n }\n\n private resolveType(\n sourceFile: SourceFile,\n schema: Schema | Reference,\n ): string {\n if (isReference(schema)) {\n const modelInfo = resolveReferenceModelInfo(schema);\n addImportRefModel(sourceFile, this.context.outputDir, modelInfo);\n return modelInfo.name;\n }\n if (isArray(schema)) {\n const itemType = this.resolveType(sourceFile, schema.items);\n return toArrayType(itemType);\n }\n if (isMap(schema)) {\n const additionalProperties = schema.additionalProperties;\n if (typeof additionalProperties === 'boolean') {\n return 'Record<string, any>';\n }\n const valueType = this.resolveType(sourceFile, additionalProperties);\n return `Record<string, ${valueType}>`;\n }\n if (schema.type && isPrimitive(schema.type)) {\n return resolvePrimitiveType(schema.type);\n }\n\n return 'any';\n }\n\n /**\n * Resolves the return type for a schema.\n * @param sourceFile - The source file to add imports to\n * @param schema - The schema to resolve the return type for\n * @returns The resolved return type string\n */\n private resolveSchemaReturnType(\n sourceFile: SourceFile,\n schema: Schema | Reference,\n ): string {\n return `Promise<${this.resolveType(sourceFile, schema)}>`;\n }\n\n /**\n * Resolves the return type for an operation based on its responses.\n * @param sourceFile - The source file to add imports to\n * @param operation - The operation to resolve the return type for\n * @returns Object containing type and optional stream flag\n */\n private resolveReturnType(\n sourceFile: SourceFile,\n operation: Operation,\n ): MethodReturnType {\n const okResponse = extractOkResponse(operation);\n if (!okResponse) {\n this.context.logger.info(\n `No OK response found for operation ${operation.operationId}, using default return type: ${this.defaultReturnType.type}`,\n );\n return this.defaultReturnType;\n }\n const jsonSchema =\n extractResponseJsonSchema(okResponse) ||\n extractResponseWildcardSchema(okResponse);\n if (jsonSchema) {\n const returnType = this.resolveSchemaReturnType(sourceFile, jsonSchema);\n this.context.logger.info(\n `Resolved JSON/wildcard response return type for operation ${operation.operationId}: ${returnType}`,\n );\n return {\n type: returnType,\n metadata:\n returnType === STRING_RETURN_TYPE.type\n ? STRING_RETURN_TYPE.metadata\n : undefined,\n };\n }\n const eventStreamSchema = extractResponseEventStreamSchema(okResponse);\n if (eventStreamSchema) {\n if (isReference(eventStreamSchema)) {\n const schema = extractSchema(\n eventStreamSchema,\n this.context.openAPI.components!,\n )!;\n if (isArray(schema) && isReference(schema.items)) {\n const modelInfo = resolveReferenceModelInfo(schema.items);\n this.context.logger.info(\n `Adding import for event stream model: ${modelInfo.name} from ${modelInfo.path}`,\n );\n addImportRefModel(sourceFile, this.context.outputDir, modelInfo);\n const dataType = modelInfo.name.includes('ServerSentEvent')\n ? `${modelInfo.name}['data']`\n : modelInfo.name;\n const returnType = `Promise<JsonServerSentEventStream<${dataType}>>`;\n this.context.logger.info(\n `Resolved event stream return type for operation ${operation.operationId}: ${returnType}`,\n );\n return {\n type: returnType,\n metadata: STREAM_RESULT_EXTRACTOR_METADATA,\n };\n }\n }\n const returnType = `Promise<JsonServerSentEventStream<any>>`;\n this.context.logger.info(\n `Resolved generic event stream return type for operation ${operation.operationId}: ${returnType}`,\n );\n return { type: returnType, metadata: STREAM_RESULT_EXTRACTOR_METADATA };\n }\n this.context.logger.info(\n `Using default return type for operation ${operation.operationId}: ${this.defaultReturnType.type}`,\n );\n return this.defaultReturnType;\n }\n\n /**\n * Processes a single operation and adds it as a method to the client class.\n * @param tag - The tag for parameter filtering\n * @param sourceFile - The source file containing the client\n * @param apiClientClass - The client class to add the method to\n * @param operation - The operation to process\n */\n private processOperation(\n tag: Tag,\n sourceFile: SourceFile,\n apiClientClass: ClassDeclaration,\n operation: OperationEndpoint,\n ) {\n this.context.logger.info(\n `Processing operation: ${operation.operation.operationId} (${operation.method} ${operation.path})`,\n );\n const methodName = this.getMethodName(apiClientClass, operation.operation);\n this.context.logger.info(`Generated method name: ${methodName}`);\n const parameters = this.resolveParameters(\n tag,\n sourceFile,\n operation.operation,\n );\n const returnType = this.resolveReturnType(sourceFile, operation.operation);\n const methodDecorator = returnType.metadata\n ? {\n name: methodToDecorator(operation.method),\n arguments: [`'${operation.path}'`, returnType.metadata],\n }\n : {\n name: methodToDecorator(operation.method),\n arguments: [`'${operation.path}'`],\n };\n this.context.logger.info(\n `Creating method with ${parameters.length} parameters, return type: ${returnType.type}`,\n );\n const methodDeclaration = apiClientClass.addMethod({\n name: methodName,\n decorators: [methodDecorator],\n parameters: parameters,\n returnType: returnType.type,\n statements: [\n `throw autoGeneratedError(${parameters.map(parameter => parameter.name).join(',')});`,\n ],\n });\n addJSDoc(methodDeclaration, [\n operation.operation.summary,\n operation.operation.description,\n `- operationId: \\`${operation.operation.operationId}\\``,\n `- path: \\`${operation.path}\\``,\n ]);\n this.context.logger.success(`Operation method generated: ${methodName}`);\n }\n\n /**\n * Groups operations by their tags for client generation.\n * @param apiClientTags - Map of valid API client tags\n * @returns Map of operations grouped by tag name\n */\n private groupOperations(\n apiClientTags: Map<string, Tag>,\n ): Map<string, Set<OperationEndpoint>> {\n this.context.logger.info('Grouping operations by API client tags');\n const operations: Map<string, Set<OperationEndpoint>> = new Map();\n const availableEndpoints = extractOperationEndpoints(\n this.context.openAPI.paths,\n ).filter(endpoint => {\n if (!endpoint.operation.operationId) {\n return false;\n }\n const operationTags = endpoint.operation.tags;\n if (!operationTags || operationTags.length == 0) {\n return false;\n }\n return operationTags.every(tagName => {\n return apiClientTags.has(tagName);\n });\n });\n let totalOperations = 0;\n for (const endpoint of availableEndpoints) {\n endpoint.operation.tags!.forEach(tagName => {\n if (!operations.has(tagName)) {\n operations.set(tagName, new Set());\n }\n operations.get(tagName)!.add(endpoint);\n totalOperations++;\n });\n }\n this.context.logger.info(\n `Grouped ${totalOperations} operations into ${operations.size} tag groups`,\n );\n return operations;\n }\n\n private shouldIgnoreTag(tagName: string): boolean {\n return (\n tagName === 'wow' ||\n tagName === 'Actuator' ||\n this.isAggregateTag(tagName)\n );\n }\n\n /**\n * Resolves valid API client tags from the OpenAPI specification.\n * Filters out system tags like 'wow' and 'Actuator' and aggregate tags.\n * @returns Map of valid API client tags\n */\n private resolveApiTags(): Map<string, Tag> {\n this.context.logger.info(\n 'Resolving API client tags from OpenAPI specification',\n );\n const apiClientTags: Map<string, Tag> = new Map<string, Tag>();\n const totalTags = this.context.openAPI.tags?.length || 0;\n for (const pathItem of Object.values(this.context.openAPI.paths)) {\n extractOperations(pathItem).forEach(methodOperation => {\n methodOperation.operation.tags?.forEach(tagName => {\n if (!this.shouldIgnoreTag(tagName) && !apiClientTags.has(tagName)) {\n apiClientTags.set(tagName, {\n name: tagName,\n description: '',\n });\n }\n });\n });\n }\n let filteredTags = 0;\n this.context.openAPI.tags?.forEach(tag => {\n if (!this.shouldIgnoreTag(tag.name)) {\n apiClientTags.set(tag.name, tag);\n filteredTags++;\n this.context.logger.info(`Included API client tag: ${tag.name}`);\n } else {\n this.context.logger.info(\n `Excluded tag: ${tag.name} (wow/Actuator/aggregate)`,\n );\n }\n });\n this.context.logger.info(\n `Resolved ${filteredTags} API client tags from ${totalTags} total tags`,\n );\n return apiClientTags;\n }\n\n private isAggregateTag(tagName: string): boolean {\n for (const aggregates of this.context.contextAggregates.values()) {\n for (const aggregate of aggregates) {\n if (aggregate.aggregate.tag.name === tagName) {\n return true;\n }\n }\n }\n return false;\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 {\n ClassDeclaration,\n OptionalKind,\n ParameterDeclarationStructure,\n SourceFile,\n VariableDeclarationKind,\n} from 'ts-morph';\nimport {\n AggregateDefinition,\n CommandDefinition,\n TagAliasAggregate,\n} from '../aggregate';\nimport { GenerateContext, Generator } from '../generateContext';\nimport {\n IMPORT_WOW_PATH,\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n} from '../model';\nimport {\n addImport,\n addImportRefModel,\n addJSDoc,\n camelCase,\n isEmptyObject,\n resolveOptionalFields,\n resolvePathParameterType,\n} from '../utils';\nimport {\n addApiMetadataCtor,\n addImportDecorator,\n addImportEventStream,\n createDecoratorClass,\n STREAM_RESULT_EXTRACTOR_METADATA,\n} from './decorators';\nimport {\n createClientFilePath,\n resolveClassName,\n methodToDecorator,\n} 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 implements Generator {\n private readonly commandEndpointPathsSuffix = 'CommandEndpointPaths';\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(public readonly context: GenerateContext) {}\n\n /**\n * Generates command client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(\n this.context.contextAggregates.values(),\n ).reduce((sum, set) => sum + set.size, 0);\n this.context.logger.info('--- Generating Command Clients ---');\n this.context.logger.progress(\n `Generating command clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.context.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.context.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing command client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processAggregate(aggregateDefinition);\n });\n }\n this.context.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.context.logger.info(\n `Processing command client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n const commandClientFile = createClientFilePath(\n this.context.project,\n this.context.outputDir,\n aggregate.aggregate,\n 'commandClient',\n );\n\n this.context.logger.info(\n `Processing command endpoint paths for ${aggregate.commands.size} commands`,\n );\n\n const aggregateCommandEndpointPathsName = this.processCommandEndpointPaths(\n commandClientFile,\n aggregate,\n );\n this.processCommandTypes(commandClientFile, aggregate);\n this.context.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: ${resolveContextDeclarationName(aggregate.aggregate.contextAlias)}\n }`,\n },\n ],\n isExported: false,\n });\n\n this.context.logger.info(\n `Adding imports from ${IMPORT_WOW_PATH}: CommandRequest, CommandResult, CommandResultEventStream, CommandBody, DeleteAggregateCommand, RecoverAggregateCommand`,\n );\n commandClientFile.addImportDeclaration({\n moduleSpecifier: IMPORT_WOW_PATH,\n namedImports: [\n 'CommandRequest',\n 'CommandResult',\n 'CommandResultEventStream',\n 'CommandBody',\n 'DeleteAggregateCommand',\n 'RecoverAggregateCommand',\n ],\n isTypeOnly: true,\n });\n\n this.context.logger.info(\n `Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor`,\n );\n addImportEventStream(commandClientFile);\n\n this.context.logger.info(\n `Adding import from @ahoo-wang/fetcher: ContentTypeValues`,\n );\n addImport(commandClientFile, '@ahoo-wang/fetcher', ['ContentTypeValues']);\n\n this.context.logger.info(\n `Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators`,\n );\n addImportDecorator(commandClientFile);\n this.context.logger.info(`Generating standard command client class`);\n this.processCommandClient(\n commandClientFile,\n aggregate,\n aggregateCommandEndpointPathsName,\n );\n\n this.context.logger.info(`Generating stream command client class`);\n this.processStreamCommandClient(commandClientFile, aggregate);\n\n this.context.logger.success(\n `Command client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n\n resolveAggregateCommandEndpointPathsName(\n aggregate: TagAliasAggregate,\n ): string {\n return resolveClassName(aggregate, this.commandEndpointPathsSuffix);\n }\n\n processCommandEndpointPaths(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ): string {\n const aggregateCommandEndpointPathsName =\n this.resolveAggregateCommandEndpointPathsName(\n aggregateDefinition.aggregate,\n );\n this.context.logger.info(\n `Creating command endpoint paths enum: ${aggregateCommandEndpointPathsName}`,\n );\n const enumDeclaration = clientFile.addEnum({\n name: aggregateCommandEndpointPathsName,\n isExported: true,\n });\n aggregateDefinition.commands.forEach(command => {\n this.context.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.context.logger.success(\n `Command endpoint paths enum created with ${aggregateDefinition.commands.size} entries`,\n );\n return aggregateCommandEndpointPathsName;\n }\n\n resolveCommandTypeName(definition: CommandDefinition): [ModelInfo, string] {\n const commandModelInfo = resolveModelInfo(definition.schema.key);\n return [commandModelInfo, commandModelInfo.name + 'Command'];\n }\n\n resolveCommandType(clientFile: SourceFile, definition: CommandDefinition) {\n const [commandModelInfo, commandName] =\n this.resolveCommandTypeName(definition);\n if (commandModelInfo.path === IMPORT_WOW_PATH) {\n return;\n }\n addImportRefModel(clientFile, this.context.outputDir, commandModelInfo);\n let commandType = `${commandModelInfo.name}`;\n const optionalFields = resolveOptionalFields(definition.schema.schema)\n .map(fieldName => `'${fieldName}'`)\n .join(' | ');\n if (optionalFields !== '') {\n commandType = `PartialBy<${commandType},${optionalFields}>`;\n }\n commandType = `CommandBody<${commandType}>`;\n clientFile.addTypeAlias({\n name: commandName,\n type: `${commandType}`,\n isExported: true,\n });\n }\n\n processCommandTypes(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ) {\n aggregateDefinition.commands.forEach(command => {\n this.resolveCommandType(clientFile, command);\n });\n }\n\n getEndpointPath(\n aggregateCommandEndpointPathsName: string,\n command: CommandDefinition,\n ): string {\n return `${aggregateCommandEndpointPathsName}.${command.name.toUpperCase()}`;\n }\n\n processCommandClient(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n aggregateCommandEndpointPathsName: string,\n ) {\n const commandClientName = resolveClassName(\n aggregateDefinition.aggregate,\n 'CommandClient',\n );\n const commandClient = createDecoratorClass(\n commandClientName,\n clientFile,\n [],\n ['R = CommandResult'],\n );\n addApiMetadataCtor(commandClient, this.defaultCommandClientOptionsName);\n\n aggregateDefinition.commands.forEach(command => {\n this.processCommandMethod(\n aggregateDefinition,\n commandClient,\n command,\n aggregateCommandEndpointPathsName,\n );\n });\n }\n\n processStreamCommandClient(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ) {\n const commandClientName = resolveClassName(\n aggregateDefinition.aggregate,\n 'CommandClient',\n );\n const commandStreamClientName = resolveClassName(\n aggregateDefinition.aggregate,\n 'StreamCommandClient',\n );\n\n const streamCommandClient = createDecoratorClass(\n commandStreamClientName,\n clientFile,\n [`''`, STREAM_RESULT_EXTRACTOR_METADATA],\n [],\n `${commandClientName}<CommandResultEventStream>`,\n );\n streamCommandClient.addConstructor({\n parameters: [\n {\n name: 'apiMetadata',\n type: 'ApiMetadata',\n initializer: this.defaultCommandClientOptionsName,\n } as OptionalKind<ParameterDeclarationStructure>,\n ],\n statements: `super(apiMetadata);`,\n });\n }\n\n private resolveParameters(\n tag: Tag,\n definition: CommandDefinition,\n ): OptionalKind<ParameterDeclarationStructure>[] {\n const [commandModelInfo, commandName] =\n this.resolveCommandTypeName(definition);\n this.context.logger.info(\n `Adding import for command model: ${commandModelInfo.name} from path: ${commandModelInfo.path}`,\n );\n\n const parameters = definition.pathParameters\n .filter(parameter => {\n return !this.context.isIgnoreCommandClientPathParameters(\n tag.name,\n parameter.name,\n );\n })\n .map(parameter => {\n const parameterType = resolvePathParameterType(parameter);\n this.context.logger.info(\n `Adding path parameter: ${parameter.name} (type: ${parameterType})`,\n );\n return {\n name: parameter.name,\n type: parameterType,\n hasQuestionToken: false,\n decorators: [\n {\n name: 'path',\n arguments: [`'${parameter.name}'`],\n },\n ],\n };\n });\n\n this.context.logger.info(\n `Adding command request parameter: commandRequest (type: CommandRequest<${commandName}>)`,\n );\n parameters.push({\n name: 'commandRequest',\n hasQuestionToken: isEmptyObject(definition.schema.schema),\n type: `CommandRequest<${commandName}>`,\n decorators: [\n {\n name: 'request',\n arguments: [],\n },\n ],\n });\n\n this.context.logger.info(\n `Adding attributes parameter: attributes (type: Record<string, any>)`,\n );\n parameters.push({\n name: 'attributes',\n hasQuestionToken: true,\n type: 'Record<string, any>',\n decorators: [\n {\n name: 'attribute',\n arguments: [],\n },\n ],\n });\n return parameters;\n }\n\n processCommandMethod(\n aggregate: AggregateDefinition,\n client: ClassDeclaration,\n definition: CommandDefinition,\n aggregateCommandEndpointPathsName: string,\n ) {\n this.context.logger.info(\n `Generating command method: ${camelCase(definition.name)} for command: ${definition.name}`,\n );\n this.context.logger.info(\n `Command method details: HTTP ${definition.method}, path: ${definition.path}`,\n );\n const parameters = this.resolveParameters(\n aggregate.aggregate.tag,\n definition,\n );\n const methodDeclaration = client.addMethod({\n name: camelCase(definition.name),\n decorators: [\n {\n name: methodToDecorator(definition.method),\n arguments: [\n `${this.getEndpointPath(aggregateCommandEndpointPathsName, definition)}`,\n ],\n },\n ],\n parameters: parameters,\n returnType: 'Promise<R>',\n statements: `throw autoGeneratedError(${parameters.map(parameter => parameter.name).join(',')});`,\n });\n\n this.context.logger.info(\n `Adding JSDoc documentation for method: ${camelCase(definition.name)}`,\n );\n addJSDoc(methodDeclaration, [\n definition.summary,\n definition.description,\n `- operationId: \\`${definition.operation.operationId}\\``,\n `- path: \\`${definition.path}\\``,\n ]);\n\n this.context.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 { SourceFile, VariableDeclarationKind } from 'ts-morph';\nimport { AggregateDefinition, TagAliasAggregate } from '../aggregate';\nimport { GenerateContext, Generator } from '../generateContext';\nimport {\n IMPORT_WOW_PATH,\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n} from '../model';\nimport { addImportRefModel, camelCase } from '../utils';\nimport {\n createClientFilePath,\n inferPathSpecType,\n resolveClassName,\n} 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 implements Generator {\n private readonly domainEventTypeSuffix = 'DomainEventType';\n private readonly domainEventTypeMapTitleSuffix = 'DomainEventTypeMapTitle';\n\n /**\n * Creates a new QueryClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(public readonly context: GenerateContext) {}\n\n /**\n * Generates query client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(\n this.context.contextAggregates.values(),\n ).reduce((sum, set) => sum + set.size, 0);\n this.context.logger.info('--- Generating Query Clients ---');\n this.context.logger.progress(\n `Generating query clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.context.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.context.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing query client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processQueryClient(aggregateDefinition);\n });\n }\n this.context.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.context.project,\n this.context.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.context.logger.info(\n `Processing query client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n this.context.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.context.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: ${resolveContextDeclarationName(aggregate.aggregate.contextAlias)},\n aggregateName: '${aggregate.aggregate.aggregateName}',\n resourceAttribution: ${inferPathSpecType(aggregate)},\n }`,\n },\n ],\n isExported: false,\n });\n this.processAggregateDomainEventTypes(aggregate, queryClientFile);\n const aggregateDomainEventType = this.processAggregateDomainEventType(\n aggregate,\n queryClientFile,\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.context.logger.info(\n `Adding import for state model: ${stateModelInfo.name} from path: ${stateModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.context.outputDir, stateModelInfo);\n this.context.logger.info(\n `Adding import for fields model: ${fieldsModelInfo.name} from path: ${fieldsModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.context.outputDir, fieldsModelInfo);\n\n this.context.logger.info(\n `Creating query client factory: ${clientFactoryName}`,\n );\n queryClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: clientFactoryName,\n initializer: `new QueryClientFactory<${stateModelInfo.name}, ${fieldsModelInfo.name} | string, ${aggregateDomainEventType}>(${defaultClientOptionsName})`,\n },\n ],\n isExported: true,\n });\n\n this.context.logger.success(\n `Query client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n\n private processAggregateDomainEventType(\n aggregate: AggregateDefinition,\n queryClientFile: SourceFile,\n ) {\n const eventModelInfos: ModelInfo[] = [];\n this.context.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.context.logger.info(\n `Adding import for event model: ${eventModelInfo.name} from path: ${eventModelInfo.path}`,\n );\n addImportRefModel(\n queryClientFile,\n this.context.outputDir,\n eventModelInfo,\n );\n eventModelInfos.push(eventModelInfo);\n }\n const aggregateDomainEventType = resolveClassName(\n aggregate.aggregate,\n this.domainEventTypeSuffix,\n );\n const eventTypeUnion = eventModelInfos.map(it => it.name).join(' | ');\n this.context.logger.info(\n `Creating domain event types union: ${aggregateDomainEventType} = ${eventTypeUnion}`,\n );\n queryClientFile.addTypeAlias({\n isExported: true,\n name: aggregateDomainEventType,\n type: eventTypeUnion,\n });\n return aggregateDomainEventType;\n }\n\n private processAggregateDomainEventTypes(\n aggregate: AggregateDefinition,\n queryClientFile: SourceFile,\n ) {\n const aggregateDomainEventTypes = resolveClassName(\n aggregate.aggregate,\n this.domainEventTypeMapTitleSuffix,\n );\n const enumDeclaration = queryClientFile.addEnum({\n name: aggregateDomainEventTypes,\n isExported: true,\n });\n for (const event of aggregate.events.values()) {\n enumDeclaration.addMember({\n name: event.name,\n initializer: `'${event.title}'`,\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 { GenerateContext, Generator } from '../generateContext';\nimport { ApiClientGenerator } from './apiClientGenerator';\nimport { CommandClientGenerator } from './commandClientGenerator';\nimport { QueryClientGenerator } from './queryClientGenerator';\n\n/**\n * Generates TypeScript client classes for aggregates.\n * Creates query clients and command clients based on aggregate definitions.\n */\nexport class ClientGenerator implements Generator {\n private readonly queryClientGenerator: QueryClientGenerator;\n private readonly commandClientGenerator: CommandClientGenerator;\n private readonly apiClientGenerator: ApiClientGenerator;\n\n /**\n * Creates a new ClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(public readonly context: GenerateContext) {\n this.queryClientGenerator = new QueryClientGenerator(context);\n this.commandClientGenerator = new CommandClientGenerator(context);\n this.apiClientGenerator = new ApiClientGenerator(context);\n }\n\n /**\n * Generates client classes for all aggregates.\n */\n generate(): void {\n this.context.logger.info('--- Generating Clients ---');\n this.context.logger.progress(\n `Generating clients for ${this.context.contextAggregates.size} bounded contexts`,\n );\n let currentIndex = 0;\n for (const [contextAlias] of this.context.contextAggregates) {\n currentIndex++;\n this.context.logger.progressWithCount(\n currentIndex,\n this.context.contextAggregates.size,\n `Processing bounded context: ${contextAlias}`,\n 1,\n );\n }\n this.queryClientGenerator.generate();\n this.commandClientGenerator.generate();\n this.apiClientGenerator.generate();\n this.context.logger.success('Client generation completed');\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 { Project, SourceFile } from 'ts-morph';\nimport { BoundedContextAggregates } from './aggregate';\nimport { GenerateContextInit, GeneratorConfiguration, Logger } from './types';\nimport { getOrCreateSourceFile } from './utils';\n\nexport class GenerateContext implements GenerateContextInit {\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 readonly config: GeneratorConfiguration;\n private readonly defaultIgnorePathParameters = ['tenantId', 'ownerId'];\n readonly currentContextAlias: string | undefined;\n\n constructor(context: GenerateContextInit) {\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 this.config = context.config ?? {};\n this.currentContextAlias = this.openAPI.info['x-wow-context-alias'];\n }\n\n getOrCreateSourceFile(filePath: string): SourceFile {\n return getOrCreateSourceFile(this.project, this.outputDir, filePath);\n }\n\n isIgnoreApiClientPathParameters(\n tagName: string,\n parameterName: string,\n ): boolean {\n const ignorePathParameters =\n this.config.apiClients?.[tagName]?.ignorePathParameters ??\n this.defaultIgnorePathParameters;\n return ignorePathParameters.includes(parameterName);\n }\n\n isIgnoreCommandClientPathParameters(\n tagName: string,\n parameterName: string,\n ): boolean {\n return this.defaultIgnorePathParameters.includes(parameterName);\n }\n}\n\nexport interface Generator {\n /**\n * Generates code based on the provided context.\n * Subclasses must implement this method to define their specific generation logic.\n */\n 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 { Directory, Project, SourceFile } from 'ts-morph';\nimport { AggregateResolver } from './aggregate';\nimport { ClientGenerator } from './client';\nimport { GenerateContext } from './generateContext';\nimport { ModelGenerator } from './model';\nimport { GeneratorConfiguration, GeneratorOptions } from './types';\nimport { parseConfiguration, parseOpenAPI } from './utils';\n\n/**\n * Default path to the generator configuration file.\n * This path is used when no custom config path is provided in the generator options.\n */\nexport const DEFAULT_CONFIG_PATH = './fetcher-generator.config.json';\n\n/**\n * Main code generator class that orchestrates the generation of TypeScript code from OpenAPI specifications.\n * This class handles the entire code generation process, including parsing OpenAPI specs,\n * resolving aggregates, generating models and clients, and formatting the output.\n *\n * @example\n * ```typescript\n * const generator = new CodeGenerator({\n * inputPath: './openapi.yaml',\n * outputDir: './generated',\n * tsConfigFilePath: './tsconfig.json',\n * logger: new ConsoleLogger(),\n * });\n * await generator.generate();\n * ```\n */\nexport class CodeGenerator {\n private readonly project: Project;\n\n /**\n * Creates a new CodeGenerator instance with the specified options.\n *\n * @param options - Configuration options for the code generation process, including input/output paths, TypeScript config, and logger.\n * @throws Error if the project initialization fails due to invalid TypeScript configuration or missing files.\n */\n constructor(private readonly options: GeneratorOptions) {\n this.project = new Project(options);\n this.options.logger.info(\n `Project instance created with tsConfigFilePath: ${this.options.tsConfigFilePath}`,\n );\n }\n\n /**\n * Generates TypeScript code from the OpenAPI specification.\n * This method performs the following steps:\n * 1. Parses the OpenAPI specification from the input path.\n * 2. Resolves bounded context aggregates.\n * 3. Parses the generator configuration.\n * 4. Generates models and clients.\n * 5. Creates index files for the output directory.\n * 6. Optimizes and formats the generated source files.\n * 7. Saves the project to disk.\n *\n * @returns A promise that resolves when code generation is complete.\n * @throws Error if OpenAPI parsing fails, configuration parsing fails, or file operations fail.\n *\n * @example\n * ```typescript\n * await generator.generate();\n * ```\n */\n async generate(): Promise<void> {\n this.options.logger.info(\n 'Starting code generation from OpenAPI specification',\n );\n const currentWorkingDir = process.cwd();\n this.options.logger.info(`Work directory: ${currentWorkingDir}`);\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 const configPath = this.options.configPath ?? DEFAULT_CONFIG_PATH;\n let config: GeneratorConfiguration = {};\n try {\n this.options.logger.info(`Parsing configuration file: ${configPath}`);\n config = await parseConfiguration(configPath);\n } catch (e) {\n this.options.logger.info(`Configuration file parsing failed: ${e}`);\n }\n\n const context: GenerateContext = new GenerateContext({\n openAPI: openAPI,\n project: this.project,\n outputDir: this.options.outputDir,\n contextAggregates: boundedContextAggregates,\n logger: this.options.logger,\n config: config,\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 const outputDir = this.project.getDirectory(this.options.outputDir);\n if (!outputDir) {\n this.options.logger.info('Output directory not found.');\n return;\n }\n this.options.logger.info('Generating index files');\n this.generateIndex(outputDir);\n this.options.logger.info('Index files generated successfully');\n\n this.options.logger.info('Optimizing source files');\n this.optimizeSourceFiles(outputDir);\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 * This method recursively processes all directories under the output directory,\n * creating index.ts files that export all TypeScript files and subdirectories.\n *\n * @param outputDir - The root output directory to generate index files for.\n *\n * @example\n * ```typescript\n * const outputDir = project.getDirectory('./generated');\n * generator.generateIndex(outputDir);\n * ```\n */\n generateIndex(outputDir: Directory) {\n this.options.logger.info(\n `Generating index files for output directory: ${this.options.outputDir}`,\n );\n this.processDirectory(outputDir);\n this.generateIndexForDirectory(outputDir);\n this.options.logger.info('Index file generation completed');\n }\n\n /**\n * Recursively processes all subdirectories to generate index files.\n * @param dir - The directory to process.\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 * Collects all .ts files (excluding index.ts) and subdirectories,\n * then creates export statements for each.\n *\n * @param dir - The directory to generate the index file 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 const subDirs: Directory[] = dir.getDirectories();\n\n this.options.logger.info(\n `Found ${tsFiles.length} TypeScript files and ${subDirs.length} subdirectories in ${dirPath}`,\n );\n\n if (tsFiles.length === 0 && subDirs.length === 0) {\n this.options.logger.info(\n `No files or subdirectories to export in ${dirPath}, skipping index generation`,\n );\n return;\n }\n\n const indexFilePath = `${dirPath}/index.ts`;\n const indexFile =\n this.project.getSourceFile(indexFilePath) ||\n this.project.createSourceFile(indexFilePath, '', { overwrite: true });\n\n indexFile.removeText();\n\n for (const tsFile of tsFiles) {\n const relativePath = `./${tsFile.getBaseNameWithoutExtension()}`;\n indexFile.addExportDeclaration({\n moduleSpecifier: relativePath,\n isTypeOnly: false,\n namedExports: [],\n });\n }\n\n for (const subDir of subDirs) {\n const relativePath = `./${subDir.getBaseName()}`;\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 + subDirs.length} exports`,\n );\n }\n\n /**\n * Optimizes all source files in the output directory.\n * Performs formatting, import organization, and fixes missing imports.\n *\n * @param outputDir - The root output directory containing source files to optimize.\n */\n optimizeSourceFiles(outputDir: Directory) {\n const sourceFiles = outputDir.getDescendantSourceFiles();\n this.options.logger.info(\n `Optimizing ${sourceFiles.length} source files in ${outputDir.getPath()}`,\n );\n sourceFiles.forEach((sourceFile, index) => {\n this.options.logger.info(\n `Optimizing file [${sourceFile.getFilePath()}] - ${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","splitName","name","tokenizeName","part","splitCamelCase","parts","result","current","i","char","isUpper","prevIsLower","pascalCase","firstChar","rest","camelCase","pascalCaseName","upperSnakeCase","resolvePropertyName","resolveEnumMemberName","isReference","schema","extractResponseSchema","contentType","response","extractResponseJsonSchema","ContentTypeValues","extractResponseEventStreamSchema","extractResponseWildcardSchema","PRIMITIVE_TYPES","isPrimitive","type","isEnum","isObject","isArray","isAnyOf","isOneOf","isAllOf","isComposition","toArrayType","isMap","isEmptyObject","isReadOnly","resolvePrimitiveType","it","resolveOptionalFields","required","operationEndpointComparator","left","right","extractOperationEndpoints","paths","operationEndpoints","path","pathItem","extractOperations","methodOperation","operation","extractOkResponse","extractOperationOkResponseJsonSchema","okResponse","extractPathParameters","parameter","DEFAULT_PATH_PARAMETER_TYPE","resolvePathParameterType","loadResource","loadHttpResource","loadFile","url","resolve","reject","readFile","err","data","parseOpenAPI","inputPath","content","inferFileFormat","parse","parseConfiguration","configPath","trimmedContent","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","sep","addImportModelInfo","currentModel","refModel","jsDoc","descriptions","separator","filtered","v","addJSDoc","node","jsdoc","schemaJSDoc","key","addJsonJsDoc","addNumericConstraintsJsDoc","addStringConstraintsJsDoc","addArrayConstraintsJsDoc","addSchemaJSDoc","addMainSchemaJSDoc","jsonJsDoc","propertyName","json","constraintsDescriptions","isAliasAggregate","tagName","tagToAggregate","tag","tagsToAggregates","tags","tagAliasAggregates","aggregates","tagAliasAggregate","operationIdToCommandName","operationId","CommandOkResponseRef","IdParameterRef","AggregateResolver","openAPI","endpoints","endpoint","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","resolveReferenceModelInfo","resolveContextDeclarationName","TypeGenerator","properties","propName","propSchema","resolvedPropName","jsDocDescriptions","doc","propertyDefs","additionalProps","val","types","s","itemType","value","interfaceDeclaration","propType","propertySignature","allOfSchema","resolvedType","ModelGenerator","context","schemas","stateAggregatedTypeNames","keySchemas","index","aggregatedTypeNames","typeNames","boundedContext","suffix","typeName","contextName","FETCHER_MODULE_SPECIFIER","FETCHER_NAMED_IMPORTS","DECORATOR_MODULE_SPECIFIER","DECORATOR_NAMED_IMPORTS","DEFAULT_RETURN_TYPE","STRING_RETURN_TYPE","STREAM_RESULT_EXTRACTOR_METADATA","addImportFetcher","addImportDecorator","createDecoratorClass","className","apiArgs","typeParameters","extendsClass","addApiMetadataCtor","classDeclaration","initializer","Scope","EVENTSTREAM_MODULE_SPECIFIER","addImportEventStream","inferPathSpecType","aggregateDefinition","tenantSpecCount","ownerSpecCount","command","ResourceAttributionPathSpec","createClientFilePath","resolveClassName","methodToDecorator","method","OPERATION_METHOD_NAME_KEY","resolveMethodName","isExists","methodName","operationName","ApiClientGenerator","apiClientTags","groupOperations","clientCount","operations","apiClientFile","apiClientClass","requestBody","requestBodySchema","requestType","parameterType","additionalProperties","jsonSchema","returnType","eventStreamSchema","methodDecorator","methodDeclaration","availableEndpoints","operationTags","totalOperations","totalTags","filteredTags","CommandClientGenerator","totalAggregates","sum","set","currentIndex","commandClientFile","aggregateCommandEndpointPathsName","VariableDeclarationKind","clientFile","enumDeclaration","definition","commandModelInfo","commandType","optionalFields","fieldName","commandClientName","commandClient","commandStreamClientName","client","QueryClientGenerator","queryClientFile","defaultClientOptionsName","aggregateDomainEventType","clientFactoryName","stateModelInfo","fieldsModelInfo","eventModelInfos","eventModelInfo","eventTypeUnion","aggregateDomainEventTypes","ClientGenerator","GenerateContext","parameterName","DEFAULT_CONFIG_PATH","CodeGenerator","options","Project","currentWorkingDir","boundedContextAggregates","config","e","dir","subDirs","subDir","dirPath","tsFiles","indexFilePath","indexFile","tsFile","sourceFiles"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/utils/components.ts","../src/utils/naming.ts","../src/utils/references.ts","../src/utils/responses.ts","../src/utils/schemas.ts","../src/utils/operations.ts","../src/utils/resources.ts","../src/utils/parsers.ts","../src/utils/sourceFiles.ts","../src/aggregate/utils.ts","../src/aggregate/aggregateResolver.ts","../src/model/wowTypeMapping.ts","../src/model/modelInfo.ts","../src/model/typeGenerator.ts","../src/model/modelGenerator.ts","../src/client/decorators.ts","../src/client/utils.ts","../src/client/apiClientGenerator.ts","../src/client/commandClientGenerator.ts","../src/client/queryClientGenerator.ts","../src/client/clientGenerator.ts","../src/generateContext.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./?;:,()[\\]{}|\\\\]+/;\n\nexport function splitName(name: string) {\n return name.split(NAMING_SEPARATORS);\n}\n\n/**\n * Splits a name string or array of strings by common naming separators.\n *\n * This function takes a string or array of strings and splits them based on common naming\n * separators including hyphens, underscores, spaces, dots, and before uppercase letters.\n * If an array is provided, each element is split individually and the results are flattened.\n *\n * @param name - A string or array of strings to split by naming separators\n * @returns An array of string parts split by naming separators\n */\nexport function tokenizeName(name: string | string[]): string[] {\n if (Array.isArray(name)) {\n // If input is an array, split each element by naming separators and flatten the result\n return name.flatMap(part => splitCamelCase(splitName(part)));\n }\n return splitCamelCase(splitName(name));\n}\n\n/**\n * Splits camelCase strings properly, keeping consecutive uppercase letters together.\n *\n * @param parts - Array of string parts to process\n * @returns Array of properly split parts\n */\nexport function splitCamelCase(parts: string[]): string[] {\n return parts.flatMap(part => {\n if (part.length === 0) {\n return [];\n }\n\n // Split on uppercase letters that follow lowercase letters\n const result: string[] = [];\n let current = '';\n\n for (let i = 0; i < part.length; i++) {\n const char = part[i];\n const isUpper = /[A-Z]/.test(char);\n const prevIsLower = i > 0 && /[a-z]/.test(part[i - 1]);\n\n if (isUpper && prevIsLower && current) {\n result.push(current);\n current = char;\n } else {\n current += char;\n }\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n });\n}\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 const names: string[] = tokenizeName(name);\n return names\n .filter(part => part.length > 0)\n .map(part => {\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/**\n * Converts a string or array of strings to UPPER_SNAKE_CASE format.\n *\n * This function takes a string or array of strings and converts them to UPPER_SNAKE_CASE format\n * by splitting the input based on common naming separators, converting each part to uppercase,\n * and joining them with underscores. It properly handles consecutive uppercase letters\n * (like acronyms) by treating them as single units.\n *\n * @param name - A string or array of strings to convert to UPPER_SNAKE_CASE\n * @returns The UPPER_SNAKE_CASE formatted string\n */\nexport function upperSnakeCase(name: string | string[]): string {\n if (name === '' || (Array.isArray(name) && name.length === 0)) {\n return '';\n }\n\n const names = tokenizeName(name);\n return names\n .filter(part => part.length > 0)\n .map(part => part.toUpperCase())\n .join('_');\n}\n\nexport function resolvePropertyName(name: string): string {\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)) {\n return name;\n }\n\n return `'${name}'`;\n}\n\nexport function resolveEnumMemberName(name: string): string {\n if (/^\\d+$/.test(name)) {\n return `NUM_${name}`;\n }\n return resolvePropertyName(upperSnakeCase(name));\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 { ContentTypeValues } from '@ahoo-wang/fetcher';\nimport { Reference, Response, Schema } from '@ahoo-wang/fetcher-openapi';\nimport { isReference } from './references';\n\nexport function extractResponseSchema(\n contentType: string,\n response?: Response | Reference,\n): Schema | Reference | undefined {\n if (!response) {\n return;\n }\n if (isReference(response)) {\n return undefined;\n }\n\n if (!response.content) {\n return undefined;\n }\n return response.content[contentType]?.schema;\n}\n\n/**\n * Extracts the JSON schema from an OK response.\n * @param response - The response object or reference\n * @returns The JSON schema from the response content or undefined if not found\n */\nexport function extractResponseJsonSchema(\n response?: Response | Reference,\n): Schema | Reference | undefined {\n return extractResponseSchema(ContentTypeValues.APPLICATION_JSON, response);\n}\n\nexport function extractResponseEventStreamSchema(\n response?: Response | Reference,\n): Schema | Reference | undefined {\n return extractResponseSchema(ContentTypeValues.TEXT_EVENT_STREAM, response);\n}\n\nexport function extractResponseWildcardSchema(\n response?: Response | Reference,\n): Schema | Reference | undefined {\n return extractResponseSchema('*/*', response);\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, 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\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 ObjectSchema = Schema & {\n type: 'object';\n properties: Record<string, Schema | Reference>;\n};\n\nexport function isObject(schema: Schema): schema is ObjectSchema {\n return schema.type === 'object' && !!schema.properties;\n}\n\nexport type ArraySchema = Schema & { type: 'array'; items: Schema | Reference };\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 ArraySchema {\n return schema.type === 'array' && !!schema.items;\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\nexport type MapSchema = Schema & {\n type: 'object';\n additionalProperties: boolean | Schema | Reference;\n};\n\nexport function isMap(schema: Schema): schema is MapSchema {\n return (\n schema.type === 'object' &&\n !schema.properties &&\n schema.additionalProperties !== undefined\n );\n}\n\nconst X_MAP_KEY_SCHEMA = 'x-map-key-schema';\n\nexport function getMapKeySchema(schema: Schema): Schema | Reference | undefined {\n return schema[X_MAP_KEY_SCHEMA];\n}\n\n/**\n * Checks if a schema represents an empty object.\n * @param schema - The schema to check\n * @returns True if the schema represents an empty object, false otherwise\n */\nexport function isEmptyObject(schema: Schema): boolean {\n if (schema.type !== 'object') {\n return false;\n }\n if (!schema.properties) {\n return true;\n }\n return Object.keys(schema.properties).length === 0;\n}\n\nexport function isReadOnly(schema: Schema | Reference): boolean {\n return (schema as Schema).readOnly === true;\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\nexport function resolveOptionalFields(schema: Schema): string[] {\n if (!isObject(schema)) {\n return [];\n }\n const required = schema.required || [];\n return Object.keys(schema.properties).filter(it => !required.includes(it));\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 Components,\n HTTPMethod,\n Operation,\n Parameter,\n PathItem,\n Paths,\n Reference,\n Response,\n Schema,\n} from '@ahoo-wang/fetcher-openapi';\nimport { extractParameter } from './components';\nimport { isReference } from './references';\nimport { extractResponseJsonSchema } from './responses';\nimport { isPrimitive, resolvePrimitiveType } from './schemas';\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\nexport interface OperationEndpoint extends MethodOperation {\n path: string;\n}\n\nexport function operationEndpointComparator(\n left: OperationEndpoint,\n right: OperationEndpoint,\n): number {\n if (left.operation.operationId && right.operation.operationId) {\n return left.operation.operationId.localeCompare(\n right.operation.operationId,\n );\n }\n if (left.path && right.path) {\n return left.path.localeCompare(right.path);\n }\n if (left.method && right.method) {\n return left.method.localeCompare(right.method);\n }\n return 0;\n}\n\nexport function extractOperationEndpoints(\n paths: Paths,\n): Array<OperationEndpoint> {\n const operationEndpoints: OperationEndpoint[] = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n extractOperations(pathItem).forEach(methodOperation => {\n operationEndpoints.push({\n method: methodOperation.method,\n operation: methodOperation.operation,\n path,\n });\n });\n }\n return operationEndpoints.sort(operationEndpointComparator);\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 extractResponseJsonSchema(okResponse);\n}\n\n/**\n * Extracts path parameters from an operation.\n * @param operation - The OpenAPI operation to extract path parameters from\n * @param components - The OpenAPI components object used to resolve references\n * @returns Array of path parameters\n */\nexport function extractPathParameters(\n operation: Operation,\n components: Components,\n): Parameter[] {\n if (!operation.parameters) {\n return [];\n }\n return operation.parameters\n .map(parameter => {\n if (isReference(parameter)) {\n return extractParameter(parameter, components)!;\n }\n return parameter;\n })\n .filter(parameter => parameter.in === 'path');\n}\n\nconst DEFAULT_PATH_PARAMETER_TYPE = 'string';\n\n/**\n * Resolves the type of a path parameter.\n * @param parameter - The path parameter to resolve the type for\n * @returns The resolved primitive type as a string, or the default path parameter type if the schema is missing,\n * is a reference, lacks a type, or the type is not primitive\n */\nexport function resolvePathParameterType(parameter: Parameter): string {\n if (\n !parameter.schema ||\n isReference(parameter.schema) ||\n !parameter.schema.type ||\n !isPrimitive(parameter.schema.type)\n ) {\n return DEFAULT_PATH_PARAMETER_TYPE;\n }\n return resolvePrimitiveType(parameter.schema.type);\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 { GeneratorConfiguration } from '../types';\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 async function parseConfiguration(\n configPath: string,\n): Promise<GeneratorConfiguration> {\n const content = await loadResource(configPath);\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: ${configPath}`);\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 { combineURLs } from '@ahoo-wang/fetcher';\nimport { join, relative, sep } from 'path';\nimport { JSDocableNode, Project, SourceFile } from 'ts-morph';\nimport { ModelInfo } from '../model';\nimport { Reference, Schema } from '@ahoo-wang/fetcher-openapi';\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 const sourceDir = sourceFile.getDirectoryPath();\n const targetFilePath = join(outputDir, refModelInfo.path, MODEL_FILE_NAME);\n let relativePath = relative(sourceDir, targetFilePath);\n relativePath = relativePath.replace(/\\.ts$/, '');\n // Normalize path separators to forward slashes for cross-platform compatibility\n relativePath = relativePath.split(sep).join('/');\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath;\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 * @returns The formatted JSDoc string or undefined if both title and description are empty\n */\nexport function jsDoc(\n descriptions: (string | undefined)[],\n separator = '\\n',\n): string | undefined {\n if (!Array.isArray(descriptions)) {\n return undefined;\n }\n const filtered = descriptions.filter(\n v => typeof v === 'string' && v.length > 0,\n );\n return filtered.length > 0 ? filtered.join(separator) : undefined;\n}\n\n/**\n * Adds a JSDoc comment to a node with the provided title and description.\n */\nexport function addJSDoc(\n node: JSDocableNode,\n descriptions: (string | undefined)[],\n) {\n const jsdoc = jsDoc(descriptions);\n if (!jsdoc) {\n return;\n }\n node.addJsDoc(jsdoc);\n}\n\nexport function schemaJSDoc(schema: Schema, key?: string) {\n const descriptions: (string | undefined)[] = [\n schema.title,\n schema.description,\n ];\n if (key) {\n descriptions.push(`- key: ${key}`);\n }\n if (schema.format) {\n descriptions.push(`- format: ${schema.format}`);\n }\n\n addJsonJsDoc(descriptions, schema, 'default');\n addJsonJsDoc(descriptions, schema, 'example');\n addNumericConstraintsJsDoc(descriptions, schema);\n addStringConstraintsJsDoc(descriptions, schema);\n addArrayConstraintsJsDoc(descriptions, schema);\n return descriptions;\n}\n\n/**\n * Adds a JSDoc comment to a node based on the schema's title and description.\n * @param node - The node to add the JSDoc comment to\n * @param schema - The schema containing title and description\n * @param key - The key associated with the schema\n */\nexport function addSchemaJSDoc(\n node: JSDocableNode,\n schema: Schema | Reference,\n key?: string,\n) {\n const descriptions = schemaJSDoc(schema as Schema, key);\n addJSDoc(node, descriptions);\n}\n\nexport function addMainSchemaJSDoc(\n node: JSDocableNode,\n schema: Schema | Reference,\n key?: string,\n) {\n const descriptions = schemaJSDoc(schema as Schema, key);\n jsonJsDoc(descriptions, 'schema', schema);\n addJSDoc(node, descriptions);\n}\n\nfunction addJsonJsDoc(\n descriptions: (string | undefined)[],\n schema: any,\n propertyName: keyof Schema,\n) {\n const json = schema[propertyName];\n if (!json) {\n return;\n }\n if (typeof json !== 'object') {\n descriptions.push(`- ${propertyName}: \\`${json}\\``);\n return;\n }\n jsonJsDoc(descriptions, propertyName, json);\n}\n\nfunction jsonJsDoc(\n descriptions: (string | undefined)[],\n name: string,\n json: any,\n) {\n descriptions.push(`- ${name}: `);\n descriptions.push('```json');\n descriptions.push(JSON.stringify(json, null, 2));\n descriptions.push('```');\n}\n\nfunction addNumericConstraintsJsDoc(\n descriptions: (string | undefined)[],\n schema: Schema,\n) {\n const constraintsDescriptions = ['- Numeric Constraints'];\n if (schema.minimum !== undefined) {\n constraintsDescriptions.push(` - minimum: ${schema.minimum}`);\n }\n if (schema.maximum !== undefined) {\n constraintsDescriptions.push(` - maximum: ${schema.maximum}`);\n }\n if (schema.exclusiveMinimum !== undefined) {\n constraintsDescriptions.push(\n ` - exclusiveMinimum: ${schema.exclusiveMinimum}`,\n );\n }\n if (schema.exclusiveMaximum !== undefined) {\n constraintsDescriptions.push(\n ` - exclusiveMaximum: ${schema.exclusiveMaximum}`,\n );\n }\n if (schema.multipleOf !== undefined) {\n constraintsDescriptions.push(` - multipleOf: ${schema.multipleOf}`);\n }\n if (constraintsDescriptions.length === 1) {\n return;\n }\n descriptions.push(...constraintsDescriptions);\n}\n\nfunction addStringConstraintsJsDoc(\n descriptions: (string | undefined)[],\n schema: Schema,\n) {\n const constraintsDescriptions = ['- String Constraints'];\n if (schema.minLength !== undefined) {\n constraintsDescriptions.push(` - minLength: ${schema.minLength}`);\n }\n if (schema.maxLength !== undefined) {\n constraintsDescriptions.push(` - maxLength: ${schema.maxLength}`);\n }\n if (schema.pattern !== undefined) {\n constraintsDescriptions.push(` - pattern: ${schema.pattern}`);\n }\n if (constraintsDescriptions.length === 1) {\n return;\n }\n descriptions.push(...constraintsDescriptions);\n}\n\nfunction addArrayConstraintsJsDoc(\n descriptions: (string | undefined)[],\n schema: Schema,\n) {\n const constraintsDescriptions = ['- Array Constraints'];\n if (schema.minItems !== undefined) {\n constraintsDescriptions.push(` - minItems: ${schema.minItems}`);\n }\n if (schema.maxItems !== undefined) {\n constraintsDescriptions.push(` - maxItems: ${schema.maxItems}`);\n }\n if (schema.uniqueItems !== undefined) {\n constraintsDescriptions.push(` - uniqueItems: ${schema.uniqueItems}`);\n }\n if (constraintsDescriptions.length === 1) {\n return;\n }\n descriptions.push(...constraintsDescriptions);\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 { PartialBy } from '@ahoo-wang/fetcher';\nimport { Tag } from '@ahoo-wang/fetcher-openapi';\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 {\n extractOkResponse,\n extractOperationEndpoints,\n extractOperationOkResponseJsonSchema,\n extractParameter,\n extractRequestBody,\n extractSchema,\n isReference,\n keySchema,\n MethodOperation,\n} from '../utils';\nimport { EventStreamSchema } from './types';\nimport { operationIdToCommandName, tagsToAggregates } from './utils';\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 const endpoints = extractOperationEndpoints(this.openAPI.paths);\n for (const endpoint of endpoints) {\n this.commands(endpoint.path, endpoint);\n this.state(endpoint.operation);\n this.events(endpoint.operation);\n this.fields(endpoint.operation);\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.command.CommandResultArray': 'CommandResultArray',\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.api.query.DynamicDocument': 'DynamicDocument',\n 'wow.api.query.DynamicDocumentArray': 'DynamicDocumentArray',\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 { Reference } from '@ahoo-wang/fetcher-openapi';\nimport { Named } from '@ahoo-wang/fetcher-wow';\nimport { extractComponentKey, pascalCase, upperSnakeCase } from '../utils';\nimport { IMPORT_WOW_PATH, WOW_TYPE_MAPPING } from './wowTypeMapping';\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 // 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\nexport function resolveReferenceModelInfo(reference: Reference): ModelInfo {\n const componentKey = extractComponentKey(reference);\n return resolveModelInfo(componentKey);\n}\n\nexport function resolveContextDeclarationName(contextAlias: string): string {\n const contextUpperName = upperSnakeCase(contextAlias);\n return `${contextUpperName}_BOUNDED_CONTEXT_ALIAS`;\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 { ModelInfo, resolveReferenceModelInfo } from './modelInfo';\nimport { InterfaceDeclaration, JSDocableNode, SourceFile } from 'ts-morph';\nimport { Reference, Schema } from '@ahoo-wang/fetcher-openapi';\nimport {\n addImportModelInfo,\n addMainSchemaJSDoc,\n addSchemaJSDoc,\n AllOfSchema,\n ArraySchema,\n CompositionSchema,\n EnumSchema, getMapKeySchema,\n isAllOf,\n isArray,\n isComposition,\n isEnum,\n isMap,\n isObject,\n isReadOnly,\n isReference,\n jsDoc,\n KeySchema,\n MapSchema,\n ObjectSchema, resolveEnumMemberName,\n resolvePrimitiveType, resolvePropertyName,\n schemaJSDoc,\n toArrayType,\n} from '../utils';\nimport { Generator } from '../generateContext';\n\nexport class TypeGenerator implements Generator {\n constructor(\n private readonly modelInfo: ModelInfo,\n private readonly sourceFile: SourceFile,\n private readonly keySchema: KeySchema,\n private readonly outputDir: string,\n ) {\n }\n\n generate(): void {\n const node = this.process();\n if (node) {\n addMainSchemaJSDoc(node, this.keySchema.schema, this.keySchema.key);\n }\n }\n\n private process(): JSDocableNode | undefined {\n const { schema } = this.keySchema;\n if (isEnum(schema)) {\n return this.processEnum(schema);\n }\n if (isObject(schema)) {\n return this.processInterface(schema);\n }\n if (isArray(schema)) {\n return this.processArray(schema);\n }\n if (isAllOf(schema)) {\n return this.processIntersection(schema);\n }\n if (isComposition(schema)) {\n return this.processComposition(schema);\n }\n return this.processTypeAlias(schema);\n }\n\n private resolveReference(schema: Reference) {\n const refModelInfo = resolveReferenceModelInfo(schema);\n addImportModelInfo(\n this.modelInfo,\n this.sourceFile,\n this.outputDir,\n refModelInfo,\n );\n return refModelInfo;\n }\n\n private resolveAdditionalProperties(schema: Schema): string {\n if (\n schema.additionalProperties === undefined ||\n schema.additionalProperties === false\n ) {\n return '';\n }\n\n if (schema.additionalProperties === true) {\n return '[key: string]: any';\n }\n\n const valueType = this.resolveType(schema.additionalProperties);\n return `[key: string]: ${valueType}`;\n }\n\n private resolvePropertyDefinitions(schema: ObjectSchema): string[] {\n const { properties } = schema;\n return Object.entries(properties).map(([propName, propSchema]) => {\n const type = this.resolveType(propSchema);\n const resolvedPropName = resolvePropertyName(propName);\n if (!isReference(propSchema)) {\n const jsDocDescriptions = schemaJSDoc(propSchema);\n const doc = jsDoc(jsDocDescriptions, '\\n * ');\n if (doc) {\n return `\n /**\n * ${doc}\n */\n ${resolvedPropName}: ${type}\n `;\n }\n }\n return `${resolvedPropName}: ${type}`;\n });\n }\n\n private resolveObjectType(schema: Schema): string {\n const parts: string[] = [];\n if (isObject(schema)) {\n const propertyDefs = this.resolvePropertyDefinitions(schema);\n parts.push(...propertyDefs);\n }\n\n const additionalProps = this.resolveAdditionalProperties(schema);\n if (additionalProps) {\n parts.push(additionalProps);\n }\n\n if (parts.length === 0) {\n return 'Record<string, any>';\n }\n\n return `{\\n ${parts.join(';\\n ')}; \\n}`;\n }\n\n private resolveMapValueType(schema: MapSchema): string {\n if (\n schema.additionalProperties === undefined ||\n schema.additionalProperties === false ||\n schema.additionalProperties === true\n ) {\n return 'any';\n }\n return this.resolveType(schema.additionalProperties);\n }\n\n private resolveMapKeyType(schema: Schema): string {\n const mapKeySchema = getMapKeySchema(schema);\n if (!mapKeySchema) {\n return 'string';\n }\n return this.resolveType(mapKeySchema)\n }\n\n private resolveMapType(schema: MapSchema): string {\n const keyType = this.resolveMapKeyType(schema);\n const valueType = this.resolveMapValueType(schema);\n return `Record<${keyType},${valueType}>`;\n }\n\n\n resolveType(schema: Schema | Reference): string {\n if (isReference(schema)) {\n return this.resolveReference(schema).name;\n }\n if (isMap(schema)) {\n return this.resolveMapType(schema);\n }\n if (schema.const) {\n return `'${schema.const}'`;\n }\n if (isEnum(schema)) {\n return schema.enum.map(val => `\\`${val}\\``).join(' | ');\n }\n\n if (isComposition(schema)) {\n const schemas = schema.oneOf || schema.anyOf || schema.allOf || [];\n const types = schemas.map(s => this.resolveType(s));\n const separator = isAllOf(schema) ? ' & ' : ' | ';\n return `(${types.join(separator)})`;\n }\n\n if (isArray(schema)) {\n const itemType = this.resolveType(schema.items);\n return toArrayType(itemType);\n }\n if (schema.type === 'object') {\n return this.resolveObjectType(schema);\n }\n if (!schema.type) {\n return 'any';\n }\n return resolvePrimitiveType(schema.type);\n }\n\n private processEnum(schema: EnumSchema): JSDocableNode | undefined {\n return this.sourceFile.addEnum({\n name: this.modelInfo.name,\n isExported: true,\n members: schema.enum\n .filter(value => typeof value === 'string' && value.length > 0)\n .map(value => ({\n name: resolveEnumMemberName(value),\n initializer: `\\`${value}\\``,\n })),\n });\n }\n\n private addPropertyToInterface(\n interfaceDeclaration: InterfaceDeclaration,\n propName: string,\n propSchema: Schema | Reference,\n ): void {\n const propType = this.resolveType(propSchema);\n const resolvedPropName = resolvePropertyName(propName);\n let propertySignature = interfaceDeclaration.getProperty(resolvedPropName);\n if (propertySignature) {\n propertySignature.setType(propType);\n } else {\n propertySignature = interfaceDeclaration.addProperty({\n name: resolvedPropName,\n type: propType,\n isReadonly: isReadOnly(propSchema),\n });\n }\n addSchemaJSDoc(propertySignature, propSchema);\n }\n\n private processInterface(schema: ObjectSchema): JSDocableNode | undefined {\n const interfaceDeclaration = this.sourceFile.addInterface({\n name: this.modelInfo.name,\n isExported: true,\n });\n\n const properties = schema.properties || {};\n\n Object.entries(properties).forEach(([propName, propSchema]) => {\n this.addPropertyToInterface(interfaceDeclaration, propName, propSchema);\n });\n\n if (schema.additionalProperties) {\n const indexSignature = interfaceDeclaration.addIndexSignature({\n keyName: 'key',\n keyType: 'string',\n returnType: this.resolveType(\n schema.additionalProperties === true\n ? {}\n : (schema.additionalProperties as Schema | Reference),\n ),\n });\n indexSignature.addJsDoc('Additional properties');\n }\n return interfaceDeclaration;\n }\n\n private processArray(schema: ArraySchema): JSDocableNode | undefined {\n const itemType = this.resolveType(schema.items);\n return this.sourceFile.addTypeAlias({\n name: this.modelInfo.name,\n type: `Array<${itemType}>`,\n isExported: true,\n });\n }\n\n private processComposition(\n schema: CompositionSchema,\n ): JSDocableNode | undefined {\n return this.sourceFile.addTypeAlias({\n name: this.modelInfo.name,\n type: this.resolveType(schema),\n isExported: true,\n });\n }\n\n private processIntersection(schema: AllOfSchema): JSDocableNode | undefined {\n const interfaceDeclaration = this.sourceFile.addInterface({\n name: this.modelInfo.name,\n isExported: true,\n });\n schema.allOf.forEach(allOfSchema => {\n if (isReference(allOfSchema)) {\n const resolvedType = this.resolveType(allOfSchema);\n interfaceDeclaration.addExtends(resolvedType);\n return;\n }\n if (isObject(allOfSchema)) {\n Object.entries(allOfSchema.properties).forEach(\n ([propName, propSchema]) => {\n this.addPropertyToInterface(\n interfaceDeclaration,\n propName,\n propSchema,\n );\n },\n );\n }\n });\n\n return interfaceDeclaration;\n }\n\n private processTypeAlias(schema: Schema): JSDocableNode | undefined {\n return this.sourceFile.addTypeAlias({\n name: this.modelInfo.name,\n type: this.resolveType(schema),\n isExported: true,\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 { Schema } from '@ahoo-wang/fetcher-openapi';\nimport { SourceFile } from 'ts-morph';\n\nimport { GenerateContext, Generator } from '../generateContext';\nimport { getModelFileName, KeySchema, pascalCase } from '../utils';\nimport {\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n} from './modelInfo';\nimport { TypeGenerator } from './typeGenerator';\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 implements Generator {\n constructor(public readonly context: GenerateContext) {\n }\n\n private getOrCreateSourceFile(modelInfo: ModelInfo): SourceFile {\n const fileName = getModelFileName(modelInfo);\n return this.context.getOrCreateSourceFile(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.context.openAPI.components?.schemas;\n if (!schemas) {\n this.context.logger.info('No schemas found in OpenAPI specification');\n return;\n }\n const stateAggregatedTypeNames = this.stateAggregatedTypeNames();\n const keySchemas = this.filterSchemas(schemas, stateAggregatedTypeNames);\n this.context.logger.progress(\n `Generating models for ${keySchemas.length} schemas`,\n );\n keySchemas.forEach((keySchema, index) => {\n this.context.logger.progressWithCount(\n index + 1,\n keySchemas.length,\n `Processing schema: ${keySchema.key}`,\n 2,\n );\n this.generateKeyedSchema(keySchema);\n });\n this.context.logger.success('Model generation completed');\n }\n\n private filterSchemas(\n schemas: Record<string, Schema>,\n aggregatedTypeNames: Set<string>,\n ): KeySchema[] {\n return Object.entries(schemas)\n .map(([schemaKey, schema]) => ({\n key: schemaKey,\n schema,\n }))\n .filter(\n keySchema => !this.isWowSchema(keySchema.key, aggregatedTypeNames),\n );\n }\n\n private isWowSchema(\n schemaKey: string,\n stateAggregatedTypeNames: Set<string>,\n ): boolean {\n if (\n schemaKey !== 'wow.api.query.PagedList' &&\n schemaKey.startsWith('wow.api.query.') &&\n schemaKey.endsWith('PagedList')\n ) {\n return false;\n }\n\n if (schemaKey.startsWith('wow.api.query.Operator') &&\n schemaKey.endsWith('Map')\n ) {\n return false;\n }\n\n if (\n schemaKey.startsWith('wow.') ||\n schemaKey.endsWith('AggregatedCondition') ||\n schemaKey.endsWith('AggregatedDomainEventStream') ||\n schemaKey.endsWith('AggregatedDomainEventStreamPagedList') ||\n schemaKey.endsWith('AggregatedDomainEventStreamServerSentEventNonNullData') ||\n schemaKey.endsWith('AggregatedListQuery') ||\n schemaKey.endsWith('AggregatedPagedQuery') ||\n schemaKey.endsWith('AggregatedSingleQuery')\n ) {\n return true;\n }\n const modelInfo = resolveModelInfo(schemaKey);\n return stateAggregatedTypeNames.has(modelInfo.name);\n }\n\n private aggregatedSchemaSuffix = [\n 'MaterializedSnapshot',\n 'MaterializedSnapshotPagedList',\n 'MaterializedSnapshotServerSentEventNonNullData',\n 'PagedList',\n 'ServerSentEventNonNullData',\n 'Snapshot',\n 'StateEvent',\n ];\n\n private stateAggregatedTypeNames() {\n const typeNames = new Set<string>();\n for (const [boundedContext, aggregates] of this.context.contextAggregates) {\n this.generateBoundedContext(boundedContext);\n for (const aggregate of aggregates) {\n this.aggregatedSchemaSuffix.forEach(suffix => {\n const modelInfo = resolveModelInfo(aggregate.state.key);\n const typeName = pascalCase(modelInfo.name) + suffix;\n typeNames.add(typeName);\n });\n }\n }\n return typeNames;\n }\n\n /**\n * Generates a model for a specific schema key.\n * Processes enums, objects, unions, and type aliases in order.\n *\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(keySchema: KeySchema) {\n const modelInfo = resolveModelInfo(keySchema.key);\n const sourceFile = this.getOrCreateSourceFile(modelInfo);\n const typeGenerator = new TypeGenerator(\n modelInfo,\n sourceFile,\n keySchema,\n this.context.outputDir,\n );\n typeGenerator.generate();\n }\n\n generateBoundedContext(contextAlias: string) {\n const filePath = `${contextAlias}/boundedContext.ts`;\n this.context.logger.info(`Creating bounded context file: ${filePath}`);\n const file = this.context.getOrCreateSourceFile(filePath);\n const contextName = resolveContextDeclarationName(contextAlias);\n file.addStatements(`export const ${contextName} = '${contextAlias}';`);\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 {\n ClassDeclaration,\n OptionalKind,\n ParameterDeclarationStructure,\n Scope,\n SourceFile,\n} from 'ts-morph';\nimport { addImport } from '../utils';\n\nexport const FETCHER_MODULE_SPECIFIER = '@ahoo-wang/fetcher';\nexport const FETCHER_NAMED_IMPORTS = [\n 'ResultExtractors'\n];\n\n/**\n * The module specifier for the fetcher-decorator package.\n */\nexport const DECORATOR_MODULE_SPECIFIER = '@ahoo-wang/fetcher-decorator';\n\n/**\n * Named imports from the fetcher-decorator package.\n */\nexport const DECORATOR_NAMED_IMPORTS = [\n 'type ApiMetadata',\n 'type ApiMetadataCapable',\n 'type ParameterRequest',\n 'api',\n 'get',\n 'post',\n 'put',\n 'patch',\n 'del',\n 'request',\n 'attribute',\n 'path',\n 'autoGeneratedError',\n];\n\nexport interface MethodReturnType {\n type: string;\n metadata?: string;\n}\n\nexport const DEFAULT_RETURN_TYPE: MethodReturnType = {\n type: 'Promise<Response>',\n metadata: `{resultExtractor: ResultExtractors.Response }`,\n};\n\nexport const STRING_RETURN_TYPE: MethodReturnType = {\n type: 'Promise<string>',\n metadata: `{resultExtractor: ResultExtractors.Text }`,\n};\n\n/**\n * Metadata configuration for stream result extraction.\n */\nexport const STREAM_RESULT_EXTRACTOR_METADATA = `{\n headers: { Accept: ContentTypeValues.TEXT_EVENT_STREAM },\n resultExtractor: JsonEventStreamResultExtractor,\n}`;\n\nexport function addImportFetcher(sourceFile: SourceFile) {\n addImport(sourceFile, FETCHER_MODULE_SPECIFIER, FETCHER_NAMED_IMPORTS);\n}\n/**\n * Adds the necessary imports for decorator functionality to the source file.\n *\n * @param sourceFile - The source file to add imports to\n *\n * @example\n * ```typescript\n * const sourceFile = project.createSourceFile('api.ts');\n * addImportDecorator(sourceFile);\n * ```\n */\nexport function addImportDecorator(sourceFile: SourceFile) {\n addImport(sourceFile, DECORATOR_MODULE_SPECIFIER, DECORATOR_NAMED_IMPORTS);\n}\n\n/**\n * Creates a new class declaration with the @api decorator.\n *\n * @param className - The name of the class to create\n * @param sourceFile - The source file to add the class to\n * @param apiArgs - Optional arguments for the @api decorator\n * @param typeParameters - Optional type parameters for the class\n * @param extendsClass - Optional class to extend\n * @returns The created class declaration\n *\n * @example\n * ```typescript\n * const sourceFile = project.createSourceFile('UserApi.ts');\n * const classDecl = createDecoratorClass('UserApi', sourceFile, ['baseUrl']);\n * ```\n */\nexport function createDecoratorClass(\n className: string,\n sourceFile: SourceFile,\n apiArgs: string[] = [],\n typeParameters: string[] = [],\n extendsClass?: string,\n): ClassDeclaration {\n return sourceFile.addClass({\n name: className,\n isExported: true,\n typeParameters: typeParameters,\n extends: extendsClass,\n decorators: [\n {\n name: 'api',\n arguments: apiArgs,\n },\n ],\n });\n}\n\n/**\n * Adds the ApiMetadataCapable interface implementation and constructor to a class declaration.\n *\n * @param classDeclaration - The class declaration to modify\n * @param initializer - Optional initializer for the apiMetadata parameter\n *\n * @example\n * ```typescript\n * const classDecl = createDecoratorClass('UserApi', sourceFile);\n * addApiMetadataCtor(classDecl, '{}');\n * ```\n */\nexport function addApiMetadataCtor(\n classDeclaration: ClassDeclaration,\n initializer?: string,\n) {\n classDeclaration.addImplements('ApiMetadataCapable');\n classDeclaration.addConstructor({\n parameters: [\n {\n name: 'apiMetadata',\n type: 'ApiMetadata',\n hasQuestionToken: initializer === undefined,\n scope: Scope.Public,\n isReadonly: true,\n initializer: initializer,\n } as OptionalKind<ParameterDeclarationStructure>,\n ],\n });\n}\n\nexport const EVENTSTREAM_MODULE_SPECIFIER = '@ahoo-wang/fetcher-eventstream';\n\nexport function addImportEventStream(sourceFile: SourceFile) {\n addImport(sourceFile, EVENTSTREAM_MODULE_SPECIFIER, [\n 'JsonEventStreamResultExtractor',\n 'type JsonServerSentEventStream',\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 {\n camelCase,\n getOrCreateSourceFile,\n pascalCase,\n splitName,\n} from '../utils';\nimport { Operation } from '@ahoo-wang/fetcher-openapi';\n\n/**\n * Infers the appropriate resource attribution path specification type based on command paths in an aggregate definition.\n *\n * This function analyzes the command paths within an aggregate to determine whether the aggregate primarily uses\n * tenant-based or owner-based resource attribution. It counts occurrences of tenant and owner path prefixes\n * and returns the most prevalent type.\n *\n * @param aggregateDefinition - The aggregate definition containing commands with path specifications\n * @returns The inferred path specification type as a string constant:\n * - 'ResourceAttributionPathSpec.NONE' if no tenant or owner paths are found\n * - 'ResourceAttributionPathSpec.TENANT' if tenant paths are more prevalent\n * - 'ResourceAttributionPathSpec.OWNER' if owner paths are more prevalent or equal\n *\n * @example\n * ```typescript\n * const aggregateDef = {\n * commands: [\n * { path: '/tenant/{tenantId}/users' },\n * { path: '/tenant/{tenantId}/orders' },\n * { path: '/owner/{ownerId}/profile' }\n * ]\n * };\n * const pathSpec = inferPathSpecType(aggregateDef);\n * // Returns: 'ResourceAttributionPathSpec.TENANT'\n * ```\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\n/**\n * Creates or retrieves a source file for a client within an aggregate's directory structure.\n *\n * This function generates the appropriate file path based on the aggregate's context alias and name,\n * then uses the project's file management utilities to create or get the source file.\n *\n * @param project - The TypeScript project instance managing the source files\n * @param outputDir - The base output directory where generated files will be placed\n * @param aggregate - The aggregate metadata containing context alias and aggregate name\n * @param fileName - The name of the file to create (without extension)\n * @returns The created or retrieved SourceFile instance\n *\n * @throws Will throw an error if the file cannot be created or retrieved\n *\n * @example\n * ```typescript\n * const project = new Project();\n * const aggregate = { contextAlias: 'user', aggregateName: 'profile' };\n * const sourceFile = createClientFilePath(project, '/output', aggregate, 'UserProfileClient');\n * // Creates/retrieves file at: /output/user/profile/UserProfileClient.ts\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\nexport function resolveClassName(\n aggregate: TagAliasAggregate,\n suffix: string,\n): string {\n return `${pascalCase(aggregate.aggregateName)}${suffix}`;\n}\n\n/**\n * Converts HTTP method names to their corresponding decorator names.\n *\n * This function handles special cases where HTTP method names need to be mapped to different\n * decorator names for compatibility with the decorator framework.\n *\n * @param method - The HTTP method name (e.g., 'get', 'post', 'delete')\n * @returns The corresponding decorator name, with 'delete' mapped to 'del'\n *\n * @example\n * ```typescript\n * methodToDecorator('get'); // Returns: 'get'\n * methodToDecorator('post'); // Returns: 'post'\n * methodToDecorator('delete'); // Returns: 'del'\n * ```\n */\nexport function methodToDecorator(method: string): string {\n if (method === 'delete') {\n return 'del';\n }\n return method;\n}\n\nconst OPERATION_METHOD_NAME_KEY = 'x-fetcher-method';\n\n/**\n * Resolves a unique method name for an OpenAPI operation.\n *\n * This function attempts to generate a unique method name for an operation by:\n * 1. Using the custom 'x-fetcher-method' extension if present\n * 2. Deriving from the operationId by trying progressively shorter suffixes\n * 3. Falling back to the full camelCase operationId if no unique name is found\n *\n * The function splits the operationId by common separators and tries to find the shortest\n * unique method name by checking from the end of the name parts.\n *\n * @param operation - The OpenAPI operation object containing operationId and other metadata\n * @param isExists - A function that checks if a method name already exists in the target class\n * @returns A unique method name string, or undefined if the operation has no operationId\n *\n * @throws Will not throw, but returns undefined for operations without operationId\n *\n * @example\n * ```typescript\n * const operation = { operationId: 'user.getProfile' };\n * const isExists = (name) => name === 'getProfile'; // Assume getProfile exists\n * const methodName = resolveMethodName(operation, isExists);\n * // Returns: 'user.getProfile' (fallback since getProfile exists)\n *\n * const operation2 = { operationId: 'user.create' };\n * const methodName2 = resolveMethodName(operation2, isExists);\n * // Returns: 'create' (unique method name found)\n * ```\n */\nexport function resolveMethodName(\n operation: Operation,\n isExists: (methodName: string) => boolean,\n): string | undefined {\n const methodName = operation[OPERATION_METHOD_NAME_KEY];\n if (methodName) {\n return methodName;\n }\n if (!operation.operationId) {\n return undefined;\n }\n\n const nameParts = splitName(operation.operationId);\n for (let i = nameParts.length - 1; i >= 0; i--) {\n const operationName = camelCase(nameParts.slice(i));\n if (isExists(operationName)) {\n continue;\n }\n return operationName;\n }\n return camelCase(nameParts);\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 { combineURLs } from '@ahoo-wang/fetcher';\nimport {\n Operation,\n Reference,\n RequestBody,\n Schema,\n Tag,\n} from '@ahoo-wang/fetcher-openapi';\nimport {\n ClassDeclaration,\n OptionalKind,\n ParameterDeclarationStructure,\n SourceFile,\n} from 'ts-morph';\nimport { GenerateContext, Generator } from '../generateContext';\nimport {\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n resolveReferenceModelInfo,\n} from '../model';\nimport {\n addImportRefModel,\n addJSDoc,\n extractOkResponse,\n extractOperationEndpoints,\n extractOperations,\n extractPathParameters,\n extractRequestBody,\n extractResponseEventStreamSchema,\n extractResponseJsonSchema,\n extractResponseWildcardSchema,\n extractSchema,\n isArray, isMap,\n isPrimitive,\n isReference,\n OperationEndpoint,\n resolvePathParameterType,\n resolvePrimitiveType, toArrayType,\n} from '../utils';\nimport {\n addApiMetadataCtor,\n addImportDecorator,\n addImportEventStream, addImportFetcher,\n createDecoratorClass,\n DEFAULT_RETURN_TYPE,\n MethodReturnType,\n STREAM_RESULT_EXTRACTOR_METADATA,\n STRING_RETURN_TYPE,\n} from './decorators';\nimport { methodToDecorator, resolveMethodName } from './utils';\n\n/**\n * Generator for creating TypeScript API client classes from OpenAPI specifications.\n * Generates client classes with proper decorators, type annotations, and method signatures.\n */\nexport class ApiClientGenerator implements Generator {\n private defaultParameterRequestType = 'ParameterRequest';\n private defaultReturnType = DEFAULT_RETURN_TYPE;\n\n private readonly apiMetadataCtorInitializer: string | undefined;\n\n /**\n * Creates a new ApiClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and configuration\n */\n constructor(public readonly context: GenerateContext) {\n this.apiMetadataCtorInitializer = this.context.currentContextAlias\n ? `{basePath:${resolveContextDeclarationName(this.context.currentContextAlias)}}`\n : undefined;\n }\n\n /**\n * Generates API client classes for all valid tags in the OpenAPI specification.\n * Processes tags, groups operations, and creates client classes with methods.\n */\n generate() {\n this.context.logger.info('Starting API client generation');\n const apiClientTags: Map<string, Tag> = this.resolveApiTags();\n this.context.logger.info(\n `Resolved ${apiClientTags.size} API client tags: ${Array.from(apiClientTags.keys()).join(', ')}`,\n );\n\n const groupOperations = this.groupOperations(apiClientTags);\n this.context.logger.info(\n `Grouped operations into ${groupOperations.size} tag groups`,\n );\n\n this.generateApiClients(apiClientTags, groupOperations);\n this.context.logger.success('API client generation completed');\n }\n\n /**\n * Generates API client classes for each tag group.\n * @param apiClientTags - Map of valid API client tags\n * @param groupOperations - Map of operations grouped by tag\n */\n private generateApiClients(\n apiClientTags: Map<string, Tag>,\n groupOperations: Map<string, Set<OperationEndpoint>>,\n ) {\n this.context.logger.info(\n `Generating ${groupOperations.size} API client classes`,\n );\n let clientCount = 0;\n for (const [tagName, operations] of groupOperations) {\n clientCount++;\n this.context.logger.progressWithCount(\n clientCount,\n groupOperations.size,\n `Generating API client for tag: ${tagName}`,\n );\n const tag = apiClientTags.get(tagName)!;\n this.generateApiClient(tag, operations);\n }\n }\n\n /**\n * Creates a new source file for the API client.\n * @param modelInfo - The model information for the client\n * @returns The created source file\n */\n private createApiClientFile(modelInfo: ModelInfo): SourceFile {\n let filePath = modelInfo.path;\n if (this.context.currentContextAlias) {\n filePath = combineURLs(this.context.currentContextAlias, filePath);\n }\n filePath = combineURLs(filePath, `${modelInfo.name}ApiClient.ts`);\n this.context.logger.info(`Creating API client file: ${filePath}`);\n return this.context.getOrCreateSourceFile(filePath);\n }\n\n /**\n * Generates a single API client class for the given tag and operations.\n * @param tag - The OpenAPI tag for the client\n * @param operations - Set of operations for this client\n */\n private generateApiClient(tag: Tag, operations: Set<OperationEndpoint>) {\n const modelInfo = resolveModelInfo(tag.name);\n this.context.logger.info(\n `Generating API client class: ${modelInfo.name}ApiClient with ${operations.size} operations`,\n );\n const apiClientFile = this.createApiClientFile(modelInfo);\n addImportFetcher(apiClientFile);\n addImportDecorator(apiClientFile);\n addImportEventStream(apiClientFile);\n const apiClientClass = createDecoratorClass(\n modelInfo.name + 'ApiClient',\n apiClientFile,\n );\n addJSDoc(apiClientClass, [tag.description]);\n addApiMetadataCtor(apiClientClass, this.apiMetadataCtorInitializer);\n this.context.logger.info(\n `Processing ${operations.size} operations for ${modelInfo.name}ApiClient`,\n );\n operations.forEach(operation => {\n this.processOperation(tag, apiClientFile, apiClientClass, operation);\n });\n this.context.logger.success(\n `Completed API client: ${modelInfo.name}ApiClient`,\n );\n }\n\n /**\n * Generates a unique method name for the operation.\n * @param apiClientClass - The client class to check for existing methods\n * @param operation - The operation to generate a name for\n * @returns A unique camelCase method name\n */\n private getMethodName(\n apiClientClass: ClassDeclaration,\n operation: Operation,\n ): string {\n const methodName = resolveMethodName(operation, name => {\n return apiClientClass.getMethod(name) !== undefined;\n });\n if (!methodName) {\n throw new Error(\n `Unable to resolve method name for apiClientClass:${apiClientClass.getName()}.`,\n );\n }\n return methodName;\n }\n\n /**\n * Resolves the request type for an operation based on its request body.\n * @param sourceFile - The source file to add imports to\n * @param operation - The operation to resolve the request type for\n * @returns The resolved request type string\n */\n private resolveRequestType(\n sourceFile: SourceFile,\n operation: Operation,\n ): string {\n if (!operation.requestBody) {\n this.context.logger.info(\n `No request body found for operation ${operation.operationId}, using default: ${this.defaultParameterRequestType}`,\n );\n return this.defaultParameterRequestType;\n }\n let requestBody: RequestBody | undefined;\n if (isReference(operation.requestBody)) {\n this.context.logger.info(\n `Extracting request body from reference for operation: ${operation.operationId}`,\n );\n requestBody = extractRequestBody(\n operation.requestBody,\n this.context.openAPI.components!,\n );\n } else {\n requestBody = operation.requestBody;\n }\n if (!requestBody) {\n this.context.logger.info(\n `Request body extraction failed for operation ${operation.operationId}, using default: ${this.defaultParameterRequestType}`,\n );\n return this.defaultParameterRequestType;\n }\n if (requestBody.content['multipart/form-data']) {\n this.context.logger.info(\n `Detected multipart/form-data content for operation ${operation.operationId}, using ParameterRequest<FormData>`,\n );\n return 'ParameterRequest<FormData>';\n }\n if (requestBody.content['application/json']) {\n const requestBodySchema = requestBody.content['application/json'].schema;\n if (isReference(requestBodySchema)) {\n const modelInfo = resolveReferenceModelInfo(requestBodySchema);\n this.context.logger.info(\n `Adding import for request body model: ${modelInfo.name} from ${modelInfo.path}`,\n );\n addImportRefModel(sourceFile, this.context.outputDir, modelInfo);\n const requestType = `ParameterRequest<${modelInfo.name}>`;\n this.context.logger.info(\n `Resolved request type for operation ${operation.operationId}: ${requestType}`,\n );\n return requestType;\n }\n }\n this.context.logger.info(\n `Using default request type for operation ${operation.operationId}: ${this.defaultParameterRequestType}`,\n );\n return this.defaultParameterRequestType;\n }\n\n /**\n * Resolves method parameters for an operation.\n * @param tag - The tag for parameter filtering\n * @param sourceFile - The source file to add imports to\n * @param operation - The operation to resolve parameters for\n * @returns Array of parameter declarations\n */\n private resolveParameters(\n tag: Tag,\n sourceFile: SourceFile,\n operation: Operation,\n ): OptionalKind<ParameterDeclarationStructure>[] {\n const pathParameters = extractPathParameters(\n operation,\n this.context.openAPI.components!,\n ).filter(parameter => {\n return !this.context.isIgnoreApiClientPathParameters(\n tag.name,\n parameter.name,\n );\n });\n this.context.logger.info(\n `Found ${pathParameters.length} path parameters for operation ${operation.operationId}`,\n );\n const parameters = pathParameters.map(parameter => {\n const parameterType = resolvePathParameterType(parameter);\n this.context.logger.info(\n `Adding path parameter: ${parameter.name} (type: ${parameterType})`,\n );\n return {\n name: parameter.name,\n type: parameterType,\n hasQuestionToken: false,\n decorators: [\n {\n name: 'path',\n arguments: [`'${parameter.name}'`],\n },\n ],\n };\n });\n const requestType = this.resolveRequestType(sourceFile, operation);\n this.context.logger.info(`Adding httpRequest parameter: ${requestType}`);\n parameters.push({\n name: 'httpRequest',\n hasQuestionToken: requestType === this.defaultParameterRequestType,\n type: `${requestType}`,\n decorators: [\n {\n name: 'request',\n arguments: [],\n },\n ],\n });\n this.context.logger.info(\n `Adding attributes parameter: Record<string, any>`,\n );\n parameters.push({\n name: 'attributes',\n hasQuestionToken: true,\n type: 'Record<string, any>',\n decorators: [\n {\n name: 'attribute',\n arguments: [],\n },\n ],\n });\n return parameters;\n }\n\n private resolveType(\n sourceFile: SourceFile,\n schema: Schema | Reference,\n ): string {\n if (isReference(schema)) {\n const modelInfo = resolveReferenceModelInfo(schema);\n addImportRefModel(sourceFile, this.context.outputDir, modelInfo);\n return modelInfo.name;\n }\n if (isArray(schema)) {\n const itemType = this.resolveType(sourceFile, schema.items);\n return toArrayType(itemType);\n }\n if (isMap(schema)) {\n const additionalProperties = schema.additionalProperties;\n if (typeof additionalProperties === 'boolean') {\n return 'Record<string, any>';\n }\n const valueType = this.resolveType(sourceFile, additionalProperties);\n return `Record<string, ${valueType}>`;\n }\n if (schema.type && isPrimitive(schema.type)) {\n return resolvePrimitiveType(schema.type);\n }\n\n return 'any';\n }\n\n /**\n * Resolves the return type for a schema.\n * @param sourceFile - The source file to add imports to\n * @param schema - The schema to resolve the return type for\n * @returns The resolved return type string\n */\n private resolveSchemaReturnType(\n sourceFile: SourceFile,\n schema: Schema | Reference,\n ): string {\n return `Promise<${this.resolveType(sourceFile, schema)}>`;\n }\n\n /**\n * Resolves the return type for an operation based on its responses.\n * @param sourceFile - The source file to add imports to\n * @param operation - The operation to resolve the return type for\n * @returns Object containing type and optional stream flag\n */\n private resolveReturnType(\n sourceFile: SourceFile,\n operation: Operation,\n ): MethodReturnType {\n const okResponse = extractOkResponse(operation);\n if (!okResponse) {\n this.context.logger.info(\n `No OK response found for operation ${operation.operationId}, using default return type: ${this.defaultReturnType.type}`,\n );\n return this.defaultReturnType;\n }\n const jsonSchema =\n extractResponseJsonSchema(okResponse) ||\n extractResponseWildcardSchema(okResponse);\n if (jsonSchema) {\n const returnType = this.resolveSchemaReturnType(sourceFile, jsonSchema);\n this.context.logger.info(\n `Resolved JSON/wildcard response return type for operation ${operation.operationId}: ${returnType}`,\n );\n return {\n type: returnType,\n metadata:\n returnType === STRING_RETURN_TYPE.type\n ? STRING_RETURN_TYPE.metadata\n : undefined,\n };\n }\n const eventStreamSchema = extractResponseEventStreamSchema(okResponse);\n if (eventStreamSchema) {\n if (isReference(eventStreamSchema)) {\n const schema = extractSchema(\n eventStreamSchema,\n this.context.openAPI.components!,\n )!;\n if (isArray(schema) && isReference(schema.items)) {\n const modelInfo = resolveReferenceModelInfo(schema.items);\n this.context.logger.info(\n `Adding import for event stream model: ${modelInfo.name} from ${modelInfo.path}`,\n );\n addImportRefModel(sourceFile, this.context.outputDir, modelInfo);\n const dataType = modelInfo.name.includes('ServerSentEvent')\n ? `${modelInfo.name}['data']`\n : modelInfo.name;\n const returnType = `Promise<JsonServerSentEventStream<${dataType}>>`;\n this.context.logger.info(\n `Resolved event stream return type for operation ${operation.operationId}: ${returnType}`,\n );\n return {\n type: returnType,\n metadata: STREAM_RESULT_EXTRACTOR_METADATA,\n };\n }\n }\n const returnType = `Promise<JsonServerSentEventStream<any>>`;\n this.context.logger.info(\n `Resolved generic event stream return type for operation ${operation.operationId}: ${returnType}`,\n );\n return { type: returnType, metadata: STREAM_RESULT_EXTRACTOR_METADATA };\n }\n this.context.logger.info(\n `Using default return type for operation ${operation.operationId}: ${this.defaultReturnType.type}`,\n );\n return this.defaultReturnType;\n }\n\n /**\n * Processes a single operation and adds it as a method to the client class.\n * @param tag - The tag for parameter filtering\n * @param sourceFile - The source file containing the client\n * @param apiClientClass - The client class to add the method to\n * @param operation - The operation to process\n */\n private processOperation(\n tag: Tag,\n sourceFile: SourceFile,\n apiClientClass: ClassDeclaration,\n operation: OperationEndpoint,\n ) {\n this.context.logger.info(\n `Processing operation: ${operation.operation.operationId} (${operation.method} ${operation.path})`,\n );\n const methodName = this.getMethodName(apiClientClass, operation.operation);\n this.context.logger.info(`Generated method name: ${methodName}`);\n const parameters = this.resolveParameters(\n tag,\n sourceFile,\n operation.operation,\n );\n const returnType = this.resolveReturnType(sourceFile, operation.operation);\n const methodDecorator = returnType.metadata\n ? {\n name: methodToDecorator(operation.method),\n arguments: [`'${operation.path}'`, returnType.metadata],\n }\n : {\n name: methodToDecorator(operation.method),\n arguments: [`'${operation.path}'`],\n };\n this.context.logger.info(\n `Creating method with ${parameters.length} parameters, return type: ${returnType.type}`,\n );\n const methodDeclaration = apiClientClass.addMethod({\n name: methodName,\n decorators: [methodDecorator],\n parameters: parameters,\n returnType: returnType.type,\n statements: [\n `throw autoGeneratedError(${parameters.map(parameter => parameter.name).join(',')});`,\n ],\n });\n addJSDoc(methodDeclaration, [\n operation.operation.summary,\n operation.operation.description,\n `- operationId: \\`${operation.operation.operationId}\\``,\n `- path: \\`${operation.path}\\``,\n ]);\n this.context.logger.success(`Operation method generated: ${methodName}`);\n }\n\n /**\n * Groups operations by their tags for client generation.\n * @param apiClientTags - Map of valid API client tags\n * @returns Map of operations grouped by tag name\n */\n private groupOperations(\n apiClientTags: Map<string, Tag>,\n ): Map<string, Set<OperationEndpoint>> {\n this.context.logger.info('Grouping operations by API client tags');\n const operations: Map<string, Set<OperationEndpoint>> = new Map();\n const availableEndpoints = extractOperationEndpoints(\n this.context.openAPI.paths,\n ).filter(endpoint => {\n if (!endpoint.operation.operationId) {\n return false;\n }\n const operationTags = endpoint.operation.tags;\n if (!operationTags || operationTags.length == 0) {\n return false;\n }\n return operationTags.every(tagName => {\n return apiClientTags.has(tagName);\n });\n });\n let totalOperations = 0;\n for (const endpoint of availableEndpoints) {\n endpoint.operation.tags!.forEach(tagName => {\n if (!operations.has(tagName)) {\n operations.set(tagName, new Set());\n }\n operations.get(tagName)!.add(endpoint);\n totalOperations++;\n });\n }\n this.context.logger.info(\n `Grouped ${totalOperations} operations into ${operations.size} tag groups`,\n );\n return operations;\n }\n\n private shouldIgnoreTag(tagName: string): boolean {\n return (\n tagName === 'wow' ||\n tagName === 'Actuator' ||\n this.isAggregateTag(tagName)\n );\n }\n\n /**\n * Resolves valid API client tags from the OpenAPI specification.\n * Filters out system tags like 'wow' and 'Actuator' and aggregate tags.\n * @returns Map of valid API client tags\n */\n private resolveApiTags(): Map<string, Tag> {\n this.context.logger.info(\n 'Resolving API client tags from OpenAPI specification',\n );\n const apiClientTags: Map<string, Tag> = new Map<string, Tag>();\n const totalTags = this.context.openAPI.tags?.length || 0;\n for (const pathItem of Object.values(this.context.openAPI.paths)) {\n extractOperations(pathItem).forEach(methodOperation => {\n methodOperation.operation.tags?.forEach(tagName => {\n if (!this.shouldIgnoreTag(tagName) && !apiClientTags.has(tagName)) {\n apiClientTags.set(tagName, {\n name: tagName,\n description: '',\n });\n }\n });\n });\n }\n let filteredTags = 0;\n this.context.openAPI.tags?.forEach(tag => {\n if (!this.shouldIgnoreTag(tag.name)) {\n apiClientTags.set(tag.name, tag);\n filteredTags++;\n this.context.logger.info(`Included API client tag: ${tag.name}`);\n } else {\n this.context.logger.info(\n `Excluded tag: ${tag.name} (wow/Actuator/aggregate)`,\n );\n }\n });\n this.context.logger.info(\n `Resolved ${filteredTags} API client tags from ${totalTags} total tags`,\n );\n return apiClientTags;\n }\n\n private isAggregateTag(tagName: string): boolean {\n for (const aggregates of this.context.contextAggregates.values()) {\n for (const aggregate of aggregates) {\n if (aggregate.aggregate.tag.name === tagName) {\n return true;\n }\n }\n }\n return false;\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 {\n ClassDeclaration,\n OptionalKind,\n ParameterDeclarationStructure,\n SourceFile,\n VariableDeclarationKind,\n} from 'ts-morph';\nimport {\n AggregateDefinition,\n CommandDefinition,\n TagAliasAggregate,\n} from '../aggregate';\nimport { GenerateContext, Generator } from '../generateContext';\nimport {\n IMPORT_WOW_PATH,\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n} from '../model';\nimport {\n addImport,\n addImportRefModel,\n addJSDoc,\n camelCase,\n isEmptyObject,\n resolveOptionalFields,\n resolvePathParameterType,\n} from '../utils';\nimport {\n addApiMetadataCtor,\n addImportDecorator,\n addImportEventStream,\n createDecoratorClass,\n STREAM_RESULT_EXTRACTOR_METADATA,\n} from './decorators';\nimport {\n createClientFilePath,\n resolveClassName,\n methodToDecorator,\n} 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 implements Generator {\n private readonly commandEndpointPathsSuffix = 'CommandEndpointPaths';\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(public readonly context: GenerateContext) {}\n\n /**\n * Generates command client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(\n this.context.contextAggregates.values(),\n ).reduce((sum, set) => sum + set.size, 0);\n this.context.logger.info('--- Generating Command Clients ---');\n this.context.logger.progress(\n `Generating command clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.context.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.context.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing command client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processAggregate(aggregateDefinition);\n });\n }\n this.context.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.context.logger.info(\n `Processing command client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n const commandClientFile = createClientFilePath(\n this.context.project,\n this.context.outputDir,\n aggregate.aggregate,\n 'commandClient',\n );\n\n this.context.logger.info(\n `Processing command endpoint paths for ${aggregate.commands.size} commands`,\n );\n\n const aggregateCommandEndpointPathsName = this.processCommandEndpointPaths(\n commandClientFile,\n aggregate,\n );\n this.processCommandTypes(commandClientFile, aggregate);\n this.context.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: ${resolveContextDeclarationName(aggregate.aggregate.contextAlias)}\n }`,\n },\n ],\n isExported: false,\n });\n\n this.context.logger.info(\n `Adding imports from ${IMPORT_WOW_PATH}: CommandRequest, CommandResult, CommandResultEventStream, CommandBody, DeleteAggregateCommand, RecoverAggregateCommand`,\n );\n commandClientFile.addImportDeclaration({\n moduleSpecifier: IMPORT_WOW_PATH,\n namedImports: [\n 'CommandRequest',\n 'CommandResult',\n 'CommandResultEventStream',\n 'CommandBody',\n 'DeleteAggregateCommand',\n 'RecoverAggregateCommand',\n ],\n isTypeOnly: true,\n });\n\n this.context.logger.info(\n `Adding import from @ahoo-wang/fetcher-eventstream: JsonEventStreamResultExtractor`,\n );\n addImportEventStream(commandClientFile);\n\n this.context.logger.info(\n `Adding import from @ahoo-wang/fetcher: ContentTypeValues`,\n );\n addImport(commandClientFile, '@ahoo-wang/fetcher', ['ContentTypeValues']);\n\n this.context.logger.info(\n `Adding imports from @ahoo-wang/fetcher-decorator: ApiMetadata types and decorators`,\n );\n addImportDecorator(commandClientFile);\n this.context.logger.info(`Generating standard command client class`);\n this.processCommandClient(\n commandClientFile,\n aggregate,\n aggregateCommandEndpointPathsName,\n );\n\n this.context.logger.info(`Generating stream command client class`);\n this.processStreamCommandClient(commandClientFile, aggregate);\n\n this.context.logger.success(\n `Command client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n\n resolveAggregateCommandEndpointPathsName(\n aggregate: TagAliasAggregate,\n ): string {\n return resolveClassName(aggregate, this.commandEndpointPathsSuffix);\n }\n\n processCommandEndpointPaths(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ): string {\n const aggregateCommandEndpointPathsName =\n this.resolveAggregateCommandEndpointPathsName(\n aggregateDefinition.aggregate,\n );\n this.context.logger.info(\n `Creating command endpoint paths enum: ${aggregateCommandEndpointPathsName}`,\n );\n const enumDeclaration = clientFile.addEnum({\n name: aggregateCommandEndpointPathsName,\n isExported: true,\n });\n aggregateDefinition.commands.forEach(command => {\n this.context.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.context.logger.success(\n `Command endpoint paths enum created with ${aggregateDefinition.commands.size} entries`,\n );\n return aggregateCommandEndpointPathsName;\n }\n\n resolveCommandTypeName(definition: CommandDefinition): [ModelInfo, string] {\n const commandModelInfo = resolveModelInfo(definition.schema.key);\n return [commandModelInfo, commandModelInfo.name + 'Command'];\n }\n\n resolveCommandType(clientFile: SourceFile, definition: CommandDefinition) {\n const [commandModelInfo, commandName] =\n this.resolveCommandTypeName(definition);\n if (commandModelInfo.path === IMPORT_WOW_PATH) {\n return;\n }\n addImportRefModel(clientFile, this.context.outputDir, commandModelInfo);\n let commandType = `${commandModelInfo.name}`;\n const optionalFields = resolveOptionalFields(definition.schema.schema)\n .map(fieldName => `'${fieldName}'`)\n .join(' | ');\n if (optionalFields !== '') {\n commandType = `PartialBy<${commandType},${optionalFields}>`;\n }\n commandType = `CommandBody<${commandType}>`;\n clientFile.addTypeAlias({\n name: commandName,\n type: `${commandType}`,\n isExported: true,\n });\n }\n\n processCommandTypes(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ) {\n aggregateDefinition.commands.forEach(command => {\n this.resolveCommandType(clientFile, command);\n });\n }\n\n getEndpointPath(\n aggregateCommandEndpointPathsName: string,\n command: CommandDefinition,\n ): string {\n return `${aggregateCommandEndpointPathsName}.${command.name.toUpperCase()}`;\n }\n\n processCommandClient(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n aggregateCommandEndpointPathsName: string,\n ) {\n const commandClientName = resolveClassName(\n aggregateDefinition.aggregate,\n 'CommandClient',\n );\n const commandClient = createDecoratorClass(\n commandClientName,\n clientFile,\n [],\n ['R = CommandResult'],\n );\n addApiMetadataCtor(commandClient, this.defaultCommandClientOptionsName);\n\n aggregateDefinition.commands.forEach(command => {\n this.processCommandMethod(\n aggregateDefinition,\n commandClient,\n command,\n aggregateCommandEndpointPathsName,\n );\n });\n }\n\n processStreamCommandClient(\n clientFile: SourceFile,\n aggregateDefinition: AggregateDefinition,\n ) {\n const commandClientName = resolveClassName(\n aggregateDefinition.aggregate,\n 'CommandClient',\n );\n const commandStreamClientName = resolveClassName(\n aggregateDefinition.aggregate,\n 'StreamCommandClient',\n );\n\n const streamCommandClient = createDecoratorClass(\n commandStreamClientName,\n clientFile,\n [`''`, STREAM_RESULT_EXTRACTOR_METADATA],\n [],\n `${commandClientName}<CommandResultEventStream>`,\n );\n streamCommandClient.addConstructor({\n parameters: [\n {\n name: 'apiMetadata',\n type: 'ApiMetadata',\n initializer: this.defaultCommandClientOptionsName,\n } as OptionalKind<ParameterDeclarationStructure>,\n ],\n statements: `super(apiMetadata);`,\n });\n }\n\n private resolveParameters(\n tag: Tag,\n definition: CommandDefinition,\n ): OptionalKind<ParameterDeclarationStructure>[] {\n const [commandModelInfo, commandName] =\n this.resolveCommandTypeName(definition);\n this.context.logger.info(\n `Adding import for command model: ${commandModelInfo.name} from path: ${commandModelInfo.path}`,\n );\n\n const parameters = definition.pathParameters\n .filter(parameter => {\n return !this.context.isIgnoreCommandClientPathParameters(\n tag.name,\n parameter.name,\n );\n })\n .map(parameter => {\n const parameterType = resolvePathParameterType(parameter);\n this.context.logger.info(\n `Adding path parameter: ${parameter.name} (type: ${parameterType})`,\n );\n return {\n name: parameter.name,\n type: parameterType,\n hasQuestionToken: false,\n decorators: [\n {\n name: 'path',\n arguments: [`'${parameter.name}'`],\n },\n ],\n };\n });\n\n this.context.logger.info(\n `Adding command request parameter: commandRequest (type: CommandRequest<${commandName}>)`,\n );\n parameters.push({\n name: 'commandRequest',\n hasQuestionToken: isEmptyObject(definition.schema.schema),\n type: `CommandRequest<${commandName}>`,\n decorators: [\n {\n name: 'request',\n arguments: [],\n },\n ],\n });\n\n this.context.logger.info(\n `Adding attributes parameter: attributes (type: Record<string, any>)`,\n );\n parameters.push({\n name: 'attributes',\n hasQuestionToken: true,\n type: 'Record<string, any>',\n decorators: [\n {\n name: 'attribute',\n arguments: [],\n },\n ],\n });\n return parameters;\n }\n\n processCommandMethod(\n aggregate: AggregateDefinition,\n client: ClassDeclaration,\n definition: CommandDefinition,\n aggregateCommandEndpointPathsName: string,\n ) {\n this.context.logger.info(\n `Generating command method: ${camelCase(definition.name)} for command: ${definition.name}`,\n );\n this.context.logger.info(\n `Command method details: HTTP ${definition.method}, path: ${definition.path}`,\n );\n const parameters = this.resolveParameters(\n aggregate.aggregate.tag,\n definition,\n );\n const methodDeclaration = client.addMethod({\n name: camelCase(definition.name),\n decorators: [\n {\n name: methodToDecorator(definition.method),\n arguments: [\n `${this.getEndpointPath(aggregateCommandEndpointPathsName, definition)}`,\n ],\n },\n ],\n parameters: parameters,\n returnType: 'Promise<R>',\n statements: `throw autoGeneratedError(${parameters.map(parameter => parameter.name).join(',')});`,\n });\n\n this.context.logger.info(\n `Adding JSDoc documentation for method: ${camelCase(definition.name)}`,\n );\n addJSDoc(methodDeclaration, [\n definition.summary,\n definition.description,\n `- operationId: \\`${definition.operation.operationId}\\``,\n `- path: \\`${definition.path}\\``,\n ]);\n\n this.context.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 { SourceFile, VariableDeclarationKind } from 'ts-morph';\nimport { AggregateDefinition, TagAliasAggregate } from '../aggregate';\nimport { GenerateContext, Generator } from '../generateContext';\nimport {\n IMPORT_WOW_PATH,\n ModelInfo,\n resolveContextDeclarationName,\n resolveModelInfo,\n} from '../model';\nimport { addImportRefModel, camelCase } from '../utils';\nimport {\n createClientFilePath,\n inferPathSpecType,\n resolveClassName,\n} 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 implements Generator {\n private readonly domainEventTypeSuffix = 'DomainEventType';\n private readonly domainEventTypeMapTitleSuffix = 'DomainEventTypeMapTitle';\n\n /**\n * Creates a new QueryClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(public readonly context: GenerateContext) {}\n\n /**\n * Generates query client classes for all aggregates.\n */\n generate(): void {\n const totalAggregates = Array.from(\n this.context.contextAggregates.values(),\n ).reduce((sum, set) => sum + set.size, 0);\n this.context.logger.info('--- Generating Query Clients ---');\n this.context.logger.progress(\n `Generating query clients for ${totalAggregates} aggregates`,\n );\n let currentIndex = 0;\n for (const [, aggregates] of this.context.contextAggregates) {\n aggregates.forEach(aggregateDefinition => {\n currentIndex++;\n this.context.logger.progressWithCount(\n currentIndex,\n totalAggregates,\n `Processing query client for aggregate: ${aggregateDefinition.aggregate.aggregateName}`,\n );\n this.processQueryClient(aggregateDefinition);\n });\n }\n this.context.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.context.project,\n this.context.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.context.logger.info(\n `Processing query client for aggregate: ${aggregate.aggregate.aggregateName} in context: ${aggregate.aggregate.contextAlias}`,\n );\n\n this.context.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.context.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: ${resolveContextDeclarationName(aggregate.aggregate.contextAlias)},\n aggregateName: '${aggregate.aggregate.aggregateName}',\n resourceAttribution: ${inferPathSpecType(aggregate)},\n }`,\n },\n ],\n isExported: false,\n });\n this.processAggregateDomainEventTypes(aggregate, queryClientFile);\n const aggregateDomainEventType = this.processAggregateDomainEventType(\n aggregate,\n queryClientFile,\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.context.logger.info(\n `Adding import for state model: ${stateModelInfo.name} from path: ${stateModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.context.outputDir, stateModelInfo);\n this.context.logger.info(\n `Adding import for fields model: ${fieldsModelInfo.name} from path: ${fieldsModelInfo.path}`,\n );\n addImportRefModel(queryClientFile, this.context.outputDir, fieldsModelInfo);\n\n this.context.logger.info(\n `Creating query client factory: ${clientFactoryName}`,\n );\n queryClientFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: clientFactoryName,\n initializer: `new QueryClientFactory<${stateModelInfo.name}, ${fieldsModelInfo.name} | string, ${aggregateDomainEventType}>(${defaultClientOptionsName})`,\n },\n ],\n isExported: true,\n });\n\n this.context.logger.success(\n `Query client generation completed for aggregate: ${aggregate.aggregate.aggregateName}`,\n );\n }\n\n private processAggregateDomainEventType(\n aggregate: AggregateDefinition,\n queryClientFile: SourceFile,\n ) {\n const eventModelInfos: ModelInfo[] = [];\n this.context.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.context.logger.info(\n `Adding import for event model: ${eventModelInfo.name} from path: ${eventModelInfo.path}`,\n );\n addImportRefModel(\n queryClientFile,\n this.context.outputDir,\n eventModelInfo,\n );\n eventModelInfos.push(eventModelInfo);\n }\n const aggregateDomainEventType = resolveClassName(\n aggregate.aggregate,\n this.domainEventTypeSuffix,\n );\n const eventTypeUnion = eventModelInfos.map(it => it.name).join(' | ');\n this.context.logger.info(\n `Creating domain event types union: ${aggregateDomainEventType} = ${eventTypeUnion}`,\n );\n queryClientFile.addTypeAlias({\n isExported: true,\n name: aggregateDomainEventType,\n type: eventTypeUnion,\n });\n return aggregateDomainEventType;\n }\n\n private processAggregateDomainEventTypes(\n aggregate: AggregateDefinition,\n queryClientFile: SourceFile,\n ) {\n const aggregateDomainEventTypes = resolveClassName(\n aggregate.aggregate,\n this.domainEventTypeMapTitleSuffix,\n );\n const enumDeclaration = queryClientFile.addEnum({\n name: aggregateDomainEventTypes,\n isExported: true,\n });\n for (const event of aggregate.events.values()) {\n enumDeclaration.addMember({\n name: event.name,\n initializer: `'${event.title}'`,\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 { GenerateContext, Generator } from '../generateContext';\nimport { ApiClientGenerator } from './apiClientGenerator';\nimport { CommandClientGenerator } from './commandClientGenerator';\nimport { QueryClientGenerator } from './queryClientGenerator';\n\n/**\n * Generates TypeScript client classes for aggregates.\n * Creates query clients and command clients based on aggregate definitions.\n */\nexport class ClientGenerator implements Generator {\n private readonly queryClientGenerator: QueryClientGenerator;\n private readonly commandClientGenerator: CommandClientGenerator;\n private readonly apiClientGenerator: ApiClientGenerator;\n\n /**\n * Creates a new ClientGenerator instance.\n * @param context - The generation context containing OpenAPI spec and project details\n */\n constructor(public readonly context: GenerateContext) {\n this.queryClientGenerator = new QueryClientGenerator(context);\n this.commandClientGenerator = new CommandClientGenerator(context);\n this.apiClientGenerator = new ApiClientGenerator(context);\n }\n\n /**\n * Generates client classes for all aggregates.\n */\n generate(): void {\n this.context.logger.info('--- Generating Clients ---');\n this.context.logger.progress(\n `Generating clients for ${this.context.contextAggregates.size} bounded contexts`,\n );\n let currentIndex = 0;\n for (const [contextAlias] of this.context.contextAggregates) {\n currentIndex++;\n this.context.logger.progressWithCount(\n currentIndex,\n this.context.contextAggregates.size,\n `Processing bounded context: ${contextAlias}`,\n 1,\n );\n }\n this.queryClientGenerator.generate();\n this.commandClientGenerator.generate();\n this.apiClientGenerator.generate();\n this.context.logger.success('Client generation completed');\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 { Project, SourceFile } from 'ts-morph';\nimport { BoundedContextAggregates } from './aggregate';\nimport { GenerateContextInit, GeneratorConfiguration, Logger } from './types';\nimport { getOrCreateSourceFile } from './utils';\n\nexport class GenerateContext implements GenerateContextInit {\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 readonly config: GeneratorConfiguration;\n private readonly defaultIgnorePathParameters = ['tenantId', 'ownerId'];\n readonly currentContextAlias: string | undefined;\n\n constructor(context: GenerateContextInit) {\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 this.config = context.config ?? {};\n this.currentContextAlias = this.openAPI.info['x-wow-context-alias'];\n }\n\n getOrCreateSourceFile(filePath: string): SourceFile {\n return getOrCreateSourceFile(this.project, this.outputDir, filePath);\n }\n\n isIgnoreApiClientPathParameters(\n tagName: string,\n parameterName: string,\n ): boolean {\n const ignorePathParameters =\n this.config.apiClients?.[tagName]?.ignorePathParameters ??\n this.defaultIgnorePathParameters;\n return ignorePathParameters.includes(parameterName);\n }\n\n isIgnoreCommandClientPathParameters(\n tagName: string,\n parameterName: string,\n ): boolean {\n return this.defaultIgnorePathParameters.includes(parameterName);\n }\n}\n\nexport interface Generator {\n /**\n * Generates code based on the provided context.\n * Subclasses must implement this method to define their specific generation logic.\n */\n 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 { Directory, Project, SourceFile } from 'ts-morph';\nimport { AggregateResolver } from './aggregate';\nimport { ClientGenerator } from './client';\nimport { GenerateContext } from './generateContext';\nimport { ModelGenerator } from './model';\nimport { GeneratorConfiguration, GeneratorOptions } from './types';\nimport { parseConfiguration, parseOpenAPI } from './utils';\n\n/**\n * Default path to the generator configuration file.\n * This path is used when no custom config path is provided in the generator options.\n */\nexport const DEFAULT_CONFIG_PATH = './fetcher-generator.config.json';\n\n/**\n * Main code generator class that orchestrates the generation of TypeScript code from OpenAPI specifications.\n * This class handles the entire code generation process, including parsing OpenAPI specs,\n * resolving aggregates, generating models and clients, and formatting the output.\n *\n * @example\n * ```typescript\n * const generator = new CodeGenerator({\n * inputPath: './openapi.yaml',\n * outputDir: './generated',\n * tsConfigFilePath: './tsconfig.json',\n * logger: new ConsoleLogger(),\n * });\n * await generator.generate();\n * ```\n */\nexport class CodeGenerator {\n private readonly project: Project;\n\n /**\n * Creates a new CodeGenerator instance with the specified options.\n *\n * @param options - Configuration options for the code generation process, including input/output paths, TypeScript config, and logger.\n * @throws Error if the project initialization fails due to invalid TypeScript configuration or missing files.\n */\n constructor(private readonly options: GeneratorOptions) {\n this.project = new Project(options);\n this.options.logger.info(\n `Project instance created with tsConfigFilePath: ${this.options.tsConfigFilePath}`,\n );\n }\n\n /**\n * Generates TypeScript code from the OpenAPI specification.\n * This method performs the following steps:\n * 1. Parses the OpenAPI specification from the input path.\n * 2. Resolves bounded context aggregates.\n * 3. Parses the generator configuration.\n * 4. Generates models and clients.\n * 5. Creates index files for the output directory.\n * 6. Optimizes and formats the generated source files.\n * 7. Saves the project to disk.\n *\n * @returns A promise that resolves when code generation is complete.\n * @throws Error if OpenAPI parsing fails, configuration parsing fails, or file operations fail.\n *\n * @example\n * ```typescript\n * await generator.generate();\n * ```\n */\n async generate(): Promise<void> {\n this.options.logger.info(\n 'Starting code generation from OpenAPI specification',\n );\n const currentWorkingDir = process.cwd();\n this.options.logger.info(`Work directory: ${currentWorkingDir}`);\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 const configPath = this.options.configPath ?? DEFAULT_CONFIG_PATH;\n let config: GeneratorConfiguration = {};\n try {\n this.options.logger.info(`Parsing configuration file: ${configPath}`);\n config = await parseConfiguration(configPath);\n } catch (e) {\n this.options.logger.info(`Configuration file parsing failed: ${e}`);\n }\n\n const context: GenerateContext = new GenerateContext({\n openAPI: openAPI,\n project: this.project,\n outputDir: this.options.outputDir,\n contextAggregates: boundedContextAggregates,\n logger: this.options.logger,\n config: config,\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 const outputDir = this.project.getDirectory(this.options.outputDir);\n if (!outputDir) {\n this.options.logger.info('Output directory not found.');\n return;\n }\n this.options.logger.info('Generating index files');\n this.generateIndex(outputDir);\n this.options.logger.info('Index files generated successfully');\n\n this.options.logger.info('Optimizing source files');\n this.optimizeSourceFiles(outputDir);\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 * This method recursively processes all directories under the output directory,\n * creating index.ts files that export all TypeScript files and subdirectories.\n *\n * @param outputDir - The root output directory to generate index files for.\n *\n * @example\n * ```typescript\n * const outputDir = project.getDirectory('./generated');\n * generator.generateIndex(outputDir);\n * ```\n */\n generateIndex(outputDir: Directory) {\n this.options.logger.info(\n `Generating index files for output directory: ${this.options.outputDir}`,\n );\n this.processDirectory(outputDir);\n this.generateIndexForDirectory(outputDir);\n this.options.logger.info('Index file generation completed');\n }\n\n /**\n * Recursively processes all subdirectories to generate index files.\n * @param dir - The directory to process.\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 * Collects all .ts files (excluding index.ts) and subdirectories,\n * then creates export statements for each.\n *\n * @param dir - The directory to generate the index file 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 const subDirs: Directory[] = dir.getDirectories();\n\n this.options.logger.info(\n `Found ${tsFiles.length} TypeScript files and ${subDirs.length} subdirectories in ${dirPath}`,\n );\n\n if (tsFiles.length === 0 && subDirs.length === 0) {\n this.options.logger.info(\n `No files or subdirectories to export in ${dirPath}, skipping index generation`,\n );\n return;\n }\n\n const indexFilePath = `${dirPath}/index.ts`;\n const indexFile =\n this.project.getSourceFile(indexFilePath) ||\n this.project.createSourceFile(indexFilePath, '', { overwrite: true });\n\n indexFile.removeText();\n\n for (const tsFile of tsFiles) {\n const relativePath = `./${tsFile.getBaseNameWithoutExtension()}`;\n indexFile.addExportDeclaration({\n moduleSpecifier: relativePath,\n isTypeOnly: false,\n namedExports: [],\n });\n }\n\n for (const subDir of subDirs) {\n const relativePath = `./${subDir.getBaseName()}`;\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 + subDirs.length} exports`,\n );\n }\n\n /**\n * Optimizes all source files in the output directory.\n * Performs formatting, import organization, and fixes missing imports.\n *\n * @param outputDir - The root output directory containing source files to optimize.\n */\n optimizeSourceFiles(outputDir: Directory) {\n const sourceFiles = outputDir.getDescendantSourceFiles();\n this.options.logger.info(\n `Optimizing ${sourceFiles.length} source files in ${outputDir.getPath()}`,\n );\n sourceFiles.forEach((sourceFile, index) => {\n this.options.logger.info(\n `Optimizing file [${sourceFile.getFilePath()}] - ${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","splitName","name","tokenizeName","part","splitCamelCase","parts","result","current","i","char","isUpper","prevIsLower","pascalCase","firstChar","rest","camelCase","pascalCaseName","upperSnakeCase","resolvePropertyName","resolveEnumMemberName","isReference","schema","extractResponseSchema","contentType","response","extractResponseJsonSchema","ContentTypeValues","extractResponseEventStreamSchema","extractResponseWildcardSchema","PRIMITIVE_TYPES","isPrimitive","type","isEnum","isObject","isArray","isAnyOf","isOneOf","isAllOf","isComposition","toArrayType","isMap","X_MAP_KEY_SCHEMA","getMapKeySchema","isEmptyObject","isReadOnly","resolvePrimitiveType","it","resolveOptionalFields","required","operationEndpointComparator","left","right","extractOperationEndpoints","paths","operationEndpoints","path","pathItem","extractOperations","methodOperation","operation","extractOkResponse","extractOperationOkResponseJsonSchema","okResponse","extractPathParameters","parameter","DEFAULT_PATH_PARAMETER_TYPE","resolvePathParameterType","loadResource","loadHttpResource","loadFile","url","resolve","reject","readFile","err","data","parseOpenAPI","inputPath","content","inferFileFormat","parse","parseConfiguration","configPath","trimmedContent","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","sep","addImportModelInfo","currentModel","refModel","jsDoc","descriptions","separator","filtered","v","addJSDoc","node","jsdoc","schemaJSDoc","key","addJsonJsDoc","addNumericConstraintsJsDoc","addStringConstraintsJsDoc","addArrayConstraintsJsDoc","addSchemaJSDoc","addMainSchemaJSDoc","jsonJsDoc","propertyName","json","constraintsDescriptions","isAliasAggregate","tagName","tagToAggregate","tag","tagsToAggregates","tags","tagAliasAggregates","aggregates","tagAliasAggregate","operationIdToCommandName","operationId","CommandOkResponseRef","IdParameterRef","AggregateResolver","openAPI","endpoints","endpoint","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","resolveReferenceModelInfo","resolveContextDeclarationName","TypeGenerator","properties","propName","propSchema","resolvedPropName","jsDocDescriptions","doc","propertyDefs","additionalProps","mapKeySchema","keyType","valueType","val","types","s","itemType","value","interfaceDeclaration","propType","propertySignature","allOfSchema","resolvedType","ModelGenerator","context","schemas","stateAggregatedTypeNames","keySchemas","index","aggregatedTypeNames","typeNames","boundedContext","suffix","typeName","contextName","FETCHER_MODULE_SPECIFIER","FETCHER_NAMED_IMPORTS","DECORATOR_MODULE_SPECIFIER","DECORATOR_NAMED_IMPORTS","DEFAULT_RETURN_TYPE","STRING_RETURN_TYPE","STREAM_RESULT_EXTRACTOR_METADATA","addImportFetcher","addImportDecorator","createDecoratorClass","className","apiArgs","typeParameters","extendsClass","addApiMetadataCtor","classDeclaration","initializer","Scope","EVENTSTREAM_MODULE_SPECIFIER","addImportEventStream","inferPathSpecType","aggregateDefinition","tenantSpecCount","ownerSpecCount","command","ResourceAttributionPathSpec","createClientFilePath","resolveClassName","methodToDecorator","method","OPERATION_METHOD_NAME_KEY","resolveMethodName","isExists","methodName","operationName","ApiClientGenerator","apiClientTags","groupOperations","clientCount","operations","apiClientFile","apiClientClass","requestBody","requestBodySchema","requestType","parameterType","additionalProperties","jsonSchema","returnType","eventStreamSchema","methodDecorator","methodDeclaration","availableEndpoints","operationTags","totalOperations","totalTags","filteredTags","CommandClientGenerator","totalAggregates","sum","set","currentIndex","commandClientFile","aggregateCommandEndpointPathsName","VariableDeclarationKind","clientFile","enumDeclaration","definition","commandModelInfo","commandType","optionalFields","fieldName","commandClientName","commandClient","commandStreamClientName","client","QueryClientGenerator","queryClientFile","defaultClientOptionsName","aggregateDomainEventType","clientFactoryName","stateModelInfo","fieldsModelInfo","eventModelInfos","eventModelInfo","eventTypeUnion","aggregateDomainEventTypes","ClientGenerator","GenerateContext","parameterName","DEFAULT_CONFIG_PATH","CodeGenerator","options","Project","currentWorkingDir","boundedContextAggregates","config","e","dir","subDirs","subDir","dirPath","tsFiles","indexFilePath","indexFile","tsFile","sourceFiles"],"mappings":"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"}
|