czh-api 1.0.3 → 1.0.5

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.
@@ -16,6 +16,11 @@ export interface Endpoint {
16
16
  hasData: boolean;
17
17
  contentType?: string;
18
18
  jsdocParams: Array<{ name: string; type?: string; description?: string; required?: boolean }>;
19
+ // Separate jsdoc params for params and data to avoid merging
20
+ paramsJsdocParams: Array<{ name: string; type?: string; description?: string; required?: boolean }>;
21
+ dataJsdocParams: Array<{ name: string; type?: string; description?: string; required?: boolean }>;
22
+ // Jsdoc params for response type
23
+ responseJsdocParams: Array<{ name: string; type?: string; description?: string; required?: boolean }>;
19
24
  }
20
25
 
21
26
  export interface Module {
@@ -106,7 +111,7 @@ function getModuleName(path: string, pathPrefixes: Array<{ path: string; package
106
111
  return parts[0] || 'default';
107
112
  }
108
113
 
109
- function convertOpenApiTypeToTypeScript(openApiType: string | undefined): string {
114
+ function convertOpenApiTypeToTypeScript(openApiType: string | undefined): string {
110
115
  if (!openApiType) return 'any';
111
116
 
112
117
  switch (openApiType) {
@@ -120,12 +125,88 @@ function convertOpenApiTypeToTypeScript(openApiType: string | undefined): string
120
125
  return 'boolean';
121
126
  case 'string':
122
127
  return 'string';
123
- case 'number':
124
- return 'number';
125
- default:
126
- return 'any';
127
- }
128
- }
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
+ }
129
210
 
130
211
  function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, allSchemas: { [key: string]: any }): Required<Endpoint>['jsdocParams'] {
131
212
  const params: Required<Endpoint>['jsdocParams'] = [];
@@ -141,13 +222,15 @@ function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3
141
222
 
142
223
  if (targetSchema?.properties) {
143
224
  for (const propName in targetSchema.properties) {
144
- const prop = targetSchema.properties[propName] as OpenAPIV3.SchemaObject;
145
-
146
- let propType = 'any';
225
+ const prop = targetSchema.properties[propName] as OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject;
226
+ let propType = resolveSchemaToTypeScript(prop, allSchemas);
227
+ const propDescription = isReferenceObject(prop)
228
+ ? ((allSchemas[getSchemaName(prop.$ref)] as OpenAPIV3.SchemaObject | undefined)?.description || '')
229
+ : (prop?.description || '');
147
230
 
148
231
  // 处理 anyOf 数组 (FastAPI 常用的联合类型)
149
- if (prop.anyOf && Array.isArray(prop.anyOf)) {
150
- const types = prop.anyOf.map(item => {
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 => {
151
234
  if (isReferenceObject(item)) {
152
235
  return getSchemaName(item.$ref);
153
236
  } else {
@@ -168,8 +251,8 @@ function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3
168
251
  }
169
252
  }
170
253
  // 处理 oneOf 数组
171
- else if (prop.oneOf && Array.isArray(prop.oneOf)) {
172
- const types = prop.oneOf.map(item => {
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 => {
173
256
  if (isReferenceObject(item)) {
174
257
  return getSchemaName(item.$ref);
175
258
  } else {
@@ -190,16 +273,26 @@ function extractJsdocParamsFromSchema(schema: OpenAPIV3.SchemaObject | OpenAPIV3
190
273
  }
191
274
  }
192
275
  // 处理普通类型
193
- else if (prop.type) {
194
- propType = convertOpenApiTypeToTypeScript(prop.type);
195
- }
196
-
197
- params.push({
198
- name: propName,
199
- type: propType,
200
- description: prop?.description || '',
201
- required: targetSchema.required?.includes(propName)
202
- });
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
+ });
203
296
  }
204
297
  }
205
298
  return params;
@@ -290,6 +383,9 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
290
383
  let requestBodyTypeName: string | undefined = undefined;
291
384
  let contentType: string | undefined = undefined;
292
385
  const jsdocParams: Required<Endpoint>['jsdocParams'] = [];
386
+ const paramsJsdocParams: Required<Endpoint>['paramsJsdocParams'] = [];
387
+ const dataJsdocParams: Required<Endpoint>['dataJsdocParams'] = [];
388
+ const responseJsdocParams: Required<Endpoint>['responseJsdocParams'] = [];
293
389
 
294
390
  // --- FormData Detection ---
295
391
  let isFormData = false;
@@ -378,14 +474,18 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
378
474
  requestBodyTypeName = typeName;
379
475
  modules[moduleName].schemas[typeName] = formDataSchema;
380
476
  referencedTypes.push(typeName);
381
- jsdocParams.push(...extractJsdocParamsFromSchema(formDataSchema, allSchemas));
477
+ const formDataJsdoc = extractJsdocParamsFromSchema(formDataSchema, allSchemas);
478
+ jsdocParams.push(...formDataJsdoc);
479
+ dataJsdocParams.push(...formDataJsdoc);
382
480
  }
383
481
 
384
482
  if (Object.keys(paramsSchema.properties || {}).length > 0) {
385
483
  requestParamsTypeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Params`;
386
484
  modules[moduleName].schemas[requestParamsTypeName] = paramsSchema;
387
485
  referencedTypes.push(requestParamsTypeName);
388
- jsdocParams.push(...extractJsdocParamsFromSchema(paramsSchema, allSchemas));
486
+ const paramsJsdoc = extractJsdocParamsFromSchema(paramsSchema, allSchemas);
487
+ jsdocParams.push(...paramsJsdoc);
488
+ paramsJsdocParams.push(...paramsJsdoc);
389
489
  }
390
490
  }
391
491
 
@@ -400,7 +500,9 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
400
500
  requestBodyTypeName = name;
401
501
  addSchemaWithDependencies(name, modules[moduleName], allSchemas);
402
502
  referencedTypes.push(name);
403
- jsdocParams.push(...extractJsdocParamsFromSchema(jsonContent.schema, allSchemas));
503
+ const bodyJsdoc = extractJsdocParamsFromSchema(jsonContent.schema, allSchemas);
504
+ jsdocParams.push(...bodyJsdoc);
505
+ dataJsdocParams.push(...bodyJsdoc);
404
506
  } else {
405
507
  // Handle inline schema (including arrays)
406
508
  const schema = jsonContent.schema as OpenAPIV3.SchemaObject;
@@ -416,10 +518,14 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
416
518
  const itemSchemaName = getSchemaName(schema.items.$ref);
417
519
  addSchemaWithDependencies(itemSchemaName, modules[moduleName], allSchemas);
418
520
  } else {
419
- jsdocParams.push(...extractJsdocParamsFromSchema(schema.items as OpenAPIV3.SchemaObject, allSchemas));
521
+ const arrayJsdoc = extractJsdocParamsFromSchema(schema.items as OpenAPIV3.SchemaObject, allSchemas);
522
+ jsdocParams.push(...arrayJsdoc);
523
+ dataJsdocParams.push(...arrayJsdoc);
420
524
  }
421
525
  } else if (schema.type === 'object') {
422
- jsdocParams.push(...extractJsdocParamsFromSchema(schema, allSchemas));
526
+ const objJsdoc = extractJsdocParamsFromSchema(schema, allSchemas);
527
+ jsdocParams.push(...objJsdoc);
528
+ dataJsdocParams.push(...objJsdoc);
423
529
  }
424
530
  }
425
531
  }
@@ -431,8 +537,9 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
431
537
  const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Data`;
432
538
  requestBodyTypeName = typeName;
433
539
  modules[moduleName].schemas[typeName] = formDataContent.schema as OpenAPIV3.SchemaObject;
434
- referencedTypes.push(typeName);
435
- jsdocParams.push(...extractJsdocParamsFromSchema(formDataContent.schema, allSchemas));
540
+ referencedTypes.push(typeName);
541
+ const formJsdoc = extractJsdocParamsFromSchema(formDataContent.schema, allSchemas);
542
+ dataJsdocParams.push(...formJsdoc);
436
543
  }
437
544
  }
438
545
 
@@ -448,8 +555,34 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
448
555
  responseTypeName = name;
449
556
  addSchemaWithDependencies(name, modules[moduleName], allSchemas);
450
557
  referencedTypes.push(name);
451
- }
452
- }
558
+ responseJsdocParams.push(...extractJsdocParamsFromSchema(schema, allSchemas));
559
+ } else if (schema && !isReferenceObject(schema)) {
560
+ 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
+ }
453
586
 
454
587
  // Convert path to template literal string for path parameters
455
588
  const urlTemplate = path.replace(/\{(\w+)\}/g, '${params.$1}');
@@ -467,6 +600,9 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
467
600
  hasData: !!requestBodyTypeName,
468
601
  contentType,
469
602
  jsdocParams,
603
+ paramsJsdocParams,
604
+ dataJsdocParams,
605
+ responseJsdocParams,
470
606
  };
471
607
 
472
608
  modules[moduleName].endpoints.push(endpoint);
@@ -474,4 +610,4 @@ export const processApi = (api: OpenAPI.Document, excludePaths: string[] = [], i
474
610
  }
475
611
 
476
612
  return modules;
477
- };
613
+ };
@@ -10,12 +10,7 @@ export const {{functionName}} = ({{#if hasParams}}params: {{requestParamsTypeNam
10
10
  return http.request<{{responseTypeName}}>({
11
11
  url: `{{path}}`,
12
12
  method: '{{method}}',
13
- {{#if hasParams}}
14
- params,
15
- {{/if}}
16
- {{#if hasData}}
17
- data,
18
- {{/if}}
13
+ {{#if hasParams}}{{#unless (eq method 'put')}}{{#unless (eq method 'post')}}params,{{/unless}}{{/unless}}{{/if}}{{#if hasData}}data,{{/if}}
19
14
  {{#if contentType}}
20
15
  headers: { 'Content-Type': '{{contentType}}' },
21
16
  {{/if}}