@openapi-qraft/tanstack-query-react-plugin 2.0.0-next.8 → 2.0.0

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/dist/generateCode.d.ts +3 -3
  3. package/dist/generateCode.d.ts.map +1 -1
  4. package/dist/generateCode.js +3 -3
  5. package/dist/generateCode.js.map +1 -1
  6. package/dist/lib/createOperationCommonTSDoc.d.ts +3 -0
  7. package/dist/lib/createOperationCommonTSDoc.d.ts.map +1 -0
  8. package/dist/lib/createOperationCommonTSDoc.js +8 -0
  9. package/dist/lib/createOperationCommonTSDoc.js.map +1 -0
  10. package/dist/plugin.d.ts.map +1 -1
  11. package/dist/plugin.js +4 -1
  12. package/dist/plugin.js.map +1 -1
  13. package/dist/ts-factory/filterUnusedTypes.d.ts +9 -0
  14. package/dist/ts-factory/filterUnusedTypes.d.ts.map +1 -0
  15. package/dist/ts-factory/filterUnusedTypes.js +34 -0
  16. package/dist/ts-factory/filterUnusedTypes.js.map +1 -0
  17. package/dist/ts-factory/getClientFactory.d.ts +1 -1
  18. package/dist/ts-factory/getClientFactory.d.ts.map +1 -1
  19. package/dist/ts-factory/getClientFactory.js +1 -1
  20. package/dist/ts-factory/getClientFactory.js.map +1 -1
  21. package/dist/ts-factory/getIndexFactory.d.ts +1 -1
  22. package/dist/ts-factory/getIndexFactory.d.ts.map +1 -1
  23. package/dist/ts-factory/getIndexFactory.js +2 -2
  24. package/dist/ts-factory/getIndexFactory.js.map +1 -1
  25. package/dist/ts-factory/getServiceFactory.d.ts +5 -3
  26. package/dist/ts-factory/getServiceFactory.d.ts.map +1 -1
  27. package/dist/ts-factory/getServiceFactory.js +124 -72
  28. package/dist/ts-factory/getServiceFactory.js.map +1 -1
  29. package/dist/ts-factory/getServiceIndexFactory.d.ts +3 -3
  30. package/dist/ts-factory/getServiceIndexFactory.d.ts.map +1 -1
  31. package/dist/ts-factory/getServiceIndexFactory.js +1 -1
  32. package/dist/ts-factory/getServiceIndexFactory.js.map +1 -1
  33. package/dist/ts-factory/service-operation.generated/ServiceOperationFetchInfiniteQuery.d.ts.map +1 -1
  34. package/dist/ts-factory/service-operation.generated/ServiceOperationFetchInfiniteQuery.js +26 -67
  35. package/dist/ts-factory/service-operation.generated/ServiceOperationFetchInfiniteQuery.js.map +1 -1
  36. package/dist/ts-factory/service-operation.generated/ServiceOperationFetchQuery.d.ts.map +1 -1
  37. package/dist/ts-factory/service-operation.generated/ServiceOperationFetchQuery.js +16 -1
  38. package/dist/ts-factory/service-operation.generated/ServiceOperationFetchQuery.js.map +1 -1
  39. package/dist/ts-factory/service-operation.generated/ServiceOperationGetInfiniteQueryData.d.ts.map +1 -1
  40. package/dist/ts-factory/service-operation.generated/ServiceOperationGetInfiniteQueryData.js +6 -10
  41. package/dist/ts-factory/service-operation.generated/ServiceOperationGetInfiniteQueryData.js.map +1 -1
  42. package/dist/ts-factory/service-operation.generated/ServiceOperationGetQueryData.d.ts.map +1 -1
  43. package/dist/ts-factory/service-operation.generated/ServiceOperationGetQueryData.js +6 -10
  44. package/dist/ts-factory/service-operation.generated/ServiceOperationGetQueryData.js.map +1 -1
  45. package/dist/ts-factory/service-operation.generated/ServiceOperationGetQueryState.d.ts.map +1 -1
  46. package/dist/ts-factory/service-operation.generated/ServiceOperationGetQueryState.js +6 -10
  47. package/dist/ts-factory/service-operation.generated/ServiceOperationGetQueryState.js.map +1 -1
  48. package/dist/ts-factory/service-operation.generated/ServiceOperationMutationFn.d.ts.map +1 -1
  49. package/dist/ts-factory/service-operation.generated/ServiceOperationMutationFn.js +7 -4
  50. package/dist/ts-factory/service-operation.generated/ServiceOperationMutationFn.js.map +1 -1
  51. package/dist/ts-factory/service-operation.generated/ServiceOperationQueryFn.d.ts.map +1 -1
  52. package/dist/ts-factory/service-operation.generated/ServiceOperationQueryFn.js +11 -17
  53. package/dist/ts-factory/service-operation.generated/ServiceOperationQueryFn.js.map +1 -1
  54. package/dist/ts-factory/service-operation.generated/ServiceOperationSetQueryData.d.ts.map +1 -1
  55. package/dist/ts-factory/service-operation.generated/ServiceOperationSetQueryData.js +9 -3
  56. package/dist/ts-factory/service-operation.generated/ServiceOperationSetQueryData.js.map +1 -1
  57. package/dist/ts-factory/service-operation.generated/ServiceOperationUseMutation.d.ts.map +1 -1
  58. package/dist/ts-factory/service-operation.generated/ServiceOperationUseMutation.js +12 -15
  59. package/dist/ts-factory/service-operation.generated/ServiceOperationUseMutation.js.map +1 -1
  60. package/dist/ts-factory/tsdoc/createOperationMethodTSDocExample.d.ts +6 -0
  61. package/dist/ts-factory/tsdoc/createOperationMethodTSDocExample.d.ts.map +1 -0
  62. package/dist/ts-factory/tsdoc/createOperationMethodTSDocExample.js +31 -0
  63. package/dist/ts-factory/tsdoc/createOperationMethodTSDocExample.js.map +1 -0
  64. package/dist/ts-factory/tsdoc/createUseInfiniteQueryOperationTSDocExample.d.ts +5 -0
  65. package/dist/ts-factory/tsdoc/createUseInfiniteQueryOperationTSDocExample.d.ts.map +1 -0
  66. package/dist/ts-factory/tsdoc/createUseInfiniteQueryOperationTSDocExample.js +53 -0
  67. package/dist/ts-factory/tsdoc/createUseInfiniteQueryOperationTSDocExample.js.map +1 -0
  68. package/dist/ts-factory/tsdoc/createUseIsFetchingOperationTSDocExample.d.ts +3 -0
  69. package/dist/ts-factory/tsdoc/createUseIsFetchingOperationTSDocExample.d.ts.map +1 -0
  70. package/dist/ts-factory/tsdoc/createUseIsFetchingOperationTSDocExample.js +41 -0
  71. package/dist/ts-factory/tsdoc/createUseIsFetchingOperationTSDocExample.js.map +1 -0
  72. package/dist/ts-factory/tsdoc/createUseIsMutatingOperationTSDocExample.d.ts +3 -0
  73. package/dist/ts-factory/tsdoc/createUseIsMutatingOperationTSDocExample.d.ts.map +1 -0
  74. package/dist/ts-factory/tsdoc/createUseIsMutatingOperationTSDocExample.js +41 -0
  75. package/dist/ts-factory/tsdoc/createUseIsMutatingOperationTSDocExample.js.map +1 -0
  76. package/dist/ts-factory/tsdoc/createUseMutationOperationTSDocExample.d.ts +3 -0
  77. package/dist/ts-factory/tsdoc/createUseMutationOperationTSDocExample.d.ts.map +1 -0
  78. package/dist/ts-factory/tsdoc/createUseMutationOperationTSDocExample.js +44 -0
  79. package/dist/ts-factory/tsdoc/createUseMutationOperationTSDocExample.js.map +1 -0
  80. package/dist/ts-factory/tsdoc/createUseMutationStateOperationTSDocExample.d.ts +3 -0
  81. package/dist/ts-factory/tsdoc/createUseMutationStateOperationTSDocExample.d.ts.map +1 -0
  82. package/dist/ts-factory/tsdoc/createUseMutationStateOperationTSDocExample.js +55 -0
  83. package/dist/ts-factory/tsdoc/createUseMutationStateOperationTSDocExample.js.map +1 -0
  84. package/dist/ts-factory/tsdoc/createUseQueriesOperationTSDocExample.d.ts +3 -0
  85. package/dist/ts-factory/tsdoc/createUseQueriesOperationTSDocExample.d.ts.map +1 -0
  86. package/dist/ts-factory/tsdoc/createUseQueriesOperationTSDocExample.js +88 -0
  87. package/dist/ts-factory/tsdoc/createUseQueriesOperationTSDocExample.js.map +1 -0
  88. package/dist/ts-factory/tsdoc/createUseQueryOperationTSDocExample.d.ts +3 -0
  89. package/dist/ts-factory/tsdoc/createUseQueryOperationTSDocExample.d.ts.map +1 -0
  90. package/dist/ts-factory/tsdoc/createUseQueryOperationTSDocExample.js +37 -0
  91. package/dist/ts-factory/tsdoc/createUseQueryOperationTSDocExample.js.map +1 -0
  92. package/dist/ts-factory/tsdoc/createUseSuspenseInfiniteQueryOperationTSDocExample.d.ts +3 -0
  93. package/dist/ts-factory/tsdoc/createUseSuspenseInfiniteQueryOperationTSDocExample.d.ts.map +1 -0
  94. package/dist/ts-factory/tsdoc/createUseSuspenseInfiniteQueryOperationTSDocExample.js +39 -0
  95. package/dist/ts-factory/tsdoc/createUseSuspenseInfiniteQueryOperationTSDocExample.js.map +1 -0
  96. package/dist/ts-factory/tsdoc/lib/createOperationMethodCallExpressionExampleNode.d.ts +7 -0
  97. package/dist/ts-factory/tsdoc/lib/createOperationMethodCallExpressionExampleNode.d.ts.map +1 -0
  98. package/dist/ts-factory/tsdoc/lib/createOperationMethodCallExpressionExampleNode.js +6 -0
  99. package/dist/ts-factory/tsdoc/lib/createOperationMethodCallExpressionExampleNode.js.map +1 -0
  100. package/dist/ts-factory/tsdoc/lib/createOperationMethodParametersExampleNodes.d.ts +4 -0
  101. package/dist/ts-factory/tsdoc/lib/createOperationMethodParametersExampleNodes.d.ts.map +1 -0
  102. package/dist/ts-factory/tsdoc/lib/createOperationMethodParametersExampleNodes.js +47 -0
  103. package/dist/ts-factory/tsdoc/lib/createOperationMethodParametersExampleNodes.js.map +1 -0
  104. package/package.json +6 -6
  105. package/src/generateCode.ts +8 -8
  106. package/src/lib/createOperationCommonTSDoc.ts +11 -0
  107. package/src/plugin.ts +8 -3
  108. package/src/ts-factory/filterUnusedTypes.ts +49 -0
  109. package/src/ts-factory/getClientFactory.ts +2 -2
  110. package/src/ts-factory/getIndexFactory.ts +13 -4
  111. package/src/ts-factory/getServiceFactory.ts +213 -139
  112. package/src/ts-factory/getServiceIndexFactory.ts +7 -7
  113. package/src/ts-factory/service-operation.generated/ServiceOperationFetchInfiniteQuery.ts +101 -190
  114. package/src/ts-factory/service-operation.generated/ServiceOperationFetchQuery.ts +80 -0
  115. package/src/ts-factory/service-operation.generated/ServiceOperationGetInfiniteQueryData.ts +28 -41
  116. package/src/ts-factory/service-operation.generated/ServiceOperationGetQueryData.ts +28 -41
  117. package/src/ts-factory/service-operation.generated/ServiceOperationGetQueryState.ts +28 -41
  118. package/src/ts-factory/service-operation.generated/ServiceOperationMutationFn.ts +23 -22
  119. package/src/ts-factory/service-operation.generated/ServiceOperationQueryFn.ts +49 -70
  120. package/src/ts-factory/service-operation.generated/ServiceOperationSetQueryData.ts +34 -10
  121. package/src/ts-factory/service-operation.generated/ServiceOperationUseMutation.ts +42 -59
  122. package/src/ts-factory/tsdoc/createOperationMethodTSDocExample.ts +65 -0
  123. package/src/ts-factory/tsdoc/createUseInfiniteQueryOperationTSDocExample.ts +135 -0
  124. package/src/ts-factory/tsdoc/createUseIsFetchingOperationTSDocExample.ts +81 -0
  125. package/src/ts-factory/tsdoc/createUseIsMutatingOperationTSDocExample.ts +74 -0
  126. package/src/ts-factory/tsdoc/createUseMutationOperationTSDocExample.ts +88 -0
  127. package/src/ts-factory/tsdoc/createUseMutationStateOperationTSDocExample.ts +154 -0
  128. package/src/ts-factory/tsdoc/createUseQueriesOperationTSDocExample.ts +292 -0
  129. package/src/ts-factory/tsdoc/createUseQueryOperationTSDocExample.ts +76 -0
  130. package/src/ts-factory/tsdoc/createUseSuspenseInfiniteQueryOperationTSDocExample.ts +63 -0
  131. package/src/ts-factory/tsdoc/lib/createOperationMethodCallExpressionExampleNode.ts +28 -0
  132. package/src/ts-factory/tsdoc/lib/createOperationMethodParametersExampleNodes.ts +83 -0
