czh-api 1.0.5 → 1.0.7
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/CHANGELOG.md +49 -30
- package/api.json +39529 -0
- package/dist/commands/build.js +35 -16
- package/dist/core/parser.js +11 -5
- package/package.json +1 -1
- package/src/commands/build.ts +405 -377
- package/src/core/parser.ts +146 -140
package/dist/commands/build.js
CHANGED
|
@@ -256,8 +256,8 @@ function improveTypeDefinitions(typesContent, endpoints) {
|
|
|
256
256
|
if (requestParamsTypeName && isValidTypeIdentifier(requestParamsTypeName) && endpoint.paramsJsdocParams && endpoint.paramsJsdocParams.length > 0) {
|
|
257
257
|
const paramsFields = buildFieldsFromJsdocParams(endpoint.paramsJsdocParams);
|
|
258
258
|
if (paramsFields) {
|
|
259
|
-
typeImprovements[requestParamsTypeName] = `export interface ${requestParamsTypeName} {
|
|
260
|
-
${paramsFields}
|
|
259
|
+
typeImprovements[requestParamsTypeName] = `export interface ${requestParamsTypeName} {
|
|
260
|
+
${paramsFields}
|
|
261
261
|
}`;
|
|
262
262
|
}
|
|
263
263
|
}
|
|
@@ -266,8 +266,8 @@ ${paramsFields}
|
|
|
266
266
|
if (requestBodyTypeName && isValidTypeIdentifier(requestBodyTypeName) && endpoint.dataJsdocParams && endpoint.dataJsdocParams.length > 0) {
|
|
267
267
|
const dataFields = buildFieldsFromJsdocParams(endpoint.dataJsdocParams);
|
|
268
268
|
if (dataFields) {
|
|
269
|
-
typeImprovements[requestBodyTypeName] = `export interface ${requestBodyTypeName} {
|
|
270
|
-
${dataFields}
|
|
269
|
+
typeImprovements[requestBodyTypeName] = `export interface ${requestBodyTypeName} {
|
|
270
|
+
${dataFields}
|
|
271
271
|
}`;
|
|
272
272
|
}
|
|
273
273
|
}
|
|
@@ -276,8 +276,8 @@ ${dataFields}
|
|
|
276
276
|
if (responseTargetType && endpoint.responseTypeName !== 'void' && endpoint.responseJsdocParams && endpoint.responseJsdocParams.length > 0) {
|
|
277
277
|
const responseFields = buildFieldsFromJsdocParams(endpoint.responseJsdocParams);
|
|
278
278
|
if (responseFields) {
|
|
279
|
-
typeImprovements[responseTargetType] = `export interface ${responseTargetType} {
|
|
280
|
-
${responseFields}
|
|
279
|
+
typeImprovements[responseTargetType] = `export interface ${responseTargetType} {
|
|
280
|
+
${responseFields}
|
|
281
281
|
}`;
|
|
282
282
|
}
|
|
283
283
|
}
|
|
@@ -384,6 +384,25 @@ function normalizeSchemaRefs(value) {
|
|
|
384
384
|
}
|
|
385
385
|
return value;
|
|
386
386
|
}
|
|
387
|
+
function stripNestedSchemaTitles(value, depth = 0) {
|
|
388
|
+
if (Array.isArray(value)) {
|
|
389
|
+
return value.map(item => stripNestedSchemaTitles(item, depth + 1));
|
|
390
|
+
}
|
|
391
|
+
if (value && typeof value === 'object') {
|
|
392
|
+
const obj = value;
|
|
393
|
+
const normalized = {};
|
|
394
|
+
for (const [key, currentValue] of Object.entries(obj)) {
|
|
395
|
+
// json-schema-to-typescript may generate invalid type aliases from nested title values
|
|
396
|
+
// (e.g. Chinese punctuation or numeric-leading titles), so keep only root-level titles.
|
|
397
|
+
if (key === 'title' && depth > 0) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
normalized[key] = stripNestedSchemaTitles(currentValue, depth + 1);
|
|
401
|
+
}
|
|
402
|
+
return normalized;
|
|
403
|
+
}
|
|
404
|
+
return value;
|
|
405
|
+
}
|
|
387
406
|
const handleBuild = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
388
407
|
try {
|
|
389
408
|
console.log(chalk_1.default.blue('Building API from source...'));
|
|
@@ -483,7 +502,7 @@ const handleBuild = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
483
502
|
if (Object.keys(module.schemas).length > 0) {
|
|
484
503
|
console.log(chalk_1.default.blue(`正在为模块 "${moduleName}" 生成类型文件,包含 ${Object.keys(module.schemas).length} 个 schema`));
|
|
485
504
|
try {
|
|
486
|
-
const normalizedModuleSchemas = normalizeSchemaRefs(module.schemas);
|
|
505
|
+
const normalizedModuleSchemas = stripNestedSchemaTitles(normalizeSchemaRefs(module.schemas));
|
|
487
506
|
const schemasWithTitles = {};
|
|
488
507
|
for (const schemaName in normalizedModuleSchemas) {
|
|
489
508
|
schemasWithTitles[schemaName] = Object.assign(Object.assign({}, normalizedModuleSchemas[schemaName]), { title: schemaName });
|
|
@@ -533,7 +552,7 @@ const handleBuild = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
533
552
|
// 尝试逐个验证 schema,过滤掉有问题的
|
|
534
553
|
const validSchemas = {};
|
|
535
554
|
const invalidSchemas = [];
|
|
536
|
-
const normalizedModuleSchemas = normalizeSchemaRefs(module.schemas);
|
|
555
|
+
const normalizedModuleSchemas = stripNestedSchemaTitles(normalizeSchemaRefs(module.schemas));
|
|
537
556
|
for (const schemaName in normalizedModuleSchemas) {
|
|
538
557
|
try {
|
|
539
558
|
// 尝试单独编译每个 schema
|
|
@@ -644,8 +663,8 @@ const handleBuild = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
644
663
|
if (requestParamsTypeName && isValidTypeIdentifier(requestParamsTypeName) && endpoint.paramsJsdocParams && endpoint.paramsJsdocParams.length > 0) {
|
|
645
664
|
const paramsFields = buildFields(endpoint.paramsJsdocParams);
|
|
646
665
|
if (paramsFields) {
|
|
647
|
-
typeDefinitions[requestParamsTypeName] = `export interface ${requestParamsTypeName} {
|
|
648
|
-
${paramsFields}
|
|
666
|
+
typeDefinitions[requestParamsTypeName] = `export interface ${requestParamsTypeName} {
|
|
667
|
+
${paramsFields}
|
|
649
668
|
}`;
|
|
650
669
|
}
|
|
651
670
|
}
|
|
@@ -654,8 +673,8 @@ ${paramsFields}
|
|
|
654
673
|
if (requestBodyTypeName && isValidTypeIdentifier(requestBodyTypeName) && endpoint.dataJsdocParams && endpoint.dataJsdocParams.length > 0) {
|
|
655
674
|
const dataFields = buildFields(endpoint.dataJsdocParams);
|
|
656
675
|
if (dataFields) {
|
|
657
|
-
typeDefinitions[requestBodyTypeName] = `export interface ${requestBodyTypeName} {
|
|
658
|
-
${dataFields}
|
|
676
|
+
typeDefinitions[requestBodyTypeName] = `export interface ${requestBodyTypeName} {
|
|
677
|
+
${dataFields}
|
|
659
678
|
}`;
|
|
660
679
|
}
|
|
661
680
|
}
|
|
@@ -664,8 +683,8 @@ ${dataFields}
|
|
|
664
683
|
if (responseTargetType && endpoint.responseTypeName !== 'void' && endpoint.responseJsdocParams && endpoint.responseJsdocParams.length > 0) {
|
|
665
684
|
const responseFields = buildFields(endpoint.responseJsdocParams);
|
|
666
685
|
if (responseFields) {
|
|
667
|
-
typeDefinitions[responseTargetType] = `export interface ${responseTargetType} {
|
|
668
|
-
${responseFields}
|
|
686
|
+
typeDefinitions[responseTargetType] = `export interface ${responseTargetType} {
|
|
687
|
+
${responseFields}
|
|
669
688
|
}`;
|
|
670
689
|
}
|
|
671
690
|
}
|
|
@@ -688,8 +707,8 @@ ${responseFields}
|
|
|
688
707
|
typeDefinitions[typeName] = schemaBasedDefinition;
|
|
689
708
|
return;
|
|
690
709
|
}
|
|
691
|
-
typeDefinitions[typeName] = `export interface ${typeName} {
|
|
692
|
-
[key: string]: any;
|
|
710
|
+
typeDefinitions[typeName] = `export interface ${typeName} {
|
|
711
|
+
[key: string]: any;
|
|
693
712
|
}`;
|
|
694
713
|
}
|
|
695
714
|
});
|
package/dist/core/parser.js
CHANGED
|
@@ -148,7 +148,7 @@ function resolveSchemaToTypeScript(schema, allSchemas) {
|
|
|
148
148
|
return `${baseType}${nullable}`;
|
|
149
149
|
}
|
|
150
150
|
function extractJsdocParamsFromSchema(schema, allSchemas) {
|
|
151
|
-
var _a, _b;
|
|
151
|
+
var _a, _b, _c;
|
|
152
152
|
const params = [];
|
|
153
153
|
if (!schema)
|
|
154
154
|
return params;
|
|
@@ -163,9 +163,13 @@ function extractJsdocParamsFromSchema(schema, allSchemas) {
|
|
|
163
163
|
if (targetSchema === null || targetSchema === void 0 ? void 0 : targetSchema.properties) {
|
|
164
164
|
for (const propName in targetSchema.properties) {
|
|
165
165
|
const prop = targetSchema.properties[propName];
|
|
166
|
+
if (!prop) {
|
|
167
|
+
params.push({ name: propName, type: 'any', description: '', required: (_a = targetSchema.required) === null || _a === void 0 ? void 0 : _a.includes(propName) });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
166
170
|
let propType = resolveSchemaToTypeScript(prop, allSchemas);
|
|
167
171
|
const propDescription = isReferenceObject(prop)
|
|
168
|
-
? (((
|
|
172
|
+
? (((_b = allSchemas[getSchemaName(prop.$ref)]) === null || _b === void 0 ? void 0 : _b.description) || '')
|
|
169
173
|
: ((prop === null || prop === void 0 ? void 0 : prop.description) || '');
|
|
170
174
|
// 处理 anyOf 数组 (FastAPI 常用的联合类型)
|
|
171
175
|
if (false && prop.anyOf && Array.isArray(prop.anyOf)) {
|
|
@@ -231,7 +235,7 @@ function extractJsdocParamsFromSchema(schema, allSchemas) {
|
|
|
231
235
|
name: propName,
|
|
232
236
|
type: propType || 'any',
|
|
233
237
|
description: propDescription,
|
|
234
|
-
required: (
|
|
238
|
+
required: (_c = targetSchema.required) === null || _c === void 0 ? void 0 : _c.includes(propName)
|
|
235
239
|
});
|
|
236
240
|
}
|
|
237
241
|
}
|
|
@@ -381,7 +385,8 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
|
|
|
381
385
|
// Collect params for the FormData body type
|
|
382
386
|
if (!formDataSchema.properties)
|
|
383
387
|
formDataSchema.properties = {};
|
|
384
|
-
|
|
388
|
+
const paramSchema = (param.schema || { type: param.type || 'string', format: param.format, description: param.description });
|
|
389
|
+
formDataSchema.properties[param.name] = paramSchema;
|
|
385
390
|
if (param.required) {
|
|
386
391
|
if (!formDataSchema.required)
|
|
387
392
|
formDataSchema.required = [];
|
|
@@ -392,7 +397,8 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
|
|
|
392
397
|
// Always collect path params
|
|
393
398
|
if (!paramsSchema.properties)
|
|
394
399
|
paramsSchema.properties = {};
|
|
395
|
-
|
|
400
|
+
const paramSchema = (param.schema || { type: param.type || 'string', format: param.format, description: param.description });
|
|
401
|
+
paramsSchema.properties[param.name] = paramSchema;
|
|
396
402
|
if (param.required) {
|
|
397
403
|
if (!paramsSchema.required)
|
|
398
404
|
paramsSchema.required = [];
|