@goast/typescript 0.0.5 → 0.2.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 (217) hide show
  1. package/assets/{service → client}/angular/request-builder.ts +6 -2
  2. package/assets/client/fetch/{url-builder.ts → fetch-client.utils.ts} +15 -0
  3. package/assets/stubs/easy-network-stub/easy-network-stub.utils.ts +235 -0
  4. package/cjs/lib/ast/_index.js +108 -0
  5. package/cjs/lib/ast/common.js +2 -0
  6. package/cjs/lib/ast/index.js +5 -0
  7. package/cjs/lib/ast/node.js +10 -0
  8. package/cjs/lib/ast/nodes/argument.js +20 -0
  9. package/cjs/lib/ast/nodes/array-type.js +27 -0
  10. package/cjs/lib/ast/nodes/arrow-function.js +51 -0
  11. package/cjs/lib/ast/nodes/call.js +26 -0
  12. package/cjs/lib/ast/nodes/class.js +70 -0
  13. package/cjs/lib/ast/nodes/constructor-parameter.js +46 -0
  14. package/cjs/lib/ast/nodes/constructor.js +42 -0
  15. package/cjs/lib/ast/nodes/decorator.js +38 -0
  16. package/cjs/lib/ast/nodes/doc-tag.js +64 -0
  17. package/cjs/lib/ast/nodes/doc.js +57 -0
  18. package/cjs/lib/ast/nodes/enum-value.js +35 -0
  19. package/cjs/lib/ast/nodes/enum.js +46 -0
  20. package/cjs/lib/ast/nodes/export.js +27 -0
  21. package/cjs/lib/ast/nodes/function-type.js +35 -0
  22. package/cjs/lib/ast/nodes/function.js +60 -0
  23. package/cjs/lib/ast/nodes/generic-parameter.js +40 -0
  24. package/cjs/lib/ast/nodes/indexer.js +32 -0
  25. package/cjs/lib/ast/nodes/interface.js +60 -0
  26. package/cjs/lib/ast/nodes/intersection-type.js +44 -0
  27. package/cjs/lib/ast/nodes/lookup-type.js +30 -0
  28. package/cjs/lib/ast/nodes/method.js +82 -0
  29. package/cjs/lib/ast/nodes/object-type.js +24 -0
  30. package/cjs/lib/ast/nodes/object.js +24 -0
  31. package/cjs/lib/ast/nodes/parameter.js +45 -0
  32. package/cjs/lib/ast/nodes/property-accessor.js +128 -0
  33. package/cjs/lib/ast/nodes/property.js +119 -0
  34. package/cjs/lib/ast/nodes/reference.js +63 -0
  35. package/cjs/lib/ast/nodes/string.js +30 -0
  36. package/cjs/lib/ast/nodes/tuple.js +28 -0
  37. package/cjs/lib/ast/nodes/type-alias.js +36 -0
  38. package/cjs/lib/ast/nodes/typeof.js +23 -0
  39. package/cjs/lib/ast/nodes/types.js +2 -0
  40. package/cjs/lib/ast/nodes/union-type.js +44 -0
  41. package/cjs/lib/ast/nodes/variable.js +38 -0
  42. package/cjs/lib/ast/references/angular.js +12 -0
  43. package/cjs/lib/ast/references/easy-network-stub.js +8 -0
  44. package/cjs/lib/ast/references/index.js +7 -0
  45. package/cjs/lib/ast/references/rxjs.js +9 -0
  46. package/cjs/lib/ast/references/typescript.js +33 -0
  47. package/cjs/lib/ast/utils/get-type-script-builder-options.js +19 -0
  48. package/cjs/lib/ast/utils/to-ts-node.js +24 -0
  49. package/cjs/lib/ast/utils/write-ts-generic-parameters.js +11 -0
  50. package/cjs/lib/ast/utils/write-ts-members.js +18 -0
  51. package/cjs/lib/ast/utils/write-ts-nodes.js +24 -0
  52. package/cjs/lib/ast/utils/write-ts-parameters.js +14 -0
  53. package/cjs/lib/config.js +5 -3
  54. package/cjs/lib/file-builder.js +45 -202
  55. package/cjs/lib/generators/file-generator.js +2 -18
  56. package/cjs/lib/generators/index.js +1 -0
  57. package/cjs/lib/generators/models/model-generator.js +144 -205
  58. package/cjs/lib/generators/models/models-generator.js +12 -26
  59. package/cjs/lib/generators/models/models.js +1 -1
  60. package/cjs/lib/generators/services/angular-services/angular-service-generator.js +183 -306
  61. package/cjs/lib/generators/services/angular-services/angular-services-generator.js +168 -76
  62. package/cjs/lib/generators/services/angular-services/models.js +10 -1
  63. package/cjs/lib/generators/services/angular-services/refs.js +24 -0
  64. package/cjs/lib/generators/services/easy-network-stub/easy-network-stub-generator.js +169 -0
  65. package/cjs/lib/generators/services/easy-network-stub/easy-network-stubs-generator.js +73 -0
  66. package/cjs/lib/generators/services/easy-network-stub/index.js +6 -0
  67. package/cjs/lib/generators/services/easy-network-stub/models.js +10 -0
  68. package/cjs/lib/generators/services/easy-network-stub/refs.js +21 -0
  69. package/cjs/lib/generators/services/fetch-clients/fetch-client-generator.js +121 -181
  70. package/cjs/lib/generators/services/fetch-clients/fetch-clients-generator.js +5 -1
  71. package/cjs/lib/generators/services/fetch-clients/refs.js +17 -0
  72. package/cjs/lib/import-collection.js +18 -19
  73. package/esm/lib/ast/_index.js +37 -0
  74. package/esm/lib/ast/common.js +1 -0
  75. package/esm/lib/ast/index.js +2 -0
  76. package/esm/lib/ast/node.js +6 -0
  77. package/esm/lib/ast/nodes/argument.js +16 -0
  78. package/esm/lib/ast/nodes/array-type.js +23 -0
  79. package/esm/lib/ast/nodes/arrow-function.js +47 -0
  80. package/esm/lib/ast/nodes/call.js +22 -0
  81. package/esm/lib/ast/nodes/class.js +66 -0
  82. package/esm/lib/ast/nodes/constructor-parameter.js +42 -0
  83. package/esm/lib/ast/nodes/constructor.js +38 -0
  84. package/esm/lib/ast/nodes/decorator.js +34 -0
  85. package/esm/lib/ast/nodes/doc-tag.js +60 -0
  86. package/esm/lib/ast/nodes/doc.js +53 -0
  87. package/esm/lib/ast/nodes/enum-value.js +31 -0
  88. package/esm/lib/ast/nodes/enum.js +42 -0
  89. package/esm/lib/ast/nodes/export.js +22 -0
  90. package/esm/lib/ast/nodes/function-type.js +31 -0
  91. package/esm/lib/ast/nodes/function.js +56 -0
  92. package/esm/lib/ast/nodes/generic-parameter.js +36 -0
  93. package/esm/lib/ast/nodes/indexer.js +28 -0
  94. package/esm/lib/ast/nodes/interface.js +56 -0
  95. package/esm/lib/ast/nodes/intersection-type.js +40 -0
  96. package/esm/lib/ast/nodes/lookup-type.js +26 -0
  97. package/esm/lib/ast/nodes/method.js +77 -0
  98. package/esm/lib/ast/nodes/object-type.js +20 -0
  99. package/esm/lib/ast/nodes/object.js +20 -0
  100. package/esm/lib/ast/nodes/parameter.js +41 -0
  101. package/esm/lib/ast/nodes/property-accessor.js +121 -0
  102. package/esm/lib/ast/nodes/property.js +113 -0
  103. package/esm/lib/ast/nodes/reference.js +59 -0
  104. package/esm/lib/ast/nodes/string.js +26 -0
  105. package/esm/lib/ast/nodes/tuple.js +24 -0
  106. package/esm/lib/ast/nodes/type-alias.js +32 -0
  107. package/esm/lib/ast/nodes/typeof.js +18 -0
  108. package/esm/lib/ast/nodes/types.js +1 -0
  109. package/esm/lib/ast/nodes/union-type.js +40 -0
  110. package/esm/lib/ast/nodes/variable.js +34 -0
  111. package/esm/lib/ast/references/angular.js +9 -0
  112. package/esm/lib/ast/references/easy-network-stub.js +5 -0
  113. package/esm/lib/ast/references/index.js +5 -0
  114. package/esm/lib/ast/references/rxjs.js +6 -0
  115. package/esm/lib/ast/references/typescript.js +30 -0
  116. package/esm/lib/ast/utils/get-type-script-builder-options.js +15 -0
  117. package/esm/lib/ast/utils/to-ts-node.js +20 -0
  118. package/esm/lib/ast/utils/write-ts-generic-parameters.js +7 -0
  119. package/esm/lib/ast/utils/write-ts-members.js +14 -0
  120. package/esm/lib/ast/utils/write-ts-nodes.js +19 -0
  121. package/esm/lib/ast/utils/write-ts-parameters.js +10 -0
  122. package/esm/lib/config.js +5 -3
  123. package/esm/lib/file-builder.js +44 -202
  124. package/esm/lib/generators/file-generator.js +2 -18
  125. package/esm/lib/generators/index.js +1 -0
  126. package/esm/lib/generators/models/model-generator.js +149 -210
  127. package/esm/lib/generators/models/models-generator.js +15 -29
  128. package/esm/lib/generators/models/models.js +1 -1
  129. package/esm/lib/generators/services/angular-services/angular-service-generator.js +186 -309
  130. package/esm/lib/generators/services/angular-services/angular-services-generator.js +170 -78
  131. package/esm/lib/generators/services/angular-services/models.js +10 -1
  132. package/esm/lib/generators/services/angular-services/refs.js +20 -0
  133. package/esm/lib/generators/services/easy-network-stub/easy-network-stub-generator.js +165 -0
  134. package/esm/lib/generators/services/easy-network-stub/easy-network-stubs-generator.js +69 -0
  135. package/esm/lib/generators/services/easy-network-stub/index.js +3 -0
  136. package/esm/lib/generators/services/easy-network-stub/models.js +7 -0
  137. package/esm/lib/generators/services/easy-network-stub/refs.js +17 -0
  138. package/esm/lib/generators/services/fetch-clients/fetch-client-generator.js +123 -183
  139. package/esm/lib/generators/services/fetch-clients/fetch-clients-generator.js +5 -1
  140. package/esm/lib/generators/services/fetch-clients/refs.js +13 -0
  141. package/esm/lib/import-collection.js +17 -18
  142. package/package.json +6 -6
  143. package/types/lib/ast/_index.d.ts +38 -0
  144. package/types/lib/ast/common.d.ts +1 -0
  145. package/types/lib/ast/index.d.ts +1 -0
  146. package/types/lib/ast/node.d.ts +4 -0
  147. package/types/lib/ast/nodes/argument.d.ts +17 -0
  148. package/types/lib/ast/nodes/array-type.d.ts +19 -0
  149. package/types/lib/ast/nodes/arrow-function.d.ts +29 -0
  150. package/types/lib/ast/nodes/call.d.ts +20 -0
  151. package/types/lib/ast/nodes/class.d.ts +41 -0
  152. package/types/lib/ast/nodes/constructor-parameter.d.ts +19 -0
  153. package/types/lib/ast/nodes/constructor.d.ts +25 -0
  154. package/types/lib/ast/nodes/decorator.d.ts +22 -0
  155. package/types/lib/ast/nodes/doc-tag.d.ts +73 -0
  156. package/types/lib/ast/nodes/doc.d.ts +28 -0
  157. package/types/lib/ast/nodes/enum-value.d.ts +21 -0
  158. package/types/lib/ast/nodes/enum.d.ts +26 -0
  159. package/types/lib/ast/nodes/export.d.ts +19 -0
  160. package/types/lib/ast/nodes/function-type.d.ts +23 -0
  161. package/types/lib/ast/nodes/function.d.ts +35 -0
  162. package/types/lib/ast/nodes/generic-parameter.d.ts +25 -0
  163. package/types/lib/ast/nodes/indexer.d.ts +23 -0
  164. package/types/lib/ast/nodes/interface.d.ts +36 -0
  165. package/types/lib/ast/nodes/intersection-type.d.ts +17 -0
  166. package/types/lib/ast/nodes/lookup-type.d.ts +19 -0
  167. package/types/lib/ast/nodes/method.d.ts +45 -0
  168. package/types/lib/ast/nodes/object-type.d.ts +20 -0
  169. package/types/lib/ast/nodes/object.d.ts +19 -0
  170. package/types/lib/ast/nodes/parameter.d.ts +28 -0
  171. package/types/lib/ast/nodes/property-accessor.d.ts +53 -0
  172. package/types/lib/ast/nodes/property.d.ts +84 -0
  173. package/types/lib/ast/nodes/reference.d.ts +46 -0
  174. package/types/lib/ast/nodes/string.d.ts +18 -0
  175. package/types/lib/ast/nodes/tuple.d.ts +17 -0
  176. package/types/lib/ast/nodes/type-alias.d.ts +27 -0
  177. package/types/lib/ast/nodes/typeof.d.ts +18 -0
  178. package/types/lib/ast/nodes/types.d.ts +18 -0
  179. package/types/lib/ast/nodes/union-type.d.ts +17 -0
  180. package/types/lib/ast/nodes/variable.d.ts +28 -0
  181. package/types/lib/ast/references/angular.d.ts +37 -0
  182. package/types/lib/ast/references/easy-network-stub.d.ts +26 -0
  183. package/types/lib/ast/references/index.d.ts +3 -0
  184. package/types/lib/ast/references/rxjs.d.ts +30 -0
  185. package/types/lib/ast/references/typescript.d.ts +133 -0
  186. package/types/lib/ast/utils/get-type-script-builder-options.d.ts +3 -0
  187. package/types/lib/ast/utils/to-ts-node.d.ts +8 -0
  188. package/types/lib/ast/utils/write-ts-generic-parameters.d.ts +3 -0
  189. package/types/lib/ast/utils/write-ts-members.d.ts +5 -0
  190. package/types/lib/ast/utils/write-ts-nodes.d.ts +6 -0
  191. package/types/lib/ast/utils/write-ts-parameters.d.ts +3 -0
  192. package/types/lib/common-results.d.ts +4 -0
  193. package/types/lib/config.d.ts +5 -2
  194. package/types/lib/file-builder.d.ts +21 -98
  195. package/types/lib/generators/file-generator.d.ts +3 -7
  196. package/types/lib/generators/index.d.ts +1 -0
  197. package/types/lib/generators/models/model-generator.d.ts +18 -23
  198. package/types/lib/generators/models/models-generator.d.ts +4 -5
  199. package/types/lib/generators/models/models.d.ts +4 -4
  200. package/types/lib/generators/services/angular-services/angular-service-generator.d.ts +15 -35
  201. package/types/lib/generators/services/angular-services/angular-services-generator.d.ts +12 -10
  202. package/types/lib/generators/services/angular-services/models.d.ts +67 -22
  203. package/types/lib/generators/services/angular-services/refs.d.ts +34 -0
  204. package/types/lib/generators/services/easy-network-stub/easy-network-stub-generator.d.ts +32 -0
  205. package/types/lib/generators/services/easy-network-stub/easy-network-stubs-generator.d.ts +25 -0
  206. package/types/lib/generators/services/easy-network-stub/index.d.ts +3 -0
  207. package/types/lib/generators/services/easy-network-stub/models.d.ts +51 -0
  208. package/types/lib/generators/services/easy-network-stub/refs.d.ts +49 -0
  209. package/types/lib/generators/services/fetch-clients/fetch-client-generator.d.ts +10 -22
  210. package/types/lib/generators/services/fetch-clients/models.d.ts +4 -1
  211. package/types/lib/generators/services/fetch-clients/refs.d.ts +23 -0
  212. package/types/lib/import-collection.d.ts +13 -5
  213. package/assets/client/fetch/types.ts +0 -14
  214. package/assets/service/angular/api-configuration.ts +0 -18
  215. package/assets/service/angular/base-service.ts +0 -29
  216. package/assets/service/angular/response-handlers.ts +0 -127
  217. package/assets/service/angular/strict-http-response.ts +0 -8
