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.
@@ -87,11 +87,68 @@ function convertOpenApiTypeToTypeScript(openApiType) {
87
87
  case 'number':
88
88
  return 'number';
89
89
  default:
90
- return 'any';
90
+ return openApiType;
91
91
  }
92
92
  }
93
+ function resolveSchemaToTypeScript(schema, allSchemas) {
94
+ if (!schema)
95
+ return 'any';
96
+ if (isReferenceObject(schema)) {
97
+ return getSchemaName(schema.$ref) || 'any';
98
+ }
99
+ if (schema.anyOf && Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
100
+ const unionTypes = schema.anyOf
101
+ .map(item => resolveSchemaToTypeScript(item, allSchemas))
102
+ .filter(Boolean);
103
+ if (unionTypes.length > 0) {
104
+ return [...new Set(unionTypes)].join(' | ');
105
+ }
106
+ }
107
+ if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
108
+ const unionTypes = schema.oneOf
109
+ .map(item => resolveSchemaToTypeScript(item, allSchemas))
110
+ .filter(Boolean);
111
+ if (unionTypes.length > 0) {
112
+ return [...new Set(unionTypes)].join(' | ');
113
+ }
114
+ }
115
+ if (schema.allOf && Array.isArray(schema.allOf) && schema.allOf.length > 0) {
116
+ const intersectionTypes = schema.allOf
117
+ .map(item => resolveSchemaToTypeScript(item, allSchemas))
118
+ .filter(Boolean);
119
+ if (intersectionTypes.length > 0) {
120
+ return [...new Set(intersectionTypes)].join(' & ');
121
+ }
122
+ }
123
+ if (schema.type === 'array') {
124
+ const itemType = resolveSchemaToTypeScript(schema.items, allSchemas);
125
+ return `${itemType || 'any'}[]`;
126
+ }
127
+ if (schema.type === 'object') {
128
+ if (schema.properties && Object.keys(schema.properties).length > 0) {
129
+ const requiredSet = new Set(schema.required || []);
130
+ const inlineFields = Object.entries(schema.properties).map(([key, value]) => {
131
+ const fieldType = resolveSchemaToTypeScript(value, allSchemas);
132
+ const optional = requiredSet.has(key) ? '' : '?';
133
+ return `${key}${optional}: ${fieldType || 'any'}`;
134
+ });
135
+ return `{ ${inlineFields.join('; ')} }`;
136
+ }
137
+ if (schema.additionalProperties) {
138
+ if (schema.additionalProperties === true) {
139
+ return 'Record<string, any>';
140
+ }
141
+ const valueType = resolveSchemaToTypeScript(schema.additionalProperties, allSchemas);
142
+ return `Record<string, ${valueType || 'any'}>`;
143
+ }
144
+ return 'any';
145
+ }
146
+ const baseType = convertOpenApiTypeToTypeScript(schema.type);
147
+ const nullable = schema.nullable ? ' | null' : '';
148
+ return `${baseType}${nullable}`;
149
+ }
93
150
  function extractJsdocParamsFromSchema(schema, allSchemas) {
94
- var _a;
151
+ var _a, _b;
95
152
  const params = [];
96
153
  if (!schema)
97
154
  return params;
@@ -106,9 +163,12 @@ function extractJsdocParamsFromSchema(schema, allSchemas) {
106
163
  if (targetSchema === null || targetSchema === void 0 ? void 0 : targetSchema.properties) {
107
164
  for (const propName in targetSchema.properties) {
108
165
  const prop = targetSchema.properties[propName];
109
- let propType = 'any';
166
+ let propType = resolveSchemaToTypeScript(prop, allSchemas);
167
+ const propDescription = isReferenceObject(prop)
168
+ ? (((_a = allSchemas[getSchemaName(prop.$ref)]) === null || _a === void 0 ? void 0 : _a.description) || '')
169
+ : ((prop === null || prop === void 0 ? void 0 : prop.description) || '');
110
170
  // 处理 anyOf 数组 (FastAPI 常用的联合类型)
111
- if (prop.anyOf && Array.isArray(prop.anyOf)) {
171
+ if (false && prop.anyOf && Array.isArray(prop.anyOf)) {
112
172
  const types = prop.anyOf.map(item => {
113
173
  if (isReferenceObject(item)) {
114
174
  return getSchemaName(item.$ref);
@@ -130,7 +190,7 @@ function extractJsdocParamsFromSchema(schema, allSchemas) {
130
190
  }
131
191
  }
132
192
  // 处理 oneOf 数组
133
- else if (prop.oneOf && Array.isArray(prop.oneOf)) {
193
+ else if (false && prop.oneOf && Array.isArray(prop.oneOf)) {
134
194
  const types = prop.oneOf.map(item => {
135
195
  if (isReferenceObject(item)) {
136
196
  return getSchemaName(item.$ref);
@@ -152,14 +212,26 @@ function extractJsdocParamsFromSchema(schema, allSchemas) {
152
212
  }
153
213
  }
154
214
  // 处理普通类型
155
- else if (prop.type) {
156
- propType = convertOpenApiTypeToTypeScript(prop.type);
215
+ else if (false && prop.type) {
216
+ const propSchema = prop;
217
+ if (propSchema.type === 'array' && propSchema.items) {
218
+ if (isReferenceObject(propSchema.items)) {
219
+ propType = `${getSchemaName(propSchema.items.$ref)}[]`;
220
+ }
221
+ else {
222
+ const itemType = convertOpenApiTypeToTypeScript(propSchema.items.type);
223
+ propType = `${itemType}[]`;
224
+ }
225
+ }
226
+ else {
227
+ propType = convertOpenApiTypeToTypeScript(propSchema.type);
228
+ }
157
229
  }
158
230
  params.push({
159
231
  name: propName,
160
- type: propType,
161
- description: (prop === null || prop === void 0 ? void 0 : prop.description) || '',
162
- required: (_a = targetSchema.required) === null || _a === void 0 ? void 0 : _a.includes(propName)
232
+ type: propType || 'any',
233
+ description: propDescription,
234
+ required: (_b = targetSchema.required) === null || _b === void 0 ? void 0 : _b.includes(propName)
163
235
  });
164
236
  }
165
237
  }
@@ -238,6 +310,9 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
238
310
  let requestBodyTypeName = undefined;
239
311
  let contentType = undefined;
240
312
  const jsdocParams = [];
313
+ const paramsJsdocParams = [];
314
+ const dataJsdocParams = [];
315
+ const responseJsdocParams = [];
241
316
  // --- FormData Detection ---
242
317
  let isFormData = false;
243
318
  // Method 1: Check requestBody
@@ -331,13 +406,17 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
331
406
  requestBodyTypeName = typeName;
332
407
  modules[moduleName].schemas[typeName] = formDataSchema;
333
408
  referencedTypes.push(typeName);
334
- jsdocParams.push(...extractJsdocParamsFromSchema(formDataSchema, allSchemas));
409
+ const formDataJsdoc = extractJsdocParamsFromSchema(formDataSchema, allSchemas);
410
+ jsdocParams.push(...formDataJsdoc);
411
+ dataJsdocParams.push(...formDataJsdoc);
335
412
  }
336
413
  if (Object.keys(paramsSchema.properties || {}).length > 0) {
337
414
  requestParamsTypeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Params`;
338
415
  modules[moduleName].schemas[requestParamsTypeName] = paramsSchema;
339
416
  referencedTypes.push(requestParamsTypeName);
340
- jsdocParams.push(...extractJsdocParamsFromSchema(paramsSchema, allSchemas));
417
+ const paramsJsdoc = extractJsdocParamsFromSchema(paramsSchema, allSchemas);
418
+ jsdocParams.push(...paramsJsdoc);
419
+ paramsJsdocParams.push(...paramsJsdoc);
341
420
  }
342
421
  }
343
422
  // Handle standard Request Body
@@ -350,7 +429,9 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
350
429
  requestBodyTypeName = name;
351
430
  addSchemaWithDependencies(name, modules[moduleName], allSchemas);
352
431
  referencedTypes.push(name);
353
- jsdocParams.push(...extractJsdocParamsFromSchema(jsonContent.schema, allSchemas));
432
+ const bodyJsdoc = extractJsdocParamsFromSchema(jsonContent.schema, allSchemas);
433
+ jsdocParams.push(...bodyJsdoc);
434
+ dataJsdocParams.push(...bodyJsdoc);
354
435
  }
355
436
  else {
356
437
  // Handle inline schema (including arrays)
@@ -367,11 +448,15 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
367
448
  addSchemaWithDependencies(itemSchemaName, modules[moduleName], allSchemas);
368
449
  }
369
450
  else {
370
- jsdocParams.push(...extractJsdocParamsFromSchema(schema.items, allSchemas));
451
+ const arrayJsdoc = extractJsdocParamsFromSchema(schema.items, allSchemas);
452
+ jsdocParams.push(...arrayJsdoc);
453
+ dataJsdocParams.push(...arrayJsdoc);
371
454
  }
372
455
  }
373
456
  else if (schema.type === 'object') {
374
- jsdocParams.push(...extractJsdocParamsFromSchema(schema, allSchemas));
457
+ const objJsdoc = extractJsdocParamsFromSchema(schema, allSchemas);
458
+ jsdocParams.push(...objJsdoc);
459
+ dataJsdocParams.push(...objJsdoc);
375
460
  }
376
461
  }
377
462
  }
@@ -385,7 +470,8 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
385
470
  requestBodyTypeName = typeName;
386
471
  modules[moduleName].schemas[typeName] = formDataContent.schema;
387
472
  referencedTypes.push(typeName);
388
- jsdocParams.push(...extractJsdocParamsFromSchema(formDataContent.schema, allSchemas));
473
+ const formJsdoc = extractJsdocParamsFromSchema(formDataContent.schema, allSchemas);
474
+ dataJsdocParams.push(...formJsdoc);
389
475
  }
390
476
  }
391
477
  // Handle Response Body
@@ -399,6 +485,35 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
399
485
  responseTypeName = name;
400
486
  addSchemaWithDependencies(name, modules[moduleName], allSchemas);
401
487
  referencedTypes.push(name);
488
+ responseJsdocParams.push(...extractJsdocParamsFromSchema(schema, allSchemas));
489
+ }
490
+ else if (schema && !isReferenceObject(schema)) {
491
+ const inlineSchema = schema;
492
+ if (inlineSchema.type === 'object' || inlineSchema.properties) {
493
+ // Generate a named type for inline response schema
494
+ const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Response`;
495
+ responseTypeName = typeName;
496
+ modules[moduleName].schemas[typeName] = inlineSchema;
497
+ referencedTypes.push(typeName);
498
+ responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema, allSchemas));
499
+ }
500
+ else if (inlineSchema.type === 'array' && inlineSchema.items) {
501
+ if (isReferenceObject(inlineSchema.items)) {
502
+ const itemSchemaName = getSchemaName(inlineSchema.items.$ref);
503
+ // Prefer direct `ItemType[]` for array responses to avoid unnecessary alias schema compilation.
504
+ responseTypeName = `${itemSchemaName}[]`;
505
+ referencedTypes.push(itemSchemaName);
506
+ addSchemaWithDependencies(itemSchemaName, modules[moduleName], allSchemas);
507
+ responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema.items, allSchemas));
508
+ }
509
+ else {
510
+ const typeName = `${functionName.charAt(0).toUpperCase() + functionName.slice(1)}Response`;
511
+ responseTypeName = typeName;
512
+ modules[moduleName].schemas[typeName] = inlineSchema;
513
+ referencedTypes.push(typeName);
514
+ responseJsdocParams.push(...extractJsdocParamsFromSchema(inlineSchema, allSchemas));
515
+ }
516
+ }
402
517
  }
403
518
  }
404
519
  // Convert path to template literal string for path parameters
@@ -416,6 +531,9 @@ const processApi = (api, excludePaths = [], includePaths = [], pathPrefixes = []
416
531
  hasData: !!requestBodyTypeName,
417
532
  contentType,
418
533
  jsdocParams,
534
+ paramsJsdocParams,
535
+ dataJsdocParams,
536
+ responseJsdocParams,
419
537
  };
420
538
  modules[moduleName].endpoints.push(endpoint);
421
539
  }
@@ -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}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "czh-api",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A CLI tool to generate TypeScript API clients from Swagger/OpenAPI documents.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {