@acrool/rtk-query-codegen-openapi 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bin/cli.mjs +26 -26
- package/lib/bin/cli.mjs.map +1 -1
- package/lib/index.d.mts +9 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +42 -17
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +42 -17
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/generators/rtk-enhance-endpoints-generator.ts +13 -5
- package/src/generators/rtk-query-generator.ts +3 -3
- package/src/generators/types-generator.ts +75 -43
- package/src/types.ts +27 -18
package/lib/bin/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../src/utils/http.ts","../../src/bin/cli.ts","../../src/bin/utils.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"],"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}","#!/usr/bin/env node\n\nimport program from 'commander';\nimport { createRequire } from 'node:module';\nimport { cleanOutputDirectory, setupTypeScriptSupport, validateConfigFile, validateTypeScriptSupport } from './utils';\nimport { dirname, resolve } from 'node:path';\nimport { generateEndpoints } from '../index';\n\nconst require = createRequire(__filename);\n\n\n\n\n\n/**\n * 執行代碼生成流程\n * 載入設定檔並驗證是否包含 outputFiles 屬性,清理輸出目錄,然後執行端點生成\n * @param {string} configFile - 設定檔案路徑\n */\nexport async function runGeneration(configFile: string): Promise<void> {\n const absoluteConfigPath = resolve(process.cwd(), configFile);\n process.chdir(dirname(absoluteConfigPath));\n\n const unparsedConfig = require(absoluteConfigPath);\n const config = unparsedConfig.default ?? unparsedConfig;\n\n if (!('outputFiles' in config)) {\n console.error('Configuration must include \"outputFiles\" property. Single file output is no longer supported.');\n process.exit(1);\n }\n\n // 清理輸出目錄\n if (config.outputFiles && config.outputFiles.outputDir) {\n cleanOutputDirectory(config.outputFiles.outputDir);\n }\n\n try {\n console.log('Generating multiple outputs...');\n await generateEndpoints(config);\n console.log('Done');\n } catch (err) {\n console.error('Generation failed:', err);\n process.exit(1);\n }\n}\n\n\n/**\n * CLI 主要執行函數\n * 設置 TypeScript 支援、解析命令列參數、驗證設定檔並執行代碼生成\n */\nasync function main(): Promise<void> {\n const meta = require('../../package.json');\n const hasTypeScriptSupport = setupTypeScriptSupport();\n\n program\n .version(meta.version)\n .usage('<path/to/config.js>')\n .parse(process.argv);\n\n const configFile = program.args[0];\n\n if (program.args.length === 0) {\n program.help();\n return;\n }\n\n validateConfigFile(configFile);\n validateTypeScriptSupport(configFile, hasTypeScriptSupport);\n\n await runGeneration(configFile);\n}\n\nmain().catch((err) => {\n console.error('CLI execution failed:', err);\n process.exit(1);\n});","import program from 'commander';\nimport { createRequire } from 'node:module';\nimport { resolve } from 'node:path';\nimport { existsSync, rmSync, readdirSync, statSync, mkdirSync } from 'node:fs';\nimport path from 'node:path';\n\nconst require = createRequire(__filename);\n\n\n\n\n/**\n * 備份 enhanceEndpoints.ts 檔案\n * @param {string} outputDir - 輸出目錄路徑\n * @returns {Map<string, Buffer>} 備份的檔案內容對應\n */\nfunction backupEnhanceEndpoints(outputDir: string): Map<string, Buffer> {\n const backupMap = new Map<string, Buffer>();\n\n if (!existsSync(outputDir)) {\n return backupMap;\n }\n\n function scanDirectory(dir: string): void {\n try {\n const items = readdirSync(dir);\n\n for (const item of items) {\n const itemPath = path.join(dir, item);\n const stat = statSync(itemPath);\n\n if (stat.isDirectory()) {\n scanDirectory(itemPath);\n } else if (item === 'enhanceEndpoints.ts') {\n // 讀取檔案內容到記憶體\n const content = require('node:fs').readFileSync(itemPath);\n backupMap.set(itemPath, content);\n }\n }\n } catch (error) {\n // 忽略掃描錯誤,繼續處理其他目錄\n }\n }\n\n scanDirectory(outputDir);\n return backupMap;\n}\n\n/**\n * 還原 enhanceEndpoints.ts 檔案\n * @param {Map<string, Buffer>} backupMap - 備份檔案內容對應\n */\nfunction restoreEnhanceEndpoints(backupMap: Map<string, Buffer>): void {\n for (const [originalPath, content] of backupMap) {\n try {\n // 確保目錄存在\n const dir = path.dirname(originalPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // 寫入檔案內容\n require('node:fs').writeFileSync(originalPath, content);\n } catch (error) {\n console.warn(`Failed to restore ${originalPath}:`, error);\n }\n }\n}\n\n/**\n * 清理輸出目錄,但保護 enhanceEndpoints.ts 檔案\n * 移除設定檔中指定的 outputDir 目錄及其內容,但會備份並還原 enhanceEndpoints.ts\n * @param {string} outputDir - 要清理的目錄路徑\n */\nexport function cleanOutputDirectory(outputDir: string): void {\n // 安全檢查:避免刪除重要目錄\n const dangerousPaths = ['/', '/usr', '/etc', '/var', '/home', '/Users', '.', '..'];\n const normalizedPath = resolve(outputDir);\n\n if (dangerousPaths.some(path => normalizedPath === resolve(path))) {\n console.error(`Dangerous path detected: ${normalizedPath}. Refusing to delete.`);\n process.exit(1);\n }\n\n if (existsSync(outputDir)) {\n console.log(`Cleaning output directory: ${outputDir}`);\n\n // 1. 備份所有 enhanceEndpoints.ts 檔案\n const backupMap = backupEnhanceEndpoints(outputDir);\n\n // 2. 刪除整個目錄\n rmSync(outputDir, { recursive: true, force: true });\n\n // 3. 還原 enhanceEndpoints.ts 檔案\n if (backupMap.size > 0) {\n restoreEnhanceEndpoints(backupMap);\n console.log(`Protected ${backupMap.size} enhanceEndpoints.ts file(s) from deletion`);\n }\n\n console.log(`Directory cleaned: ${outputDir}`);\n }\n}\n\n\n/**\n * 設置 TypeScript 支援\n * 優先使用 esbuild-runner,其次使用 ts-node\n * @returns {boolean} 是否成功設置 TypeScript 支援\n */\nexport function setupTypeScriptSupport(): boolean {\n try {\n if (require.resolve('esbuild') && require.resolve('esbuild-runner')) {\n require('esbuild-runner/register');\n return true;\n }\n } catch {}\n\n try {\n if (require.resolve('typescript') && require.resolve('ts-node')) {\n (require('ts-node') as typeof import('ts-node')).register({\n transpileOnly: true,\n compilerOptions: {\n target: 'es6',\n module: 'commonjs',\n },\n });\n return true;\n }\n } catch {}\n\n return false;\n}\n\n/**\n * 驗證設定檔案格式是否有效\n * 支援 .js/.ts/.mjs/.mts/.cjs/.cts/.json/.jsonc 格式\n * @param {string} configFile - 設定檔案路徑\n */\nexport function validateConfigFile(configFile: string): void {\n if (!configFile || !/\\.([mc]?(jsx?|tsx?)|jsonc?)?$/.test(configFile)) {\n console.error('Please provide a valid configuration file.');\n program.help();\n }\n}\n\n/**\n * 驗證 TypeScript 設定檔是否有相應的執行環境支援\n * @param {string} configFile - 設定檔案路徑\n * @param {boolean} hasTypeScriptSupport - 是否已設置 TypeScript 支援\n */\nexport function validateTypeScriptSupport(configFile: string, hasTypeScriptSupport: boolean): void {\n if (/\\.[mc]?tsx?$/.test(configFile) && !hasTypeScriptSupport) {\n console.error('Encountered a TypeScript config file, but neither esbuild-runner nor ts-node are installed.');\n process.exit(1);\n }\n}\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';\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 } = {\n groups: [],\n commonTypes: '',\n componentSchema: '',\n doNotModify: '',\n utils: ''\n };\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\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 // 如果沒有任何 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\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 // 寫入 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 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>;","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 return {\n operationNames,\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}\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 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 };\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 responseTypeContent = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap);\n if (responseTypeContent.trim() === '') {\n // 如果沒有實際內容,使用 void\n endpointTypes.push(\n `export type ${resTypeName} = void;`,\n ``\n );\n } else {\n // 有實際內容,使用 type 定義\n endpointTypes.push(\n `export type ${resTypeName} = {`,\n responseTypeContent,\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\n const jsonContent = content['application/json'];\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 properties.push(` body?: any; // Request body from OpenAPI`);\n }\n }\n \n // 如果沒有任何參數,返回空內容(將由調用方處理為 void)\n if (properties.length === 0) {\n return ''; // 返回空字串,讓調用方決定使用 void\n }\n \n return properties.join('\\n');\n}\n\n/**\n * 生成 Response 類型的內容\n */\nfunction generateResponseTypeContent(endpoint: EndpointInfo, operationDefinitions?: any[], schemaTypeMap: Record<string, string> = {}): string {\n const properties: string[] = [];\n \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 const jsonContent = successResponse.content['application/json'];\n if (jsonContent?.schema) {\n const responseProps = parseSchemaProperties(jsonContent.schema, schemaTypeMap);\n properties.push(...responseProps);\n } else {\n properties.push(` // Success response from OpenAPI`);\n properties.push(` data?: any;`);\n }\n }\n }\n \n // 如果沒有響應定義,返回空內容(將由調用方處理為 void)\n if (properties.length === 0) {\n return ''; // 返回空字串,讓調用方決定使用 void\n }\n \n return properties.join('\\n');\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 const description = propSchema.description ? ` // ${propSchema.description}` : '';\n\n // 如果屬性名包含特殊字符(如 -),需要加上引號\n const needsQuotes = /[^a-zA-Z0-9_$]/.test(propName);\n const quotedPropName = needsQuotes ? `\"${propName}\"` : propName;\n\n properties.push(` ${quotedPropName}${optional}: ${propType};${description}`);\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 // 如果沒有屬性,返回空物件\n if (entries.length === 0) {\n baseType = '{}';\n } else {\n // 計算下一層的縮排\n const nextIndent = ' '.repeat(indentLevel + 1);\n const currentIndent = ' '.repeat(indentLevel);\n\n const props = entries.map(([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 return `${nextIndent}${quotedKey}${optional}: ${type};`;\n }).join('\\n');\n\n baseType = `{\\n${props}\\n${currentIndent}}`;\n }\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}","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}>, options: GenerationOptions) {\n\n const { groupKey } = options;\n\n // 獲取類型名稱\n const httpClientTypeName = options.httpClient?.importReturnTypeName || options.httpClient?.importName || '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 return ` /** ${info.summary || info.operationName} */\n ${info.operationName}: build.${methodType}<\n ${info.responseTypeName},\n ${argType}\n >({\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 || options.httpClient.importName}} from \"${options.httpClient.file}\";\n`\n : `import {IRestFulEndpointsQueryReturn} from \"@acrool/react-fetcher\";\n`;\n\n return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${apiImport}${httpClientImport}\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}","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 const { groupKey } = options;\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 return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\nimport { ECacheTagTypes } from \"@/store/tagTypes\";\nimport api from \"./query.generated\";\n\nconst enhancedApi = api.enhanceEndpoints({\n endpoints: {\n${endpointConfigs}\n },\n});\n\nexport default enhancedApi;\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}"],"mappings":"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","names":["fileURLToPath","getFilename","__filename","init_esm_shims","__esmMin","http_exports","__export","argumentMatches","defaultIsDataResponse","getOperationName","getOverrides","getTags","operationMatches","_getOperationName","code","includeDefault","parsedCode","verb","path","pathItem","patternMatches","pattern","filters","operationName","filter","checkMatch","operationDefinition","argumentDefinition","argumentName","operation","endpointOverrides","override","init_http","__esmMin","init_esm_shims","init_esm_shims","program","createRequire","init_esm_shims","program","createRequire","resolve","existsSync","rmSync","readdirSync","statSync","mkdirSync","path","require","__filename","backupEnhanceEndpoints","outputDir","backupMap","scanDirectory","dir","items","item","itemPath","content","restoreEnhanceEndpoints","originalPath","error","cleanOutputDirectory","dangerousPaths","normalizedPath","setupTypeScriptSupport","validateConfigFile","configFile","validateTypeScriptSupport","hasTypeScriptSupport","dirname","resolve","init_esm_shims","init_esm_shims","path","ts","init_esm_shims","init_esm_shims","capitalize","str","init_esm_shims","fs","path","init_esm_shims","isValidUrl","string","downloadSchemaFile","remoteFile","targetPath","isValidUrl","dir","path","fs","response","content","error","init_esm_shims","init_esm_shims","operationKeys","getOperationDefinitions","v3Doc","path","pathItem","arg","operationKeys","verb","operation","init_esm_shims","SwaggerParser","converter","getV3Doc","spec","httpResolverOptions","doc","init_esm_shims","isQuery","verb","path","overrides","queryMatch","OpenApiService","schemaLocation","httpResolverOptions","doc","getV3Doc","remoteUrl","localPath","downloadSchemaFile","init_esm_shims","camelCase","GroupService","paths","config","groupKeyMatch","outputDir","groupedPaths","acc","path","rawGroupKey","groupKey","result","operationName","operationDefinition","pathGroupKey","init_esm_shims","fs","path","init_esm_shims","path","fs","ensureDirectoryExists","filePath","dirname","FileWriterService","filePath","content","resolvedPath","path","fs","ensureDirectoryExists","error","files","results","result","groupOutputDir","filesToWrite","outputDir","sharedFiles","schema","init_esm_shims","ApiGenerator","OpenApiParserService","v3Doc","options","ApiGenerator","schemaName","schema","filterEndpoints","operationMatches","getOperationDefinitions","init_esm_shims","generateCommonTypesFile","init_esm_shims","ts","toPascalCase","name","renameIdentifier","node","oldName","newName","context","rootNode","visit","generateComponentSchemaFile","interfaces","printer","resultFile","renamedInterfaces","typeNameMapping","originalName","pascalCaseName","renamedNode","printed","init_esm_shims","generateDoNotModifyFile","init_esm_shims","ts","init_esm_shims","init_http","supportDeepObjects","EndpointInfoExtractor","options","operationDefinitions","operationDefinition","verb","path","operation","operationNameSuffix","argSuffix","responseSuffix","queryMatch","endpointOverrides","operationName","getOperationName","finalOperationName","capitalize","argTypeName","responseTypeName","isQuery","getOverrides","queryKeyName","summary","queryParams","pathParams","isVoidArg","hasRequestBody","contentType","pathItem","operationParameters","pathItemParameters","pp","op","allParameters","param","parameters","content","contentTypes","init_esm_shims","toPascalCase","name","generateTypesFile","endpointInfos","_options","schemaInterfaces","operationDefinitions","schemaTypeMap","actualTypeName","openApiName","importStatement","typeDefinitions","endpointTypes","endpoint","reqTypeName","resTypeName","requestTypeContent","generateRequestTypeContent","responseTypeContent","generateResponseTypeContent","properties","param","optional","paramType","getTypeFromParameter","operationDef","op","content","jsonContent","formContent","bodyType","getTypeFromSchema","successResponse","responseProps","parseSchemaProperties","schema","required","propName","propSchema","propType","description","quotedPropName","indentLevel","refPath","originalTypeName","baseType","val","itemType","entries","nextIndent","currentIndent","key","type","quotedKey","init_esm_shims","generateRtkQueryFile","endpointInfos","options","groupKey","httpClientTypeName","endpoints","info","methodType","argType","urlPath","param","paramsSection","typeImports","type","typeImportStatement","apiImport","httpClientImport","capitalizedOperationName","regularHook","lazyHook","init_esm_shims","generateRtkEnhanceEndpointsFile","endpointInfos","options","groupKey","info","ApiCodeGenerator","parserService","options","EndpointInfoExtractor","operationDefinitions","endpointInfos","typesContent","rtkQueryContent","generateRtkQueryFile","enhanceEndpointsContent","generateRtkEnhanceEndpointsFile","indexContent","info","generatorOptions","schemaInterfaces","curr","alias","ts","name","generateTypesFile","groupKey","init_esm_shims","generateUtilsFile","UnifiedCodeGenerator","OpenApiService","GroupService","FileWriterService","options","OpenApiParserService","apiGen","curr","alias","ts","name","paths","groupInfos","groupInfo","groupContent","error","generateCommonTypesFile","generateComponentSchemaFile","generateDoNotModifyFile","generateUtilsFile","results","errors","generatedGroups","group","groupOutputDir","path","groupResults","outputDir","sharedResults","schemaResults","mainIndexContent","mainIndexResult","outputFiles","commonConfig","groupOptions","ApiCodeGenerator","groupKey","generateEndpoints","options","result","UnifiedCodeGenerator","require","createRequire","__filename","runGeneration","configFile","absoluteConfigPath","resolve","dirname","unparsedConfig","config","cleanOutputDirectory","generateEndpoints","err","main","meta","hasTypeScriptSupport","setupTypeScriptSupport","program","validateConfigFile","validateTypeScriptSupport"]}
|
|
1
|
+
{"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../src/utils/http.ts","../../src/bin/cli.ts","../../src/bin/utils.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"],"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}","#!/usr/bin/env node\n\nimport program from 'commander';\nimport { createRequire } from 'node:module';\nimport { cleanOutputDirectory, setupTypeScriptSupport, validateConfigFile, validateTypeScriptSupport } from './utils';\nimport { dirname, resolve } from 'node:path';\nimport { generateEndpoints } from '../index';\n\nconst require = createRequire(__filename);\n\n\n\n\n\n/**\n * 執行代碼生成流程\n * 載入設定檔並驗證是否包含 outputFiles 屬性,清理輸出目錄,然後執行端點生成\n * @param {string} configFile - 設定檔案路徑\n */\nexport async function runGeneration(configFile: string): Promise<void> {\n const absoluteConfigPath = resolve(process.cwd(), configFile);\n process.chdir(dirname(absoluteConfigPath));\n\n const unparsedConfig = require(absoluteConfigPath);\n const config = unparsedConfig.default ?? unparsedConfig;\n\n if (!('outputFiles' in config)) {\n console.error('Configuration must include \"outputFiles\" property. Single file output is no longer supported.');\n process.exit(1);\n }\n\n // 清理輸出目錄\n if (config.outputFiles && config.outputFiles.outputDir) {\n cleanOutputDirectory(config.outputFiles.outputDir);\n }\n\n try {\n console.log('Generating multiple outputs...');\n await generateEndpoints(config);\n console.log('Done');\n } catch (err) {\n console.error('Generation failed:', err);\n process.exit(1);\n }\n}\n\n\n/**\n * CLI 主要執行函數\n * 設置 TypeScript 支援、解析命令列參數、驗證設定檔並執行代碼生成\n */\nasync function main(): Promise<void> {\n const meta = require('../../package.json');\n const hasTypeScriptSupport = setupTypeScriptSupport();\n\n program\n .version(meta.version)\n .usage('<path/to/config.js>')\n .parse(process.argv);\n\n const configFile = program.args[0];\n\n if (program.args.length === 0) {\n program.help();\n return;\n }\n\n validateConfigFile(configFile);\n validateTypeScriptSupport(configFile, hasTypeScriptSupport);\n\n await runGeneration(configFile);\n}\n\nmain().catch((err) => {\n console.error('CLI execution failed:', err);\n process.exit(1);\n});","import program from 'commander';\nimport { createRequire } from 'node:module';\nimport { resolve } from 'node:path';\nimport { existsSync, rmSync, readdirSync, statSync, mkdirSync } from 'node:fs';\nimport path from 'node:path';\n\nconst require = createRequire(__filename);\n\n\n\n\n/**\n * 備份 enhanceEndpoints.ts 檔案\n * @param {string} outputDir - 輸出目錄路徑\n * @returns {Map<string, Buffer>} 備份的檔案內容對應\n */\nfunction backupEnhanceEndpoints(outputDir: string): Map<string, Buffer> {\n const backupMap = new Map<string, Buffer>();\n\n if (!existsSync(outputDir)) {\n return backupMap;\n }\n\n function scanDirectory(dir: string): void {\n try {\n const items = readdirSync(dir);\n\n for (const item of items) {\n const itemPath = path.join(dir, item);\n const stat = statSync(itemPath);\n\n if (stat.isDirectory()) {\n scanDirectory(itemPath);\n } else if (item === 'enhanceEndpoints.ts') {\n // 讀取檔案內容到記憶體\n const content = require('node:fs').readFileSync(itemPath);\n backupMap.set(itemPath, content);\n }\n }\n } catch (error) {\n // 忽略掃描錯誤,繼續處理其他目錄\n }\n }\n\n scanDirectory(outputDir);\n return backupMap;\n}\n\n/**\n * 還原 enhanceEndpoints.ts 檔案\n * @param {Map<string, Buffer>} backupMap - 備份檔案內容對應\n */\nfunction restoreEnhanceEndpoints(backupMap: Map<string, Buffer>): void {\n for (const [originalPath, content] of backupMap) {\n try {\n // 確保目錄存在\n const dir = path.dirname(originalPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // 寫入檔案內容\n require('node:fs').writeFileSync(originalPath, content);\n } catch (error) {\n console.warn(`Failed to restore ${originalPath}:`, error);\n }\n }\n}\n\n/**\n * 清理輸出目錄,但保護 enhanceEndpoints.ts 檔案\n * 移除設定檔中指定的 outputDir 目錄及其內容,但會備份並還原 enhanceEndpoints.ts\n * @param {string} outputDir - 要清理的目錄路徑\n */\nexport function cleanOutputDirectory(outputDir: string): void {\n // 安全檢查:避免刪除重要目錄\n const dangerousPaths = ['/', '/usr', '/etc', '/var', '/home', '/Users', '.', '..'];\n const normalizedPath = resolve(outputDir);\n\n if (dangerousPaths.some(path => normalizedPath === resolve(path))) {\n console.error(`Dangerous path detected: ${normalizedPath}. Refusing to delete.`);\n process.exit(1);\n }\n\n if (existsSync(outputDir)) {\n console.log(`Cleaning output directory: ${outputDir}`);\n\n // 1. 備份所有 enhanceEndpoints.ts 檔案\n const backupMap = backupEnhanceEndpoints(outputDir);\n\n // 2. 刪除整個目錄\n rmSync(outputDir, { recursive: true, force: true });\n\n // 3. 還原 enhanceEndpoints.ts 檔案\n if (backupMap.size > 0) {\n restoreEnhanceEndpoints(backupMap);\n console.log(`Protected ${backupMap.size} enhanceEndpoints.ts file(s) from deletion`);\n }\n\n console.log(`Directory cleaned: ${outputDir}`);\n }\n}\n\n\n/**\n * 設置 TypeScript 支援\n * 優先使用 esbuild-runner,其次使用 ts-node\n * @returns {boolean} 是否成功設置 TypeScript 支援\n */\nexport function setupTypeScriptSupport(): boolean {\n try {\n if (require.resolve('esbuild') && require.resolve('esbuild-runner')) {\n require('esbuild-runner/register');\n return true;\n }\n } catch {}\n\n try {\n if (require.resolve('typescript') && require.resolve('ts-node')) {\n (require('ts-node') as typeof import('ts-node')).register({\n transpileOnly: true,\n compilerOptions: {\n target: 'es6',\n module: 'commonjs',\n },\n });\n return true;\n }\n } catch {}\n\n return false;\n}\n\n/**\n * 驗證設定檔案格式是否有效\n * 支援 .js/.ts/.mjs/.mts/.cjs/.cts/.json/.jsonc 格式\n * @param {string} configFile - 設定檔案路徑\n */\nexport function validateConfigFile(configFile: string): void {\n if (!configFile || !/\\.([mc]?(jsx?|tsx?)|jsonc?)?$/.test(configFile)) {\n console.error('Please provide a valid configuration file.');\n program.help();\n }\n}\n\n/**\n * 驗證 TypeScript 設定檔是否有相應的執行環境支援\n * @param {string} configFile - 設定檔案路徑\n * @param {boolean} hasTypeScriptSupport - 是否已設置 TypeScript 支援\n */\nexport function validateTypeScriptSupport(configFile: string, hasTypeScriptSupport: boolean): void {\n if (/\\.[mc]?tsx?$/.test(configFile) && !hasTypeScriptSupport) {\n console.error('Encountered a TypeScript config file, but neither esbuild-runner nor ts-node are installed.');\n process.exit(1);\n }\n}\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';\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 } = {\n groups: [],\n commonTypes: '',\n componentSchema: '',\n doNotModify: '',\n utils: ''\n };\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\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 // 如果沒有任何 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\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 // 寫入 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 * Cache tag types configuration for RTK Query cache invalidation\n * If provided, will import the specified type from the given file in enhanceEndpoints.ts\n * Example: { file: \"@/store/tagTypes\", importName: \"ECacheTagTypes\" }\n */\n cacheTagTypes?: {\n file: string;\n importReturnTypeName: string;\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 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 return {\n operationNames,\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}\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 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 };\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 responseTypeContent = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap);\n if (responseTypeContent.trim() === '') {\n // 如果沒有實際內容,使用 void\n endpointTypes.push(\n `export type ${resTypeName} = void;`,\n ``\n );\n } else {\n // 有實際內容,使用 type 定義\n endpointTypes.push(\n `export type ${resTypeName} = {`,\n responseTypeContent,\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\n/**\n * 生成 Response 類型的內容\n */\nfunction generateResponseTypeContent(endpoint: EndpointInfo, operationDefinitions?: any[], schemaTypeMap: Record<string, string> = {}): string {\n const properties: string[] = [];\n\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 responseProps = parseSchemaProperties(jsonContent.schema, schemaTypeMap);\n properties.push(...responseProps);\n } else {\n properties.push(` // Success response from OpenAPI`);\n properties.push(` data?: any;`);\n }\n }\n }\n\n // 如果沒有響應定義,返回空內容(將由調用方處理為 void)\n if (properties.length === 0) {\n return ''; // 返回空字串,讓調用方決定使用 void\n }\n\n return properties.join('\\n');\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}>, options: GenerationOptions) {\n\n const { groupKey } = options;\n\n // 獲取類型名稱\n const httpClientTypeName = options.httpClient?.importReturnTypeName || options.httpClient?.importName || '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 return ` /** ${info.summary || info.operationName} */\n ${info.operationName}: build.${methodType}<\n ${info.responseTypeName},\n ${argType}\n >({\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 return `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n${apiImport}${httpClientImport}\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 const { groupKey, cacheTagTypes } = options;\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 let importStatements = `/* eslint-disable */\n// [Warning] Generated automatically - do not edit manually\n\n`;\n\n // 如果有 cacheTagTypes 配置,則添加導入\n if (cacheTagTypes) {\n importStatements += `import { ${cacheTagTypes.importReturnTypeName} } from \"${cacheTagTypes.file}\";\\n`;\n }\n\n importStatements += `import 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}"],"mappings":"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","names":["fileURLToPath","getFilename","__filename","init_esm_shims","__esmMin","http_exports","__export","argumentMatches","defaultIsDataResponse","getOperationName","getOverrides","getTags","operationMatches","_getOperationName","code","includeDefault","parsedCode","verb","path","pathItem","patternMatches","pattern","filters","operationName","filter","checkMatch","operationDefinition","argumentDefinition","argumentName","operation","endpointOverrides","override","init_http","__esmMin","init_esm_shims","init_esm_shims","program","createRequire","init_esm_shims","program","createRequire","resolve","existsSync","rmSync","readdirSync","statSync","mkdirSync","path","require","__filename","backupEnhanceEndpoints","outputDir","backupMap","scanDirectory","dir","items","item","itemPath","content","restoreEnhanceEndpoints","originalPath","error","cleanOutputDirectory","dangerousPaths","normalizedPath","setupTypeScriptSupport","validateConfigFile","configFile","validateTypeScriptSupport","hasTypeScriptSupport","dirname","resolve","init_esm_shims","init_esm_shims","path","ts","init_esm_shims","init_esm_shims","capitalize","str","init_esm_shims","fs","path","init_esm_shims","isValidUrl","string","downloadSchemaFile","remoteFile","targetPath","isValidUrl","dir","path","fs","response","content","error","init_esm_shims","init_esm_shims","operationKeys","getOperationDefinitions","v3Doc","path","pathItem","arg","operationKeys","verb","operation","init_esm_shims","SwaggerParser","converter","getV3Doc","spec","httpResolverOptions","doc","init_esm_shims","isQuery","verb","path","overrides","queryMatch","OpenApiService","schemaLocation","httpResolverOptions","doc","getV3Doc","remoteUrl","localPath","downloadSchemaFile","init_esm_shims","camelCase","GroupService","paths","config","groupKeyMatch","outputDir","groupedPaths","acc","path","rawGroupKey","groupKey","result","operationName","operationDefinition","pathGroupKey","init_esm_shims","fs","path","init_esm_shims","path","fs","ensureDirectoryExists","filePath","dirname","FileWriterService","filePath","content","resolvedPath","path","fs","ensureDirectoryExists","error","files","results","result","groupOutputDir","filesToWrite","outputDir","sharedFiles","schema","init_esm_shims","ApiGenerator","OpenApiParserService","v3Doc","options","ApiGenerator","schemaName","schema","filterEndpoints","operationMatches","getOperationDefinitions","init_esm_shims","generateCommonTypesFile","init_esm_shims","ts","toPascalCase","name","renameIdentifier","node","oldName","newName","context","rootNode","visit","generateComponentSchemaFile","interfaces","printer","resultFile","renamedInterfaces","typeNameMapping","originalName","pascalCaseName","renamedNode","printed","init_esm_shims","generateDoNotModifyFile","init_esm_shims","ts","init_esm_shims","init_http","supportDeepObjects","EndpointInfoExtractor","options","operationDefinitions","operationDefinition","verb","path","operation","operationNameSuffix","argSuffix","responseSuffix","queryMatch","endpointOverrides","operationName","getOperationName","finalOperationName","capitalize","argTypeName","responseTypeName","isQuery","getOverrides","queryKeyName","summary","queryParams","pathParams","isVoidArg","hasRequestBody","contentType","pathItem","operationParameters","pathItemParameters","pp","op","allParameters","param","parameters","content","contentTypes","init_esm_shims","toPascalCase","name","generateTypesFile","endpointInfos","_options","schemaInterfaces","operationDefinitions","schemaTypeMap","actualTypeName","openApiName","importStatement","typeDefinitions","endpointTypes","endpoint","reqTypeName","resTypeName","requestTypeContent","generateRequestTypeContent","responseTypeContent","generateResponseTypeContent","properties","param","optional","paramType","getTypeFromParameter","operationDef","op","content","jsonContent","formContent","bodyType","getTypeFromSchema","firstContent","successResponse","responseProps","parseSchemaProperties","schema","required","propName","propSchema","propType","quotedPropName","indentLevel","refPath","originalTypeName","baseType","val","itemType","entries","nextIndent","currentIndent","props","key","type","quotedKey","init_esm_shims","generateRtkQueryFile","endpointInfos","options","groupKey","httpClientTypeName","endpoints","info","methodType","argType","urlPath","param","paramsSection","typeImports","type","typeImportStatement","apiImport","httpClientImport","capitalizedOperationName","regularHook","lazyHook","init_esm_shims","generateRtkEnhanceEndpointsFile","endpointInfos","options","groupKey","cacheTagTypes","endpointConfigs","info","importStatements","ApiCodeGenerator","parserService","options","EndpointInfoExtractor","operationDefinitions","endpointInfos","typesContent","rtkQueryContent","generateRtkQueryFile","enhanceEndpointsContent","generateRtkEnhanceEndpointsFile","indexContent","info","generatorOptions","schemaInterfaces","curr","alias","ts","name","generateTypesFile","groupKey","init_esm_shims","generateUtilsFile","UnifiedCodeGenerator","OpenApiService","GroupService","FileWriterService","options","OpenApiParserService","apiGen","curr","alias","ts","name","paths","groupInfos","groupInfo","groupContent","error","generateCommonTypesFile","generateComponentSchemaFile","generateDoNotModifyFile","generateUtilsFile","results","errors","generatedGroups","group","groupOutputDir","path","groupResults","outputDir","sharedResults","schemaResults","mainIndexContent","mainIndexResult","outputFiles","commonConfig","groupOptions","ApiCodeGenerator","groupKey","generateEndpoints","options","result","UnifiedCodeGenerator","require","createRequire","__filename","runGeneration","configFile","absoluteConfigPath","resolve","dirname","unparsedConfig","config","cleanOutputDirectory","generateEndpoints","err","main","meta","hasTypeScriptSupport","setupTypeScriptSupport","program","validateConfigFile","validateTypeScriptSupport"]}
|
package/lib/index.d.mts
CHANGED
|
@@ -53,6 +53,15 @@ interface CommonOptions {
|
|
|
53
53
|
file: string;
|
|
54
54
|
importReturnTypeName: string;
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Cache tag types configuration for RTK Query cache invalidation
|
|
58
|
+
* If provided, will import the specified type from the given file in enhanceEndpoints.ts
|
|
59
|
+
* Example: { file: "@/store/tagTypes", importName: "ECacheTagTypes" }
|
|
60
|
+
*/
|
|
61
|
+
cacheTagTypes?: {
|
|
62
|
+
file: string;
|
|
63
|
+
importReturnTypeName: string;
|
|
64
|
+
};
|
|
56
65
|
/**
|
|
57
66
|
* defaults to "enhancedApi"
|
|
58
67
|
*/
|
package/lib/index.d.ts
CHANGED
|
@@ -53,6 +53,15 @@ interface CommonOptions {
|
|
|
53
53
|
file: string;
|
|
54
54
|
importReturnTypeName: string;
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Cache tag types configuration for RTK Query cache invalidation
|
|
58
|
+
* If provided, will import the specified type from the given file in enhanceEndpoints.ts
|
|
59
|
+
* Example: { file: "@/store/tagTypes", importName: "ECacheTagTypes" }
|
|
60
|
+
*/
|
|
61
|
+
cacheTagTypes?: {
|
|
62
|
+
file: string;
|
|
63
|
+
importReturnTypeName: string;
|
|
64
|
+
};
|
|
56
65
|
/**
|
|
57
66
|
* defaults to "enhancedApi"
|
|
58
67
|
*/
|