@acrool/rtk-query-codegen-openapi 1.3.0-alpha.1 → 1.4.0-alpha.0
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/lib/bin/cli.mjs +41 -39
- package/lib/bin/cli.mjs.map +1 -1
- package/lib/index.js +297 -35
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +297 -35
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/generators/component-schema-generator.ts +10 -1
- package/src/generators/types-generator.ts +121 -32
- package/src/services/unified-code-generator.ts +100 -14
- package/src/utils/schema-ref-analyzer.ts +218 -0
package/lib/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/utils/http.ts","../src/index.ts","../src/services/unified-code-generator.ts","../src/services/openapi-service.ts","../src/utils/capitalize.ts","../src/utils/downloadSchema.ts","../src/utils/isValidUrl.ts","../src/utils/getOperationDefinitions.ts","../src/types.ts","../src/utils/getV3Doc.ts","../src/utils/isQuery.ts","../src/services/group-service.ts","../src/services/file-writer-service.ts","../src/utils/directory.ts","../src/services/openapi-parser-service.ts","../src/generators/common-types-generator.ts","../src/generators/component-schema-generator.ts","../src/generators/do-not-modify-generator.ts","../src/services/api-code-generator.ts","../src/services/endpoint-info-extractor.ts","../src/generators/types-generator.ts","../src/generators/rtk-query-generator.ts","../src/generators/rtk-enhance-endpoints-generator.ts","../src/generators/utils-generator.ts","../src/generators/tag-types-generator.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import type {\n EndpointMatcher, EndpointOverrides,\n OperationDefinition,\n ParameterDefinition,\n ParameterMatcher,\n TextMatcher,\n} from '../types';\nimport {\n getOperationName as _getOperationName,\n} from 'oazapfts/generate';\n\n\n/**\n * 判斷 HTTP 狀態碼是否為成功的數據響應\n */\nexport function defaultIsDataResponse(code: string, includeDefault: boolean) {\n if (includeDefault && code === 'default') {\n return true;\n }\n const parsedCode = Number(code);\n return !Number.isNaN(parsedCode) && parsedCode >= 200 && parsedCode < 300;\n}\n\n/**\n * 根據 HTTP 方法和路徑生成操作名稱\n */\nexport function getOperationName({ verb, path }: Pick<OperationDefinition, 'verb' | 'path'>) {\n return _getOperationName(verb, path, undefined);\n}\n\n\n\n\n/**\n * 從路徑項目中提取標籤(tags)\n */\nexport function getTags({ verb, pathItem }: Pick<OperationDefinition, 'verb' | 'pathItem'>): string[] {\n return verb ? pathItem[verb]?.tags || [] : [];\n}\n\n/**\n * 創建文本匹配器函數,用於過濾操作名稱\n */\nfunction patternMatches(pattern?: TextMatcher) {\n const filters = Array.isArray(pattern) ? pattern : [pattern];\n return function matcher(operationName: string) {\n if (!pattern) return true;\n return filters.some((filter) =>\n typeof filter === 'string' ? filter === operationName : filter?.test(operationName)\n );\n };\n}\n\n/**\n * 創建操作匹配器函數,用於過濾操作定義\n */\nexport function operationMatches(pattern?: EndpointMatcher) {\n const checkMatch = typeof pattern === 'function' ? pattern : patternMatches(pattern);\n return function matcher(operationDefinition: OperationDefinition) {\n if (!pattern) return true;\n const operationName = getOperationName(operationDefinition);\n return checkMatch(operationName, operationDefinition);\n };\n}\n\n/**\n * 創建參數匹配器函數,用於過濾參數定義\n */\nexport function argumentMatches(pattern?: ParameterMatcher) {\n const checkMatch = typeof pattern === 'function' ? pattern : patternMatches(pattern);\n return function matcher(argumentDefinition: ParameterDefinition) {\n if (!pattern || argumentDefinition.in === 'path') return true;\n const argumentName = argumentDefinition.name;\n return checkMatch(argumentName, argumentDefinition);\n };\n}\n\n/**\n * 獲取操作的覆蓋配置\n */\nexport function getOverrides(\n operation: OperationDefinition,\n endpointOverrides?: EndpointOverrides[]\n): EndpointOverrides | undefined {\n return endpointOverrides?.find((override) => operationMatches(override.pattern)(operation));\n}","import { UnifiedCodeGenerator, type UnifiedGenerationOptions, type UnifiedGenerationResult } from './services/unified-code-generator';\n\nexport type { OutputFilesConfig, ConfigFile } from './types';\n\n\n/**\n * 產生 Endpoints - 直接使用統一代碼生成器\n * @param options - 端點生成選項\n */\nexport async function generateEndpoints(options: UnifiedGenerationOptions): Promise<string | void> {\n const generator = new UnifiedCodeGenerator(options);\n\n const result = await generator.generateAll();\n \n if (!result.success) {\n if (result.errors.length > 0) {\n throw result.errors[0];\n }\n }\n return;\n}\n","import path from 'node:path';\nimport ts from 'typescript';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport { OpenApiService } from './openapi-service';\nimport { GroupService, type GroupConfig } from './group-service';\nimport { FileWriterService, type FileWriteResult } from './file-writer-service';\nimport { OpenApiParserService } from './openapi-parser-service';\nimport { generateCommonTypesFile } from '../generators/common-types-generator';\nimport { generateComponentSchemaFile } from '../generators/component-schema-generator';\nimport { generateDoNotModifyFile } from '../generators/do-not-modify-generator';\nimport type { GenerationOptions, CommonOptions } from '../types';\nimport { ApiCodeGenerator } from './api-code-generator';\nimport { generateUtilsFile } from '../generators/utils-generator';\nimport { generateTagTypesFile } from '../generators/tag-types-generator';\n\n/**\n * 統一代碼生成器選項\n */\nexport interface UnifiedGenerationOptions extends CommonOptions {\n outputFiles: GroupConfig;\n remoteFile?: string;\n}\n\n/**\n * 統一代碼生成器結果\n */\nexport interface UnifiedGenerationResult {\n success: boolean;\n writtenFiles: FileWriteResult[];\n errors: Error[];\n generatedGroups: string[];\n}\n\n/**\n * 統一代碼生成器\n * \n * 設計理念:\n * - 統一管理所有生成流程\n * - 內建 schema 處理和存儲\n * - 提供準備、生成、發佈的分階段操作\n * - 避免重複初始化和處理\n * \n * 使用方式:\n * 1. prepare() - 準備階段:解析 schema、初始化服務\n * 2. generateContent() - 生成階段:產生所有內容但不寫檔\n * 3. release() - 發佈階段:統一寫入所有檔案\n */\nexport class UnifiedCodeGenerator {\n private _options: UnifiedGenerationOptions;\n\n private openApiService = new OpenApiService();\n private groupService = new GroupService();\n private fileWriterService = new FileWriterService();\n \n // 內部狀態存儲\n private openApiDoc: OpenAPIV3.Document | null = null;\n private parserService: OpenApiParserService | null = null;\n private schemaInterfaces: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration> = {};\n private actualSchemaFile: string = '';\n \n // 生成內容存儲\n private generatedContent: {\n groups: Array<{\n groupKey: string;\n outputPath: string;\n content: any;\n }>;\n commonTypes: string;\n componentSchema: string;\n doNotModify: string;\n utils: string;\n tagTypes: string;\n } = {\n groups: [],\n commonTypes: '',\n componentSchema: '',\n doNotModify: '',\n utils: '',\n tagTypes: ''\n };\n\n // 收集所有 tags\n private allTags: Set<string> = new Set();\n\n\n constructor(options: UnifiedGenerationOptions) {\n this._options = options;\n }\n\n\n\n /**\n * 一次性生成(整合所有階段)\n */\n async generateAll(): Promise<UnifiedGenerationResult> {\n await this.prepare();\n\n // 生成各API文件\n await this.generateApi();\n // await this.generateQuery();\n\n // 生成共用\n this.generateCommonTypesContent()\n this.generateSchemaContent()\n this.generateUtilsContent()\n this.generateDoNotModifyContent()\n this.generateTagTypesContent()\n\n return await this.release();\n }\n\n\n\n /**\n * 準備階段:解析 schema 並初始化所有服務\n */\n async prepare(): Promise<void> {\n // console.log('UnifiedCodeGenerator: 準備階段開始...');\n \n // 步驟 1: 解析實際的 schema 檔案路徑\n this.actualSchemaFile = this._options.schemaFile;\n if (this._options.remoteFile) {\n this.actualSchemaFile = await this.openApiService.downloadSchema(\n this._options.remoteFile,\n this._options.schemaFile\n );\n }\n\n // 步驟 2: 獲取 OpenAPI 文檔(只初始化一次)\n this.openApiDoc = await this.openApiService.getDocument(\n this.actualSchemaFile,\n this._options.httpResolverOptions\n );\n\n // 步驟 3: 初始化解析器服務並處理 schema\n this.parserService = new OpenApiParserService(this.openApiDoc, this._options);\n this.parserService.initialize();\n\n // 步驟 4: 提取並儲存 schema interfaces\n const apiGen = this.parserService.getApiGenerator();\n this.schemaInterfaces = apiGen.aliases.reduce<Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>>((curr, alias) => {\n if (ts.isInterfaceDeclaration(alias) || ts.isTypeAliasDeclaration(alias)) {\n const name = alias.name.text;\n return {\n ...curr,\n [name]: alias,\n };\n }\n return curr;\n }, {});\n\n // console.log('UnifiedCodeGenerator: 準備階段完成');\n }\n\n\n\n /**\n * 生成階段:產生所有內容但不寫檔\n */\n async generateApi(): Promise<void> {\n if (!this.openApiDoc || !this.parserService) {\n throw new Error('請先調用 prepare() 方法');\n }\n\n // console.log('UnifiedCodeGenerator: 內容生成階段開始...');\n\n // 獲取所有 API 接口Path並分組\n const paths = this.openApiService.getPaths(this.openApiDoc);\n const groupInfos = this.groupService.groupPaths(paths, this._options.outputFiles);\n\n // 為每個群組生成內容\n for (const groupInfo of Object.values(groupInfos)) {\n try {\n const groupContent = await this.generateApiGroupContent(\n this._options,\n groupInfo\n );\n\n // 檢查群組是否有任何有效的 endpoint\n if (groupContent.operationNames.length > 0) {\n this.generatedContent.groups.push({\n groupKey: groupInfo.groupKey,\n outputPath: groupInfo.outputPath,\n content: groupContent\n });\n\n // 收集此群組的所有 tags\n if (groupContent.tags && Array.isArray(groupContent.tags)) {\n groupContent.tags.forEach((tag: string) => this.allTags.add(tag));\n }\n }\n // 如果沒有任何 endpoint,則跳過此群組,不創建資料夾\n } catch (error) {\n throw new Error(`群組 ${groupInfo.groupKey} 生成失敗: ${error}`);\n }\n }\n\n // console.log('UnifiedCodeGenerator: 內容生成階段完成');\n }\n\n\n\n /**\n * 生成 common types\n */\n private async generateCommonTypesContent(): Promise<void> {\n this.generatedContent.commonTypes = generateCommonTypesFile();\n }\n\n /**\n * 生成Schema\n */\n private async generateSchemaContent(): Promise<void> {\n this.generatedContent.componentSchema = generateComponentSchemaFile(this.schemaInterfaces);\n }\n\n /**\n * 生成 DO_NOT_MODIFY.md\n */\n private async generateDoNotModifyContent(): Promise<void> {\n this.generatedContent.doNotModify = generateDoNotModifyFile();\n }\n\n\n /**\n * 生成 Utils Function\n */\n private async generateUtilsContent(): Promise<void> {\n this.generatedContent.utils = generateUtilsFile();\n }\n\n /**\n * 生成 Tag Types\n */\n private async generateTagTypesContent(): Promise<void> {\n const tagsArray = Array.from(this.allTags);\n this.generatedContent.tagTypes = generateTagTypesFile(tagsArray);\n }\n\n\n\n\n /**\n * 發佈階段:統一寫入所有檔案\n */\n async release(): Promise<UnifiedGenerationResult> {\n const results: FileWriteResult[] = [];\n const errors: Error[] = [];\n const generatedGroups: string[] = [];\n\n // console.log('UnifiedCodeGenerator: 發佈階段開始...');\n\n try {\n // 寫入群組檔案\n for (const group of this.generatedContent.groups) {\n try {\n if (group.content?.files) {\n const groupOutputDir = path.dirname(group.outputPath);\n // RTK Query 模式 (唯一支援模式)\n const groupResults = await this.fileWriterService.writeGroupFiles(\n groupOutputDir,\n {\n types: group.content.files.types,\n queryService: group.content.files.queryService,\n enhanceEndpoints: group.content.files.enhanceEndpoints,\n index: group.content.files.index\n }\n );\n\n results.push(...groupResults);\n generatedGroups.push(group.groupKey);\n }\n } catch (error) {\n errors.push(new Error(`寫入群組 ${group.groupKey} 失敗: ${error}`));\n }\n }\n\n // 寫入共用檔案\n const outputDir = this.generatedContent.groups[0] ? \n path.dirname(path.dirname(this.generatedContent.groups[0].outputPath)) : \n './generated';\n\n // 寫入共用檔案 (包含 DO_NOT_MODIFY.md)\n if (this.generatedContent.commonTypes || this.generatedContent.doNotModify || this.generatedContent.utils) {\n const sharedResults = await this.fileWriterService.writeSharedFiles(\n outputDir,\n {\n commonTypes: this.generatedContent.commonTypes || undefined,\n doNotModify: this.generatedContent.doNotModify || undefined,\n utils: this.generatedContent.utils || undefined\n }\n );\n results.push(...sharedResults);\n }\n\n // 寫入 tagTypes.ts\n if (this.generatedContent.tagTypes) {\n const tagTypesResult = await this.fileWriterService.writeFile(\n path.join(outputDir, 'tagTypes.ts'),\n this.generatedContent.tagTypes\n );\n results.push(tagTypesResult);\n }\n\n // 寫入 component schema\n if (this.generatedContent.componentSchema) {\n const schemaResults = await this.fileWriterService.writeSchemaFile(\n outputDir,\n this.generatedContent.componentSchema\n );\n results.push(...schemaResults);\n }\n\n // 生成主 index.ts 檔案\n const mainIndexContent = this.generateMainIndex(generatedGroups);\n const mainIndexResult = await this.fileWriterService.writeFile(\n path.join(outputDir, 'index.ts'),\n mainIndexContent\n );\n results.push(mainIndexResult);\n\n } catch (error) {\n errors.push(error as Error);\n }\n\n // console.log('UnifiedCodeGenerator: 發佈階段完成');\n\n return {\n success: errors.length === 0,\n writtenFiles: results,\n errors,\n generatedGroups\n };\n }\n\n\n /**\n * 為單一群組生成內容\n */\n private async generateApiGroupContent(\n options: UnifiedGenerationOptions,\n groupInfo: { groupKey: string; paths: string[]; outputPath: string }\n ): Promise<any> {\n const { outputFiles, ...commonConfig } = options;\n\n // 建立群組特定的生成選項\n const groupOptions: GenerationOptions = {\n ...commonConfig,\n schemaFile: this.actualSchemaFile,\n outputFile: groupInfo.outputPath,\n sharedTypesFile: `${outputFiles.outputDir}/common-types.ts`,\n filterEndpoints: this.groupService.createGroupFilter(groupInfo.groupKey, outputFiles),\n queryMatch: outputFiles.queryMatch,\n groupKey: groupInfo.groupKey,\n };\n\n // 使用新的 ApiCodeGenerator 生成程式碼,重用已處理的 v3Doc\n if (!this.openApiDoc || !this.parserService) {\n throw new Error('OpenAPI 文檔未初始化,請先調用 prepare()');\n }\n \n const apiGenerator = new ApiCodeGenerator(this.parserService, groupOptions);\n const result = await apiGenerator.generate();\n\n\n return result;\n }\n\n /**\n * 生成主 index.ts 檔案\n */\n private generateMainIndex(generatedGroups: string[]): string {\n const exports = generatedGroups.map(groupKey => `export * from \"./${groupKey}\";`).join('\\n');\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${exports}\n`;\n }\n\n}","import type { OpenAPIV3 } from 'openapi-types';\nimport { getV3Doc, downloadSchemaFile } from '../utils';\n\n/**\n * OpenAPI 服務 - 負責獲取和處理 OpenAPI 文檔\n * \n * 單一職責:\n * - 從本地文件或遠程URL獲取OpenAPI文檔\n * - 管理文檔快取\n * - 提供文檔基本操作方法\n * \n * 設計原則:\n * - 非收集模式:每次調用都是獨立的操作\n * - 無副作用:不修改傳入的參數\n * - 可測試性:所有方法都有明確的輸入輸出\n */\nexport class OpenApiService {\n private docCache: Record<string, OpenAPIV3.Document> = {};\n\n /**\n * 獲取 OpenAPI 文檔\n * @param schemaLocation - Schema 位置 (URL 或本地路徑)\n * @param httpResolverOptions - HTTP 解析選項\n */\n async getDocument(\n schemaLocation: string, \n httpResolverOptions?: any\n ): Promise<OpenAPIV3.Document> {\n if (this.docCache[schemaLocation]) {\n return this.docCache[schemaLocation];\n }\n\n const doc = await getV3Doc(schemaLocation, httpResolverOptions);\n this.docCache[schemaLocation] = doc;\n return doc;\n }\n\n /**\n * 下載遠程 Schema 文件\n * @param remoteUrl - 遠程 URL\n * @param localPath - 本地儲存路徑\n */\n async downloadSchema(remoteUrl: string, localPath: string): Promise<string> {\n return downloadSchemaFile(remoteUrl, localPath);\n }\n\n /**\n * 獲取所有 API 路徑\n * @param doc - OpenAPI 文檔\n */\n getPaths(doc: OpenAPIV3.Document): string[] {\n return Object.keys(doc.paths || {});\n }\n\n /**\n * 清除快取\n */\n clearCache(): void {\n this.docCache = {};\n }\n}","export function capitalize(str: string) {\n return str.replace(str[0], str[0].toUpperCase());\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { isValidUrl } from './isValidUrl';\n\nexport async function downloadSchemaFile(remoteFile: string, targetPath: string): Promise<string> {\n // 如果不是網址,拋出錯誤\n if (!isValidUrl(remoteFile)) {\n throw new Error(`remoteFile must be a valid URL: ${remoteFile}`);\n }\n\n try {\n // 確保目錄存在\n const dir = path.dirname(targetPath);\n if (!fs.existsSync(dir)) {\n await fs.promises.mkdir(dir, { recursive: true });\n }\n\n // 下載檔案\n const response = await fetch(remoteFile);\n if (!response.ok) {\n throw new Error(`Failed to download schema from ${remoteFile}: ${response.statusText}`);\n }\n\n const content = await response.text();\n await fs.promises.writeFile(targetPath, content, 'utf-8');\n\n console.log(`Schema downloaded from ${remoteFile} to ${targetPath}`);\n return targetPath;\n } catch (error) {\n console.error(`Error downloading schema from ${remoteFile}:`, error);\n throw error;\n }\n} ","export function isValidUrl(string: string) {\n try {\n new URL(string);\n } catch (_) {\n return false;\n }\n\n return true;\n}\n","import type { OpenAPIV3 } from 'openapi-types';\nimport type { OperationDefinition } from '../types';\nimport { operationKeys } from '../types';\n\nexport function getOperationDefinitions(v3Doc: OpenAPIV3.Document): OperationDefinition[] {\n return Object.entries(v3Doc.paths).flatMap(([path, pathItem]) =>\n !pathItem\n ? []\n : Object.entries(pathItem)\n .filter((arg): arg is [(typeof operationKeys)[number], OpenAPIV3.OperationObject] =>\n operationKeys.includes(arg[0] as any)\n )\n .map(([verb, operation]) => ({\n path,\n verb,\n pathItem,\n operation,\n }))\n );\n}\n","import type SwaggerParser from '@apidevtools/swagger-parser';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport ts from 'typescript';\n\n// 重新匯出服務相關類型\nexport type {\n GroupConfig,\n GroupInfo\n} from './services/group-service';\n\nexport type {\n FileWriteResult\n} from './services/file-writer-service';\n\n\nexport type {\n UnifiedGenerationOptions as EndpointGenerationOptions,\n UnifiedGenerationResult as EndpointGenerationResult\n} from './services/unified-code-generator';\n\nexport type OperationDefinition = {\n path: string;\n verb: (typeof operationKeys)[number];\n pathItem: OpenAPIV3.PathItemObject;\n operation: OpenAPIV3.OperationObject;\n};\n\nexport type ParameterDefinition = OpenAPIV3.ParameterObject;\n\ntype Require<T, K extends keyof T> = { [k in K]-?: NonNullable<T[k]> } & Omit<T, K>;\ntype Optional<T, K extends keyof T> = { [k in K]?: NonNullable<T[k]> } & Omit<T, K>;\ntype Id<T> = { [K in keyof T]: T[K] } & {};\ntype AtLeastOneKey<T> = {\n [K in keyof T]-?: Pick<T, K> & Partial<T>;\n}[keyof T];\n\nexport const operationKeys = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'] as const;\n\nexport type GenerationOptions = Id<\n CommonOptions &\n Optional<OutputFileOptions, 'outputFile'> & {\n isDataResponse?(\n code: string,\n includeDefault: boolean,\n response: OpenAPIV3.ResponseObject,\n allResponses: OpenAPIV3.ResponsesObject\n ): boolean;\n}\n>;\n\nexport interface CommonOptions {\n /**\n * local schema file path (only supports local files)\n */\n schemaFile: string;\n /**\n * remote schema file URL (when provided, will download to schemaFile path)\n */\n remoteFile?: string;\n /**\n * Configuration for WebApiConfiguration import\n * defaults to { file: \"@core/api/web-api-configuration\", importName: \"WebApiConfiguration\" }\n */\n apiConfiguration?: {\n file: string;\n importName: string;\n };\n /**\n * HTTP client configuration for API calls\n * defaults to { file: \"@core/httpClient/webapi/webapi-http-client.providers\", importName: \"WEBAPI_HTTP_CLIENT\" }\n */\n httpClient?: {\n file: string;\n importReturnTypeName: string; // 用於指定別名導入,例如 IRestFulEndpointsQueryReturn\n };\n /**\n * defaults to \"enhancedApi\"\n */\n exportName?: string;\n /**\n * defaults to \"Req\"\n */\n argSuffix?: string;\n /**\n * defaults to \"Res\"\n */\n responseSuffix?: string;\n /**\n * defaults to empty\n */\n operationNameSuffix?: string;\n /**\n * defaults to `false`\n * `true` will generate lazy query hooks (useLazy prefix) for query endpoints\n */\n useLazyQueries?: boolean;\n /**\n * defaults to false\n * `true` will generate a union type for `undefined` properties like: `{ id?: string | undefined }` instead of `{ id?: string }`\n */\n unionUndefined?: boolean;\n /**\n * defaults to false\n * `true` will result in all generated endpoints having `providesTags`/`invalidatesTags` declarations for the `tags` of their respective operation definition\n * @see https://redux-toolkit.js.org/rtk-query/usage/code-generation for more information\n */\n tag?: boolean;\n /**\n * defaults to false\n * `true` will add `encodeURIComponent` to the generated path parameters\n */\n encodePathParams?: boolean;\n /**\n * defaults to false\n * `true` will add `encodeURIComponent` to the generated query parameters\n */\n encodeQueryParams?: boolean;\n /**\n * defaults to false\n * `true` will \"flatten\" the arg so that you can do things like `useGetEntityById(1)` instead of `useGetEntityById({ entityId: 1 })`\n */\n flattenArg?: boolean;\n /**\n * default to false\n * If set to `true`, the default response type will be included in the generated code for all endpoints.\n * @see https://swagger.io/docs/specification/describing-responses/#default\n */\n includeDefault?: boolean;\n /**\n * default to false\n * `true` will not generate separate types for read-only and write-only properties.\n */\n mergeReadWriteOnly?: boolean;\n /**\n *\n * HTTPResolverOptions object that is passed to the SwaggerParser bundle function.\n */\n httpResolverOptions?: SwaggerParser.HTTPResolverOptions;\n\n /**\n * defaults to undefined\n * If present the given file will be used as prettier config when formatting the generated code. If undefined the default prettier config\n * resolution mechanism will be used.\n */\n prettierConfigFile?: string;\n /**\n * defaults to \"@acrool/react-fetcher\"\n * File path for importing IRestFulEndpointsQueryReturn type\n */\n endpointsQueryReturnTypeFile?: string;\n}\n\nexport type TextMatcher = string | RegExp | (string | RegExp)[];\n\nexport type EndpointMatcherFunction = (operationName: string, operationDefinition: OperationDefinition) => boolean;\n\nexport type EndpointMatcher = TextMatcher | EndpointMatcherFunction;\n\nexport type ParameterMatcherFunction = (parameterName: string, parameterDefinition: ParameterDefinition) => boolean;\n\nexport type ParameterMatcher = TextMatcher | ParameterMatcherFunction;\n\nexport interface OutputFileOptions extends Partial<CommonOptions> {\n outputFile: string;\n filterEndpoints?: EndpointMatcher;\n endpointOverrides?: EndpointOverrides[];\n queryMatch?: (method: string, path: string) => boolean;\n sharedTypesFile?: string;\n /**\n * groupKey for service class naming, e.g., \"room\" -> \"RoomService\"\n */\n groupKey?: string;\n}\n\nexport type EndpointOverrides = {\n pattern: EndpointMatcher;\n} & AtLeastOneKey<{\n type: 'mutation' | 'query';\n parameterFilter: ParameterMatcher;\n}>;\n\nexport type OutputFilesConfig = {\n groupKeyMatch: (path: string) => string;\n outputDir: string;\n queryMatch?: (method: string, path: string) => boolean;\n filterEndpoint?: (operationName: string, path: string, groupKey: string) => boolean;\n};\n\nexport type ConfigFile =\n | Id<Require<CommonOptions & OutputFileOptions, 'outputFile'>>\n | Id<\n Omit<CommonOptions, 'outputFile'> & {\n // outputFiles: { [outputFile: string]: Omit<OutputFileOptions, 'outputFile'> };\n outputFiles: OutputFilesConfig\n}\n>;\n\nexport type GenerateApiResult = {\n operationNames: string[];\n tags: string[]; // 收集到的所有 tags\n files: {\n types: string;\n queryService: string; // RTK Query generated file\n index: string;\n enhanceEndpoints?: string; // RTK Query enhance endpoints file\n commonTypes?: string;\n componentSchema?: string;\n };\n};\n\n\n\nexport type QueryArgDefinition = {\n name: string;\n originalName: string;\n type: ts.TypeNode;\n required?: boolean;\n param?: OpenAPIV3.ParameterObject;\n} & (\n | {\n origin: 'param';\n param: OpenAPIV3.ParameterObject;\n}\n | {\n origin: 'body';\n body: OpenAPIV3.RequestBodyObject;\n}\n );\n\nexport type QueryArgDefinitions = Record<string, QueryArgDefinition>;\n","import SwaggerParser from '@apidevtools/swagger-parser';\nimport type { OpenAPIV3 } from 'openapi-types';\n// @ts-ignore\nimport converter from 'swagger2openapi';\n\nexport async function getV3Doc(\n spec: string,\n httpResolverOptions?: SwaggerParser.HTTPResolverOptions\n): Promise<OpenAPIV3.Document> {\n const doc = await SwaggerParser.bundle(spec, {\n resolve: {\n http: httpResolverOptions,\n },\n });\n\n const isOpenApiV3 = 'openapi' in doc && doc.openapi.startsWith('3');\n\n if (isOpenApiV3) {\n return doc as OpenAPIV3.Document;\n } else {\n const result = await converter.convertObj(doc, {});\n return result.openapi as OpenAPIV3.Document;\n }\n}\n","import type { EndpointOverrides, operationKeys } from '../types';\n\nexport function isQuery(\n verb: (typeof operationKeys)[number],\n path: string,\n overrides: EndpointOverrides | undefined,\n queryMatch?: (method: string, path: string) => boolean\n) {\n if (queryMatch) {\n return queryMatch(verb, path);\n }\n if (overrides?.type) {\n return overrides.type === 'query';\n }\n return verb === 'get';\n}\n","import camelCase from 'lodash.camelcase';\n\n/**\n * 群組配置介面\n */\nexport interface GroupConfig {\n outputDir: string;\n groupKeyMatch: (path: string) => string | null;\n filterEndpoint?: (operationName: string, path: string, groupKey: string) => boolean;\n queryMatch?: (operationName: string) => boolean;\n}\n\n/**\n * 群組信息介面\n */\nexport interface GroupInfo {\n groupKey: string;\n paths: string[];\n outputPath: string;\n}\n\n/**\n * 群組服務 - 負責處理 API 路徑分組\n */\nexport class GroupService {\n /**\n * 根據配置對路徑進行分組\n * @param paths - API 路徑陣列\n * @param config - 群組配置\n */\n groupPaths(paths: string[], config: GroupConfig): Record<string, GroupInfo> {\n const { groupKeyMatch, outputDir } = config;\n \n const groupedPaths = paths.reduce((acc, path) => {\n const rawGroupKey = groupKeyMatch(path);\n const groupKey = rawGroupKey ? camelCase(rawGroupKey) : '_common';\n \n if (!acc[groupKey]) {\n acc[groupKey] = [];\n }\n acc[groupKey].push(path);\n return acc;\n }, {} as Record<string, string[]>);\n\n // 轉換為 GroupInfo 格式\n const result: Record<string, GroupInfo> = {};\n for (const [groupKey, paths] of Object.entries(groupedPaths)) {\n result[groupKey] = {\n groupKey,\n paths,\n outputPath: `${outputDir}/${groupKey}/query.service.ts`\n };\n }\n\n return result;\n }\n\n /**\n * 為特定群組建立篩選函數\n * @param groupKey - 群組鍵\n * @param config - 群組配置\n */\n createGroupFilter(\n groupKey: string,\n config: GroupConfig\n ): (operationName: string, operationDefinition: any) => boolean {\n return (operationName: string, operationDefinition: any) => {\n const path = operationDefinition.path;\n\n // 檢查路徑是否匹配當前分組\n const pathGroupKey = camelCase(config.groupKeyMatch(path) || '');\n if (pathGroupKey !== groupKey && (pathGroupKey || '_common') !== groupKey) {\n return false;\n }\n\n // 使用 filterEndpoint 進行額外篩選\n if (config.filterEndpoint) {\n return config.filterEndpoint(operationName, path, groupKey);\n }\n\n return true;\n };\n }\n}","import fs from 'node:fs';\nimport path from 'node:path';\nimport { ensureDirectoryExists } from '../utils/directory';\n\n/**\n * 檔案寫入結果\n */\nexport interface FileWriteResult {\n path: string;\n success: boolean;\n error?: Error;\n}\n\n/**\n * 檔案寫入服務 - 負責將產生的內容寫入檔案\n */\nexport class FileWriterService {\n /**\n * 寫入單一檔案\n * @param filePath - 檔案路徑\n * @param content - 檔案內容\n */\n async writeFile(filePath: string, content: string): Promise<FileWriteResult> {\n try {\n const resolvedPath = path.resolve(process.cwd(), filePath);\n const fileName = path.basename(resolvedPath);\n\n // enhanceEndpoints.ts 如果已存在則跳過寫入\n if (fileName === 'enhanceEndpoints.ts' && fs.existsSync(resolvedPath)) {\n return {\n path: resolvedPath,\n success: true\n };\n }\n\n await ensureDirectoryExists(resolvedPath);\n\n fs.writeFileSync(resolvedPath, content);\n\n return {\n path: resolvedPath,\n success: true\n };\n } catch (error) {\n return {\n path: filePath,\n success: false,\n error: error as Error\n };\n }\n }\n\n /**\n * 批次寫入多個檔案\n * @param files - 檔案路徑與內容的對應表\n */\n async writeFiles(files: Record<string, string>): Promise<FileWriteResult[]> {\n const results: FileWriteResult[] = [];\n\n for (const [filePath, content] of Object.entries(files)) {\n const result = await this.writeFile(filePath, content);\n results.push(result);\n }\n\n return results;\n }\n\n\n /**\n * 為群組寫入 RTK Query 檔案結構\n * @param groupOutputDir - 群組輸出目錄\n * @param files - 檔案內容\n */\n async writeGroupFiles(\n groupOutputDir: string,\n files: {\n types?: string; // types.ts\n queryService?: string; // query.generated.ts\n enhanceEndpoints?: string; // enhanceEndpoints.ts\n index?: string; // index.ts\n }\n ): Promise<FileWriteResult[]> {\n const filesToWrite: Record<string, string> = {};\n\n if (files.types) {\n filesToWrite[path.join(groupOutputDir, 'types.ts')] = files.types;\n }\n\n if (files.queryService) {\n filesToWrite[path.join(groupOutputDir, 'query.generated.ts')] = files.queryService;\n }\n\n if (files.enhanceEndpoints) {\n filesToWrite[path.join(groupOutputDir, 'enhanceEndpoints.ts')] = files.enhanceEndpoints;\n }\n\n if (files.index) {\n filesToWrite[path.join(groupOutputDir, 'index.ts')] = files.index;\n }\n\n return this.writeFiles(filesToWrite);\n }\n\n /**\n * 寫入共享檔案\n * @param outputDir - 輸出目錄\n * @param sharedFiles - 共享檔案內容\n */\n async writeSharedFiles(\n outputDir: string,\n sharedFiles: {\n commonTypes?: string;\n doNotModify?: string;\n utils?: string;\n }\n ): Promise<FileWriteResult[]> {\n const filesToWrite: Record<string, string> = {};\n\n if (sharedFiles.commonTypes) {\n filesToWrite[path.join(outputDir, 'common-types.ts')] = sharedFiles.commonTypes;\n }\n \n\n if (sharedFiles.doNotModify) {\n filesToWrite[path.join(outputDir, 'DO_NOT_MODIFY.md')] = sharedFiles.doNotModify;\n }\n\n if (sharedFiles.utils) {\n filesToWrite[path.join(outputDir, 'utils.ts')] = sharedFiles.utils;\n }\n\n return this.writeFiles(filesToWrite);\n }\n\n /**\n * 寫入共享檔案\n * @param outputDir - 輸出目錄\n * @param schema\n */\n async writeSchemaFile(\n outputDir: string,\n schema: string\n ): Promise<FileWriteResult[]> {\n const filesToWrite: Record<string, string> = {};\n\n filesToWrite[path.join(outputDir, 'schema.ts')] = schema;\n\n return this.writeFiles(filesToWrite);\n }\n\n\n}","import path from 'node:path';\nimport fs from 'node:fs';\n\n/**\n * 確保目錄存在的函數\n * @param filePath\n */\nexport async function ensureDirectoryExists(filePath: string) {\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) {\n await fs.promises.mkdir(dirname, { recursive: true });\n }\n}\n\n/**\n * 檢查檔案是否存在的函數\n * @param filePath\n */\nexport function fileExists(filePath: string): boolean {\n try {\n return fs.statSync(filePath).isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * 獲取資料夾名稱並轉換為 API 名稱\n * @param dirPath\n */\nexport function getApiNameFromDir(dirPath: string): string {\n const dirName = path.basename(dirPath);\n return `${dirName}Api`;\n}\n\n\n\n\n/**\n * 確保基礎文件存在的函數\n * @param outputDir\n * @param operationNames\n */\nexport async function ensureBaseFilesExist(outputDir: string, operationNames: string[]) {\n const enhanceEndpointsPath = path.join(outputDir, 'enhanceEndpoints.ts');\n const indexPath = path.join(outputDir, 'index.ts');\n\n // 如果 enhanceEndpoints.ts 不存在,創建它\n if (!fileExists(enhanceEndpointsPath)) {\n // 生成操作名稱的字符串\n const operationNamesString = operationNames\n .map(name => ` ${name}: {},`)\n .join('\\n');\n\n const enhanceEndpointsContent = `import api from './query.service';\n\nconst enhancedApi = api.enhanceEndpoints({\n endpoints: {\n${operationNamesString}\n },\n});\n\nexport default enhancedApi;\n`;\n await fs.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, 'utf-8');\n }\n // 如果文件已存在,不做任何修改\n\n // 如果 index.ts 不存在,創建它\n if (!fileExists(indexPath)) {\n const indexContent = `export * from './query.service';\n`;\n await fs.promises.writeFile(indexPath, indexContent, 'utf-8');\n }\n}","import ApiGenerator from 'oazapfts/generate';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport type { GenerationOptions } from '../types';\nimport { getOperationDefinitions } from '../utils';\n\n/**\n * OpenAPI 解析器服務 - 負責解析 OpenAPI 文檔並提取相關數據\n */\nexport class OpenApiParserService {\n private apiGen: ApiGenerator;\n\n constructor(\n private v3Doc: OpenAPIV3.Document,\n options: Partial<GenerationOptions>\n ) {\n this.apiGen = new ApiGenerator(v3Doc, {\n unionUndefined: options.unionUndefined,\n mergeReadWriteOnly: options.mergeReadWriteOnly,\n });\n }\n\n /**\n * 初始化 - 預處理組件\n */\n initialize(): void {\n if (this.apiGen.spec.components?.schemas) {\n // 原因:oazapfts 會優先使用 schema.title 作為類型名稱,但應該使用 schema key\n // 這只在記憶體中修改,不影響原始 OpenAPI 文件\n Object.keys(this.apiGen.spec.components.schemas).forEach(schemaName => {\n const schema = this.apiGen.spec.components!.schemas![schemaName];\n if (schema && typeof schema === 'object' && 'title' in schema) {\n delete schema.title;\n }\n });\n\n this.apiGen.preprocessComponents(this.apiGen.spec.components.schemas);\n\n // 手動為每個 schema 生成 type alias\n Object.keys(this.apiGen.spec.components.schemas).forEach(schemaName => {\n try {\n this.apiGen.getRefAlias({ $ref: `#/components/schemas/${schemaName}` });\n } catch (error) {\n // 忽略無法生成的 schema\n }\n });\n }\n }\n\n /**\n * 獲取操作定義列表\n * @param filterEndpoints - 端點過濾函數\n */\n getOperationDefinitions(filterEndpoints?: any) {\n const { operationMatches } = require('../utils/http');\n return getOperationDefinitions(this.v3Doc).filter(operationMatches(filterEndpoints));\n }\n\n /**\n * 獲取 API 生成器實例\n */\n getApiGenerator(): ApiGenerator {\n return this.apiGen;\n }\n\n /**\n * 獲取 OpenAPI 文檔\n */\n getDocument(): OpenAPIV3.Document {\n return this.v3Doc;\n }\n\n /**\n * 獲取所有 schema 類型名稱\n */\n getSchemaTypeNames(): Set<string> {\n const schemeTypeNames = new Set<string>();\n // 這裡可以根據需要添加 schema 類型名稱的提取邏輯\n return schemeTypeNames;\n }\n}","/**\n * 產生 CommonTypeFile\n */\nexport function generateCommonTypesFile() {\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n \nexport interface RequestOptions {\n headers?: Record<string, string>;\n observe?: 'body' | 'events' | 'response';\n responseType?: 'arraybuffer' | 'blob' | 'json' | 'text';\n reportProgress?: boolean;\n withCredentials?: boolean;\n}\n\nexport interface IRequestConfig {\n timeout?: number;\n}\n\nexport type IRestFulEndpointsQueryReturn<TVariables> = TVariables extends void ? \n void | {fetchOptions?: IRequestConfig;}: \n {\n variables: TVariables;\n fetchOptions?: IRequestConfig;\n };\n`;\n\n}\n\n","import ts from 'typescript';\n\n/**\n * 轉換類型名稱為大駝峰命名\n */\nfunction toPascalCase(name: string): string {\n return name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n/**\n * 重新命名 TypeScript 節點中的標識符\n */\nfunction renameIdentifier(node: ts.Node, oldName: string, newName: string): ts.Node {\n return ts.transform(node, [\n context => rootNode => ts.visitNode(rootNode, function visit(node): ts.Node {\n if (ts.isIdentifier(node) && node.text === oldName) {\n return ts.factory.createIdentifier(newName);\n }\n return ts.visitEachChild(node, visit, context);\n })\n ]).transformed[0];\n}\n\n/**\n * 產生 component-schema.ts 內容\n * @param interfaces\n */\nexport function generateComponentSchemaFile(interfaces: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>) {\n const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n\n const resultFile = ts.createSourceFile(\n 'component-schema.ts',\n '',\n ts.ScriptTarget.Latest,\n false,\n ts.ScriptKind.TS\n );\n\n // 處理類型名稱轉換為大駝峰,並建立映射表\n const renamedInterfaces: Array<string> = [];\n const typeNameMapping: Record<string, string> = {};\n\n Object.entries(interfaces).forEach(([originalName, node]) => {\n const pascalCaseName = toPascalCase(originalName);\n typeNameMapping[originalName] = pascalCaseName;\n\n // 重新命名節點\n const renamedNode = renameIdentifier(node, originalName, pascalCaseName);\n const printed = printer.printNode(ts.EmitHint.Unspecified, renamedNode, resultFile);\n renamedInterfaces.push(printed);\n });\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${renamedInterfaces.join('\\n')}\n`;\n}","/**\n * 產生 DO_NOT_MODIFY.md 說明檔案\n * \n * 此檔案用於提醒開發者不要修改產生器生成的程式碼\n */\nexport function generateDoNotModifyFile(): string {\n return `# 請勿修改此資料夾\n\n⚠️ **重要提醒:請勿修改此資料夾中的任何檔案**\n\n此資料夾中的所有檔案都是透過程式碼產生器自動產生的。任何手動修改的內容在下次重新產生時都將會被覆蓋。\n\n## 如何修改這些檔案?\n\n如果您需要修改這些檔案的內容,請:\n\n1. 修改相對應的設定檔案或模板\n2. 重新執行程式碼產生器\n3. 讓產生器自動更新這些檔案\n\n## 產生器相關資訊\n\n這些檔案是由 @acrool/rtk-query-codegen-openapi 產生器所建立。\n\n如有疑問,請參考專案文件或聯繫開發團隊。\n`;\n}","import type { OpenAPIV3 } from 'openapi-types';\nimport ts from 'typescript';\nimport { OpenApiParserService } from './openapi-parser-service';\nimport { EndpointInfoExtractor } from './endpoint-info-extractor';\nimport { generateTypesFile } from '../generators/types-generator';\nimport { generateRtkQueryFile } from '../generators/rtk-query-generator';\nimport { generateRtkEnhanceEndpointsFile } from '../generators/rtk-enhance-endpoints-generator';\nimport type { GenerationOptions, GenerateApiResult } from '../types';\n\n/**\n * API 程式碼生成器 - 負責生成單一群組的 RTK Query 相關程式碼\n *\n * 設計理念:\n * - 類別化管理:使用 class 封裝邏輯\n * - RTK Query 專用:只生成 React/RTK Query 代碼\n * - 重用資源:接受外部已處理的 v3Doc,避免重複處理\n */\nexport class ApiCodeGenerator {\n private infoExtractor: EndpointInfoExtractor;\n\n constructor(\n private parserService: OpenApiParserService,\n private options: GenerationOptions\n ) {\n // 初始化端點資訊提取器\n this.infoExtractor = new EndpointInfoExtractor(options);\n }\n\n /**\n * 生成完整的 RTK Query 程式碼\n */\n async generate(): Promise<GenerateApiResult> {\n // 步驟 1: 獲取操作定義\n const operationDefinitions = this.parserService.getOperationDefinitions(this.options.filterEndpoints);\n\n // 步驟 2: 提取端點資訊\n const endpointInfos = this.infoExtractor.extractEndpointInfos(operationDefinitions);\n\n // 步驟 3: 生成 RTK Query 代碼\n return this.generateRtkQueryCode(endpointInfos);\n }\n\n /**\n * 生成 RTK Query 代碼\n */\n private generateRtkQueryCode(endpointInfos: Array<any>): GenerateApiResult {\n // 步驟 1: 生成 types 檔案 (React 模式也需要)\n const typesContent = this.generateTypes(endpointInfos);\n\n // 步驟 2: 生成 RTK Query 檔案\n const rtkQueryContent = generateRtkQueryFile(endpointInfos, this.options);\n\n // 步驟 3: 生成 enhance endpoints 檔案\n const enhanceEndpointsContent = generateRtkEnhanceEndpointsFile(endpointInfos, this.options);\n\n // 步驟 4: 生成 index 檔案\n const indexContent = this.generateIndex();\n\n\n // 步驟 6: 收集操作名稱\n const operationNames = endpointInfos.map(info => info.operationName);\n\n // 步驟 7: 收集所有 tags\n const allTags = new Set<string>();\n endpointInfos.forEach(info => {\n if (info.tags && Array.isArray(info.tags)) {\n info.tags.forEach((tag: string) => allTags.add(tag));\n }\n });\n\n return {\n operationNames,\n tags: Array.from(allTags),\n files: {\n types: typesContent,\n queryService: rtkQueryContent, // RTK Query 檔案\n index: indexContent,\n enhanceEndpoints: enhanceEndpointsContent // 新增的 enhance endpoints 檔案\n }\n };\n }\n\n\n /**\n * 生成 Types 檔案內容\n */\n private generateTypes(endpointInfos: Array<any>): string {\n const generatorOptions = {\n ...this.options,\n apiConfiguration: this.options.apiConfiguration || { \n file: '@/store/webapi', \n importName: 'WebApiConfiguration' \n }\n };\n\n // 從 parser service 獲取 schema interfaces\n const apiGen = this.parserService.getApiGenerator();\n const schemaInterfaces = apiGen.aliases.reduce<Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>>((curr, alias) => {\n if (ts.isInterfaceDeclaration(alias) || ts.isTypeAliasDeclaration(alias)) {\n const name = alias.name.text;\n return {\n ...curr,\n [name]: alias,\n };\n }\n return curr;\n }, {});\n\n // 獲取操作定義以供類型生成使用\n const operationDefinitions = this.parserService.getOperationDefinitions(this.options.filterEndpoints);\n\n return generateTypesFile(endpointInfos, generatorOptions, schemaInterfaces, operationDefinitions);\n }\n\n\n /**\n * 生成 Index 檔案內容\n */\n private generateIndex(): string {\n const groupKey = this.options.groupKey || '';\n const exportName = groupKey ?\n `${groupKey.charAt(0).toLowerCase() + groupKey.slice(1)}Api` :\n 'api';\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport { default as ${exportName} } from \"./enhanceEndpoints\";\nexport * from \"./query.generated\";\nexport * from \"./types\";\n`;\n }\n\n // /**\n // * 獲取已解析的 parser service(供外部使用)\n // */\n // getParserService(): OpenApiParserService {\n // return this.parserService;\n // }\n //\n // /**\n // * 獲取端點資訊提取器(供外部使用)\n // */\n // getInfoExtractor(): EndpointInfoExtractor {\n // return this.infoExtractor;\n // }\n}","import { capitalize, isQuery as testIsQuery } from '../utils';\nimport { getOperationName, getOverrides } from '../utils/http';\nimport type { OperationDefinition, GenerationOptions } from '../types';\nimport { supportDeepObjects } from 'oazapfts/generate';\n\n/**\n * 端點資訊介面\n */\nexport interface EndpointInfo {\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n contentType: string;\n hasRequestBody: boolean;\n tags: string[];\n}\n\n/**\n * 端點資訊提取器 - 專門負責從操作定義中提取端點資訊\n */\nexport class EndpointInfoExtractor {\n constructor(\n private options: Pick<GenerationOptions, 'operationNameSuffix' | 'argSuffix' | 'responseSuffix' | 'queryMatch' | 'endpointOverrides'>\n ) {}\n\n /**\n * 從操作定義列表提取端點資訊\n * @param operationDefinitions - 操作定義列表\n */\n extractEndpointInfos(operationDefinitions: OperationDefinition[]): EndpointInfo[] {\n return operationDefinitions.map((operationDefinition) => {\n return this.extractSingleEndpointInfo(operationDefinition);\n });\n }\n\n /**\n * 從單一操作定義提取端點資訊\n * @param operationDefinition - 操作定義\n */\n private extractSingleEndpointInfo(operationDefinition: OperationDefinition): EndpointInfo {\n const { verb, path, operation } = operationDefinition;\n const { operationNameSuffix = '', argSuffix = 'Req', responseSuffix = 'Res', queryMatch, endpointOverrides } = this.options;\n\n // 獲取操作名稱\n const operationName = getOperationName({ verb, path });\n const finalOperationName = operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName;\n\n // 生成類型名稱\n const argTypeName = capitalize(operationName + operationNameSuffix + argSuffix);\n const responseTypeName = capitalize(operationName + operationNameSuffix + responseSuffix);\n\n // 判斷是否為查詢類型\n const isQuery = testIsQuery(verb, path, getOverrides(operationDefinition, endpointOverrides), queryMatch);\n\n // 生成查詢鍵名稱\n const queryKeyName = `${operationName.replace(/([A-Z])/g, '_$1').toUpperCase()}`;\n\n // 提取 OpenAPI summary\n const summary = operation.summary || `${verb.toUpperCase()} ${path}`;\n\n // 解析參數\n const { queryParams, pathParams, isVoidArg, hasRequestBody } = this.extractParameters(operationDefinition);\n\n // 提取 content type\n const contentType = this.extractContentType(operation);\n\n // 提取 tags\n const tags = Array.isArray(operation.tags) ? operation.tags : [];\n\n return {\n operationName: finalOperationName,\n argTypeName,\n responseTypeName,\n isQuery,\n verb: verb.toUpperCase(),\n path,\n queryKeyName,\n queryParams,\n pathParams,\n isVoidArg,\n summary,\n contentType,\n hasRequestBody,\n tags\n };\n }\n\n /**\n * 提取操作的參數資訊\n * @param operationDefinition - 操作定義\n */\n private extractParameters(operationDefinition: OperationDefinition) {\n const { operation, pathItem } = operationDefinition;\n\n // 解析參數\n const operationParameters = this.resolveArray(operation.parameters);\n const pathItemParameters = this.resolveArray(pathItem.parameters)\n .filter((pp) => !operationParameters.some((op) => op.name === pp.name && op.in === pp.in));\n\n const allParameters = supportDeepObjects([...pathItemParameters, ...operationParameters])\n .filter((param) => param.in !== 'header');\n\n const queryParams = allParameters.filter(param => param.in === 'query');\n const pathParams = allParameters.filter(param => param.in === 'path');\n\n // 檢查是否有 request body\n const hasRequestBody = !!operation.requestBody;\n\n // 檢查是否為 void 類型參數\n const isVoidArg = queryParams.length === 0 && pathParams.length === 0 && !operation.requestBody;\n\n return {\n queryParams,\n pathParams,\n isVoidArg,\n hasRequestBody\n };\n }\n\n /**\n * 解析參數陣列 (模擬 apiGen.resolveArray)\n */\n private resolveArray(parameters: any): any[] {\n if (!parameters) return [];\n return Array.isArray(parameters) ? parameters : [parameters];\n }\n\n /**\n * 提取操作的 content type\n * @param operation - 操作對象\n */\n private extractContentType(operation: any): string {\n // 檢查 requestBody 是否存在\n if (!operation.requestBody) {\n return 'application/json';\n }\n\n // 從 requestBody.content 中獲取第一個 content type\n const content = operation.requestBody.content;\n if (!content || typeof content !== 'object') {\n return 'application/json';\n }\n\n const contentTypes = Object.keys(content);\n if (contentTypes.length === 0) {\n return 'application/json';\n }\n\n // 返回第一個 content type\n return contentTypes[0];\n }\n}","import ts from 'typescript';\nimport type { GenerationOptions } from '../types';\n\n/**\n * 轉換類型名稱為大駝峰命名\n */\nconst toPascalCase = (name: string): string => {\n return name.charAt(0).toUpperCase() + name.slice(1);\n};\n\nexport interface EndpointInfo {\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n}\n\nexport function generateTypesFile(\n endpointInfos: EndpointInfo[],\n _options: GenerationOptions,\n schemaInterfaces?: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>,\n operationDefinitions?: any[]\n) {\n\n // 創建 schema 類型名稱映射表 - 使用實際生成的類型名稱\n const schemaTypeMap: Record<string, string> = {};\n\n if (schemaInterfaces) {\n Object.keys(schemaInterfaces).forEach(actualTypeName => {\n // 直接使用實際生成的類型名稱,不進行轉換\n // 這確保了 types.ts 中的引用與 schema.ts 中的定義完全一致\n schemaTypeMap[actualTypeName] = actualTypeName;\n\n // 為了兼容 OpenAPI 中可能存在的不同命名方式,添加常見的映射\n // 例如:TokenResponseVO -> TokenResponseVo\n if (actualTypeName.endsWith('Vo')) {\n const openApiName = actualTypeName.slice(0, -2) + 'VO';\n schemaTypeMap[openApiName] = actualTypeName;\n }\n if (actualTypeName.endsWith('Dto')) {\n const openApiName = actualTypeName.slice(0, -3) + 'DTO';\n schemaTypeMap[openApiName] = actualTypeName;\n }\n });\n }\n\n // 生成 import 語句\n let importStatement = `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually \n \n`;\n\n // 檢查是否需要引入 schema.ts\n const hasSchemaTypes = schemaInterfaces && Object.keys(schemaInterfaces).length > 0;\n if (hasSchemaTypes) {\n importStatement += `import * as Schema from \"../schema\";\\n`;\n }\n\n importStatement += '\\n';\n\n // 收集所有需要的類型定義\n const typeDefinitions: string[] = [];\n\n // 注意:不再在 types.ts 中重複生成 schema 類型\n // schema 類型已經在 schema.ts 中生成,這裡直接使用 Schema.* 引用\n\n // 無論是否有 schema,都要生成 endpoint 特定的 Req/Res 類型\n const endpointTypes: string[] = [];\n\n // 為每個端點生成 Req/Res 類型\n endpointInfos.forEach(endpoint => {\n // 使用 endpoint 中提供的準確類型名稱\n const reqTypeName = endpoint.argTypeName;\n const resTypeName = endpoint.responseTypeName;\n\n // 生成 Request 類型(總是生成)\n if (reqTypeName) {\n const requestTypeContent = generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap);\n if (requestTypeContent.trim() === '') {\n // 如果沒有實際內容,使用 void\n endpointTypes.push(\n `export type ${reqTypeName} = void;`,\n ``\n );\n } else {\n // 有實際內容,使用 type 定義\n endpointTypes.push(\n `export type ${reqTypeName} = {`,\n requestTypeContent,\n `};`,\n ``\n );\n }\n }\n\n // 生成 Response 類型(總是生成)\n if (resTypeName) {\n const responseTypeResult = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap);\n if (responseTypeResult.content.trim() === '') {\n // 如果沒有實際內容,使用 void\n endpointTypes.push(\n `export type ${resTypeName} = void;`,\n ``\n );\n } else if (responseTypeResult.isDirectType) {\n // 直接類型引用(如 $ref、array、primitive),使用 type alias\n endpointTypes.push(\n `export type ${resTypeName} = ${responseTypeResult.content};`,\n ``\n );\n } else {\n // 有 object 屬性內容,使用 type 定義\n endpointTypes.push(\n `export type ${resTypeName} = {`,\n responseTypeResult.content,\n `};`,\n ``\n );\n }\n }\n });\n\n if (endpointTypes.length > 0) {\n typeDefinitions.push(endpointTypes.join('\\n'));\n }\n\n // 如果沒有任何類型定義,至少添加一些基本說明\n if (typeDefinitions.length === 0) {\n typeDefinitions.push(\n `// 此檔案用於定義 API 相關的類型`,\n `// 類型定義會根據 OpenAPI Schema 自動生成`,\n ``\n );\n }\n\n return importStatement + typeDefinitions.join('\\n\\n');\n}\n\n/**\n * 生成 Request 類型的內容\n */\nfunction generateRequestTypeContent(endpoint: EndpointInfo, operationDefinitions?: any[], schemaTypeMap: Record<string, string> = {}): string {\n const properties: string[] = [];\n\n // 如果有 query 參數\n if (endpoint.queryParams && endpoint.queryParams.length > 0) {\n endpoint.queryParams.forEach(param => {\n const optional = param.required ? '' : '?';\n const paramType = getTypeFromParameter(param, schemaTypeMap);\n properties.push(` ${param.name}${optional}: ${paramType};`);\n });\n }\n\n // 如果有 path 參數\n if (endpoint.pathParams && endpoint.pathParams.length > 0) {\n endpoint.pathParams.forEach(param => {\n const optional = param.required ? '' : '?';\n const paramType = getTypeFromParameter(param, schemaTypeMap);\n properties.push(` ${param.name}${optional}: ${paramType};`);\n });\n }\n\n // 如果有 request body(從 operationDefinitions 中獲取)\n const operationDef = operationDefinitions?.find(op => {\n // 嘗試多種匹配方式\n return op.operation?.operationId === endpoint.operationName ||\n op.operation?.operationId === endpoint.operationName.toLowerCase() ||\n // 也嘗試匹配 verb + path 組合\n (op.verb === endpoint.verb.toLowerCase() && op.path === endpoint.path);\n });\n\n if (operationDef?.operation?.requestBody) {\n const requestBody = operationDef.operation.requestBody;\n const content = requestBody.content;\n\n // 處理不同的 content types,優先使用 application/json,其次嘗試其他類型\n const jsonContent = content['application/json'] || content['*/*'];\n const formContent = content['multipart/form-data'] || content['application/x-www-form-urlencoded'];\n\n if (jsonContent?.schema) {\n // indentLevel=1 因為 body 屬性已經在類型定義內(有 2 個空格縮排)\n const bodyType = getTypeFromSchema(jsonContent.schema, schemaTypeMap, 1);\n properties.push(` body: ${bodyType};`);\n } else if (formContent?.schema) {\n // indentLevel=1 因為 body 屬性已經在類型定義內(有 2 個空格縮排)\n const bodyType = getTypeFromSchema(formContent.schema, schemaTypeMap, 1);\n properties.push(` body: ${bodyType};`);\n } else {\n // fallback 到第一個可用的 content-type\n const firstContent = Object.values(content)[0] as any;\n if (firstContent?.schema) {\n const bodyType = getTypeFromSchema(firstContent.schema, schemaTypeMap, 1);\n properties.push(` body: ${bodyType};`);\n } else {\n properties.push(` body?: any; // Request body from OpenAPI`);\n }\n }\n }\n\n // 如果沒有任何參數,返回空內容(將由調用方處理為 void)\n if (properties.length === 0) {\n return ''; // 返回空字串,讓調用方決定使用 void\n }\n\n return properties.join('\\n');\n}\n\ninterface ResponseTypeResult {\n content: string;\n /** true when content is a direct type (e.g. Schema.Pet, string[]) rather than object properties */\n isDirectType: boolean;\n}\n\n/**\n * 生成 Response 類型的內容\n */\nfunction generateResponseTypeContent(endpoint: EndpointInfo, operationDefinitions?: any[], schemaTypeMap: Record<string, string> = {}): ResponseTypeResult {\n // 嘗試從 operationDefinitions 中獲取響應結構\n const operationDef = operationDefinitions?.find(op => {\n // 嘗試多種匹配方式\n return op.operation?.operationId === endpoint.operationName ||\n op.operation?.operationId === endpoint.operationName.toLowerCase() ||\n // 也嘗試匹配 verb + path 組合\n (op.verb === endpoint.verb.toLowerCase() && op.path === endpoint.path);\n });\n\n if (operationDef?.operation?.responses) {\n // 檢查 200 響應\n const successResponse = operationDef.operation.responses['200'] ||\n operationDef.operation.responses['201'];\n\n if (successResponse?.content) {\n // 優先使用 application/json,其次嘗試其他 content-type(包括 */*)\n const jsonContent = successResponse.content['application/json'] ||\n successResponse.content['*/*'] ||\n Object.values(successResponse.content)[0]; // fallback 到第一個可用的 content-type\n\n if (jsonContent?.schema) {\n const schema = jsonContent.schema;\n\n // 如果 schema 是 $ref 引用、array、或 primitive,直接使用 getTypeFromSchema\n if (schema.$ref || schema.type !== 'object' || !schema.properties) {\n const directType = getTypeFromSchema(schema, schemaTypeMap, 0);\n if (directType && directType !== 'any') {\n return { content: directType, isDirectType: true };\n }\n }\n\n // 如果是有 properties 的 object,展開為屬性列表\n const responseProps = parseSchemaProperties(schema, schemaTypeMap);\n if (responseProps.length > 0) {\n return { content: responseProps.join('\\n'), isDirectType: false };\n }\n }\n }\n }\n\n // 如果沒有響應定義,返回空內容(將由調用方處理為 void)\n return { content: '', isDirectType: false };\n}\n\n/**\n * 解析 OpenAPI schema 的 properties 並生成 TypeScript 屬性定義\n */\nfunction parseSchemaProperties(schema: any, schemaTypeMap: Record<string, string> = {}): string[] {\n const properties: string[] = [];\n\n if (schema.type === 'object' && schema.properties) {\n const required = schema.required || [];\n\n Object.entries(schema.properties).forEach(([propName, propSchema]: [string, any]) => {\n const isRequired = required.includes(propName);\n const optional = isRequired ? '' : '?';\n // indentLevel=1 因為屬性已經在類型定義內(有 2 個空格縮排)\n const propType = getTypeFromSchema(propSchema, schemaTypeMap, 1);\n\n // 如果屬性名包含特殊字符(如 -),需要加上引號\n const needsQuotes = /[^a-zA-Z0-9_$]/.test(propName);\n const quotedPropName = needsQuotes ? `\"${propName}\"` : propName;\n\n // 生成 JSDoc 註解\n if (propSchema.description) {\n properties.push(` /** ${propSchema.description} */`);\n }\n properties.push(` ${quotedPropName}${optional}: ${propType};`);\n });\n }\n\n return properties;\n}\n\n/**\n * 從 OpenAPI schema 獲取 TypeScript 類型\n * @param schema OpenAPI schema 定義\n * @param schemaTypeMap 類型名稱映射表\n * @param indentLevel 縮排層級,用於格式化內嵌物件\n */\nfunction getTypeFromSchema(schema: any, schemaTypeMap: Record<string, string> = {}, indentLevel: number = 0): string {\n if (!schema) return 'any';\n\n // 處理 $ref 引用,使用 Schema.TypeName 格式\n if (schema.$ref) {\n const refPath = schema.$ref;\n if (refPath.startsWith('#/components/schemas/')) {\n const originalTypeName = refPath.replace('#/components/schemas/', '');\n // 使用映射表查找實際的類型名稱,並轉換為大駝峰\n const actualTypeName = schemaTypeMap[originalTypeName] || originalTypeName;\n const pascalCaseTypeName = toPascalCase(actualTypeName);\n const baseType = `Schema.${pascalCaseTypeName}`;\n // 處理 nullable\n return schema.nullable ? `${baseType} | null` : baseType;\n }\n }\n\n let baseType: string;\n\n switch (schema.type) {\n case 'string':\n if (schema.enum) {\n baseType = schema.enum.map((val: string) => `\"${val}\"`).join(' | ');\n } else if (schema.format === 'binary') {\n // 處理檔案上傳:format: \"binary\" 應該對應 Blob 類型\n baseType = 'Blob';\n } else {\n baseType = 'string';\n }\n break;\n case 'number':\n case 'integer':\n baseType = 'number';\n break;\n case 'boolean':\n baseType = 'boolean';\n break;\n case 'array':\n const itemType = schema.items ? getTypeFromSchema(schema.items, schemaTypeMap, indentLevel) : 'any';\n // 如果 itemType 包含聯合類型(包含 |),需要加括號\n const needsParentheses = itemType.includes('|');\n baseType = needsParentheses ? `(${itemType})[]` : `${itemType}[]`;\n break;\n case 'object':\n if (schema.properties) {\n // 如果有具體的屬性定義,生成內聯對象類型(多行格式)\n const entries = Object.entries(schema.properties);\n\n // 如果沒有屬性但有 additionalProperties,生成 Record 類型\n if (entries.length === 0) {\n if (schema.additionalProperties) {\n const valueType = schema.additionalProperties === true\n ? 'any'\n : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel);\n baseType = `Record<string, ${valueType}>`;\n } else {\n baseType = '{}';\n }\n } else {\n // 計算下一層的縮排\n const nextIndent = ' '.repeat(indentLevel + 1);\n const currentIndent = ' '.repeat(indentLevel);\n\n const props: string[] = [];\n entries.forEach(([key, propSchema]: [string, any]) => {\n const required = schema.required || [];\n const optional = required.includes(key) ? '' : '?';\n const type = getTypeFromSchema(propSchema, schemaTypeMap, indentLevel + 1);\n\n // 如果屬性名包含特殊字符(如 -),需要加上引號\n const needsQuotes = /[^a-zA-Z0-9_$]/.test(key);\n const quotedKey = needsQuotes ? `\"${key}\"` : key;\n\n // 生成 JSDoc 註解\n if (propSchema.description) {\n props.push(`${nextIndent}/** ${propSchema.description} */`);\n }\n props.push(`${nextIndent}${quotedKey}${optional}: ${type};`);\n });\n\n baseType = `{\\n${props.join('\\n')}\\n${currentIndent}}`;\n }\n } else if (schema.additionalProperties) {\n // 如果沒有 properties 但有 additionalProperties\n const valueType = schema.additionalProperties === true\n ? 'any'\n : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel);\n baseType = `Record<string, ${valueType}>`;\n } else {\n baseType = 'any';\n }\n break;\n default:\n baseType = 'any';\n break;\n }\n\n // 處理 nullable\n return schema.nullable ? `${baseType} | null` : baseType;\n}\n\n/**\n * 從參數定義中獲取 TypeScript 類型\n */\nfunction getTypeFromParameter(param: any, schemaTypeMap: Record<string, string> = {}): string {\n if (!param.schema) return 'any';\n return getTypeFromSchema(param.schema, schemaTypeMap);\n}\n","import type { GenerationOptions } from '../types';\n\nexport function generateRtkQueryFile(endpointInfos: Array<{\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n contentType: string;\n hasRequestBody: boolean;\n tags: string[];\n}>, options: GenerationOptions) {\n\n const { groupKey } = options;\n\n // 獲取類型名稱\n const httpClientTypeName = options.httpClient?.importReturnTypeName || 'IRestFulEndpointsQueryReturn';\n\n // 生成端點定義\n const endpoints = endpointInfos.map(info => {\n const methodType = info.isQuery ? 'query' : 'mutation';\n const argType = info.isVoidArg ? 'void' : `${httpClientTypeName}<${info.argTypeName}>`;\n\n // 處理 path parameters - 替換 {id} 為 ${queryArg.variables.id}\n let urlPath = info.path;\n if (info.pathParams && info.pathParams.length > 0) {\n info.pathParams.forEach((param: any) => {\n urlPath = urlPath.replace(`{${param.name}}`, `\\${queryArg.variables.${param.name}}`);\n });\n // 使用模板字符串\n urlPath = '`' + urlPath + '`';\n } else {\n // 使用普通字符串\n urlPath = `\"${urlPath}\"`;\n }\n\n // 處理 query parameters\n let paramsSection = '';\n if (info.queryParams && info.queryParams.length > 0) {\n const paramsLines = info.queryParams.map((param: any) =>\n ` ${param.name}: queryArg.variables.${param.name},`\n ).join('\\n');\n paramsSection = `\n params: {\n${paramsLines}\n },`;\n }\n\n // 處理 tags\n let tagsSection = '';\n if (info.tags && info.tags.length > 0) {\n const tagsArray = info.tags.map(tag => {\n // 將 tag 轉為大駝峰(去除空格),與 ECacheTagTypes 枚舉 key 一致\n const pascalTag = tag.split(/\\s+/).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');\n return `ECacheTagTypes.${pascalTag}`;\n }).join(', ');\n if (info.isQuery) {\n tagsSection = `\n providesTags: [${tagsArray}],`;\n } else {\n tagsSection = `\n invalidatesTags: (result, error) => error ? [] : [${tagsArray}],`;\n }\n }\n\n return ` /** ${info.summary || info.operationName} */\n ${info.operationName}: build.${methodType}<\n ${info.responseTypeName},\n ${argType}\n >({${tagsSection}\n query: (queryArg) => ({\n url: ${urlPath},\n method: \"${info.verb.toUpperCase()}\",\n contentType: \"${info.contentType}\",${paramsSection}${info.hasRequestBody ? `\n body: queryArg.variables.body,` : ''}${info.isVoidArg ? '' : `\n fetchOptions: queryArg?.fetchOptions,`}\n }),\n }),`;\n }).join('\\n');\n\n // 生成類型導入\n const typeImports = [\n ...new Set([\n ...endpointInfos.map(info => info.argTypeName),\n ...endpointInfos.map(info => info.responseTypeName)\n ])\n ].filter(type => type !== 'VoidApiArg');\n\n const typeImportStatement = typeImports.length > 0\n ? `import type { ${typeImports.join(', ')} } from \"./types\";`\n : '';\n\n // 根據配置生成 import 語句\n const apiImport = options.apiConfiguration\n ? `import {${options.apiConfiguration.importName} as api} from \"${options.apiConfiguration.file.replace(/\\.ts$/, '')}\";\n`\n : `import {baseApi as api} from \"../../../library/redux/baseApi\";\n`;\n\n const httpClientImport = options.httpClient\n ? `import {${options.httpClient.importReturnTypeName}} from \"${options.httpClient.file}\";\n`\n : `import {IRestFulEndpointsQueryReturn} from \"@acrool/react-fetcher\";\n`;\n\n // 檢查是否有任何 endpoint 使用了 tags\n const hasTags = endpointInfos.some(info => info.tags && info.tags.length > 0);\n const tagTypesImport = hasTags\n ? `import {ECacheTagTypes} from \"../tagTypes\";\n`\n : '';\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${apiImport}${httpClientImport}${tagTypesImport}\n${typeImportStatement}\n\n\nconst injectedRtkApi = api.injectEndpoints({\n endpoints: (build) => ({\n${endpoints}\n }),\n});\n\nexport const {\n${endpointInfos.map(info => {\n const capitalizedOperationName = info.operationName.charAt(0).toUpperCase() + info.operationName.slice(1);\n if (info.isQuery) {\n // For queries, generate both regular and lazy hooks if useLazyQueries is enabled\n const regularHook = `use${capitalizedOperationName}Query`;\n if (options.useLazyQueries) {\n const lazyHook = `useLazy${capitalizedOperationName}Query`;\n return ` ${regularHook},\\n ${lazyHook},`;\n } else {\n return ` ${regularHook},`;\n }\n } else {\n // For mutations, only generate regular hook\n const mutationHook = `use${capitalizedOperationName}Mutation`;\n return ` ${mutationHook},`;\n }\n }).join('\\n')}\n} = injectedRtkApi;\n\nexport default injectedRtkApi;\n`;\n}\n","import type { GenerationOptions } from '../types';\n\nexport function generateRtkEnhanceEndpointsFile(endpointInfos: Array<{\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n}>, options: GenerationOptions) {\n\n // 生成端點配置\n const endpointConfigs = endpointInfos.map(info => {\n // 為 query 類型的端點添加 providesTags,為 mutation 類型的添加 invalidatesTags\n if (info.isQuery) {\n // Query 端點提供 tags\n return ` ${info.operationName}: {\n providesTags: (result, error, arg) => [],\n },`;\n } else {\n // Mutation 端點使 tags 失效\n return ` ${info.operationName}: {\n invalidatesTags: (result, error, arg) => [],\n },`;\n }\n }).join('\\n');\n\n // 生成 import 語句\n const importStatements = `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nimport api from \"./query.generated\";\n`;\n\n return `${importStatements}\nconst enhancedApi = api.enhanceEndpoints({\n endpoints: {\n${endpointConfigs}\n },\n});\n\nexport default enhancedApi;\n`;\n}\n","import ts from 'typescript';\n\n\n/**\n * 產生 Utils function 內容\n * @param interfaces\n */\nexport function generateUtilsFile() {\n\n // 分析接口內容以找出需要從 shared-types 導入的類型\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually \n \n/**\n* Clear undefined in object\n*/\nexport function withoutUndefined(obj?: Record<string, any>) {\n if(typeof obj === 'undefined') return;\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined && v !== null)\n );\n}\n\n`\n}\n\n/**\n * 大寫底線字串 轉 小駝峰\n * @param str\n */\nexport function toCamelCase(str: string): string {\n return str.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}","/**\n * 將 tag 名稱轉換為大駝峰命名(去除空格)\n * 例如: \"Home Banner\" -> \"HomeBanner\", \"payout methods\" -> \"PayoutMethods\"\n */\nfunction toPascalCase(tag: string): string {\n return tag\n .split(/\\s+/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n}\n\n/**\n * 生成 RTK Query 的 cache tag types 枚举文件\n * @param tags - 去重后的 tags 数组\n * @returns 生成的 TypeScript 枚举代码\n */\nexport function generateTagTypesFile(tags: string[]): string {\n // 如果没有 tags,生成一个空的枚举\n if (tags.length === 0) {\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport enum ECacheTagTypes {\n}\n`;\n }\n\n // 生成枚举项,key 使用大駝峰命名(去除空格),value 保留原始 tag 名稱\n const enumEntries = tags\n .sort() // 按字母顺序排序\n .map(tag => ` ${toPascalCase(tag)} = '${tag}',`)\n .join('\\n');\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport enum ECacheTagTypes {\n${enumEntries}\n}\n`;\n}\n"],"mappings":"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","names":["path","path","ts","path","path","path","paths","fs","path","path","fs","path","fs","operationMatches","node","ts","path","isQuery","toPascalCase","baseType","ts","toPascalCase","ts","path"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/utils/http.ts","../src/index.ts","../src/services/unified-code-generator.ts","../src/services/openapi-service.ts","../src/utils/capitalize.ts","../src/utils/downloadSchema.ts","../src/utils/isValidUrl.ts","../src/utils/getOperationDefinitions.ts","../src/types.ts","../src/utils/getV3Doc.ts","../src/utils/isQuery.ts","../src/services/group-service.ts","../src/services/file-writer-service.ts","../src/utils/directory.ts","../src/services/openapi-parser-service.ts","../src/generators/common-types-generator.ts","../src/generators/component-schema-generator.ts","../src/generators/do-not-modify-generator.ts","../src/services/api-code-generator.ts","../src/services/endpoint-info-extractor.ts","../src/generators/types-generator.ts","../src/generators/rtk-query-generator.ts","../src/generators/rtk-enhance-endpoints-generator.ts","../src/generators/utils-generator.ts","../src/generators/tag-types-generator.ts","../src/utils/schema-ref-analyzer.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import type {\n EndpointMatcher, EndpointOverrides,\n OperationDefinition,\n ParameterDefinition,\n ParameterMatcher,\n TextMatcher,\n} from '../types';\nimport {\n getOperationName as _getOperationName,\n} from 'oazapfts/generate';\n\n\n/**\n * 判斷 HTTP 狀態碼是否為成功的數據響應\n */\nexport function defaultIsDataResponse(code: string, includeDefault: boolean) {\n if (includeDefault && code === 'default') {\n return true;\n }\n const parsedCode = Number(code);\n return !Number.isNaN(parsedCode) && parsedCode >= 200 && parsedCode < 300;\n}\n\n/**\n * 根據 HTTP 方法和路徑生成操作名稱\n */\nexport function getOperationName({ verb, path }: Pick<OperationDefinition, 'verb' | 'path'>) {\n return _getOperationName(verb, path, undefined);\n}\n\n\n\n\n/**\n * 從路徑項目中提取標籤(tags)\n */\nexport function getTags({ verb, pathItem }: Pick<OperationDefinition, 'verb' | 'pathItem'>): string[] {\n return verb ? pathItem[verb]?.tags || [] : [];\n}\n\n/**\n * 創建文本匹配器函數,用於過濾操作名稱\n */\nfunction patternMatches(pattern?: TextMatcher) {\n const filters = Array.isArray(pattern) ? pattern : [pattern];\n return function matcher(operationName: string) {\n if (!pattern) return true;\n return filters.some((filter) =>\n typeof filter === 'string' ? filter === operationName : filter?.test(operationName)\n );\n };\n}\n\n/**\n * 創建操作匹配器函數,用於過濾操作定義\n */\nexport function operationMatches(pattern?: EndpointMatcher) {\n const checkMatch = typeof pattern === 'function' ? pattern : patternMatches(pattern);\n return function matcher(operationDefinition: OperationDefinition) {\n if (!pattern) return true;\n const operationName = getOperationName(operationDefinition);\n return checkMatch(operationName, operationDefinition);\n };\n}\n\n/**\n * 創建參數匹配器函數,用於過濾參數定義\n */\nexport function argumentMatches(pattern?: ParameterMatcher) {\n const checkMatch = typeof pattern === 'function' ? pattern : patternMatches(pattern);\n return function matcher(argumentDefinition: ParameterDefinition) {\n if (!pattern || argumentDefinition.in === 'path') return true;\n const argumentName = argumentDefinition.name;\n return checkMatch(argumentName, argumentDefinition);\n };\n}\n\n/**\n * 獲取操作的覆蓋配置\n */\nexport function getOverrides(\n operation: OperationDefinition,\n endpointOverrides?: EndpointOverrides[]\n): EndpointOverrides | undefined {\n return endpointOverrides?.find((override) => operationMatches(override.pattern)(operation));\n}","import { UnifiedCodeGenerator, type UnifiedGenerationOptions, type UnifiedGenerationResult } from './services/unified-code-generator';\n\nexport type { OutputFilesConfig, ConfigFile } from './types';\n\n\n/**\n * 產生 Endpoints - 直接使用統一代碼生成器\n * @param options - 端點生成選項\n */\nexport async function generateEndpoints(options: UnifiedGenerationOptions): Promise<string | void> {\n const generator = new UnifiedCodeGenerator(options);\n\n const result = await generator.generateAll();\n \n if (!result.success) {\n if (result.errors.length > 0) {\n throw result.errors[0];\n }\n }\n return;\n}\n","import path from 'node:path';\nimport ts from 'typescript';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport { OpenApiService } from './openapi-service';\nimport { GroupService, type GroupConfig } from './group-service';\nimport { FileWriterService, type FileWriteResult } from './file-writer-service';\nimport { OpenApiParserService } from './openapi-parser-service';\nimport { generateCommonTypesFile } from '../generators/common-types-generator';\nimport { generateComponentSchemaFile } from '../generators/component-schema-generator';\nimport { generateDoNotModifyFile } from '../generators/do-not-modify-generator';\nimport type { GenerationOptions, CommonOptions, OperationDefinition } from '../types';\nimport { ApiCodeGenerator } from './api-code-generator';\nimport { EndpointInfoExtractor } from './endpoint-info-extractor';\nimport { generateUtilsFile } from '../generators/utils-generator';\nimport { generateTagTypesFile } from '../generators/tag-types-generator';\nimport { analyzeSchemaRefs } from '../utils/schema-ref-analyzer';\nimport { generateTypesFile } from '../generators/types-generator';\n\n/**\n * 統一代碼生成器選項\n */\nexport interface UnifiedGenerationOptions extends CommonOptions {\n outputFiles: GroupConfig;\n remoteFile?: string;\n}\n\n/**\n * 統一代碼生成器結果\n */\nexport interface UnifiedGenerationResult {\n success: boolean;\n writtenFiles: FileWriteResult[];\n errors: Error[];\n generatedGroups: string[];\n}\n\n/**\n * 統一代碼生成器\n * \n * 設計理念:\n * - 統一管理所有生成流程\n * - 內建 schema 處理和存儲\n * - 提供準備、生成、發佈的分階段操作\n * - 避免重複初始化和處理\n * \n * 使用方式:\n * 1. prepare() - 準備階段:解析 schema、初始化服務\n * 2. generateContent() - 生成階段:產生所有內容但不寫檔\n * 3. release() - 發佈階段:統一寫入所有檔案\n */\nexport class UnifiedCodeGenerator {\n private _options: UnifiedGenerationOptions;\n\n private openApiService = new OpenApiService();\n private groupService = new GroupService();\n private fileWriterService = new FileWriterService();\n \n // 內部狀態存儲\n private openApiDoc: OpenAPIV3.Document | null = null;\n private parserService: OpenApiParserService | null = null;\n private schemaInterfaces: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration> = {};\n private actualSchemaFile: string = '';\n \n // 生成內容存儲\n private generatedContent: {\n groups: Array<{\n groupKey: string;\n outputPath: string;\n content: any;\n }>;\n commonTypes: string;\n componentSchema: string;\n doNotModify: string;\n utils: string;\n tagTypes: string;\n } = {\n groups: [],\n commonTypes: '',\n componentSchema: '',\n doNotModify: '',\n utils: '',\n tagTypes: ''\n };\n\n // 收集所有 tags\n private allTags: Set<string> = new Set();\n\n // 收集每個 group 的 operation definitions(用於 schema 引用分析)\n private groupOperationDefs: Map<string, OperationDefinition[]> = new Map();\n // 收集每個 group 的生成選項(用於重新生成 types)\n private groupGenerationOptions: Map<string, GenerationOptions> = new Map();\n\n\n constructor(options: UnifiedGenerationOptions) {\n this._options = options;\n }\n\n\n\n /**\n * 一次性生成(整合所有階段)\n */\n async generateAll(): Promise<UnifiedGenerationResult> {\n await this.prepare();\n\n // 生成各API文件(第一階段:生成所有 group 的內容)\n await this.generateApi();\n\n // 分析 schema 引用並拆分(第二階段:將 group-local schema 移到各 group 的 types.ts)\n this.splitSchemaByUsage();\n\n // 生成共用\n this.generateCommonTypesContent();\n this.generateSchemaContent();\n this.generateUtilsContent();\n this.generateDoNotModifyContent();\n this.generateTagTypesContent();\n\n return await this.release();\n }\n\n\n\n /**\n * 準備階段:解析 schema 並初始化所有服務\n */\n async prepare(): Promise<void> {\n // console.log('UnifiedCodeGenerator: 準備階段開始...');\n \n // 步驟 1: 解析實際的 schema 檔案路徑\n this.actualSchemaFile = this._options.schemaFile;\n if (this._options.remoteFile) {\n this.actualSchemaFile = await this.openApiService.downloadSchema(\n this._options.remoteFile,\n this._options.schemaFile\n );\n }\n\n // 步驟 2: 獲取 OpenAPI 文檔(只初始化一次)\n this.openApiDoc = await this.openApiService.getDocument(\n this.actualSchemaFile,\n this._options.httpResolverOptions\n );\n\n // 步驟 3: 初始化解析器服務並處理 schema\n this.parserService = new OpenApiParserService(this.openApiDoc, this._options);\n this.parserService.initialize();\n\n // 步驟 4: 提取並儲存 schema interfaces\n const apiGen = this.parserService.getApiGenerator();\n this.schemaInterfaces = apiGen.aliases.reduce<Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>>((curr, alias) => {\n if (ts.isInterfaceDeclaration(alias) || ts.isTypeAliasDeclaration(alias)) {\n const name = alias.name.text;\n return {\n ...curr,\n [name]: alias,\n };\n }\n return curr;\n }, {});\n\n // console.log('UnifiedCodeGenerator: 準備階段完成');\n }\n\n\n\n /**\n * 生成階段:產生所有內容但不寫檔\n */\n async generateApi(): Promise<void> {\n if (!this.openApiDoc || !this.parserService) {\n throw new Error('請先調用 prepare() 方法');\n }\n\n // console.log('UnifiedCodeGenerator: 內容生成階段開始...');\n\n // 獲取所有 API 接口Path並分組\n const paths = this.openApiService.getPaths(this.openApiDoc);\n const groupInfos = this.groupService.groupPaths(paths, this._options.outputFiles);\n\n // 為每個群組生成內容\n for (const groupInfo of Object.values(groupInfos)) {\n try {\n const groupContent = await this.generateApiGroupContent(\n this._options,\n groupInfo\n );\n\n // 檢查群組是否有任何有效的 endpoint\n if (groupContent.operationNames.length > 0) {\n this.generatedContent.groups.push({\n groupKey: groupInfo.groupKey,\n outputPath: groupInfo.outputPath,\n content: groupContent\n });\n\n // 收集此群組的所有 tags\n if (groupContent.tags && Array.isArray(groupContent.tags)) {\n groupContent.tags.forEach((tag: string) => this.allTags.add(tag));\n }\n }\n // 如果沒有任何 endpoint,則跳過此群組,不創建資料夾\n } catch (error) {\n throw new Error(`群組 ${groupInfo.groupKey} 生成失敗: ${error}`);\n }\n }\n\n // console.log('UnifiedCodeGenerator: 內容生成階段完成');\n }\n\n\n\n /**\n * 分析 schema 引用,將只被單一 group 使用的 schema 移到該 group 的 types.ts\n */\n private splitSchemaByUsage(): void {\n if (!this.openApiDoc || this.groupOperationDefs.size === 0) return;\n\n // 獲取 OpenAPI 原始 schema 定義(用於遞迴分析 $ref 依賴)\n const rawSchemas = this.openApiDoc.components?.schemas ?? {};\n const allSchemaNames = Object.keys(this.schemaInterfaces);\n\n // 分析引用\n const analysis = analyzeSchemaRefs(\n this.groupOperationDefs,\n rawSchemas as Record<string, any>,\n allSchemaNames\n );\n\n // 儲存 shared schema 名稱(供 generateSchemaContent 使用)\n this.sharedSchemaNames = analysis.sharedSchemas;\n\n // 為每個 group 重新生成 types.ts(包含 local schema 定義)\n for (const group of this.generatedContent.groups) {\n const localNames = analysis.groupLocalSchemas.get(group.groupKey);\n if (!localNames || localNames.size === 0) continue;\n\n const groupOptions = this.groupGenerationOptions.get(group.groupKey);\n if (!groupOptions || !this.parserService) continue;\n\n // 收集 local schema interfaces\n const localSchemaInterfaces: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration> = {};\n for (const name of localNames) {\n if (this.schemaInterfaces[name]) {\n localSchemaInterfaces[name] = this.schemaInterfaces[name];\n }\n }\n\n // 獲取 endpoint infos(需要重新提取以重新生成 types)\n const infoExtractor = new EndpointInfoExtractor(groupOptions);\n const operationDefs = this.groupOperationDefs.get(group.groupKey) ?? [];\n const endpointInfos = infoExtractor.extractEndpointInfos(operationDefs);\n\n const generatorOptions = {\n ...groupOptions,\n apiConfiguration: groupOptions.apiConfiguration || {\n file: '@/store/webapi',\n importName: 'WebApiConfiguration'\n }\n };\n\n // 重新生成 types.ts,帶入 local schema 資訊\n const newTypesContent = generateTypesFile(\n endpointInfos,\n generatorOptions,\n this.schemaInterfaces,\n operationDefs,\n {\n localSchemaInterfaces,\n localSchemaNames: localNames,\n }\n );\n\n group.content.files.types = newTypesContent;\n }\n }\n\n // 儲存 shared schema 名稱(只有這些會寫入 schema.ts)\n private sharedSchemaNames: Set<string> | null = null;\n\n /**\n * 生成 common types\n */\n private async generateCommonTypesContent(): Promise<void> {\n this.generatedContent.commonTypes = generateCommonTypesFile();\n }\n\n /**\n * 生成Schema(只包含 shared types,排除 group-local 和未使用的 types)\n */\n private async generateSchemaContent(): Promise<void> {\n this.generatedContent.componentSchema = generateComponentSchemaFile(\n this.schemaInterfaces,\n this.sharedSchemaNames ?? undefined\n );\n }\n\n /**\n * 生成 DO_NOT_MODIFY.md\n */\n private async generateDoNotModifyContent(): Promise<void> {\n this.generatedContent.doNotModify = generateDoNotModifyFile();\n }\n\n\n /**\n * 生成 Utils Function\n */\n private async generateUtilsContent(): Promise<void> {\n this.generatedContent.utils = generateUtilsFile();\n }\n\n /**\n * 生成 Tag Types\n */\n private async generateTagTypesContent(): Promise<void> {\n const tagsArray = Array.from(this.allTags);\n this.generatedContent.tagTypes = generateTagTypesFile(tagsArray);\n }\n\n\n\n\n /**\n * 發佈階段:統一寫入所有檔案\n */\n async release(): Promise<UnifiedGenerationResult> {\n const results: FileWriteResult[] = [];\n const errors: Error[] = [];\n const generatedGroups: string[] = [];\n\n // console.log('UnifiedCodeGenerator: 發佈階段開始...');\n\n try {\n // 寫入群組檔案\n for (const group of this.generatedContent.groups) {\n try {\n if (group.content?.files) {\n const groupOutputDir = path.dirname(group.outputPath);\n // RTK Query 模式 (唯一支援模式)\n const groupResults = await this.fileWriterService.writeGroupFiles(\n groupOutputDir,\n {\n types: group.content.files.types,\n queryService: group.content.files.queryService,\n enhanceEndpoints: group.content.files.enhanceEndpoints,\n index: group.content.files.index\n }\n );\n\n results.push(...groupResults);\n generatedGroups.push(group.groupKey);\n }\n } catch (error) {\n errors.push(new Error(`寫入群組 ${group.groupKey} 失敗: ${error}`));\n }\n }\n\n // 寫入共用檔案\n const outputDir = this.generatedContent.groups[0] ? \n path.dirname(path.dirname(this.generatedContent.groups[0].outputPath)) : \n './generated';\n\n // 寫入共用檔案 (包含 DO_NOT_MODIFY.md)\n if (this.generatedContent.commonTypes || this.generatedContent.doNotModify || this.generatedContent.utils) {\n const sharedResults = await this.fileWriterService.writeSharedFiles(\n outputDir,\n {\n commonTypes: this.generatedContent.commonTypes || undefined,\n doNotModify: this.generatedContent.doNotModify || undefined,\n utils: this.generatedContent.utils || undefined\n }\n );\n results.push(...sharedResults);\n }\n\n // 寫入 tagTypes.ts\n if (this.generatedContent.tagTypes) {\n const tagTypesResult = await this.fileWriterService.writeFile(\n path.join(outputDir, 'tagTypes.ts'),\n this.generatedContent.tagTypes\n );\n results.push(tagTypesResult);\n }\n\n // 寫入 component schema\n if (this.generatedContent.componentSchema) {\n const schemaResults = await this.fileWriterService.writeSchemaFile(\n outputDir,\n this.generatedContent.componentSchema\n );\n results.push(...schemaResults);\n }\n\n // 生成主 index.ts 檔案\n const mainIndexContent = this.generateMainIndex(generatedGroups);\n const mainIndexResult = await this.fileWriterService.writeFile(\n path.join(outputDir, 'index.ts'),\n mainIndexContent\n );\n results.push(mainIndexResult);\n\n } catch (error) {\n errors.push(error as Error);\n }\n\n // console.log('UnifiedCodeGenerator: 發佈階段完成');\n\n return {\n success: errors.length === 0,\n writtenFiles: results,\n errors,\n generatedGroups\n };\n }\n\n\n /**\n * 為單一群組生成內容\n */\n private async generateApiGroupContent(\n options: UnifiedGenerationOptions,\n groupInfo: { groupKey: string; paths: string[]; outputPath: string }\n ): Promise<any> {\n const { outputFiles, ...commonConfig } = options;\n\n // 建立群組特定的生成選項\n const groupOptions: GenerationOptions = {\n ...commonConfig,\n schemaFile: this.actualSchemaFile,\n outputFile: groupInfo.outputPath,\n sharedTypesFile: `${outputFiles.outputDir}/common-types.ts`,\n filterEndpoints: this.groupService.createGroupFilter(groupInfo.groupKey, outputFiles),\n queryMatch: outputFiles.queryMatch,\n groupKey: groupInfo.groupKey,\n };\n\n // 使用新的 ApiCodeGenerator 生成程式碼,重用已處理的 v3Doc\n if (!this.openApiDoc || !this.parserService) {\n throw new Error('OpenAPI 文檔未初始化,請先調用 prepare()');\n }\n\n // 收集此 group 的 operation definitions(用於後續 schema 引用分析)\n const groupOpDefs = this.parserService.getOperationDefinitions(groupOptions.filterEndpoints);\n this.groupOperationDefs.set(groupInfo.groupKey, groupOpDefs);\n this.groupGenerationOptions.set(groupInfo.groupKey, groupOptions);\n\n const apiGenerator = new ApiCodeGenerator(this.parserService, groupOptions);\n const result = await apiGenerator.generate();\n\n return result;\n }\n\n /**\n * 生成主 index.ts 檔案\n */\n private generateMainIndex(generatedGroups: string[]): string {\n const groupExports = generatedGroups.map(groupKey => `export * from \"./${groupKey}\";`).join('\\n');\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport * from \"./schema\";\n${groupExports}\n`;\n }\n\n}","import type { OpenAPIV3 } from 'openapi-types';\nimport { getV3Doc, downloadSchemaFile } from '../utils';\n\n/**\n * OpenAPI 服務 - 負責獲取和處理 OpenAPI 文檔\n * \n * 單一職責:\n * - 從本地文件或遠程URL獲取OpenAPI文檔\n * - 管理文檔快取\n * - 提供文檔基本操作方法\n * \n * 設計原則:\n * - 非收集模式:每次調用都是獨立的操作\n * - 無副作用:不修改傳入的參數\n * - 可測試性:所有方法都有明確的輸入輸出\n */\nexport class OpenApiService {\n private docCache: Record<string, OpenAPIV3.Document> = {};\n\n /**\n * 獲取 OpenAPI 文檔\n * @param schemaLocation - Schema 位置 (URL 或本地路徑)\n * @param httpResolverOptions - HTTP 解析選項\n */\n async getDocument(\n schemaLocation: string, \n httpResolverOptions?: any\n ): Promise<OpenAPIV3.Document> {\n if (this.docCache[schemaLocation]) {\n return this.docCache[schemaLocation];\n }\n\n const doc = await getV3Doc(schemaLocation, httpResolverOptions);\n this.docCache[schemaLocation] = doc;\n return doc;\n }\n\n /**\n * 下載遠程 Schema 文件\n * @param remoteUrl - 遠程 URL\n * @param localPath - 本地儲存路徑\n */\n async downloadSchema(remoteUrl: string, localPath: string): Promise<string> {\n return downloadSchemaFile(remoteUrl, localPath);\n }\n\n /**\n * 獲取所有 API 路徑\n * @param doc - OpenAPI 文檔\n */\n getPaths(doc: OpenAPIV3.Document): string[] {\n return Object.keys(doc.paths || {});\n }\n\n /**\n * 清除快取\n */\n clearCache(): void {\n this.docCache = {};\n }\n}","export function capitalize(str: string) {\n return str.replace(str[0], str[0].toUpperCase());\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { isValidUrl } from './isValidUrl';\n\nexport async function downloadSchemaFile(remoteFile: string, targetPath: string): Promise<string> {\n // 如果不是網址,拋出錯誤\n if (!isValidUrl(remoteFile)) {\n throw new Error(`remoteFile must be a valid URL: ${remoteFile}`);\n }\n\n try {\n // 確保目錄存在\n const dir = path.dirname(targetPath);\n if (!fs.existsSync(dir)) {\n await fs.promises.mkdir(dir, { recursive: true });\n }\n\n // 下載檔案\n const response = await fetch(remoteFile);\n if (!response.ok) {\n throw new Error(`Failed to download schema from ${remoteFile}: ${response.statusText}`);\n }\n\n const content = await response.text();\n await fs.promises.writeFile(targetPath, content, 'utf-8');\n\n console.log(`Schema downloaded from ${remoteFile} to ${targetPath}`);\n return targetPath;\n } catch (error) {\n console.error(`Error downloading schema from ${remoteFile}:`, error);\n throw error;\n }\n} ","export function isValidUrl(string: string) {\n try {\n new URL(string);\n } catch (_) {\n return false;\n }\n\n return true;\n}\n","import type { OpenAPIV3 } from 'openapi-types';\nimport type { OperationDefinition } from '../types';\nimport { operationKeys } from '../types';\n\nexport function getOperationDefinitions(v3Doc: OpenAPIV3.Document): OperationDefinition[] {\n return Object.entries(v3Doc.paths).flatMap(([path, pathItem]) =>\n !pathItem\n ? []\n : Object.entries(pathItem)\n .filter((arg): arg is [(typeof operationKeys)[number], OpenAPIV3.OperationObject] =>\n operationKeys.includes(arg[0] as any)\n )\n .map(([verb, operation]) => ({\n path,\n verb,\n pathItem,\n operation,\n }))\n );\n}\n","import type SwaggerParser from '@apidevtools/swagger-parser';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport ts from 'typescript';\n\n// 重新匯出服務相關類型\nexport type {\n GroupConfig,\n GroupInfo\n} from './services/group-service';\n\nexport type {\n FileWriteResult\n} from './services/file-writer-service';\n\n\nexport type {\n UnifiedGenerationOptions as EndpointGenerationOptions,\n UnifiedGenerationResult as EndpointGenerationResult\n} from './services/unified-code-generator';\n\nexport type OperationDefinition = {\n path: string;\n verb: (typeof operationKeys)[number];\n pathItem: OpenAPIV3.PathItemObject;\n operation: OpenAPIV3.OperationObject;\n};\n\nexport type ParameterDefinition = OpenAPIV3.ParameterObject;\n\ntype Require<T, K extends keyof T> = { [k in K]-?: NonNullable<T[k]> } & Omit<T, K>;\ntype Optional<T, K extends keyof T> = { [k in K]?: NonNullable<T[k]> } & Omit<T, K>;\ntype Id<T> = { [K in keyof T]: T[K] } & {};\ntype AtLeastOneKey<T> = {\n [K in keyof T]-?: Pick<T, K> & Partial<T>;\n}[keyof T];\n\nexport const operationKeys = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'] as const;\n\nexport type GenerationOptions = Id<\n CommonOptions &\n Optional<OutputFileOptions, 'outputFile'> & {\n isDataResponse?(\n code: string,\n includeDefault: boolean,\n response: OpenAPIV3.ResponseObject,\n allResponses: OpenAPIV3.ResponsesObject\n ): boolean;\n}\n>;\n\nexport interface CommonOptions {\n /**\n * local schema file path (only supports local files)\n */\n schemaFile: string;\n /**\n * remote schema file URL (when provided, will download to schemaFile path)\n */\n remoteFile?: string;\n /**\n * Configuration for WebApiConfiguration import\n * defaults to { file: \"@core/api/web-api-configuration\", importName: \"WebApiConfiguration\" }\n */\n apiConfiguration?: {\n file: string;\n importName: string;\n };\n /**\n * HTTP client configuration for API calls\n * defaults to { file: \"@core/httpClient/webapi/webapi-http-client.providers\", importName: \"WEBAPI_HTTP_CLIENT\" }\n */\n httpClient?: {\n file: string;\n importReturnTypeName: string; // 用於指定別名導入,例如 IRestFulEndpointsQueryReturn\n };\n /**\n * defaults to \"enhancedApi\"\n */\n exportName?: string;\n /**\n * defaults to \"Req\"\n */\n argSuffix?: string;\n /**\n * defaults to \"Res\"\n */\n responseSuffix?: string;\n /**\n * defaults to empty\n */\n operationNameSuffix?: string;\n /**\n * defaults to `false`\n * `true` will generate lazy query hooks (useLazy prefix) for query endpoints\n */\n useLazyQueries?: boolean;\n /**\n * defaults to false\n * `true` will generate a union type for `undefined` properties like: `{ id?: string | undefined }` instead of `{ id?: string }`\n */\n unionUndefined?: boolean;\n /**\n * defaults to false\n * `true` will result in all generated endpoints having `providesTags`/`invalidatesTags` declarations for the `tags` of their respective operation definition\n * @see https://redux-toolkit.js.org/rtk-query/usage/code-generation for more information\n */\n tag?: boolean;\n /**\n * defaults to false\n * `true` will add `encodeURIComponent` to the generated path parameters\n */\n encodePathParams?: boolean;\n /**\n * defaults to false\n * `true` will add `encodeURIComponent` to the generated query parameters\n */\n encodeQueryParams?: boolean;\n /**\n * defaults to false\n * `true` will \"flatten\" the arg so that you can do things like `useGetEntityById(1)` instead of `useGetEntityById({ entityId: 1 })`\n */\n flattenArg?: boolean;\n /**\n * default to false\n * If set to `true`, the default response type will be included in the generated code for all endpoints.\n * @see https://swagger.io/docs/specification/describing-responses/#default\n */\n includeDefault?: boolean;\n /**\n * default to false\n * `true` will not generate separate types for read-only and write-only properties.\n */\n mergeReadWriteOnly?: boolean;\n /**\n *\n * HTTPResolverOptions object that is passed to the SwaggerParser bundle function.\n */\n httpResolverOptions?: SwaggerParser.HTTPResolverOptions;\n\n /**\n * defaults to undefined\n * If present the given file will be used as prettier config when formatting the generated code. If undefined the default prettier config\n * resolution mechanism will be used.\n */\n prettierConfigFile?: string;\n /**\n * defaults to \"@acrool/react-fetcher\"\n * File path for importing IRestFulEndpointsQueryReturn type\n */\n endpointsQueryReturnTypeFile?: string;\n}\n\nexport type TextMatcher = string | RegExp | (string | RegExp)[];\n\nexport type EndpointMatcherFunction = (operationName: string, operationDefinition: OperationDefinition) => boolean;\n\nexport type EndpointMatcher = TextMatcher | EndpointMatcherFunction;\n\nexport type ParameterMatcherFunction = (parameterName: string, parameterDefinition: ParameterDefinition) => boolean;\n\nexport type ParameterMatcher = TextMatcher | ParameterMatcherFunction;\n\nexport interface OutputFileOptions extends Partial<CommonOptions> {\n outputFile: string;\n filterEndpoints?: EndpointMatcher;\n endpointOverrides?: EndpointOverrides[];\n queryMatch?: (method: string, path: string) => boolean;\n sharedTypesFile?: string;\n /**\n * groupKey for service class naming, e.g., \"room\" -> \"RoomService\"\n */\n groupKey?: string;\n}\n\nexport type EndpointOverrides = {\n pattern: EndpointMatcher;\n} & AtLeastOneKey<{\n type: 'mutation' | 'query';\n parameterFilter: ParameterMatcher;\n}>;\n\nexport type OutputFilesConfig = {\n groupKeyMatch: (path: string) => string;\n outputDir: string;\n queryMatch?: (method: string, path: string) => boolean;\n filterEndpoint?: (operationName: string, path: string, groupKey: string) => boolean;\n};\n\nexport type ConfigFile =\n | Id<Require<CommonOptions & OutputFileOptions, 'outputFile'>>\n | Id<\n Omit<CommonOptions, 'outputFile'> & {\n // outputFiles: { [outputFile: string]: Omit<OutputFileOptions, 'outputFile'> };\n outputFiles: OutputFilesConfig\n}\n>;\n\nexport type GenerateApiResult = {\n operationNames: string[];\n tags: string[]; // 收集到的所有 tags\n files: {\n types: string;\n queryService: string; // RTK Query generated file\n index: string;\n enhanceEndpoints?: string; // RTK Query enhance endpoints file\n commonTypes?: string;\n componentSchema?: string;\n };\n};\n\n\n\nexport type QueryArgDefinition = {\n name: string;\n originalName: string;\n type: ts.TypeNode;\n required?: boolean;\n param?: OpenAPIV3.ParameterObject;\n} & (\n | {\n origin: 'param';\n param: OpenAPIV3.ParameterObject;\n}\n | {\n origin: 'body';\n body: OpenAPIV3.RequestBodyObject;\n}\n );\n\nexport type QueryArgDefinitions = Record<string, QueryArgDefinition>;\n","import SwaggerParser from '@apidevtools/swagger-parser';\nimport type { OpenAPIV3 } from 'openapi-types';\n// @ts-ignore\nimport converter from 'swagger2openapi';\n\nexport async function getV3Doc(\n spec: string,\n httpResolverOptions?: SwaggerParser.HTTPResolverOptions\n): Promise<OpenAPIV3.Document> {\n const doc = await SwaggerParser.bundle(spec, {\n resolve: {\n http: httpResolverOptions,\n },\n });\n\n const isOpenApiV3 = 'openapi' in doc && doc.openapi.startsWith('3');\n\n if (isOpenApiV3) {\n return doc as OpenAPIV3.Document;\n } else {\n const result = await converter.convertObj(doc, {});\n return result.openapi as OpenAPIV3.Document;\n }\n}\n","import type { EndpointOverrides, operationKeys } from '../types';\n\nexport function isQuery(\n verb: (typeof operationKeys)[number],\n path: string,\n overrides: EndpointOverrides | undefined,\n queryMatch?: (method: string, path: string) => boolean\n) {\n if (queryMatch) {\n return queryMatch(verb, path);\n }\n if (overrides?.type) {\n return overrides.type === 'query';\n }\n return verb === 'get';\n}\n","import camelCase from 'lodash.camelcase';\n\n/**\n * 群組配置介面\n */\nexport interface GroupConfig {\n outputDir: string;\n groupKeyMatch: (path: string) => string | null;\n filterEndpoint?: (operationName: string, path: string, groupKey: string) => boolean;\n queryMatch?: (operationName: string) => boolean;\n}\n\n/**\n * 群組信息介面\n */\nexport interface GroupInfo {\n groupKey: string;\n paths: string[];\n outputPath: string;\n}\n\n/**\n * 群組服務 - 負責處理 API 路徑分組\n */\nexport class GroupService {\n /**\n * 根據配置對路徑進行分組\n * @param paths - API 路徑陣列\n * @param config - 群組配置\n */\n groupPaths(paths: string[], config: GroupConfig): Record<string, GroupInfo> {\n const { groupKeyMatch, outputDir } = config;\n \n const groupedPaths = paths.reduce((acc, path) => {\n const rawGroupKey = groupKeyMatch(path);\n const groupKey = rawGroupKey ? camelCase(rawGroupKey) : '_common';\n \n if (!acc[groupKey]) {\n acc[groupKey] = [];\n }\n acc[groupKey].push(path);\n return acc;\n }, {} as Record<string, string[]>);\n\n // 轉換為 GroupInfo 格式\n const result: Record<string, GroupInfo> = {};\n for (const [groupKey, paths] of Object.entries(groupedPaths)) {\n result[groupKey] = {\n groupKey,\n paths,\n outputPath: `${outputDir}/${groupKey}/query.service.ts`\n };\n }\n\n return result;\n }\n\n /**\n * 為特定群組建立篩選函數\n * @param groupKey - 群組鍵\n * @param config - 群組配置\n */\n createGroupFilter(\n groupKey: string,\n config: GroupConfig\n ): (operationName: string, operationDefinition: any) => boolean {\n return (operationName: string, operationDefinition: any) => {\n const path = operationDefinition.path;\n\n // 檢查路徑是否匹配當前分組\n const pathGroupKey = camelCase(config.groupKeyMatch(path) || '');\n if (pathGroupKey !== groupKey && (pathGroupKey || '_common') !== groupKey) {\n return false;\n }\n\n // 使用 filterEndpoint 進行額外篩選\n if (config.filterEndpoint) {\n return config.filterEndpoint(operationName, path, groupKey);\n }\n\n return true;\n };\n }\n}","import fs from 'node:fs';\nimport path from 'node:path';\nimport { ensureDirectoryExists } from '../utils/directory';\n\n/**\n * 檔案寫入結果\n */\nexport interface FileWriteResult {\n path: string;\n success: boolean;\n error?: Error;\n}\n\n/**\n * 檔案寫入服務 - 負責將產生的內容寫入檔案\n */\nexport class FileWriterService {\n /**\n * 寫入單一檔案\n * @param filePath - 檔案路徑\n * @param content - 檔案內容\n */\n async writeFile(filePath: string, content: string): Promise<FileWriteResult> {\n try {\n const resolvedPath = path.resolve(process.cwd(), filePath);\n const fileName = path.basename(resolvedPath);\n\n // enhanceEndpoints.ts 如果已存在則跳過寫入\n if (fileName === 'enhanceEndpoints.ts' && fs.existsSync(resolvedPath)) {\n return {\n path: resolvedPath,\n success: true\n };\n }\n\n await ensureDirectoryExists(resolvedPath);\n\n fs.writeFileSync(resolvedPath, content);\n\n return {\n path: resolvedPath,\n success: true\n };\n } catch (error) {\n return {\n path: filePath,\n success: false,\n error: error as Error\n };\n }\n }\n\n /**\n * 批次寫入多個檔案\n * @param files - 檔案路徑與內容的對應表\n */\n async writeFiles(files: Record<string, string>): Promise<FileWriteResult[]> {\n const results: FileWriteResult[] = [];\n\n for (const [filePath, content] of Object.entries(files)) {\n const result = await this.writeFile(filePath, content);\n results.push(result);\n }\n\n return results;\n }\n\n\n /**\n * 為群組寫入 RTK Query 檔案結構\n * @param groupOutputDir - 群組輸出目錄\n * @param files - 檔案內容\n */\n async writeGroupFiles(\n groupOutputDir: string,\n files: {\n types?: string; // types.ts\n queryService?: string; // query.generated.ts\n enhanceEndpoints?: string; // enhanceEndpoints.ts\n index?: string; // index.ts\n }\n ): Promise<FileWriteResult[]> {\n const filesToWrite: Record<string, string> = {};\n\n if (files.types) {\n filesToWrite[path.join(groupOutputDir, 'types.ts')] = files.types;\n }\n\n if (files.queryService) {\n filesToWrite[path.join(groupOutputDir, 'query.generated.ts')] = files.queryService;\n }\n\n if (files.enhanceEndpoints) {\n filesToWrite[path.join(groupOutputDir, 'enhanceEndpoints.ts')] = files.enhanceEndpoints;\n }\n\n if (files.index) {\n filesToWrite[path.join(groupOutputDir, 'index.ts')] = files.index;\n }\n\n return this.writeFiles(filesToWrite);\n }\n\n /**\n * 寫入共享檔案\n * @param outputDir - 輸出目錄\n * @param sharedFiles - 共享檔案內容\n */\n async writeSharedFiles(\n outputDir: string,\n sharedFiles: {\n commonTypes?: string;\n doNotModify?: string;\n utils?: string;\n }\n ): Promise<FileWriteResult[]> {\n const filesToWrite: Record<string, string> = {};\n\n if (sharedFiles.commonTypes) {\n filesToWrite[path.join(outputDir, 'common-types.ts')] = sharedFiles.commonTypes;\n }\n \n\n if (sharedFiles.doNotModify) {\n filesToWrite[path.join(outputDir, 'DO_NOT_MODIFY.md')] = sharedFiles.doNotModify;\n }\n\n if (sharedFiles.utils) {\n filesToWrite[path.join(outputDir, 'utils.ts')] = sharedFiles.utils;\n }\n\n return this.writeFiles(filesToWrite);\n }\n\n /**\n * 寫入共享檔案\n * @param outputDir - 輸出目錄\n * @param schema\n */\n async writeSchemaFile(\n outputDir: string,\n schema: string\n ): Promise<FileWriteResult[]> {\n const filesToWrite: Record<string, string> = {};\n\n filesToWrite[path.join(outputDir, 'schema.ts')] = schema;\n\n return this.writeFiles(filesToWrite);\n }\n\n\n}","import path from 'node:path';\nimport fs from 'node:fs';\n\n/**\n * 確保目錄存在的函數\n * @param filePath\n */\nexport async function ensureDirectoryExists(filePath: string) {\n const dirname = path.dirname(filePath);\n if (!fs.existsSync(dirname)) {\n await fs.promises.mkdir(dirname, { recursive: true });\n }\n}\n\n/**\n * 檢查檔案是否存在的函數\n * @param filePath\n */\nexport function fileExists(filePath: string): boolean {\n try {\n return fs.statSync(filePath).isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * 獲取資料夾名稱並轉換為 API 名稱\n * @param dirPath\n */\nexport function getApiNameFromDir(dirPath: string): string {\n const dirName = path.basename(dirPath);\n return `${dirName}Api`;\n}\n\n\n\n\n/**\n * 確保基礎文件存在的函數\n * @param outputDir\n * @param operationNames\n */\nexport async function ensureBaseFilesExist(outputDir: string, operationNames: string[]) {\n const enhanceEndpointsPath = path.join(outputDir, 'enhanceEndpoints.ts');\n const indexPath = path.join(outputDir, 'index.ts');\n\n // 如果 enhanceEndpoints.ts 不存在,創建它\n if (!fileExists(enhanceEndpointsPath)) {\n // 生成操作名稱的字符串\n const operationNamesString = operationNames\n .map(name => ` ${name}: {},`)\n .join('\\n');\n\n const enhanceEndpointsContent = `import api from './query.service';\n\nconst enhancedApi = api.enhanceEndpoints({\n endpoints: {\n${operationNamesString}\n },\n});\n\nexport default enhancedApi;\n`;\n await fs.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, 'utf-8');\n }\n // 如果文件已存在,不做任何修改\n\n // 如果 index.ts 不存在,創建它\n if (!fileExists(indexPath)) {\n const indexContent = `export * from './query.service';\n`;\n await fs.promises.writeFile(indexPath, indexContent, 'utf-8');\n }\n}","import ApiGenerator from 'oazapfts/generate';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport type { GenerationOptions } from '../types';\nimport { getOperationDefinitions } from '../utils';\n\n/**\n * OpenAPI 解析器服務 - 負責解析 OpenAPI 文檔並提取相關數據\n */\nexport class OpenApiParserService {\n private apiGen: ApiGenerator;\n\n constructor(\n private v3Doc: OpenAPIV3.Document,\n options: Partial<GenerationOptions>\n ) {\n this.apiGen = new ApiGenerator(v3Doc, {\n unionUndefined: options.unionUndefined,\n mergeReadWriteOnly: options.mergeReadWriteOnly,\n });\n }\n\n /**\n * 初始化 - 預處理組件\n */\n initialize(): void {\n if (this.apiGen.spec.components?.schemas) {\n // 原因:oazapfts 會優先使用 schema.title 作為類型名稱,但應該使用 schema key\n // 這只在記憶體中修改,不影響原始 OpenAPI 文件\n Object.keys(this.apiGen.spec.components.schemas).forEach(schemaName => {\n const schema = this.apiGen.spec.components!.schemas![schemaName];\n if (schema && typeof schema === 'object' && 'title' in schema) {\n delete schema.title;\n }\n });\n\n this.apiGen.preprocessComponents(this.apiGen.spec.components.schemas);\n\n // 手動為每個 schema 生成 type alias\n Object.keys(this.apiGen.spec.components.schemas).forEach(schemaName => {\n try {\n this.apiGen.getRefAlias({ $ref: `#/components/schemas/${schemaName}` });\n } catch (error) {\n // 忽略無法生成的 schema\n }\n });\n }\n }\n\n /**\n * 獲取操作定義列表\n * @param filterEndpoints - 端點過濾函數\n */\n getOperationDefinitions(filterEndpoints?: any) {\n const { operationMatches } = require('../utils/http');\n return getOperationDefinitions(this.v3Doc).filter(operationMatches(filterEndpoints));\n }\n\n /**\n * 獲取 API 生成器實例\n */\n getApiGenerator(): ApiGenerator {\n return this.apiGen;\n }\n\n /**\n * 獲取 OpenAPI 文檔\n */\n getDocument(): OpenAPIV3.Document {\n return this.v3Doc;\n }\n\n /**\n * 獲取所有 schema 類型名稱\n */\n getSchemaTypeNames(): Set<string> {\n const schemeTypeNames = new Set<string>();\n // 這裡可以根據需要添加 schema 類型名稱的提取邏輯\n return schemeTypeNames;\n }\n}","/**\n * 產生 CommonTypeFile\n */\nexport function generateCommonTypesFile() {\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n \nexport interface RequestOptions {\n headers?: Record<string, string>;\n observe?: 'body' | 'events' | 'response';\n responseType?: 'arraybuffer' | 'blob' | 'json' | 'text';\n reportProgress?: boolean;\n withCredentials?: boolean;\n}\n\nexport interface IRequestConfig {\n timeout?: number;\n}\n\nexport type IRestFulEndpointsQueryReturn<TVariables> = TVariables extends void ? \n void | {fetchOptions?: IRequestConfig;}: \n {\n variables: TVariables;\n fetchOptions?: IRequestConfig;\n };\n`;\n\n}\n\n","import ts from 'typescript';\n\n/**\n * 轉換類型名稱為大駝峰命名\n */\nfunction toPascalCase(name: string): string {\n return name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n/**\n * 重新命名 TypeScript 節點中的標識符\n */\nfunction renameIdentifier(node: ts.Node, oldName: string, newName: string): ts.Node {\n return ts.transform(node, [\n context => rootNode => ts.visitNode(rootNode, function visit(node): ts.Node {\n if (ts.isIdentifier(node) && node.text === oldName) {\n return ts.factory.createIdentifier(newName);\n }\n return ts.visitEachChild(node, visit, context);\n })\n ]).transformed[0];\n}\n\n/**\n * 產生 component-schema.ts 內容\n * @param interfaces\n * @param includeOnly - 若提供,則只輸出此 Set 中的類型名稱\n */\nexport function generateComponentSchemaFile(\n interfaces: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>,\n includeOnly?: Set<string>\n) {\n const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n\n const resultFile = ts.createSourceFile(\n 'component-schema.ts',\n '',\n ts.ScriptTarget.Latest,\n false,\n ts.ScriptKind.TS\n );\n\n // 處理類型名稱轉換為大駝峰,並建立映射表\n const renamedInterfaces: Array<string> = [];\n const typeNameMapping: Record<string, string> = {};\n\n Object.entries(interfaces).forEach(([originalName, node]) => {\n const pascalCaseName = toPascalCase(originalName);\n typeNameMapping[originalName] = pascalCaseName;\n\n // 如果有過濾條件,跳過不在名單中的類型\n if (includeOnly && !includeOnly.has(originalName)) {\n return;\n }\n\n // 重新命名節點\n const renamedNode = renameIdentifier(node, originalName, pascalCaseName);\n const printed = printer.printNode(ts.EmitHint.Unspecified, renamedNode, resultFile);\n renamedInterfaces.push(printed);\n });\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${renamedInterfaces.join('\\n')}\n`;\n}","/**\n * 產生 DO_NOT_MODIFY.md 說明檔案\n * \n * 此檔案用於提醒開發者不要修改產生器生成的程式碼\n */\nexport function generateDoNotModifyFile(): string {\n return `# 請勿修改此資料夾\n\n⚠️ **重要提醒:請勿修改此資料夾中的任何檔案**\n\n此資料夾中的所有檔案都是透過程式碼產生器自動產生的。任何手動修改的內容在下次重新產生時都將會被覆蓋。\n\n## 如何修改這些檔案?\n\n如果您需要修改這些檔案的內容,請:\n\n1. 修改相對應的設定檔案或模板\n2. 重新執行程式碼產生器\n3. 讓產生器自動更新這些檔案\n\n## 產生器相關資訊\n\n這些檔案是由 @acrool/rtk-query-codegen-openapi 產生器所建立。\n\n如有疑問,請參考專案文件或聯繫開發團隊。\n`;\n}","import type { OpenAPIV3 } from 'openapi-types';\nimport ts from 'typescript';\nimport { OpenApiParserService } from './openapi-parser-service';\nimport { EndpointInfoExtractor } from './endpoint-info-extractor';\nimport { generateTypesFile } from '../generators/types-generator';\nimport { generateRtkQueryFile } from '../generators/rtk-query-generator';\nimport { generateRtkEnhanceEndpointsFile } from '../generators/rtk-enhance-endpoints-generator';\nimport type { GenerationOptions, GenerateApiResult } from '../types';\n\n/**\n * API 程式碼生成器 - 負責生成單一群組的 RTK Query 相關程式碼\n *\n * 設計理念:\n * - 類別化管理:使用 class 封裝邏輯\n * - RTK Query 專用:只生成 React/RTK Query 代碼\n * - 重用資源:接受外部已處理的 v3Doc,避免重複處理\n */\nexport class ApiCodeGenerator {\n private infoExtractor: EndpointInfoExtractor;\n\n constructor(\n private parserService: OpenApiParserService,\n private options: GenerationOptions\n ) {\n // 初始化端點資訊提取器\n this.infoExtractor = new EndpointInfoExtractor(options);\n }\n\n /**\n * 生成完整的 RTK Query 程式碼\n */\n async generate(): Promise<GenerateApiResult> {\n // 步驟 1: 獲取操作定義\n const operationDefinitions = this.parserService.getOperationDefinitions(this.options.filterEndpoints);\n\n // 步驟 2: 提取端點資訊\n const endpointInfos = this.infoExtractor.extractEndpointInfos(operationDefinitions);\n\n // 步驟 3: 生成 RTK Query 代碼\n return this.generateRtkQueryCode(endpointInfos);\n }\n\n /**\n * 生成 RTK Query 代碼\n */\n private generateRtkQueryCode(endpointInfos: Array<any>): GenerateApiResult {\n // 步驟 1: 生成 types 檔案 (React 模式也需要)\n const typesContent = this.generateTypes(endpointInfos);\n\n // 步驟 2: 生成 RTK Query 檔案\n const rtkQueryContent = generateRtkQueryFile(endpointInfos, this.options);\n\n // 步驟 3: 生成 enhance endpoints 檔案\n const enhanceEndpointsContent = generateRtkEnhanceEndpointsFile(endpointInfos, this.options);\n\n // 步驟 4: 生成 index 檔案\n const indexContent = this.generateIndex();\n\n\n // 步驟 6: 收集操作名稱\n const operationNames = endpointInfos.map(info => info.operationName);\n\n // 步驟 7: 收集所有 tags\n const allTags = new Set<string>();\n endpointInfos.forEach(info => {\n if (info.tags && Array.isArray(info.tags)) {\n info.tags.forEach((tag: string) => allTags.add(tag));\n }\n });\n\n return {\n operationNames,\n tags: Array.from(allTags),\n files: {\n types: typesContent,\n queryService: rtkQueryContent, // RTK Query 檔案\n index: indexContent,\n enhanceEndpoints: enhanceEndpointsContent // 新增的 enhance endpoints 檔案\n }\n };\n }\n\n\n /**\n * 生成 Types 檔案內容\n */\n private generateTypes(endpointInfos: Array<any>): string {\n const generatorOptions = {\n ...this.options,\n apiConfiguration: this.options.apiConfiguration || { \n file: '@/store/webapi', \n importName: 'WebApiConfiguration' \n }\n };\n\n // 從 parser service 獲取 schema interfaces\n const apiGen = this.parserService.getApiGenerator();\n const schemaInterfaces = apiGen.aliases.reduce<Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>>((curr, alias) => {\n if (ts.isInterfaceDeclaration(alias) || ts.isTypeAliasDeclaration(alias)) {\n const name = alias.name.text;\n return {\n ...curr,\n [name]: alias,\n };\n }\n return curr;\n }, {});\n\n // 獲取操作定義以供類型生成使用\n const operationDefinitions = this.parserService.getOperationDefinitions(this.options.filterEndpoints);\n\n return generateTypesFile(endpointInfos, generatorOptions, schemaInterfaces, operationDefinitions);\n }\n\n\n /**\n * 生成 Index 檔案內容\n */\n private generateIndex(): string {\n const groupKey = this.options.groupKey || '';\n const exportName = groupKey ?\n `${groupKey.charAt(0).toLowerCase() + groupKey.slice(1)}Api` :\n 'api';\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport { default as ${exportName} } from \"./enhanceEndpoints\";\nexport * from \"./query.generated\";\nexport * from \"./types\";\n`;\n }\n\n // /**\n // * 獲取已解析的 parser service(供外部使用)\n // */\n // getParserService(): OpenApiParserService {\n // return this.parserService;\n // }\n //\n // /**\n // * 獲取端點資訊提取器(供外部使用)\n // */\n // getInfoExtractor(): EndpointInfoExtractor {\n // return this.infoExtractor;\n // }\n}","import { capitalize, isQuery as testIsQuery } from '../utils';\nimport { getOperationName, getOverrides } from '../utils/http';\nimport type { OperationDefinition, GenerationOptions } from '../types';\nimport { supportDeepObjects } from 'oazapfts/generate';\n\n/**\n * 端點資訊介面\n */\nexport interface EndpointInfo {\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n contentType: string;\n hasRequestBody: boolean;\n tags: string[];\n}\n\n/**\n * 端點資訊提取器 - 專門負責從操作定義中提取端點資訊\n */\nexport class EndpointInfoExtractor {\n constructor(\n private options: Pick<GenerationOptions, 'operationNameSuffix' | 'argSuffix' | 'responseSuffix' | 'queryMatch' | 'endpointOverrides'>\n ) {}\n\n /**\n * 從操作定義列表提取端點資訊\n * @param operationDefinitions - 操作定義列表\n */\n extractEndpointInfos(operationDefinitions: OperationDefinition[]): EndpointInfo[] {\n return operationDefinitions.map((operationDefinition) => {\n return this.extractSingleEndpointInfo(operationDefinition);\n });\n }\n\n /**\n * 從單一操作定義提取端點資訊\n * @param operationDefinition - 操作定義\n */\n private extractSingleEndpointInfo(operationDefinition: OperationDefinition): EndpointInfo {\n const { verb, path, operation } = operationDefinition;\n const { operationNameSuffix = '', argSuffix = 'Req', responseSuffix = 'Res', queryMatch, endpointOverrides } = this.options;\n\n // 獲取操作名稱\n const operationName = getOperationName({ verb, path });\n const finalOperationName = operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName;\n\n // 生成類型名稱\n const argTypeName = capitalize(operationName + operationNameSuffix + argSuffix);\n const responseTypeName = capitalize(operationName + operationNameSuffix + responseSuffix);\n\n // 判斷是否為查詢類型\n const isQuery = testIsQuery(verb, path, getOverrides(operationDefinition, endpointOverrides), queryMatch);\n\n // 生成查詢鍵名稱\n const queryKeyName = `${operationName.replace(/([A-Z])/g, '_$1').toUpperCase()}`;\n\n // 提取 OpenAPI summary\n const summary = operation.summary || `${verb.toUpperCase()} ${path}`;\n\n // 解析參數\n const { queryParams, pathParams, isVoidArg, hasRequestBody } = this.extractParameters(operationDefinition);\n\n // 提取 content type\n const contentType = this.extractContentType(operation);\n\n // 提取 tags\n const tags = Array.isArray(operation.tags) ? operation.tags : [];\n\n return {\n operationName: finalOperationName,\n argTypeName,\n responseTypeName,\n isQuery,\n verb: verb.toUpperCase(),\n path,\n queryKeyName,\n queryParams,\n pathParams,\n isVoidArg,\n summary,\n contentType,\n hasRequestBody,\n tags\n };\n }\n\n /**\n * 提取操作的參數資訊\n * @param operationDefinition - 操作定義\n */\n private extractParameters(operationDefinition: OperationDefinition) {\n const { operation, pathItem } = operationDefinition;\n\n // 解析參數\n const operationParameters = this.resolveArray(operation.parameters);\n const pathItemParameters = this.resolveArray(pathItem.parameters)\n .filter((pp) => !operationParameters.some((op) => op.name === pp.name && op.in === pp.in));\n\n const allParameters = supportDeepObjects([...pathItemParameters, ...operationParameters])\n .filter((param) => param.in !== 'header');\n\n const queryParams = allParameters.filter(param => param.in === 'query');\n const pathParams = allParameters.filter(param => param.in === 'path');\n\n // 檢查是否有 request body\n const hasRequestBody = !!operation.requestBody;\n\n // 檢查是否為 void 類型參數\n const isVoidArg = queryParams.length === 0 && pathParams.length === 0 && !operation.requestBody;\n\n return {\n queryParams,\n pathParams,\n isVoidArg,\n hasRequestBody\n };\n }\n\n /**\n * 解析參數陣列 (模擬 apiGen.resolveArray)\n */\n private resolveArray(parameters: any): any[] {\n if (!parameters) return [];\n return Array.isArray(parameters) ? parameters : [parameters];\n }\n\n /**\n * 提取操作的 content type\n * @param operation - 操作對象\n */\n private extractContentType(operation: any): string {\n // 檢查 requestBody 是否存在\n if (!operation.requestBody) {\n return 'application/json';\n }\n\n // 從 requestBody.content 中獲取第一個 content type\n const content = operation.requestBody.content;\n if (!content || typeof content !== 'object') {\n return 'application/json';\n }\n\n const contentTypes = Object.keys(content);\n if (contentTypes.length === 0) {\n return 'application/json';\n }\n\n // 返回第一個 content type\n return contentTypes[0];\n }\n}","import ts from 'typescript';\nimport type { GenerationOptions } from '../types';\n\n/**\n * 轉換類型名稱為大駝峰命名\n */\nconst toPascalCase = (name: string): string => {\n return name.charAt(0).toUpperCase() + name.slice(1);\n};\n\n/**\n * 重新命名 TypeScript 節點中的標識符\n */\nfunction renameIdentifier(node: ts.Node, oldName: string, newName: string): ts.Node {\n return ts.transform(node, [\n context => rootNode => ts.visitNode(rootNode, function visit(node): ts.Node {\n if (ts.isIdentifier(node) && node.text === oldName) {\n return ts.factory.createIdentifier(newName);\n }\n return ts.visitEachChild(node, visit, context);\n })\n ]).transformed[0];\n}\n\n/**\n * 將節點中引用到 shared schema 的標識符加上 Schema. 前綴\n * 例如: TaskDto → Schema.TaskDto(如果 TaskDto 是 shared schema)\n */\nfunction prefixSharedSchemaRefs(\n node: ts.Node,\n allSchemaNames: Set<string>,\n localSchemaNames: Set<string>,\n declarationName: string\n): ts.Node {\n // 建立需要加前綴的 schema 名稱集合(shared = all - local)\n const sharedNames = new Set<string>();\n for (const name of allSchemaNames) {\n if (!localSchemaNames.has(name)) {\n sharedNames.add(toPascalCase(name));\n }\n }\n\n return ts.transform(node, [\n context => rootNode => ts.visitNode(rootNode, function visit(node): ts.Node {\n // 對於類型引用中的標識符,如果是 shared schema 名稱,加上 Schema. 前綴\n if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {\n const name = node.typeName.text;\n if (sharedNames.has(name) && name !== declarationName) {\n const qualifiedName = ts.factory.createQualifiedName(\n ts.factory.createIdentifier('Schema'),\n ts.factory.createIdentifier(name)\n );\n return ts.factory.createTypeReferenceNode(qualifiedName, node.typeArguments);\n }\n }\n return ts.visitEachChild(node, visit, context);\n })\n ]).transformed[0];\n}\n\nexport interface EndpointInfo {\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n}\n\n/**\n * Group-local schema 類型生成選項\n */\nexport interface LocalSchemaOptions {\n /** 此 group 專屬的 schema interfaces(會直接生成在 types.ts 中) */\n localSchemaInterfaces?: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>;\n /** 此 group 專屬的 schema 名稱集合(用於判斷引用時使用本地名稱還是 Schema.*) */\n localSchemaNames?: Set<string>;\n}\n\nexport function generateTypesFile(\n endpointInfos: EndpointInfo[],\n _options: GenerationOptions,\n schemaInterfaces?: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>,\n operationDefinitions?: any[],\n localSchemaOptions?: LocalSchemaOptions\n) {\n const localSchemaNames = localSchemaOptions?.localSchemaNames ?? new Set<string>();\n const localSchemaInterfaces = localSchemaOptions?.localSchemaInterfaces ?? {};\n\n // 創建 schema 類型名稱映射表 - 使用實際生成的類型名稱\n const schemaTypeMap: Record<string, string> = {};\n\n if (schemaInterfaces) {\n Object.keys(schemaInterfaces).forEach(actualTypeName => {\n // 直接使用實際生成的類型名稱,不進行轉換\n // 這確保了 types.ts 中的引用與 schema.ts 中的定義完全一致\n schemaTypeMap[actualTypeName] = actualTypeName;\n\n // 為了兼容 OpenAPI 中可能存在的不同命名方式,添加常見的映射\n // 例如:TokenResponseVO -> TokenResponseVo\n if (actualTypeName.endsWith('Vo')) {\n const openApiName = actualTypeName.slice(0, -2) + 'VO';\n schemaTypeMap[openApiName] = actualTypeName;\n }\n if (actualTypeName.endsWith('Dto')) {\n const openApiName = actualTypeName.slice(0, -3) + 'DTO';\n schemaTypeMap[openApiName] = actualTypeName;\n }\n });\n }\n\n // 判斷是否有 shared schema 類型需要引用(排除 local 之後仍有 shared 的情況)\n const hasSharedSchemaTypes = schemaInterfaces && Object.keys(schemaInterfaces).some(\n name => !localSchemaNames.has(name)\n );\n\n // 生成 import 語句\n let importStatement = `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n`;\n\n // 只有在有 shared schema 類型時才引入 schema.ts\n if (hasSharedSchemaTypes) {\n importStatement += `import * as Schema from \"../schema\";\\n`;\n }\n\n importStatement += '\\n';\n\n // 收集所有需要的類型定義\n const typeDefinitions: string[] = [];\n\n // 生成 group-local schema 類型定義(原本在 schema.ts,現在移到此 group 的 types.ts)\n if (Object.keys(localSchemaInterfaces).length > 0) {\n const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n const resultFile = ts.createSourceFile('types.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);\n const localTypeDefs: string[] = [];\n\n // 建立所有 schema 名稱集合(用於判斷哪些引用需要加 Schema. 前綴)\n const allSchemaNameSet = new Set(schemaInterfaces ? Object.keys(schemaInterfaces) : []);\n\n for (const [originalName, node] of Object.entries(localSchemaInterfaces)) {\n const pascalCaseName = toPascalCase(originalName);\n // 重新命名節點中的宣告名稱\n let transformedNode = renameIdentifier(node, originalName, pascalCaseName);\n // 將引用到 shared schema 的標識符加上 Schema. 前綴\n transformedNode = prefixSharedSchemaRefs(transformedNode, allSchemaNameSet, localSchemaNames, pascalCaseName);\n const printed = printer.printNode(ts.EmitHint.Unspecified, transformedNode, resultFile);\n localTypeDefs.push(printed);\n }\n\n if (localTypeDefs.length > 0) {\n typeDefinitions.push(localTypeDefs.join('\\n'));\n }\n }\n\n // 無論是否有 schema,都要生成 endpoint 特定的 Req/Res 類型\n const endpointTypes: string[] = [];\n\n // 為每個端點生成 Req/Res 類型\n endpointInfos.forEach(endpoint => {\n // 使用 endpoint 中提供的準確類型名稱\n const reqTypeName = endpoint.argTypeName;\n const resTypeName = endpoint.responseTypeName;\n\n // 生成 Request 類型(總是生成)\n if (reqTypeName) {\n const requestTypeContent = generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap, localSchemaNames);\n if (requestTypeContent.trim() === '') {\n // 如果沒有實際內容,使用 void\n endpointTypes.push(\n `export type ${reqTypeName} = void;`,\n ``\n );\n } else {\n // 有實際內容,使用 type 定義\n endpointTypes.push(\n `export type ${reqTypeName} = {`,\n requestTypeContent,\n `};`,\n ``\n );\n }\n }\n\n // 生成 Response 類型(總是生成)\n if (resTypeName) {\n const responseTypeResult = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap, localSchemaNames);\n if (responseTypeResult.content.trim() === '') {\n // 如果沒有實際內容,使用 void\n endpointTypes.push(\n `export type ${resTypeName} = void;`,\n ``\n );\n } else if (responseTypeResult.isDirectType) {\n // 直接類型引用(如 $ref、array、primitive),使用 type alias\n endpointTypes.push(\n `export type ${resTypeName} = ${responseTypeResult.content};`,\n ``\n );\n } else {\n // 有 object 屬性內容,使用 type 定義\n endpointTypes.push(\n `export type ${resTypeName} = {`,\n responseTypeResult.content,\n `};`,\n ``\n );\n }\n }\n });\n\n if (endpointTypes.length > 0) {\n typeDefinitions.push(endpointTypes.join('\\n'));\n }\n\n // 如果沒有任何類型定義,至少添加一些基本說明\n if (typeDefinitions.length === 0) {\n typeDefinitions.push(\n `// 此檔案用於定義 API 相關的類型`,\n `// 類型定義會根據 OpenAPI Schema 自動生成`,\n ``\n );\n }\n\n return importStatement + typeDefinitions.join('\\n\\n');\n}\n\n/**\n * 生成 Request 類型的內容\n */\nfunction generateRequestTypeContent(endpoint: EndpointInfo, operationDefinitions?: any[], schemaTypeMap: Record<string, string> = {}, localSchemaNames: Set<string> = new Set()): string {\n const properties: string[] = [];\n\n // 如果有 query 參數\n if (endpoint.queryParams && endpoint.queryParams.length > 0) {\n endpoint.queryParams.forEach(param => {\n const optional = param.required ? '' : '?';\n const paramType = getTypeFromParameter(param, schemaTypeMap, localSchemaNames);\n properties.push(` ${param.name}${optional}: ${paramType};`);\n });\n }\n\n // 如果有 path 參數\n if (endpoint.pathParams && endpoint.pathParams.length > 0) {\n endpoint.pathParams.forEach(param => {\n const optional = param.required ? '' : '?';\n const paramType = getTypeFromParameter(param, schemaTypeMap, localSchemaNames);\n properties.push(` ${param.name}${optional}: ${paramType};`);\n });\n }\n\n // 如果有 request body(從 operationDefinitions 中獲取)\n const operationDef = operationDefinitions?.find(op => {\n // 嘗試多種匹配方式\n return op.operation?.operationId === endpoint.operationName ||\n op.operation?.operationId === endpoint.operationName.toLowerCase() ||\n // 也嘗試匹配 verb + path 組合\n (op.verb === endpoint.verb.toLowerCase() && op.path === endpoint.path);\n });\n\n if (operationDef?.operation?.requestBody) {\n const requestBody = operationDef.operation.requestBody;\n const content = requestBody.content;\n\n // 處理不同的 content types,優先使用 application/json,其次嘗試其他類型\n const jsonContent = content['application/json'] || content['*/*'];\n const formContent = content['multipart/form-data'] || content['application/x-www-form-urlencoded'];\n\n if (jsonContent?.schema) {\n const bodyType = getTypeFromSchema(jsonContent.schema, schemaTypeMap, 1, localSchemaNames);\n properties.push(` body: ${bodyType};`);\n } else if (formContent?.schema) {\n const bodyType = getTypeFromSchema(formContent.schema, schemaTypeMap, 1, localSchemaNames);\n properties.push(` body: ${bodyType};`);\n } else {\n // fallback 到第一個可用的 content-type\n const firstContent = Object.values(content)[0] as any;\n if (firstContent?.schema) {\n const bodyType = getTypeFromSchema(firstContent.schema, schemaTypeMap, 1, localSchemaNames);\n properties.push(` body: ${bodyType};`);\n } else {\n properties.push(` body?: any; // Request body from OpenAPI`);\n }\n }\n }\n\n // 如果沒有任何參數,返回空內容(將由調用方處理為 void)\n if (properties.length === 0) {\n return ''; // 返回空字串,讓調用方決定使用 void\n }\n\n return properties.join('\\n');\n}\n\ninterface ResponseTypeResult {\n content: string;\n /** true when content is a direct type (e.g. Schema.Pet, string[]) rather than object properties */\n isDirectType: boolean;\n}\n\n/**\n * 生成 Response 類型的內容\n */\nfunction generateResponseTypeContent(endpoint: EndpointInfo, operationDefinitions?: any[], schemaTypeMap: Record<string, string> = {}, localSchemaNames: Set<string> = new Set()): ResponseTypeResult {\n // 嘗試從 operationDefinitions 中獲取響應結構\n const operationDef = operationDefinitions?.find(op => {\n // 嘗試多種匹配方式\n return op.operation?.operationId === endpoint.operationName ||\n op.operation?.operationId === endpoint.operationName.toLowerCase() ||\n // 也嘗試匹配 verb + path 組合\n (op.verb === endpoint.verb.toLowerCase() && op.path === endpoint.path);\n });\n\n if (operationDef?.operation?.responses) {\n // 檢查 200 響應\n const successResponse = operationDef.operation.responses['200'] ||\n operationDef.operation.responses['201'];\n\n if (successResponse?.content) {\n // 優先使用 application/json,其次嘗試其他 content-type(包括 */*)\n const jsonContent = successResponse.content['application/json'] ||\n successResponse.content['*/*'] ||\n Object.values(successResponse.content)[0]; // fallback 到第一個可用的 content-type\n\n if (jsonContent?.schema) {\n const schema = jsonContent.schema;\n\n // 如果 schema 是 $ref 引用、array、或 primitive,直接使用 getTypeFromSchema\n if (schema.$ref || schema.type !== 'object' || !schema.properties) {\n const directType = getTypeFromSchema(schema, schemaTypeMap, 0, localSchemaNames);\n if (directType && directType !== 'any') {\n return { content: directType, isDirectType: true };\n }\n }\n\n // 如果是有 properties 的 object,展開為屬性列表\n const responseProps = parseSchemaProperties(schema, schemaTypeMap, localSchemaNames);\n if (responseProps.length > 0) {\n return { content: responseProps.join('\\n'), isDirectType: false };\n }\n }\n }\n }\n\n // 如果沒有響應定義,返回空內容(將由調用方處理為 void)\n return { content: '', isDirectType: false };\n}\n\n/**\n * 解析 OpenAPI schema 的 properties 並生成 TypeScript 屬性定義\n */\nfunction parseSchemaProperties(schema: any, schemaTypeMap: Record<string, string> = {}, localSchemaNames: Set<string> = new Set()): string[] {\n const properties: string[] = [];\n\n if (schema.type === 'object' && schema.properties) {\n const required = schema.required || [];\n\n Object.entries(schema.properties).forEach(([propName, propSchema]: [string, any]) => {\n const isRequired = required.includes(propName);\n const optional = isRequired ? '' : '?';\n // indentLevel=1 因為屬性已經在類型定義內(有 2 個空格縮排)\n const propType = getTypeFromSchema(propSchema, schemaTypeMap, 1, localSchemaNames);\n\n // 如果屬性名包含特殊字符(如 -),需要加上引號\n const needsQuotes = /[^a-zA-Z0-9_$]/.test(propName);\n const quotedPropName = needsQuotes ? `\"${propName}\"` : propName;\n\n // 生成 JSDoc 註解\n if (propSchema.description) {\n properties.push(` /** ${propSchema.description} */`);\n }\n properties.push(` ${quotedPropName}${optional}: ${propType};`);\n });\n }\n\n return properties;\n}\n\n/**\n * 從 OpenAPI schema 獲取 TypeScript 類型\n * @param schema OpenAPI schema 定義\n * @param schemaTypeMap 類型名稱映射表\n * @param indentLevel 縮排層級,用於格式化內嵌物件\n */\nfunction getTypeFromSchema(schema: any, schemaTypeMap: Record<string, string> = {}, indentLevel: number = 0, localSchemaNames: Set<string> = new Set()): string {\n if (!schema) return 'any';\n\n // 處理 $ref 引用\n if (schema.$ref) {\n const refPath = schema.$ref;\n if (refPath.startsWith('#/components/schemas/')) {\n const originalTypeName = refPath.replace('#/components/schemas/', '');\n // 使用映射表查找實際的類型名稱,並轉換為大駝峰\n const actualTypeName = schemaTypeMap[originalTypeName] || originalTypeName;\n const pascalCaseTypeName = toPascalCase(actualTypeName);\n // 如果是 local schema,直接使用本地名稱;否則使用 Schema.TypeName\n const baseType = localSchemaNames.has(originalTypeName)\n ? pascalCaseTypeName\n : `Schema.${pascalCaseTypeName}`;\n // 處理 nullable\n return schema.nullable ? `${baseType} | null` : baseType;\n }\n }\n\n let baseType: string;\n\n switch (schema.type) {\n case 'string':\n if (schema.enum) {\n baseType = schema.enum.map((val: string) => `\"${val}\"`).join(' | ');\n } else if (schema.format === 'binary') {\n // 處理檔案上傳:format: \"binary\" 應該對應 Blob 類型\n baseType = 'Blob';\n } else {\n baseType = 'string';\n }\n break;\n case 'number':\n case 'integer':\n baseType = 'number';\n break;\n case 'boolean':\n baseType = 'boolean';\n break;\n case 'array':\n const itemType = schema.items ? getTypeFromSchema(schema.items, schemaTypeMap, indentLevel, localSchemaNames) : 'any';\n // 如果 itemType 包含聯合類型(包含 |),需要加括號\n const needsParentheses = itemType.includes('|');\n baseType = needsParentheses ? `(${itemType})[]` : `${itemType}[]`;\n break;\n case 'object':\n if (schema.properties) {\n // 如果有具體的屬性定義,生成內聯對象類型(多行格式)\n const entries = Object.entries(schema.properties);\n\n // 如果沒有屬性但有 additionalProperties,生成 Record 類型\n if (entries.length === 0) {\n if (schema.additionalProperties) {\n const valueType = schema.additionalProperties === true\n ? 'any'\n : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel, localSchemaNames);\n baseType = `Record<string, ${valueType}>`;\n } else {\n baseType = '{}';\n }\n } else {\n // 計算下一層的縮排\n const nextIndent = ' '.repeat(indentLevel + 1);\n const currentIndent = ' '.repeat(indentLevel);\n\n const props: string[] = [];\n entries.forEach(([key, propSchema]: [string, any]) => {\n const required = schema.required || [];\n const optional = required.includes(key) ? '' : '?';\n const type = getTypeFromSchema(propSchema, schemaTypeMap, indentLevel + 1, localSchemaNames);\n\n // 如果屬性名包含特殊字符(如 -),需要加上引號\n const needsQuotes = /[^a-zA-Z0-9_$]/.test(key);\n const quotedKey = needsQuotes ? `\"${key}\"` : key;\n\n // 生成 JSDoc 註解\n if (propSchema.description) {\n props.push(`${nextIndent}/** ${propSchema.description} */`);\n }\n props.push(`${nextIndent}${quotedKey}${optional}: ${type};`);\n });\n\n baseType = `{\\n${props.join('\\n')}\\n${currentIndent}}`;\n }\n } else if (schema.additionalProperties) {\n // 如果沒有 properties 但有 additionalProperties\n const valueType = schema.additionalProperties === true\n ? 'any'\n : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel, localSchemaNames);\n baseType = `Record<string, ${valueType}>`;\n } else {\n baseType = 'any';\n }\n break;\n default:\n baseType = 'any';\n break;\n }\n\n // 處理 nullable\n return schema.nullable ? `${baseType} | null` : baseType;\n}\n\n/**\n * 從參數定義中獲取 TypeScript 類型\n */\nfunction getTypeFromParameter(param: any, schemaTypeMap: Record<string, string> = {}, localSchemaNames: Set<string> = new Set()): string {\n if (!param.schema) return 'any';\n return getTypeFromSchema(param.schema, schemaTypeMap, 0, localSchemaNames);\n}\n","import type { GenerationOptions } from '../types';\n\nexport function generateRtkQueryFile(endpointInfos: Array<{\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n contentType: string;\n hasRequestBody: boolean;\n tags: string[];\n}>, options: GenerationOptions) {\n\n const { groupKey } = options;\n\n // 獲取類型名稱\n const httpClientTypeName = options.httpClient?.importReturnTypeName || 'IRestFulEndpointsQueryReturn';\n\n // 生成端點定義\n const endpoints = endpointInfos.map(info => {\n const methodType = info.isQuery ? 'query' : 'mutation';\n const argType = info.isVoidArg ? 'void' : `${httpClientTypeName}<${info.argTypeName}>`;\n\n // 處理 path parameters - 替換 {id} 為 ${queryArg.variables.id}\n let urlPath = info.path;\n if (info.pathParams && info.pathParams.length > 0) {\n info.pathParams.forEach((param: any) => {\n urlPath = urlPath.replace(`{${param.name}}`, `\\${queryArg.variables.${param.name}}`);\n });\n // 使用模板字符串\n urlPath = '`' + urlPath + '`';\n } else {\n // 使用普通字符串\n urlPath = `\"${urlPath}\"`;\n }\n\n // 處理 query parameters\n let paramsSection = '';\n if (info.queryParams && info.queryParams.length > 0) {\n const paramsLines = info.queryParams.map((param: any) =>\n ` ${param.name}: queryArg.variables.${param.name},`\n ).join('\\n');\n paramsSection = `\n params: {\n${paramsLines}\n },`;\n }\n\n // 處理 tags\n let tagsSection = '';\n if (info.tags && info.tags.length > 0) {\n const tagsArray = info.tags.map(tag => {\n // 將 tag 轉為大駝峰(去除空格),與 ECacheTagTypes 枚舉 key 一致\n const pascalTag = tag.split(/\\s+/).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');\n return `ECacheTagTypes.${pascalTag}`;\n }).join(', ');\n if (info.isQuery) {\n tagsSection = `\n providesTags: [${tagsArray}],`;\n } else {\n tagsSection = `\n invalidatesTags: (result, error) => error ? [] : [${tagsArray}],`;\n }\n }\n\n return ` /** ${info.summary || info.operationName} */\n ${info.operationName}: build.${methodType}<\n ${info.responseTypeName},\n ${argType}\n >({${tagsSection}\n query: (queryArg) => ({\n url: ${urlPath},\n method: \"${info.verb.toUpperCase()}\",\n contentType: \"${info.contentType}\",${paramsSection}${info.hasRequestBody ? `\n body: queryArg.variables.body,` : ''}${info.isVoidArg ? '' : `\n fetchOptions: queryArg?.fetchOptions,`}\n }),\n }),`;\n }).join('\\n');\n\n // 生成類型導入\n const typeImports = [\n ...new Set([\n ...endpointInfos.map(info => info.argTypeName),\n ...endpointInfos.map(info => info.responseTypeName)\n ])\n ].filter(type => type !== 'VoidApiArg');\n\n const typeImportStatement = typeImports.length > 0\n ? `import type { ${typeImports.join(', ')} } from \"./types\";`\n : '';\n\n // 根據配置生成 import 語句\n const apiImport = options.apiConfiguration\n ? `import {${options.apiConfiguration.importName} as api} from \"${options.apiConfiguration.file.replace(/\\.ts$/, '')}\";\n`\n : `import {baseApi as api} from \"../../../library/redux/baseApi\";\n`;\n\n const httpClientImport = options.httpClient\n ? `import {${options.httpClient.importReturnTypeName}} from \"${options.httpClient.file}\";\n`\n : `import {IRestFulEndpointsQueryReturn} from \"@acrool/react-fetcher\";\n`;\n\n // 檢查是否有任何 endpoint 使用了 tags\n const hasTags = endpointInfos.some(info => info.tags && info.tags.length > 0);\n const tagTypesImport = hasTags\n ? `import {ECacheTagTypes} from \"../tagTypes\";\n`\n : '';\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${apiImport}${httpClientImport}${tagTypesImport}\n${typeImportStatement}\n\n\nconst injectedRtkApi = api.injectEndpoints({\n endpoints: (build) => ({\n${endpoints}\n }),\n});\n\nexport const {\n${endpointInfos.map(info => {\n const capitalizedOperationName = info.operationName.charAt(0).toUpperCase() + info.operationName.slice(1);\n if (info.isQuery) {\n // For queries, generate both regular and lazy hooks if useLazyQueries is enabled\n const regularHook = `use${capitalizedOperationName}Query`;\n if (options.useLazyQueries) {\n const lazyHook = `useLazy${capitalizedOperationName}Query`;\n return ` ${regularHook},\\n ${lazyHook},`;\n } else {\n return ` ${regularHook},`;\n }\n } else {\n // For mutations, only generate regular hook\n const mutationHook = `use${capitalizedOperationName}Mutation`;\n return ` ${mutationHook},`;\n }\n }).join('\\n')}\n} = injectedRtkApi;\n\nexport default injectedRtkApi;\n`;\n}\n","import type { GenerationOptions } from '../types';\n\nexport function generateRtkEnhanceEndpointsFile(endpointInfos: Array<{\n operationName: string;\n argTypeName: string;\n responseTypeName: string;\n isQuery: boolean;\n verb: string;\n path: string;\n queryKeyName: string;\n queryParams: any[];\n pathParams: any[];\n isVoidArg: boolean;\n summary: string;\n}>, options: GenerationOptions) {\n\n // 生成端點配置\n const endpointConfigs = endpointInfos.map(info => {\n // 為 query 類型的端點添加 providesTags,為 mutation 類型的添加 invalidatesTags\n if (info.isQuery) {\n // Query 端點提供 tags\n return ` ${info.operationName}: {\n providesTags: (result, error, arg) => [],\n },`;\n } else {\n // Mutation 端點使 tags 失效\n return ` ${info.operationName}: {\n invalidatesTags: (result, error, arg) => [],\n },`;\n }\n }).join('\\n');\n\n // 生成 import 語句\n const importStatements = `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nimport api from \"./query.generated\";\n`;\n\n return `${importStatements}\nconst enhancedApi = api.enhanceEndpoints({\n endpoints: {\n${endpointConfigs}\n },\n});\n\nexport default enhancedApi;\n`;\n}\n","import ts from 'typescript';\n\n\n/**\n * 產生 Utils function 內容\n * @param interfaces\n */\nexport function generateUtilsFile() {\n\n // 分析接口內容以找出需要從 shared-types 導入的類型\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually \n \n/**\n* Clear undefined in object\n*/\nexport function withoutUndefined(obj?: Record<string, any>) {\n if(typeof obj === 'undefined') return;\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined && v !== null)\n );\n}\n\n`\n}\n\n/**\n * 大寫底線字串 轉 小駝峰\n * @param str\n */\nexport function toCamelCase(str: string): string {\n return str.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}","/**\n * 將 tag 名稱轉換為大駝峰命名(去除空格)\n * 例如: \"Home Banner\" -> \"HomeBanner\", \"payout methods\" -> \"PayoutMethods\"\n */\nfunction toPascalCase(tag: string): string {\n return tag\n .split(/\\s+/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n}\n\n/**\n * 生成 RTK Query 的 cache tag types 枚举文件\n * @param tags - 去重后的 tags 数组\n * @returns 生成的 TypeScript 枚举代码\n */\nexport function generateTagTypesFile(tags: string[]): string {\n // 如果没有 tags,生成一个空的枚举\n if (tags.length === 0) {\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport enum ECacheTagTypes {\n}\n`;\n }\n\n // 生成枚举项,key 使用大駝峰命名(去除空格),value 保留原始 tag 名稱\n const enumEntries = tags\n .sort() // 按字母顺序排序\n .map(tag => ` ${toPascalCase(tag)} = '${tag}',`)\n .join('\\n');\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nexport enum ECacheTagTypes {\n${enumEntries}\n}\n`;\n}\n","import type { OpenAPIV3 } from 'openapi-types';\nimport type { OperationDefinition } from '../types';\n\n/**\n * Schema 引用分析結果\n */\nexport interface SchemaRefAnalysis {\n /** 被多個 group 共用的 schema 名稱 */\n sharedSchemas: Set<string>;\n /** 每個 group 專屬的 schema 名稱 */\n groupLocalSchemas: Map<string, Set<string>>;\n /** 完全未被引用的 schema 名稱 */\n unusedSchemas: Set<string>;\n}\n\n/**\n * 從 OpenAPI schema 物件中遞迴收集所有 $ref 引用的 schema 名稱\n */\nfunction collectRefsFromSchema(schema: any, refs: Set<string>): void {\n if (!schema || typeof schema !== 'object') return;\n\n if (schema.$ref && typeof schema.$ref === 'string') {\n const match = schema.$ref.match(/^#\\/components\\/schemas\\/(.+)$/);\n if (match) {\n refs.add(match[1]);\n }\n }\n\n // 遍歷所有屬性\n if (schema.properties) {\n for (const prop of Object.values(schema.properties)) {\n collectRefsFromSchema(prop, refs);\n }\n }\n\n // array items\n if (schema.items) {\n collectRefsFromSchema(schema.items, refs);\n }\n\n // additionalProperties\n if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {\n collectRefsFromSchema(schema.additionalProperties, refs);\n }\n\n // allOf / oneOf / anyOf\n for (const key of ['allOf', 'oneOf', 'anyOf'] as const) {\n if (Array.isArray(schema[key])) {\n for (const item of schema[key]) {\n collectRefsFromSchema(item, refs);\n }\n }\n }\n}\n\n/**\n * 從一組 operation definitions 收集所有直接引用的 schema 名稱\n */\nfunction collectDirectRefs(operationDefs: OperationDefinition[]): Set<string> {\n const refs = new Set<string>();\n\n for (const opDef of operationDefs) {\n const op = opDef.operation;\n\n // 收集 parameters 中的 refs\n if (op.parameters) {\n for (const param of op.parameters) {\n const p = param as OpenAPIV3.ParameterObject;\n if (p.schema) {\n collectRefsFromSchema(p.schema, refs);\n }\n }\n }\n\n // 收集 requestBody 中的 refs\n if (op.requestBody) {\n const rb = op.requestBody as OpenAPIV3.RequestBodyObject;\n if (rb.content) {\n for (const ct of Object.values(rb.content)) {\n if (ct.schema) {\n collectRefsFromSchema(ct.schema, refs);\n }\n }\n }\n }\n\n // 收集 responses 中的 refs\n if (op.responses) {\n for (const resp of Object.values(op.responses)) {\n const r = resp as OpenAPIV3.ResponseObject;\n if (r.content) {\n for (const ct of Object.values(r.content)) {\n if (ct.schema) {\n collectRefsFromSchema(ct.schema, refs);\n }\n }\n }\n }\n }\n }\n\n return refs;\n}\n\n/**\n * 解析 schema 的遞迴依賴(transitive dependencies)\n * 例如 TaskResponseDto 引用了 TaskDto,TaskDto 又引用了 TaskStatusRefDto\n */\nfunction resolveTransitiveDeps(\n directRefs: Set<string>,\n allSchemas: Record<string, any>\n): Set<string> {\n const resolved = new Set<string>();\n const queue = [...directRefs];\n\n while (queue.length > 0) {\n const name = queue.pop()!;\n if (resolved.has(name)) continue;\n resolved.add(name);\n\n const schema = allSchemas[name];\n if (!schema) continue;\n\n const nestedRefs = new Set<string>();\n collectRefsFromSchema(schema, nestedRefs);\n\n for (const ref of nestedRefs) {\n if (!resolved.has(ref)) {\n queue.push(ref);\n }\n }\n }\n\n return resolved;\n}\n\n/**\n * 分析所有 group 的 schema 引用,分類為 shared / group-local / unused\n */\nexport function analyzeSchemaRefs(\n groupOperations: Map<string, OperationDefinition[]>,\n allSchemas: Record<string, any>,\n allSchemaNames: string[]\n): SchemaRefAnalysis {\n // 步驟 1:收集每個 group 的完整引用(含遞迴依賴)\n const groupRefs = new Map<string, Set<string>>();\n\n for (const [groupKey, opDefs] of groupOperations) {\n const directRefs = collectDirectRefs(opDefs);\n const fullRefs = resolveTransitiveDeps(directRefs, allSchemas);\n groupRefs.set(groupKey, fullRefs);\n }\n\n // 步驟 2:統計每個 schema 被多少個 group 引用\n const refCountMap = new Map<string, Set<string>>();\n\n for (const [groupKey, refs] of groupRefs) {\n for (const schemaName of refs) {\n if (!refCountMap.has(schemaName)) {\n refCountMap.set(schemaName, new Set());\n }\n refCountMap.get(schemaName)!.add(groupKey);\n }\n }\n\n // 步驟 3:分類\n const sharedSchemas = new Set<string>();\n const groupLocalSchemas = new Map<string, Set<string>>();\n const unusedSchemas = new Set<string>();\n\n for (const schemaName of allSchemaNames) {\n const groups = refCountMap.get(schemaName);\n\n if (!groups || groups.size === 0) {\n unusedSchemas.add(schemaName);\n } else if (groups.size === 1) {\n const groupKey = [...groups][0];\n if (!groupLocalSchemas.has(groupKey)) {\n groupLocalSchemas.set(groupKey, new Set());\n }\n groupLocalSchemas.get(groupKey)!.add(schemaName);\n } else {\n sharedSchemas.add(schemaName);\n }\n }\n\n // 步驟 4:確保 group-local schema 的依賴一致性\n // 如果 group-A-local 的 schema 依賴了 group-B-local 的 schema,兩者都提升為 shared\n let changed = true;\n while (changed) {\n changed = false;\n for (const [groupKey, localSchemas] of groupLocalSchemas) {\n for (const schemaName of [...localSchemas]) {\n const schema = allSchemas[schemaName];\n if (!schema) continue;\n\n const deps = new Set<string>();\n collectRefsFromSchema(schema, deps);\n\n for (const dep of deps) {\n // 檢查 dep 是否是其他 group 的 local schema\n for (const [otherGroup, otherLocals] of groupLocalSchemas) {\n if (otherGroup !== groupKey && otherLocals.has(dep)) {\n // 衝突!兩者都提升為 shared\n sharedSchemas.add(dep);\n sharedSchemas.add(schemaName);\n otherLocals.delete(dep);\n localSchemas.delete(schemaName);\n changed = true;\n }\n }\n }\n }\n }\n }\n\n return { sharedSchemas, groupLocalSchemas, unusedSchemas };\n}\n"],"mappings":"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","names":["path","path","ts","path","path","path","paths","fs","path","path","fs","path","fs","operationMatches","node","ts","path","isQuery","ts","toPascalCase","renameIdentifier","node","baseType","ts","toPascalCase","ts","path"]}
|
package/package.json
CHANGED
|
@@ -24,8 +24,12 @@ function renameIdentifier(node: ts.Node, oldName: string, newName: string): ts.N
|
|
|
24
24
|
/**
|
|
25
25
|
* 產生 component-schema.ts 內容
|
|
26
26
|
* @param interfaces
|
|
27
|
+
* @param includeOnly - 若提供,則只輸出此 Set 中的類型名稱
|
|
27
28
|
*/
|
|
28
|
-
export function generateComponentSchemaFile(
|
|
29
|
+
export function generateComponentSchemaFile(
|
|
30
|
+
interfaces: Record<string, ts.InterfaceDeclaration | ts.TypeAliasDeclaration>,
|
|
31
|
+
includeOnly?: Set<string>
|
|
32
|
+
) {
|
|
29
33
|
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
30
34
|
|
|
31
35
|
const resultFile = ts.createSourceFile(
|
|
@@ -44,6 +48,11 @@ export function generateComponentSchemaFile(interfaces: Record<string, ts.Interf
|
|
|
44
48
|
const pascalCaseName = toPascalCase(originalName);
|
|
45
49
|
typeNameMapping[originalName] = pascalCaseName;
|
|
46
50
|
|
|
51
|
+
// 如果有過濾條件,跳過不在名單中的類型
|
|
52
|
+
if (includeOnly && !includeOnly.has(originalName)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
47
56
|
// 重新命名節點
|
|
48
57
|
const renamedNode = renameIdentifier(node, originalName, pascalCaseName);
|
|
49
58
|
const printed = printer.printNode(ts.EmitHint.Unspecified, renamedNode, resultFile);
|