anl 26.108.0 → 26.109.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ar.md +2 -2
- package/README.es.md +1 -1
- package/README.fr.md +1 -1
- package/README.zh.md +36 -36
- package/lib/package.json.js +1 -1
- package/lib/src/build-type/core/components.js +1 -1
- package/package.json +1 -1
package/README.ar.md
CHANGED
|
@@ -160,7 +160,7 @@ $ anl type
|
|
|
160
160
|
},
|
|
161
161
|
"swaggerConfig": [
|
|
162
162
|
{
|
|
163
|
-
"url": "https://generator3.swagger.io/
|
|
163
|
+
"url": "https://generator3.swagger.io/openapi.json",
|
|
164
164
|
"apiListFileName": "op.ts",
|
|
165
165
|
"modulePrefix": "/forward",
|
|
166
166
|
"dataLevel": "serve",
|
|
@@ -168,7 +168,7 @@ $ anl type
|
|
|
168
168
|
"headers": {},
|
|
169
169
|
"includeInterface": [
|
|
170
170
|
{
|
|
171
|
-
"path": "/
|
|
171
|
+
"path": "/generate",
|
|
172
172
|
"method": "post"
|
|
173
173
|
}
|
|
174
174
|
]
|
package/README.es.md
CHANGED
package/README.fr.md
CHANGED
package/README.zh.md
CHANGED
|
@@ -133,8 +133,8 @@ $ anl type
|
|
|
133
133
|
"dataLevel": "data"
|
|
134
134
|
}
|
|
135
135
|
],
|
|
136
|
-
"excludeInterface":[]
|
|
137
|
-
}
|
|
136
|
+
"excludeInterface": []
|
|
137
|
+
}
|
|
138
138
|
}
|
|
139
139
|
```
|
|
140
140
|
|
|
@@ -167,7 +167,7 @@ $ anl type
|
|
|
167
167
|
"headers": {},
|
|
168
168
|
"includeInterface": [
|
|
169
169
|
{
|
|
170
|
-
"path": "/
|
|
170
|
+
"path": "/generate",
|
|
171
171
|
"method": "post",
|
|
172
172
|
"dataLevel": "axios"
|
|
173
173
|
}
|
|
@@ -187,39 +187,39 @@ $ anl type
|
|
|
187
187
|
|
|
188
188
|
#### 配置项说明
|
|
189
189
|
|
|
190
|
-
| 配置项 | 类型
|
|
191
|
-
| ---------------------------------- |
|
|
192
|
-
| saveTypeFolderPath | string
|
|
193
|
-
| saveApiListFolderPath | string
|
|
194
|
-
| saveEnumFolderPath | string
|
|
195
|
-
| importEnumPath | string
|
|
196
|
-
| swaggerJsonUrl | string
|
|
197
|
-
| swaggerConfig | object \| Array<object>
|
|
198
|
-
| swaggerConfig[].url | string
|
|
199
|
-
| swaggerConfig[].publicPrefix | string
|
|
200
|
-
| swaggerConfig[].modulePrefix | string
|
|
201
|
-
| swaggerConfig[].apiListFileName | string
|
|
202
|
-
| swaggerConfig[].headers | object
|
|
203
|
-
| swaggerConfig[].dataLevel | 'data' \| 'serve' \| 'axios'
|
|
204
|
-
| swaggerConfig[].parameterSeparator | '$' \| '\_'
|
|
205
|
-
| swaggerConfig[].includeInterface | Array<{path: string, method: string, dataLevel?: 'data' \| 'serve' \| 'axios'}> | 否 | 该服务器包含的接口列表。每个接口可单独配置 `dataLevel`,具有最高优先级。若未设置,使用全局 `includeInterface` 配置
|
|
206
|
-
| swaggerConfig[].excludeInterface | Array<{path: string, method: string}>
|
|
207
|
-
| requestMethodsImportPath | string
|
|
208
|
-
| dataLevel | 'data' \| 'serve' \| 'axios'
|
|
209
|
-
| formatting | object
|
|
210
|
-
| formatting.indentation | string
|
|
211
|
-
| formatting.lineEnding | string
|
|
212
|
-
| headers | object
|
|
213
|
-
| includeInterface | Array<{path: string, method: string}>
|
|
214
|
-
| excludeInterface | Array<{path: string, method: string}>
|
|
215
|
-
| publicPrefix | string
|
|
216
|
-
| modulePrefix | string
|
|
217
|
-
| apiListFileName | string
|
|
218
|
-
| enmuConfig | object
|
|
219
|
-
| enmuConfig.erasableSyntaxOnly | boolean
|
|
220
|
-
| enmuConfig.varnames | string
|
|
221
|
-
| enmuConfig.comment | string
|
|
222
|
-
| parameterSeparator | '$' \| '\_'
|
|
190
|
+
| 配置项 | 类型 | 必填 | 说明 |
|
|
191
|
+
| ---------------------------------- | ------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
192
|
+
| saveTypeFolderPath | string | 是 | 类型定义文件保存路径 |
|
|
193
|
+
| saveApiListFolderPath | string | 是 | API 请求函数文件保存路径 |
|
|
194
|
+
| saveEnumFolderPath | string | 是 | 枚举数据文件保存路径 |
|
|
195
|
+
| importEnumPath | string | 是 | 枚举导入路径(apps/types/models/\*.ts 中 enum 文件的引用的路径) |
|
|
196
|
+
| swaggerJsonUrl | string | 否 | Swagger JSON 文档地址(已迁移到 `swaggerConfig.url`,保留用于兼容旧版配置)**后面迭代版本会删除该字段** |
|
|
197
|
+
| swaggerConfig | object \| Array<object> | 否 | Swagger 服务器配置。单个服务器可直接填写对象,多个服务器使用数组。每个服务器可配置 `url`、`publicPrefix`、`modulePrefix`、`apiListFileName`、`headers`、`dataLevel`、`parameterSeparator`、`includeInterface`、`excludeInterface`<br />这个字段 对应 单 Swagger 服务器配置 与 多 Swagger 服务器配置 示例,请向上滚动查看 |
|
|
198
|
+
| swaggerConfig[].url | string | 是 | Swagger JSON 文档地址 |
|
|
199
|
+
| swaggerConfig[].publicPrefix | string | 否 | url path 上的公共前缀,例如:api/users、api/users/{id} ,api 就是公共前缀 |
|
|
200
|
+
| swaggerConfig[].modulePrefix | string | 否 | 请求路径前缀(可以理解为模块名),会自动添加到每个 API 请求路径前面。<br />例如:`modulePrefix: "/forward"` 时,<br />`/publicPrefix/modulePrefix/user` , 会变成 `/publicPrefix/forward/user` |
|
|
201
|
+
| swaggerConfig[].apiListFileName | string | 否 | API 列表文件名,默认为 `index.ts`。多个服务器时,每个服务器的API 列表文件名必须唯一 |
|
|
202
|
+
| swaggerConfig[].headers | object | 否 | 该服务器的请求头配置 |
|
|
203
|
+
| swaggerConfig[].dataLevel | 'data' \| 'serve' \| 'axios' | 否 | 该服务器的接口返回数据层级。若未设置,使用全局 `dataLevel` 配置 |
|
|
204
|
+
| swaggerConfig[].parameterSeparator | '$' \| '\_' | 否 | 该服务器生成 API 名称和类型名称时使用的分隔符。若未设置,使用全局 `parameterSeparator` 配置 |
|
|
205
|
+
| swaggerConfig[].includeInterface | Array<{path: string, method: string, dataLevel?: 'data' \| 'serve' \| 'axios'}> | 否 | 该服务器包含的接口列表。每个接口可单独配置 `dataLevel`,具有最高优先级。若未设置,使用全局 `includeInterface` 配置 |
|
|
206
|
+
| swaggerConfig[].excludeInterface | Array<{path: string, method: string}> | 否 | 该服务器排除的接口列表。若未设置,使用全局 `excludeInterface` 配置 |
|
|
207
|
+
| requestMethodsImportPath | string | 是 | 请求方法导入路径 |
|
|
208
|
+
| dataLevel | 'data' \| 'serve' \| 'axios' | 否 | 全局接口返回数据层级配置,默认值:`'serve'`。各服务器可单独配置覆盖 |
|
|
209
|
+
| formatting | object | 否 | 代码格式化配置 |
|
|
210
|
+
| formatting.indentation | string | 否 | 代码缩进字符,例如:`"\t"` 或 `" "`(两个空格) |
|
|
211
|
+
| formatting.lineEnding | string | 否 | 换行符,例如:`"\n"` (LF) 或 `"\r\n"` (CRLF) |
|
|
212
|
+
| headers | object | 否 | 全局请求头配置(已迁移到 `swaggerConfig`,保留用于兼容旧版配置) |
|
|
213
|
+
| includeInterface | Array<{path: string, method: string}> | 否 | 全局包含的接口:`saveApiListFolderPath`指定的接口列表文件,只会包含列表中的接口,与 `excludeInterface` 字段互斥。各服务器可单独配置覆盖 |
|
|
214
|
+
| excludeInterface | Array<{path: string, method: string}> | 否 | 全局排除的接口: `saveApiListFolderPath` 指定的接口列表文本,不存在该列表中的接口,与 `includeInterface` 互斥。各服务器可单独配置覆盖 |
|
|
215
|
+
| publicPrefix | string | 否 | 全局 url path 上的公共前缀(已迁移到 `swaggerConfig`,保留用于兼容旧版配置) |
|
|
216
|
+
| modulePrefix | string | 否 | 全局请求路径前缀(各服务器可单独配置覆盖) |
|
|
217
|
+
| apiListFileName | string | 否 | 全局 API 列表文件名,默认为 `index.ts`(已迁移到 `swaggerConfig`,保留用于兼容旧版配置) |
|
|
218
|
+
| enmuConfig | object | 是 | 枚举配置对象 |
|
|
219
|
+
| enmuConfig.erasableSyntaxOnly | boolean | 是 | 与 tsconfig.json 的 `compilerOptions.erasableSyntaxOnly` 选项保持一致。为 `true` 时,生成 const 对象而非 enum(仅类型语法)。默认值:`false` |
|
|
220
|
+
| enmuConfig.varnames | string | 否 | Swagger schema 中自定义枚举成员名所在的字段名。默认值:`enum-varnames`。 |
|
|
221
|
+
| enmuConfig.comment | string | 否 | Swagger schema 中自定义枚举描述所在的字段名(用于生成注释)。默认值:`enum-descriptions`。 |
|
|
222
|
+
| parameterSeparator | '$' \| '\_' | 否 | 全局生成 API 名称和类型名称时,路径段和参数之间使用的分隔符。例如,`/users/{userId}/posts` 使用分隔符 `'_'` 会生成 `users_userId_posts_GET`。默认值:`'_'`。各服务器可单独配置覆盖 |
|
|
223
223
|
|
|
224
224
|
#### 配置项与生成的文件对应关系
|
|
225
225
|
|
package/lib/package.json.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e="26.
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e="26.109.0",i="FE command line tool",t="bin/an-cli.js",s={registry:"https://registry.npmjs.org"},o={dev:"rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript -w",build:"rimraf lib && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",pub:"bash publish.sh",ts:"tsc ./src/int.ts --noEmit --watch",blink:"npm run build && npm link","sync-docs":"node scripts/sync-docs.js"},r={anl:"bin/an-cli.js"},n="Gleason <bianliuzhu@gmail.com>",l={"@commitlint/cli":"^17.4.3","@commitlint/config-conventional":"^17.4.3","@rollup/plugin-commonjs":"^21.0.1","@rollup/plugin-json":"^4.1.0","@rollup/plugin-node-resolve":"^13.1.3","@rollup/plugin-typescript":"^8.3.0","@types/inquirer":"^9.0.7","@types/shelljs":"^0.8.11","@typescript-eslint/eslint-plugin":"^5.52.0","@typescript-eslint/parser":"^5.52.0","cross-env":"^7.0.3",eslint:"^8.7.0",husky:"^8.0.3","openapi-types":"^12.1.3",prettier:"^3.3.2",rimraf:"^5.0.7",rollup:"^2.64.0","rollup-plugin-cleandir":"^2.0.0","rollup-plugin-copy":"^3.5.0","rollup-plugin-terser":"^7.0.2",typescript:"^4.5.4"},p={"app-root-path":"^3.1.0",cac:"^6.7.12",chalk:"4.*","clear-console":"^1.1.0",commander:"14.0.1",figures:"^6.1.0",inquirer:"^10.1.8","log-symbols":"^5.1.0",ora:"5.*","progress-estimator":"^0.3.0",shelljs:"^0.8.5"},c=["cli","command-line","frontend","typescript","type-generation","code-generator","swagger","openapi","api","rest-api","eslint","stylelint","prettier","commitlint","linter","formatter","react","vue","git","gitflow","developer-tools","automation","scaffolding"],a=["package.json","README.md","lib","template"],u={type:"git",url:"git+https://github.com/bianliuzhu/an-cli.git"},g="commonjs",m={name:"anl",version:e,description:i,main:t,publishConfig:s,scripts:o,bin:r,author:n,license:"ISC",devDependencies:l,dependencies:p,keywords:c,files:a,repository:u,type:g};exports.author=n,exports.bin=r,exports.default=m,exports.dependencies=p,exports.description=i,exports.devDependencies=l,exports.files=a,exports.keywords=c,exports.license="ISC",exports.main=t,exports.name="anl",exports.publishConfig=s,exports.repository=u,exports.scripts=o,exports.type=g,exports.version=e;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("fs"),t=require("../../utils/index.js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i=n(e);exports.default=class{config;schemas={};enumsMap=new Map;schemasMap=new Map;defaultReturn={headerRef:"",renderStr:"",comment:"",typeName:""};requiredFieldS=[];appendMode;constructor(e,t,n){this.schemas=e,this.config=t,this.appendMode=n?.appendMode??!1,this.config.formatting&&(this.config.formatting.indentation=this.config.formatting.indentation??"\t")}handleEnum(e,n){const i=n.charAt(0).toUpperCase()+n.slice(1);if(t.isValidJSON(e.example)){const t=this.convertJsonToEnumString(e.example,i),r=this.getEnumTypeName(i);return{headerRef:"",renderStr:`${this.config.formatting?.indentation}${n}${this.requiredFieldS.includes(n)?"":"?"}: ${r}${this.nullable(e.nullable)};`,comment:t}}const r=this.typeNameToFileName(i),s=this.parseEnum(e,i);return s&&!this.enumsMap.has(r)?(this.enumsMap.set(r,{fileName:r,content:s.renderStr}),{headerRef:"",renderStr:""}):null}nullable(e){return""+(e?" | null":"")}getEnumTypeName(e){return this.config.enmuConfig.erasableSyntaxOnly?`${e}Type`:e}fieldComment(e){const{description:t}=e;if(t){return["\t","/**","\n",`\t * ${t}`,"\n","\t */"].join("")}return""}typeNameToFileName(e){return e.replace(/_/g,"-").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase().replace(/-+/g,"-")}nameTheHumpCenterStroke(e){const t=e.replace("#/components/schemas/",""),n={typeName:t,fileName:this.typeNameToFileName(t),dataType:""};if(this.schemas){const e=this.schemas[t];e.enum?n.dataType="enum":n.dataType=e.type}return n}parseRef(e){if(!e?.trim())return{headerRefStr:"",typeName:"",dataType:""};const{fileName:t,typeName:n,dataType:i=""}=this.nameTheHumpCenterStroke(e);let r;if("enum"===i){r=`import type { ${this.getEnumTypeName(n)} } from '${this.config.importEnumPath}';`}else r=`import type { ${n} } from './${t}';`;return{headerRefStr:r,typeName:n,dataType:i}}parseObject(e,t){let n="",i="";if("object"===e.type){const r=e;if("object"==typeof r.additionalProperties){const e=this.parseArray(r.additionalProperties,t)??this.defaultReturn;n=e?.headerRef??"",i=e?.renderStr??""}i="boolean"==typeof r.additionalProperties?`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: Record<string, unknown>${this.nullable(r.nullable)};`:`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: ${e.type}${this.nullable(e.nullable)};`}return{headerRef:n,renderStr:i}}parseArray(e,n){const i=e,{items:r={},nullable:s,example:a}=i,o=r?.$ref;if(o){const{headerRefStr:e,typeName:i,dataType:r}=this.parseRef(o);if("enum"===r&&t.isValidJSON(a)){const e=this.typeNameToFileName(i),t=this.convertJsonToEnumString(a,i);this.enumsMap.set(e,{fileName:e,content:t})}const u="enum"===r?this.getEnumTypeName(i):i;return{headerRef:e,renderStr:`${this.config.formatting?.indentation}${n}${this.requiredFieldS.includes(n)?"":"?"}: Array<${u}>${this.nullable(s)};`,typeName:u}}const u=r?.type;let l="integer"===u?"number":u;return"object"===u&&(l="Record<string, unknown>"),{headerRef:"",renderStr:`${this.config.formatting?.indentation}${n}${this.requiredFieldS.includes(n)?"":"?"}: Array<${l}>${this.nullable(s)};`,typeName:l}}parseBoolean(e,t){return"boolean"===e.type?`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: boolean${this.nullable(e.nullable)};`:""}extractEnumMetadata(e){const t={},{enmuConfig:n}=this.config,i=e;if(n?.varnames){const e=i[n.varnames];Array.isArray(e)&&(t.customNames=e.map(e=>`${e}`))}if(n?.comment){const e=i[n.comment];if(e&&"object"==typeof e&&!Array.isArray(e)){const n={};Object.entries(e).forEach(([e,t])=>{"string"==typeof t&&(n[e]=t)}),Object.keys(n).length&&(t.descriptionMap=n)}}return t}resolveEnumMemberName(e,t,n){const{customNames:i,isNumericEnum:r,treatStringAsNumeric:s}=n,a=i?.[t];return"string"==typeof a&&a.trim()?a:r||"string"==typeof e&&s?`NUMBER_${e}`:"string"==typeof e&&e?e.toUpperCase():`ENUM_${t}`}parseEnum(e,t){if(!Array.isArray(e.enum))return null;const n=Boolean(e.type&&["integer","number"].includes(e.type)),i=e.enum,r="string"===e.type&&i.every(e=>"string"==typeof e&&!isNaN(Number(e))),{customNames:s,descriptionMap:a}=this.extractEnumMetadata(e),o=this.config.enmuConfig.erasableSyntaxOnly,u=i.map((e,t)=>{const i=this.resolveEnumMemberName(e,t,{customNames:s,isNumericEnum:n,treatStringAsNumeric:r}),u=n?`${e}`:`'${String(e)}'`,l=o?`${i}: ${u},`:`${i} = ${u},`,c=a?.[String(e)];return c?[`${this.config.formatting?.indentation}/** ${c} */`,`${this.config.formatting?.indentation}${l}`].join("\n"):`${this.config.formatting?.indentation}${l}`});return u.length?o?{headerRef:"",renderStr:[`export const ${t} = {`,...u,"} as const;","",`export type ${this.getEnumTypeName(t)} = typeof ${t}[keyof typeof ${t}];`].join("\n")}:{headerRef:"",renderStr:[`export enum ${t} {`,...u,"}"].join("\n")}:null}parseInteger(e,t){if(Array.isArray(e.enum)){const n=t.charAt(0).toUpperCase()+t.slice(1);return this.parseEnum(e,n)?.renderStr??""}return`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: number${this.nullable(e.nullable)};`}parseNumber(e,t){if("number"!==e.type)return null;if(e.enum){const n=this.handleEnum(e,t);if(n)return n}return{headerRef:"",renderStr:`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: number${this.nullable(e.nullable)};`}}convertJsonToEnumString(e,t){try{const n=JSON.parse(e);if(this.config.enmuConfig.erasableSyntaxOnly){return`export const ${t} = {\n${Object.entries(n).map(([e,t])=>`${this.config.formatting?.indentation}${e}: '${t}'`).join(",\n")}\n} as const;\n\nexport type ${this.getEnumTypeName(t)} = typeof ${t}[keyof typeof ${t}];`}return`export enum ${t} {\n${Object.entries(n).map(([e,t])=>`${this.config.formatting?.indentation}${e} = '${t}'`).join(",\n")}\n}`}catch(e){return console.error("JSON 解析失败:",e),""}}parseString(e,t){if("string"!==e.type)return null;if(e.enum){const n=this.handleEnum(e,t);if(n)return n}return{headerRef:"",renderStr:`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: string${this.nullable(e.nullable)};`}}parseProperties(e,n){const i=[],r=[];for(const s in e){const a=e[s];if(a?.$ref){const{headerRefStr:e,typeName:o,dataType:u}=this.parseRef(a.$ref);r.includes(e)||o===n||r.push(e);const l=a,c=this.fieldComment(l);""!==c&&i.push(c);const m="enum"===u?this.getEnumTypeName(o):o;i.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${m};`);const h=a.example;if("enum"===u&&h&&t.isValidJSON(h)){const e=this.typeNameToFileName(o),t=this.convertJsonToEnumString(h,o);this.enumsMap.set(e,{fileName:e,content:t})}continue}if("allOf"in a){const e=a.allOf?.[0];if(e?.$ref){const{headerRefStr:t,typeName:o,dataType:u}=this.parseRef(e.$ref),l="enum"===u?this.getEnumTypeName(o):o;r.includes(t)||o===n||r.push(t);const c=a,m=this.fieldComment(c);""!==m&&i.push(m),i.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${l}${this.nullable(a.nullable)};`);continue}}const o=a,u=this.fieldComment(o);switch(""!==u&&i.push(u),o.type){case"array":{const e=this.parseArray(o,s)??this.defaultReturn;i.push(e?.renderStr??""),r.includes(e.headerRef)||n===e.typeName||r.push(e.headerRef)}break;case"boolean":i.push(this.parseBoolean(o,s));break;case"integer":i.push(this.parseInteger(o,s));break;case"number":{const e=this.parseNumber(o,s);e&&(e.headerRef&&!r.includes(e.headerRef)&&r.push(e.headerRef),i.push(e.renderStr))}break;case"string":if(o.enum){const e=s.charAt(0).toUpperCase()+s.slice(1);if(o.example&&t.isValidJSON(o.example)){const t=this.getEnumTypeName(e),n=`import type { ${t} } from '${this.config.importEnumPath}';`;r.includes(n)||r.push(n);const a=this.typeNameToFileName(e);if(!this.enumsMap.has(a)){const t=this.convertJsonToEnumString(o.example,e);this.enumsMap.set(a,{fileName:a,content:t})}i.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${t}${this.nullable(o.nullable)};`)}else{const t=this.parseEnum(o,e);if(t?.renderStr){const n=this.getEnumTypeName(e),a=`import type { ${n} } from '${this.config.importEnumPath}';`;r.includes(a)||r.push(a);const u=this.typeNameToFileName(e);this.enumsMap.has(u)||this.enumsMap.set(u,{fileName:u,content:t.renderStr}),i.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${n}${this.nullable(o.nullable)};`)}}}else o.format&&"binary"===o.format?i.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: File${this.nullable(o.nullable)};`):i.push(this.parseString(o,s)?.renderStr??"");break;case"object":{const{headerRef:e,renderStr:t}=this.parseObject(o,s)??this.defaultReturn;i.push(t),r.includes(e)||r.push(e)}}}const s=[`export interface ${n} {`,...i,"}"];if(r.length>0){const e=r.filter(e=>""!==e);e.length>0&&e.push(""),s.unshift(...e)}const a=s.join("\n");return{headerRef:r.join("\n"),renderStr:a}}async generateContent(e,t){if("items"in e)return console.warn(`数组类型未处理: ${t}`,e.items),"";switch(e.type){case"boolean":return this.parseBoolean(e,t);case"integer":return this.parseInteger(e,t);case"number":{const n=this.parseNumber(e,t);return n?.renderStr??""}case"object":{const n=this.parseProperties(e.properties,t);return n?.renderStr??""}case"string":{const n=this.parseString(e,t);return n?.renderStr??""}default:return""}}async parseData(){try{if(!this.schemas)return void console.warn("schemas 为空");for(const[e,t]of Object.entries(this.schemas)){if("$ref"in t){console.warn(`跳过 ReferenceObject: ${e}`);continue}const n="type"in t?t:null;if(!n?.type){console.warn(`无效的 schema 对象: ${e}`);continue}this.requiredFieldS=t.required??[];const i=this.typeNameToFileName(e),r=await this.generateContent(n,e);if(r){(r.includes("export enum ")||r.includes("export const ")&&r.includes("as const"))&&!this.enumsMap.has(i)?this.enumsMap.set(i,{fileName:i,content:r}):this.schemasMap.set(e,{fileName:i,content:r})}}}catch(e){throw console.error("解析过程出错:",e),e}}async writeEnums(){const e=[],n=[];for(const[,i]of this.enumsMap){const r=async({fileName:e,content:i})=>{n.push(`export * from './${e}';`);const r=`${this.config.saveEnumFolderPath}/${e}.ts`;await t.writeFileRecursive(r,i),t.log.info(`${r.padEnd(80)} - Write done!`)};e.push(r(i))}await Promise.all(e),await this.writeIndexFile(`${this.config.saveEnumFolderPath}/index.ts`,n),t.log.success("Enums write done!")}async writeFile(){const e=[],n=[],i=`${this.config.saveTypeFolderPath}/models/`;for(const[,r]of this.schemasMap){const s=async({fileName:e,content:r})=>{n.push(`export * from './${e}';`);const s=`${i}${e}.ts`;await t.writeFileRecursive(s,r),t.log.info(`${s.padEnd(80)} - Write done!`)};e.push(s(r))}await Promise.all(e),await this.writeIndexFile(`${i}index.ts`,n),t.log.success("Component parse & write done!")}async handle(){await this.parseData(),await this.writeFile(),await this.writeEnums()}async writeIndexFile(e,n){const r=n.filter(Boolean);if(!r.length)return;let s=[];if(this.appendMode)try{s=(await i.default.promises.readFile(e,"utf8")).split("\n").filter(e=>""!==e.trim())}catch{s=[]}const a=new Set(s),o=[...s,...r.filter(e=>!a.has(e))].join("\n");await t.writeFileRecursive(e,o)}};
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("fs"),t=require("../../utils/index.js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(e);exports.default=class{config;schemas={};enumsMap=new Map;schemasMap=new Map;defaultReturn={headerRef:"",renderStr:"",comment:"",typeName:""};requiredFieldS=[];appendMode;constructor(e,t,n){this.schemas=e,this.config=t,this.appendMode=n?.appendMode??!1,this.config.formatting&&(this.config.formatting.indentation=this.config.formatting.indentation??"\t")}handleEnum(e,n){const r=n.charAt(0).toUpperCase()+n.slice(1);if(t.isValidJSON(e.example)){const t=this.convertJsonToEnumString(e.example,r),i=this.getEnumTypeName(r);return{headerRef:"",renderStr:`${this.config.formatting?.indentation}${n}${this.requiredFieldS.includes(n)?"":"?"}: ${i}${this.nullable(e.nullable)};`,comment:t}}const i=this.typeNameToFileName(r),s=this.parseEnum(e,r);return s&&!this.enumsMap.has(i)?(this.enumsMap.set(i,{fileName:i,content:s.renderStr}),{headerRef:"",renderStr:""}):null}nullable(e){return""+(e?" | null":"")}getEnumTypeName(e){return this.config.enmuConfig.erasableSyntaxOnly?`${e}Type`:e}fieldComment(e){const{description:t}=e;if(t){return["\t","/**","\n",`\t * ${t}`,"\n","\t */"].join("")}return""}typeNameToFileName(e){return e.replace(/_/g,"-").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase().replace(/-+/g,"-")}nameTheHumpCenterStroke(e){const t=e.replace("#/components/schemas/",""),n={typeName:t,fileName:this.typeNameToFileName(t),dataType:""};if(this.schemas){const e=this.schemas[t];e.enum?n.dataType="enum":n.dataType=e.type}return n}parseRef(e){if(!e?.trim())return{headerRefStr:"",typeName:"",dataType:""};const{fileName:t,typeName:n,dataType:r=""}=this.nameTheHumpCenterStroke(e);let i;if("enum"===r){i=`import type { ${this.getEnumTypeName(n)} } from '${this.config.importEnumPath}';`}else i=`import type { ${n} } from './${t}';`;return{headerRefStr:i,typeName:n,dataType:r}}parseObject(e,t){let n="",r="";if("object"===e.type){const i=e;if("object"==typeof i.additionalProperties){const e=this.parseArray(i.additionalProperties,t)??this.defaultReturn;n=e?.headerRef??"",r=e?.renderStr??""}r="boolean"==typeof i.additionalProperties?`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: Record<string, unknown>${this.nullable(i.nullable)};`:`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: ${e.type}${this.nullable(e.nullable)};`}return{headerRef:n,renderStr:r}}parseArray(e,n){const r=e,{items:i={},nullable:s,example:a}=r,o=i?.$ref;if(o){const{headerRefStr:e,typeName:r,dataType:i}=this.parseRef(o);if("enum"===i&&t.isValidJSON(a)){const e=this.typeNameToFileName(r),t=this.convertJsonToEnumString(a,r);this.enumsMap.set(e,{fileName:e,content:t})}const c="enum"===i?this.getEnumTypeName(r):r;return{headerRef:e,renderStr:`${this.config.formatting?.indentation}${n}${this.requiredFieldS.includes(n)?"":"?"}: Array<${c}>${this.nullable(s)};`,typeName:c}}const c=i?.type;let u="integer"===c?"number":c;return"object"===c&&(u="Record<string, unknown>"),{headerRef:"",renderStr:`${this.config.formatting?.indentation}${n}${this.requiredFieldS.includes(n)?"":"?"}: Array<${u}>${this.nullable(s)};`,typeName:u}}parseBoolean(e,t){return"boolean"===e.type?`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: boolean${this.nullable(e.nullable)};`:""}extractEnumMetadata(e){const t={},{enmuConfig:n}=this.config,r=e;if(n?.varnames){const e=r[n.varnames];Array.isArray(e)&&(t.customNames=e.map(e=>`${e}`))}if(n?.comment){const e=r[n.comment];if(e&&"object"==typeof e&&!Array.isArray(e)){const n={};Object.entries(e).forEach(([e,t])=>{"string"==typeof t&&(n[e]=t)}),Object.keys(n).length&&(t.descriptionMap=n)}}return t}resolveEnumMemberName(e,t,n){const{customNames:r,isNumericEnum:i,treatStringAsNumeric:s}=n,a=r?.[t];return"string"==typeof a&&a.trim()?a:i||"string"==typeof e&&s?`NUMBER_${e}`:"string"==typeof e&&e?e.toUpperCase():`ENUM_${t}`}parseEnum(e,t){if(!Array.isArray(e.enum))return null;const n=Boolean(e.type&&["integer","number"].includes(e.type)),r=e.enum,i="string"===e.type&&r.every(e=>"string"==typeof e&&!isNaN(Number(e))),{customNames:s,descriptionMap:a}=this.extractEnumMetadata(e),o=this.config.enmuConfig.erasableSyntaxOnly,c=r.map((e,t)=>{const r=this.resolveEnumMemberName(e,t,{customNames:s,isNumericEnum:n,treatStringAsNumeric:i}),c=n?`${e}`:`'${String(e)}'`,u=o?`${r}: ${c},`:`${r} = ${c},`,m=a?.[String(e)];return m?[`${this.config.formatting?.indentation}/** ${m} */`,`${this.config.formatting?.indentation}${u}`].join("\n"):`${this.config.formatting?.indentation}${u}`});return c.length?o?{headerRef:"",renderStr:[`export const ${t} = {`,...c,"} as const;","",`export type ${this.getEnumTypeName(t)} = typeof ${t}[keyof typeof ${t}];`].join("\n")}:{headerRef:"",renderStr:[`export enum ${t} {`,...c,"}"].join("\n")}:null}parseInteger(e,t){if(Array.isArray(e.enum)){const n=t.charAt(0).toUpperCase()+t.slice(1);return this.parseEnum(e,n)?.renderStr??""}return`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: number${this.nullable(e.nullable)};`}parseNumber(e,t){if("number"!==e.type)return null;if(e.enum){const n=this.handleEnum(e,t);if(n)return n}return{headerRef:"",renderStr:`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: number${this.nullable(e.nullable)};`}}convertJsonToEnumString(e,t){try{const n=JSON.parse(e);if(this.config.enmuConfig.erasableSyntaxOnly){return`export const ${t} = {\n${Object.entries(n).map(([e,t])=>`${this.config.formatting?.indentation}${e}: '${t}'`).join(",\n")}\n} as const;\n\nexport type ${this.getEnumTypeName(t)} = typeof ${t}[keyof typeof ${t}];`}return`export enum ${t} {\n${Object.entries(n).map(([e,t])=>`${this.config.formatting?.indentation}${e} = '${t}'`).join(",\n")}\n}`}catch(e){return console.error("JSON 解析失败:",e),""}}getStringTypeByFormat(e){if(!e)return{type:"string"};switch(e){case"date-time":return{type:"Date",comment:"ISO 8601 格式的日期时间字符串 (例如: 2024-01-09T12:00:00Z)"};case"date":return{type:"Date",comment:"ISO 8601 格式的日期字符串 (例如: 2024-01-09)"};case"time":return{type:"string",comment:"ISO 8601 格式的时间字符串 (例如: 12:00:00)"};case"email":case"idn-email":return{type:"string",comment:"邮箱地址"};case"uuid":return{type:"string",comment:"UUID 格式字符串"};case"uri":case"uri-reference":case"iri":case"iri-reference":return{type:"string",comment:"URI 格式字符串"};case"hostname":case"idn-hostname":return{type:"string",comment:"主机名"};case"ipv4":return{type:"string",comment:"IPv4 地址"};case"ipv6":return{type:"string",comment:"IPv6 地址"};case"binary":return{type:"File",comment:"二进制文件"};default:return{type:"string"}}}parseString(e,t){if("string"!==e.type)return null;if(e.enum){const n=this.handleEnum(e,t);if(n)return n}const{type:n,comment:r}=this.getStringTypeByFormat(e.format);return{headerRef:"",renderStr:`${this.config.formatting?.indentation}${t}${this.requiredFieldS.includes(t)?"":"?"}: ${n}${this.nullable(e.nullable)};${r?` // ${r}`:""}`}}parseProperties(e,n){const r=[],i=[];for(const s in e){const a=e[s];if(a?.$ref){const{headerRefStr:e,typeName:o,dataType:c}=this.parseRef(a.$ref);i.includes(e)||o===n||i.push(e);const u=a,m=this.fieldComment(u);""!==m&&r.push(m);const l="enum"===c?this.getEnumTypeName(o):o;r.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${l};`);const p=a.example;if("enum"===c&&p&&t.isValidJSON(p)){const e=this.typeNameToFileName(o),t=this.convertJsonToEnumString(p,o);this.enumsMap.set(e,{fileName:e,content:t})}continue}if("allOf"in a){const e=a.allOf?.[0];if(e?.$ref){const{headerRefStr:t,typeName:o,dataType:c}=this.parseRef(e.$ref),u="enum"===c?this.getEnumTypeName(o):o;i.includes(t)||o===n||i.push(t);const m=a,l=this.fieldComment(m);""!==l&&r.push(l),r.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${u}${this.nullable(a.nullable)};`);continue}}const o=a,c=this.fieldComment(o);switch(""!==c&&r.push(c),o.type){case"array":{const e=this.parseArray(o,s)??this.defaultReturn;r.push(e?.renderStr??""),i.includes(e.headerRef)||n===e.typeName||i.push(e.headerRef)}break;case"boolean":r.push(this.parseBoolean(o,s));break;case"integer":r.push(this.parseInteger(o,s));break;case"number":{const e=this.parseNumber(o,s);e&&(e.headerRef&&!i.includes(e.headerRef)&&i.push(e.headerRef),r.push(e.renderStr))}break;case"string":if(o.enum){const e=s.charAt(0).toUpperCase()+s.slice(1);if(o.example&&t.isValidJSON(o.example)){const t=this.getEnumTypeName(e),n=`import type { ${t} } from '${this.config.importEnumPath}';`;i.includes(n)||i.push(n);const a=this.typeNameToFileName(e);if(!this.enumsMap.has(a)){const t=this.convertJsonToEnumString(o.example,e);this.enumsMap.set(a,{fileName:a,content:t})}r.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${t}${this.nullable(o.nullable)};`)}else{const t=this.parseEnum(o,e);if(t?.renderStr){const n=this.getEnumTypeName(e),a=`import type { ${n} } from '${this.config.importEnumPath}';`;i.includes(a)||i.push(a);const c=this.typeNameToFileName(e);this.enumsMap.has(c)||this.enumsMap.set(c,{fileName:c,content:t.renderStr}),r.push(`${this.config.formatting?.indentation}${s}${this.requiredFieldS.includes(s)?"":"?"}: ${n}${this.nullable(o.nullable)};`)}}}else r.push(this.parseString(o,s)?.renderStr??"");break;case"object":{const{headerRef:e,renderStr:t}=this.parseObject(o,s)??this.defaultReturn;r.push(t),i.includes(e)||i.push(e)}}}const s=[`export interface ${n} {`,...r,"}"];if(i.length>0){const e=i.filter(e=>""!==e);e.length>0&&e.push(""),s.unshift(...e)}const a=s.join("\n");return{headerRef:i.join("\n"),renderStr:a}}async generateContent(e,t){if("items"in e)return console.warn(`数组类型未处理: ${t}`,e.items),"";switch(e.type){case"boolean":return this.parseBoolean(e,t);case"integer":return this.parseInteger(e,t);case"number":{const n=this.parseNumber(e,t);return n?.renderStr??""}case"object":{const n=this.parseProperties(e.properties,t);return n?.renderStr??""}case"string":{const n=this.parseString(e,t);return n?.renderStr??""}default:return""}}async parseData(){try{if(!this.schemas)return void console.warn("schemas 为空");for(const[e,t]of Object.entries(this.schemas)){if("$ref"in t){console.warn(`跳过 ReferenceObject: ${e}`);continue}const n="type"in t?t:null;if(!n?.type){console.warn(`无效的 schema 对象: ${e}`);continue}this.requiredFieldS=t.required??[];const r=this.typeNameToFileName(e),i=await this.generateContent(n,e);if(i){(i.includes("export enum ")||i.includes("export const ")&&i.includes("as const"))&&!this.enumsMap.has(r)?this.enumsMap.set(r,{fileName:r,content:i}):this.schemasMap.set(e,{fileName:r,content:i})}}}catch(e){throw console.error("解析过程出错:",e),e}}async writeEnums(){const e=[],n=[];for(const[,r]of this.enumsMap){const i=async({fileName:e,content:r})=>{n.push(`export * from './${e}';`);const i=`${this.config.saveEnumFolderPath}/${e}.ts`;await t.writeFileRecursive(i,r),t.log.info(`${i.padEnd(80)} - Write done!`)};e.push(i(r))}await Promise.all(e),await this.writeIndexFile(`${this.config.saveEnumFolderPath}/index.ts`,n),t.log.success("Enums write done!")}async writeFile(){const e=[],n=[],r=`${this.config.saveTypeFolderPath}/models/`;for(const[,i]of this.schemasMap){const s=async({fileName:e,content:i})=>{n.push(`export * from './${e}';`);const s=`${r}${e}.ts`;await t.writeFileRecursive(s,i),t.log.info(`${s.padEnd(80)} - Write done!`)};e.push(s(i))}await Promise.all(e),await this.writeIndexFile(`${r}index.ts`,n),t.log.success("Component parse & write done!")}async handle(){await this.parseData(),await this.writeFile(),await this.writeEnums()}async writeIndexFile(e,n){const i=n.filter(Boolean);if(!i.length)return;let s=[];if(this.appendMode)try{s=(await r.default.promises.readFile(e,"utf8")).split("\n").filter(e=>""!==e.trim())}catch{s=[]}const a=new Set(s),o=[...s,...i.filter(e=>!a.has(e))].join("\n");await t.writeFileRecursive(e,o)}};
|