@@ -1,6 +1,8 @@
1
- import { ServiceOperation } from '@openapi-qraft/plugin/lib/open-api/getServices';
1
+ import { ServiceOperation } from '@openapi-qraft/plugin/lib/open-api/OpenAPIService';
2
2
  import camelCase from 'camelcase';
3
3
  import ts from 'typescript';
4
+ import { createOperationCommonTSDoc } from '../lib/createOperationCommonTSDoc.js';
5
+ import { filterUnusedTypes } from './filterUnusedTypes.js';
4
6
  import { createServiceOperationCancelQueriesNodes } from './service-operation.generated/ServiceOperationCancelQueries.js';
5
7
  import { createServiceOperationFetchInfiniteQueryNodes } from './service-operation.generated/ServiceOperationFetchInfiniteQuery.js';
6
8
  import { createServiceOperationFetchQueryNodes } from './service-operation.generated/ServiceOperationFetchQuery.js';
@@ -29,6 +31,7 @@ import { createServiceOperationUseQueryNodes } from './service-operation.generat
29
31
  import { createServiceOperationUseSuspenseInfiniteQueryNodes } from './service-operation.generated/ServiceOperationUseSuspenseInfiniteQuery.js';
30
32
  import { createServiceOperationUseSuspenseQueriesNodes } from './service-operation.generated/ServiceOperationUseSuspenseQueries.js';
