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/src/core/parser.ts
CHANGED
|
@@ -111,7 +111,7 @@ function getModuleName(path: string, pathPrefixes: Array<{ path: string; package
|
|
|
111
111
|
return parts[0] || 'default';
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function convertOpenApiTypeToTypeScript(openApiType: string | undefined): string {
|
|
114
|
+
function convertOpenApiTypeToTypeScript(openApiType: string | undefined): string {
|
|
115
115
|
if (!openApiType) return 'any';
|
|
116
116
|
|
|
117
117
|
switch (openApiType) {
|
|
@@ -125,88 +125,88 @@ function convertOpenApiTypeToTypeScript(openApiType: string | undefined): string
|
|
|
125
125
|
return 'boolean';
|
|
126
126
|
case 'string':
|
|
127
127
|
return 'string';
|
|
128
|
-
case 'number':
|
|
129
|
-
return 'number';
|
|
130
|
-
default:
|
|
131
|
-
return openApiType;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function resolveSchemaToTypeScript(
|
|
136
|
-
schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined,
|
|
137
|
-
allSchemas: { [key: string]: any }
|
|
138
|
-
): string {
|
|
139
|
-
if (!schema) return 'any';
|
|
140
|
-
|
|
141
|
-
if (isReferenceObject(schema)) {
|
|
142
|
-
return getSchemaName(schema.$ref) || 'any';
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (schema.anyOf && Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
|
|
146
|
-
const unionTypes = schema.anyOf
|
|
147
|
-
.map(item => resolveSchemaToTypeScript(item as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas))
|
|
148
|
-
.filter(Boolean);
|
|
149
|
-
if (unionTypes.length > 0) {
|
|
150
|
-
return [...new Set(unionTypes)].join(' | ');
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
|
|
155
|
-
const unionTypes = schema.oneOf
|
|
156
|
-
.map(item => resolveSchemaToTypeScript(item as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas))
|
|
157
|
-
.filter(Boolean);
|
|
158
|
-
if (unionTypes.length > 0) {
|
|
159
|
-
return [...new Set(unionTypes)].join(' | ');
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (schema.allOf && Array.isArray(schema.allOf) && schema.allOf.length > 0) {
|
|
164
|
-
const intersectionTypes = schema.allOf
|
|
165
|
-
.map(item => resolveSchemaToTypeScript(item as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas))
|
|
166
|
-
.filter(Boolean);
|
|
167
|
-
if (intersectionTypes.length > 0) {
|
|
168
|
-
return [...new Set(intersectionTypes)].join(' & ');
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (schema.type === 'array') {
|
|
173
|
-
const itemType = resolveSchemaToTypeScript(
|
|
174
|
-
schema.items as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined,
|
|
175
|
-
allSchemas
|
|
176
|
-
);
|
|
177
|
-
return `${itemType || 'any'}[]`;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (schema.type === 'object') {
|
|
181
|
-
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
182
|
-
const requiredSet = new Set(schema.required || []);
|
|
183
|
-
const inlineFields = Object.entries(schema.properties).map(([key, value]) => {
|
|
184
|
-
const fieldType = resolveSchemaToTypeScript(
|
|
185
|
-
value as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
|
|
186
|
-
allSchemas
|
|
187
|
-
);
|
|
188
|
-
const optional = requiredSet.has(key) ? '' : '?';
|
|
189
|
-
return `${key}${optional}: ${fieldType || 'any'}`;
|
|
190
|
-
});
|
|
191
|
-
return `{ ${inlineFields.join('; ')} }`;
|
|
192
|
-
}
|
|
193
|
-
if (schema.additionalProperties) {
|
|
194
|
-
if (schema.additionalProperties === true) {
|
|
195
|
-
return 'Record<string, any>';
|
|
196
|
-
}
|
|
197
|
-
const valueType = resolveSchemaToTypeScript(
|
|
198
|
-
schema.additionalProperties as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
|
|
199
|
-
allSchemas
|
|
200
|
-
);
|
|
201
|
-
return `Record<string, ${valueType || 'any'}>`;
|
|
202
|
-
}
|
|
203
|
-
return 'any';
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const baseType = convertOpenApiTypeToTypeScript(schema.type);
|
|
207
|
-
const nullable = schema.nullable ? ' | null' : '';
|
|
208
|
-
return `${baseType}${nullable}`;
|
|
209
|
-
}
|
|
128
|
+
case 'number':
|
|
129
|
+
return 'number';
|
|
130
|
+
default:
|
|
131
|
+
return openApiType;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function resolveSchemaToTypeScript(
|
|
136
|
+
schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined,
|
|
137
|
+
allSchemas: { [key: string]: any }
|
|
138
|
+
): string {
|
|
139
|
+
if (!schema) return 'any';
|
|
140
|
+
|
|
141
|
+
if (isReferenceObject(schema)) {
|
|
142
|
+
return getSchemaName(schema.$ref) || 'any';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (schema.anyOf && Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
|
|
146
|
+
const unionTypes = schema.anyOf
|
|
147
|
+
.map(item => resolveSchemaToTypeScript(item as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas))
|
|
148
|
+
.filter(Boolean);
|
|
149
|
+
if (unionTypes.length > 0) {
|
|
150
|
+
return [...new Set(unionTypes)].join(' | ');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
|
|
155
|
+
const unionTypes = schema.oneOf
|
|
156
|
+
.map(item => resolveSchemaToTypeScript(item as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas))
|
|
157
|
+
.filter(Boolean);
|
|
158
|
+
if (unionTypes.length > 0) {
|
|
159
|
+
return [...new Set(unionTypes)].join(' | ');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (schema.allOf && Array.isArray(schema.allOf) && schema.allOf.length > 0) {
|
|
164
|
+
const intersectionTypes = schema.allOf
|
|
165
|
+
.map(item => resolveSchemaToTypeScript(item as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas))
|
|
166
|
+
.filter(Boolean);
|
|
167
|
+
if (intersectionTypes.length > 0) {
|
|
168
|
+
return [...new Set(intersectionTypes)].join(' & ');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (schema.type === 'array') {
|
|
173
|
+
const itemType = resolveSchemaToTypeScript(
|
|
174
|
+
schema.items as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined,
|
|
175
|
+
allSchemas
|
|
176
|
+
);
|
|
177
|
+
return `${itemType || 'any'}[]`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (schema.type === 'object') {
|
|
181
|
+
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
182
|
+
const requiredSet = new Set(schema.required || []);
|
|
183
|
+
const inlineFields = Object.entries(schema.properties).map(([key, value]) => {
|
|
184
|
+
const fieldType = resolveSchemaToTypeScript(
|
|
185
|
+
value as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
|
|
186
|
+
allSchemas
|
|
187
|
+
);
|
|
188
|
+
const optional = requiredSet.has(key) ? '' : '?';
|
|
189
|
+
return `${key}${optional}: ${fieldType || 'any'}`;
|
|
190
|
+
});
|
|
191
|
+
return `{ ${inlineFields.join('; ')} }`;
|
|
192
|
+
}
|
|
193
|
+
if (schema.additionalProperties) {
|
|
194
|
+
if (schema.additionalProperties === true) {
|
|
195
|
+
return 'Record<string, any>';
|
|
196
|
+
}
|
|
197
|
+
const valueType = resolveSchemaToTypeScript(
|
|
198
|
+
schema.additionalProperties as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
|
|
199
|
+
allSchemas
|
|
200
|
+
);
|
|
201
|
+
return `Record<string, ${valueType || 'any'}>`;
|
|
202
|
+
}
|
|
203
|
+
return 'any';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const baseType = convertOpenApiTypeToTypeScript(schema.type);
|
|
207
|
+
const nullable = schema.nullable ? ' | null' : '';
|
|
208
|
+
return `${baseType}${nullable}`;
|
|
209
|
+
}
|
|
210
210
|
|
|
211
211
|
function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas: { [key: string]: any }): Required<Endpoint>['jsdocParams'] {
|
|
212
212
|
const params: Required<Endpoint>['jsdocParams'] = [];
|
|
@@ -222,15 +222,19 @@ function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3
|
|
|
222
222
|
|
|
223
223
|
if (targetSchema?.properties) {
|
|
224
224
|
for (const propName in targetSchema.properties) {
|
|
225
|
-
const prop = targetSchema.properties[propName] as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
225
|
+
const prop = targetSchema.properties[propName] as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject;
|
|
226
|
+
if (!prop) {
|
|
227
|
+
params.push({ name: propName, type: 'any', description: '', required: targetSchema.required?.includes(propName) });
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
let propType = resolveSchemaToTypeScript(prop, allSchemas);
|
|
231
|
+
const propDescription = isReferenceObject(prop)
|
|
232
|
+
? ((allSchemas[getSchemaName(prop.$ref)] as OpenAPIV3.SchemaObject | undefined)?.description || '')
|
|
233
|
+
: (prop?.description || '');
|
|
230
234
|
|
|
231
235
|
// 处理 anyOf 数组 (FastAPI 常用的联合类型)
|
|
232
|
-
if (false && (prop as OpenAPIV3.SchemaObject).anyOf && Array.isArray((prop as OpenAPIV3.SchemaObject).anyOf)) {
|
|
233
|
-
const types = (prop as OpenAPIV3.SchemaObject).anyOf!.map(item => {
|
|
236
|
+
if (false && (prop as OpenAPIV3.SchemaObject).anyOf && Array.isArray((prop as OpenAPIV3.SchemaObject).anyOf)) {
|
|
237
|
+
const types = (prop as OpenAPIV3.SchemaObject).anyOf!.map(item => {
|
|
234
238
|
if (isReferenceObject(item)) {
|
|
235
239
|
return getSchemaName(item.$ref);
|
|
236
240
|
} else {
|
|
@@ -251,8 +255,8 @@ function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3
|
|
|
251
255
|
}
|
|
252
256
|
}
|
|
253
257
|
// 处理 oneOf 数组
|
|
254
|
-
else if (false && (prop as OpenAPIV3.SchemaObject).oneOf && Array.isArray((prop as OpenAPIV3.SchemaObject).oneOf)) {
|
|
255
|
-
const types = (prop as OpenAPIV3.SchemaObject).oneOf!.map(item => {
|
|
258
|
+
else if (false && (prop as OpenAPIV3.SchemaObject).oneOf && Array.isArray((prop as OpenAPIV3.SchemaObject).oneOf)) {
|
|
259
|
+
const types = (prop as OpenAPIV3.SchemaObject).oneOf!.map(item => {
|
|
256
260
|
if (isReferenceObject(item)) {
|
|
257
261
|
return getSchemaName(item.$ref);
|
|
258
262
|
} else {
|
|
@@ -273,26 +277,26 @@ function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3
|
|
|
273
277
|
}
|
|
274
278
|
}
|
|
275
279
|
// 处理普通类型
|
|
276
|
-
else if (false && (prop as OpenAPIV3.SchemaObject).type) {
|
|
277
|
-
const propSchema: any = prop as any;
|
|
278
|
-
if (propSchema.type === 'array' && propSchema.items) {
|
|
279
|
-
if (isReferenceObject(propSchema.items)) {
|
|
280
|
-
propType = `${getSchemaName(propSchema.items.$ref)}[]`;
|
|
281
|
-
} else {
|
|
282
|
-
const itemType = convertOpenApiTypeToTypeScript((propSchema.items as OpenAPIV3.SchemaObject).type);
|
|
283
|
-
propType = `${itemType}[]`;
|
|
284
|
-
}
|
|
285
|
-
} else {
|
|
286
|
-
propType = convertOpenApiTypeToTypeScript(propSchema.type);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
params.push({
|
|
291
|
-
name: propName,
|
|
292
|
-
type: propType || 'any',
|
|
293
|
-
description: propDescription,
|
|
294
|
-
required: targetSchema.required?.includes(propName)
|
|
295
|
-
});
|
|
280
|
+
else if (false && (prop as OpenAPIV3.SchemaObject).type) {
|
|
281
|
+
const propSchema: any = prop as any;
|
|
282
|
+
if (propSchema.type === 'array' && propSchema.items) {
|
|
283
|
+
if (isReferenceObject(propSchema.items)) {
|
|
284
|
+
propType = `${getSchemaName(propSchema.items.$ref)}[]`;
|
|
285
|
+
} else {
|
|
286
|
+
const itemType = convertOpenApiTypeToTypeScript((propSchema.items as OpenAPIV3.SchemaObject).type);
|
|
287
|
+
propType = `${itemType}[]`;
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
propType = convertOpenApiTypeToTypeScript(propSchema.type);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
params.push({
|
|
295
|
+
name: propName,
|
|
296
|
+
type: propType || 'any',
|
|
297
|
+
description: propDescription,
|
|
298
|
+
required: targetSchema.required?.includes(propName)
|
|
299
|
+
});
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
302
|
return params;
|
|
@@ -452,7 +456,8 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
|
|
|
452
456
|
} else if (isFormData && (param.in === 'query' || param.in === 'formData')) {
|
|
453
457
|
// Collect params for the FormData body type
|
|
454
458
|
if(!formDataSchema.properties) formDataSchema.properties = {};
|
|
455
|
-
|
|
459
|
+
const paramSchema = (param.schema || { type: (param as any).type || 'string', format: (param as any).format, description: param.description }) as OpenAPIV3.SchemaObject;
|
|
460
|
+
formDataSchema.properties[param.name] = paramSchema;
|
|
456
461
|
if(param.required) {
|
|
457
462
|
if(!formDataSchema.required) formDataSchema.required = [];
|
|
458
463
|
formDataSchema.required.push(param.name);
|
|
@@ -460,7 +465,8 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
|
|
|
460
465
|
} else if (param.in === 'path' || param.in === 'query') {
|
|
461
466
|
// Always collect path params
|
|
462
467
|
if(!paramsSchema.properties) paramsSchema.properties = {};
|
|
463
|
-
|
|
468
|
+
const paramSchema = (param.schema || { type: (param as any).type || 'string', format: (param as any).format, description: param.description }) as OpenAPIV3.SchemaObject;
|
|
469
|
+
paramsSchema.properties[param.name] = paramSchema;
|
|
464
470
|
if(param.required) {
|
|
465
471
|
if(!paramsSchema.required) paramsSchema.required = [];
|
|
466
472
|
paramsSchema.required.push(param.name);
|
|
@@ -558,31 +564,31 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
|
|
|
558
564
|
responseJsdocParams.push(...extractJsdocParamsFromSchema(schema, allSchemas));
|
|
559
565
|
} else if (schema && !isReferenceObject(schema)) {
|
|
560
566
|
const inlineSchema = schema as OpenAPIV3.SchemaObject;
|
|
561
|
-
if (inlineSchema.type === 'object' || inlineSchema.properties) {
|
|
562
|
-
// Generate a named type for inline response schema
|
|
563
|
-
const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Response`;
|
|
564
|
-
responseTypeName = typeName;
|
|
565
|
-
modules[moduleName].schemas[typeName] = inlineSchema;
|
|
566
|
-
referencedTypes.push(typeName);
|
|
567
|
-
responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema, allSchemas));
|
|
568
|
-
} else if (inlineSchema.type === 'array' && inlineSchema.items) {
|
|
569
|
-
if (isReferenceObject(inlineSchema.items)) {
|
|
570
|
-
const itemSchemaName = getSchemaName(inlineSchema.items.$ref);
|
|
571
|
-
// Prefer direct `ItemType[]` for array responses to avoid unnecessary alias schema compilation.
|
|
572
|
-
responseTypeName = `${itemSchemaName}[]`;
|
|
573
|
-
referencedTypes.push(itemSchemaName);
|
|
574
|
-
addSchemaWithDependencies(itemSchemaName, modules[moduleName], allSchemas);
|
|
575
|
-
responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema.items, allSchemas));
|
|
576
|
-
} else {
|
|
577
|
-
const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Response`;
|
|
578
|
-
responseTypeName = typeName;
|
|
579
|
-
modules[moduleName].schemas[typeName] = inlineSchema;
|
|
580
|
-
referencedTypes.push(typeName);
|
|
581
|
-
responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema, allSchemas));
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
567
|
+
if (inlineSchema.type === 'object' || inlineSchema.properties) {
|
|
568
|
+
// Generate a named type for inline response schema
|
|
569
|
+
const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Response`;
|
|
570
|
+
responseTypeName = typeName;
|
|
571
|
+
modules[moduleName].schemas[typeName] = inlineSchema;
|
|
572
|
+
referencedTypes.push(typeName);
|
|
573
|
+
responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema, allSchemas));
|
|
574
|
+
} else if (inlineSchema.type === 'array' && inlineSchema.items) {
|
|
575
|
+
if (isReferenceObject(inlineSchema.items)) {
|
|
576
|
+
const itemSchemaName = getSchemaName(inlineSchema.items.$ref);
|
|
577
|
+
// Prefer direct `ItemType[]` for array responses to avoid unnecessary alias schema compilation.
|
|
578
|
+
responseTypeName = `${itemSchemaName}[]`;
|
|
579
|
+
referencedTypes.push(itemSchemaName);
|
|
580
|
+
addSchemaWithDependencies(itemSchemaName, modules[moduleName], allSchemas);
|
|
581
|
+
responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema.items, allSchemas));
|
|
582
|
+
} else {
|
|
583
|
+
const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Response`;
|
|
584
|
+
responseTypeName = typeName;
|
|
585
|
+
modules[moduleName].schemas[typeName] = inlineSchema;
|
|
586
|
+
referencedTypes.push(typeName);
|
|
587
|
+
responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema, allSchemas));
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
586
592
|
|
|
587
593
|
// Convert path to template literal string for path parameters
|
|
588
594
|
const urlTemplate = path.replace(/\{(\w+)\}/g, '${params.$1}');
|
|
@@ -610,4 +616,4 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
|
|
|
610
616
|
}
|
|
611
617
|
|
|
612
618
|
return modules;
|
|
613
|
-
};
|
|
619
|
+
};
|