@@ -1,356 +1,233 @@
1
- import { writeFileSync } from 'fs';
2
- import { dirname, resolve } from 'path';
3
- import { ensureDirSync } from 'fs-extra';
4
- import { toCasing } from '@goast/core';
5
- import { TypeScriptFileBuilder, } from '../../../file-builder';
1
+ import { resolve } from 'path';
2
+ import { appendValueGroup, builderTemplate as s, toCasing, } from '@goast/core';
3
+ import { ts } from '../../../ast';
4
+ import { TypeScriptFileBuilder } from '../../../file-builder';
6
5
  import { TypeScriptFileGenerator } from '../../file-generator';
7
6
  export class DefaultTypeScriptAngularServiceGenerator extends TypeScriptFileGenerator {
8
- constructor() {
9
- super(...arguments);
10
- this.httpClientType = {
11
- name: 'HttpClient',
12
- module: '@angular/common/http',
13
- };
14
- this.httpContextType = {
15
- name: 'HttpContext',
16
- module: '@angular/common/http',
17
- };
18
- this.httpResponseType = {
19
- name: 'HttpResponse',
20
- module: '@angular/common/http',
21
- };
22
- this.observableType = {
23
- name: 'Observable',
24
- module: 'rxjs',
25
- };
26
- this.rxjsFilterType = {
27
- name: 'filter',
28
- module: 'rxjs',
29
- };
30
- this.rxjsMapType = {
31
- name: 'map',
32
- module: 'rxjs',
33
- };
34
- }
35
- getApiConfigurationType(ctx) {
36
- return { name: 'ApiConfiguration', module: resolve(this.getUtilsDirPath(ctx), 'api-configuration.ts') };
37
- }
38
- getBaseServiceType(ctx) {
39
- return { name: 'BaseService', module: resolve(this.getUtilsDirPath(ctx), 'base-service.ts') };
40
- }
41
- getStrictHttpResponseType(ctx) {
42
- return { name: 'StrictHttpResponse', module: resolve(this.getUtilsDirPath(ctx), 'strict-http-response.ts') };
43
- }
44
- getRequestBuilderType(ctx) {
45
- return { name: 'RequestBuilder', module: resolve(this.getUtilsDirPath(ctx), 'request-builder.ts') };
46
- }
47
7
  generate(ctx) {
8
+ const responseModels = this.generateResponseModels(ctx);
48
9
  const filePath = this.getServiceFilePath(ctx);
49
10
  const name = this.getServiceClassName(ctx);
50
- console.log(`Generating service ${name} in ${filePath}...`);
51
- ensureDirSync(dirname(filePath));
52
- const serviceBuilder = new TypeScriptFileBuilder(filePath, ctx.config);
53
- this.generateServiceFileContent(ctx, serviceBuilder);
54
- writeFileSync(filePath, serviceBuilder.toString());
11
+ TypeScriptFileBuilder.generate({
12
+ logName: `service ${name}`,
13
+ filePath,
14
+ options: ctx.config,
15
+ generator: (b) => b.append(this.getServiceFileContent(ctx)),
16
+ });
55
17
  return {
56
18
  filePath,
57
19
  component: name,
58
- responseModels: {},
59
- imports: [{ kind: 'file', name, modulePath: filePath }],
20
+ responseModels,
60
21
  };
61
22
  }
62
- generateServiceFileContent(ctx, builder) {
63
- builder
64
- .append((builder) => builder.forEach(ctx.service.endpoints, (builder, endpoint) => this.generateEndpointParamsType(ctx, builder, endpoint), { separator: '\n' }))
65
- .ensurePreviousLineEmpty()
66
- .append((builder) => this.generateClass(ctx, builder));
67
- }
68
- // protected generateResponseModels(ctx: Context): Output['responseModels'] {
69
- // const filePath = this.get;
70
- // const builder = new TypeScriptFileBuilder();
71
- // }
72
- //protected generateResponseModelsFileContent(ctx: Context, builder: Builder) {}
73
- generateEndpointParamsType(ctx, builder, endpoint) {
74
- if (!this.hasEndpointParams(ctx, endpoint)) {
75
- return;
23
+ // #region Response Model
24
+ generateResponseModels(ctx) {
25
+ const result = {};
26
+ const filePath = this.getResponseModelFilePath(ctx);
27
+ const builder = new TypeScriptFileBuilder(filePath, ctx.config);
28
+ for (const endpoint of ctx.service.endpoints) {
29
+ const name = this.getResponseModelName(ctx, endpoint);
30
+ builder.appendLine(this.getResponseModelFileContent(ctx, endpoint));
31
+ result[endpoint.id] = { component: name, filePath };
32
+ }
33
+ builder.writeToFile();
34
+ return result;
35
+ }
36
+ getResponseModelFileContent(ctx, endpoint) {
37
+ const result = appendValueGroup([]);
38
+ const statusCodes = this.getEndpointStatusCodes(ctx, endpoint);
39
+ let statusCodeType;
40
+ const statusCodesTypeName = toCasing(`${endpoint.name}_StatusCodes`, ctx.config.typeNameCasing);
41
+ result.values.push(ts.typeAlias(statusCodesTypeName, ts.unionType(Object.keys(statusCodes))));
42
+ if (ctx.config.strictResponseTypes) {
43
+ statusCodeType = ts.reference(statusCodesTypeName);
44
+ }
45
+ else {
46
+ statusCodeType = ctx.refs.httpStatusCode();
76
47
  }
77
- const params = [];
48
+ result.values.push(ts.typeAlias(this.getResponseModelName(ctx, endpoint), ts.intersectionType([
49
+ ts.unionType([
50
+ ...Object.entries(statusCodes).map(([key, value]) => ts.intersectionType([
51
+ ts.refs.angular.httpResponse([value]),
52
+ ts.objectType({ members: [ts.property('status', { type: key })] }),
53
+ ])),
54
+ !ctx.config.strictResponseTypes
55
+ ? ts.intersectionType([
56
+ ts.refs.angular.httpResponse([this.getAnyType(ctx)]),
57
+ ts.objectType({
58
+ members: [
59
+ ts.property('status', {
60
+ type: ts.refs.exclude([ctx.refs.httpStatusCode(), ts.reference(statusCodesTypeName)]),
61
+ }),
62
+ ],
63
+ }),
64
+ ])
65
+ : null,
66
+ ]),
67
+ ts.objectType({ members: [ts.property('status', { type: 'TStatus' })] }),
68
+ ]), {
69
+ export: true,
70
+ generics: [
71
+ ts.genericParameter('TStatus', {
72
+ constraint: statusCodeType,
73
+ default: statusCodeType,
74
+ }),
75
+ ],
76
+ }));
77
+ return result;
78
+ }
79
+ getEndpointStatusCodes(ctx, endpoint) {
80
+ return Object.fromEntries([
81
+ ...Object.entries(ctx.config.defaultStatusCodeResponseTypes).map(([key, value]) => [
82
+ key,
83
+ typeof value === 'function' ? this.getSchemaType(ctx, value(ctx.data.schemas)) : value,
84
+ ]),
85
+ ...endpoint.responses
86
+ .filter((x) => x.statusCode)
87
+ .map((x) => { var _a; return [x.statusCode, this.getSchemaType(ctx, (_a = x.contentOptions[0]) === null || _a === void 0 ? void 0 : _a.schema, ts.refs.never())]; }),
88
+ ]);
89
+ }
90
+ // #endregion
91
+ getServiceFileContent(ctx) {
92
+ const code = appendValueGroup([], '\n');
93
+ for (const endpoint of ctx.service.endpoints) {
94
+ if (endpoint.parameters.length > 0 || endpoint.requestBody !== undefined) {
95
+ code.values.push(this.getEndpointParamsType(ctx, endpoint));
96
+ }
97
+ }
98
+ code.values.push(this.getClass(ctx));
99
+ return code;
100
+ }
101
+ getEndpointParamsType(ctx, endpoint) {
102
+ const type = ts.objectType();
78
103
  for (const parameter of endpoint.parameters) {
79
104
  const schema = parameter.schema;
80
- params.push((builder) => builder.appendProperty({
81
- name: this.toPropertyName(ctx, parameter.name),
82
- documentation: parameter.description,
83
- type: schema ? (builder) => builder.appendModelUsage(ctx.input.models[schema.id]) : this.getAnyType(ctx),
84
- isOptional: !parameter.required,
105
+ type.members.push(ts.property(toCasing(parameter.name, ctx.config.propertyNameCasing), {
106
+ doc: ts.doc({ description: parameter.description }),
107
+ type: schema ? (b) => b.appendModelUsage(ctx.input.models[schema.id]) : this.getAnyType(ctx),
108
+ optional: !parameter.required,
85
109
  }));
86
110
  }
87
111
  if (endpoint.requestBody !== undefined) {
88
112
  const body = endpoint.requestBody;
89
113
  const schema = body.content[0].schema;
90
- params.push((builder) => builder.appendProperty({
91
- name: 'body',
92
- documentation: body.description,
93
- type: schema ? (builder) => builder.appendModelUsage(ctx.input.models[schema.id]) : this.getAnyType(ctx),
94
- isOptional: !body.required,
114
+ type.members.push(ts.property('body', {
115
+ doc: ts.doc({ description: body.description }),
116
+ type: schema ? (b) => b.appendModelUsage(ctx.input.models[schema.id]) : this.getAnyType(ctx),
117
+ optional: !body.required,
95
118
  }));
96
119
  }
97
- builder.appendTypeDeclaration({
98
- name: this.getEndpointParamsTypeName(ctx, endpoint),
99
- documentation: `Parameters for operation ${this.getEndpointMethodName(ctx, endpoint)}`,
100
- type: (builder) => builder.appendCodeBlock(...params),
120
+ return ts.typeAlias(this.getEndpointParamsTypeName(ctx, endpoint), type, {
121
+ doc: ts.doc({ description: `Parameters for operation ${this.getEndpointMethodName(ctx, endpoint)}` }),
101
122
  });
102
123
  }
103
- generateClass(ctx, builder) {
104
- builder.appendClass(this.getClassOptions(ctx));
105
- }
106
- generateClassContent(ctx, builder) {
107
- builder
108
- .append((builder) => this.generateConstructor(ctx, builder))
109
- .forEach(ctx.service.endpoints, (builder, endpoint) => builder.ensurePreviousLineEmpty().append((builder) => this.generateEndpoint(ctx, builder, endpoint)));
110
- }
111
- generateConstructor(ctx, builder) {
112
- builder.appendConstructor(this.getConstructorOptions(ctx));
113
- }
114
- generateConstructorContent(ctx, builder) {
115
- builder.appendLine('super(config, http);');
116
- }
117
- generateEndpoint(ctx, builder, endpoint) {
118
- builder
119
- .append((builder) => this.generateEndpointPathProperty(ctx, builder, endpoint))
120
- .ensurePreviousLineEmpty()
121
- .append((builder) => this.generateEndpointResponseMethod(ctx, builder, endpoint))
122
- .ensurePreviousLineEmpty()
123
- .append((builder) => this.generateEndpointMethod(ctx, builder, endpoint));
124
- }
125
- generateEndpointPathProperty(ctx, builder, endpoint) {
126
- builder.appendProperty(this.getEndpointPathPropertyOptions(ctx, endpoint));
127
- }
128
- generateEndpointResponseMethod(ctx, builder, endpoint) {
129
- builder.appendMethod(this.getEndpointResponseMethodOptions(ctx, endpoint));
130
- }
131
- generateEndpointResponseMethodContent(ctx, builder, endpoint) {
132
- var _a, _b;
133
- builder
134
- .append('const rb = new ')
135
- .appendExternalTypeUsage(this.getRequestBuilderType(ctx))
136
- .appendParameters('this.rootUrl', `${this.getServiceClassName(ctx)}.${this.getEndpointPathPropertyName(ctx, endpoint)}`, this.toStringLiteral(ctx, endpoint.method))
137
- .appendLine(';');
138
- if (this.hasEndpointParams(ctx, endpoint)) {
139
- builder.append('if (params) ').appendCodeBlock((builder) => builder
140
- .forEach(endpoint.parameters.filter((x) => x.target === 'path' || x.target === 'query' || x.target === 'header'), (builder, parameter) => builder
141
- .append('rb.', parameter.target)
142
- .appendParameters(this.toStringLiteral(ctx, parameter.name), `params.${toCasing(parameter.name, 'camel')}`, (builder) => builder.appendObjectLiteral(parameter.style !== undefined
143
- ? `style: ${this.toStringLiteral(ctx, parameter.style)}`
144
- : undefined, parameter.explode !== undefined ? `explode: ${parameter.explode ? 'true' : 'false'}` : undefined))
145
- .appendLine(';'))
146
- .if(endpoint.requestBody !== undefined, (builder) => {
147
- var _a, _b, _c;
148
- return builder
149
- .append('rb.body')
150
- .appendParameters('params.body', this.toStringLiteral(ctx, (_c = (_b = (_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.content[0]) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : 'application/json'))
151
- .appendLine(';');
152
- }));
153
- }
154
- const response = this.getEndpointSuccessResponse(ctx, endpoint);
155
- const accept = (_b = (_a = response === null || response === void 0 ? void 0 : response.contentOptions[0]) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : '*/*';
156
- const responseType = accept.includes('json') ? 'json' : 'text';
157
- builder
158
- .ensurePreviousLineEmpty()
159
- .append('this.http.request')
160
- .appendParameters((builder) => builder
161
- .append('rb.build')
162
- .appendParameters((builder) => builder.appendObjectLiteral(`responseType: ${this.toStringLiteral(ctx, responseType)}`, `accept: ${this.toStringLiteral(ctx, accept)}`, 'context: context')))
163
- .append('.pipe')
164
- .appendParameters((builder) => builder.appendExternalTypeUsage(this.rxjsFilterType).appendParameters((builder) => builder.appendFunction({
165
- parameters: ['r: any'],
166
- body: (builder) => builder.append('r instanceof ').appendExternalTypeUsage(this.httpResponseType),
167
- singleLine: true,
168
- })), (builder) => builder.appendExternalTypeUsage(this.rxjsMapType).appendParameters((builder) => {
169
- var _a;
170
- return builder.appendFunction({
171
- parameters: [{ name: 'r', type: this.httpResponseType, genericArguments: ['any'] }],
172
- body: ((_a = response === null || response === void 0 ? void 0 : response.contentOptions) === null || _a === void 0 ? void 0 : _a[0])
173
- ? (builder) => builder
174
- .append('r as ')
175
- .appendExternalTypeUsage(this.getStrictHttpResponseType(ctx))
176
- .appendGenericArguments((builder) => this.generateEndpointSuccessResponseSchema(ctx, builder, endpoint))
177
- : (builder) => builder
178
- .parenthesize('()', (builder) => builder
179
- .append('r as ')
180
- .appendExternalTypeUsage(this.httpResponseType)
181
- .appendGenericArguments('any'))
182
- .append('.clone')
183
- .appendParameters((builder) => builder.appendObjectLiteral('body: undefined'))
184
- .append(' as ')
185
- .appendExternalTypeUsage(this.getStrictHttpResponseType(ctx))
186
- .appendGenericArguments('void'),
187
- singleLine: true,
188
- });
189
- }))
190
- .appendLine(';');
191
- }
192
- generateEndpointMethod(ctx, builder, endpoint) {
193
- builder.appendMethod(this.getEndpointMethodOptions(ctx, endpoint));
194
- }
195
- generateEndpointMethodContent(ctx, builder, endpoint) {
196
- builder
197
- .append('return this.', this.getEndpointResponseMethodName(ctx, endpoint))
198
- .appendParameters(this.hasEndpointParams(ctx, endpoint) ? 'params' : undefined, 'context')
199
- .append('.pipe')
200
- .appendParameters((builder) => builder
201
- .appendExternalTypeUsage(this.rxjsMapType)
202
- .append('((r: ')
203
- .appendExternalTypeUsage(this.getStrictHttpResponseType(ctx))
204
- .appendGenericArguments((builder) => this.generateEndpointSuccessResponseSchema(ctx, builder, endpoint))
205
- .append(') => r.body as ')
206
- .append((builder) => this.generateEndpointSuccessResponseSchema(ctx, builder, endpoint))
207
- .append(')'))
208
- .appendLine(';');
209
- }
210
- getClassOptions(ctx) {
211
- return {
212
- name: this.getServiceClassName(ctx),
213
- documentation: ctx.service.description,
214
- annotations: [
215
- {
216
- name: 'Injectable',
217
- module: '@angular/core',
218
- args: [(builder) => builder.appendObjectLiteral(`providedIn: ${this.toStringLiteral(ctx, 'root')}`)],
219
- },
124
+ getClass(ctx) {
125
+ return ts.class(this.getServiceClassName(ctx), {
126
+ doc: ts.doc({ description: ctx.service.description }),
127
+ decorators: [ts.decorator(ts.refs.angular.injectable(), [ts.toNode({ providedIn: 'root' })])],
128
+ export: true,
129
+ extends: ctx.refs.apiBaseService(),
130
+ members: [
131
+ ...ctx.service.endpoints.map((e) => ts.property(this.getEndpointPathPropertyName(ctx, e), {
132
+ accessModifier: 'private',
133
+ static: true,
134
+ readonly: true,
135
+ value: ts.string(e.path),
136
+ })),
137
+ ...ctx.service.endpoints.map((e) => this.getEndpointMethod(ctx, e)),
220
138
  ],
221
- extends: (builder) => builder.appendExternalTypeUsage(this.getBaseServiceType(ctx)),
222
- body: (builder) => this.generateClassContent(ctx, builder),
223
- };
139
+ });
224
140
  }
225
- getConstructorOptions(ctx) {
226
- return {
141
+ getEndpointMethod(ctx, endpoint) {
142
+ var _a, _b, _c, _d;
143
+ const hasParams = this.hasEndpointParams(ctx, endpoint);
144
+ const paramsOptional = !endpoint.parameters.some((p) => p.required) && !((_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.required);
145
+ const returnType = ts.refs.promise([
146
+ ts.reference(this.getResponseModelName(ctx, endpoint), this.getResponseModelFilePath(ctx)),
147
+ ]);
148
+ const accept = (_d = (_c = (_b = this.getEndpointSuccessResponse(ctx, endpoint)) === null || _b === void 0 ? void 0 : _b.contentOptions[0]) === null || _c === void 0 ? void 0 : _c.type) !== null && _d !== void 0 ? _d : '*/*';
149
+ const responseType = accept.includes('json') ? 'json' : 'text';
150
+ return ts.method(this.getEndpointMethodName(ctx, endpoint), {
151
+ accessModifier: 'public',
227
152
  parameters: [
228
- { name: 'config', type: (builder) => builder.appendExternalTypeUsage(this.getApiConfigurationType(ctx)) },
229
- { name: 'http', type: (builder) => builder.appendExternalTypeUsage(this.httpClientType) },
153
+ hasParams
154
+ ? ts.parameter('params', {
155
+ optional: paramsOptional,
156
+ type: ts.reference(this.getEndpointParamsTypeName(ctx, endpoint)),
157
+ })
158
+ : null,
159
+ ts.parameter('context', { optional: true, type: ts.refs.angular.httpContext() }),
230
160
  ],
231
- body: (builder) => this.generateConstructorContent(ctx, builder),
232
- };
233
- }
234
- getEndpointPathPropertyOptions(ctx, endpoint) {
235
- return {
236
- name: this.getEndpointPathPropertyName(ctx, endpoint),
237
- documentation: ctx.config.exposePathProperties
238
- ? `Path part for operation ${this.getEndpointMethodName(ctx, endpoint)}`
239
- : undefined,
240
- isStatic: true,
241
- accessibility: ctx.config.exposePathProperties ? 'public' : 'protected',
242
- isReadonly: true,
243
- initializer: this.toStringLiteral(ctx, endpoint.path),
244
- };
245
- }
246
- getEndpointMethodParams(ctx, endpoint) {
247
- const params = [];
248
- if (this.hasEndpointParams(ctx, endpoint)) {
249
- params.push({
250
- name: 'params',
251
- type: this.getEndpointParamsTypeName(ctx, endpoint),
252
- });
253
- }
254
- params.push({
255
- name: 'context',
256
- isOptional: true,
257
- type: (builder) => builder.appendExternalTypeUsage(this.httpContextType),
161
+ returnType,
162
+ body: appendValueGroup([
163
+ s `const rb = new ${ctx.refs.requestBuilder()}(this.rootUrl, ${this.getServiceClassName(ctx)}.${this.getEndpointPathPropertyName(ctx, endpoint)}, '${endpoint.method}');`,
164
+ hasParams
165
+ ? (b) => {
166
+ var _a;
167
+ return b.appendIf(paramsOptional, 'if (params) ').parenthesizeIf(paramsOptional, '{}', appendValueGroup([
168
+ ...endpoint.parameters
169
+ .filter((p) => p.target === 'path' || p.target === 'query' || p.target === 'header')
170
+ .map((p) => {
171
+ const options = ts.object({
172
+ members: [
173
+ p.style !== undefined ? ts.property('style', { value: ts.string(p.style) }) : null,
174
+ p.explode !== undefined ? ts.property('explode', { value: p.explode }) : null,
175
+ ],
176
+ });
177
+ return s `rb.${p.target}(${ts.string(p.name)}, params.${toCasing(p.name, ctx.config.propertyNameCasing)}, ${options});`;
178
+ }),
179
+ endpoint.requestBody
180
+ ? s `rb.body(params.body, ${ts.string((_a = endpoint.requestBody.content[0].type) !== null && _a !== void 0 ? _a : 'application/json')});`
181
+ : null,
182
+ ], '\n'), { multiline: true });
183
+ }
184
+ : null,
185
+ '',
186
+ s `return ${ts.refs.rxjs.firstValueFrom()}(${s.indent `
187
+ this.http.request(rb.build({${s.indent `
188
+ responseType: ${ts.string(responseType)},
189
+ accept: ${ts.string(accept)},
190
+ context,`}
191
+ })).pipe(${s.indent `
192
+ ${ts.refs.rxjs.filter()}((r: unknown) => r instanceof ${ts.refs.angular.httpResponse.infer()}),
193
+ ${ts.refs.rxjs.take()}(1),`}
194
+ )`}
195
+ ) as unknown as ${returnType};`,
196
+ ], '\n'),
258
197
  });
259
- return params;
260
- }
261
- generateEndpointSuccessResponseSchema(ctx, builder, endpoint) {
262
- var _a;
263
- const successResponse = this.getEndpointSuccessResponse(ctx, endpoint);
264
- const schema = (_a = successResponse === null || successResponse === void 0 ? void 0 : successResponse.contentOptions[0]) === null || _a === void 0 ? void 0 : _a.schema;
265
- if (schema) {
266
- const model = ctx.input.models[schema.id];
267
- if (model) {
268
- builder.appendModelUsage(model);
269
- }
270
- else {
271
- builder.append(this.getAnyType(ctx));
272
- }
273
- }
274
- else {
275
- builder.append('void');
276
- }
277
- }
278
- getEndpointResponseMethodOptions(ctx, endpoint) {
279
- return {
280
- name: this.getEndpointResponseMethodName(ctx, endpoint),
281
- accessibility: ctx.config.exposeResponseMethods ? 'public' : 'protected',
282
- documentation: ctx.config.exposeResponseMethods
283
- ? [
284
- endpoint.summary,
285
- endpoint.description,
286
- 'This method provides access to the full `HttpResponse`, allowing access to response headers.\n' +
287
- `To access only the response body, use \`${this.getEndpointMethodName(ctx, endpoint)}()\` instead.`,
288
- ]
289
- .filter((x) => x)
290
- .join('\n\n')
291
- : undefined,
292
- parameters: this.getEndpointMethodParams(ctx, endpoint),
293
- returnType: (builder) => builder
294
- .appendExternalTypeUsage(this.observableType)
295
- .appendGenericArguments((builder) => builder
296
- .appendExternalTypeUsage(this.getStrictHttpResponseType(ctx))
297
- .appendGenericArguments((builder) => this.generateEndpointSuccessResponseSchema(ctx, builder, endpoint))),
298
- body: (builder) => this.generateEndpointResponseMethodContent(ctx, builder, endpoint),
299
- };
300
- }
301
- getEndpointMethodOptions(ctx, endpoint) {
302
- return {
303
- name: this.getEndpointMethodName(ctx, endpoint),
304
- accessibility: 'public',
305
- documentation: [
306
- endpoint.summary,
307
- endpoint.description,
308
- ctx.config.exposeResponseMethods
309
- ? 'This method provides access only to the response body.\n' +
310
- `To access the full response (for headers, for example), \`${this.getEndpointResponseMethodName(ctx, endpoint)}()\` instead.`
311
- : undefined,
312
- ]
313
- .filter((x) => x)
314
- .join('\n\n'),
315
- parameters: this.getEndpointMethodParams(ctx, endpoint),
316
- returnType: ctx.config.clientMethodFlavor === 'response-handler'
317
- ? 'void'
318
- : (builder) => builder
319
- .appendExternalTypeUsage(this.observableType)
320
- .appendGenericArguments((builder) => this.generateEndpointSuccessResponseSchema(ctx, builder, endpoint)),
321
- body: (builder) => this.generateEndpointMethodContent(ctx, builder, endpoint),
322
- };
323
198
  }
324
199
  getEndpointSuccessResponse(ctx, endpoint) {
325
200
  var _a;
326
201
  return ((_a = endpoint.responses.find((x) => x.statusCode && x.statusCode >= 200 && x.statusCode < 300)) !== null && _a !== void 0 ? _a : endpoint.responses.find((x) => x.statusCode === undefined));
327
202
  }
328
203
  getServiceClassName(ctx) {
329
- return this.toTypeName(ctx, ctx.service.name);
204
+ return toCasing(ctx.service.name + '_Service', ctx.config.typeNameCasing);
330
205
  }
331
- hasEndpointParams(ctx, endpoint) {
332
- return endpoint.parameters.length > 0 || endpoint.requestBody !== undefined;
206
+ getResponseModelName(ctx, endpoint) {
207
+ return toCasing(`${this.getEndpointMethodName(ctx, endpoint)}ApiResponse`, ctx.config.typeNameCasing);
333
208
  }
334
209
  getEndpointParamsTypeName(ctx, endpoint) {
335
- return toCasing(this.getEndpointMethodName(ctx, endpoint), 'pascal') + 'Params';
210
+ return toCasing(this.getEndpointMethodName(ctx, endpoint) + '_Params', ctx.config.typeNameCasing);
336
211
  }
337
212
  getEndpointPathPropertyName(ctx, endpoint) {
338
- return this.getEndpointMethodName(ctx, endpoint) + 'Path';
213
+ return toCasing(this.getEndpointMethodName(ctx, endpoint) + '_Path', ctx.config.constantNameCasing);
339
214
  }
340
215
  getEndpointMethodName(ctx, endpoint) {
341
- return this.toMethodName(ctx, endpoint.name);
342
- }
343
- getEndpointResponseMethodName(ctx, endpoint) {
344
- return this.getEndpointMethodName(ctx, endpoint) + '$Response';
216
+ return toCasing(endpoint.name, ctx.config.functionNameCasing);
345
217
  }
346
218
  getServiceFilePath(ctx) {
347
219
  return resolve(ctx.config.outputDir, ctx.config.servicesDirPath, `${toCasing(ctx.service.name, ctx.config.fileNameCasing)}.ts`);
348
220
  }
349
- getResponseModelsFilePath(ctx) {
350
- var _a;
351
- return resolve(ctx.config.outputDir, (_a = ctx.config.responseModelsDirPath) !== null && _a !== void 0 ? _a : 'models/responses', `${toCasing(ctx.service.name, ctx.config.responseModelsFileNameCasing)}.ts`);
221
+ getResponseModelFilePath(ctx) {
222
+ return resolve(ctx.config.outputDir, ctx.config.responseModelsDirPath, `${toCasing(ctx.service.name, ctx.config.responseModelFileNameCasing)}.ts`);
223
+ }
224
+ hasEndpointParams(ctx, endpoint) {
225
+ return endpoint.parameters.length > 0 || endpoint.requestBody !== undefined;
352
226
  }
353
- getUtilsDirPath(ctx) {
354
- return resolve(ctx.config.outputDir, ctx.config.utilsDirPath);
227
+ getSchemaType(ctx, schema, fallback) {
228
+ const output = schema && ctx.input.models[schema.id];
229
+ if (!output)
230
+ return fallback !== null && fallback !== void 0 ? fallback : this.getAnyType(ctx);
231
+ return (b) => b.appendModelUsage(output);
355
232
  }
356
233
  }