@acrool/rtk-query-codegen-openapi 0.0.2 → 0.0.6

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/src/generate.ts CHANGED
@@ -38,8 +38,8 @@ function defaultIsDataResponse(code: string, includeDefault: boolean) {
38
38
  return !Number.isNaN(parsedCode) && parsedCode >= 200 && parsedCode < 300;
39
39
  }
40
40
 
41
- function getOperationName({ verb, path, operation }: Pick<OperationDefinition, 'verb' | 'path' | 'operation'>) {
42
- return _getOperationName(verb, path, operation.operationId);
41
+ function getOperationName({ verb, path }: Pick<OperationDefinition, 'verb' | 'path' >) {
42
+ return _getOperationName(verb, path, undefined);
43
43
  }
44
44
 
45
45
  function getTags({ verb, pathItem }: Pick<OperationDefinition, 'verb' | 'pathItem'>): string[] {
@@ -128,49 +128,176 @@ export async function generateApi(
128
128
  mergeReadWriteOnly,
129
129
  });
130
130
 
131
- // 如果提供了 sharedTypesFile,則將 components 輸出到該文件
131
+ const schemeTypeNames = new Set<string>();
132
+
133
+ function addSchemeTypeName(name: string) {
134
+ schemeTypeNames.add(name);
135
+ schemeTypeNames.add(camelCase(name));
136
+ schemeTypeNames.add(capitalize(camelCase(name)));
137
+ }
138
+
132
139
  if (sharedTypesFile) {
140
+ const resultFile = ts.createSourceFile(
141
+ 'sharedTypes.ts',
142
+ '',
143
+ ts.ScriptTarget.Latest,
144
+ /*setParentNodes*/ false,
145
+ ts.ScriptKind.TS
146
+ );
147
+ const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
148
+
149
+ const allTypeDefinitions: ts.Statement[] = [];
150
+ const definedTypeNames = new Set<string>();
151
+
133
152
  const components = v3Doc.components;
134
153
  if (components) {
135
- const resultFile = ts.createSourceFile(
136
- 'sharedTypes.ts',
137
- '',
138
- ts.ScriptTarget.Latest,
139
- /*setParentNodes*/ false,
140
- ts.ScriptKind.TS
141
- );
142
- const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
154
+ const componentDefinitions = Object.entries(components).map(([componentType, componentDefs]) => {
155
+ const typeEntries = Object.entries(componentDefs as Record<string, unknown>)
156
+ .map(([name, def]) => {
157
+ addSchemeTypeName(name);
158
+ const typeName = capitalize(camelCase(name));
159
+ definedTypeNames.add(typeName);
160
+ const typeNode = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(def as OpenAPIV3.SchemaObject));
161
+ return factory.createTypeAliasDeclaration(
162
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
163
+ factory.createIdentifier(typeName),
164
+ undefined,
165
+ typeNode
166
+ );
167
+ });
168
+ return factory.createModuleDeclaration(
169
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
170
+ factory.createIdentifier('Scheme'),
171
+ factory.createModuleBlock(typeEntries),
172
+ ts.NodeFlags.Namespace
173
+ );
174
+ });
175
+ allTypeDefinitions.push(...componentDefinitions);
176
+ }
143
177
 
144
- // components 轉換為 TypeScript 類型定義
145
- const typeDefinitions = Object.entries(components).flatMap(([_, componentDefs]) => {
146
- return Object.entries(componentDefs as Record<string, unknown>).map(([name, def]) => {
147
- const typeNode = apiGen.getTypeFromSchema(def as OpenAPIV3.SchemaObject);
178
+ const enumEntries = [
179
+ ...apiGen.enumAliases.filter(e => ts.isEnumDeclaration(e)),
180
+ ...apiGen.enumAliases.filter(e => ts.isTypeAliasDeclaration(e)),
181
+ ].map(enumDecl => {
182
+ if (ts.isEnumDeclaration(enumDecl)) {
183
+ return factory.createEnumDeclaration(
184
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
185
+ enumDecl.name,
186
+ enumDecl.members
187
+ );
188
+ } else if (ts.isTypeAliasDeclaration(enumDecl)) {
189
+ return factory.createTypeAliasDeclaration(
190
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
191
+ enumDecl.name,
192
+ enumDecl.typeParameters,
193
+ enumDecl.type
194
+ );
195
+ }
196
+ return enumDecl;
197
+ });
198
+
199
+ const unionTypeEnums = apiGen.aliases
200
+ .filter(alias => {
201
+ if (ts.isTypeAliasDeclaration(alias) && alias.type) {
202
+ return ts.isUnionTypeNode(alias.type);
203
+ }
204
+ return false;
205
+ })
206
+ .map(alias => {
207
+ if (ts.isTypeAliasDeclaration(alias)) {
148
208
  return factory.createTypeAliasDeclaration(
149
209
  [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
150
- factory.createIdentifier(name),
151
- undefined,
152
- typeNode
210
+ alias.name,
211
+ alias.typeParameters,
212
+ alias.type
153
213
  );
154
- });
214
+ }
215
+ return alias;
155
216
  });
156
-
157
- const output = printer.printNode(
158
- ts.EmitHint.Unspecified,
159
- factory.createSourceFile(
160
- typeDefinitions,
161
- factory.createToken(ts.SyntaxKind.EndOfFileToken),
162
- ts.NodeFlags.None
163
- ),
164
- resultFile
217
+
218
+ const allEnumEntries = [...enumEntries, ...unionTypeEnums];
219
+
220
+ if (allEnumEntries.length > 0) {
221
+ allTypeDefinitions.push(
222
+ factory.createModuleDeclaration(
223
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
224
+ factory.createIdentifier('Enum'),
225
+ factory.createModuleBlock(allEnumEntries),
226
+ ts.NodeFlags.Namespace
227
+ )
165
228
  );
229
+ }
230
+
231
+ if (apiGen.aliases.length > 0) {
232
+ const aliasEntries = apiGen.aliases
233
+ .filter(alias => {
234
+ if (ts.isTypeAliasDeclaration(alias)) {
235
+ const isDefinedInComponents = definedTypeNames.has(alias.name.text);
236
+ const isUnionTypeEnum = ts.isUnionTypeNode(alias.type);
237
+ return !isDefinedInComponents && !isUnionTypeEnum;
238
+ }
239
+ return false;
240
+ })
241
+ .map(alias => {
242
+ if (ts.isTypeAliasDeclaration(alias)) {
243
+ return factory.createTypeAliasDeclaration(
244
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
245
+ alias.name,
246
+ alias.typeParameters,
247
+ alias.type
248
+ );
249
+ }
250
+ return alias;
251
+ });
166
252
 
167
- // 寫入文件
168
- const fs = await import('node:fs/promises');
169
- await fs.writeFile(sharedTypesFile, output, 'utf-8');
253
+ if (aliasEntries.length > 0) {
254
+ const existingSchemeIndex = allTypeDefinitions.findIndex(def =>
255
+ ts.isModuleDeclaration(def) &&
256
+ ts.isIdentifier(def.name) &&
257
+ def.name.text === 'Scheme'
258
+ );
259
+
260
+ if (existingSchemeIndex >= 0) {
261
+ const existingScheme = allTypeDefinitions[existingSchemeIndex] as ts.ModuleDeclaration;
262
+ const mergedMembers = [...(existingScheme.body as ts.ModuleBlock).statements, ...aliasEntries];
263
+ allTypeDefinitions[existingSchemeIndex] = factory.createModuleDeclaration(
264
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
265
+ factory.createIdentifier('Scheme'),
266
+ factory.createModuleBlock(mergedMembers),
267
+ ts.NodeFlags.Namespace
268
+ );
269
+ } else {
270
+ allTypeDefinitions.push(
271
+ factory.createModuleDeclaration(
272
+ [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
273
+ factory.createIdentifier('Scheme'),
274
+ factory.createModuleBlock(aliasEntries),
275
+ ts.NodeFlags.Namespace
276
+ )
277
+ );
278
+ }
279
+ }
170
280
  }
281
+
282
+ const fs = await import('node:fs/promises');
283
+ const path = await import('node:path');
284
+
285
+ const sharedTypesDir = path.dirname(sharedTypesFile);
286
+ await fs.mkdir(sharedTypesDir, { recursive: true });
287
+
288
+ const output = printer.printNode(
289
+ ts.EmitHint.Unspecified,
290
+ factory.createSourceFile(
291
+ allTypeDefinitions,
292
+ factory.createToken(ts.SyntaxKind.EndOfFileToken),
293
+ ts.NodeFlags.None
294
+ ),
295
+ resultFile
296
+ );
297
+
298
+ await fs.writeFile(sharedTypesFile, output, 'utf-8');
171
299
  }
172
300
 
173
- // temporary workaround for https://github.com/oazapfts/oazapfts/issues/491
174
301
  if (apiGen.spec.components?.schemas) {
175
302
  apiGen.preprocessComponents(apiGen.spec.components.schemas);
176
303
  }
@@ -203,17 +330,18 @@ export async function generateApi(
203
330
  apiFile = apiFile.replace(/\\/g, '/');
204
331
  if (!apiFile.startsWith('.')) apiFile = `./${apiFile}`;
205
332
  }
206
- // 處理 sharedTypesFile 的路徑
207
- if (sharedTypesFile && sharedTypesFile.startsWith('.')) {
208
- sharedTypesFile = path.relative(path.dirname(outputFile), sharedTypesFile);
209
- sharedTypesFile = sharedTypesFile.replace(/\\/g, '/');
210
- if (!sharedTypesFile.startsWith('.')) sharedTypesFile = `./${sharedTypesFile}`;
211
- }
212
333
  }
213
334
  apiFile = apiFile.replace(/\.[jt]sx?$/, '');
214
- if (sharedTypesFile) {
215
- sharedTypesFile = sharedTypesFile.replace(/\.[jt]sx?$/, '');
216
- }
335
+
336
+ const sharedTypesImportPath = sharedTypesFile && outputFile
337
+ ? (() => {
338
+ let rel = path.relative(path.dirname(outputFile), sharedTypesFile)
339
+ .replace(/\\/g, '/')
340
+ .replace(/\.[jt]sx?$/, '');
341
+ if (!rel.startsWith('.')) rel = './' + rel;
342
+ return rel;
343
+ })()
344
+ : './shared-types';
217
345
 
218
346
  return printer.printNode(
219
347
  ts.EmitHint.Unspecified,
@@ -222,16 +350,10 @@ export async function generateApi(
222
350
  generateImportNode(apiFile, { [apiImport]: 'api' }),
223
351
  generateImportNode('@acrool/react-fetcher', { IRestFulEndpointsQueryReturn: 'IRestFulEndpointsQueryReturn' }),
224
352
  ...(sharedTypesFile ? [
225
- factory.createImportDeclaration(
226
- undefined,
227
- factory.createImportClause(
228
- false,
229
- undefined,
230
- factory.createNamespaceImport(factory.createIdentifier('SharedTypes'))
231
- ),
232
- factory.createStringLiteral(sharedTypesFile),
233
- undefined
234
- )
353
+ generateImportNode(sharedTypesImportPath, {
354
+ Scheme: 'Scheme',
355
+ ...(useEnumType ? { Enum: 'Enum' } : {})
356
+ })
235
357
  ] : []),
236
358
  ...(tag ? [generateTagTypes({ addTagTypes: extractAllTagTypes({ operationDefinitions }) })] : []),
237
359
  generateCreateApiCall({
@@ -241,6 +363,7 @@ export async function generateApi(
241
363
  generateEndpoint({
242
364
  operationDefinition,
243
365
  overrides: getOverrides(operationDefinition, endpointOverrides),
366
+ sharedTypesFile: !!sharedTypesFile,
244
367
  })
245
368
  ),
246
369
  true
@@ -285,9 +408,11 @@ export async function generateApi(
285
408
  function generateEndpoint({
286
409
  operationDefinition,
287
410
  overrides,
411
+ sharedTypesFile,
288
412
  }: {
289
413
  operationDefinition: OperationDefinition;
290
414
  overrides?: EndpointOverrides;
415
+ sharedTypesFile: boolean;
291
416
  }) {
292
417
  const {
293
418
  verb,
@@ -296,73 +421,37 @@ export async function generateApi(
296
421
  operation,
297
422
  operation: { responses, requestBody },
298
423
  } = operationDefinition;
299
- const operationName = getOperationName({ verb, path, operation });
424
+ const operationName = getOperationName({ verb, path });
300
425
  const tags = tag ? getTags({ verb, pathItem }) : [];
301
426
  const isQuery = testIsQuery(verb, overrides);
302
427
 
303
428
  const returnsJson = apiGen.getResponseType(responses) === 'json';
304
429
  let ResponseType: ts.TypeNode = factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
305
-
306
- function replaceReferences(schema: any): ts.TypeNode {
307
- if (!schema) return factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
308
-
309
- const refName = getReferenceName(schema);
310
- if (refName && sharedTypesFile) {
311
- return factory.createTypeReferenceNode(
312
- factory.createQualifiedName(
313
- factory.createIdentifier('SharedTypes'),
314
- factory.createIdentifier(refName)
315
- ),
316
- undefined
317
- );
318
- }
319
-
320
- if (schema.type === 'object' && schema.properties) {
321
- const members = Object.entries(schema.properties).map(([key, value]: [string, any]) => {
322
- return factory.createPropertySignature(
323
- undefined,
324
- factory.createIdentifier(key),
325
- schema.required?.includes(key) ? undefined : factory.createToken(ts.SyntaxKind.QuestionToken),
326
- replaceReferences(value)
327
- );
328
- });
329
- return factory.createTypeLiteralNode(members);
330
- }
331
-
332
- if (schema.type === 'array' && schema.items) {
333
- return factory.createArrayTypeNode(replaceReferences(schema.items));
334
- }
335
-
336
- return apiGen.getTypeFromSchema(schema);
337
- }
338
-
339
430
  if (returnsJson) {
340
431
  const returnTypes = Object.entries(responses || {})
341
432
  .map(
342
- ([code, response]) => {
343
- const resolvedResponse = apiGen.resolve(response);
344
- if (!resolvedResponse.content?.['application/json']?.schema) {
345
- return [code, resolvedResponse, factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)] as const;
346
- }
347
-
348
- const schema = resolvedResponse.content['application/json'].schema;
349
- const type = replaceReferences(schema);
350
-
351
- return [code, resolvedResponse, type] as const;
352
- }
433
+ ([code, response]) =>
434
+ [
435
+ code,
436
+ apiGen.resolve(response),
437
+ wrapWithSchemeIfComponent(
438
+ apiGen.getTypeFromResponse(response, 'readOnly') ||
439
+ factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
440
+ ),
441
+ ] as const
353
442
  )
354
443
  .filter(([status, response]) =>
355
444
  isDataResponse(status, includeDefault, apiGen.resolve(response), responses || {})
356
445
  )
357
446
  .filter(([_1, _2, type]) => type !== keywordType.void)
358
- .map(([code, response, type]) =>
359
- ts.addSyntheticLeadingComment(
360
- { ...type },
447
+ .map(([code, response, type]) => {
448
+ return ts.addSyntheticLeadingComment(
449
+ type,
361
450
  ts.SyntaxKind.MultiLineCommentTrivia,
362
451
  `* status ${code} ${response.description} `,
363
452
  false
364
- )
365
- );
453
+ );
454
+ });
366
455
  if (returnTypes.length > 0) {
367
456
  ResponseType = factory.createUnionTypeNode(returnTypes);
368
457
  }
@@ -392,28 +481,36 @@ export async function generateApi(
392
481
  const queryArg: QueryArgDefinitions = {};
393
482
  function generateName(name: string, potentialPrefix: string) {
394
483
  const isPureSnakeCase = /^[a-zA-Z][a-zA-Z0-9_]*$/.test(name);
395
- // prefix with `query`, `path` or `body` if there are multiple paramters with the same name
396
484
  const hasNamingConflict = allNames.filter((n) => n === name).length > 1;
397
485
  if (hasNamingConflict) {
398
486
  name = `${potentialPrefix}_${name}`;
399
487
  }
400
- // convert to camelCase if the name is pure snake_case and there are no naming conflicts
401
488
  const camelCaseName = camelCase(name);
402
489
  if (isPureSnakeCase && !allNames.includes(camelCaseName)) {
403
490
  name = camelCaseName;
404
491
  }
405
- // if there are still any naming conflicts, prepend with underscore
406
492
  while (name in queryArg) {
407
493
  name = `_${name}`;
408
494
  }
409
495
  return name;
410
496
  }
411
497
 
498
+ for (const param of parameters) {
499
+ const name = generateName(param.name, param.in);
500
+ queryArg[name] = {
501
+ origin: 'param',
502
+ name,
503
+ originalName: param.name,
504
+ type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, undefined, 'writeOnly')),
505
+ required: param.required,
506
+ param,
507
+ };
508
+ }
509
+
412
510
  if (requestBody) {
413
511
  const body = apiGen.resolve(requestBody);
414
512
  const schema = apiGen.getSchemaFromContent(body.content);
415
- const type = replaceReferences(schema);
416
-
513
+ const type = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema));
417
514
  const schemaName = camelCase(
418
515
  (type as any).name ||
419
516
  getReferenceName(schema) ||
@@ -426,27 +523,12 @@ export async function generateApi(
426
523
  origin: 'body',
427
524
  name,
428
525
  originalName: schemaName,
429
- type,
526
+ type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema, undefined, 'writeOnly')),
430
527
  required: true,
431
528
  body,
432
529
  };
433
530
  }
434
531
 
435
- for (const param of parameters) {
436
- const name = generateName(param.name, param.in);
437
- const paramSchema = isReference(param) ? param : param.schema;
438
- const type = replaceReferences(paramSchema);
439
-
440
- queryArg[name] = {
441
- origin: 'param',
442
- name,
443
- originalName: param.name,
444
- type,
445
- required: param.required,
446
- param,
447
- };
448
- }
449
-
450
532
  const propertyName = (name: string | ts.PropertyName): ts.PropertyName => {
451
533
  if (typeof name === 'string') {
452
534
  return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
@@ -617,14 +699,132 @@ export async function generateApi(
617
699
  );
618
700
  }
619
701
 
620
- // eslint-disable-next-line no-empty-pattern
621
702
  function generateQueryEndpointProps({}: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions {
622
- return {}; /* TODO needs implementation - skip for now */
703
+ return {};
623
704
  }
624
705
 
625
- // eslint-disable-next-line no-empty-pattern
626
706
  function generateMutationEndpointProps({}: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions {
627
- return {}; /* TODO needs implementation - skip for now */
707
+ return {};
708
+ }
709
+
710
+ function wrapWithSchemeIfComponent(typeNode: ts.TypeNode): ts.TypeNode {
711
+ if (ts.isTypeReferenceNode(typeNode) && ts.isIdentifier(typeNode.typeName)) {
712
+ const typeName = typeNode.typeName.text;
713
+
714
+ // 檢查是否為 enum 類型(包括在 enumAliases 和 aliases 中的)
715
+ const isEnumType = useEnumType && (
716
+ apiGen.enumAliases.some(enumDecl => {
717
+ if (ts.isEnumDeclaration(enumDecl) || ts.isTypeAliasDeclaration(enumDecl)) {
718
+ return enumDecl.name.text === typeName;
719
+ }
720
+ return false;
721
+ }) ||
722
+ apiGen.aliases.some(alias => {
723
+ if (ts.isTypeAliasDeclaration(alias) && alias.type) {
724
+ // 檢查是否為 union type 的 enum
725
+ if (ts.isUnionTypeNode(alias.type)) {
726
+ return alias.name.text === typeName;
727
+ }
728
+ }
729
+ return false;
730
+ })
731
+ );
732
+
733
+ if (isEnumType) {
734
+ return factory.createTypeReferenceNode(
735
+ factory.createQualifiedName(
736
+ factory.createIdentifier('Enum'),
737
+ typeNode.typeName
738
+ ),
739
+ typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
740
+ );
741
+ }
742
+
743
+ if (schemeTypeNames.has(typeName)) {
744
+ return factory.createTypeReferenceNode(
745
+ factory.createQualifiedName(
746
+ factory.createIdentifier('Scheme'),
747
+ typeNode.typeName
748
+ ),
749
+ typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
750
+ );
751
+ }
752
+ if (typeNode.typeArguments) {
753
+ return factory.createTypeReferenceNode(
754
+ typeNode.typeName,
755
+ typeNode.typeArguments.map(wrapWithSchemeIfComponent)
756
+ );
757
+ }
758
+ }
759
+ if (ts.isArrayTypeNode(typeNode)) {
760
+ return factory.createArrayTypeNode(wrapWithSchemeIfComponent(typeNode.elementType));
761
+ }
762
+ if (ts.isUnionTypeNode(typeNode)) {
763
+ // 檢查是否為 enum 的 union type
764
+ const unionTypes = typeNode.types;
765
+ if (unionTypes.length > 0 && unionTypes.every(type =>
766
+ ts.isLiteralTypeNode(type) &&
767
+ (ts.isStringLiteral(type.literal) || ts.isNumericLiteral(type.literal))
768
+ )) {
769
+ // 這是一個 enum 的 union type,我們需要找到對應的 enum 類型
770
+ const enumValues = unionTypes.map(type => {
771
+ if (ts.isLiteralTypeNode(type)) {
772
+ if (ts.isStringLiteral(type.literal)) {
773
+ return type.literal.text;
774
+ } else if (ts.isNumericLiteral(type.literal)) {
775
+ return type.literal.text;
776
+ }
777
+ }
778
+ return null;
779
+ }).filter(Boolean);
780
+
781
+ // 查找對應的 enum 類型
782
+ const matchingEnum = apiGen.aliases.find(alias => {
783
+ if (ts.isTypeAliasDeclaration(alias) && ts.isUnionTypeNode(alias.type)) {
784
+ const aliasValues = alias.type.types.map(type => {
785
+ if (ts.isLiteralTypeNode(type)) {
786
+ if (ts.isStringLiteral(type.literal)) {
787
+ return type.literal.text;
788
+ } else if (ts.isNumericLiteral(type.literal)) {
789
+ return type.literal.text;
790
+ }
791
+ }
792
+ return null;
793
+ }).filter(Boolean);
794
+
795
+ return aliasValues.length === enumValues.length &&
796
+ aliasValues.every(val => enumValues.includes(val));
797
+ }
798
+ return false;
799
+ });
800
+
801
+ // 對於所有的 enum 類型,直接使用字串型別,不轉換為 Enum
802
+ // 這樣可以避免自動命名造成的變更問題
803
+ if (matchingEnum && ts.isTypeAliasDeclaration(matchingEnum)) {
804
+ // 直接返回原始的 union type,不轉換為 Enum
805
+ return typeNode;
806
+ }
807
+ }
808
+
809
+ return factory.createUnionTypeNode(typeNode.types.map(wrapWithSchemeIfComponent));
810
+ }
811
+ if (ts.isTypeLiteralNode(typeNode)) {
812
+ return factory.createTypeLiteralNode(
813
+ typeNode.members.map(member => {
814
+ if (ts.isPropertySignature(member) && member.type) {
815
+ return factory.updatePropertySignature(
816
+ member,
817
+ member.modifiers,
818
+ member.name,
819
+ member.questionToken,
820
+ wrapWithSchemeIfComponent(member.type)
821
+ );
822
+ }
823
+ return member;
824
+ })
825
+ );
826
+ }
827
+ return typeNode;
628
828
  }
629
829
  }
630
830
 
@@ -20,7 +20,7 @@ type CreateBindingParams = {
20
20
  };
21
21
 
22
22
  const createBinding = ({
23
- operationDefinition: { verb, path, operation },
23
+ operationDefinition: { verb, path },
24
24
  overrides,
25
25
  isLazy = false,
26
26
  }: CreateBindingParams) =>
@@ -28,7 +28,7 @@ const createBinding = ({
28
28
  undefined,
29
29
  undefined,
30
30
  factory.createIdentifier(
31
- `use${isLazy ? 'Lazy' : ''}${capitalize(getOperationName(verb, path, operation.operationId))}${
31
+ `use${isLazy ? 'Lazy' : ''}${capitalize(getOperationName(verb, path, undefined))}${
32
32
  isQuery(verb, overrides) ? 'Query' : 'Mutation'
33
33
  }`
34
34
  ),