@cnbcool/cnb-api-generate 2.4.7 → 2.5.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/built/codegen/api/build-query-value-expression.js +62 -0
- package/built/codegen/api/generate-api-function-ast-node.js +2 -2
- package/built/codegen/api/generate-function-content-ast-node.js +16 -8
- package/built/codegen/api/generate-function-params-ast-node.js +69 -12
- package/built/utils/compute-param-aliases.js +55 -0
- package/built/utils/flatten-tool-options.js +7 -2
- package/built/utils/query-path-alias.js +38 -0
- package/client/lib/format-params.ts +24 -2
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildQueryValueExpression = buildQueryValueExpression;
|
|
37
|
+
const ts = __importStar(require("typescript"));
|
|
38
|
+
const query_path_alias_1 = require("../../utils/query-path-alias");
|
|
39
|
+
/**
|
|
40
|
+
* 构造请求参数对象里 `params:` / `_originParams.query:` 字段的值表达式。
|
|
41
|
+
*
|
|
42
|
+
* 规则:
|
|
43
|
+
* - path 与 query 没有同名冲突时:直接返回 `Identifier(queryVarName)`,
|
|
44
|
+
* 生成代码形如 `params: __query`;
|
|
45
|
+
* - 存在同名冲突时(如 `/{repo}/-/knowledge/base/query/{query}` 同时带 `?query=xxx`):
|
|
46
|
+
* 返回对象字面量 `{ ...__query, ["<原始 key>"]: q_<原始 key>, ... }`,
|
|
47
|
+
* 通过计算属性把别名 `q_xxx` 映射回 swagger 里的原始 key,
|
|
48
|
+
* 保证发给后端的 query string key 与 swagger 契约一致。
|
|
49
|
+
*/
|
|
50
|
+
function buildQueryValueExpression(queryVarName, pathParams, queryParams) {
|
|
51
|
+
const aliasMap = (0, query_path_alias_1.collectQueryPathAliasMap)(pathParams, queryParams);
|
|
52
|
+
if (aliasMap.size === 0) {
|
|
53
|
+
return ts.factory.createIdentifier(queryVarName);
|
|
54
|
+
}
|
|
55
|
+
const properties = [
|
|
56
|
+
ts.factory.createSpreadAssignment(ts.factory.createIdentifier(queryVarName)),
|
|
57
|
+
];
|
|
58
|
+
aliasMap.forEach((aliasName, originalName) => {
|
|
59
|
+
properties.push(ts.factory.createPropertyAssignment(ts.factory.createComputedPropertyName(ts.factory.createStringLiteral(originalName)), ts.factory.createIdentifier(aliasName)));
|
|
60
|
+
});
|
|
61
|
+
return ts.factory.createObjectLiteralExpression(properties, false);
|
|
62
|
+
}
|
|
@@ -55,7 +55,7 @@ function generateApiFunctionASTNode(methodData, definitions, defintionsMap) {
|
|
|
55
55
|
let dependencies = new Set();
|
|
56
56
|
// 根据parameters的类型,处理请求中不同的数据的处理方式
|
|
57
57
|
const { pathParams, bodyParams, queryParams } = (0, filter_api_param_1.filterApiParam)(path, parameters);
|
|
58
|
-
const { requestParamsASTNodes: paramASTNodes, reduxActionMap, dependencies: paramsDependencies, requestInterfaceASTNodes: paramsInterfaceASTNodes, } = (0, generate_function_params_ast_node_1.generateFunctionParamsASTNode)(methodData, pathParams, queryParams, bodyParams, defintionsMap);
|
|
58
|
+
const { requestParamsASTNodes: paramASTNodes, reduxActionMap, dependencies: paramsDependencies, requestInterfaceASTNodes: paramsInterfaceASTNodes, paramAliases, } = (0, generate_function_params_ast_node_1.generateFunctionParamsASTNode)(methodData, pathParams, queryParams, bodyParams, defintionsMap);
|
|
59
59
|
if (paramsDependencies && paramsDependencies.size > 0) {
|
|
60
60
|
dependencies = new Set([...dependencies, ...paramsDependencies]);
|
|
61
61
|
}
|
|
@@ -113,7 +113,7 @@ function generateApiFunctionASTNode(methodData, definitions, defintionsMap) {
|
|
|
113
113
|
? undefined
|
|
114
114
|
: ts.factory.createIdentifier(methodData.exportName), undefined, paramASTNodes, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
115
115
|
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(constants_1.CNB_REQUEST_RESULT_INTERFACE), [successApiReturnType, errorApiReturnType]),
|
|
116
|
-
]), (0, generate_function_content_ast_node_1.generateFunctionContentASTNode)(methodData, successApiReturnType, errorApiReturnType, pathParams, queryParams, bodyParams)));
|
|
116
|
+
]), (0, generate_function_content_ast_node_1.generateFunctionContentASTNode)(methodData, successApiReturnType, errorApiReturnType, pathParams, queryParams, bodyParams, paramAliases)));
|
|
117
117
|
for (const dependency of dependencies) {
|
|
118
118
|
const defintion = defintionsMap[dependency];
|
|
119
119
|
requestFileDependenciesASTNodes.push((0, generate_import_ast_node_1.generateImportAstNode)(defintion.exportName, defintion.filename, false, category, defintion.type));
|
|
@@ -38,11 +38,17 @@ const ts = __importStar(require("typescript"));
|
|
|
38
38
|
const constants_1 = require("../../constants");
|
|
39
39
|
const generate_request_url_ast_node_1 = require("./generate-request-url-ast-node");
|
|
40
40
|
const is_skills_1 = require("../../utils/is-skills");
|
|
41
|
-
|
|
41
|
+
const build_query_value_expression_1 = require("./build-query-value-expression");
|
|
42
|
+
function generateFunctionContentASTNode(methodData, fetchSuccessResponse, fetchErrorResponse, pathParams, queryParams, bodyParams, paramAliases) {
|
|
43
|
+
var _a, _b, _c, _d;
|
|
44
|
+
const queryVarName = (_a = paramAliases === null || paramAliases === void 0 ? void 0 : paramAliases.queryName) !== null && _a !== void 0 ? _a : constants_1.CNB_REQUEST_PARAM_QUERY_NAME;
|
|
45
|
+
const reqVarName = (_b = paramAliases === null || paramAliases === void 0 ? void 0 : paramAliases.reqName) !== null && _b !== void 0 ? _b : constants_1.CNB_REQUEST_PARAM_REQ_NAME;
|
|
46
|
+
const optionsVarName = (_c = paramAliases === null || paramAliases === void 0 ? void 0 : paramAliases.optionsName) !== null && _c !== void 0 ? _c : constants_1.CNB_REQUEST_PARAM_OPTIONS_NAME;
|
|
47
|
+
const axiosConfigVarName = (_d = paramAliases === null || paramAliases === void 0 ? void 0 : paramAliases.axiosConfigName) !== null && _d !== void 0 ? _d : constants_1.CNB_REQUEST_AXIOS_CONFIG_NAME;
|
|
42
48
|
const requestParams = [
|
|
43
|
-
ts.factory.createSpreadAssignment(ts.factory.createIdentifier(
|
|
44
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_CONFIG_NEXT_REQ), ts.factory.createIdentifier(
|
|
45
|
-
ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_OPTIONS_NAME), ts.factory.createIdentifier(
|
|
49
|
+
ts.factory.createSpreadAssignment(ts.factory.createIdentifier(axiosConfigVarName)),
|
|
50
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_CONFIG_NEXT_REQ), ts.factory.createIdentifier(reqVarName)),
|
|
51
|
+
ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_OPTIONS_NAME), ts.factory.createIdentifier(optionsVarName)),
|
|
46
52
|
];
|
|
47
53
|
// 请求路径
|
|
48
54
|
requestParams.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_CONFIG_URL), (0, generate_request_url_ast_node_1.generateRequestUrlASTNode)(methodData.path, pathParams)));
|
|
@@ -52,11 +58,12 @@ function generateFunctionContentASTNode(methodData, fetchSuccessResponse, fetchE
|
|
|
52
58
|
requestParams.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_CONFIG_METHOD), ts.factory.createStringLiteral(methodData.method)));
|
|
53
59
|
// 请求query
|
|
54
60
|
if (queryParams && queryParams.length > 0) {
|
|
55
|
-
requestParams.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_QUERY_KEY_NAME),
|
|
61
|
+
requestParams.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_QUERY_KEY_NAME), (0, build_query_value_expression_1.buildQueryValueExpression)(queryVarName, pathParams, queryParams)));
|
|
56
62
|
}
|
|
57
63
|
// 请求body
|
|
58
64
|
if (bodyParams) {
|
|
59
|
-
|
|
65
|
+
const bodyVarName = (paramAliases === null || paramAliases === void 0 ? void 0 : paramAliases.bodyParamName) || bodyParams.name;
|
|
66
|
+
requestParams.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_CONFIG_DATA), ts.factory.createIdentifier(bodyVarName)));
|
|
60
67
|
}
|
|
61
68
|
// 生成skills时,请求参数需要包含_originalParams,用于后处理时使用
|
|
62
69
|
if ((0, is_skills_1.isSkills)()) {
|
|
@@ -72,10 +79,11 @@ function generateFunctionContentASTNode(methodData, fetchSuccessResponse, fetchE
|
|
|
72
79
|
objectLiteralExpression.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_PATH_PARAM_ORIGIN_NAME), ts.factory.createObjectLiteralExpression(pathParams.map((p) => ts.factory.createShorthandPropertyAssignment(ts.factory.createIdentifier(p.name), undefined)), false)));
|
|
73
80
|
}
|
|
74
81
|
if (queryParams.length > 0) {
|
|
75
|
-
objectLiteralExpression.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_QUERY_PARAM_ORIGIN_NAME),
|
|
82
|
+
objectLiteralExpression.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_QUERY_PARAM_ORIGIN_NAME), (0, build_query_value_expression_1.buildQueryValueExpression)(queryVarName, pathParams, queryParams)));
|
|
76
83
|
}
|
|
77
84
|
if (bodyParams) {
|
|
78
|
-
|
|
85
|
+
const bodyVarName = (paramAliases === null || paramAliases === void 0 ? void 0 : paramAliases.bodyParamName) || bodyParams.name;
|
|
86
|
+
objectLiteralExpression.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_BODY_PARAM_ORIGIN_NAME), ts.factory.createIdentifier(bodyVarName)));
|
|
79
87
|
}
|
|
80
88
|
requestParams.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(constants_1.CNB_REQUEST_ORIGIN_PARAM_NAME), ts.factory.createObjectLiteralExpression(objectLiteralExpression, true)));
|
|
81
89
|
}
|
|
@@ -42,8 +42,13 @@ const get_keyword_type_node_1 = require("../../utils/get-keyword-type-node");
|
|
|
42
42
|
const is_english_only_1 = require("../../utils/is-english-only");
|
|
43
43
|
const constants_1 = require("../../constants");
|
|
44
44
|
const md_array_type_content_ast_node_1 = require("../types/md-array-type-content-ast-node");
|
|
45
|
+
const compute_param_aliases_1 = require("../../utils/compute-param-aliases");
|
|
46
|
+
const query_path_alias_1 = require("../../utils/query-path-alias");
|
|
45
47
|
function generateFunctionParamsASTNode(methodData, pathParams, queryParams, bodyParams, defintionsMap) {
|
|
46
48
|
var _a;
|
|
49
|
+
// 计算保留变量名(query/req/options/axiosConfig)的安全别名,
|
|
50
|
+
// 避免与 path/body 参数重名导致 "Argument name clash" 等语法错误。
|
|
51
|
+
const paramAliases = (0, compute_param_aliases_1.computeParamAliases)(pathParams, bodyParams);
|
|
47
52
|
// request函数参数
|
|
48
53
|
const requestParamsASTNodes = [];
|
|
49
54
|
const requestInterfaceASTNodes = [];
|
|
@@ -60,8 +65,29 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
60
65
|
const paramsInterfaceName = `${(0, format_interface_name_1.formatInterfaceName)(methodData.exportName)}Params`;
|
|
61
66
|
const paramMap = {};
|
|
62
67
|
const firstParams = [];
|
|
63
|
-
//
|
|
64
|
-
|
|
68
|
+
// path 参数与 query 参数同名时(如 /{repo}/-/knowledge/base/query/{query} 同时带 ?query=xxx):
|
|
69
|
+
// 两者语义不同,需要同时在类型里表达:
|
|
70
|
+
// - path 字段沿用 swagger 的原名(URL 模板里的字面占位,必须保持原名);
|
|
71
|
+
// - query 字段通过 `q_<name>` 别名字段在 interface 中暴露,
|
|
72
|
+
// 运行时再通过计算属性把别名映射回 swagger 的原始 key(见 generate-function-content-ast-node.ts)。
|
|
73
|
+
const pathParamNameSet = new Set(pathParams.map((p) => p.name));
|
|
74
|
+
[
|
|
75
|
+
...pathParams,
|
|
76
|
+
...queryParams.map((q) => {
|
|
77
|
+
if (!pathParamNameSet.has(q.name))
|
|
78
|
+
return q;
|
|
79
|
+
// 同名冲突:拷贝 query 参数并改名为 `q_<name>`,以便在 interface 中作为独立字段出现
|
|
80
|
+
const aliasName = (0, query_path_alias_1.getQueryPathAliasName)(q.name);
|
|
81
|
+
const aliasDesc = q.description
|
|
82
|
+
? `${q.description}(query string 参数;该路由 path 也存在同名字段,为避免冲突此处使用别名 ${aliasName})`
|
|
83
|
+
: `query string 参数;该路由 path 也存在同名字段,为避免冲突此处使用别名 ${aliasName}`;
|
|
84
|
+
return {
|
|
85
|
+
...q,
|
|
86
|
+
name: aliasName,
|
|
87
|
+
description: aliasDesc,
|
|
88
|
+
};
|
|
89
|
+
}),
|
|
90
|
+
].map((item) => {
|
|
65
91
|
paramMap[item.name] = item;
|
|
66
92
|
});
|
|
67
93
|
Object.keys(paramMap).forEach((key) => {
|
|
@@ -146,10 +172,21 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
146
172
|
const pathParamsBindingElements = pathParams.map((item) => {
|
|
147
173
|
return ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(item.name), undefined);
|
|
148
174
|
});
|
|
175
|
+
// 同名 path/query 别名字段(如 q_query),需要单独从对象中解构出来,
|
|
176
|
+
// 避免被 `...__query` 吞掉后再做重映射(保留了可读性,并与 generate-function-content-ast-node 联动)。
|
|
177
|
+
const aliasQueryBindingElements = (queryParams || [])
|
|
178
|
+
.filter((q) => pathParamNameSet.has(q.name))
|
|
179
|
+
.map((q) => {
|
|
180
|
+
const aliasName = (0, query_path_alias_1.getQueryPathAliasName)(q.name);
|
|
181
|
+
return ts.factory.createBindingElement(undefined, undefined, ts.factory.createIdentifier(aliasName), undefined);
|
|
182
|
+
});
|
|
149
183
|
// 创建解构参数
|
|
150
|
-
const deconstructionParams = [
|
|
184
|
+
const deconstructionParams = [
|
|
185
|
+
...pathParamsBindingElements,
|
|
186
|
+
...aliasQueryBindingElements,
|
|
187
|
+
];
|
|
151
188
|
if (queryParams && queryParams.length > 0) {
|
|
152
|
-
deconstructionParams.push(ts.factory.createBindingElement(ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), undefined, ts.factory.createIdentifier(
|
|
189
|
+
deconstructionParams.push(ts.factory.createBindingElement(ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), undefined, ts.factory.createIdentifier(paramAliases.queryName), undefined));
|
|
153
190
|
}
|
|
154
191
|
requestParamsASTNodes.push(ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern(deconstructionParams), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(paramsInterfaceName), undefined), undefined));
|
|
155
192
|
// redux action参数定义
|
|
@@ -176,6 +213,11 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
176
213
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
177
214
|
for (let i = 0; i < allRequestParams.length; i++) {
|
|
178
215
|
const param = allRequestParams[i];
|
|
216
|
+
// 仅 body 参数需要用别名替换标识符;单个 path 参数保留原名(必须等于 URL 占位符)
|
|
217
|
+
const isBodyParam = bodyParams !== null && param === bodyParams;
|
|
218
|
+
const effectiveParamName = isBodyParam && paramAliases.bodyParamName
|
|
219
|
+
? paramAliases.bodyParamName
|
|
220
|
+
: param.name;
|
|
179
221
|
if (param === null || param === void 0 ? void 0 : param.schema) {
|
|
180
222
|
// 多维数组处理
|
|
181
223
|
if (param.schema.type &&
|
|
@@ -192,13 +234,13 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
192
234
|
requestInterfaceASTNodes.push(ts.factory.createExpressionStatement(ts.factory.createStringLiteral(`<$${paramsBodyName}$>`)));
|
|
193
235
|
// 创建interface主体
|
|
194
236
|
requestInterfaceASTNodes.push(ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(paramsBodyName), undefined, returnType));
|
|
195
|
-
requestParamsASTNodes.push(ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier(
|
|
237
|
+
requestParamsASTNodes.push(ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier(effectiveParamName), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(paramsBodyName), undefined), undefined));
|
|
196
238
|
if (typeDependencies && typeDependencies.size > 0) {
|
|
197
239
|
dependencies = new Set([...dependencies, ...typeDependencies]);
|
|
198
240
|
}
|
|
199
241
|
// redux action参数定义
|
|
200
242
|
reduxActionMap.paramsSequence.push({
|
|
201
|
-
param:
|
|
243
|
+
param: effectiveParamName,
|
|
202
244
|
typeLiteral: paramsBodyName,
|
|
203
245
|
typeLiteralLabel: constants_1.TypeLiteralLabel.Quoted,
|
|
204
246
|
required: param.required,
|
|
@@ -207,7 +249,14 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
207
249
|
}
|
|
208
250
|
else {
|
|
209
251
|
const [imports, astNode, paramsSequenceItem] = (0, generate_function_refs_type_params_ast_node_1.generateFunctionReferenceTypeDataParamsASTNode)(param, defintionsMap);
|
|
210
|
-
astNode &&
|
|
252
|
+
if (astNode && isBodyParam && effectiveParamName !== param.name) {
|
|
253
|
+
// 替换 body 参数的标识符为别名
|
|
254
|
+
requestParamsASTNodes.push(ts.factory.updateParameterDeclaration(astNode, astNode.modifiers, astNode.dotDotDotToken, ts.factory.createIdentifier(effectiveParamName), astNode.questionToken, astNode.type, astNode.initializer));
|
|
255
|
+
paramsSequenceItem.param = effectiveParamName;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
astNode && requestParamsASTNodes.push(astNode);
|
|
259
|
+
}
|
|
211
260
|
if (imports && imports.size > 0) {
|
|
212
261
|
dependencies = new Set([...dependencies, ...imports]);
|
|
213
262
|
}
|
|
@@ -216,11 +265,14 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
216
265
|
}
|
|
217
266
|
}
|
|
218
267
|
else {
|
|
219
|
-
|
|
268
|
+
let normalParamsASTNode = (0, generate_function_normal_params_ast_node_1.generateFunctionNormalParamsASTNode)(param);
|
|
269
|
+
if (isBodyParam && effectiveParamName !== param.name) {
|
|
270
|
+
normalParamsASTNode = ts.factory.updateParameterDeclaration(normalParamsASTNode, normalParamsASTNode.modifiers, normalParamsASTNode.dotDotDotToken, ts.factory.createIdentifier(effectiveParamName), normalParamsASTNode.questionToken, normalParamsASTNode.type, normalParamsASTNode.initializer);
|
|
271
|
+
}
|
|
220
272
|
requestParamsASTNodes.push(normalParamsASTNode);
|
|
221
273
|
// redux action参数定义
|
|
222
274
|
reduxActionMap.paramsSequence.push({
|
|
223
|
-
param:
|
|
275
|
+
param: effectiveParamName,
|
|
224
276
|
typeLiteral: param.type || null,
|
|
225
277
|
typeLiteralLabel: constants_1.TypeLiteralLabel.Native,
|
|
226
278
|
required: param.required,
|
|
@@ -229,9 +281,13 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
229
281
|
}
|
|
230
282
|
// 添加requestConfig
|
|
231
283
|
requestParamsASTNodes.push(ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createObjectBindingPattern([
|
|
232
|
-
ts.factory.createBindingElement(undefined,
|
|
233
|
-
|
|
234
|
-
|
|
284
|
+
ts.factory.createBindingElement(undefined, paramAliases.reqName === constants_1.CNB_REQUEST_PARAM_REQ_NAME
|
|
285
|
+
? undefined
|
|
286
|
+
: ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_REQ_NAME), ts.factory.createIdentifier(paramAliases.reqName), undefined),
|
|
287
|
+
ts.factory.createBindingElement(undefined, paramAliases.optionsName === constants_1.CNB_REQUEST_PARAM_OPTIONS_NAME
|
|
288
|
+
? undefined
|
|
289
|
+
: ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_OPTIONS_NAME), ts.factory.createIdentifier(paramAliases.optionsName), undefined),
|
|
290
|
+
ts.factory.createBindingElement(ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), undefined, ts.factory.createIdentifier(paramAliases.axiosConfigName), undefined),
|
|
235
291
|
]), undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(constants_1.CNB_REQUEST_PARAM_TYPE_NAME), undefined), ts.factory.createObjectLiteralExpression([], false)));
|
|
236
292
|
// redux action参数定义
|
|
237
293
|
reduxActionMap.paramsSequence.push({
|
|
@@ -245,5 +301,6 @@ function generateFunctionParamsASTNode(methodData, pathParams, queryParams, body
|
|
|
245
301
|
reduxActionMap,
|
|
246
302
|
dependencies,
|
|
247
303
|
requestInterfaceASTNodes,
|
|
304
|
+
paramAliases,
|
|
248
305
|
};
|
|
249
306
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeParamAliases = computeParamAliases;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const RESERVED_DEFAULTS = {
|
|
6
|
+
queryName: constants_1.CNB_REQUEST_PARAM_QUERY_NAME,
|
|
7
|
+
reqName: constants_1.CNB_REQUEST_PARAM_REQ_NAME,
|
|
8
|
+
optionsName: constants_1.CNB_REQUEST_PARAM_OPTIONS_NAME,
|
|
9
|
+
axiosConfigName: constants_1.CNB_REQUEST_AXIOS_CONFIG_NAME,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 给定一个目标变量名 base 和已被占用的名字集合 used,
|
|
13
|
+
* 返回不与 used 冲突的安全名(依次尝试 _base、__base 等)。
|
|
14
|
+
*/
|
|
15
|
+
function pickUniqueName(base, used) {
|
|
16
|
+
if (!used.has(base))
|
|
17
|
+
return base;
|
|
18
|
+
let candidate = `_${base}`;
|
|
19
|
+
while (used.has(candidate)) {
|
|
20
|
+
candidate = `_${candidate}`;
|
|
21
|
+
}
|
|
22
|
+
return candidate;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 根据 path/body 参数名计算需要使用的保留变量名别名,避免命名冲突。
|
|
26
|
+
*
|
|
27
|
+
* 注意 path 参数名是"硬约束"(必须等于 URL 模板中的占位符名),
|
|
28
|
+
* 因此优先占用 path 参数名,再依次给 body / 保留变量分配安全名。
|
|
29
|
+
*/
|
|
30
|
+
function computeParamAliases(pathParams = [], bodyParams = null) {
|
|
31
|
+
var _a;
|
|
32
|
+
const used = new Set();
|
|
33
|
+
pathParams.forEach((p) => {
|
|
34
|
+
if (p === null || p === void 0 ? void 0 : p.name)
|
|
35
|
+
used.add(p.name);
|
|
36
|
+
});
|
|
37
|
+
// body 参数名:与 path 参数 / 保留名冲突时改名
|
|
38
|
+
const originalBodyName = (_a = bodyParams === null || bodyParams === void 0 ? void 0 : bodyParams.name) !== null && _a !== void 0 ? _a : '';
|
|
39
|
+
const bodyParamName = originalBodyName
|
|
40
|
+
? pickUniqueName(originalBodyName, used)
|
|
41
|
+
: '';
|
|
42
|
+
if (bodyParamName)
|
|
43
|
+
used.add(bodyParamName);
|
|
44
|
+
const aliases = {
|
|
45
|
+
...RESERVED_DEFAULTS,
|
|
46
|
+
bodyParamName,
|
|
47
|
+
};
|
|
48
|
+
// 保留变量按顺序分配,先分配出去的别名也要避免后续被占用
|
|
49
|
+
['queryName', 'reqName', 'optionsName', 'axiosConfigName'].forEach((key) => {
|
|
50
|
+
const safe = pickUniqueName(RESERVED_DEFAULTS[key], used);
|
|
51
|
+
aliases[key] = safe;
|
|
52
|
+
used.add(safe);
|
|
53
|
+
});
|
|
54
|
+
return aliases;
|
|
55
|
+
}
|
|
@@ -36,20 +36,25 @@ function flattenToolOptions(toolInfo) {
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
// query
|
|
39
|
+
// query 参数:与 path 同名时,optKey 前缀 q- 以避免 Commander 选项名冲突
|
|
40
40
|
if (queryDef) {
|
|
41
|
+
const pathKeys = new Set(pathDef ? Object.keys(pathDef) : []);
|
|
41
42
|
for (const [key, param] of Object.entries(queryDef)) {
|
|
42
43
|
const valuePlaceholder = (0, option_value_flag_1.optionValueFlag)(param.type);
|
|
43
44
|
const rawDesc = (0, trim_summary_1.trimSummary)(param.description || '');
|
|
44
45
|
const desc = param.required ? `[必填] ${rawDesc}` : rawDesc;
|
|
46
|
+
const conflict = pathKeys.has(key);
|
|
47
|
+
const optKey = conflict ? `q-${key}` : key;
|
|
45
48
|
const opt = {
|
|
46
|
-
optKey
|
|
49
|
+
optKey,
|
|
47
50
|
valuePlaceholder,
|
|
48
51
|
description: desc,
|
|
49
52
|
required: !!param.required,
|
|
50
53
|
isArray: false,
|
|
51
54
|
source: 'query',
|
|
52
55
|
};
|
|
56
|
+
if (conflict)
|
|
57
|
+
opt.originalName = key;
|
|
53
58
|
if (param.enum)
|
|
54
59
|
opt.choices = param.enum;
|
|
55
60
|
if (param.default !== undefined)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QUERY_PATH_ALIAS_PREFIX = void 0;
|
|
4
|
+
exports.getQueryPathAliasName = getQueryPathAliasName;
|
|
5
|
+
exports.collectQueryPathAliasMap = collectQueryPathAliasMap;
|
|
6
|
+
/**
|
|
7
|
+
* path 参数与 query 参数同名时,query 字段在生成的 interface / 函数解构里
|
|
8
|
+
* 统一使用的别名前缀。
|
|
9
|
+
*
|
|
10
|
+
* 例如 swagger 中 `/{repo}/-/knowledge/base/query/{query}` 同时存在
|
|
11
|
+
* { name: 'query', in: 'path' }
|
|
12
|
+
* { name: 'query', in: 'query' }
|
|
13
|
+
* 两个语义不同的参数。我们保留 path 字段的原名(URL 占位),
|
|
14
|
+
* 而 query 字段改名为 `q_query`,运行时再用计算属性映射回原始 key。
|
|
15
|
+
*/
|
|
16
|
+
exports.QUERY_PATH_ALIAS_PREFIX = 'q_';
|
|
17
|
+
/**
|
|
18
|
+
* 给定 swagger 原始 query 参数名,返回它在生成代码里的别名。
|
|
19
|
+
*/
|
|
20
|
+
function getQueryPathAliasName(originalName) {
|
|
21
|
+
return `${exports.QUERY_PATH_ALIAS_PREFIX}${originalName}`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 收集 query 参数中名字与 path 参数同名的项,返回 `原始名 -> 别名` 的映射。
|
|
25
|
+
* 没有冲突时返回空 Map。
|
|
26
|
+
*/
|
|
27
|
+
function collectQueryPathAliasMap(pathParams = [], queryParams = []) {
|
|
28
|
+
const map = new Map();
|
|
29
|
+
if (!pathParams.length || !queryParams.length)
|
|
30
|
+
return map;
|
|
31
|
+
const pathNameSet = new Set(pathParams.map((p) => p.name));
|
|
32
|
+
for (const q of queryParams) {
|
|
33
|
+
if (pathNameSet.has(q.name)) {
|
|
34
|
+
map.set(q.name, getQueryPathAliasName(q.name));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return map;
|
|
38
|
+
}
|
|
@@ -48,8 +48,7 @@ export function formatParams(
|
|
|
48
48
|
const bodyProps = paramDefs.body?.schema?.properties || {};
|
|
49
49
|
|
|
50
50
|
const reservedKeys = new Set([
|
|
51
|
-
'module', 'tool', 'help', 'short', 'verbose',
|
|
52
|
-
'path', 'query', 'data', 'h', 'v',
|
|
51
|
+
'module', 'tool', 'help', 'short', 'verbose', 'h', 'v',
|
|
53
52
|
]);
|
|
54
53
|
|
|
55
54
|
// 收集 array<object> 展开字段的临时存储:{ arrayName: { propName: string[] } }
|
|
@@ -97,6 +96,18 @@ export function formatParams(
|
|
|
97
96
|
// 归入 path
|
|
98
97
|
if (!formatted.path) formatted.path = {};
|
|
99
98
|
formatted.path[key] = value;
|
|
99
|
+
// path 与 query 同名时,query 参数通过 q- 前缀传入(见下方 q- 分支);
|
|
100
|
+
// 但若调用方直接用 --<name> 传了值(旧习惯/兼容),且 queryDef 里也有同名项,
|
|
101
|
+
// 则同时回填到 query,保证 URL 查询参数也被带上。
|
|
102
|
+
if (queryDef[key]) {
|
|
103
|
+
if (!formatted.query) formatted.query = {};
|
|
104
|
+
const paramType = queryDef[key].type;
|
|
105
|
+
if (paramType === 'number' && typeof value === 'string' && !isNaN(Number(value))) {
|
|
106
|
+
formatted.query[key] = Number(value);
|
|
107
|
+
} else {
|
|
108
|
+
formatted.query[key] = value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
100
111
|
} else if (queryDef[key]) {
|
|
101
112
|
// 归入 query
|
|
102
113
|
if (!formatted.query) formatted.query = {};
|
|
@@ -106,6 +117,17 @@ export function formatParams(
|
|
|
106
117
|
} else {
|
|
107
118
|
formatted.query[key] = value;
|
|
108
119
|
}
|
|
120
|
+
} else if ((key.startsWith('q-') || key.startsWith('q_'))
|
|
121
|
+
&& queryDef[key.replace(/^q[-_]/, '')]) {
|
|
122
|
+
// query 参数与 path 同名时,CLI 层以 q- 前缀区分,这里还原为真实 query key
|
|
123
|
+
const originalKey = key.replace(/^q[-_]/, '');
|
|
124
|
+
if (!formatted.query) formatted.query = {};
|
|
125
|
+
const paramType = queryDef[originalKey].type;
|
|
126
|
+
if (paramType === 'number' && typeof value === 'string' && !isNaN(Number(value))) {
|
|
127
|
+
formatted.query[originalKey] = Number(value);
|
|
128
|
+
} else {
|
|
129
|
+
formatted.query[originalKey] = value;
|
|
130
|
+
}
|
|
109
131
|
} else if (bodyProps[key]) {
|
|
110
132
|
// body 字段(无冲突,直接用原 key)
|
|
111
133
|
if (!formatted.data) formatted.data = {};
|