31
33
  import { createServiceOperationUseSuspenseQueryNodes } from './service-operation.generated/ServiceOperationUseSuspenseQuery.js';
34
+ import { createOperationMethodTSDocExample } from './tsdoc/createOperationMethodTSDocExample.js';
32
35
 
33
36
  const factory = ts.factory;
34
37
 
@@ -36,18 +39,27 @@ export type ServiceImportsFactoryOptions = {
36
39
  openapiTypesImportPath: string;
37
40
  };
38
41
 
42
+ type Service = { typeName: string; variableName: string };
43
+
39
44
  export const getServiceFactory = (
40
- service: { typeName: string; variableName: string },
45
+ service: Service,
41
46
  operations: ServiceOperation[],
42
47
  { openapiTypesImportPath }: ServiceImportsFactoryOptions
43
48
  ) => {
44
- return [
45
- getOpenAPISchemaImportsFactory(openapiTypesImportPath),
46
- ...getServiceOperationImportsFactory(operations),
49
+ const mainNodes = [
47
50
  getServiceInterfaceFactory(service, operations),
48
51
  getServiceVariableFactory(service, operations),
49
52
  ...getOperationsTypes(operations),
50
53
  ];
54
+
55
+ const importNodes = [
56
+ getOpenAPISchemaImportsFactory(openapiTypesImportPath),
57
+ ...getServiceOperationImportsFactory(
58
+ filterUnusedTypes(getModuleTypeImports(operations), mainNodes)
59
+ ),
60
+ ];
61
+
62
+ return [...importNodes, ...mainNodes];
51
63
  };
52
64
 
53
65
  const getOpenAPISchemaImportsFactory = (schemaTypesPath: string) => {
@@ -70,18 +82,11 @@ const getOpenAPISchemaImportsFactory = (schemaTypesPath: string) => {
70
82
  );
71
83
  };
72
84
 
73
- const getServiceOperationImportsFactory = (operations: ServiceOperation[]) => {
85
+ const getServiceOperationImportsFactory = (
86
+ moduleImports: Record<string, string[]>
87
+ ) => {
74
88
  const factory = ts.factory;
75
89
 
76
- const moduleImports = getModuleTypeImports([
77
- ...(operations.some((operation) => operation.method === 'get')
78
- ? createServicesQueryOperationNodes()
79
- : []),
80
- ...(operations.some((operation) => operation.method !== 'get')
81
- ? createServicesMutationOperationNodes()
82
- : []),
83
- ]);
84
-
85
90
  return Object.entries(moduleImports).map(
86
91
  ([moduleName, importSpecifierNames]) => {
87
92
  return factory.createImportDeclaration(
@@ -105,76 +110,78 @@ const getServiceOperationImportsFactory = (operations: ServiceOperation[]) => {
105
110
  );
106
111
  };
107
112
 
108
- const __getServiceOperationGenericsPathImportsFactory = (
109
- operationGenericsPath: string,
110
- operations: ServiceOperation[]
111
- ) => {
112
- const factory = ts.factory;
113
-
114
- const queryMethods = ['get', 'head', 'options'] as const; // todo::make it shared
115
-
116
- return factory.createImportDeclaration(
117
- undefined,
118
- factory.createImportClause(
119
- true,
120
- undefined,
121
- factory.createNamedImports(
122
- [
123
- operations.some((operation) =>
124
- queryMethods.some((method) => method === operation.method)
125
- )
126
- ? factory.createImportSpecifier(
127
- false,
128
- undefined,
129
- factory.createIdentifier('ServiceOperationQuery')
130
- )
131
- : null,
132
- operations.some(
133
- (operation) =>
134
- !queryMethods.some((method) => method === operation.method)
135
- )
136
- ? factory.createImportSpecifier(
137
- false,
138
- undefined,
139
- factory.createIdentifier('ServiceOperationMutation')
140
- )
141
- : null,
142
- ].filter((node): node is NonNullable<typeof node> => Boolean(node))
143
- )
144
- ),
145
- factory.createStringLiteral(operationGenericsPath)
146
- );
147
- };
148
-
149
113
  const getServiceInterfaceFactory = (
150
- { typeName }: { typeName: string },
114
+ service: Service,
151
115
  operations: ServiceOperation[]
152
116
  ) => {
153
117
  return factory.createInterfaceDeclaration(
154
118
  [factory.createToken(ts.SyntaxKind.ExportKeyword)],
155
- factory.createIdentifier(typeName),
119
+ factory.createIdentifier(service.typeName),
156
120
  undefined,
157
121
  undefined,
158
- operations.map(getServiceInterfaceOperationFactory)
122
+ operations.map((operation) =>
123
+ getServiceInterfaceOperationFactory(operation, service)
124
+ )
159
125
  );
160
126
  };
161
127
 
162
- const getServiceInterfaceOperationFactory = (operation: ServiceOperation) => {
128
+ const getServiceInterfaceOperationFactory = (
129
+ operation: ServiceOperation,
130
+ service: Service
131
+ ) => {
163
132
  const operationMethodNodes = getMethodSignatureNodes(
164
133
  operation.method === 'get'
165
134
  ? createServicesQueryOperationNodes()
166
135
  : createServicesMutationOperationNodes()
167
136
  );
168
- operationMethodNodes.forEach(
169
- (node) => void addSyntheticLeadingOperationComment(node, operation)
170
- );
137
+
138
+ operationMethodNodes.forEach((node) => {
139
+ if (
140
+ ts.isMethodSignature(node) &&
141
+ ts.isIdentifier(node.name) &&
142
+ node.name.text
143
+ ) {
144
+ const operationCustomTSDoc = createOperationMethodTSDocExample(
145
+ operation,
146
+ {
147
+ serviceVariableName: service.variableName,
148
+ operationMethodName: node.name.text,
149
+ }
150
+ );
151
+ // Query and Mutation methods (hooks and QueryClient methods)
152
+ ts.addSyntheticLeadingComment(
153
+ node,
154
+ ts.SyntaxKind.MultiLineCommentTrivia,
155
+ createMultilineComment(
156
+ operationCustomTSDoc
157
+ ? operationCustomTSDoc
158
+ : createOperationCommonTSDoc(operation)
159
+ ),
160
+ true
161
+ );
162
+ } else if (ts.isCallSignatureDeclaration(node)) {
163
+ // Query and Mutation functions (invoke methods)
164
+ ts.addSyntheticLeadingComment(
165
+ node,
166
+ ts.SyntaxKind.MultiLineCommentTrivia,
167
+ createMultilineComment([...createOperationCommonTSDoc(operation)]),
168
+ true
169
+ );
170
+ }
171
+ });
171
172
 
172
173
  const node = factory.createPropertySignature(
173
174
  undefined,
174
175
  factory.createIdentifier(operation.name),
175
176
  undefined,
176
177
  factory.createTypeLiteralNode([
177
- ...replaceGenericTypesWithOperationTypes(operationMethodNodes, operation),
178
+ ...replaceGenericTypesWithOperationTypes(
179
+ reduceAreAllOptionalConditionalTParamsType(
180
+ operationMethodNodes,
181
+ operation
182
+ ),
183
+ operation
184
+ ),
178
185
  factory.createPropertySignature(
179
186
  undefined,
180
187
  factory.createIdentifier('schema'),
@@ -234,7 +241,7 @@ const getServiceInterfaceOperationFactory = (operation: ServiceOperation) => {
234
241
  ])
235
242
  );
236
243
 
237
- addSyntheticLeadingOperationComment(node, operation);
244
+ addOperationTSDoc(node, operation);
238
245
 
239
246
  return node;
240
247
  };
@@ -260,13 +267,17 @@ const getOperationSchemaFactory = (operation: ServiceOperation) => {
260
267
  )
261
268
  ),
262
269
 
263
- operation.mediaType
270
+ operation.requestBody
264
271
  ? factory.createPropertySignature(
265
272
  undefined,
266
273
  factory.createIdentifier('mediaType'),
267
274
  undefined,
268
- factory.createLiteralTypeNode(
269
- factory.createStringLiteral(operation.mediaType)
275
+ factory.createTupleTypeNode(
276
+ Object.keys(operation.requestBody.content).map((mediaType) =>
277
+ factory.createLiteralTypeNode(
278
+ factory.createStringLiteral(mediaType)
279
+ )
280
+ )
270
281
  )
271
282
  )
272
283
  : null,
@@ -342,44 +353,57 @@ const getOperationResponseFactory = (
342
353
  };
343
354
 
344
355
  const getOperationBodyFactory = (operation: ServiceOperation) => {
345
- if (!operation.mediaType)
356
+ if (!operation.requestBody)
346
357
  return factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword);
347
358
 
348
- return factory.createIndexedAccessTypeNode(
349
- factory.createIndexedAccessTypeNode(
350
- factory.createTypeReferenceNode(factory.createIdentifier('NonNullable'), [
359
+ const mediaTypes = Object.keys(operation.requestBody.content);
360
+
361
+ return factory.createUnionTypeNode([
362
+ ...mediaTypes.map((mediaType) =>
363
+ factory.createIndexedAccessTypeNode(
351
364
  factory.createIndexedAccessTypeNode(
352
- factory.createIndexedAccessTypeNode(
353
- factory.createIndexedAccessTypeNode(
354
- factory.createTypeReferenceNode(
355
- factory.createIdentifier('paths'),
356
- undefined
365
+ factory.createTypeReferenceNode(
366
+ factory.createIdentifier('NonNullable'),
367
+ [
368
+ factory.createIndexedAccessTypeNode(
369
+ factory.createIndexedAccessTypeNode(
370
+ factory.createIndexedAccessTypeNode(
371
+ factory.createTypeReferenceNode(
372
+ factory.createIdentifier('paths'),
373
+ undefined
374
+ ),
375
+ factory.createLiteralTypeNode(
376
+ factory.createStringLiteral(operation.path)
377
+ )
378
+ ),
379
+ factory.createLiteralTypeNode(
380
+ factory.createStringLiteral(operation.method)
381
+ )
382
+ ),
383
+ factory.createLiteralTypeNode(
384
+ factory.createStringLiteral('requestBody')
385
+ )
357
386
  ),
358
- factory.createLiteralTypeNode(
359
- factory.createStringLiteral(operation.path)
360
- )
361
- ),
362
- factory.createLiteralTypeNode(
363
- factory.createStringLiteral(operation.method)
364
- )
387
+ ]
365
388
  ),
366
- factory.createLiteralTypeNode(
367
- factory.createStringLiteral('requestBody')
368
- )
389
+ // todo::Add optional NonNullable inference, see `POST /entities/{entity_id}/documents`
390
+ factory.createLiteralTypeNode(factory.createStringLiteral('content'))
369
391
  ),
370
- ]),
371
- // todo::Add optional NonNullable inference, see `POST /entities/{entity_id}/documents`
372
- factory.createLiteralTypeNode(factory.createStringLiteral('content'))
392
+ factory.createLiteralTypeNode(factory.createStringLiteral(mediaType))
393
+ )
373
394
  ),
374
- factory.createLiteralTypeNode(
375
- factory.createStringLiteral(operation.mediaType)
376
- )
377
- );
395
+ ...(mediaTypes.some((mediaType) => mediaType.includes('/form-data'))
396
+ ? [factory.createTypeReferenceNode(factory.createIdentifier('FormData'))]
397
+ : []),
398
+ ]);
378
399
  };
379
400
 
380
- const getOperationParametersFactory = (operation: ServiceOperation) => {
381
- if (!operation.parameters)
382
- return factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword);
401
+ const createOperationParametersFactory = (operation: ServiceOperation) => {
402
+ if (!operation.parameters?.length)
403
+ return operation.method === 'get'
404
+ ? factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
405
+ : // mutation with predefined parameters fallback to an empty object
406
+ factory.createTypeLiteralNode([]);
383
407
 
384
408
  return factory.createIndexedAccessTypeNode(
385
409
  factory.createIndexedAccessTypeNode(
@@ -401,7 +425,7 @@ const getOperationParametersFactory = (operation: ServiceOperation) => {
401
425
  };
402
426
 
403
427
  const getServiceVariableFactory = (
404
- { variableName }: { variableName: string },
428
+ service: Service,
405
429
  operations: ServiceOperation[]
406
430
  ) => {
407
431
  return factory.createVariableStatement(
@@ -409,10 +433,12 @@ const getServiceVariableFactory = (
409
433
  factory.createVariableDeclarationList(
410
434
  [
411
435
  factory.createVariableDeclaration(
412
- factory.createIdentifier(variableName),
436
+ factory.createIdentifier(service.variableName),
413
437
  undefined,
414
438
  factory.createTypeLiteralNode(
415
- operations.map(getServiceVariableTypeFactory)
439
+ operations.map((operation) =>
440
+ getServiceVariableTypeFactory(operation)
441
+ )
416
442
  ),
417
443
  factory.createObjectLiteralExpression(
418
444
  operations.map(getServiceVariablePropertyFactory),
@@ -438,7 +464,7 @@ const getOperationsTypes = (operations: ServiceOperation[]) => {
438
464
  undefined,
439
465
  factory.createIdentifier(getOperationParametersTypeName(operation)),
440
466
  undefined,
441
- getOperationParametersFactory(operation)
467
+ createOperationParametersFactory(operation)
442
468
  ),
443
469
  factory.createTypeAliasDeclaration(
444
470
  undefined,
@@ -499,7 +525,7 @@ const getServiceVariableTypeFactory = (operation: ServiceOperation) => {
499
525
  ])
500
526
  );
501
527
 
502
- addSyntheticLeadingOperationComment(node, operation);
528
+ addOperationTSDoc(node, operation);
503
529
 
504
530
  return node;
505
531
  };
@@ -521,10 +547,14 @@ const getServiceVariablePropertyFactory = (operation: ServiceOperation) => {
521
547
  factory.createIdentifier('url'),
522
548
  factory.createStringLiteral(operation.path)
523
549
  ),
524
- operation.mediaType
550
+ operation.requestBody
525
551
  ? factory.createPropertyAssignment(
526
552
  factory.createIdentifier('mediaType'),
527
- factory.createStringLiteral(operation.mediaType)
553
+ factory.createArrayLiteralExpression(
554
+ Object.keys(operation.requestBody.content).map(
555
+ (mediaType) => factory.createStringLiteral(mediaType)
556
+ )
557
+ )
528
558
  )
529
559
  : null,
530
560
 
@@ -566,23 +596,8 @@ const createMultilineComment = (comment: string[]) => {
566
596
  return '';
567
597
  };
568
598
 
569
- const createOperationComment = (operation: ServiceOperation) => {
570
- return createMultilineComment(
571
- [
572
- operation.deprecated ? '@deprecated' : null,
573
- operation.summary ? `@summary ${operation.summary}` : null,
574
- operation.description ? `@description ${operation.description}` : null,
575
- ].filter((comment): comment is NonNullable<typeof comment> =>
576
- Boolean(comment)
577
- )
578
- );
579
- };
580
-
581
- const addSyntheticLeadingOperationComment = (
582
- node: ts.Node,
583
- operation: ServiceOperation
584
- ) => {
585
- const comment = createOperationComment(operation);
599
+ const addOperationTSDoc = (node: ts.Node, operation: ServiceOperation) => {
600
+ const comment = createMultilineComment(createOperationCommonTSDoc(operation));
586
601
 
587
602
  if (comment)
588
603
  ts.addSyntheticLeadingComment(
@@ -648,25 +663,36 @@ const getMethodSignatureNodes = (
648
663
  );
649
664
  };
650
665
 
651
- const getModuleTypeImports = (nodes: ts.Node[]) => {
666
+ /**
667
+ * Returns a list of all the modules that are imported by the operations.
668
+ * @param operations
669
+ * @returns Record<moduleName, importSpecifierNames[]>
670
+ */
671
+ const getModuleTypeImports = (operations: ServiceOperation[]) => {
672
+ const nodes = [
673
+ ...(operations.some((operation) => operation.method === 'get')
674
+ ? createServicesQueryOperationNodes()
675
+ : []),
676
+ ...(operations.some((operation) => operation.method !== 'get')
677
+ ? createServicesMutationOperationNodes()
678
+ : []),
679
+ ];
680
+
652
681
  return nodes
653
- .map((node) => {
654
- const foo =
655
- ts.isImportDeclaration(node) &&
656
- ts.isStringLiteral(node.moduleSpecifier) &&
657
- node.importClause?.isTypeOnly &&
658
- node.importClause.namedBindings &&
659
- ts.isNamedImports(node.importClause.namedBindings)
660
- ? {
661
- module: node.moduleSpecifier.text,
662
- imports: node.importClause.namedBindings.elements
663
- .filter(ts.isImportSpecifier)
664
- .map((specifier) => specifier.name.text),
665
- }
666
- : undefined;
667
-
668
- return foo;
669
- })
682
+ .map((node) =>
683
+ ts.isImportDeclaration(node) &&
684
+ ts.isStringLiteral(node.moduleSpecifier) &&
685
+ node.importClause?.isTypeOnly &&
686
+ node.importClause.namedBindings &&
687
+ ts.isNamedImports(node.importClause.namedBindings)
688
+ ? {
689
+ module: node.moduleSpecifier.text,
690
+ imports: node.importClause.namedBindings.elements
691
+ .filter(ts.isImportSpecifier)
692
+ .map((specifier) => specifier.name.text),
693
+ }
694
+ : undefined
695
+ )
670
696
  .reduce<Record<string, string[]>>((acc, item) => {
671
697
  if (!item) return acc;
672
698
  if (!acc[item.module])
@@ -676,10 +702,18 @@ const getModuleTypeImports = (nodes: ts.Node[]) => {
676
702
  arrayFilterUniqueCallback
677
703
  );
678
704
 
705
+ acc[item.module].sort();
706
+
679
707
  return acc;
680
708
  }, {});
681
709
  };
682
710
 
711
+ /**
712
+ * Replaces generic types with operation types with named types.
713
+ *
714
+ * For example, replaces `TParams` and `TQueryFnData` will be
715
+ * replaced with `GetEntitiesSchemaParameters` and `GetEntitiesSchemaData`.
716
+ */
683
717
  function replaceGenericTypesWithOperationTypes<T extends ts.Node>(
684
718
  node: T[],
685
719
  operation: ServiceOperation
@@ -721,6 +755,46 @@ function replaceGenericTypesWithOperationTypes<T extends ts.Node>(
721
755
  return result.transformed as T[];
722
756
  }
723
757
 
758
+ /**
759
+ * Replaces `AreAllOptional<TParams>` with `TParams | void` if `TParams` is optional,
760
+ * and with `TParams` when at least one parameter is required.
761
+ */
762
+ function reduceAreAllOptionalConditionalTParamsType<T extends ts.Node>(
763
+ node: T[],
764
+ operation: ServiceOperation
765
+ ): T[] {
766
+ const transformer =
767
+ (context: ts.TransformationContext) => (rootNode: ts.Node) => {
768
+ function visit(node: ts.Node): ts.Node {
769
+ if (
770
+ ts.isConditionalTypeNode(node) &&
771
+ ts.isTypeReferenceNode(node.checkType) &&
772
+ ts.isIdentifier(node.checkType.typeName) &&
773
+ node.checkType.typeName.text === 'AreAllOptional' &&
774
+ node.checkType.typeArguments?.every((node) => {
775
+ return (
776
+ ts.isTypeReferenceNode(node) &&
777
+ ts.isIdentifier(node.typeName) &&
778
+ node.typeName.text === 'TParams'
779
+ );
780
+ })
781
+ ) {
782
+ if (operation.parameters?.some((parameter) => parameter.required)) {
783
+ return node.falseType;
784
+ } else {
785
+ return node.trueType;
786
+ }
787
+ }
788
+ return ts.visitEachChild(node, visit, context);
789
+ }
790
+ return ts.visitNode(rootNode, visit);
791
+ };
792
+
793
+ const result = ts.transform(node, [transformer]);
794
+
795
+ return result.transformed as T[];
796
+ }
797
+
724
798
  function arrayFilterUniqueCallback<T>(value: T, index: number, self: T[]) {
725
799
  return self.indexOf(value) === index;
726
800
  }
@@ -1,10 +1,10 @@
1
- import { Service } from '@openapi-qraft/plugin/lib/open-api/getServices';
1
+ import { OpenAPIService } from '@openapi-qraft/plugin/lib/open-api/OpenAPIService';
2
2
  import ts from 'typescript';
3
3
 
4
- type Options = { explicitImportExtensions: boolean };
4
+ type Options = { explicitImportExtensions: '.js' | '.ts' | undefined };
5
5
 
6
6
  export const getServiceIndexFactory = (
7
- services: Service[],
7
+ services: OpenAPIService[],
8
8
  options: Options
9
9
  ) => {
10
10
  return [
@@ -14,7 +14,7 @@ export const getServiceIndexFactory = (
14
14
  ];
15
15
  };
16
16
 
17
- const getServiceIndexInterfaceFactory = (services: Service[]) => {
17
+ const getServiceIndexInterfaceFactory = (services: OpenAPIService[]) => {
18
18
  const factory = ts.factory;
19
19
 
20
20
  return factory.createTypeAliasDeclaration(
@@ -37,7 +37,7 @@ const getServiceIndexInterfaceFactory = (services: Service[]) => {
37
37
  );
38
38
  };
39
39
 
40
- const getServiceIndexVariableFactory = (services: Service[]) => {
40
+ const getServiceIndexVariableFactory = (services: OpenAPIService[]) => {
41
41
  const factory = ts.factory;
42
42
 
43
43
  return factory.createVariableStatement(
@@ -71,7 +71,7 @@ const getServiceIndexVariableFactory = (services: Service[]) => {
71
71
  };
72
72
 
73
73
  const getServicesImportsFactory = (
74
- services: Service[],
74
+ services: OpenAPIService[],
75
75
  { explicitImportExtensions }: Options
76
76
  ) => {
77
77
  const factory = ts.factory;
@@ -96,7 +96,7 @@ const getServicesImportsFactory = (
96
96
  ])
97
97
  ),
98
98
  factory.createStringLiteral(
99
- `./${fileBaseName}${explicitImportExtensions ? '.js' : ''}`
99
+ `./${fileBaseName}${explicitImportExtensions ?? ''}`
100
100
  )
101
101
  )
102
102
  );