anl 26.930.0 → 26.1010.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,16 +2,24 @@
2
2
 
3
3
  [English](https://bianliuzhu.github.io/an-cli/#/en/) | [简体中文](https://bianliuzhu.github.io/an-cli/#/zh-cn/) | [日本語](https://bianliuzhu.github.io/an-cli/#/jp/) | [Español](https://bianliuzhu.github.io/an-cli/#/es/) | [Français](https://bianliuzhu.github.io/an-cli/#/fr/) | [Русский](https://bianliuzhu.github.io/an-cli/#/ru/) | [العربية](https://bianliuzhu.github.io/an-cli/#/ar/)
4
4
 
5
+ > [!NOTE]
6
+ > Starting from version **26.201.0**, new features are documented only in **English** and **简体中文**. Other language versions are no longer updated.
7
+ >
8
+ > 从 **26.201.0** 版本开始,新增功能仅更新 **英文** 和 **简体中文** 文档,其他语言文档不再更新。
9
+
5
10
  ---
6
11
 
7
12
  # Overview
8
13
 
14
+ Path prefix configuration now uses `stripPathPrefix`, `requestPathPrefix` and `mockPathPrefix`, without legacy aliases. [Migration guide](https://bianliuzhu.github.io/an-cli/#/en/anl-type?id=path-prefix-migration).
15
+
9
16
  > an-cli is a frontend command-line tool that includes the following commands:
10
17
  >
11
18
  > - `anl type` command: A command-line tool that automatically generates TypeScript type definitions and API request functions based on Swagger JSON.
12
19
  > - `anl mock` command: Generates Mock.js JSON files from local service response types for mock-service-plugin. [Documentation](https://bianliuzhu.github.io/an-cli/#/en/anl-mock).
13
20
  > - `anl lint` command: Generates eslint, stylelint, prettier, commitLint, and VSCode related configurations for React or Vue projects
14
21
  > - `anl git` command: Generates git local configuration with optional features: gitflow standard branch creation, git commit messages subject, and git custom command configuration
22
+ > - `anl skill` command: Initializes Agent Skill files for AI-assisted development, supporting api-report and api-mock skills.
15
23
 
16
24
  ## Features
17
25
 
@@ -27,6 +35,13 @@
27
35
  - 🌐 Supports multiple Swagger server configurations
28
36
  - 🔧 Supports HTTP methods like OPTIONS, HEAD, SEARCH
29
37
 
38
+ - `anl mock`
39
+ - Select one, multiple, or all generated services
40
+ - Recursively generate Mock.js templates with inferred response envelopes
41
+ - Write service-scoped JSON files with `@url` and `@method` headers
42
+ - Preserve existing mocks unless `--overwrite` is specified
43
+ - [Usage and plugin installation](https://bianliuzhu.github.io/an-cli/#/en/anl-mock)
44
+
30
45
  - `anl lint`
31
46
  - 🔍 One-click configuration for various lint tools
32
47
  - 🎨 Automated ESLint configuration
@@ -41,16 +56,24 @@
41
56
  - 🔄 Provides git custom command configuration and entry points
42
57
  - 📦 Automated generation with zero configuration
43
58
 
59
+ - `anl skill`
60
+ - Initialize Agent Skill files for AI-assisted development
61
+ - Support api-report for API change reports and api-mock for AI-assisted mock generation
62
+ - [Usage](https://bianliuzhu.github.io/an-cli/#/en/anl-skill)
63
+
44
64
  ---
45
65
 
46
66
  # 功能概述
47
67
 
68
+ 路径前缀配置已统一为 `stripPathPrefix`、`requestPathPrefix`、`mockPathPrefix`,不保留旧字段别名。升级前请查看[迁移说明](https://bianliuzhu.github.io/an-cli/#/zh-cn/anl-type?id=路径前缀迁移)。
69
+
48
70
  > an-cli 是前端命令行工具,包含以下命令:
49
71
  >
50
72
  > - `anl type` 命令:基于 Swagger JSON 自动生成 TypeScript 类型定义和 API 请求函数的命令行工具。
51
73
  > - `anl mock` 命令:从本地服务响应类型生成供 mock-service-plugin 使用的 Mock.js JSON 文件。[使用文档](https://bianliuzhu.github.io/an-cli/#/zh-cn/anl-mock)。
52
74
  > - `anl lint` 命令: 生成 react 或 vue 项目 eslint、stylelint、prettier、commitLint、VSCode相关配置
53
75
  > - `anl git` 命令: 生成 git 本地配置,并设有可选功能: gitflow 标准分支创建、git commit messages 主题、git 自定义命令配置
76
+ > - `anl skill` 命令:初始化 AI 辅助开发的 Agent Skill 文件,支持 api-report 和 api-mock。
54
77
 
55
78
  ## 功能特点
56
79
 
@@ -66,6 +89,13 @@
66
89
  - 🌐 支持多 Swagger 服务器配置
67
90
  - 🔧 支持 OPTIONS、HEAD、SEARCH 等 HTTP 方法
68
91
 
92
+ - `anl mock`
93
+ - 选择单个、多个或全部已生成的服务
94
+ - 推导响应外壳并递归生成 Mock.js 模板
95
+ - 按服务目录输出带有 `@url`、`@method` 注释的 JSON 文件
96
+ - 默认保留已有 mock,仅在指定 `--overwrite` 时覆盖
97
+ - [使用说明与插件安装](https://bianliuzhu.github.io/an-cli/#/zh-cn/anl-mock)
98
+
69
99
  - `anl lint`
70
100
  - 🔍 一键配置各种 lint 工具
71
101
  - 🎨 ESLint 配置自动化
@@ -80,6 +110,11 @@
80
110
  - 🔄 提供 git 自定义命令配置以及入口
81
111
  - 📦 自动化生成 0 配置
82
112
 
113
+ - `anl skill`
114
+ - 初始化 AI 辅助开发的 Agent Skill 文件
115
+ - 支持 api-report 接口变更报告与 api-mock AI 辅助 mock 生成
116
+ - [使用说明](https://bianliuzhu.github.io/an-cli/#/zh-cn/anl-skill)
117
+
83
118
  ---
84
119
 
85
120
  # نظرة عامة على الوظائف
package/config.d.ts CHANGED
@@ -48,8 +48,16 @@ export interface IConfigSwaggerServer {
48
48
  name?: string;
49
49
  /** swagger json 的 url */
50
50
  url: string;
51
- /** 公共前缀 */
52
- publicPrefix?: string;
51
+ /** @deprecated 已移除,禁止使用;请改用 stripPathPrefix。为此字段配置前缀会产生类型错误,运行时不会生效。 */
52
+ publicPrefix?: never;
53
+ /** 从 OpenAPI 路径开头移除的前缀,按完整路径段匹配;同时影响生成的函数名、类型名、文件名和请求路径。未匹配时保留原路径。 */
54
+ stripPathPrefix?: string;
55
+ /** @deprecated 已移除,禁止使用;请改用 requestPathPrefix。为此字段配置前缀会产生类型错误,运行时不会生效。 */
56
+ modulePrefix?: never;
57
+ /** 添加到裁剪后的请求路径前的前缀,不影响生成名称;自动补齐开头斜杠并移除末尾斜杠,不去重路径段。 */
58
+ requestPathPrefix?: string;
59
+ /** 仅 anl mock 使用的额外路径前缀,如 '/api'。添加到已生成 API 的实际路径前,保留 requestPathPrefix,不修改 API 代码;自动处理首尾斜杠,不去重路径段,未配置、空字符串或 '/' 时不追加。 */
60
+ mockPathPrefix?: string;
53
61
  /** 生成接口默认返回数据层级(服务级配置) */
54
62
  dataLevel?: TDatalevel;
55
63
  /** 参数分隔符(服务级配置) */
@@ -66,8 +74,6 @@ export interface IConfigSwaggerServer {
66
74
  includeTags?: string[];
67
75
  /** 排除的模块(tag)列表,与 includeTags 互斥,优先级低于 includeInterface/excludeInterface(在单接口过滤之后应用) */
68
76
  excludeTags?: string[];
69
- /** path 前缀 */
70
- modulePrefix?: string;
71
77
  /** 响应模型转换配置 */
72
78
  responseModelTransform?: IResponseModelTransform;
73
79
  /** 当前服务的 mock 生成选项,覆盖全局 mock 配置 */
@@ -87,6 +93,11 @@ export interface IConfigSwaggerServer {
87
93
  enumIsolation?: 'segment' | 'none';
88
94
  }
89
95
 
96
+ /**
97
+ * CLI 配置。
98
+ * 已移除的前缀字段:publicPrefix 改用 stripPathPrefix,modulePrefix 改用 requestPathPrefix,mockUrlPrefix 改用服务级 mockPathPrefix。
99
+ * 旧前缀字段运行时不再读取,不提供兼容别名;publicPrefix 和 modulePrefix 仅保留 never 类型声明,用于类型报错和迁移提示。
100
+ */
90
101
  export interface ConfigType {
91
102
  /** 存放生成的类型文件的文件夹路径 */
92
103
  saveTypeFolderPath: string;
@@ -94,11 +105,17 @@ export interface ConfigType {
94
105
  saveApiListFolderPath: string;
95
106
  /** anl mock 生成选项 */
96
107
  mock?: MockConfig;
97
- /** 兼容旧配置的 swagger json 地址(已迁移到 swaggerConfig 中) */
108
+ /**
109
+ * 兼容旧配置的 Swagger JSON 地址。
110
+ * @deprecated 请改用 swaggerConfig.url;多服务时在 swaggerConfig 数组的每个服务中配置 url。
111
+ */
98
112
  swaggerJsonUrl?: string;
99
113
  /** swagger 服务器列表 */
100
114
  swaggerConfig: IConfigSwaggerServer[] | IConfigSwaggerServer;
101
- /** api list 生成文件名,单个 swaggerServer 可省略,默认 index.ts */
115
+ /**
116
+ * 兼容旧配置的 API 列表生成文件名,默认 index.ts。
117
+ * @deprecated 请改用 swaggerConfig.apiListFileName;多服务时为每个服务配置唯一文件名,单服务可省略。
118
+ */
102
119
  apiListFileName?: string;
103
120
  /** 请求方法导入路径 */
104
121
  requestMethodsImportPath: string;
@@ -110,10 +127,19 @@ export interface ConfigType {
110
127
  * - `taro` 基于 `Taro.request`(Taro 3+ 跨端)
111
128
  * 注意:切换模板时需手动删除 `<saveApiListFolderPath>/config/` 目录,CLI 才会重新写入对应模板文件。 */
112
129
  requestTemplate?: RequestTemplate;
113
- /** 追加请求头 */
130
+ /**
131
+ * 兼容旧配置的全局请求头,服务级配置优先。
132
+ * @deprecated 请改用 swaggerConfig.headers;多服务时将公共请求头配置到各服务的 headers 中。
133
+ */
114
134
  headers?: Record<string, string>;
115
- /** 公共前缀(仅为兼容旧配置,最终以服务级配置为准) */
116
- publicPrefix?: string;
135
+ /** @deprecated 已移除,禁止使用;请改用 stripPathPrefix,或服务级 swaggerConfig.stripPathPrefix。为此字段配置前缀会产生类型错误,运行时不会生效。 */
136
+ publicPrefix?: never;
137
+ /** 从 OpenAPI 路径开头移除的全局默认前缀,同时影响生成名称和请求路径;服务级配置优先,空字符串可清除全局默认值。 */
138
+ stripPathPrefix?: string;
139
+ /** @deprecated 已移除,禁止使用;请改用 requestPathPrefix,或服务级 swaggerConfig.requestPathPrefix。为此字段配置前缀会产生类型错误,运行时不会生效。 */
140
+ modulePrefix?: never;
141
+ /** 添加到裁剪后的请求路径前的全局默认前缀,不影响生成名称;服务级配置优先,空字符串可清除全局默认值。 */
142
+ requestPathPrefix?: string;
117
143
  /** 生成接口默认返回数据层级(服务级配置注入) */
118
144
  dataLevel?: TDatalevel;
119
145
  /** 参数分隔符(服务级配置注入) */
@@ -126,8 +152,6 @@ export interface ConfigType {
126
152
  includeTags?: string[];
127
153
  /** 排除的模块(tag)列表(服务级配置注入) */
128
154
  excludeTags?: string[];
129
- /** path 前缀(服务级配置注入) */
130
- modulePrefix?: string;
131
155
  /** 响应模型转换配置(服务级配置注入) */
132
156
  responseModelTransform?: IResponseModelTransform;
133
157
  /** 请求超时时间(毫秒),默认 60000 */
@@ -1 +1 @@
1
- const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`);require(`../utils/index.cjs`);const n=require(`../swagger-codegen/config-template.cjs`),r=require(`../swagger-codegen/shared/naming.cjs`),i=require(`./reader.cjs`),a=require(`./template.cjs`),o=require(`./writer.cjs`);let s=require(`inquirer`);s=e.__toESM(s);let c=require(`jiti`),l=require(`node:fs`),u=require(`node:fs/promises`);u=e.__toESM(u);let d=require(`node:path`);d=e.__toESM(d);function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function p(e){let t=d.default.join(e,`an.config.ts`),n=d.default.join(e,`an.config.json`),r=(0,l.existsSync)(t)?t:n;if(!(0,l.existsSync)(r))throw Error(`No an.config.ts or an.config.json found. Run anl type first.`);try{let e=r===t?await(0,c.createJiti)(__filename,{interopDefault:!0}).import(t):JSON.parse(await u.default.readFile(n,`utf8`)),i=f(e)&&f(e.default)?e.default:e;if(!f(i))throw Error(`The configuration must export an object.`);return i}catch(e){throw Error(`Cannot load ${r}: ${e instanceof Error?e.message:String(e)}`)}}function m(e,t,n,r){let i=t??n;if(typeof i!=`string`||!i.trim())throw Error(`${r} must be a non-empty directory path.`);return d.default.resolve(e,i)}function h(e,t){for(let n of[e,t]){if(n!==void 0&&!f(n))throw Error(`mock must be an object.`);if(n?.responseDefaults!==void 0&&!f(n.responseDefaults))throw Error(`mock.responseDefaults must be an object.`)}let n={...e,...t,responseDefaults:{...e?.responseDefaults,...t?.responseDefaults}};for(let[e,t]of[[`arrayLength`,100],[`maxDepth`,30]]){let r=n[e];if(r!==void 0&&(!Number.isInteger(r)||r<1||r>t))throw Error(`mock.${e} must be an integer between 1 and ${t}.`)}return n}async function g(e,t){let n=new Map,a=t.swaggerConfig?Array.isArray(t.swaggerConfig)?t.swaggerConfig:[t.swaggerConfig]:[];for(let e of a){if(!f(e))throw Error(`Each swaggerConfig service must be an object.`);let r=e.apiListFileName??t.apiListFileName??`index.ts`;if(typeof r!=`string`||/[\\/]/.test(r)||r.includes(`..`))throw Error(`apiListFileName must be a single file name.`);if(n.has(r))throw Error(`Duplicate apiListFileName in swaggerConfig: ${r}`);n.set(r,e)}let o=await u.default.readdir(e,{withFileTypes:!0}).catch(t=>{throw t.code===`ENOENT`?Error(`API directory not found: ${e}. Run anl type first.`):t}),s=[],c=new Set,l=new Set;for(let a of o.sort((e,t)=>e.name.localeCompare(t.name))){if(!a.isFile()||!a.name.endsWith(`.ts`)||a.name.endsWith(`.d.ts`))continue;let o=d.default.join(e,a.name);if(!i.isGeneratedApiFile(o))continue;let u=n.get(a.name),f=r.computeSegment(a.name);if(u?.name!==void 0&&typeof u.name!=`string`)throw Error(`Service name must be a string.`);let p=u?.name?.trim()??``,m=p.length?p:f;if(!f||c.has(f.toLowerCase()))throw Error(`Conflicting mock service directory for ${a.name}`);if(l.has(m.toLowerCase()))throw Error(`Duplicate mock service name: ${m}`);c.add(f.toLowerCase()),l.add(m.toLowerCase()),s.push({name:m,segment:f,fileName:a.name,apiFile:o,options:h(t.mock,u?.mock)})}if(!s.length)throw Error(`No generated service API files found in ${e}. Run anl type first.`);return s}async function _(e,t,n=!!(process.stdin.isTTY&&process.stdout.isTTY)){if(t.all&&t.service!==void 0)throw Error(`--all and --service cannot be used together.`);if(t.service!==void 0){let n=t.service.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean);if(!n.length)throw Error(`--service requires at least one service name.`);let r=new Map(e.map(e=>[e.name.toLowerCase(),e]));for(let t of e)r.has(t.segment.toLowerCase())||r.set(t.segment.toLowerCase(),t);let i=n.filter(e=>!r.has(e));if(i.length)throw Error(`Unknown generated service(s): ${i.join(`, `)}. Available: ${e.map(e=>e.name).join(`, `)}.`);let a=new Set(n.map(e=>r.get(e)));return e.filter(e=>a.has(e))}if(t.all||!n||e.length===1)return e;let{picked:r}=await s.default.prompt([{type:`checkbox`,name:`picked`,message:`Select services to generate mock files (empty = all):`,choices:e.map((e,t)=>({name:`${e.name} (${e.fileName})`,value:t})),pageSize:Math.min(20,e.length)}]);return r.length?e.filter((e,t)=>r.includes(t)):e}async function v(e={},r=process.cwd()){let s=await p(r),c=n.createDefaultConfig(),l=e.logLevel??s.logLevel??`info`;if(![`silent`,`error`,`warn`,`info`,`verbose`].includes(l))throw Error(`Invalid log level: ${l}`);t.setLogLevel(l);let u=m(r,s.saveApiListFolderPath,c.saveApiListFolderPath,`saveApiListFolderPath`),f=m(r,s.saveTypeFolderPath,c.saveTypeFolderPath,`saveTypeFolderPath`),h=m(r,e.mockDir??s.mock?.mockDir,`mocks`,`mock.mockDir`);if(h===d.default.parse(h).root)throw Error(`mockDir cannot be the filesystem root.`);let v=await _(await g(u,s),e);t.log.section(`anl mock`,h),t.log.print(`Services: ${v.map(e=>e.name).join(`, `)}`);let{checker:y,operations:b}=i.readMockOperations({projectRoot:r,apiDir:u,typeDir:f,apiFiles:v.map(e=>e.apiFile)}),x=[],S=await o.writeMockFiles(h,b.map(e=>{let t=v.find(t=>t.apiFile===e.sourceFile),n=a.renderMockOperation(y,e,t.options);return x.push(...n.warnings),{service:t.segment,operation:e,template:n.template}}),{overwrite:e.overwrite,...s.formatting});for(let e of S.files)t.log.verbose(e);if(x.length){t.log.warning(`${x.length} field(s) need review (unknown or recursive types). Use --log-level verbose for details.`);for(let e of x)t.log.verbose(e)}return t.log.success(`Mock files: ${S.generated} generated, ${S.overwritten} overwritten, ${S.skipped} skipped.`),{...S,warnings:x}}exports.mockHandle=v;
1
+ const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`);require(`../utils/index.cjs`);const n=require(`../swagger-codegen/config-template.cjs`),r=require(`../swagger-codegen/shared/naming.cjs`),i=require(`./reader.cjs`),a=require(`./template.cjs`),o=require(`./writer.cjs`);let s=require(`inquirer`);s=e.__toESM(s);let c=require(`jiti`),l=require(`node:fs`),u=require(`node:fs/promises`);u=e.__toESM(u);let d=require(`node:path`);d=e.__toESM(d);function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function p(e){let t=d.default.join(e,`an.config.ts`),n=d.default.join(e,`an.config.json`),r=(0,l.existsSync)(t)?t:n;if(!(0,l.existsSync)(r))throw Error(`No an.config.ts or an.config.json found. Run anl type first.`);try{let e=r===t?await(0,c.createJiti)(__filename,{interopDefault:!0}).import(t):JSON.parse(await u.default.readFile(n,`utf8`)),i=f(e)&&f(e.default)?e.default:e;if(!f(i))throw Error(`The configuration must export an object.`);return i}catch(e){throw Error(`Cannot load ${r}: ${e instanceof Error?e.message:String(e)}`)}}function m(e,t,n,r){let i=t??n;if(typeof i!=`string`||!i.trim())throw Error(`${r} must be a non-empty directory path.`);return d.default.resolve(e,i)}function h(e,t){for(let n of[e,t]){if(n!==void 0&&!f(n))throw Error(`mock must be an object.`);if(n?.responseDefaults!==void 0&&!f(n.responseDefaults))throw Error(`mock.responseDefaults must be an object.`)}let n={...e,...t,responseDefaults:{...e?.responseDefaults,...t?.responseDefaults}};for(let[e,t]of[[`arrayLength`,100],[`maxDepth`,30]]){let r=n[e];if(r!==void 0&&(!Number.isInteger(r)||r<1||r>t))throw Error(`mock.${e} must be an integer between 1 and ${t}.`)}return n}function g(e){if(e===void 0||e===``)return``;if(typeof e!=`string`||/[\s?#\\:]|\*\//.test(e))throw Error(`mockPathPrefix must be a URL path prefix without whitespace, a host, query or fragment.`);let t=e.replace(/^\/+|\/+$/g,``);return t?`/${t}`:``}async function _(e,t){let n=new Map,a=t.swaggerConfig?Array.isArray(t.swaggerConfig)?t.swaggerConfig:[t.swaggerConfig]:[];for(let e of a){if(!f(e))throw Error(`Each swaggerConfig service must be an object.`);let r=e.apiListFileName??t.apiListFileName??`index.ts`;if(typeof r!=`string`||/[\\/]/.test(r)||r.includes(`..`))throw Error(`apiListFileName must be a single file name.`);if(n.has(r))throw Error(`Duplicate apiListFileName in swaggerConfig: ${r}`);n.set(r,e)}let o=await u.default.readdir(e,{withFileTypes:!0}).catch(t=>{throw t.code===`ENOENT`?Error(`API directory not found: ${e}. Run anl type first.`):t}),s=[],c=new Set,l=new Set;for(let a of o.sort((e,t)=>e.name.localeCompare(t.name))){if(!a.isFile()||!a.name.endsWith(`.ts`)||a.name.endsWith(`.d.ts`))continue;let o=d.default.join(e,a.name);if(!i.isGeneratedApiFile(o))continue;let u=n.get(a.name),f=r.computeSegment(a.name);if(u?.name!==void 0&&typeof u.name!=`string`)throw Error(`Service name must be a string.`);let p=u?.name?.trim()??``,m=p.length?p:f;if(!f||c.has(f.toLowerCase()))throw Error(`Conflicting mock service directory for ${a.name}`);if(l.has(m.toLowerCase()))throw Error(`Duplicate mock service name: ${m}`);c.add(f.toLowerCase()),l.add(m.toLowerCase()),s.push({name:m,segment:f,fileName:a.name,apiFile:o,mockPathPrefix:g(u?.mockPathPrefix),options:h(t.mock,u?.mock)})}if(!s.length)throw Error(`No generated service API files found in ${e}. Run anl type first.`);return s}async function v(e,t,n=!!(process.stdin.isTTY&&process.stdout.isTTY)){if(t.all&&t.service!==void 0)throw Error(`--all and --service cannot be used together.`);if(t.service!==void 0){let n=t.service.split(`,`).map(e=>e.trim().toLowerCase()).filter(Boolean);if(!n.length)throw Error(`--service requires at least one service name.`);let r=new Map(e.map(e=>[e.name.toLowerCase(),e]));for(let t of e)r.has(t.segment.toLowerCase())||r.set(t.segment.toLowerCase(),t);let i=n.filter(e=>!r.has(e));if(i.length)throw Error(`Unknown generated service(s): ${i.join(`, `)}. Available: ${e.map(e=>e.name).join(`, `)}.`);let a=new Set(n.map(e=>r.get(e)));return e.filter(e=>a.has(e))}if(t.all||!n||e.length===1)return e;let{picked:r}=await s.default.prompt([{type:`checkbox`,name:`picked`,message:`Select services to generate mock files (empty = all):`,choices:e.map((e,t)=>({name:`${e.name} (${e.fileName})`,value:t})),pageSize:Math.min(20,e.length)}]);return r.length?e.filter((e,t)=>r.includes(t)):e}async function y(e={},r=process.cwd()){let s=await p(r),c=n.createDefaultConfig(),l=e.logLevel??s.logLevel??`info`;if(![`silent`,`error`,`warn`,`info`,`verbose`].includes(l))throw Error(`Invalid log level: ${l}`);t.setLogLevel(l);let u=m(r,s.saveApiListFolderPath,c.saveApiListFolderPath,`saveApiListFolderPath`),f=m(r,s.saveTypeFolderPath,c.saveTypeFolderPath,`saveTypeFolderPath`),h=m(r,e.mockDir??s.mock?.mockDir,`mocks`,`mock.mockDir`);if(h===d.default.parse(h).root)throw Error(`mockDir cannot be the filesystem root.`);let g=await v(await _(u,s),e);t.log.section(`anl mock`,h),t.log.print(`Services: ${g.map(e=>e.name).join(`, `)}`);let{checker:y,operations:b}=i.readMockOperations({projectRoot:r,apiDir:u,typeDir:f,apiFiles:g.map(e=>e.apiFile)}),x=[],S=await o.writeMockFiles(h,b.map(e=>{let t=g.find(t=>t.apiFile===e.sourceFile),n=t.mockPathPrefix?{...e,url:`${t.mockPathPrefix}/${e.url.replace(/^\/+/,``)}`}:e,r=a.renderMockOperation(y,n,t.options);return x.push(...r.warnings),{service:t.segment,operation:n,template:r.template}}),{overwrite:e.overwrite,...s.formatting});for(let e of S.files)t.log.verbose(e);if(x.length){t.log.warning(`${x.length} field(s) need review (unknown or recursive types). Use --log-level verbose for details.`);for(let e of x)t.log.verbose(e)}return t.log.success(`Mock files: ${S.generated} generated, ${S.overwritten} overwritten, ${S.skipped} skipped.`),{...S,warnings:x}}exports.mockHandle=y;
package/lib/package.cjs CHANGED
@@ -1 +1 @@
1
- var e=`26.930.0`;Object.defineProperty(exports,`version`,{enumerable:!0,get:function(){return e}});
1
+ var e=`26.1010.0`;Object.defineProperty(exports,`version`,{enumerable:!0,get:function(){return e}});
@@ -1,6 +1,6 @@
1
- const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`),n=require(`../utils/index.cjs`),r=require(`./shared/constants.cjs`),i=require(`./config-template.cjs`),a=require(`./shared/naming.cjs`),o=require(`./shared/writer.cjs`),s=require(`./components/index.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=i.createDefaultConfig();b&&(S.saveTypeFolderPath=`apps/types`,S.saveApiListFolderPath=`apps/types`,S.saveEnumFolderPath=`apps/enums`);var C=class{schemas={};paths={};async handle(e,n,r){let i=a.getServiceTag(e);t.log.section(i||`service`,e.swaggerJsonUrl);try{t.spinner.start(`Fetching Swagger data...`);let i=await c.getSwaggerJson(e);if(!i)throw t.spinner.error(`Failed to fetch Swagger data`),Error(`无法获取 Swagger 数据`);let a=u.normalizeOpenApiDocument(i,e=>t.log.warn(e));t.spinner.success(`Swagger data fetched`),this.schemas=a.components?.schemas??{},this.paths=a.paths??{};let o=new p.SchemaDiagnostics(a),d=new s.default(this.schemas,e,{appendMode:n},o),f=new l.default(this.paths,a.components?.parameters,this.schemas,e,o);return t.spinner.start(`Generating types and APIs...`),await d.handle(),await f.handle(),t.spinner.success(`Types and APIs generated`),o.flush((e,n)=>{n===`info`?t.log.print(e):n===`verbose`?t.log.verbose(e):t.log.warn(e)}),r===`gen`?f.getGeneratedInterfacesForOutput():r===`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(`
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(`
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,a){let o=g.default.join(e,`an.config.ts`),s=g.default.join(e,`an.config.json`);if(h.default.existsSync(o))return t.log.info(`检测到 an.config.ts 配置文件。`),this.loadTsConfig(o);if(h.default.existsSync(s))return this.loadJsonConfig(s);y=!1,t.log.warning(`配置文件不存在,将自动创建配置文件。`);let c=r.DEFAULT_REQUEST_TEMPLATE;if(a)c=f.normalizeRequestTemplate(a,`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 默认为 "${r.DEFAULT_REQUEST_TEMPLATE}"。可通过 --template 指定或修改 an.config.ts 后重跑。`);let l=i.createDefaultConfig(c);await n.writeFileRecursive(o,i.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 r=a.computeSegment(e.apiListFileName).toLowerCase();r&&!n.has(r)&&n.set(r,t)});let r=new Set,i=[];for(let e of t){let t=e.toLowerCase(),a=n.get(t);a===void 0?i.push(e):r.add(a)}if(i.length){let t=e.map(e=>e.name??a.computeSegment(e.apiListFileName)).filter(Boolean).join(`, `);throw Error(`未找到匹配的 swagger 服务:${i.join(`, `)}。可用服务:${t||`<无>`}`)}return Array.from(r).sort((e,t)=>e-t)}async promptSelectServices(e){let t=e.map((e,t)=>{let n=a.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,r,i,o,s){let c=process.cwd();try{let l=await this.getConfig(c,s),u={...S,...l},p=i??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=>a.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`?``:a.segmentToNamespacePrefix(a.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(`
1
+ const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`../utils/logger.cjs`),n=require(`../utils/index.cjs`),r=require(`./shared/constants.cjs`),i=require(`./config-template.cjs`),a=require(`./shared/naming.cjs`),o=require(`./shared/writer.cjs`),s=require(`./components/index.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=i.createDefaultConfig();b&&(S.saveTypeFolderPath=`apps/types`,S.saveApiListFolderPath=`apps/types`,S.saveEnumFolderPath=`apps/enums`);var C=class{schemas={};paths={};async handle(e,n,r){let i=a.getServiceTag(e);t.log.section(i||`service`,e.swaggerJsonUrl);try{t.spinner.start(`Fetching Swagger data...`);let i=await c.getSwaggerJson(e);if(!i)throw t.spinner.error(`Failed to fetch Swagger data`),Error(`无法获取 Swagger 数据`);let a=u.normalizeOpenApiDocument(i,e=>t.log.warn(e));t.spinner.success(`Swagger data fetched`),this.schemas=a.components?.schemas??{},this.paths=a.paths??{};let o=new p.SchemaDiagnostics(a),d=new s.default(this.schemas,e,{appendMode:n},o),f=new l.default(this.paths,a.components?.parameters,this.schemas,e,o);return t.spinner.start(`Generating types and APIs...`),await d.handle(),await f.handle(),t.spinner.success(`Types and APIs generated`),o.flush((e,n)=>{n===`info`?t.log.print(e):n===`verbose`?t.log.verbose(e):t.log.warn(e)}),r===`gen`?f.getGeneratedInterfacesForOutput():r===`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`,stripPathPrefix:e.stripPathPrefix??``,apiListFileName:e.apiListFileName??`index.ts`,headers:e.headers??{}},r=this.getSystemLocale();r.startsWith(`zh`)||r.includes(`chinese`)?(t.log.print(`
2
+ 检测到旧版配置,请更新 an.config.json:`),t.log.print(`1) 将 swaggerJsonUrl / stripPathPrefix / 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(`
3
+ Legacy configuration detected, please update an.config.json:`),t.log.print(`1) Move swaggerJsonUrl / stripPathPrefix / 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??``,stripPathPrefix:e.stripPathPrefix??``,apiListFileName:e.apiListFileName??`index.ts`,headers:e.headers??{},requestPathPrefix:e.requestPathPrefix});let i=(t,r)=>{let i=t.url||e.swaggerJsonUrl;if(!i)throw Error(`swaggerConfig[${r}] 缺少 url,请补充后重试。`);let a=t.stripPathPrefix??e.stripPathPrefix??``;!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,stripPathPrefix:a,apiListFileName:o,headers:s,dataLevel:c,parameterSeparator:l,includeInterface:u,excludeInterface:d,requestPathPrefix:t.requestPathPrefix??e.requestPathPrefix??``,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,stripPathPrefix:t.stripPathPrefix??e.stripPathPrefix,headers:t.headers,apiListFileName:t.apiListFileName,dataLevel:t.dataLevel,parameterSeparator:t.parameterSeparator,includeInterface:t.includeInterface,excludeInterface:t.excludeInterface,includeTags:t.includeTags,excludeTags:t.excludeTags,requestPathPrefix:t.requestPathPrefix,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,a){let o=g.default.join(e,`an.config.ts`),s=g.default.join(e,`an.config.json`);if(h.default.existsSync(o))return t.log.info(`检测到 an.config.ts 配置文件。`),this.loadTsConfig(o);if(h.default.existsSync(s))return this.loadJsonConfig(s);y=!1,t.log.warning(`配置文件不存在,将自动创建配置文件。`);let c=r.DEFAULT_REQUEST_TEMPLATE;if(a)c=f.normalizeRequestTemplate(a,`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 默认为 "${r.DEFAULT_REQUEST_TEMPLATE}"。可通过 --template 指定或修改 an.config.ts 后重跑。`);let l=i.createDefaultConfig(c);await n.writeFileRecursive(o,i.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 r=a.computeSegment(e.apiListFileName).toLowerCase();r&&!n.has(r)&&n.set(r,t)});let r=new Set,i=[];for(let e of t){let t=e.toLowerCase(),a=n.get(t);a===void 0?i.push(e):r.add(a)}if(i.length){let t=e.map(e=>e.name??a.computeSegment(e.apiListFileName)).filter(Boolean).join(`, `);throw Error(`未找到匹配的 swagger 服务:${i.join(`, `)}。可用服务:${t||`<无>`}`)}return Array.from(r).sort((e,t)=>e-t)}async promptSelectServices(e){let t=e.map((e,t)=>{let n=a.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,r,i,o,s){let c=process.cwd();try{let l=await this.getConfig(c,s),u={...S,...l},p=i??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=>a.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`?``:a.segmentToNamespacePrefix(a.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
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=>a.isEnumIsolated(g[e])&&b[e])&&await this.writeTopLevelEnumsBarrel(u,b,g,w,T),g.every(a.isEnumIsolated)&&await this.warnLegacyTopLevelEnums(u)),r!==void 0&&r!==!1&&await d.formatGeneratedFiles(u,r,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
5
  `)}}catch(e){let n=e instanceof Error?e.message:`Unknown error`;t.log.error(`Initialization failed: ${n}`),process.exitCode=1}}printExecutionPlan(e,n,r){let i=new Set(n);t.log.print(_.default.cyan(r?`
6
6
  [anl type] 选择型生成,仅处理以下服务:`:`
@@ -2,7 +2,7 @@ const e=require(`../../utils/logger.cjs`);require(`../../utils/index.cjs`);const
2
2
  `)?n.push(`${t}/** ${r[0]} */`):(n.push(`${t}/**`),r.forEach(e=>{e.includes(`
3
3
  `)?e.split(`
4
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=t.sanitizeIdentifierName(l.name);i.push(`${s}type ${e} = ${n.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=t.formatPropertyName(l.name);a.push(`${s}${i}${e}: ${n.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=t.formatPropertyName(l.name);o.push(`${s}${i}${e}: ${n.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 t=this.getIndentation(),{schema:r}=this.pickRequestBodyContent(e);if(r){let e=this.schemaResolver.main(r,`request`);return`${t}type Body = ${n.indentContinuationLines(Array.isArray(e)?`{ ${e.join(`
5
- `)} }`:e,t)};`}}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 t=this.pickPreferredResponse(e);if(!t){this.contentBody.response=`type Response = unknown`,this.contentBody._response=`unknown`;return}let r=`content`in t?t:null,i=`$ref`in t?t: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
+ `)} }`:e,t)};`}}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):`{}`}normalizeRequestPathPrefix(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.normalizeRequestPathPrefix(this.config.requestPathPrefix),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 t=this.pickPreferredResponse(e);if(!t){this.contentBody.response=`type Response = unknown`,this.contentBody._response=`unknown`;return}let r=`content`in t?t:null,i=`$ref`in t?t: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(`
6
6
  `)};`;else{let t=this.config.formatting?.lineEnding,n=this.config.formatting?.indentation;this.contentBody.response=`interface Response {${t}${e.join(`
7
7
  `)}${t}${n}};`}this.contentBody._response=`${e.join(`
8
8
  `)}`}else this.contentBody.response=`type Response = ${n.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(`
@@ -1 +1 @@
1
- const e=require(`../shared/naming.cjs`);function t(e){let t=e.replace(/^[0-9]+/,``);return t?(t=t.replace(/[^a-zA-Z0-9_.-]/g,``),t):`num`+e}function n(e,n=!1){let r=t(e).split(/[-_.]+/).filter(e=>e.length>0);return r.length===0?``:r.map((e,t)=>t===0&&n?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)}function r(e){let n=t(e).split(/[-_.]+/).filter(e=>e.length>0);return n.length===0?``:n.map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)}function i(e){return e?e.replace(/^\/+|\/+$/g,``):``}function a(e,t){let n=t.replace(/^\/+/,``),r=i(e.publicPrefix);if(r&&n.startsWith(r+`/`))n=n.slice(r.length+1);else if(r&&n===r)n=``;else if(r&&n.startsWith(r)){let e=n.slice(r.length);(e.startsWith(`/`)||e===``)&&(n=e.replace(/^\/+/,``))}return n}function o(e){let n=[];for(let r=0;r<e.length;r++){let i=e[r],a=e[r+1];i.type===`normal`&&a?.type===`param`&&t(i.normalized).toLowerCase().replace(/[-_.]/g,``)===t(a.normalized).toLowerCase().replace(/[-_.]/g,``)||n.push(i)}return n}function s(i,s){let c=i;i.startsWith(`/`)||(c=`/`+i);let[l,u]=c.split(`|`),d=a(s,l),f=d?d.split(`/`).filter(e=>e):[],p=o(f.map(e=>e.startsWith(`{`)&&e.endsWith(`}`)?{type:`param`,original:e,normalized:e.slice(1,-1)}:{type:`normal`,original:e,normalized:e})),m=s.parameterSeparator??`_`,h=``,g=[],_=e=>{if(g.length>0){let t=g.map((t,r)=>n(t,e&&r===0)).join(``);h+=(h&&g.length>0?m:``)+t,g=[]}};for(let e of p)if(e.type===`normal`)g.push(e.normalized);else{_(h===``);let n=t(e.normalized);h+=(h?m:``)+n}_(h===``);let v=``;g=[];let y=()=>{if(g.length>0){let e=g.map(e=>r(e)).join(``);v+=(v&&g.length>0?m:``)+e,g=[]}};for(let e of p)if(e.type===`normal`)g.push(e.normalized);else{y();let t=r(e.normalized);v+=(v?m:``)+t}y();let b=``;f.length>0?(b=f.map(e=>e.replace(/[{}]/g,``)).join(`-`),b=`${b}-${u}`.toLowerCase()):b=`${u}`.toLowerCase();let x=`/`+d;d||(x=`/`),x=x.replace(/\{([\w-]+)\}/g,(e,t)=>`\${${t.replace(/-/g,`_`)}}`);let S=v?`${v}_${u}`:u,C=e.getNamespacePrefix(s),w=C?`${C}_${S}`:S;return{apiName:h?`${h}_${u}`:u,fileName:b,typeName:w,path:x}}exports.convertEndpointString=s;
1
+ const e=require(`../shared/naming.cjs`);function t(e){let t=e.replace(/^[0-9]+/,``);return t?(t=t.replace(/[^a-zA-Z0-9_.-]/g,``),t):`num`+e}function n(e,n=!1){let r=t(e).split(/[-_.]+/).filter(e=>e.length>0);return r.length===0?``:r.map((e,t)=>t===0&&n?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)}function r(e){let n=t(e).split(/[-_.]+/).filter(e=>e.length>0);return n.length===0?``:n.map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)}function i(e){return e?e.replace(/^\/+|\/+$/g,``):``}function a(e,t){let n=t.replace(/^\/+/,``),r=i(e.stripPathPrefix);if(r&&n.startsWith(r+`/`))n=n.slice(r.length+1);else if(r&&n===r)n=``;else if(r&&n.startsWith(r)){let e=n.slice(r.length);(e.startsWith(`/`)||e===``)&&(n=e.replace(/^\/+/,``))}return n}function o(e){let n=[];for(let r=0;r<e.length;r++){let i=e[r],a=e[r+1];i.type===`normal`&&a?.type===`param`&&t(i.normalized).toLowerCase().replace(/[-_.]/g,``)===t(a.normalized).toLowerCase().replace(/[-_.]/g,``)||n.push(i)}return n}function s(i,s){let c=i;i.startsWith(`/`)||(c=`/`+i);let[l,u]=c.split(`|`),d=a(s,l),f=d?d.split(`/`).filter(e=>e):[],p=o(f.map(e=>e.startsWith(`{`)&&e.endsWith(`}`)?{type:`param`,original:e,normalized:e.slice(1,-1)}:{type:`normal`,original:e,normalized:e})),m=s.parameterSeparator??`_`,h=``,g=[],_=e=>{if(g.length>0){let t=g.map((t,r)=>n(t,e&&r===0)).join(``);h+=(h&&g.length>0?m:``)+t,g=[]}};for(let e of p)if(e.type===`normal`)g.push(e.normalized);else{_(h===``);let n=t(e.normalized);h+=(h?m:``)+n}_(h===``);let v=``;g=[];let y=()=>{if(g.length>0){let e=g.map(e=>r(e)).join(``);v+=(v&&g.length>0?m:``)+e,g=[]}};for(let e of p)if(e.type===`normal`)g.push(e.normalized);else{y();let t=r(e.normalized);v+=(v?m:``)+t}y();let b=``;f.length>0?(b=f.map(e=>e.replace(/[{}]/g,``)).join(`-`),b=`${b}-${u}`.toLowerCase()):b=`${u}`.toLowerCase();let x=`/`+d;d||(x=`/`),x=x.replace(/\{([\w-]+)\}/g,(e,t)=>`\${${t.replace(/-/g,`_`)}}`);let S=v?`${v}_${u}`:u,C=e.getNamespacePrefix(s),w=C?`${C}_${S}`:S;return{apiName:h?`${h}_${u}`:u,fileName:b,typeName:w,path:x}}exports.convertEndpointString=s;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anl",
3
- "version": "26.930.0",
3
+ "version": "26.1010.0",
4
4
  "description": "FE command line tool",
5
5
  "main": "bin/an-cli.js",
6
6
  "exports": {