@devlearning/swagger-generator 1.0.9 → 1.0.11
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/autogeneration/output/api.autogenerated.ts +95 -0
- package/autogeneration/output/model.autogenerated.ts +69 -0
- package/dist/api.constants.js +24 -0
- package/dist/generator-old.js +369 -0
- package/dist/generator.js +483 -0
- package/dist/generators-writers/angular/api-angular-writer.js +114 -0
- package/dist/generators-writers/angular/constants.js +28 -0
- package/dist/generators-writers/angular/model-angular-writer.js +42 -0
- package/dist/generators-writers/nextjs/api-nextjs-writer.js +127 -0
- package/dist/generators-writers/nextjs/constants.js +5 -0
- package/dist/generators-writers/nextjs/model-nextjs-writer.js +41 -0
- package/dist/generators-writers/utils.js +20 -0
- package/dist/index.js +24 -0
- package/dist/model.constants.js +1 -0
- package/dist/models/api-dto.js +1 -0
- package/dist/models/enum-value-dto.js +1 -0
- package/dist/models/model-dto.js +1 -0
- package/dist/models/parameter-dto.js +1 -0
- package/dist/models/property-dto.js +1 -0
- package/dist/models/swagger/swagger-component-property.js +1 -0
- package/dist/models/swagger/swagger-component.js +1 -0
- package/dist/models/swagger/swagger-content.js +1 -0
- package/dist/models/swagger/swagger-info.js +1 -0
- package/dist/models/swagger/swagger-method.js +1 -0
- package/dist/models/swagger/swagger-schema.js +1 -0
- package/dist/models/swagger/swagger.js +1 -0
- package/dist/models/type-dto.js +1 -0
- package/dist/swagger-downloader.js +9 -0
- package/package.json +1 -1
- package/src/generator.ts +170 -110
- package/src/generators-writers/angular/api-angular-writer.ts +2 -1
- package/src/models/swagger/swagger-component-property.ts +2 -0
- package/src/models/type-dto.ts +4 -1
- package/tsconfig.json +1 -2
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import { ApiNextJsWriter } from './generators-writers/nextjs/api-nextjs-writer.js';
|
|
2
|
+
import { ApiAngularWriter } from './generators-writers/angular/api-angular-writer.js';
|
|
3
|
+
import { SingleBar, Presets } from 'cli-progress';
|
|
4
|
+
import { ModelNextJsWriter } from './generators-writers/nextjs/model-nextjs-writer.js';
|
|
5
|
+
import { ModelAngularWriter } from './generators-writers/angular/model-angular-writer.js';
|
|
6
|
+
const contentTypeApplicationJson = 'application/json';
|
|
7
|
+
const contentTypeMultipartFormData = 'multipart/form-data';
|
|
8
|
+
export class Generator {
|
|
9
|
+
_swagger;
|
|
10
|
+
_outputDirectory;
|
|
11
|
+
_outputFormat;
|
|
12
|
+
_dateLibrary;
|
|
13
|
+
_apis = [];
|
|
14
|
+
_models = [];
|
|
15
|
+
_barApis = new SingleBar({
|
|
16
|
+
format: '{bar} {percentage}% | {message} {value}/{total} Elapsed: {duration_formatted}',
|
|
17
|
+
barCompleteChar: '\u2588',
|
|
18
|
+
barIncompleteChar: '\u2591',
|
|
19
|
+
hideCursor: true,
|
|
20
|
+
barsize: 20,
|
|
21
|
+
}, Presets.shades_classic);
|
|
22
|
+
_barModels = new SingleBar({
|
|
23
|
+
format: '{bar} {percentage}% | {message} {value}/{total} Elapsed: {duration_formatted}',
|
|
24
|
+
barCompleteChar: '\u2588',
|
|
25
|
+
barIncompleteChar: '\u2591',
|
|
26
|
+
hideCursor: true,
|
|
27
|
+
barsize: 20,
|
|
28
|
+
}, Presets.shades_classic);
|
|
29
|
+
constructor(swagger, outputDirectory, outputFormat, dateLibrary) {
|
|
30
|
+
this._swagger = swagger;
|
|
31
|
+
this._outputDirectory = outputDirectory;
|
|
32
|
+
this._outputFormat = outputFormat;
|
|
33
|
+
this._dateLibrary = dateLibrary;
|
|
34
|
+
}
|
|
35
|
+
generate() {
|
|
36
|
+
console.info('%c[Swagger API Generator] %cStarting to parse Swagger JSON file...', 'color: #4CAF50; font-weight: bold;', 'color: #2196F3;');
|
|
37
|
+
this.computeApi();
|
|
38
|
+
this.generateApi();
|
|
39
|
+
this.computeModel();
|
|
40
|
+
this.generateModel();
|
|
41
|
+
console.info('%c[Swagger Generator] %cSwagger file generated successfully!', 'color: #4CAF50; font-weight: bold;', 'color: #00C853;');
|
|
42
|
+
}
|
|
43
|
+
computeApi() {
|
|
44
|
+
this._barApis.start(Object.getOwnPropertyNames(this._swagger.paths).length, 0);
|
|
45
|
+
for (let index = 0; index < Object.getOwnPropertyNames(this._swagger.paths).length; index++) {
|
|
46
|
+
const apiName = Object.getOwnPropertyNames(this._swagger.paths)[index];
|
|
47
|
+
this._barApis.update(index, { message: `Apis parsing... ${apiName}` });
|
|
48
|
+
const apiSwaggerMethodKey = this._swagger.paths[apiName];
|
|
49
|
+
const apiMethod = Object.getOwnPropertyNames(apiSwaggerMethodKey)[0];
|
|
50
|
+
const apiSwaggerMethod = apiSwaggerMethodKey[apiMethod];
|
|
51
|
+
// console.debug(`\tAPI - ${apiName} - ${apiMethod}`);
|
|
52
|
+
let apiDto = {
|
|
53
|
+
name: apiName,
|
|
54
|
+
url: apiName.replace('{version}', '1'),
|
|
55
|
+
method: apiMethod,
|
|
56
|
+
parameters: this.computeParameters(apiName, apiSwaggerMethod),
|
|
57
|
+
returnType: this.computeResponseType(apiSwaggerMethod),
|
|
58
|
+
swaggerMethodKey: apiSwaggerMethodKey,
|
|
59
|
+
swaggerMethod: apiSwaggerMethod,
|
|
60
|
+
haveRequest: apiSwaggerMethod.requestBody != null,
|
|
61
|
+
isMultiPart: apiSwaggerMethod.requestBody != null && apiSwaggerMethod.requestBody.content[contentTypeMultipartFormData] != null,
|
|
62
|
+
};
|
|
63
|
+
this._apis.push(apiDto);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
computeModel() {
|
|
67
|
+
this._barModels.start(Object.getOwnPropertyNames(this._swagger.paths).length, 0);
|
|
68
|
+
let usedTypes = [];
|
|
69
|
+
let usedMultiPart = [];
|
|
70
|
+
// for (let index = 0; index < Object.getOwnPropertyNames(this._swagger.paths).length; index++) {
|
|
71
|
+
// const apiName = Object.getOwnPropertyNames(this._swagger.paths)[index];
|
|
72
|
+
// const apiSwaggerMethodKey = this._swagger.paths[apiName];
|
|
73
|
+
// const apiMethod = Object.getOwnPropertyNames(apiSwaggerMethodKey)[0];
|
|
74
|
+
// const apiSwaggerMethod = apiSwaggerMethodKey[apiMethod];
|
|
75
|
+
// const parametersRefType = apiSwaggerMethod.parameters?.filter(x => x.in == 'query' && x.schema?.$ref != null).map(x => x.schema.$ref.replace('#/components/schemas/', ''));
|
|
76
|
+
// if (parametersRefType) {
|
|
77
|
+
// usedTypes = usedTypes.concat(parametersRefType);
|
|
78
|
+
// }
|
|
79
|
+
// const responseRefType = this.computeRequestBodyType(apiSwaggerMethod!);
|
|
80
|
+
// if (responseRefType && !responseRefType.isVoid && !responseRefType.isNativeType) {
|
|
81
|
+
// usedTypes = usedTypes.concat(responseRefType.typeName);
|
|
82
|
+
// }
|
|
83
|
+
// const contentRefType = this.computeResponseType(apiSwaggerMethod!);
|
|
84
|
+
// if (contentRefType && !contentRefType.isVoid && !contentRefType.isNativeType) {
|
|
85
|
+
// usedTypes = usedTypes.concat(contentRefType.typeName);
|
|
86
|
+
// }
|
|
87
|
+
// }
|
|
88
|
+
for (let index = 0; index < this._apis.length; index++) {
|
|
89
|
+
if (this._apis[index].returnType && this._apis[index].returnType.isTypeReference) {
|
|
90
|
+
usedTypes.push(this._apis[index].returnType);
|
|
91
|
+
}
|
|
92
|
+
if (this._apis[index].parameters) {
|
|
93
|
+
this._apis[index].parameters.forEach(parameter => {
|
|
94
|
+
if (parameter.isTypeReference) {
|
|
95
|
+
usedTypes.push(parameter);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
usedTypes = [...new Set(usedTypes.map(item => item))]; // distinct
|
|
101
|
+
this.retrieveNestedObjects(usedTypes);
|
|
102
|
+
let models = ``;
|
|
103
|
+
if (this._swagger.components != null
|
|
104
|
+
&& this._swagger.components != undefined
|
|
105
|
+
&& this._swagger.components.schemas != null
|
|
106
|
+
&& this._swagger.components.schemas != undefined) {
|
|
107
|
+
for (let index = 0; index < Object.getOwnPropertyNames(this._swagger.components.schemas).length; index++) {
|
|
108
|
+
const modelName = Object.getOwnPropertyNames(this._swagger.components.schemas)[index];
|
|
109
|
+
const swaggerComponent = this._swagger.components.schemas[modelName];
|
|
110
|
+
// console.debug(`\tModel - ${modelName}`);
|
|
111
|
+
this._models.push({
|
|
112
|
+
modelType: swaggerComponent.type == 'integer' ? 'enum' : 'class',
|
|
113
|
+
name: modelName,
|
|
114
|
+
properties: (swaggerComponent.type == 'object') ? this.retrieveComponentProperties(swaggerComponent) : [],
|
|
115
|
+
enumValues: (swaggerComponent.type == 'integer') ? this.retrieveEnumValues(modelName, swaggerComponent) : [],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
usedMultiPart.forEach(apiName => {
|
|
120
|
+
const swaggerMethod = this._swagger.paths[apiName];
|
|
121
|
+
const method = Object.getOwnPropertyNames(swaggerMethod)[0];
|
|
122
|
+
const swaggerMethodInfo = swaggerMethod[method];
|
|
123
|
+
this._models.push({
|
|
124
|
+
modelType: 'class',
|
|
125
|
+
name: this.getApiNameNormalized(apiName),
|
|
126
|
+
properties: this.retrieveComponentProperties(swaggerMethodInfo.requestBody.content[contentTypeMultipartFormData].schema),
|
|
127
|
+
enumValues: [],
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
generateApi() {
|
|
132
|
+
this._barApis.update(this._apis.length, { message: `Api generating...` });
|
|
133
|
+
if (this._outputFormat == 'angular') {
|
|
134
|
+
const apiWriter = new ApiAngularWriter(this._outputDirectory);
|
|
135
|
+
apiWriter.write(this._apis);
|
|
136
|
+
}
|
|
137
|
+
else if (this._outputFormat == 'next') {
|
|
138
|
+
const apiWriter = new ApiNextJsWriter(this._outputDirectory);
|
|
139
|
+
apiWriter.write(this._apis);
|
|
140
|
+
}
|
|
141
|
+
this._barApis.update(this._apis.length, { message: `Api gerated` });
|
|
142
|
+
this._barApis.stop();
|
|
143
|
+
}
|
|
144
|
+
generateModel() {
|
|
145
|
+
this._barModels.update(this._apis.length, { message: `Model generation...` });
|
|
146
|
+
if (this._outputFormat == 'angular') {
|
|
147
|
+
const apiWriter = new ModelAngularWriter(this._outputDirectory);
|
|
148
|
+
apiWriter.write(this._models);
|
|
149
|
+
}
|
|
150
|
+
else if (this._outputFormat == 'next') {
|
|
151
|
+
const apiWriter = new ModelNextJsWriter(this._outputDirectory);
|
|
152
|
+
apiWriter.write(this._models);
|
|
153
|
+
}
|
|
154
|
+
this._barModels.update(this._apis.length, { message: `Model generated` });
|
|
155
|
+
this._barModels.stop();
|
|
156
|
+
}
|
|
157
|
+
computeParameters(apiName, swaggerMethod) {
|
|
158
|
+
if (!apiName)
|
|
159
|
+
return [];
|
|
160
|
+
if (!swaggerMethod || swaggerMethod == null)
|
|
161
|
+
return [];
|
|
162
|
+
let parameters = [];
|
|
163
|
+
try {
|
|
164
|
+
if (swaggerMethod.requestBody != null && swaggerMethod.requestBody.content[contentTypeMultipartFormData] != null) {
|
|
165
|
+
var modelName = this.getApiNameNormalized(apiName);
|
|
166
|
+
parameters.push({
|
|
167
|
+
name: 'request',
|
|
168
|
+
typeName: modelName,
|
|
169
|
+
nullable: false,
|
|
170
|
+
isQuery: false,
|
|
171
|
+
isEnum: false,
|
|
172
|
+
isTypeReference: true,
|
|
173
|
+
isNativeType: false,
|
|
174
|
+
isArray: false,
|
|
175
|
+
isVoid: false,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
if (swaggerMethod.requestBody != null) {
|
|
180
|
+
parameters.push({
|
|
181
|
+
name: 'request',
|
|
182
|
+
typeName: swaggerMethod.requestBody.content[contentTypeApplicationJson].schema.$ref.replace('#/components/schemas/', ''),
|
|
183
|
+
nullable: false,
|
|
184
|
+
isQuery: false,
|
|
185
|
+
isEnum: false,
|
|
186
|
+
isTypeReference: true,
|
|
187
|
+
isNativeType: false,
|
|
188
|
+
isArray: false,
|
|
189
|
+
isVoid: false,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
swaggerMethod.parameters?.filter(x => x.in == 'query').forEach(parameter => {
|
|
194
|
+
if (parameter.schema.$ref != null) {
|
|
195
|
+
parameters.push({
|
|
196
|
+
name: this.toFirstLetterLowercase(parameter.name),
|
|
197
|
+
typeName: parameter.schema.$ref.replace('#/components/schemas/', ''),
|
|
198
|
+
nullable: !parameter.required,
|
|
199
|
+
swaggerParameter: parameter,
|
|
200
|
+
isQuery: true,
|
|
201
|
+
isEnum: this.isEnum(parameter.schema.$ref),
|
|
202
|
+
isTypeReference: false,
|
|
203
|
+
isNativeType: false,
|
|
204
|
+
isArray: false,
|
|
205
|
+
isVoid: false,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
parameters.push({
|
|
210
|
+
name: this.toFirstLetterLowercase(parameter.name),
|
|
211
|
+
typeName: this.getNativeType(parameter.schema),
|
|
212
|
+
nullable: !parameter.required,
|
|
213
|
+
swaggerParameter: parameter,
|
|
214
|
+
isQuery: true,
|
|
215
|
+
isEnum: false,
|
|
216
|
+
isTypeReference: false,
|
|
217
|
+
isNativeType: true,
|
|
218
|
+
isArray: false,
|
|
219
|
+
isVoid: false,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
console.error(`\t\tError in ${apiName} - Attenzione forse hai dimenticato IActionResult e non hai tipizzato il tipo restituito dal servizio`);
|
|
228
|
+
}
|
|
229
|
+
return parameters;
|
|
230
|
+
}
|
|
231
|
+
computeResponseType(swaggerMethod) {
|
|
232
|
+
if (swaggerMethod.responses[200] == null) {
|
|
233
|
+
return {
|
|
234
|
+
typeName: 'void',
|
|
235
|
+
nullable: false,
|
|
236
|
+
isVoid: true,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return this.computeSwaggerContentType(swaggerMethod.responses[200].content[contentTypeApplicationJson]);
|
|
240
|
+
}
|
|
241
|
+
computeRequestBodyType(swaggerMethod) {
|
|
242
|
+
if (swaggerMethod.requestBody == null) {
|
|
243
|
+
return {
|
|
244
|
+
typeName: 'void',
|
|
245
|
+
nullable: false,
|
|
246
|
+
isVoid: true,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return this.computeSwaggerContentType(swaggerMethod.requestBody.content[contentTypeApplicationJson]);
|
|
250
|
+
}
|
|
251
|
+
computeSwaggerContentType(swaggerContent) {
|
|
252
|
+
try {
|
|
253
|
+
if (swaggerContent.schema.$ref != null)
|
|
254
|
+
return {
|
|
255
|
+
typeName: this.getObjectName(swaggerContent.schema.$ref),
|
|
256
|
+
nullable: false,
|
|
257
|
+
isNativeType: false,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
const errorMessage = "\t\tAttenzione forse hai dimenticato IActionResult e non hai tipizzato il tipo restituito dal servizio";
|
|
262
|
+
console.error(`%c${errorMessage}`, 'color: red');
|
|
263
|
+
throw new Error(errorMessage);
|
|
264
|
+
}
|
|
265
|
+
if (swaggerContent.schema.type != null) {
|
|
266
|
+
let schema = swaggerContent.schema;
|
|
267
|
+
if (schema.type == 'array') {
|
|
268
|
+
if (schema.items.$ref != null) {
|
|
269
|
+
return {
|
|
270
|
+
typeName: `${this.getObjectName(schema.items.$ref)}`,
|
|
271
|
+
nullable: false,
|
|
272
|
+
isNativeType: false,
|
|
273
|
+
isArray: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
return {
|
|
279
|
+
typeName: this.getNativeType(swaggerContent.schema),
|
|
280
|
+
nullable: false,
|
|
281
|
+
isNativeType: true,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
// if (swaggerComponentProperty.items.$ref != null)
|
|
285
|
+
// return `${this.getObjectName(swaggerComponentProperty.items.$ref)}[]`;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
return {
|
|
289
|
+
typeName: this.getNativeType(swaggerContent.schema),
|
|
290
|
+
nullable: false,
|
|
291
|
+
isNativeType: true,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
retrieveType(swaggerComponentProperty) {
|
|
296
|
+
if (swaggerComponentProperty.$ref != null)
|
|
297
|
+
return {
|
|
298
|
+
typeName: swaggerComponentProperty.$ref.replace('#/components/schemas/', ''),
|
|
299
|
+
isTypeReference: true,
|
|
300
|
+
isNativeType: false,
|
|
301
|
+
nullable: swaggerComponentProperty.nullable ?? false,
|
|
302
|
+
isArray: false,
|
|
303
|
+
isVoid: false,
|
|
304
|
+
};
|
|
305
|
+
if (swaggerComponentProperty.type != null && swaggerComponentProperty.type == 'array')
|
|
306
|
+
if (swaggerComponentProperty.items.$ref != null)
|
|
307
|
+
return {
|
|
308
|
+
typeName: `${this.getObjectName(swaggerComponentProperty.items.$ref)}`,
|
|
309
|
+
isTypeReference: true,
|
|
310
|
+
isNativeType: false,
|
|
311
|
+
nullable: swaggerComponentProperty.nullable ?? false,
|
|
312
|
+
isArray: true,
|
|
313
|
+
isVoid: false,
|
|
314
|
+
};
|
|
315
|
+
else
|
|
316
|
+
return {
|
|
317
|
+
typeName: this.getNativeType(swaggerComponentProperty),
|
|
318
|
+
isTypeReference: false,
|
|
319
|
+
isNativeType: true,
|
|
320
|
+
nullable: swaggerComponentProperty.nullable ?? false,
|
|
321
|
+
isArray: false,
|
|
322
|
+
isVoid: false,
|
|
323
|
+
};
|
|
324
|
+
if (swaggerComponentProperty.type != null)
|
|
325
|
+
return {
|
|
326
|
+
typeName: this.getNativeType(swaggerComponentProperty),
|
|
327
|
+
isTypeReference: false,
|
|
328
|
+
isNativeType: true,
|
|
329
|
+
nullable: swaggerComponentProperty.nullable ?? false,
|
|
330
|
+
isArray: false,
|
|
331
|
+
isVoid: false,
|
|
332
|
+
};
|
|
333
|
+
if (swaggerComponentProperty.type == null)
|
|
334
|
+
return {
|
|
335
|
+
typeName: 'void',
|
|
336
|
+
isTypeReference: false,
|
|
337
|
+
isNativeType: false,
|
|
338
|
+
nullable: swaggerComponentProperty.nullable ?? false,
|
|
339
|
+
isArray: false,
|
|
340
|
+
isVoid: true,
|
|
341
|
+
};
|
|
342
|
+
console.error("unmanaged swaggerMethodInfo", swaggerComponentProperty);
|
|
343
|
+
throw new Error("unmanaged swaggerMethodInfo");
|
|
344
|
+
}
|
|
345
|
+
parametrizeObject(objectName) {
|
|
346
|
+
let component = this._swagger.components.schemas[this.getObjectName(objectName)];
|
|
347
|
+
if (component == null || component.properties == null)
|
|
348
|
+
return ``;
|
|
349
|
+
console.debug(component.properties);
|
|
350
|
+
return ``;
|
|
351
|
+
}
|
|
352
|
+
isEnum(objectName) {
|
|
353
|
+
let component = this._swagger.components.schemas[this.getObjectName(objectName)];
|
|
354
|
+
return component.enum != null;
|
|
355
|
+
}
|
|
356
|
+
isDate(schema) {
|
|
357
|
+
return schema.type == 'string' && schema.format == 'date-time';
|
|
358
|
+
}
|
|
359
|
+
getObjectName(ref) {
|
|
360
|
+
return ref.replace('#/components/schemas/', '');
|
|
361
|
+
}
|
|
362
|
+
retrieveComponentProperties(swaggerCopmponent) {
|
|
363
|
+
if (swaggerCopmponent.properties == null)
|
|
364
|
+
return [];
|
|
365
|
+
let properties = [];
|
|
366
|
+
for (let index = 0; index < Object.getOwnPropertyNames(swaggerCopmponent.properties).length; index++) {
|
|
367
|
+
const propertyName = Object.getOwnPropertyNames(swaggerCopmponent.properties)[index];
|
|
368
|
+
const type = this.retrieveType(swaggerCopmponent.properties[propertyName]);
|
|
369
|
+
properties.push({
|
|
370
|
+
...type,
|
|
371
|
+
name: propertyName,
|
|
372
|
+
nullable: type.nullable,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return properties;
|
|
376
|
+
}
|
|
377
|
+
// retrieveSchemaProperties(schema: SwaggerSchema) {
|
|
378
|
+
// if (schema.properties == null) return [];
|
|
379
|
+
// let properties: PropertyDto[] = [];
|
|
380
|
+
// for (let j = 0; j < Object.getOwnPropertyNames(schema.properties).length; j++) {
|
|
381
|
+
// let propertyName = Object.getOwnPropertyNames(schema.properties)[j];
|
|
382
|
+
// properties +=
|
|
383
|
+
// `
|
|
384
|
+
// ${this.toFirstLetterLowercase(propertyName)}: ${this.retrieveType(schema.properties[propertyName])} | undefined;`
|
|
385
|
+
// }
|
|
386
|
+
// return properties;
|
|
387
|
+
// }
|
|
388
|
+
retrieveEnumValues(name, swaggerCopmponent) {
|
|
389
|
+
if (swaggerCopmponent.enum == null)
|
|
390
|
+
return [];
|
|
391
|
+
let values = [];
|
|
392
|
+
for (let index = 0; index < swaggerCopmponent.enum.length; index++) {
|
|
393
|
+
values.push({
|
|
394
|
+
name: swaggerCopmponent.enum[index].split('-')[0].trim(),
|
|
395
|
+
value: swaggerCopmponent.enum[index].split('-')[1].trim(),
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
return values;
|
|
399
|
+
}
|
|
400
|
+
retrieveNestedObjects(usedTypes) {
|
|
401
|
+
for (let i = 0; i < usedTypes.length; i++) {
|
|
402
|
+
const swaggerCopmponent = this._swagger.components.schemas[usedTypes[i].typeName];
|
|
403
|
+
this.retrieveNestedObjectsRecursive(swaggerCopmponent, usedTypes);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
retrieveNestedObjectsRecursive(swaggerComponent, usedTypes) {
|
|
407
|
+
try {
|
|
408
|
+
if (!swaggerComponent.properties)
|
|
409
|
+
return;
|
|
410
|
+
for (let j = 0; j < Object.getOwnPropertyNames(swaggerComponent.properties).length; j++) {
|
|
411
|
+
const propertyName = Object.getOwnPropertyNames(swaggerComponent.properties)[j];
|
|
412
|
+
let nestedUsedType = '';
|
|
413
|
+
if (swaggerComponent.properties[propertyName].$ref != null) {
|
|
414
|
+
nestedUsedType = swaggerComponent.properties[propertyName].$ref.replace('#/components/schemas/', '');
|
|
415
|
+
}
|
|
416
|
+
else if (swaggerComponent.properties[propertyName].type == 'array' && swaggerComponent.properties[propertyName].items.$ref != null) {
|
|
417
|
+
nestedUsedType = swaggerComponent.properties[propertyName].items.$ref.replace('#/components/schemas/', '');
|
|
418
|
+
}
|
|
419
|
+
if (nestedUsedType != '' && usedTypes.findIndex(x => x.typeName == nestedUsedType) == -1) {
|
|
420
|
+
let nested = this._swagger.components.schemas[nestedUsedType];
|
|
421
|
+
usedTypes.push({
|
|
422
|
+
typeName: nestedUsedType,
|
|
423
|
+
isTypeReference: nested.type == 'object',
|
|
424
|
+
isNativeType: nested.type != 'object',
|
|
425
|
+
nullable: false,
|
|
426
|
+
isArray: false,
|
|
427
|
+
isVoid: false,
|
|
428
|
+
//potrebbe essere un enum
|
|
429
|
+
});
|
|
430
|
+
this.retrieveNestedObjectsRecursive(nested, usedTypes);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
debugger;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
getNativeType(schema) {
|
|
439
|
+
let nativeType = 'n.d.';
|
|
440
|
+
if (schema.$ref != null) {
|
|
441
|
+
debugger;
|
|
442
|
+
}
|
|
443
|
+
else if (schema.type == 'array') {
|
|
444
|
+
nativeType = this.getNativeType(schema.items);
|
|
445
|
+
nativeType += '[]';
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
if (schema.type == 'integer')
|
|
449
|
+
nativeType = 'number';
|
|
450
|
+
if (schema.type == 'string' && schema.format == null)
|
|
451
|
+
nativeType = 'string';
|
|
452
|
+
if (schema.type == 'string' && schema.format == 'date-time')
|
|
453
|
+
nativeType = this._dateLibrary == 'moment' ? 'moment.Moment' : 'Date';
|
|
454
|
+
if (schema.type == 'string' && schema.format == 'uuid')
|
|
455
|
+
nativeType = 'string';
|
|
456
|
+
if (schema.type == 'string' && schema.format == 'binary')
|
|
457
|
+
nativeType = 'File';
|
|
458
|
+
if (schema.type == 'number')
|
|
459
|
+
nativeType = 'number';
|
|
460
|
+
if (schema.type == 'boolean')
|
|
461
|
+
nativeType = 'boolean';
|
|
462
|
+
if (schema.type == 'object')
|
|
463
|
+
nativeType = 'any';
|
|
464
|
+
}
|
|
465
|
+
if (nativeType.indexOf('n.d') == -1) {
|
|
466
|
+
return nativeType;
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
console.error("unmanaged schema type", schema);
|
|
470
|
+
throw new Error("unmanaged schema");
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
getApiNameNormalized(apiName) {
|
|
474
|
+
let normalizedApiName = apiName.replace('/api/v{version}/', '').replaceAll('/', '_');
|
|
475
|
+
if (normalizedApiName.charAt(0) == '_') {
|
|
476
|
+
normalizedApiName = normalizedApiName.slice(1);
|
|
477
|
+
}
|
|
478
|
+
return this.toFirstLetterLowercase(normalizedApiName);
|
|
479
|
+
}
|
|
480
|
+
toFirstLetterLowercase(value) {
|
|
481
|
+
return value.charAt(0).toLowerCase() + value.slice(1);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { API_POST, API_PRE } from './constants.js';
|
|
3
|
+
import { Utils } from '../utils.js';
|
|
4
|
+
export class ApiAngularWriter {
|
|
5
|
+
_outputDirectory;
|
|
6
|
+
constructor(_outputDirectory) {
|
|
7
|
+
this._outputDirectory = _outputDirectory;
|
|
8
|
+
}
|
|
9
|
+
write(apis) {
|
|
10
|
+
let apiString = '';
|
|
11
|
+
apis.forEach(api => {
|
|
12
|
+
apiString += this._apiString(api);
|
|
13
|
+
});
|
|
14
|
+
this._writeFile(apiString);
|
|
15
|
+
}
|
|
16
|
+
_apiString(api) {
|
|
17
|
+
let apiNameNormalized = Utils.getApiNameNormalized(api.name);
|
|
18
|
+
let parametersString = this._parameters(api);
|
|
19
|
+
let queryParametersPreparation = this._queryParametersPreparation(api);
|
|
20
|
+
let requestPreparation = this._requestPreparation(api);
|
|
21
|
+
let queryParameters = this._queryParameters(api);
|
|
22
|
+
let returnTypeString = this._returnType(api);
|
|
23
|
+
let haveRequest = api.haveRequest;
|
|
24
|
+
let method = api.method.toLowerCase();
|
|
25
|
+
let httpOptions = api.isMultiPart ? 'httpOptionsMultiPart' : 'httpOptions';
|
|
26
|
+
let apiString = `
|
|
27
|
+
public ${apiNameNormalized}(${parametersString}): Observable<${returnTypeString}> {
|
|
28
|
+
${queryParametersPreparation}${requestPreparation}return this._http.${method}<${returnTypeString}>(\`\${this._baseUrl}${api.url}${queryParameters}\`${haveRequest ? ', wrappedRequest' : ''}, ${httpOptions})
|
|
29
|
+
.pipe(
|
|
30
|
+
map(x => this._handleResponse(x)),
|
|
31
|
+
catchError((err, obs) => this._handleError(err, <Observable<any>>obs))
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
return apiString;
|
|
36
|
+
}
|
|
37
|
+
_parameters(api) {
|
|
38
|
+
let parametersString = '';
|
|
39
|
+
api.parameters.forEach(parameter => {
|
|
40
|
+
const prefixType = parameter.isEnum || !parameter.isNativeType ? 'Models.' : '';
|
|
41
|
+
parametersString += `${parameter.name}${parameter.nullable ? '?' : ''}: ${prefixType}${parameter.typeName}, `;
|
|
42
|
+
});
|
|
43
|
+
if (api.parameters.length > 0)
|
|
44
|
+
parametersString = parametersString.substring(0, parametersString.length - 2);
|
|
45
|
+
return parametersString;
|
|
46
|
+
}
|
|
47
|
+
_returnType(api) {
|
|
48
|
+
const prefixType = !api.returnType?.isNativeType ? 'Models.' : '';
|
|
49
|
+
const isArray = api.returnType?.isArray ? '[]' : '';
|
|
50
|
+
return api.returnType ? `${prefixType}${api.returnType.typeName}${isArray}` : 'any';
|
|
51
|
+
}
|
|
52
|
+
_queryParametersPreparation(api) {
|
|
53
|
+
let queryParametersPreparation = '';
|
|
54
|
+
api.parameters.forEach(parameter => {
|
|
55
|
+
if (parameter.isQuery) {
|
|
56
|
+
queryParametersPreparation += this._queryParametersPreparationStatement(parameter);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return queryParametersPreparation;
|
|
60
|
+
}
|
|
61
|
+
_queryParametersPreparationStatement(parameter) {
|
|
62
|
+
if (parameter.nullable) {
|
|
63
|
+
if (Utils.isDate(parameter.swaggerParameter?.schema)) {
|
|
64
|
+
return `let ${parameter.name}Param: string = ${parameter.name} != null && ${parameter.name} != undefined && ${parameter.name}.isValid() ? encodeURIComponent(this._momentToString(${parameter.name})) : '';
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return `let ${parameter.name}Param: string = ${parameter.name} != null && ${parameter.name} != undefined ? encodeURIComponent('' + ${parameter.name}) : '';
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
if (Utils.isDate(parameter.swaggerParameter?.schema)) {
|
|
74
|
+
return `let ${parameter.name}Param: string = encodeURIComponent(this._momentToString(${parameter.name}));
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return `let ${parameter.name}Param: string = encodeURIComponent('' + ${parameter.name});
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
_queryParameters(api) {
|
|
84
|
+
let queryParameters = '';
|
|
85
|
+
api.parameters.forEach(parameter => {
|
|
86
|
+
if (parameter.isQuery) {
|
|
87
|
+
queryParameters += this._queryParametersStatement(parameter);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (queryParameters.length > 0) {
|
|
91
|
+
queryParameters = '?' + queryParameters.substring(0, queryParameters.length - 1);
|
|
92
|
+
}
|
|
93
|
+
return queryParameters;
|
|
94
|
+
}
|
|
95
|
+
_queryParametersStatement(parameter) {
|
|
96
|
+
if (parameter.swaggerParameter == null)
|
|
97
|
+
return '';
|
|
98
|
+
if (!parameter.isQuery)
|
|
99
|
+
return '';
|
|
100
|
+
return `${parameter.name}=\${${parameter.name}Param}&`;
|
|
101
|
+
}
|
|
102
|
+
_requestPreparation(api) {
|
|
103
|
+
if (!api.haveRequest) {
|
|
104
|
+
return '';
|
|
105
|
+
}
|
|
106
|
+
return `let wrappedRequest = this._handleRequest(request);
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
_writeFile(apis) {
|
|
110
|
+
fs.writeFileSync(this._outputDirectory + "/api.autogenerated.ts", `${API_PRE}
|
|
111
|
+
${apis}
|
|
112
|
+
${API_POST}`, { flag: 'w' });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const API_PRE = `import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { Observable, catchError, map } from 'rxjs';
|
|
3
|
+
import * as Models from './model.autogenerated';
|
|
4
|
+
import { HttpHeaders } from "@angular/common/http";
|
|
5
|
+
|
|
6
|
+
export const httpOptions = {
|
|
7
|
+
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const httpOptionsMultipart = {};
|
|
11
|
+
|
|
12
|
+
export abstract class ApiAutogeneratedService {
|
|
13
|
+
constructor(
|
|
14
|
+
public _http: HttpClient,
|
|
15
|
+
public _baseUrl: string,
|
|
16
|
+
) { }
|
|
17
|
+
|
|
18
|
+
protected abstract _momentToString(moment: moment.Moment): string;
|
|
19
|
+
protected abstract _handleRequest<T>(request: T): T;
|
|
20
|
+
protected abstract _handleMultipart<T>(request: T): FormData;
|
|
21
|
+
protected abstract _handleResponse<T>(response: T): T;
|
|
22
|
+
protected abstract _handleError(error: any, obs: any): Observable<never>;
|
|
23
|
+
`;
|
|
24
|
+
export const API_POST = `}`;
|
|
25
|
+
export const MODEL_PRE = `import * as moment from 'moment';
|
|
26
|
+
`;
|
|
27
|
+
export const MODEL_POST = `
|
|
28
|
+
`;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { MODEL_POST, MODEL_PRE } from './constants.js';
|
|
3
|
+
export class ModelAngularWriter {
|
|
4
|
+
_outputDirectory;
|
|
5
|
+
constructor(_outputDirectory) {
|
|
6
|
+
this._outputDirectory = _outputDirectory;
|
|
7
|
+
}
|
|
8
|
+
write(models) {
|
|
9
|
+
let modelString = '';
|
|
10
|
+
models.forEach(model => {
|
|
11
|
+
modelString += this._modelString(model);
|
|
12
|
+
});
|
|
13
|
+
this._writeFile(modelString);
|
|
14
|
+
}
|
|
15
|
+
_modelString(model) {
|
|
16
|
+
let modelString = `
|
|
17
|
+
export ${model.modelType} ${model.name} {
|
|
18
|
+
${this._properties(model)}${this._enumValues(model)}
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
return modelString;
|
|
22
|
+
}
|
|
23
|
+
_properties(model) {
|
|
24
|
+
let propertiesString = '';
|
|
25
|
+
model.properties.forEach(property => {
|
|
26
|
+
propertiesString += ` ${property.name}${property.nullable ? '?' : ''}: ${property.typeName};\n`;
|
|
27
|
+
});
|
|
28
|
+
return propertiesString.trimEnd();
|
|
29
|
+
}
|
|
30
|
+
_enumValues(model) {
|
|
31
|
+
let enumValuesString = '';
|
|
32
|
+
model.enumValues.forEach(enumValue => {
|
|
33
|
+
enumValuesString += ` ${enumValue.name} = ${enumValue.value},\n`;
|
|
34
|
+
});
|
|
35
|
+
return enumValuesString.trimEnd();
|
|
36
|
+
}
|
|
37
|
+
_writeFile(models) {
|
|
38
|
+
fs.writeFileSync(this._outputDirectory + "/model.autogenerated.ts", `${MODEL_PRE}
|
|
39
|
+
${models}
|
|
40
|
+
${MODEL_POST}`, { flag: 'w' });
|
|
41
|
+
}
|
|
42
|
+
}
|