anl 26.921.0 → 26.929.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/package.cjs +1 -1
- package/lib/standard/install-commitlint.cjs +1 -1
- package/lib/swagger-codegen/components/enum-parser.cjs +3 -3
- package/lib/swagger-codegen/components/index.cjs +1 -1
- package/lib/swagger-codegen/components/schema-resolver.cjs +8 -7
- package/lib/swagger-codegen/config-template.cjs +6 -0
- package/lib/swagger-codegen/index.cjs +7 -46
- package/lib/swagger-codegen/path/index.cjs +4 -3
- package/lib/swagger-codegen/path/schema-resolver.cjs +2 -3
- package/lib/swagger-codegen/path/writer.cjs +1 -1
- package/lib/swagger-codegen/shared/constants.cjs +1 -1
- package/lib/swagger-codegen/shared/format.cjs +1 -1
- package/lib/swagger-codegen/shared/naming.cjs +1 -1
- package/lib/swagger-codegen/shared/openapi-document.cjs +1 -0
- package/lib/swagger-codegen/shared/prettier.cjs +4 -0
- package/lib/swagger-codegen/shared/request-template.cjs +1 -0
- package/lib/swagger-codegen/shared/schema-diagnostics.cjs +2 -0
- package/lib/swagger-codegen/shared/schema-type.cjs +5 -0
- package/lib/swagger-codegen/shared/schema-utils.cjs +2 -3
- package/lib/swagger-codegen/shared/writer.cjs +3 -3
- package/lib/utils/index.cjs +1 -1
- package/package.json +4 -1
package/lib/package.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`26.
|
|
1
|
+
var e=`26.929.0`;Object.defineProperty(exports,`version`,{enumerable:!0,get:function(){return e}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`);require(`../utils/index.cjs`);const n=require(`./const.cjs`);let r=require(`fs`),i=require(`path`),a=require(`
|
|
1
|
+
const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`);require(`../utils/index.cjs`);const n=require(`./const.cjs`);let r=require(`fs`),i=require(`path`),a=require(`progress-estimator`);a=e.__toESM(a);let o=require(`shelljs`);const s=(0,a.default)({storagePath:(0,i.join)(__dirname,`.progress-estimator`)}),c=async()=>{(0,o.which)(`git`)||(t.log.warning(`Sorry, this script requires git`),(0,o.exit)(1));let e=new Promise((e,t)=>{try{(0,o.exec)(n.COMMIT_VERIFY,{silent:!0}),e({success:!0})}catch(e){t(Error(String(e)))}}),i=new Promise((e,i)=>{try{(0,o.exec)(n.NPM_HUSK,{silent:!0}),(0,o.exec)(n.HUSKY_INSTALL,{silent:!0}),(0,o.exec)(n.ADD_COMMIT_MSG,{silent:!0}),(0,r.writeFileSync)(`${process.cwd()}/commitlint.config.js`,n.COMMIT_CONFIG_CONTENT),e({success:!0})}catch(e){t.spinner.error(`Commitlint installation failed!`),i(Error(String(e)))}});try{await s(e,`Install Commitlint`,{estimate:1e4}),await s(i,`Setup Commitlint hooks and config`)}catch(e){console.log(`commitlintHanlde=====>`,e)}};exports.commitlintHanlde=c;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const e=require(`../../utils/logger.cjs`),t=require(`../../utils/index.cjs`),n=require(`../shared/format.cjs`),r=require(`../shared/naming.cjs`),i=require(`../shared/schema-utils.cjs`);var a=class{config;enumsMap=new Map;constructor(e){this.config=e}nullable(e){return i.nullableSuffix(e)}extractEnumMetadata(e){let n={},{enmuConfig:r}=this.config,i=e;if(e.example&&t.isValidJSON(e.example)&&(n.rawEnumJson=e.example),r?.varnames){let e=i[r.varnames];Array.isArray(e)&&(n.customNames=e.map(e=>`${e}`))}if(r?.comment){let e=i[r.comment];if(e&&typeof e==`object`&&!Array.isArray(e)){let t={};Object.entries(e).sort((e,t)=>e[0].localeCompare(t[0])).forEach(([e,n])=>{typeof n==`string`&&(t[e]=n)}),Object.keys(t).length&&(n.descriptionMap=t)}}return n}resolveEnumMemberName(e,t,n){let{customNames:i,isNumericEnum:a,treatStringAsNumeric:o}=n,s=i?.[t];return typeof s==`string`&&s.trim()?r.sanitizeIdentifierName(s):a||typeof e==`string`&&o?`NUMBER_${e}`:typeof e==`string`&&e?r.sanitizeIdentifierName(e.toUpperCase()):`ENUM_${t}`}convertJsonToEnumString(t,i){try{let e=JSON.parse(t);return this.config.enmuConfig.erasableSyntaxOnly?`export const ${i} = {\n${Object.entries(e).sort((e,t)=>e[0].localeCompare(t[0])).map(([e,t])=>`${n.getIndentation(this.config)}${r.sanitizeIdentifierName(e)}: '${String(t)}'`).join(`,
|
|
2
2
|
`)}\n} as const;\n\nexport type ${r.getEnumTypeName(this.config,i)} = typeof ${i}[keyof typeof ${i}];`:`export enum ${i} {\n${Object.entries(e).sort((e,t)=>e[0].localeCompare(t[0])).map(([e,t])=>`${n.getIndentation(this.config)}${r.sanitizeIdentifierName(e)} = '${String(t)}'`).join(`,
|
|
3
|
-
`)}\n}`}catch(t){return e.log.error(`JSON 解析失败: ${t instanceof Error?t.message:String(t)}`),``}}normalizeEnumValues(e){return e.map((e,t)=>{if(typeof e==`string`||typeof e==`number`)return e;if(e&&typeof e==`object`){let n=e;if(n.value!==void 0&&(typeof n.value==`string`||typeof n.value==`number`))return n.value;if(n.key!==void 0&&(typeof n.key==`string`||typeof n.key==`number`))return n.key;if(n.id!==void 0&&(typeof n.id==`string`||typeof n.id==`number`))return n.id;try{return JSON.stringify(n)}catch{return`ENUM_${t}`}}return`ENUM_${t}`})}parseEnum(e,t){if(!Array.isArray(e.enum))return null;let i=[`integer`,`number`],a=this.normalizeEnumValues(e.enum),o=!!(e.type&&i.includes(e.type)),s=e.type===`string`&&a.every(e=>typeof e==`string`&&!isNaN(Number(e))),{customNames:c,descriptionMap:l,rawEnumJson:u}=this.extractEnumMetadata(e),d=this.config.enmuConfig.erasableSyntaxOnly;if(u){let e=this.convertJsonToEnumString(u,t);if(e)return{headerRef:``,renderStr:e}}let f=a.map((e,t)=>{let r=this.resolveEnumMemberName(e,t,{customNames:c,isNumericEnum:o,treatStringAsNumeric:s}),i=o?`${e}
|
|
4
|
-
`):`${n.getIndentation(this.config)}${
|
|
3
|
+
`)}\n}`}catch(t){return e.log.error(`JSON 解析失败: ${t instanceof Error?t.message:String(t)}`),``}}normalizeEnumValues(e){return e.map((e,t)=>{if(typeof e==`string`||typeof e==`number`)return e;if(e&&typeof e==`object`){let n=e;if(n.value!==void 0&&(typeof n.value==`string`||typeof n.value==`number`))return n.value;if(n.key!==void 0&&(typeof n.key==`string`||typeof n.key==`number`))return n.key;if(n.id!==void 0&&(typeof n.id==`string`||typeof n.id==`number`))return n.id;try{return JSON.stringify(n)}catch{return`ENUM_${t}`}}return`ENUM_${t}`})}parseEnum(e,t){if(!Array.isArray(e.enum))return null;let i=[`integer`,`number`],a=this.normalizeEnumValues(e.enum),o=!!(e.type&&i.includes(e.type)),s=e.type===`string`&&a.every(e=>typeof e==`string`&&!isNaN(Number(e))),{customNames:c,descriptionMap:l,rawEnumJson:u}=this.extractEnumMetadata(e),d=this.config.enmuConfig.erasableSyntaxOnly;if(u){let e=this.convertJsonToEnumString(u,t);if(e)return{headerRef:``,renderStr:e}}let f=a.map((e,t)=>{let r=this.resolveEnumMemberName(e,t,{customNames:c,isNumericEnum:o,treatStringAsNumeric:s}),i=/^[A-Za-z_$][\w$]*$/.test(r)?r:JSON.stringify(r),a=o?`${e}`:JSON.stringify(String(e)),u=d?`${i}: ${a},`:`${i} = ${a},`,f=l?.[String(e)];return f?[`${n.getIndentation(this.config)}/** ${f} */`,`${n.getIndentation(this.config)}${u}`].join(`
|
|
4
|
+
`):`${n.getIndentation(this.config)}${u}`});return f.length?d?{headerRef:``,renderStr:[`export const ${t} = {`,...f,`} as const;`,``,`export type ${r.getEnumTypeName(this.config,t)} = typeof ${t}[keyof typeof ${t}];`].join(`
|
|
5
5
|
`)}:{headerRef:``,renderStr:[`export enum ${t} {`,...f,`}`].join(`
|
|
6
|
-
`)}:null}handleEnum(e,i,a=!1){let o=r.
|
|
6
|
+
`)}:null}handleEnum(e,i,a=!1){let o=r.resolveSchemaName(i),s=r.getEnumTypeName(this.config,o),c=r.typeNameToFileName(o),l=r.appendEnumSegment(r.adjustImportPathForSegment(this.config.importEnumPath??``,r.getServerSegment(this.config)),r.getEnumSegment(this.config));if(t.isValidJSON(e.example)){let t=this.convertJsonToEnumString(e.example,o);return this.enumsMap.has(c)||this.enumsMap.set(c,{fileName:c,content:t}),{headerRef:`import type { ${s} } from '${l}';`,renderStr:`${n.getIndentation(this.config)}${i}${a?``:`?`}: ${s}${this.nullable(e.nullable)};`,comment:t,typeName:s}}let u=this.parseEnum(e,o);return u?(this.enumsMap.has(c)||this.enumsMap.set(c,{fileName:c,content:u.renderStr}),{headerRef:`import type { ${s} } from '${l}';`,renderStr:`${n.getIndentation(this.config)}${i}${a?``:`?`}: ${s}${this.nullable(e.nullable)};`,typeName:s}):null}addEnumByName(e,t){let n=r.typeNameToFileName(e);this.enumsMap.has(n)||this.enumsMap.set(n,{fileName:n,content:t})}hasEnum(e){let t=r.typeNameToFileName(e);return this.enumsMap.has(t)}getEnumTypeName(e){return r.getEnumTypeName(this.config,e)}getEnumImport(e){return`import type { ${r.getEnumTypeName(this.config,e)} } from '${r.appendEnumSegment(r.adjustImportPathForSegment(this.config.importEnumPath??``,r.getServerSegment(this.config)),r.getEnumSegment(this.config))}';`}};exports.EnumParser=a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../shared/format.cjs`),t=require(`./schema-resolver.cjs`),n=require(`./writer.cjs`);var r=class{parser;writer;constructor(r,i,a){let
|
|
1
|
+
const e=require(`../shared/format.cjs`),t=require(`./schema-resolver.cjs`),n=require(`./writer.cjs`);var r=class{parser;writer;constructor(r,i,a,o){let s=e.applyFormattingDefaults(i);this.parser=new t.ComponentSchemaResolver(r,s,o),this.writer=new n.ComponentWriter(s,a)}async handle(){let{enumsMap:e,schemasMap:t}=this.parser.main();await this.writer.writeSchemas(t),await this.writer.writeEnums(e)}};exports.default=r;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const e=require(`../../utils/logger.cjs`)
|
|
2
|
-
`).forEach((e,t)=>
|
|
1
|
+
const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const t=require(`../shared/format.cjs`),n=require(`../shared/naming.cjs`),r=require(`../shared/schema-type.cjs`),i=require(`./enum-parser.cjs`);var a=class{schemas;config;enumParser;schemaNames;originalNames;schemasMap=new Map;constructor(e,t,r){this.diagnostics=r,this.schemas=e,this.config=t,this.enumParser=new i.EnumParser(t),this.schemaNames=n.createSchemaNameMap(e,t.enmuConfig.erasableSyntaxOnly),this.originalNames=new Map([...this.schemaNames].map(([e,t])=>[t,e]))}stringifyValue(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}buildDocComment(e,t){let n=[],{title:r,description:i}=e;r&&n.push(`@title ${r}`),i&&i.split(`
|
|
2
|
+
`).forEach((e,t)=>n.push(t===0?`@description ${e}`:e)),`deprecated`in e&&e.deprecated&&n.push(`@deprecated`),`default`in e&&e.default!==void 0&&n.push(`@default ${this.stringifyValue(e.default)}`),`example`in e&&e.example!==void 0&&n.push(`@example ${this.stringifyValue(e.example)}`),`format`in e&&e.format&&n.push(`@format ${e.format}`);let a=[[`pattern`,`@pattern`],[`minimum`,`@minimum`],[`maximum`,`@maximum`],[`exclusiveMinimum`,`@exclusiveMinimum`],[`exclusiveMaximum`,`@exclusiveMaximum`],[`minLength`,`@minLength`],[`maxLength`,`@maxLength`],[`minItems`,`@minItems`],[`maxItems`,`@maxItems`]];if(a.some(([t])=>e[t]!==void 0)){let t=a.map(([t,n])=>e[t]===void 0?``:`${n} ${this.stringifyValue(e[t])}`).filter(Boolean);n.push(...t)}if(!n.length)return``;let o=[`/**`];return n.forEach(e=>{e&&(e=e.replace(/\*\//g,`* /`),e.includes(`
|
|
3
3
|
`)?e.split(`
|
|
4
|
-
`).forEach(e=>
|
|
5
|
-
`)}nameTheHumpCenterStroke(e){let t=e
|
|
6
|
-
`)
|
|
7
|
-
`)
|
|
8
|
-
`),
|
|
4
|
+
`).forEach(e=>o.push(` * ${e}`)):o.push(` * ${e}`))}),o.push(` */`),o.join(`
|
|
5
|
+
`)}nameTheHumpCenterStroke(e){let t=e,i=this.schemaNames.get(t),a={typeName:i,fileName:n.typeNameToFileName(i),dataType:``};if(this.schemas){let e=this.schemas[t];e&&r.isNamedEnumSchema(e)?a.dataType=`enum`:a.dataType=e?.type}return a}parseRef(e){if(!e?.trim())return{headerRefStr:``,typeName:``,dataType:``};let{fileName:t,typeName:r,dataType:i=``}=this.nameTheHumpCenterStroke(e),a;if(i===`enum`){let e=n.getEnumTypeName(this.config,r),t=n.getServerSegment(this.config);a=`import type { ${e} } from '${n.appendEnumSegment(n.adjustImportPathForSegment(this.config.importEnumPath??``,t),n.getEnumSegment(this.config))}';`}else a=`import type { ${r} } from './${t}';`;return{headerRefStr:a,typeName:r,dataType:i}}renderType(i,a,o,s,c=!1){let l=new Set,u=r.renderSchemaType(i,{path:`#/components/schemas/${(this.originalNames.get(a)??a).replace(/~/g,`~0`).replace(/\//g,`~1`)}`,schemaPath:e=>this.diagnostics?.pathFor(e),direction:s,schemas:this.schemas,exactObject:c,reference:e=>{let t=r.resolveLocalSchemaReference(e,this.schemas,e=>l.add(e));if(!t)return`unknown`;let{headerRefStr:i,typeName:c,dataType:u}=this.parseRef(t.name);return c!==a&&!o.includes(i)&&o.push(i),u===`enum`?n.getEnumTypeName(this.config,c):r.directionalTypeName(c,t.schema,this.schemas,s)},property:(e,t,n)=>{if(`$ref`in e||!r.isNamedEnumSchema(e))return;let i=this.enumParser.handleEnum({...e,nullable:!1},t,n);return i?.headerRef&&!o.includes(i.headerRef)&&o.push(i.headerRef),i?.typeName},comment:e=>this.buildDocComment(e),indentation:t.getIndentation(this.config),diagnostic:(t,n,r)=>{this.diagnostics?this.diagnostics.add(t,n,r):r===`runtime`?e.log.verbose(`${n}: ${t}`):l.add(`${n}: ${t}`)}});for(let t of l)e.log.warn(`${a}: ${t}`);return u}generateContent(e,n){let i=[],a=this.renderType(e,n,i),o=[];for(let t of[`request`,`response`])r.schemaNeedsDirection(e,this.schemas,t)&&o.push(`export type ${t===`request`?`Request`:`Response`} = ${this.renderType(e,n,i,t)};`);r.hasMixedAdditionalProperties(e)&&o.push(`export type Exact<Value extends ${n}> = Value & (${this.renderType(e,n,i,void 0,!0)});`);let s=o.join(`
|
|
6
|
+
`).split(`
|
|
7
|
+
`).map(e=>`${t.getIndentation(this.config)}${e}`).join(`
|
|
8
|
+
`),c=o.length?`\nexport namespace ${n} {\n${s}\n}`:``,l=e=>(i.length?`${i.join(`
|
|
9
|
+
`)}\n\n${e}`:e).replace(/\n/g,t.getLineEnding(this.config)),u=!(`$ref`in e)&&e.type===`object`&&!e.nullable&&!e.allOf&&!e.anyOf&&!e.oneOf&&!e.enum;return u&&a.startsWith(`{`)?l(`export interface ${n} ${a}${c}`):u&&a.startsWith(`Record<`)&&a.includes(n)?l(`export interface ${n} extends ${a} {}${c}`):l(`export type ${n} = ${a};${c}`)}main(){if(!this.schemas)return e.log.warn(`schemas 为空`),{enumsMap:this.enumParser.enumsMap,schemasMap:this.schemasMap};let t=Object.keys(this.schemas).sort();for(let e of t){let t=this.schemas[e];if(!(`$ref`in t)&&r.isNamedEnumSchema(t)){let n=this.schemaNames.get(e),r=this.enumParser.parseEnum(t,n);r?.renderStr&&!this.enumParser.hasEnum(n)&&this.enumParser.addEnumByName(n,r.renderStr);continue}let i=this.schemaNames.get(e),a=n.typeNameToFileName(i),o=this.generateContent(t,i);o&&((o.includes(`export enum `)||o.includes(`export const `)&&o.includes(`as const`))&&!this.enumParser.hasEnum(i)?this.enumParser.addEnumByName(i,o):this.schemasMap.set(i,{fileName:a,content:o}))}return{enumsMap:this.enumParser.enumsMap,schemasMap:this.schemasMap}}};exports.ComponentSchemaResolver=a;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
const e=require(`./shared/constants.cjs`);function t(t=e.DEFAULT_REQUEST_TEMPLATE){return{saveTypeFolderPath:`src/types`,saveApiListFolderPath:`src/apis`,saveEnumFolderPath:`src/enums`,importEnumPath:`../../../enums`,requestMethodsImportPath:`./config/fetch`,requestTemplate:t,formatting:{indentation:` `,lineEnding:`
|
|
2
|
+
`},enmuConfig:{erasableSyntaxOnly:!1,varnames:`enum-varnames`,comment:`enum-descriptions`},swaggerConfig:[{url:`https://generator3.swagger.io/openapi.json`,apiListFileName:`index.ts`,headers:{},dataLevel:`serve`,parameterSeparator:`_`,includeInterface:[],excludeInterface:[]}]}}function n(e){return`import { defineConfig } from 'anl/config';
|
|
3
|
+
|
|
4
|
+
/** 请求模板:axios | fetch | wx | uniapp | taro,切换后需删除 <saveApiListFolderPath>/config 目录重新生成 */
|
|
5
|
+
export default defineConfig(${JSON.stringify(e,null,` `)});
|
|
6
|
+
`}exports.createDefaultConfig=t,exports.renderTsConfig=n;
|
|
@@ -1,50 +1,11 @@
|
|
|
1
|
-
const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`),n=require(`../utils/index.cjs`),r=require(`./shared/naming.cjs`),i=require(`./components/index.cjs`),
|
|
2
|
-
`},swaggerConfig:{url:`https://generator3.swagger.io/openapi.json`,apiListFileName:`index.ts`,headers:{},dataLevel:`serve`,parameterSeparator:`_`,includeInterface:[],excludeInterface:[]},enmuConfig:{erasableSyntaxOnly:!1,varnames:`enum-varnames`,comment:`enum-descriptions`}};var x=class{schemas={};paths={};async handle(e,n,s){let c=r.getServiceTag(e);t.log.section(c||`service`,e.swaggerJsonUrl);try{t.spinner.start(`Fetching Swagger data...`);let r=await a.getSwaggerJson(e);if(!r)throw t.spinner.error(`Failed to fetch Swagger data`),Error(`无法获取 Swagger 数据`);t.spinner.success(`Swagger data fetched`),this.schemas=r.components?.schemas??{},this.paths=r.paths??{};let c=new i.default(this.schemas,e,{appendMode:n}),l=new o.default(this.paths,r.components?.parameters,this.schemas,e);return t.spinner.start(`Generating types and APIs...`),await c.handle(),await l.handle(),t.spinner.success(`Types and APIs generated`),s===`gen`?l.getGeneratedInterfacesForOutput():s===`miss`?l.getMissingInterfacesForOutput():null}catch(e){throw e instanceof Error?Error(`Handle Swagger data failed: ${e.message}`):Error(`Handle Swagger data failed: unknown error`)}}async resolvePrettierExecutable(){let e=process.platform===`win32`,n=l.default.join(process.cwd(),`node_modules`,`.bin`,e?`prettier.cmd`:`prettier`);try{return await c.default.promises.access(n,c.default.constants.X_OK),t.log.info(`Using local prettier: ${n}`),`"${n}"`}catch{return`npx prettier`}}async detectPrettierConfig(){for(let e of[`.prettierrc`,`.prettierrc.json`,`.prettierrc.json5`,`.prettierrc.yaml`,`.prettierrc.yml`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`.prettierrc.ts`,`.prettierrc.cts`,`.prettierrc.mts`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`,`prettier.config.ts`,`prettier.config.cts`,`prettier.config.mts`]){let n=l.default.join(process.cwd(),e);try{return await c.default.promises.access(n),t.log.info(`Auto-detected prettier config: ${e}`),n}catch{}}try{let e=await c.default.promises.readFile(l.default.join(process.cwd(),`package.json`),`utf8`);if(JSON.parse(e).prettier)return t.log.info(`Using prettier config from package.json`),l.default.join(process.cwd(),`package.json`)}catch{}return null}async formatGeneratedFiles(e,n){let r=await this.resolvePrettierExecutable(),i=``;if(typeof n==`string`&&n.trim()){let e=l.default.resolve(process.cwd(),n.trim());try{await c.default.promises.access(e),i=` --config "${e}"`}catch{t.log.warning(`Prettier config file not found: ${n}, falling back to auto-detection...`);let e=await this.detectPrettierConfig();e&&(i=` --config "${e}"`)}}else{let e=await this.detectPrettierConfig();e&&(i=` --config "${e}"`)}let a=[],o=async(e,t)=>{try{await c.default.promises.access(e),a.push(`"${e}/${t}"`)}catch{}};if(await o(e.saveTypeFolderPath,`**/*.{ts,d.ts}`),await o(e.saveApiListFolderPath,`**/*.ts`),await o(e.saveEnumFolderPath,`**/*.ts`),a.length===0){t.log.warning(`No generated directories found to format.`);return}let s=`${r} --write ${a.join(` `)}${i}`;try{t.spinner.start(`Formatting generated files...`);let{stderr:e}=await new Promise((e,t)=>{(0,u.exec)(s,(n,r,i)=>{n?t(Error(String(n))):e({stdout:r,stderr:i})})});e&&(t.log.print(`
|
|
3
|
-
`),t.log.print(`$`,d.default.yellow(s)),t.log.print(`
|
|
4
|
-
`)),t.spinner.success(`File formatting successful`),t.log.print(`
|
|
5
|
-
`)}catch(e){t.spinner.error(`Format failed`),t.log.print(``),t.log.print(e),t.log.error(`Format failed, please manually execute the following command:`),t.log.print(`$`,d.default.yellow(s)),t.log.print(``)}}async copyAjaxConfigFiles(e,n){let r=m?l.default.join(__dirname,`..`,`..`,`postbuild-assets`,`request-templates`):l.default.join(__dirname,`..`,`request-templates`),i=l.default.join(r,n),a=l.default.join(r,`_shared`),o=l.default.join(e,`config`);try{await c.default.promises.access(o);let e=await this.readExistingTemplateMarker(o);e&&e!==n?t.log.warning(`config folder exists at ${o}, but its embedded marker "${e}" differs from configured requestTemplate="${n}". If you want to switch, delete the config folder first: rm -rf "${o}"`):(t.log.info(`config folder already exists at ${o}, skipping generation. (template=${n})`),t.log.info(` If you want to switch template, please delete the config folder first: rm -rf "${o}"`));return}catch{}let s=[];for(let e of _){let t=l.default.join(i,e),r=l.default.join(a,e),o=null;try{await c.default.promises.access(t),o=t}catch{try{await c.default.promises.access(r),o=r}catch{throw Error(`Source file not found for template "${n}": ${e} (looked in ${i} and ${a})`)}}s.push({file:e,sourceFile:o})}await c.default.promises.mkdir(o,{recursive:!0}),t.log.info(`Using request template: ${d.default.cyan(n)} (template dir: ${i}, shared dir: ${a})`);try{for(let{file:e,sourceFile:r}of s){let i=l.default.join(o,e);if(e===`dio.ts`){let e=await c.default.promises.readFile(r,`utf8`),t=v.test(e)?e:`// @an-cli-request-template: ${n} — 切换请求模板前请删除本 config/ 目录后重新运行 anl type\n${e}`;await c.default.promises.writeFile(i,t)}else await c.default.promises.copyFile(r,i);t.log.success(`${e} create done.`)}}catch(e){throw await c.default.promises.rm(o,{recursive:!0,force:!0}).catch(()=>void 0),e instanceof Error?e:Error(String(e))}}async readExistingTemplateMarker(e){try{let t=await c.default.promises.readFile(l.default.join(e,`dio.ts`),`utf8`),n=v.exec(t.slice(0,500));return n?n[1].toLowerCase():null}catch{return null}}getSystemLocale(){try{return Intl.DateTimeFormat().resolvedOptions().locale.toLowerCase()}catch{return(process.env.LANG??process.env.LC_ALL??process.env.LC_MESSAGES??``).toLowerCase()}}showLegacyConfigHint(e){let n={url:e.swaggerJsonUrl??`https://your.swagger.json`,publicPrefix:e.publicPrefix??``,apiListFileName:e.apiListFileName??`index.ts`,headers:e.headers??{}},r=this.getSystemLocale();r.startsWith(`zh`)||r.includes(`chinese`)?(t.log.print(`
|
|
1
|
+
const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`),n=require(`../utils/index.cjs`),r=require(`./shared/naming.cjs`),i=require(`./shared/constants.cjs`),a=require(`./shared/writer.cjs`),o=require(`./components/index.cjs`),s=require(`./config-template.cjs`),c=require(`./get-data.cjs`),l=require(`./path/index.cjs`),u=require(`./shared/openapi-document.cjs`),d=require(`./shared/prettier.cjs`),f=require(`./shared/request-template.cjs`),p=require(`./shared/schema-diagnostics.cjs`);let m=require(`inquirer`);m=e.__toESM(m);let h=require(`fs`);h=e.__toESM(h);let g=require(`path`);g=e.__toESM(g);let _=require(`chalk`);_=e.__toESM(_);let v=require(`jiti`),y;const b=process.env.NODE_ENV===`debug`,x=b?g.default.join(__dirname,`..`,`..`,`postbuild-assets`,`request-templates`):g.default.join(__dirname,`..`,`request-templates`),S=s.createDefaultConfig();b&&(S.saveTypeFolderPath=`apps/types`,S.saveApiListFolderPath=`apps/types`,S.saveEnumFolderPath=`apps/enums`);var C=class{schemas={};paths={};async handle(e,n,i){let a=r.getServiceTag(e);t.log.section(a||`service`,e.swaggerJsonUrl);try{t.spinner.start(`Fetching Swagger data...`);let r=await c.getSwaggerJson(e);if(!r)throw t.spinner.error(`Failed to fetch Swagger data`),Error(`无法获取 Swagger 数据`);let a=u.normalizeOpenApiDocument(r,e=>t.log.warn(e));t.spinner.success(`Swagger data fetched`),this.schemas=a.components?.schemas??{},this.paths=a.paths??{};let s=new p.SchemaDiagnostics(a),d=new o.default(this.schemas,e,{appendMode:n},s),f=new l.default(this.paths,a.components?.parameters,this.schemas,e,s);return t.spinner.start(`Generating types and APIs...`),await d.handle(),await f.handle(),t.spinner.success(`Types and APIs generated`),s.flush((e,n)=>{n===`info`?t.log.print(e):n===`verbose`?t.log.verbose(e):t.log.warn(e)}),i===`gen`?f.getGeneratedInterfacesForOutput():i===`miss`?f.getMissingInterfacesForOutput():null}catch(e){throw t.spinner.error(`Swagger generation failed`),e instanceof Error?Error(`Handle Swagger data failed: ${e.message}`):Error(`Handle Swagger data failed: unknown error`)}}getSystemLocale(){try{return Intl.DateTimeFormat().resolvedOptions().locale.toLowerCase()}catch{return(process.env.LANG??process.env.LC_ALL??process.env.LC_MESSAGES??``).toLowerCase()}}showLegacyConfigHint(e){let n={url:e.swaggerJsonUrl??`https://your.swagger.json`,publicPrefix:e.publicPrefix??``,apiListFileName:e.apiListFileName??`index.ts`,headers:e.headers??{}},r=this.getSystemLocale();r.startsWith(`zh`)||r.includes(`chinese`)?(t.log.print(`
|
|
6
2
|
检测到旧版配置,请更新 an.config.json:`),t.log.print(`1) 将 swaggerJsonUrl / publicPrefix / headers 移到 swaggerConfig 字段。`),t.log.print(`2) 单个服务可直接填写对象,多个服务请使用数组,并确保 apiListFileName 唯一。`),t.log.print(`示例:`),t.log.print(JSON.stringify({swaggerConfig:n},null,2)),t.log.print(``)):(t.log.print(`
|
|
7
|
-
Legacy configuration detected, please update an.config.json:`),t.log.print(`1) Move swaggerJsonUrl / publicPrefix / headers to swaggerConfig field.`),t.log.print(`2) Single service can be an object directly, multiple services should use an array, and ensure apiListFileName is unique.`),t.log.print(`Example:`),t.log.print(JSON.stringify({swaggerConfig:n},null,2)),t.log.print(``))}normalizeswaggerConfig(e,t){let n=!1,r=t?e.swaggerConfig:void 0;r||=(n=!0,{url:e.swaggerJsonUrl??``,publicPrefix:e.publicPrefix??``,apiListFileName:e.apiListFileName??`index.ts`,headers:e.headers??{},modulePrefix:e.modulePrefix});let i=(t,r)=>{let i=t.url||e.swaggerJsonUrl;if(!i)throw Error(`swaggerConfig[${r}] 缺少 url,请补充后重试。`);let a=t.publicPrefix??e.publicPrefix??``;!t.url&&e.swaggerJsonUrl&&(n=!0);let o=(t.apiListFileName??e.apiListFileName??`index.ts`).trim()||`index.ts`;if(/[\\/]/.test(o)||o.includes(`..`))throw Error(`swaggerConfig[${r}].apiListFileName 非法:"${o}",请使用单个文件名(如 "bff.ts"),不要包含路径分隔符或 ".."。`);let s=t.headers??e.headers??{},c=t.dataLevel??e.dataLevel??`serve`,l=t.parameterSeparator??e.parameterSeparator??`_`,u=t.includeInterface??e.includeInterface??[],d=t.excludeInterface??e.excludeInterface??[],f=t.includeTags??e.includeTags,p=t.excludeTags??e.excludeTags,m={url:i,publicPrefix:a,apiListFileName:o,headers:s,dataLevel:c,parameterSeparator:l,includeInterface:u,excludeInterface:d,modulePrefix:t.modulePrefix??e.modulePrefix??``,responseModelTransform:t.responseModelTransform??e.responseModelTransform,timeout:t.timeout??e.timeout,namespaceIsolation:t.namespaceIsolation??e.namespaceIsolation??`segment`,enumIsolation:t.enumIsolation??e.enumIsolation??`segment`};return t.name?.trim()&&(m.name=t.name.trim()),f!==void 0&&(m.includeTags=f),p!==void 0&&(m.excludeTags=p),m},a=Array.isArray(r)?r.map((e,t)=>i(e,t)):[i(r,0)];if(a.length===0)throw Error(`swaggerConfig 不能为空,请至少配置一个 swagger 服务。`);if(a.length>1){let e=new Set;a.forEach(t=>{if(e.has(t.apiListFileName))throw Error(`swaggerConfig 中 apiListFileName 重复:${t.apiListFileName},请为每个服务设置唯一文件名。`);e.add(t.apiListFileName)});let t=new Set;a.forEach(e=>{if(e.name){if(t.has(e.name))throw Error(`swaggerConfig 中 name 重复:${e.name},请为每个服务设置唯一名称。`);t.add(e.name)}})}return n&&this.showLegacyConfigHint(e),a}buildServerConfig(e,t,n,r){return{...e,swaggerJsonUrl:t.url,publicPrefix:t.publicPrefix??e.publicPrefix,headers:t.headers,apiListFileName:t.apiListFileName,dataLevel:t.dataLevel,parameterSeparator:t.parameterSeparator,includeInterface:t.includeInterface,excludeInterface:t.excludeInterface,includeTags:t.includeTags,excludeTags:t.excludeTags,modulePrefix:t.modulePrefix,responseModelTransform:t.responseModelTransform??e.responseModelTransform,timeout:t.timeout??e.timeout,namespaceIsolation:t.namespaceIsolation??e.namespaceIsolation??`segment`,enumIsolation:t.enumIsolation??e.enumIsolation??`segment`,swaggerConfig:t,__segment:n,__namespacePrefix:r}}async loadTsConfig(e){try{let t=await(0,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
saveTypeFolderPath: 'src/types',
|
|
11
|
-
saveApiListFolderPath: 'src/apis',
|
|
12
|
-
saveEnumFolderPath: 'src/enums',
|
|
13
|
-
importEnumPath: '../../../enums',
|
|
14
|
-
requestMethodsImportPath: './config/fetch',
|
|
15
|
-
/** 请求模板:axios | fetch | wx | uniapp | taro,切换后需删除 <saveApiListFolderPath>/config 目录重新生成 */
|
|
16
|
-
requestTemplate: '${e}',
|
|
17
|
-
formatting: {
|
|
18
|
-
indentation: '\\t',
|
|
19
|
-
lineEnding: '\\n',
|
|
20
|
-
},
|
|
21
|
-
swaggerConfig: [
|
|
22
|
-
{
|
|
23
|
-
url: 'https://generator3.swagger.io/openapi.json',
|
|
24
|
-
apiListFileName: 'index.ts',
|
|
25
|
-
headers: {},
|
|
26
|
-
dataLevel: 'serve',
|
|
27
|
-
parameterSeparator: '_',
|
|
28
|
-
includeInterface: [],
|
|
29
|
-
excludeInterface: [],
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
enmuConfig: {
|
|
33
|
-
erasableSyntaxOnly: false,
|
|
34
|
-
varnames: 'enum-varnames',
|
|
35
|
-
comment: 'enum-descriptions',
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
`}resolveSelectedServiceIndices(e,t){let n=new Map;e.forEach((e,t)=>{e.name&&n.set(e.name.toLowerCase(),t)}),e.forEach((e,t)=>{let i=r.computeSegment(e.apiListFileName).toLowerCase();i&&!n.has(i)&&n.set(i,t)});let i=new Set,a=[];for(let e of t){let t=e.toLowerCase(),r=n.get(t);r===void 0?a.push(e):i.add(r)}if(a.length){let t=e.map(e=>e.name??r.computeSegment(e.apiListFileName)).filter(Boolean).join(`, `);throw Error(`未找到匹配的 swagger 服务:${a.join(`, `)}。可用服务:${t||`<无>`}`)}return Array.from(i).sort((e,t)=>e-t)}async promptSelectServices(e){let t=e.map((e,t)=>{let n=(e.name??r.computeSegment(e.apiListFileName))||`#${t}`;return{name:`${n} (${e.apiListFileName} ← ${e.url})`,value:t,short:n}}),{picked:n}=await s.default.prompt([{type:`checkbox`,name:`picked`,message:`请选择需要重新生成的 swagger 服务(空选 = 全部):`,choices:t,pageSize:Math.min(20,t.length)}]);return!n||n.length===0?e.map((e,t)=>t):n.sort((e,t)=>e-t)}async initialize(e,i,a,o,s){let l=process.cwd();try{let u=await this.getConfig(l,s),f={...b,...u},m=a??f.logLevel;m&&t.setLogLevel(m);let h=Object.prototype.hasOwnProperty.call(u,`swaggerConfig`),g=this.normalizeswaggerConfig(f,h);if(!p)return;let _=g.length>1,v=_?g.map(e=>r.computeSegment(e.apiListFileName)):g.map(()=>``);if(_){let e=new Map;v.forEach((t,n)=>{if(!t)throw Error(`swaggerConfig[${n}].apiListFileName="${g[n].apiListFileName}" 无法派生有效 segment(清洗后为空),请使用包含字母/数字的文件名。`);if(t.toLowerCase()===`index`)throw Error(`swaggerConfig[${n}].apiListFileName="${g[n].apiListFileName}" 派生 segment 为 "index",会与顶层 models/index.ts 形成自引用,请改为其他文件名(如 "main.ts" / "default.ts")。`);if(e.has(t))throw Error(`swaggerConfig 多个服务的 apiListFileName 在派生 segment 时冲突:"${g[e.get(t)].apiListFileName}" 与 "${g[n].apiListFileName}" 都解析为 "${t}",请改名以避免目录覆盖。`);e.set(t,n)})}let x=g.map(e=>(e.namespaceIsolation??f.namespaceIsolation??`segment`)===`none`?``:r.segmentToNamespacePrefix(r.computeSegment(e.apiListFileName)));if(_){let e=g.map((e,t)=>({s:e,idx:t})).filter(({s:e})=>(e.namespaceIsolation??f.namespaceIsolation??`segment`)===`none`).map(({s:e})=>e.apiListFileName);e.length>0&&t.log.warning(`检测到多服务场景下以下服务关闭了 namespace 前缀(namespaceIsolation: 'none'):${e.join(`, `)}。 不同服务若存在同名 path,将会因 declare namespace 全局合并而互相污染类型,请确认是否符合预期。`);let n=new Map;x.forEach((e,t)=>{if(e){if(n.has(e))throw Error(`swaggerConfig 多个服务派生的 namespace 前缀冲突:"${g[n.get(e)].apiListFileName}" 与 "${g[t].apiListFileName}" 都解析为前缀 "${e}",请改名以避免类型同名合并。`);n.set(e,t)}})}let S,C;o?.length?(S=this.resolveSelectedServiceIndices(g,o),C=S.length!==g.length):g.length>1&&process.stdin.isTTY&&process.stdout.isTTY?(t.log.print(d.default.cyan(`
|
|
39
|
-
检测到多个 swagger 服务,请选择本次要重新生成的服务:`)),S=await this.promptSelectServices(g),C=S.length!==g.length):(S=g.map((e,t)=>t),C=!1),this.printExecutionPlan(g,S,C),await c.default.promises.mkdir(f.saveApiListFolderPath,{recursive:!0});let w=s?y(s,`CLI --template`):y(f.requestTemplate,`an.config`);await this.copyAjaxConfigFiles(f.saveApiListFolderPath,w),C?await this.cleanSelectedTargets(f,g,S,v,_):(await n.clearDirExcept(f.saveApiListFolderPath,[`config`]),await n.clearDir(f.saveTypeFolderPath),await n.clearDir(f.saveEnumFolderPath));let T=[];for(let t=0;t<S.length;t++){let n=S[t],r=this.buildServerConfig(f,g[n],v[n],x[n]),i=C?!0:t>0,a=await this.handle(r,i,e);e&&a&&T.push({serverUrl:g[n].url,list:a})}if(_&&(await this.writeTopLevelModelsBarrel(f,v,S,C),S.filter(e=>(g[e].enumIsolation??`segment`)===`segment`).map(e=>v[e]).filter(Boolean).length>0&&await this.writeTopLevelEnumsBarrel(f,v,g,S,C),g.every(e=>(e.enumIsolation??`segment`)===`segment`)&&await this.warnLegacyTopLevelEnums(f)),i!==void 0&&i!==!1&&(C?await this.formatSelectedFiles(f,g,S,v,_,i):await this.formatGeneratedFiles(f,i)),t.log.banner(`All done — see you next time!`),e&&T.length>0){let n=e===`miss`?`excludeInterface`:`includeInterface`;for(let{serverUrl:e,list:r}of T)S.length>1?t.log.print(d.default.cyan(`\n[${n}] ${e}`)):t.log.print(d.default.cyan(`\n[${n}]`)),t.log.print(JSON.stringify(r,null,2));t.log.print(`
|
|
40
|
-
`)}}catch(e){let n=e instanceof Error?e.message:`Unknown error`;t.log.error(`Initialization failed: ${n}`),process.exitCode=1}}printExecutionPlan(e,n,i){let a=new Set(n);t.log.print(d.default.cyan(i?`
|
|
3
|
+
Legacy configuration detected, please update an.config.json:`),t.log.print(`1) Move swaggerJsonUrl / publicPrefix / headers to swaggerConfig field.`),t.log.print(`2) Single service can be an object directly, multiple services should use an array, and ensure apiListFileName is unique.`),t.log.print(`Example:`),t.log.print(JSON.stringify({swaggerConfig:n},null,2)),t.log.print(``))}normalizeswaggerConfig(e,t){let n=!1,r=t?e.swaggerConfig:void 0;r||=(n=!0,{url:e.swaggerJsonUrl??``,publicPrefix:e.publicPrefix??``,apiListFileName:e.apiListFileName??`index.ts`,headers:e.headers??{},modulePrefix:e.modulePrefix});let i=(t,r)=>{let i=t.url||e.swaggerJsonUrl;if(!i)throw Error(`swaggerConfig[${r}] 缺少 url,请补充后重试。`);let a=t.publicPrefix??e.publicPrefix??``;!t.url&&e.swaggerJsonUrl&&(n=!0);let o=(t.apiListFileName??e.apiListFileName??`index.ts`).trim()||`index.ts`;if(/[\\/]/.test(o)||o.includes(`..`))throw Error(`swaggerConfig[${r}].apiListFileName 非法:"${o}",请使用单个文件名(如 "bff.ts"),不要包含路径分隔符或 ".."。`);let s=t.headers??e.headers??{},c=t.dataLevel??e.dataLevel??`serve`,l=t.parameterSeparator??e.parameterSeparator??`_`,u=t.includeInterface??e.includeInterface??[],d=t.excludeInterface??e.excludeInterface??[],f=t.includeTags??e.includeTags,p=t.excludeTags??e.excludeTags,m={url:i,publicPrefix:a,apiListFileName:o,headers:s,dataLevel:c,parameterSeparator:l,includeInterface:u,excludeInterface:d,modulePrefix:t.modulePrefix??e.modulePrefix??``,responseModelTransform:t.responseModelTransform??e.responseModelTransform,timeout:t.timeout??e.timeout,namespaceIsolation:t.namespaceIsolation??e.namespaceIsolation??`segment`,enumIsolation:t.enumIsolation??e.enumIsolation??`segment`};return t.name?.trim()&&(m.name=t.name.trim()),f!==void 0&&(m.includeTags=f),p!==void 0&&(m.excludeTags=p),m},a=Array.isArray(r)?r.map((e,t)=>i(e,t)):[i(r,0)];if(a.length===0)throw Error(`swaggerConfig 不能为空,请至少配置一个 swagger 服务。`);if(a.length>1){let e=new Set;a.forEach(t=>{if(e.has(t.apiListFileName))throw Error(`swaggerConfig 中 apiListFileName 重复:${t.apiListFileName},请为每个服务设置唯一文件名。`);e.add(t.apiListFileName)});let t=new Set;a.forEach(e=>{if(e.name){if(t.has(e.name))throw Error(`swaggerConfig 中 name 重复:${e.name},请为每个服务设置唯一名称。`);t.add(e.name)}})}return n&&this.showLegacyConfigHint(e),a}buildServerConfig(e,t,n,r){return{...e,swaggerJsonUrl:t.url,publicPrefix:t.publicPrefix??e.publicPrefix,headers:t.headers,apiListFileName:t.apiListFileName,dataLevel:t.dataLevel,parameterSeparator:t.parameterSeparator,includeInterface:t.includeInterface,excludeInterface:t.excludeInterface,includeTags:t.includeTags,excludeTags:t.excludeTags,modulePrefix:t.modulePrefix,responseModelTransform:t.responseModelTransform??e.responseModelTransform,timeout:t.timeout??e.timeout,namespaceIsolation:t.namespaceIsolation??e.namespaceIsolation??`segment`,enumIsolation:t.enumIsolation??e.enumIsolation??`segment`,swaggerConfig:t,__segment:n,__namespacePrefix:r}}async loadTsConfig(e){try{let t=await(0,v.createJiti)(__filename,{interopDefault:!0}).import(e),n=`default`in t&&t.default?t.default:t;return y=!0,n}catch(e){y=!0;let t=e instanceof Error?e.message:String(e);throw Error(`配置文件加载失败,请检查 an.config.ts 文件: ${t}`)}}async loadJsonConfig(e){try{let t=await h.default.promises.readFile(e,`utf8`);y=!0;try{return JSON.parse(t)}catch(e){throw y=!0,Error(`配置文件格式错误,请检查 an.config.json 的 JSON 格式是否正确: ${e instanceof Error?e.message:String(e)}`)}}catch(e){throw e instanceof Error&&`code`in e&&e.code,e}}async getConfig(e,r){let a=g.default.join(e,`an.config.ts`),o=g.default.join(e,`an.config.json`);if(h.default.existsSync(a))return t.log.info(`检测到 an.config.ts 配置文件。`),this.loadTsConfig(a);if(h.default.existsSync(o))return this.loadJsonConfig(o);y=!1,t.log.warning(`配置文件不存在,将自动创建配置文件。`);let c=i.DEFAULT_REQUEST_TEMPLATE;if(r)c=f.normalizeRequestTemplate(r,`CLI --template`);else if(process.stdin.isTTY&&process.stdout.isTTY){let{picked:e}=await m.default.prompt([{type:`list`,name:`picked`,message:`请选择请求模板(决定 <saveApiListFolderPath>/config/ 下的底层实现):`,choices:[{name:`axios —— 基于 axios(浏览器/Node,需 npm i axios)`,value:`axios`},{name:`fetch —— 基于原生 fetch(浏览器/现代 Node,无额外依赖)`,value:`fetch`},{name:`wx —— 基于 wx.request(微信小程序)`,value:`wx`},{name:`uniapp —— 基于 uni.request(uni-app 跨端)`,value:`uniapp`},{name:`taro —— 基于 Taro.request(Taro 3+ 跨端)`,value:`taro`}],default:`axios`}]);c=e}else t.log.warning(`未指定 --template 且当前非交互终端,requestTemplate 默认为 "${i.DEFAULT_REQUEST_TEMPLATE}"。可通过 --template 指定或修改 an.config.ts 后重跑。`);let l=s.createDefaultConfig(c);await n.writeFileRecursive(a,s.renderTsConfig(l));try{await h.default.promises.mkdir(l.saveApiListFolderPath,{recursive:!0}),await f.copyAjaxConfigFiles(l.saveApiListFolderPath,c,x),t.log.success(`配置文件已创建(requestTemplate=${c}),并已同步初始化 ${l.saveApiListFolderPath}/config/。请检查 an.config.ts 后重新运行以生成 API。`)}catch(e){t.log.warning(`初始化 ${l.saveApiListFolderPath}/config/ 失败:${e instanceof Error?e.message:String(e)}。配置文件已创建,请修正后重跑。`)}return l}resolveSelectedServiceIndices(e,t){let n=new Map;e.forEach((e,t)=>{e.name&&n.set(e.name.toLowerCase(),t)}),e.forEach((e,t)=>{let i=r.computeSegment(e.apiListFileName).toLowerCase();i&&!n.has(i)&&n.set(i,t)});let i=new Set,a=[];for(let e of t){let t=e.toLowerCase(),r=n.get(t);r===void 0?a.push(e):i.add(r)}if(a.length){let t=e.map(e=>e.name??r.computeSegment(e.apiListFileName)).filter(Boolean).join(`, `);throw Error(`未找到匹配的 swagger 服务:${a.join(`, `)}。可用服务:${t||`<无>`}`)}return Array.from(i).sort((e,t)=>e-t)}async promptSelectServices(e){let t=e.map((e,t)=>{let n=r.getServiceIdentifier(e,t);return{name:`${n} (${e.apiListFileName} ← ${e.url})`,value:t,short:n}}),{picked:n}=await m.default.prompt([{type:`checkbox`,name:`picked`,message:`请选择需要重新生成的 swagger 服务(空选 = 全部):`,choices:t,pageSize:Math.min(20,t.length)}]);return!n||n.length===0?e.map((e,t)=>t):n.sort((e,t)=>e-t)}async initialize(e,i,a,o,s){let c=process.cwd();try{let l=await this.getConfig(c,s),u={...S,...l},p=a??u.logLevel;p&&t.setLogLevel(p);let m=Object.prototype.hasOwnProperty.call(l,`swaggerConfig`),g=this.normalizeswaggerConfig(u,m);if(!y)return;let v=g.length>1,b=v?g.map(e=>r.computeSegment(e.apiListFileName)):g.map(()=>``);if(v){let e=new Map;b.forEach((t,n)=>{if(!t)throw Error(`swaggerConfig[${n}].apiListFileName="${g[n].apiListFileName}" 无法派生有效 segment(清洗后为空),请使用包含字母/数字的文件名。`);if(t.toLowerCase()===`index`)throw Error(`swaggerConfig[${n}].apiListFileName="${g[n].apiListFileName}" 派生 segment 为 "index",会与顶层 models/index.ts 形成自引用,请改为其他文件名(如 "main.ts" / "default.ts")。`);if(e.has(t))throw Error(`swaggerConfig 多个服务的 apiListFileName 在派生 segment 时冲突:"${g[e.get(t)].apiListFileName}" 与 "${g[n].apiListFileName}" 都解析为 "${t}",请改名以避免目录覆盖。`);e.set(t,n)})}let C=g.map(e=>(e.namespaceIsolation??u.namespaceIsolation??`segment`)===`none`?``:r.segmentToNamespacePrefix(r.computeSegment(e.apiListFileName)));if(v){let e=g.map((e,t)=>({s:e,idx:t})).filter(({s:e})=>(e.namespaceIsolation??u.namespaceIsolation??`segment`)===`none`).map(({s:e})=>e.apiListFileName);e.length>0&&t.log.warning(`检测到多服务场景下以下服务关闭了 namespace 前缀(namespaceIsolation: 'none'):${e.join(`, `)}。 不同服务若存在同名 path,将会因 declare namespace 全局合并而互相污染类型,请确认是否符合预期。`);let n=new Map;C.forEach((e,t)=>{if(e){if(n.has(e))throw Error(`swaggerConfig 多个服务派生的 namespace 前缀冲突:"${g[n.get(e)].apiListFileName}" 与 "${g[t].apiListFileName}" 都解析为前缀 "${e}",请改名以避免类型同名合并。`);n.set(e,t)}})}let w,T;o?.length?(w=this.resolveSelectedServiceIndices(g,o),T=w.length!==g.length):g.length>1&&process.stdin.isTTY&&process.stdout.isTTY?(t.log.print(_.default.cyan(`
|
|
4
|
+
检测到多个 swagger 服务,请选择本次要重新生成的服务:`)),w=await this.promptSelectServices(g),T=w.length!==g.length):(w=g.map((e,t)=>t),T=!1),this.printExecutionPlan(g,w,T),await h.default.promises.mkdir(u.saveApiListFolderPath,{recursive:!0});let E=s?f.normalizeRequestTemplate(s,`CLI --template`):f.normalizeRequestTemplate(u.requestTemplate,`an.config`);await f.copyAjaxConfigFiles(u.saveApiListFolderPath,E,x),T?await this.cleanSelectedTargets(u,g,w,b,v):(await n.clearDirExcept(u.saveApiListFolderPath,[`config`]),await n.clearDir(u.saveTypeFolderPath),await n.clearDir(u.saveEnumFolderPath));let D=[];for(let t=0;t<w.length;t++){let n=w[t],r=this.buildServerConfig(u,g[n],b[n],C[n]),i=T?!0:t>0,a=await this.handle(r,i,e);e&&a&&D.push({serverUrl:g[n].url,list:a})}if(v&&(await this.writeTopLevelModelsBarrel(u,b,w,T),w.some(e=>r.isEnumIsolated(g[e])&&b[e])&&await this.writeTopLevelEnumsBarrel(u,b,g,w,T),g.every(r.isEnumIsolated)&&await this.warnLegacyTopLevelEnums(u)),i!==void 0&&i!==!1&&await d.formatGeneratedFiles(u,i,T?{servers:g,selectedIndices:w,segments:b,isolateBySegment:v}:void 0),t.log.banner(`All done — see you next time!`),e&&D.length>0){let n=e===`miss`?`excludeInterface`:`includeInterface`;for(let{serverUrl:e,list:r}of D)w.length>1?t.log.print(_.default.cyan(`\n[${n}] ${e}`)):t.log.print(_.default.cyan(`\n[${n}]`)),t.log.print(JSON.stringify(r,null,2));t.log.print(`
|
|
5
|
+
`)}}catch(e){let n=e instanceof Error?e.message:`Unknown error`;t.log.error(`Initialization failed: ${n}`),process.exitCode=1}}printExecutionPlan(e,n,i){let a=new Set(n);t.log.print(_.default.cyan(i?`
|
|
41
6
|
[anl type] 选择型生成,仅处理以下服务:`:`
|
|
42
|
-
[anl type] 全量生成,将处理所有服务:`)),e.forEach((e,n)=>{let i=
|
|
43
|
-
`).filter(e=>e.trim()!==``)}catch{e=[]}let t=new Set(u);p=[...e.filter(e=>{let n=f(e);return!(n&&t.has(n))}).map(e=>{let t=f(e);if(!t||/export\s+\*\s+as\s+/.test(e))return e;try{return l(t)}catch{return e}}),...d]}else p=d;await n.writeFileRecursive(s,p.join(`
|
|
7
|
+
[anl type] 全量生成,将处理所有服务:`)),e.forEach((e,n)=>{let i=r.getServiceIdentifier(e,n);a.has(n)?t.log.print(` ${_.default.green(`●`)} ${i} (${e.apiListFileName}) ${_.default.gray(e.url)}`):t.log.print(` ${_.default.gray(`○ skip `)}${i} (${e.apiListFileName}) ${_.default.gray(e.url)}`)}),t.log.print(``)}async cleanSelectedTargets(e,t,i,a,o){for(let s of i)if(await n.clearDir(`${e.saveApiListFolderPath}/${t[s].apiListFileName}`),o){let i=a[s];i&&(await n.clearDir(`${e.saveTypeFolderPath}/connectors/${i}`),await n.clearDir(`${e.saveTypeFolderPath}/models/${i}`),r.isEnumIsolated(t[s])&&await n.clearDir(`${e.saveEnumFolderPath}/${i}`))}else await n.clearDir(`${e.saveTypeFolderPath}/connectors`),await n.clearDir(`${e.saveTypeFolderPath}/models`)}async writeTopLevelModelsBarrel(e,r,i,o){let s=`${e.saveTypeFolderPath}/models/index.ts`,c=o?i.map(e=>r[e]).filter(Boolean):r.filter(Boolean);await n.writeFileRecursive(s,a.mergeNamespaceExports(o?await a.readIndexLines(s):[],c,c,o).join(`
|
|
44
8
|
`)+`
|
|
45
|
-
`),t.log.info(`${s} - Top-level models barrel ${o?`merged`:`written`}.`)}async writeTopLevelEnumsBarrel(e,i,
|
|
46
|
-
`).filter(e=>e.trim()!==``)}catch{e=[]}let t=new Set(p);g=[...e.filter(e=>{let n=h(e);return!(n&&t.has(n))}),...m]}else{let e=[];try{e=(await c.default.promises.readFile(l,`utf8`)).split(`
|
|
47
|
-
`).filter(e=>e.trim()!==``)}catch{e=[]}let t=new Set(p);g=[...e.filter(e=>{let n=h(e);return!(n&&t.has(n))}),...m]}await n.writeFileRecursive(l,g.join(`
|
|
9
|
+
`),t.log.info(`${s} - Top-level models barrel ${o?`merged`:`written`}.`)}async writeTopLevelEnumsBarrel(e,i,o,s,c){let l=`${e.saveEnumFolderPath}/index.ts`,u=(c?s:i.map((e,t)=>t)).filter(e=>r.isEnumIsolated(o[e])).map(e=>i[e]).filter(Boolean),d=Array.from(new Set(u)),f=(await Promise.all(d.map(async t=>{let n=`${e.saveEnumFolderPath}/${t}`;try{return(await h.default.promises.readdir(n,{withFileTypes:!0})).some(e=>e.isFile()&&/\.(d\.)?ts$/.test(e.name)&&e.name!==`index.ts`)?t:``}catch{return``}}))).filter(Boolean);await n.writeFileRecursive(l,a.mergeNamespaceExports(await a.readIndexLines(l),d,f).join(`
|
|
48
10
|
`)+`
|
|
49
|
-
`),t.log.info(`${l} - Top-level enums barrel ${
|
|
50
|
-
`)}catch(e){t.spinner.error(`Format failed`),t.log.print(e),t.log.error(`Format failed, please manually execute the following command:`),t.log.print(`$`,d.default.yellow(m))}}};m&&new x().initialize().catch(e=>{console.error(e)}),exports.Main=x;
|
|
11
|
+
`),t.log.info(`${l} - Top-level enums barrel ${c?`merged`:`written`}.`)}async warnLegacyTopLevelEnums(e){let n=e.saveEnumFolderPath;try{let e=(await h.default.promises.readdir(n,{withFileTypes:!0})).filter(e=>e.isFile()&&e.name.endsWith(`.ts`)&&e.name!==`index.ts`).map(e=>e.name);e.length>0&&t.log.warning(`检测到 ${n} 顶层仍存在历史枚举文件(${e.slice(0,5).join(`, `)}${e.length>5?` ...`:``}),共 ${e.length} 个。\n若已切换到 enumIsolation: 'segment'(默认),建议执行 \`anl type\` 全量重生成或手动清理这些文件,避免与 ${n}/<segment>/ 下的隔离枚举混用。`)}catch{}}};b&&new C().initialize().catch(e=>{console.error(e)}),exports.Main=C;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const t=require(`../shared/format.cjs`),n=require(`../shared/naming.cjs`),r=require(`../shared/http.cjs`),i=require(`./naming.cjs`),a=require(`./schema-resolver.cjs`),o=require(`./writer.cjs`);var s=function(e){return e.GET=`get`,e.PUT=`put`,e.POST=`post`,e.DELETE=`delete`,e.OPTIONS=`options`,e.HEAD=`head`,e.PATCH=`patch`,e.TRACE=`trace`,e}(s||{});const c={typeMapping:new Map([[`integer`,`number`],[`string`,`string`],[`boolean`,`boolean`],[`binary`,`File`],[`number`,`number`],[`null`,`null`],[`undefined`,`undefined`]
|
|
1
|
+
const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const t=require(`../shared/format.cjs`),n=require(`../shared/naming.cjs`),r=require(`../shared/http.cjs`),i=require(`./naming.cjs`),a=require(`./schema-resolver.cjs`),o=require(`./writer.cjs`);var s=function(e){return e.GET=`get`,e.PUT=`put`,e.POST=`post`,e.DELETE=`delete`,e.OPTIONS=`options`,e.HEAD=`head`,e.PATCH=`patch`,e.TRACE=`trace`,e}(s||{});const c={typeMapping:new Map([[`integer`,`number`],[`string`,`string`],[`boolean`,`boolean`],[`binary`,`File`],[`number`,`number`],[`null`,`null`],[`undefined`,`undefined`]]),errorHandling:{throwOnError:!1,logErrors:!0}};var l=class{pathsObject={};nonArrayType=[`boolean`,`object`,`number`,`string`,`integer`];pathKey=``;contentBody={payload:{path:[],query:[],header:[],body:[]},response:``,_response:``,fileName:``,method:``,requestPath:``,summary:``,description:``,apiName:``,typeName:``,deprecated:!1,contentType:`application/json`};Map=new Map;config;errors=[];parameters={};schemas={};schemaResolver;writer;apiListFileContent=[];allowedInterfaceKeys=new Set;allInterfaceKeys=new Set;constructor(e,n,r,i,s){this.pathsObject=e,this.parameters=n??{},this.schemas=r??{},this.config=t.applyFormattingDefaults({...c,...i,typeMapping:new Map([...c.typeMapping??[],...i.typeMapping??[]])}),this.schemaResolver=new a.SchemaResolver(this.config,this.schemas,this.parameters,this.handleError.bind(this),s),this.writer=new o.PathWriter(this.config)}handleError(t){if(!t.path&&this.contentBody.requestPath&&(t.path=this.contentBody.requestPath),!t.method&&this.contentBody.method&&(t.method=this.contentBody.method),this.errors.push(t),this.config.errorHandling?.logErrors&&e.log.error(e.formatParseError(t)),this.config.errorHandling?.throwOnError)throw Error(`${t.type}: ${t.message}`)}getIndentation(){return t.getIndentation(this.config)}getDoubleIndentation(){let e=this.getIndentation();return e+e}generateParamComment(e,t){let n=[],r=[];if(e.description&&r.push(e.description),e.deprecated&&r.push(`@deprecated`),e.schema&&typeof e.schema==`object`&&`example`in e.schema){let t=e.schema.example,n=typeof t==`string`?t:JSON.stringify(t);r.push(`@example ${n}`)}if(e.schema&&typeof e.schema==`object`&&`default`in e.schema){let t=e.schema.default,n=typeof t==`string`?t:JSON.stringify(t);r.push(`@default ${n}`)}return r.length>0&&(r.length===1&&!r[0].includes(`
|
|
2
2
|
`)?n.push(`${t}/** ${r[0]} */`):(n.push(`${t}/**`),r.forEach(e=>{e.includes(`
|
|
3
3
|
`)?e.split(`
|
|
4
|
-
`).forEach(e=>{n.push(`${t} * ${e}`)}):n.push(`${t} * ${e}`)}),n.push(`${t} */`))),n}parametersItemHandle(
|
|
4
|
+
`).forEach(e=>{n.push(`${t} * ${e}`)}):n.push(`${t} * ${e}`)}),n.push(`${t} */`))),n}parametersItemHandle(r,i,a,o){let s=this.getDoubleIndentation(),c=`$ref`in r?r:null,l=`name`in r?r:null;if(c?.$ref&&c.$ref.startsWith(`#/components/parameters/`)&&this.parameters){let e=c.$ref.replace(`#/components/parameters/`,``),t=this.parameters[e];this.parametersItemHandle(t,i,a,o)}if(l){if(!l.schema){this.handleError({type:`PARAMETERS`,message:`Parameter "${l.name}" has no schema defined, skipping`});return}let r=this.schemaResolver.main(l.schema,`request`);if(!r||typeof r!=`string`){this.handleError({type:`PARAMETERS`,message:`Failed to parse schema for parameter "${l.name}"`,details:r});return}if(l.in===`path`){this.generateParamComment(l,s).forEach(e=>i.push(e));let e=n.sanitizeIdentifierName(l.name);i.push(`${s}type ${e} = ${t.indentContinuationLines(r,s)};`),this.contentBody.payload._path?this.contentBody.payload._path[e]=r:this.contentBody.payload._path={[e]:r}}else if(l.in===`query`){this.generateParamComment(l,s).forEach(e=>a.push(e));let e=l.required===!0?``:`?`,i=n.formatPropertyName(l.name);a.push(`${s}${i}${e}: ${t.indentContinuationLines(r,s)};`),this.contentBody.payload._query?this.contentBody.payload._query[l.name]=r:this.contentBody.payload._query={[l.name]:r}}else if(l.in===`header`){this.generateParamComment(l,s).forEach(e=>o.push(e));let e=l.required===!0?``:`?`,i=n.formatPropertyName(l.name);o.push(`${s}${i}${e}: ${t.indentContinuationLines(r,s)};`),this.contentBody.payload._header?this.contentBody.payload._header[l.name]=r:this.contentBody.payload._header={[l.name]:r}}else l.in===`cookie`?e.log.verbose(`Cookie parameter "${l.name}" detected but not added to type definition`):this.handleError({type:`PARAMETERS`,message:`Unknown parameter location "${l.in}" for parameter "${l.name}"`})}}requestParametersParse(e){let t=this.getIndentation(),n=[],r=[],i=[];e?.map(e=>this.parametersItemHandle(e,n,r,i)),n.length!==0&&(n.unshift(`${t}namespace Path {`),n.push(`${t}}`)),r.length!==0&&(r.unshift(`${t}interface Query {`),r.push(`${t}}`)),i.length!==0&&(i.unshift(`${t}interface Header {`),i.push(`${t}}`)),this.contentBody.payload.path=n,this.contentBody.payload.query=r,this.contentBody.payload.header=i}pickPreferredRequestMediaType(e){if(!(!e||typeof e!=`object`)){for(let t of[`multipart/form-data`,`application/x-www-form-urlencoded`,`application/json`])if(e[t])return t;return Object.keys(e).sort()[0]}}pickRequestBodyContent(e){let t=e.content;if(!t||typeof t!=`object`)return{mediaType:`application/json`,schema:null};let n=this.pickPreferredRequestMediaType(t),i=n&&r.SUPPORTED_REQUEST_TYPES_ALL.includes(n)?n:`application/json`,a=n?t[n]:null;return{mediaType:i,schema:a&&typeof a==`object`&&a.schema?a.schema:null}}requestBodyObjectParse(e){let n=this.getIndentation(),{schema:r}=this.pickRequestBodyContent(e);if(r){let e=this.schemaResolver.main(r,`request`);return`${n}type Body = ${t.indentContinuationLines(Array.isArray(e)?`{ ${e.join(`
|
|
5
|
+
`)} }`:e,n)};`}}requestBodyParse(e){if(!e)return`{}`;let t=`$ref`in e?e:null,n=`content`in e?e:null;if(t){let e=this.schemaResolver.referenceObjectParse(t,`request`);return`${this.getIndentation()}type Body = ${e}`}return n&&Object.keys(e).length!==0?this.requestBodyObjectParse(n):`{}`}normalizemodulePrefix(e){if(!e||e.trim()===``)return``;let t=e.trim();return t=t.replace(/\/+$/g,``),t.startsWith(`/`)||(t=`/`+t),t}apiRequestItemHandle(e){let{payload:t,requestPath:n,_response:i,method:a,typeName:o,apiName:s,contentType:c}=e,{_path:l,_query:u,body:d}=t,f=e.dataLevel??this.config.dataLevel??`serve`,p=this.normalizemodulePrefix(this.config.modulePrefix),m=()=>{let e=[],t=Object.keys(l??{}).sort();for(let n of t)e.push(`${n}: ${o}.Path.${n}`);let n=e.join(e.length>1?`,`:``);return n===``?n:n+`,`},h=()=>{let e=u?`query: ${o}.Query,`:``;return e===``?``:`${e}`},g=()=>{let e=d.length>0?`body: ${o}.Body,`:``;return e===``?``:`${e}`},_=m(),v=h(),y=g(),b=()=>{let e=r.SUPPORTED_REQUEST_UPLOAD_TYPES.includes(c)?`headers: { 'Content-Type': '${c}' }`:void 0;return[`{`,e?`${e},`:``,`...params, `,v===``?``:`query,`,y===``?``:`body,`,`},`].join(``)},x=(_+v+y).replace(/,$/,``);return[`export const ${s} = `,`(`,x,x===``?`params?: IRequestFnParams`:`, params?: IRequestFnParams`,`)`,` => `,a,`${i?`<${o}.Response>`:``}`,`(`,`\`${p}${n}\`,`,b(),`'${f}'`,`);`].join(``)}pickPreferredResponse(e){let t=e[200];if(t)return t;let n=Object.keys(e).filter(e=>/^2\d\d$/.test(e)).sort((e,t)=>Number(e)-Number(t));if(n.length>0)return e[n[0]];let r=e.default;if(r)return r}responseHandle(e){let n=this.pickPreferredResponse(e);if(!n){this.contentBody.response=`type Response = unknown`,this.contentBody._response=`unknown`;return}let r=`content`in n?n:null,i=`$ref`in n?n:null;if(r===null&&i===null&&(this.contentBody.response=`type Response = unknown`,this.contentBody._response=`unknown`),i){let e=this.schemaResolver.referenceObjectParse(i,`response`);this.config.responseModelTransform&&(e=this.schemaResolver.transformResponseModel(e,this.config.responseModelTransform)),this.contentBody.response=`type Response = ${e}`,this.contentBody._response=e}if(r){let e=this.schemaResolver.responseObjectParse(r);if(this.config.responseModelTransform&&(e=this.schemaResolver.transformResponseModel(e,this.config.responseModelTransform)),Array.isArray(e)){if(e.length===1&&e[0]===`unknown`)this.contentBody.response=`type Response = ${e.join(`
|
|
5
6
|
`)};`;else{let t=this.config.formatting?.lineEnding,n=this.config.formatting?.indentation;this.contentBody.response=`interface Response {${t}${e.join(`
|
|
6
7
|
`)}${t}${n}};`}this.contentBody._response=`${e.join(`
|
|
7
|
-
`)}`}else this.contentBody.response=`type Response = ${e}
|
|
8
|
+
`)}`}else this.contentBody.response=`type Response = ${t.indentContinuationLines(e,this.getIndentation())};`,this.contentBody._response=`${e}`}}requestHandle(e){if(e.parameters&&this.requestParametersParse(e.parameters),e.requestBody){let t=this.requestBodyParse(e.requestBody);if(Array.isArray(t))this.contentBody.payload.body=t;else if(t){let e=t?.split(`
|
|
8
9
|
`)||[];this.contentBody.payload.body=e}}}computeAllowedInterfaceKeys(){let e=[],t=Object.keys(this.pathsObject).sort();for(let n of t){let t=this.pathsObject[n];if(!t)continue;let r=Object.keys(t).sort();for(let i of r){let r=t[i];if(!r||typeof r!=`object`||!Object.values(s).includes(i))continue;let a=`${n}|${String(i).toUpperCase()}`,o=Array.isArray(r.tags)?r.tags:[];e.push({key:a,pathKey:n,method:i,tags:o})}}this.allInterfaceKeys=new Set(e.map(e=>e.key));let n;n=this.config.excludeTags&&this.config.excludeTags.length>0?new Set(e.filter(e=>!e.tags.some(e=>this.config.excludeTags.includes(e))).map(e=>e.key)):new Set(e.map(e=>e.key));let r;if(this.config.excludeInterface&&this.config.excludeInterface.length>0){let e=new Set(this.config.excludeInterface.map(e=>`${e.path}|${e.method.toUpperCase()}`));r=new Set([...n].filter(t=>!e.has(t)))}else r=new Set(n);let i;i=this.config.includeTags&&this.config.includeTags.length>0?new Set(e.filter(e=>r.has(e.key)&&e.tags.some(e=>this.config.includeTags.includes(e))).map(e=>e.key)):new Set;let a;if(this.config.includeInterface&&this.config.includeInterface.length>0){let e=new Set(this.config.includeInterface.map(e=>`${e.path}|${e.method.toUpperCase()}`));a=new Set([...r].filter(t=>e.has(t)))}else a=new Set;return i.size===0&&a.size===0?new Set(r):new Set([...i,...a])}parsePathItemObject(e,t,n){if(!e)return;let r=Object.keys(e).sort();for(let a of r){let r=e[a];if(r){let e=a.toUpperCase(),o=t+`|`+e;if(!this.allowedInterfaceKeys.has(o))continue;let s=this.config.includeInterface?.find(e=>t===e.path&&e.method===a),{apiName:c,typeName:l,fileName:u,path:d}=i.convertEndpointString(o,this.config),f=r.requestBody&&`content`in r.requestBody?this.pickRequestBodyContent(r.requestBody).mediaType:`application/json`;this.contentBody={payload:{path:[],query:[],header:[],body:[]},response:``,_response:``,fileName:u,method:e,typeName:l,requestPath:d,apiName:c,summary:r.summary,description:r.description,deprecated:r.deprecated??!1,contentType:f,dataLevel:s?.dataLevel},this.requestHandle(r),this.responseHandle(r.responses),r.summary&&n.push([`/**`,`
|
|
9
10
|
`,r.deprecated?` * @deprecated ${r.summary}`:` * ${r.summary}`,`
|
|
10
11
|
`,` */`].join(``));let p=this.apiRequestItemHandle(this.contentBody);if(n.push(p,``),!this.Map.has(o)){let{payload:e}=this.contentBody,t={...this.contentBody,payload:{...e,path:[...e.path],query:[...e.query],header:[...e.header],body:[...e.body]}};this.Map.set(o,t)}}}}parseData(){this.allowedInterfaceKeys=this.computeAllowedInterfaceKeys();let e=Object.keys(this.pathsObject).sort();for(let t of e){let e=this.pathsObject[t];e&&this.parsePathItemObject(e,t,this.apiListFileContent)}return this.Map}async writeFile(){if(await this.writer.write(this.Map,this.apiListFileContent,[]),this.Map=new Map,this.errors.length>0){e.log.warning(`Completed with ${this.errors.length} error(s):`);let t=new Map;for(let e of this.errors){let n=e.type;t.has(n)||t.set(n,[]),t.get(n).push(e)}for(let[n,r]of t){e.log.warning(` ${n}: ${r.length} error(s)`);for(let t of r){let n=[t.method,t.path].filter(Boolean).join(` `);e.log.warn(` ${n?n+` - `:``}${t.message}`)}}}}async handle(){try{this.parseData(),await this.writeFile()}catch(e){if(this.handleError({type:`SCHEMA`,message:`Failed to handle schema`,details:e}),this.config.errorHandling?.throwOnError)throw e}}getGeneratedInterfacesForOutput(){return[...this.allowedInterfaceKeys].sort().map(e=>{let t=e.lastIndexOf(`|`);return{path:e.slice(0,t),method:e.slice(t+1).toLowerCase()}})}getMissingInterfacesForOutput(){return[...this.allInterfaceKeys].filter(e=>!this.allowedInterfaceKeys.has(e)).sort().map(e=>{let t=e.lastIndexOf(`|`);return{path:e.slice(0,t),method:e.slice(t+1).toLowerCase()}})}};exports.default=l;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
const e=require(`../shared/format.cjs`),
|
|
2
|
-
`)}}
|
|
3
|
-
`);a.push(`${i}${e}?: {${n}\n${i}};`)}else a.push(`${i}${e}?: ${t};`);else a.push(`${i}${e}?: ${r};`);return a}case`replace`:return n.wrapperType?n.wrapperType:(this.handleError({type:`RESPONSE`,message:`wrapperType is required when using replace transform`}),t);default:return t}}catch(e){return this.handleError({type:`RESPONSE`,message:`Failed to transform response model`,details:e}),t}}responseObjectParse(e){try{let t=e.content;if(!t)return``;let n;for(let e of r.SUPPORTED_REQUEST_TYPES_ALL)if(t[e]?.schema){n=t[e].schema;break}return n?this.main(n):``}catch(e){return this.handleError({type:`RESPONSE`,message:`Failed to parse response object`,details:e}),``}}main(e){try{if(!e)return`unknown`;if(`oneOf`in e||`allOf`in e||`anyOf`in e||`enum`in e)return this.handleComplexType(e);if(`$ref`in e)return this.referenceObjectParse(e);let t=e,r=t.type,i=n.nullableSuffix(t.nullable),a=n.applyTypeMapping(this.config,t);if(a)return a;if(r===`array`&&t.items)return n.stringifyArrayType(this.main(t.items),this.config);if(r===`object`||typeof t==`object`){if(t.properties){let e=this.propertiesParse(t.properties);return e.length?e:[`unknown`]}if(t.additionalProperties===!0)return`Record<string, unknown>`+i;if(typeof t.additionalProperties==`object`)return`Record<string, ${this.main(t.additionalProperties)}>`+i}return`unknown`}catch(e){return this.handleError({type:`SCHEMA`,message:`Failed to parse schema`,details:e}),`unknown`}}};exports.SchemaResolver=a;
|
|
1
|
+
const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const t=require(`../shared/format.cjs`),n=require(`../shared/naming.cjs`),r=require(`../shared/schema-type.cjs`),i=require(`../shared/schema-utils.cjs`),a=require(`../shared/http.cjs`);var o=class{config;schemas;parameters;referenceCache=new Map;schemaDiagnostics=new Set;schemaNames;resolvedToOriginalName=new Map;handleError;constructor(e,t,r,i,a){this.diagnostics=a,this.config=e,this.schemas=t??{},this.schemaNames=n.createSchemaNameMap(t,e.enmuConfig.erasableSyntaxOnly),this.resolvedToOriginalName=new Map([...this.schemaNames].map(([e,t])=>[t,e])),this.parameters=r??{},this.handleError=i}stringifySchemaResult(e){if(Array.isArray(e)){let n=t.getLineEnding(this.config),r=t.getIndentation(this.config);return`{${n}${e.join(n)}${n}${r}}`}return e}handleComplexType(e){return this.stringifySchemaResult(this.main(e))}referenceObjectParse(e,t){try{let i=e.$ref,a=`${t??`shared`}:${i}`,o=this.referenceCache.get(a);if(o)return o;let s=r.resolveLocalSchemaReference(i,this.schemas,e=>this.handleError({type:`REFERENCE`,message:e}));if(!s)return`unknown`;let c=s.name,l=this.schemaNames.get(c),u=n.typeNameToFileName(l),d=this.schemas?.[c],f=!1;if(d&&!(`$ref`in d)){let e=`properties`in d||d.type===`object`,t=d.type===`array`||`items`in d;r.isNamedEnumSchema(d)&&!e&&!t&&(f=!0)}let p=f?n.getEnumTypeName(this.config,l):r.directionalTypeName(l,s.schema,this.schemas,t),m=n.getServerSegment(this.config),h=n.appendEnumSegment(n.adjustImportPathForSegment(this.config.importEnumPath??``,m),n.getEnumSegment(this.config)),g=m?`../../models/${m}`:`../models`,_=f?`import('${h}/${u}').${p}`:`import('${g}/${u}').${p}`;return this.referenceCache.set(a,_),_}catch(e){return this.handleError({type:`REFERENCE`,message:`Failed to parse reference object`,details:e}),`unknown`}}nonArraySchemaObjectParse(e){return this.main(e)}arraySchemaObjectParse(e){return e.type===`array`?this.stringifySchemaResult(this.main(e)):``}propertiesParse(e){return i.formatObjectProperties(e,this.config,e=>this.main(e))}transformResponseModel(e,n){if(!n)return e;if(n.modelPattern&&typeof e==`string`){let t=/^import\('[^']+'\)\.([\w$]+)(?:\.(?:Request|Response))?$/.exec(e),r=t?t[1]:e,i=new RegExp(n.modelPattern);if(!i.test(this.resolvedToOriginalName.get(r)??r)&&!i.test(r))return e}try{switch(n.type){case`unwrap`:{let t=n.dataField??`data`;if(Array.isArray(e))return this.handleError({type:`RESPONSE`,message:`Response model unwrap is not supported for inline object response types`}),e;let r=/^import\('([^']+)'\)\.([\w$]+)(?:\.(?:Request|Response))?$/.exec(e);if(r){let[,e,n]=r,i=this.resolvedToOriginalName.get(n)??n,a=this.schemas?.[i];if(a&&!(`$ref`in a)){let e=a;if(e.properties?.[t]){let n=e.properties[t];return this.main(n,`response`)}else this.handleError({type:`RESPONSE`,message:`Field "${t}" not found in response type "${n}"`})}}return e}case`wrap`:{if(!n.wrapperFields)return this.handleError({type:`RESPONSE`,message:`wrapperFields is required when using wrap transform`}),e;let r=t.getIndentation(this.config),i=r+r,a=[],o=n.dataField??`data`;for(let[r,s]of Object.entries(n.wrapperFields))if(r===o)if(Array.isArray(e)){let t=e.join(`
|
|
2
|
+
`);a.push(`${i}${r}?: {${t}\n${i}};`)}else a.push(`${i}${r}?: ${t.indentContinuationLines(e,i)};`);else a.push(`${i}${r}?: ${s};`);return a}case`replace`:return n.wrapperType?n.wrapperType:(this.handleError({type:`RESPONSE`,message:`wrapperType is required when using replace transform`}),e);default:return e}}catch(t){return this.handleError({type:`RESPONSE`,message:`Failed to transform response model`,details:t}),e}}responseObjectParse(e){try{let t=e.content;if(!t)return`unknown`;let n;for(let e of a.SUPPORTED_REQUEST_TYPES_ALL)if(t[e]?.schema){n=t[e].schema;break}return n??=Object.keys(t).sort().map(e=>t[e].schema).find(e=>e!==void 0),n?this.main(n,`response`):`unknown`}catch(e){return this.handleError({type:`RESPONSE`,message:`Failed to parse response object`,details:e}),`unknown`}}main(n,i){try{return n?r.renderSchemaType(n,{schemaPath:e=>this.diagnostics?.pathFor(e),indentation:t.getIndentation(this.config),direction:i,schemas:this.schemas,reference:e=>this.referenceObjectParse({$ref:e},i),mapping:e=>this.config.typeMapping?.get(e.format??``)??this.config.typeMapping?.get(e.type??``),diagnostic:(t,n,r)=>{if(this.diagnostics){this.diagnostics.add(t,n,r);return}let i=`${r}: ${n}: ${t}`;this.schemaDiagnostics.has(i)||(this.schemaDiagnostics.add(i),r===`runtime`?e.log.verbose(`${n}: ${t}`):e.log.warn(`${n}: ${t}`))}}):`unknown`}catch(e){return this.handleError({type:`SCHEMA`,message:`Failed to parse schema`,details:e}),`unknown`}}};exports.SchemaResolver=o;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const e=require(`../../utils/logger.cjs`),t=require(`../../utils/index.cjs`),n=require(`../shared/format.cjs`),r=require(`../shared/naming.cjs`),i=require(`../shared/constants.cjs`);var a=class{config;formatFileHeaderComment(e){if(!e)return[];let t=e.split(`
|
|
2
2
|
`).map(e=>e.replace(/\*\//g,`*\\/`));return t.length===1?[`/** ${t[0]} */`]:[`/**`,...t.map(e=>` * ${e}`),` */`]}constructor(e){this.config=e}async write(a,o,s){let c=this.config.saveTypeFolderPath,l=r.getServerSegment(this.config),u=l?`${c}/connectors/${l}`:`${c}/connectors`,d=async(r,a)=>{let{payload:o,response:c,fileName:l}=a,[,d]=r.split(`|`);s.includes(d)||s.push(d);let f=this.formatFileHeaderComment(a.description),p=[...f,...f.length?[``]:[],`declare namespace ${a.typeName} {`,...o.path,...o.query,...o.header,...o.body,`${n.getIndentation(this.config)}${c}`,`}`],m=`${u}/${l}.d.ts`;await t.writeFileRecursive(m,p.join(`
|
|
3
|
-
`)),e.log.info(`${m.padEnd(i.PAD_END)} - Write done!`)};await t.runWithConcurrency(Array.from(a.entries()).sort((e,t)=>e[0].localeCompare(t[0])),32,([e,t])=>d(e,t)),s.sort(),o.unshift(`import { ${s.join(`, `)} } from '${this.config.requestMethodsImportPath||`./api`}';`,`
|
|
3
|
+
`).replace(/\r?\n/g,n.getLineEnding(this.config))),e.log.info(`${m.padEnd(i.PAD_END)} - Write done!`)};await t.runWithConcurrency(Array.from(a.entries()).sort((e,t)=>e[0].localeCompare(t[0])),32,([e,t])=>d(e,t)),s.sort(),o.unshift(`import { ${s.join(`, `)} } from '${this.config.requestMethodsImportPath||`./api`}';`,`
|
|
4
4
|
`);let f=this.config.apiListFileName??`index.ts`,p=`${this.config.saveApiListFolderPath}/${f}`;await t.clearDir(p),await t.writeFileRecursive(p,o.join(`
|
|
5
5
|
`)),e.log.step(`Paths parsed & written`)}};exports.PathWriter=a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
exports.PAD_END=100;
|
|
1
|
+
const e=[`axios`,`fetch`,`wx`,`uniapp`,`taro`],t=[`dio.ts`,`error-message.ts`,`fetch.ts`,`api-type.d.ts`],n=/@an-cli-request-template:\s*([a-z]+)/i,r=[`.prettierrc`,`.prettierrc.json`,`.prettierrc.json5`,`.prettierrc.yaml`,`.prettierrc.yml`,`.prettierrc.js`,`.prettierrc.cjs`,`.prettierrc.mjs`,`.prettierrc.ts`,`.prettierrc.cts`,`.prettierrc.mts`,`prettier.config.js`,`prettier.config.cjs`,`prettier.config.mjs`,`prettier.config.ts`,`prettier.config.cts`,`prettier.config.mts`];exports.DEFAULT_REQUEST_TEMPLATE=`axios`,exports.PAD_END=100,exports.PRETTIER_CONFIG_FILES=r,exports.REQUIRED_TEMPLATE_FILES=t,exports.SUPPORTED_REQUEST_TEMPLATES=e,exports.TEMPLATE_MARKER_RE=n;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
function e(e){let t={indentation:e.formatting?.indentation??` `,lineEnding:e.formatting?.lineEnding??`
|
|
2
2
|
`};return{...e,formatting:t}}function t(e){return e.formatting?.indentation??` `}function n(e){return e.formatting?.lineEnding??`
|
|
3
|
-
`}exports.applyFormattingDefaults=e,exports.getIndentation=t,exports.getLineEnding=n;
|
|
3
|
+
`}function r(e,t){return e.replace(/\r?\n/g,`\n${t}`)}exports.applyFormattingDefaults=e,exports.getIndentation=t,exports.getLineEnding=n,exports.indentContinuationLines=r;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
require(`../../_virtual/rolldown_runtime.cjs`);const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);let t=require(`pinyin-pro`);function
|
|
1
|
+
require(`../../_virtual/rolldown_runtime.cjs`);const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);let t=require(`node:crypto`),n=require(`pinyin-pro`);function r(e){return/[\u4e00-\u9fff]/.test(e)}function i(e){return e?e.charAt(0).toUpperCase()+e.slice(1):``}function a(e){return e.split(/[^a-zA-Z0-9_]+/).filter(Boolean).map(e=>i(e)).join(``)}function o(e){return r(e)?(e.match(/[\u4e00-\u9fff]+|[^\u4e00-\u9fff]+/g)??[]).map(e=>r(e)?(0,n.pinyin)(e,{toneType:`none`,type:`array`}).map(e=>i(e)).join(``):a(e)).join(``):e}function s(e){return e?/^[0-9]/.test(e)?`_${e}`:e:`Unknown`}function c(e){return s(e.split(/[^a-zA-Z0-9$\u4e00-\u9fff]+/).filter(Boolean).map(e=>i(o(e))).join(`_`))}function l(e,n=!1){let r=Object.keys(e??{}).sort().map(t=>{let r=e[t],i=n&&!(`$ref`in r)&&!!r.enum?.length&&[`string`,`number`,`integer`].includes(r.type??``);return{raw:t,name:c(t),hasEnumAlias:i}}),i=(e,t)=>[`file:${u(e)}`,`type:${e}`,...t?[`type:${e}Type`]:[]],a=new Map([[`file:index`,1]]);for(let{name:e,hasEnumAlias:t}of r)for(let n of i(e,t))a.set(n,(a.get(n)??0)+1);let o=new Set(a.keys()),s=new Map;for(let{raw:e,name:n,hasEnumAlias:c}of r){if(i(n,c).every(e=>a.get(e)===1)){s.set(e,n);continue}let r=(0,t.createHash)(`sha256`).update(e).digest(`hex`).slice(0,8),l=`${n}_${r}`,u=2;for(;i(l,c).some(e=>o.has(e));)l=`${n}_${r}_${u++}`;for(let e of i(l,c))o.add(e);s.set(e,l)}return s}function u(e){return e.replace(/[^a-zA-Z0-9]+/g,`-`).replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase().replace(/-+/g,`-`).replace(/^-|-$/g,``)||`unknown`}function d(e){let t=(e??``).trim();return t?(t.split(/[\\/]/).pop()??``).replace(/\.[^.]+$/,``).replace(/[^a-zA-Z0-9_-]+/g,`-`).replace(/^-+|-+$/g,``):``}function f(e,t){return(e.name??d(e.apiListFileName))||`#${t}`}function p(e){return(e.enumIsolation??`segment`)===`segment`}function m(e){return e.__segment??``}function h(e){if(!e)return``;let t=e.split(/[-_.]+/).filter(Boolean).map(e=>i(e.toLowerCase())).join(``);return t?/^[0-9]/.test(t)?`_${t}`:t:``}function g(e){let t=e.__namespacePrefix;return typeof t==`string`?t:(e.namespaceIsolation??`segment`)===`none`?``:h(m(e))}function _(e){let t=e.apiListFileName?.replace(/\.[^/.]+$/,``).trim();if(t)return`【${t}】`;let n=m(e);if(n)return`【${n}】`;let r=e.swaggerJsonUrl;if(r)try{let e=new URL(r).host;if(e)return`【${e}】`}catch{}return``}function v(t,n){return!n||!t?t:t.startsWith(`./`)||t.startsWith(`../`)?`../`+t:(t.startsWith(`/`)||/^[a-zA-Z@]/.test(t)||e.log.warning(`importEnumPath="${t}" 形态不明确,建议以 "./" 或 "../" 开头。多服务隔离已开启,工具未自动补偿层级,请自行确认 enum 引用是否正确。`),t)}function y(e){let t=m(e);return!t||(e.enumIsolation??`segment`)===`none`?``:t}function b(e,t){return t?e?`${e.replace(/\/+$/,``)}/${t}`:t:e}function x(e,t){return e.enmuConfig.erasableSyntaxOnly?`${t}Type`:t}function S(e){return!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)}function C(e){return S(e)?`"${e}"`:e}function w(e){return e&&e.replace(/-/g,`_`)}exports.adjustImportPathForSegment=v,exports.appendEnumSegment=b,exports.computeSegment=d,exports.createSchemaNameMap=l,exports.formatPropertyName=C,exports.getEnumSegment=y,exports.getEnumTypeName=x,exports.getNamespacePrefix=g,exports.getServerSegment=m,exports.getServiceIdentifier=f,exports.getServiceTag=_,exports.isEnumIsolated=p,exports.resolveSchemaName=c,exports.sanitizeIdentifierName=w,exports.segmentToNamespacePrefix=h,exports.typeNameToFileName=u;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function t(t,n=()=>void 0){let r=`openapi`in t?t.openapi:void 0;if(r&&!/^3\.[01]\.\d+$/.test(r))throw Error(`Unsupported OpenAPI version: ${r}. Schema generation supports OpenAPI 3.0.x and 3.1.x.`);if(!r?.startsWith(`3.1.`))return t;let i=t=>{if(t===!0)return{};if(t===!1)return{enum:[]};if(!e(t))return t;let r={...t};for(let t of[`properties`,`$defs`,`patternProperties`,`dependentSchemas`]){let n=r[t];e(n)&&(r[t]=Object.fromEntries(Object.entries(n).map(([e,t])=>[e,i(t)])))}for(let e of[`items`,`additionalProperties`,`not`,`contains`,`propertyNames`,`unevaluatedProperties`,`if`,`then`,`else`])e in r&&(e===`additionalProperties`&&typeof r[e]==`boolean`||(r[e]=i(r[e])));for(let e of[`allOf`,`anyOf`,`oneOf`,`prefixItems`]){let t=r[e];Array.isArray(t)&&(r[e]=t.map(i))}let a=Array.isArray(r.allOf)?[...r.allOf]:[];`$ref`in r&&Object.keys(r).length>1&&(a.push({$ref:r.$ref}),delete r.$ref),r.type===`null`?(delete r.type,a.push({enum:[null]})):Array.isArray(r.type)&&(a.push({anyOf:r.type.map(e=>i({type:e}))}),delete r.type),`const`in r&&(a.push({enum:[r.const]}),delete r.const),`nullable`in r&&(n(`OpenAPI 3.1 nullable is ignored; use type: null or a null union branch.`),delete r.nullable);for(let e of[`exclusiveMinimum`,`exclusiveMaximum`])if(typeof r[e]==`number`){let t=e===`exclusiveMinimum`?`minimum`:`maximum`,n=r[e],i=r[t];typeof i!=`number`||(t===`minimum`?n>=i:n<=i)?(r[t]=n,r[e]=!0):delete r[e]}return r.type===`array`&&!(`items`in r)&&(r.items={}),a.length&&(r.allOf=a),r},a=t=>Array.isArray(t)?t.map(a):e(t)?Object.fromEntries(Object.entries(t).map(([t,n])=>t===`schema`?[t,i(n)]:t===`schemas`&&e(n)?[t,Object.fromEntries(Object.entries(n).map(([e,t])=>[e,i(t)]))]:[`example`,`examples`,`default`,`enum`].includes(t)||t.startsWith(`x-`)?[t,n]:[t,a(n)])):t;return a(t)}exports.normalizeOpenApiDocument=t;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const e=require(`../../_virtual/rolldown_runtime.cjs`),t=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const n=require(`./naming.cjs`),r=require(`./constants.cjs`);let i=require(`fs`);i=e.__toESM(i);let a=require(`path`);a=e.__toESM(a);let o=require(`chalk`);o=e.__toESM(o);let s=require(`cross-spawn`);async function c(){let e=a.default.join(process.cwd(),`node_modules`,`.bin`,process.platform===`win32`?`prettier.cmd`:`prettier`);try{return await i.default.promises.access(e,i.default.constants.X_OK),t.log.info(`Using local prettier: ${e}`),{command:e,args:[]}}catch{return{command:`npx`,args:[`prettier`]}}}async function l(){for(let e of r.PRETTIER_CONFIG_FILES){let n=a.default.join(process.cwd(),e);try{return await i.default.promises.access(n),t.log.info(`Auto-detected prettier config: ${e}`),n}catch{continue}}try{let e=a.default.join(process.cwd(),`package.json`);if(JSON.parse(await i.default.promises.readFile(e,`utf8`)).prettier)return t.log.info(`Using prettier config from package.json`),e}catch{return null}return null}async function u(e){if(typeof e==`string`&&e.trim()){let n=a.default.resolve(process.cwd(),e.trim());try{return await i.default.promises.access(n),[`--config`,n]}catch{t.log.warning(`Prettier config file not found: ${e}, falling back to auto-detection...`)}}let n=await l();return n?[`--config`,n]:[]}async function d(e,t){let r=[];if(t){let{servers:i,selectedIndices:a,segments:o,isolateBySegment:s}=t;for(let t of a){r.push({path:`${e.saveApiListFolderPath}/${i[t].apiListFileName}`});let a=s?o[t]:``;for(let t of[`connectors`,`models`])r.push({path:`${e.saveTypeFolderPath}/${t}${a?`/${a}`:``}`,pattern:`**/*.{ts,d.ts}`});let c=a&&n.isEnumIsolated(i[t])?a:``;r.push({path:`${e.saveEnumFolderPath}${c?`/${c}`:``}`,pattern:c?`**/*.{ts,d.ts}`:`*.ts`})}}else r.push({path:e.saveTypeFolderPath,pattern:`**/*.{ts,d.ts}`},{path:e.saveApiListFolderPath,pattern:`**/*.ts`},{path:e.saveEnumFolderPath,pattern:`**/*.ts`});let a=new Set;for(let e of r)try{await i.default.promises.access(e.path),a.add(`${e.path}${e.pattern?`/${e.pattern}`:``}`.replace(/\\/g,`/`))}catch{continue}return[...a]}async function f(e,n,r){let i=await d(e,r);if(!i.length){t.log.warning(r?`No files to format for the selected services.`:`No generated directories found to format.`);return}let a=await c(),l=await u(n),f=[...a.args,`--write`,...i,...l],p=[a.command,...f].map(e=>JSON.stringify(e)).join(` `);try{t.spinner.start(r?`Formatting selected files...`:`Formatting generated files...`);let{stdout:e,stderr:n}=await new Promise((e,t)=>{let n=(0,s.spawn)(a.command,f,{stdio:[`ignore`,`pipe`,`pipe`]}),r=``,i=``;n.stdout?.setEncoding(`utf8`).on(`data`,e=>{r+=e}),n.stderr?.setEncoding(`utf8`).on(`data`,e=>{i+=e}),n.on(`error`,t),n.on(`close`,n=>{n===0?e({stdout:r,stderr:i}):t(Error(i||`Prettier exited with code ${String(n)}`))})});e&&t.log.print(e),n&&t.log.print(n,`
|
|
2
|
+
$`,o.default.yellow(p),`
|
|
3
|
+
`),t.spinner.success(`File formatting successful`),t.log.print(`
|
|
4
|
+
`)}catch(e){t.spinner.error(`Format failed`),t.log.print(e),t.log.error(`Format failed. Executable and arguments:`),t.log.print(`$`,o.default.yellow(p))}}exports.formatGeneratedFiles=f;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require(`../../_virtual/rolldown_runtime.cjs`),t=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const n=require(`./constants.cjs`);let r=require(`fs`);r=e.__toESM(r);let i=require(`path`);i=e.__toESM(i);let a=require(`chalk`);a=e.__toESM(a);function o(e,t){if(e==null||e===``)return n.DEFAULT_REQUEST_TEMPLATE;if(typeof e!=`string`)throw Error(`${t} 中的 requestTemplate 类型无效(期望字符串,实际 ${typeof e}),支持的值:${n.SUPPORTED_REQUEST_TEMPLATES.join(` | `)}`);let r=e.trim().toLowerCase();if(!n.SUPPORTED_REQUEST_TEMPLATES.includes(r))throw Error(`${t} 中的 requestTemplate="${e}" 无效,支持的值:${n.SUPPORTED_REQUEST_TEMPLATES.join(` | `)}`);return r}async function s(e){try{let t=await r.default.promises.readFile(i.default.join(e,`dio.ts`),`utf8`);return n.TEMPLATE_MARKER_RE.exec(t.slice(0,500))?.[1].toLowerCase()??null}catch{return null}}async function c(e,o,c){let l=i.default.join(c,o),u=i.default.join(c,`_shared`),d=i.default.join(e,`config`);if(await r.default.promises.access(d).then(()=>!0,()=>!1)){let e=await s(d);e&&e!==o?t.log.warning(`config folder exists at ${d}, but its embedded marker "${e}" differs from configured requestTemplate="${o}". To switch templates, delete the folder "${d}" first.`):(t.log.info(`config folder already exists at ${d}, skipping generation. (template=${o})`),t.log.info(` To switch templates, delete the folder "${d}" first.`));return}let f=[];for(let e of n.REQUIRED_TEMPLATE_FILES){let t=i.default.join(l,e),n=i.default.join(u,e),a;try{await r.default.promises.access(t),a=t}catch{try{await r.default.promises.access(n),a=n}catch{throw Error(`Source file not found for template "${o}": ${e} (looked in ${l} and ${u})`)}}f.push({file:e,sourceFile:a})}await r.default.promises.mkdir(d,{recursive:!0}),t.log.info(`Using request template: ${a.default.cyan(o)} (template dir: ${l}, shared dir: ${u})`);try{for(let{file:e,sourceFile:a}of f){let s=i.default.join(d,e);if(e===`dio.ts`){let e=await r.default.promises.readFile(a,`utf8`),t=n.TEMPLATE_MARKER_RE.test(e)?e:`// @an-cli-request-template: ${o} — 切换请求模板前请删除本 config/ 目录后重新运行 anl type\n${e}`;await r.default.promises.writeFile(s,t)}else await r.default.promises.copyFile(a,s);t.log.success(`${e} create done.`)}}catch(e){throw await r.default.promises.rm(d,{recursive:!0,force:!0}).catch(()=>void 0),e instanceof Error?e:Error(String(e))}}exports.copyAjaxConfigFiles=c,exports.normalizeRequestTemplate=o;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=class{locations=new WeakMap;groups=new Map;constructor(e){let t=(e,n)=>{if(!(!e||typeof e!=`object`||this.locations.has(e))){this.locations.set(e,n);for(let[r,i]of Object.entries(e))[`example`,`examples`,`default`,`enum`].includes(r)||r.startsWith(`x-`)||t(i,`${n}/${r.replace(/~/g,`~0`).replace(/\//g,`~1`)}`)}};t(e,`#`)}pathFor(e){return this.locations.get(e)}add(e,t=`#`,n=`warning`){let r=`${n}:${e}`,i=this.groups.get(r)??{message:e,kind:n,paths:new Set};i.paths.add(t),this.groups.set(r,i)}flush(e){for(let t of[`warning`,`runtime`]){let n=[...this.groups.values()].filter(e=>e.kind===t).sort((e,t)=>e.message.localeCompare(t.message));if(!n.length)continue;let r=n.reduce((e,t)=>e+t.paths.size,0),i=`${t===`warning`?`Schema warnings`:`Schema runtime validation`}: ${r} unique finding(s), ${n.length} category(s).`;t===`runtime`&&e(`${i} TypeScript types do not enforce these constraints; validate payloads at runtime. Use --log-level verbose for details.`,`info`);let a=[i];for(let{message:e,paths:t}of n){a.push(`- ${e}`);for(let e of[...t].sort())a.push(` ${e}`)}e(a.join(`
|
|
2
|
+
`),t===`warning`?`warn`:`verbose`)}this.groups.clear()}};exports.SchemaDiagnostics=e;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const e=require(`./naming.cjs`);function t(e,t){let n=new Set;for(;e&&`$ref`in e;){if(n.has(e.$ref))return;n.add(e.$ref),e=a(e.$ref,t,()=>void 0)?.schema}return e}function n(e,r,i,o=new Set){if(!e||typeof e!=`object`)return!1;if(`$ref`in e)return o.has(e.$ref)?!1:(o.add(e.$ref),n(a(e.$ref,r,()=>void 0)?.schema,r,i,o));for(let a of Object.values(e.properties??{})){let e=t(a,r);if((i===`request`?e?.readOnly:e?.writeOnly)||n(a,r,i,o))return!0}let s=[...e.allOf??[],...e.anyOf??[],...e.oneOf??[]];return e.type===`array`&&s.push(e.items),e.additionalProperties&&typeof e.additionalProperties==`object`&&s.push(e.additionalProperties),s.some(e=>n(e,r,i,o))}function r(e,t,r,i){return i&&n(t,r,i)?`${e}.${i===`request`?`Request`:`Response`}`:e}function i(e){return!(`$ref`in e)&&e.type===`object`&&!!Object.keys(e.properties??{}).length&&!!e.additionalProperties&&typeof e.additionalProperties==`object`}function a(e,t,n){let r=new Set,i=e,a;for(;;){let o;try{o=decodeURIComponent(i)}catch{n(`Invalid schema reference: ${i}.`);return}let s=/^#\/(?:components\/schemas|definitions)\/([^/]+)$/.exec(o);if(!s){n(`Unsupported schema reference: ${i}. Only local component references are supported.`);return}let c=s[1].replace(/~1/g,`/`).replace(/~0/g,`~`);if(r.has(c)){n(`Circular schema aliases: ${e}.`);return}r.add(c);let l=t&&Object.hasOwn(t,c)?t[c]:void 0;if(!l||typeof l!=`object`){n(`Unresolved schema reference: ${i}.`);return}if(a??={name:c,schema:l},!(`$ref`in l))return a;i=l.$ref}}function o(e,t){let n=t===` | `,r=n?`unknown`:`never`,i=n?`never`:`unknown`;if(e.includes(r))return r;let a=[...new Set(e.filter(e=>e!==i))];return a.length?a.length===1?a[0]:a.map(e=>e.includes(` | `)||e.includes(` & `)?`(${e})`:e).join(t):i}function s(e){return e===null?`null`:typeof e==`string`||typeof e==`boolean`||typeof e==`number`&&Number.isFinite(e)?JSON.stringify(e):Array.isArray(e)?`[${e.map(s).join(`, `)}]`:e&&typeof e==`object`?`{ ${Object.entries(e).map(([e,t])=>`${JSON.stringify(e)}: ${s(t)};`).join(` `)} }`:`never`}function c(e,t){if(!t.type)return!0;if(e===null)return t.nullable===!0;switch(t.type){case`integer`:return typeof e==`number`&&Number.isInteger(e);case`number`:return typeof e==`number`&&Number.isFinite(e);case`array`:return Array.isArray(e);case`object`:return typeof e==`object`&&!Array.isArray(e);case`string`:return typeof e==`string`;case`boolean`:return typeof e==`boolean`;default:return!1}}function l(e,n){if(!e.allOf?.length)return;let r=new Set([`type`,`properties`,`required`,`additionalProperties`,`items`,`allOf`,`title`,`description`,`example`,`deprecated`,`readOnly`,`writeOnly`]),i=new Set(n.allOfAncestors),a=[],o=new Map,s=(e,c=new Set)=>{if(!e||typeof e!=`object`||Array.isArray(e)||c.has(e)||n.allOfAncestors?.has(e))return!1;let l=t(e,n.schemas);if(!l||c.has(l)||n.allOfAncestors?.has(l)||Object.keys(l).some(e=>!r.has(e))||n.mapping?.(l)||l.type!==void 0&&l.type!==`object`&&l.type!==`array`||l.additionalProperties!==void 0&&l.additionalProperties!==!0||l.allOf&&!l.allOf.length)return!1;i.add(e),i.add(l),`$ref`in e&&o.set(l,e);let u=new Set([...c,e,l]);return a.push(l),(l.allOf??[]).every(e=>s(e,u))};if(!s(e))return;let c=new Set(a.map(e=>e.type).filter(e=>e!==void 0));if(c.size!==1)return;let l=e=>{let r=[...new Set(e)];if(r.length===1)return r[0];let i=r.map(e=>e&&typeof e==`object`&&!Array.isArray(e)?t(e,n.schemas):void 0);return{allOf:r,description:i.find(e=>e?.description)?.description,readOnly:i.some(e=>e?.readOnly),writeOnly:i.some(e=>e?.writeOnly)}};if(c.has(`array`)){if(a.some(e=>e.properties!==void 0||e.required!==void 0||e.additionalProperties!==void 0))return;let e=a.filter(e=>e.type===`array`);return e.some(e=>!e.items)?void 0:{schema:{type:`array`,items:l(e.map(e=>e.items))},ancestors:i}}if(a.some(e=>`items`in e))return;let u=a.filter(e=>Object.keys(e.properties??{}).length||e.required?.length);if(u.length===1&&u[0].type===`object`){let e=o.get(u[0]);if(e)return{schema:e,ancestors:i}}let d=new Map,f=new Set;for(let e of a){for(let t of e.required??[])f.add(t);for(let[t,n]of Object.entries(e.properties??{}))d.set(t,[...d.get(t)??[],n])}return{schema:{type:`object`,properties:Object.fromEntries([...d].map(([e,t])=>[e,l(t)])),required:[...f]},ancestors:i}}function u(n,r){let a=(n&&typeof n==`object`?r.schemaPath?.(n):void 0)??r.path??`#`,d=(e,t=`warning`)=>r.diagnostic?.(e,a,t);if(!n||typeof n!=`object`||Array.isArray(n))return d(`Invalid OpenAPI 3.0 schema; using unknown. Boolean schemas require OpenAPI 3.1.`),`unknown`;if(`$ref`in n)return r.reference(n.$ref);let f=[`pattern`,`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`,`multipleOf`,`minLength`,`maxLength`,`minItems`,`maxItems`,`uniqueItems`,`minProperties`,`maxProperties`,`not`].filter(e=>n[e]!==void 0);f.length&&d(`Validation constraints (${f.join(`, `)}) are not enforced by TypeScript; validate payloads at runtime.`,f.includes(`not`)?`warning`:`runtime`);for(let e of[`const`,`prefixItems`,`patternProperties`,`unevaluatedProperties`,`$schema`,`$id`,`if`,`then`,`else`])e in n&&d(`Unsupported schema keyword for TypeScript generation: ${e}.`);n.nullable&&!n.type&&d(`OpenAPI 3.0 nullable requires type in the same schema; nullable was ignored.`);let p=l(n,r);if(p)return u(p.schema,{...r,path:a,allOfAncestors:p.ancestors});let m=(e,t)=>u(e,{...r,exactObject:!1,path:`${a}/${t}`}),h=e=>{if(r.indentation===void 0&&!e.some(e=>e.includes(`
|
|
2
|
+
`)))return`{ ${e.join(` `)} }`;let t=r.indentation??` `;return`{\n${e.join(`
|
|
3
|
+
`).split(`
|
|
4
|
+
`).map(e=>`${t}${e}`).join(`
|
|
5
|
+
`)}\n}`},g=()=>{let a=n.properties??{},s=new Set(n.required??[]),c=[...new Set([...Object.keys(a),...s])].sort(),l=n.additionalProperties,u=l===!1?`never`:l===void 0||l===!0?`unknown`:m(l,`additionalProperties`);if(l===!1&&[...s].some(e=>!Object.hasOwn(a,e)))return`never`;if(!c.length)return`Record<string, ${u}>`;let f=[],p=c.map(n=>{let i=Object.hasOwn(a,n)?a[n]:void 0,o=t(i,r.schemas);if(o?.readOnly&&o.writeOnly&&d(`Property ${n} cannot be both readOnly and writeOnly.`),r.direction===`request`?o?.readOnly:r.direction===`response`&&o?.writeOnly)return f.push(`undefined`),`${e.formatPropertyName(n)}?: never;`;let c=s.has(n),l=i&&typeof i==`object`&&!Array.isArray(i),p=`properties/${n.replace(/~/g,`~0`).replace(/\//g,`~1`)}`,h=l?r.property?.(i,n,c)??m(i,p):i===void 0?u:m(i,p);f.push(h),c||f.push(`undefined`);let g=l&&!(`$ref`in i)?r.comment?.(i):``;return`${g?`${g}\n`:``}${e.formatPropertyName(n)}${c?``:`?`}: ${h};`});if(l!==!1){if(r.exactObject&&i(n)){let e=c.map(e=>JSON.stringify(e)).join(` | `);return`${h(p)} & ${h([`[Key in Exclude<keyof Value, ${e}>]: ${u};`])}`}u!==`unknown`&&d(`Fixed properties and additionalProperties use a widened index signature; extra property values require runtime validation.`),p.push(`[key: string]: ${o([u,...f],` | `)};`)}else d(`TypeScript structural types cannot enforce additionalProperties: false on non-empty objects.`,`runtime`);return h(p)},_;switch(n.type){case`string`:_=n.format===`binary`?`File`:`string`;break;case`integer`:case`number`:_=`number`;break;case`boolean`:_=`boolean`;break;case`array`:_=`Array<${m(n.items,`items`)}>`;break;case`object`:_=g();break;case void 0:_=n.properties||n.required||n.additionalProperties!==void 0?o([g(),`string`,`number`,`boolean`,`null`,`Array<unknown>`],` | `):`unknown`;break;default:d(`Unsupported OpenAPI 3.0 type; using unknown.`),_=`unknown`}n.type&&n.nullable&&(_=o([_,`null`],` | `));let v=r.mapping?.(n);if(v&&(_=n.type&&n.nullable?o([v,`null`],` | `):v),Array.isArray(n.enum)){let e=o(n.enum.filter(e=>c(e,n)).map(s),` | `);_=n.type===`object`||n.type===`array`?o([_,e],` & `):e}let y=[_];for(let e of[`allOf`,`anyOf`,`oneOf`]){let t=n[e];if(t){if(!t.length){d(`${e} must contain at least one schema.`);continue}e===`oneOf`&&t.length>1&&d(`oneOf is approximated as a TypeScript union; exactly-one matching requires runtime validation.`),y.push(o(t.map((t,n)=>m(t,`${e}/${n}`)),e===`allOf`?` & `:` | `))}}return o(y,` & `)}function d(e){return(e.type===`string`||e.type===`number`||e.type===`integer`)&&!e.allOf&&!e.anyOf&&!e.oneOf&&!e.not&&!!e.enum?.length&&e.enum.every(t=>t!==null&&c(t,e))}exports.directionalTypeName=r,exports.hasMixedAdditionalProperties=i,exports.isNamedEnumSchema=d,exports.renderSchemaType=u,exports.resolveLocalSchemaReference=a,exports.schemaNeedsDirection=n;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
const e=require(`./format.cjs`),t=require(`./naming.cjs`);function n(e){return e?` | null`:``}function r(
|
|
2
|
-
`)}
|
|
3
|
-
`)}};`):s.push(`${o}${c}: ${a};`)}return s}exports.applyTypeMapping=r,exports.formatObjectProperties=a,exports.nullableSuffix=n,exports.stringifyArrayType=i;
|
|
1
|
+
const e=require(`./format.cjs`),t=require(`./naming.cjs`);function n(e){return e?` | null`:``}function r(n,r,i){if(!n)return[];let a=e.getIndentation(r),o=a+a,s=[],c=Object.keys(n).sort();for(let e of c){let r=n[e],a=i(r),c=t.formatPropertyName(e);Array.isArray(a)?s.push(`${o}${c}: {${a.join(`
|
|
2
|
+
`)}};`):s.push(`${o}${c}: ${a};`)}return s}exports.formatObjectProperties=r,exports.nullableSuffix=n;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const e=require(`../../_virtual/rolldown_runtime.cjs`),t=require(`../../utils/index.cjs`);let
|
|
2
|
-
`).filter(e=>e.trim()!==``)}catch{
|
|
3
|
-
`))}exports.writeIndexFileWithDedup=
|
|
1
|
+
const e=require(`../../_virtual/rolldown_runtime.cjs`),t=require(`../../utils/index.cjs`),n=require(`./naming.cjs`);let r=require(`fs`);r=e.__toESM(r);async function i(e){try{return(await r.default.promises.readFile(e,`utf8`)).split(`
|
|
2
|
+
`).filter(e=>e.trim()!==``)}catch{return[]}}function a(e){let t=n.segmentToNamespacePrefix(e);if(!t)throw Error(`无法为 segment "${e}" 生成 namespace 别名,请改用包含字母/数字的 apiListFileName。`);return`export * as ${t} from './${e}';`}function o(e,t,n,r=!1){let i=new Set(t);return[...e.flatMap(e=>{let t=/from\s+['"]\.\/([^'"]+)['"]/.exec(e)?.[1];if(t&&i.has(t))return[];if(r&&t&&!/export\s+\*\s+as\s+/.test(e))try{return[a(t)]}catch{return[e]}return[e]}),...n.map(a)]}async function s(e,n,r={}){let{appendMode:a=!1}=r,o=n.filter(Boolean);if(!o.length)return;let s=a?await i(e):[],c=new Set(s);await t.writeFileRecursive(e,[...s,...o.filter(e=>!c.has(e))].join(`
|
|
3
|
+
`))}exports.mergeNamespaceExports=o,exports.readIndexLines=i,exports.writeIndexFileWithDedup=s;
|
package/lib/utils/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`../_virtual/rolldown_runtime.cjs`);require(`./logger.cjs`);let t=require(`fs`);t=e.__toESM(t);let n=require(`path`);n=e.__toESM(n);let r=require(`module`)
|
|
1
|
+
const e=require(`../_virtual/rolldown_runtime.cjs`);require(`./logger.cjs`);let t=require(`fs`);t=e.__toESM(t);let n=require(`path`);n=e.__toESM(n);let r=require(`module`);const i=function(e,r){return new Promise((i,a)=>{try{let o=n.default.dirname(e);t.default.mkdir(o,{recursive:!0},n=>{if(n)return a(Error(`创建目录失败`));t.default.writeFile(e,r,function(e){if(e)return a(Error(`写入文件失败`));i(!0)})})}catch(e){console.error(e),a(Error(String(e)))}})};async function a(e,t,n){let r=Array(e.length),i=Math.max(1,Math.min(t,e.length)),a=0,o=Array.from({length:i},async()=>{for(;;){let t=a++;if(t>=e.length)return;r[t]=await n(e[t],t)}});return await Promise.all(o),r}async function o(e){return await t.default.promises.rm(e,{recursive:!0,force:!0}),!0}async function s(e,r=[]){let i;try{i=await t.default.promises.readdir(e)}catch(e){if(e.code===`ENOENT`)return!0;throw e}for(let t of i)r.includes(t)||await o(n.default.join(e,t));return!0}function c(e){if(typeof e!=`string`)return!1;try{return JSON.parse(e),!0}catch{return!1}}function l(e,t=!0){let n=(0,r.createRequire)(__filename);try{let r=n(e);if(t){let t=setTimeout(()=>{delete n.cache[n.resolve(e)],clearTimeout(t)},200)}return r}catch(e){throw Error(e instanceof Error?e.message:String(e))}}exports.clearDir=o,exports.clearDirExcept=s,exports.isValidJSON=c,exports.requireModule=l,exports.runWithConcurrency=a,exports.writeFileRecursive=i;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anl",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.929.0",
|
|
4
4
|
"description": "FE command line tool",
|
|
5
5
|
"main": "bin/an-cli.js",
|
|
6
6
|
"exports": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"preinstall": "npx only-allow pnpm",
|
|
25
25
|
"dev": "tsdown --watch",
|
|
26
26
|
"build": "rimraf lib && tsdown",
|
|
27
|
+
"test:codegen": "pnpm run build && node --test tests/swagger-codegen.test.cjs",
|
|
27
28
|
"pub": "bash publish.sh",
|
|
28
29
|
"ts": "tsc ./src/int.ts --noEmit --watch",
|
|
29
30
|
"blink": "pnpm run build && pnpm link",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"@commitlint/cli": "^17.4.3",
|
|
43
44
|
"@commitlint/config-conventional": "^17.4.3",
|
|
44
45
|
"@eslint/js": "^9.39.2",
|
|
46
|
+
"@types/cross-spawn": "^6.0.6",
|
|
45
47
|
"@types/inquirer": "^9.0.7",
|
|
46
48
|
"@types/node": "^24.10.9",
|
|
47
49
|
"@types/shelljs": "^0.8.11",
|
|
@@ -72,6 +74,7 @@
|
|
|
72
74
|
"chalk": "4.*",
|
|
73
75
|
"clear-console": "^1.1.0",
|
|
74
76
|
"commander": "14.0.1",
|
|
77
|
+
"cross-spawn": "^7.0.6",
|
|
75
78
|
"figures": "^6.1.0",
|
|
76
79
|
"inquirer": "^10.1.8",
|
|
77
80
|
"jiti": "^2.6.1",
|