@devlearning/swagger-generator 1.0.11 → 1.0.13
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/.vscode/launch.json +6 -0
- package/README.md +4 -2
- package/autogen/identity/api/identity_api.dart +82 -0
- package/autogen/identity/models/auth_activate_command.dart +14 -0
- package/autogen/identity/models/auth_app_authenticate_command.dart +16 -0
- package/autogen/identity/models/auth_generate_reset_password_code_command.dart +15 -0
- package/autogen/identity/models/auth_refresh_token_command.dart +15 -0
- package/autogen/identity/models/auth_reset_password_command.dart +16 -0
- package/autogen/identity/models/auth_user_authenticate_command.dart +15 -0
- package/autogen/identity/models/auth_user_dto.dart +18 -0
- package/autogen/identity/models/auth_verify_reset_password_code_command.dart +14 -0
- package/autogen/identity/models/authentication_token.dart +17 -0
- package/autogen/mvc/models/problem_details.dart +17 -0
- package/autogen/service_defaults/models/application_exception.dart +14 -0
- package/autogen/service_defaults/models/result.dart +17 -0
- package/autogen/user_profile/api/user_profile_api.dart +46 -0
- package/autogen/user_profile/models/test_list_query.dart +13 -0
- package/autogen/user_profile/models/test_read_query.dart +13 -0
- package/autogen/user_profile/models/test_save_command.dart +13 -0
- package/autogen/user_profile/models/user_general_info_save_command.dart +13 -0
- package/dist/generator.js +63 -31
- package/dist/generators-writers/angular/api-angular-writer.js +1 -1
- package/dist/generators-writers/dart/api-dart-writer.js +110 -0
- package/dist/generators-writers/dart/model-dart-writer.js +124 -0
- package/dist/generators-writers/dart/models/import-definition-dart.js +1 -0
- package/dist/generators-writers/dart/normalizator.js +35 -0
- package/dist/generators-writers/nextjs/api-nextjs-writer.js +1 -1
- package/dist/generators-writers/utils.js +43 -2
- package/dist/index.js +72 -16
- package/dist/models/swagger/swagger-component-property.js +10 -0
- package/dist/models/swagger/swagger-component.js +1 -0
- package/dist/models/swagger/swagger-schema.js +1 -0
- package/package.json +11 -5
- package/src/generator.ts +67 -38
- package/src/generators-writers/angular/api-angular-writer.ts +1 -1
- package/src/generators-writers/dart/api-dart-writer.ts +164 -0
- package/src/generators-writers/dart/model-dart-writer.ts +176 -0
- package/src/generators-writers/dart/models/import-definition-dart.ts +6 -0
- package/src/generators-writers/dart/normalizator.ts +44 -0
- package/src/generators-writers/dart/templates/api.mustache +29 -0
- package/src/generators-writers/dart/templates/model.mustache +18 -0
- package/src/generators-writers/nextjs/api-nextjs-writer.ts +1 -1
- package/src/generators-writers/utils.ts +54 -2
- package/src/index.ts +80 -16
- package/src/models/api-dto.ts +1 -0
- package/src/models/model-dto.ts +1 -0
- package/src/models/swagger/swagger-component-property.ts +10 -9
- package/src/models/swagger/swagger-component.ts +11 -2
- package/src/models/swagger/swagger-schema.ts +18 -6
- package/src/models/swagger/swagger.ts +1 -0
- package/autogeneration/output/api.autogenerated.ts +0 -95
- package/autogeneration/output/model.autogenerated.ts +0 -69
package/dist/generator.js
CHANGED
|
@@ -3,13 +3,15 @@ import { ApiAngularWriter } from './generators-writers/angular/api-angular-write
|
|
|
3
3
|
import { SingleBar, Presets } from 'cli-progress';
|
|
4
4
|
import { ModelNextJsWriter } from './generators-writers/nextjs/model-nextjs-writer.js';
|
|
5
5
|
import { ModelAngularWriter } from './generators-writers/angular/model-angular-writer.js';
|
|
6
|
+
import { DateTimeLibrary, TargetGeneration } from './index.js';
|
|
7
|
+
import { ApiDartWriter } from './generators-writers/dart/api-dart-writer.js';
|
|
8
|
+
import { ModelDartWriter } from './generators-writers/dart/model-dart-writer.js';
|
|
9
|
+
import { Utils } from './generators-writers/utils.js';
|
|
6
10
|
const contentTypeApplicationJson = 'application/json';
|
|
7
11
|
const contentTypeMultipartFormData = 'multipart/form-data';
|
|
8
12
|
export class Generator {
|
|
9
13
|
_swagger;
|
|
10
|
-
|
|
11
|
-
_outputFormat;
|
|
12
|
-
_dateLibrary;
|
|
14
|
+
_commandLineArgs;
|
|
13
15
|
_apis = [];
|
|
14
16
|
_models = [];
|
|
15
17
|
_barApis = new SingleBar({
|
|
@@ -26,18 +28,17 @@ export class Generator {
|
|
|
26
28
|
hideCursor: true,
|
|
27
29
|
barsize: 20,
|
|
28
30
|
}, Presets.shades_classic);
|
|
29
|
-
constructor(swagger,
|
|
31
|
+
constructor(swagger, commandLineArgs) {
|
|
30
32
|
this._swagger = swagger;
|
|
31
|
-
this.
|
|
32
|
-
this._outputFormat = outputFormat;
|
|
33
|
-
this._dateLibrary = dateLibrary;
|
|
33
|
+
this._commandLineArgs = commandLineArgs;
|
|
34
34
|
}
|
|
35
35
|
generate() {
|
|
36
36
|
console.info('%c[Swagger API Generator] %cStarting to parse Swagger JSON file...', 'color: #4CAF50; font-weight: bold;', 'color: #2196F3;');
|
|
37
|
+
Utils.clearDirectory(this._commandLineArgs.outputDirectory);
|
|
37
38
|
this.computeApi();
|
|
38
|
-
this.generateApi();
|
|
39
39
|
this.computeModel();
|
|
40
40
|
this.generateModel();
|
|
41
|
+
this.generateApi();
|
|
41
42
|
console.info('%c[Swagger Generator] %cSwagger file generated successfully!', 'color: #4CAF50; font-weight: bold;', 'color: #00C853;');
|
|
42
43
|
}
|
|
43
44
|
computeApi() {
|
|
@@ -59,6 +60,7 @@ export class Generator {
|
|
|
59
60
|
swaggerMethod: apiSwaggerMethod,
|
|
60
61
|
haveRequest: apiSwaggerMethod.requestBody != null,
|
|
61
62
|
isMultiPart: apiSwaggerMethod.requestBody != null && apiSwaggerMethod.requestBody.content[contentTypeMultipartFormData] != null,
|
|
63
|
+
tag: apiSwaggerMethod.tags && apiSwaggerMethod.tags.length > 0 ? apiSwaggerMethod.tags[0] : 'default',
|
|
62
64
|
};
|
|
63
65
|
this._apis.push(apiDto);
|
|
64
66
|
}
|
|
@@ -109,6 +111,7 @@ export class Generator {
|
|
|
109
111
|
const swaggerComponent = this._swagger.components.schemas[modelName];
|
|
110
112
|
// console.debug(`\tModel - ${modelName}`);
|
|
111
113
|
this._models.push({
|
|
114
|
+
typeName: modelName,
|
|
112
115
|
modelType: swaggerComponent.type == 'integer' ? 'enum' : 'class',
|
|
113
116
|
name: modelName,
|
|
114
117
|
properties: (swaggerComponent.type == 'object') ? this.retrieveComponentProperties(swaggerComponent) : [],
|
|
@@ -121,6 +124,7 @@ export class Generator {
|
|
|
121
124
|
const method = Object.getOwnPropertyNames(swaggerMethod)[0];
|
|
122
125
|
const swaggerMethodInfo = swaggerMethod[method];
|
|
123
126
|
this._models.push({
|
|
127
|
+
typeName: this.getApiNameNormalized(apiName),
|
|
124
128
|
modelType: 'class',
|
|
125
129
|
name: this.getApiNameNormalized(apiName),
|
|
126
130
|
properties: this.retrieveComponentProperties(swaggerMethodInfo.requestBody.content[contentTypeMultipartFormData].schema),
|
|
@@ -130,28 +134,36 @@ export class Generator {
|
|
|
130
134
|
}
|
|
131
135
|
generateApi() {
|
|
132
136
|
this._barApis.update(this._apis.length, { message: `Api generating...` });
|
|
133
|
-
if (this.
|
|
134
|
-
const apiWriter = new ApiAngularWriter(this.
|
|
137
|
+
if (this._commandLineArgs.target == TargetGeneration.Angular) {
|
|
138
|
+
const apiWriter = new ApiAngularWriter(this._commandLineArgs.outputDirectory);
|
|
135
139
|
apiWriter.write(this._apis);
|
|
136
140
|
}
|
|
137
|
-
else if (this.
|
|
138
|
-
const apiWriter = new ApiNextJsWriter(this.
|
|
141
|
+
else if (this._commandLineArgs.target == TargetGeneration.Next) {
|
|
142
|
+
const apiWriter = new ApiNextJsWriter(this._commandLineArgs.outputDirectory);
|
|
139
143
|
apiWriter.write(this._apis);
|
|
140
144
|
}
|
|
141
|
-
|
|
145
|
+
else if (this._commandLineArgs.target == TargetGeneration.Dart) {
|
|
146
|
+
const apiWriter = new ApiDartWriter(this._commandLineArgs);
|
|
147
|
+
apiWriter.write(this._apis, this._models);
|
|
148
|
+
}
|
|
149
|
+
this._barApis.update(this._apis.length, { message: `Api was generated successfully` });
|
|
142
150
|
this._barApis.stop();
|
|
143
151
|
}
|
|
144
152
|
generateModel() {
|
|
145
153
|
this._barModels.update(this._apis.length, { message: `Model generation...` });
|
|
146
|
-
if (this.
|
|
147
|
-
const apiWriter = new ModelAngularWriter(this.
|
|
154
|
+
if (this._commandLineArgs.target == TargetGeneration.Angular) {
|
|
155
|
+
const apiWriter = new ModelAngularWriter(this._commandLineArgs.outputDirectory);
|
|
156
|
+
apiWriter.write(this._models);
|
|
157
|
+
}
|
|
158
|
+
else if (this._commandLineArgs.target == TargetGeneration.Next) {
|
|
159
|
+
const apiWriter = new ModelNextJsWriter(this._commandLineArgs.outputDirectory);
|
|
148
160
|
apiWriter.write(this._models);
|
|
149
161
|
}
|
|
150
|
-
else if (this.
|
|
151
|
-
const apiWriter = new
|
|
162
|
+
else if (this._commandLineArgs.target == TargetGeneration.Dart) {
|
|
163
|
+
const apiWriter = new ModelDartWriter(this._commandLineArgs);
|
|
152
164
|
apiWriter.write(this._models);
|
|
153
165
|
}
|
|
154
|
-
this._barModels.update(this._apis.length, { message: `Model generated` });
|
|
166
|
+
this._barModels.update(this._apis.length, { message: `Model was generated successfully` });
|
|
155
167
|
this._barModels.stop();
|
|
156
168
|
}
|
|
157
169
|
computeParameters(apiName, swaggerMethod) {
|
|
@@ -177,9 +189,10 @@ export class Generator {
|
|
|
177
189
|
}
|
|
178
190
|
else {
|
|
179
191
|
if (swaggerMethod.requestBody != null) {
|
|
192
|
+
const type = this.retrieveType(swaggerMethod.requestBody.content[contentTypeApplicationJson].schema);
|
|
180
193
|
parameters.push({
|
|
181
194
|
name: 'request',
|
|
182
|
-
typeName:
|
|
195
|
+
typeName: type.typeName,
|
|
183
196
|
nullable: false,
|
|
184
197
|
isQuery: false,
|
|
185
198
|
isEnum: false,
|
|
@@ -192,9 +205,10 @@ export class Generator {
|
|
|
192
205
|
else {
|
|
193
206
|
swaggerMethod.parameters?.filter(x => x.in == 'query').forEach(parameter => {
|
|
194
207
|
if (parameter.schema.$ref != null) {
|
|
208
|
+
const type = this.retrieveType(parameter.schema);
|
|
195
209
|
parameters.push({
|
|
196
210
|
name: this.toFirstLetterLowercase(parameter.name),
|
|
197
|
-
typeName:
|
|
211
|
+
typeName: type.typeName,
|
|
198
212
|
nullable: !parameter.required,
|
|
199
213
|
swaggerParameter: parameter,
|
|
200
214
|
isQuery: true,
|
|
@@ -265,7 +279,7 @@ export class Generator {
|
|
|
265
279
|
if (swaggerContent.schema.type != null) {
|
|
266
280
|
let schema = swaggerContent.schema;
|
|
267
281
|
if (schema.type == 'array') {
|
|
268
|
-
if (schema.items
|
|
282
|
+
if (schema.items?.$ref != null) {
|
|
269
283
|
return {
|
|
270
284
|
typeName: `${this.getObjectName(schema.items.$ref)}`,
|
|
271
285
|
nullable: false,
|
|
@@ -293,7 +307,7 @@ export class Generator {
|
|
|
293
307
|
}
|
|
294
308
|
}
|
|
295
309
|
retrieveType(swaggerComponentProperty) {
|
|
296
|
-
if (swaggerComponentProperty.$ref != null)
|
|
310
|
+
if (swaggerComponentProperty.$ref != null) {
|
|
297
311
|
return {
|
|
298
312
|
typeName: swaggerComponentProperty.$ref.replace('#/components/schemas/', ''),
|
|
299
313
|
isTypeReference: true,
|
|
@@ -302,8 +316,16 @@ export class Generator {
|
|
|
302
316
|
isArray: false,
|
|
303
317
|
isVoid: false,
|
|
304
318
|
};
|
|
305
|
-
|
|
306
|
-
|
|
319
|
+
}
|
|
320
|
+
if (swaggerComponentProperty.allOf != null) {
|
|
321
|
+
const type = this.retrieveType(swaggerComponentProperty.allOf[0]); //TODO per ora prendo solo il primo, ma potrebbe essere un array di tipi
|
|
322
|
+
return {
|
|
323
|
+
...type,
|
|
324
|
+
nullable: swaggerComponentProperty.nullable ?? false,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
if (swaggerComponentProperty.type != null && swaggerComponentProperty.type == 'array') {
|
|
328
|
+
if (swaggerComponentProperty.items?.$ref != null) {
|
|
307
329
|
return {
|
|
308
330
|
typeName: `${this.getObjectName(swaggerComponentProperty.items.$ref)}`,
|
|
309
331
|
isTypeReference: true,
|
|
@@ -312,7 +334,8 @@ export class Generator {
|
|
|
312
334
|
isArray: true,
|
|
313
335
|
isVoid: false,
|
|
314
336
|
};
|
|
315
|
-
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
316
339
|
return {
|
|
317
340
|
typeName: this.getNativeType(swaggerComponentProperty),
|
|
318
341
|
isTypeReference: false,
|
|
@@ -321,7 +344,9 @@ export class Generator {
|
|
|
321
344
|
isArray: false,
|
|
322
345
|
isVoid: false,
|
|
323
346
|
};
|
|
324
|
-
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (swaggerComponentProperty.type != null) {
|
|
325
350
|
return {
|
|
326
351
|
typeName: this.getNativeType(swaggerComponentProperty),
|
|
327
352
|
isTypeReference: false,
|
|
@@ -330,7 +355,8 @@ export class Generator {
|
|
|
330
355
|
isArray: false,
|
|
331
356
|
isVoid: false,
|
|
332
357
|
};
|
|
333
|
-
|
|
358
|
+
}
|
|
359
|
+
if (swaggerComponentProperty.type == null) {
|
|
334
360
|
return {
|
|
335
361
|
typeName: 'void',
|
|
336
362
|
isTypeReference: false,
|
|
@@ -339,6 +365,7 @@ export class Generator {
|
|
|
339
365
|
isArray: false,
|
|
340
366
|
isVoid: true,
|
|
341
367
|
};
|
|
368
|
+
}
|
|
342
369
|
console.error("unmanaged swaggerMethodInfo", swaggerComponentProperty);
|
|
343
370
|
throw new Error("unmanaged swaggerMethodInfo");
|
|
344
371
|
}
|
|
@@ -410,10 +437,15 @@ export class Generator {
|
|
|
410
437
|
for (let j = 0; j < Object.getOwnPropertyNames(swaggerComponent.properties).length; j++) {
|
|
411
438
|
const propertyName = Object.getOwnPropertyNames(swaggerComponent.properties)[j];
|
|
412
439
|
let nestedUsedType = '';
|
|
413
|
-
if (swaggerComponent.properties[propertyName]
|
|
440
|
+
if (!swaggerComponent.properties[propertyName])
|
|
441
|
+
continue;
|
|
442
|
+
if (swaggerComponent.properties[propertyName].$ref) {
|
|
414
443
|
nestedUsedType = swaggerComponent.properties[propertyName].$ref.replace('#/components/schemas/', '');
|
|
415
444
|
}
|
|
416
|
-
else if (swaggerComponent.properties[propertyName].
|
|
445
|
+
else if (swaggerComponent.properties[propertyName].allOf && swaggerComponent.properties[propertyName].allOf[0] && swaggerComponent.properties[propertyName].allOf[0].$ref) {
|
|
446
|
+
nestedUsedType = swaggerComponent.properties[propertyName].allOf[0].$ref.replace('#/components/schemas/', ''); //TODO Assuming allOf contains a single $ref
|
|
447
|
+
}
|
|
448
|
+
else if (swaggerComponent.properties[propertyName].type == 'array' && swaggerComponent.properties[propertyName].items?.$ref) {
|
|
417
449
|
nestedUsedType = swaggerComponent.properties[propertyName].items.$ref.replace('#/components/schemas/', '');
|
|
418
450
|
}
|
|
419
451
|
if (nestedUsedType != '' && usedTypes.findIndex(x => x.typeName == nestedUsedType) == -1) {
|
|
@@ -440,7 +472,7 @@ export class Generator {
|
|
|
440
472
|
if (schema.$ref != null) {
|
|
441
473
|
debugger;
|
|
442
474
|
}
|
|
443
|
-
else if (schema.type == 'array') {
|
|
475
|
+
else if (schema.type == 'array' && schema.items != null) {
|
|
444
476
|
nativeType = this.getNativeType(schema.items);
|
|
445
477
|
nativeType += '[]';
|
|
446
478
|
}
|
|
@@ -450,7 +482,7 @@ export class Generator {
|
|
|
450
482
|
if (schema.type == 'string' && schema.format == null)
|
|
451
483
|
nativeType = 'string';
|
|
452
484
|
if (schema.type == 'string' && schema.format == 'date-time')
|
|
453
|
-
nativeType = this.
|
|
485
|
+
nativeType = this._commandLineArgs.dateTimeLibrary == DateTimeLibrary.Moment ? 'moment.Moment' : 'Date';
|
|
454
486
|
if (schema.type == 'string' && schema.format == 'uuid')
|
|
455
487
|
nativeType = 'string';
|
|
456
488
|
if (schema.type == 'string' && schema.format == 'binary')
|
|
@@ -14,7 +14,7 @@ export class ApiAngularWriter {
|
|
|
14
14
|
this._writeFile(apiString);
|
|
15
15
|
}
|
|
16
16
|
_apiString(api) {
|
|
17
|
-
let apiNameNormalized = Utils.
|
|
17
|
+
let apiNameNormalized = Utils.getNormalizedApiPath(api.name);
|
|
18
18
|
let parametersString = this._parameters(api);
|
|
19
19
|
let queryParametersPreparation = this._queryParametersPreparation(api);
|
|
20
20
|
let requestPreparation = this._requestPreparation(api);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs, { writeFileSync } from 'fs';
|
|
2
|
+
import { Utils } from '../utils.js';
|
|
3
|
+
import * as Mustache from 'mustache';
|
|
4
|
+
import { Normalizator } from './normalizator.js';
|
|
5
|
+
export class ApiDartWriter {
|
|
6
|
+
_commandLineArgs;
|
|
7
|
+
constructor(commandLineArgs) {
|
|
8
|
+
this._commandLineArgs = commandLineArgs;
|
|
9
|
+
}
|
|
10
|
+
write(apis, models) {
|
|
11
|
+
const template = fs.readFileSync('src/generators-writers/dart/templates/api.mustache', 'utf-8');
|
|
12
|
+
const grouped = this._groupByTag(apis);
|
|
13
|
+
for (const [tag, apis] of Object.entries(grouped)) {
|
|
14
|
+
console.log(`Api: ${tag}`);
|
|
15
|
+
let subPath = '';
|
|
16
|
+
let filename = '';
|
|
17
|
+
let apiClassName = '';
|
|
18
|
+
subPath = Utils.toDartFileName(tag);
|
|
19
|
+
filename = `${Utils.toDartFileName(tag + 'Api')}`;
|
|
20
|
+
apiClassName = `${Utils.toDartClassName(tag + 'Api')}`;
|
|
21
|
+
var apiDefinition = {
|
|
22
|
+
package: this._commandLineArgs.package,
|
|
23
|
+
outputDirectory: this._commandLineArgs.outputDirectory,
|
|
24
|
+
filename: filename,
|
|
25
|
+
apiClassName: apiClassName,
|
|
26
|
+
};
|
|
27
|
+
var endpoints = [];
|
|
28
|
+
var imports = [];
|
|
29
|
+
for (const api of apis) {
|
|
30
|
+
var requestType = undefined;
|
|
31
|
+
requestType = api.haveRequest ? api.parameters[0]?.typeName || 'void' : undefined;
|
|
32
|
+
requestType = requestType?.split('.').pop();
|
|
33
|
+
requestType = Utils.toDartClassName(requestType);
|
|
34
|
+
var responseType = 'void';
|
|
35
|
+
responseType = api.returnType ? api.returnType.typeName : 'void';
|
|
36
|
+
responseType = responseType?.split('.').pop();
|
|
37
|
+
responseType = Utils.toDartClassName(responseType) ?? responseType;
|
|
38
|
+
var methodName = Utils.getNormalizedApiPath(api.name);
|
|
39
|
+
if (methodName.startsWith(Utils.toFirstLetterLowercase(tag))) {
|
|
40
|
+
methodName = methodName.slice(tag.length);
|
|
41
|
+
methodName = Utils.toFirstLetterLowercase(methodName);
|
|
42
|
+
}
|
|
43
|
+
const endpoint = {
|
|
44
|
+
methodName: methodName,
|
|
45
|
+
httpMethod: api.method.toLowerCase(),
|
|
46
|
+
path: api.url,
|
|
47
|
+
responseType: responseType,
|
|
48
|
+
haveRequest: api.haveRequest,
|
|
49
|
+
requestType: requestType,
|
|
50
|
+
isGet: api.method.toLowerCase() === 'get'
|
|
51
|
+
};
|
|
52
|
+
if (api.haveRequest && api.parameters[0]?.typeName) {
|
|
53
|
+
if (imports.findIndex(x => x.type.typeName == api.parameters[0]?.typeName) == -1) {
|
|
54
|
+
models.forEach(model => {
|
|
55
|
+
if (model.typeName === api.parameters[0]?.typeName) {
|
|
56
|
+
const normalizedInfo = Normalizator.getNormalizedInfo(model);
|
|
57
|
+
imports.push({
|
|
58
|
+
type: api.parameters[0],
|
|
59
|
+
import: `import 'package:${this._commandLineArgs.package}/${this._commandLineArgs.outputDirectory}/${normalizedInfo.subPath}/${normalizedInfo.filename}.dart';`
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (api.returnType && !api.returnType.isNativeType) {
|
|
66
|
+
if (imports.findIndex(x => x.type.typeName == api.returnType.typeName) == -1) {
|
|
67
|
+
models.forEach(model => {
|
|
68
|
+
if (model.typeName === api.returnType.typeName) {
|
|
69
|
+
const normalizedInfo = Normalizator.getNormalizedInfo(model);
|
|
70
|
+
imports.push({
|
|
71
|
+
type: api.returnType,
|
|
72
|
+
import: `import 'package:${this._commandLineArgs.package}/${this._commandLineArgs.outputDirectory}/${normalizedInfo.subPath}/${normalizedInfo.filename}.dart';`
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
endpoints.push(endpoint);
|
|
79
|
+
}
|
|
80
|
+
apiDefinition.endpoints = endpoints;
|
|
81
|
+
apiDefinition.imports = imports.map(i => i.import);
|
|
82
|
+
let destinationPath = `${this._commandLineArgs.outputDirectory}/${subPath}/api`;
|
|
83
|
+
Utils.ensureDirectorySync(`${destinationPath}`);
|
|
84
|
+
var result = Mustache.default.render(template, apiDefinition);
|
|
85
|
+
writeFileSync(`${destinationPath}/${apiDefinition.filename}.dart`, result, 'utf-8');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
_toPascalCase(input) {
|
|
89
|
+
return input
|
|
90
|
+
.replace(/[_\- ]+/g, ' ') // sostituisce underscore, dash e spazi con uno spazio singolo
|
|
91
|
+
.trim() // rimuove spazi iniziali/finali
|
|
92
|
+
.split(' ') // divide in parole
|
|
93
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
94
|
+
.join('');
|
|
95
|
+
}
|
|
96
|
+
_normalizeApiClassName(input) {
|
|
97
|
+
return input
|
|
98
|
+
.replace(/\./g, '');
|
|
99
|
+
}
|
|
100
|
+
_groupByTag(apis) {
|
|
101
|
+
const groupedByRole = apis.reduce((acc, api) => {
|
|
102
|
+
if (!acc[api.tag]) {
|
|
103
|
+
acc[api.tag] = [];
|
|
104
|
+
}
|
|
105
|
+
acc[api.tag].push(api);
|
|
106
|
+
return acc;
|
|
107
|
+
}, {});
|
|
108
|
+
return groupedByRole;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import * as Mustache from 'mustache';
|
|
3
|
+
import { Utils } from '../utils.js';
|
|
4
|
+
import { Normalizator } from './normalizator.js';
|
|
5
|
+
export class ModelDartWriter {
|
|
6
|
+
_commandLineArgs;
|
|
7
|
+
constructor(commandLineArgs) {
|
|
8
|
+
this._commandLineArgs = commandLineArgs;
|
|
9
|
+
}
|
|
10
|
+
write(models) {
|
|
11
|
+
const template = readFileSync('src/generators-writers/dart/templates/model.mustache', 'utf-8');
|
|
12
|
+
models.forEach(model => {
|
|
13
|
+
const normalizedInfo = Normalizator.getNormalizedInfo(model);
|
|
14
|
+
const dartModel = {
|
|
15
|
+
filename: normalizedInfo.filename,
|
|
16
|
+
path: this._commandLineArgs.outputDirectory,
|
|
17
|
+
modelName: normalizedInfo.modelName,
|
|
18
|
+
fields: [],
|
|
19
|
+
imports: [],
|
|
20
|
+
};
|
|
21
|
+
var imports = [];
|
|
22
|
+
model.properties.forEach(property => {
|
|
23
|
+
var fieldTypeName = this._mapTsTypeToDart(property.typeName);
|
|
24
|
+
// if (fieldTypeName.endsWith('Exception')) {
|
|
25
|
+
// debugger
|
|
26
|
+
// }
|
|
27
|
+
fieldTypeName = Normalizator.getNormalizedTypeName(fieldTypeName);
|
|
28
|
+
if (property.isTypeReference) {
|
|
29
|
+
if (imports.findIndex(x => x.type.typeName == property.typeName) == -1) {
|
|
30
|
+
models.forEach(currModel => {
|
|
31
|
+
if (currModel.typeName === property.typeName) {
|
|
32
|
+
const normalizedInfo = Normalizator.getNormalizedInfo(currModel);
|
|
33
|
+
imports.push({
|
|
34
|
+
type: property,
|
|
35
|
+
import: `import 'package:${this._commandLineArgs.package}/${this._commandLineArgs.outputDirectory}/${normalizedInfo.subPath}/${normalizedInfo.filename}.dart';`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
dartModel.fields.push({
|
|
42
|
+
name: property.name,
|
|
43
|
+
type: fieldTypeName,
|
|
44
|
+
typeName: property.typeName,
|
|
45
|
+
nullable: property.nullable ? '?' : '',
|
|
46
|
+
required: property.nullable ? '' : 'required ',
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
dartModel.imports = imports.map(i => i.import);
|
|
50
|
+
let destinationPath = `${this._commandLineArgs.outputDirectory}/${normalizedInfo.subPath}`;
|
|
51
|
+
Utils.ensureDirectorySync(`${destinationPath}`);
|
|
52
|
+
let result = Mustache.default.render(template, dartModel);
|
|
53
|
+
writeFileSync(`${destinationPath}/${normalizedInfo.filename}.dart`, result, 'utf-8');
|
|
54
|
+
});
|
|
55
|
+
// var exportDataModels = <ExportModelItemDefinitionDart[]>[];
|
|
56
|
+
// models.forEach(model => {
|
|
57
|
+
// exportDataModels.push({
|
|
58
|
+
// filename: `${model.filename}.dart`
|
|
59
|
+
// });
|
|
60
|
+
// });
|
|
61
|
+
// var exportData = <ExportModelDefinitionDart>{
|
|
62
|
+
// models: exportDataModels
|
|
63
|
+
// };
|
|
64
|
+
// const exportTemplate = readFileSync('src/generators-writers/dart/templates/model.export.mustache', 'utf-8');
|
|
65
|
+
// const exportContent = Mustache.default.render(exportTemplate, exportData);
|
|
66
|
+
// writeFileSync(`${this._commandLineArgs.outputDirectory}/_export_models.dart`, exportContent, 'utf-8');
|
|
67
|
+
// const model = [
|
|
68
|
+
// {
|
|
69
|
+
// filename: 'login_request',
|
|
70
|
+
// modelName: 'LoginRequest',
|
|
71
|
+
// fields: [
|
|
72
|
+
// { name: 'email', type: 'String' },
|
|
73
|
+
// { name: 'password', type: 'String' }
|
|
74
|
+
// ]
|
|
75
|
+
// },
|
|
76
|
+
// {
|
|
77
|
+
// filename: 'login_response',
|
|
78
|
+
// modelName: 'LoginResponse',
|
|
79
|
+
// fields: [
|
|
80
|
+
// { name: 'token', type: 'String' }
|
|
81
|
+
// ]
|
|
82
|
+
// }
|
|
83
|
+
// ];
|
|
84
|
+
// let modelString = '';
|
|
85
|
+
// models.forEach(model => {
|
|
86
|
+
// modelString += this._modelString(model);
|
|
87
|
+
// });
|
|
88
|
+
// this._writeFile(modelString);
|
|
89
|
+
}
|
|
90
|
+
_mapTsTypeToDart(type) {
|
|
91
|
+
const normalized = type.trim().toLowerCase();
|
|
92
|
+
if (normalized.endsWith("[]")) {
|
|
93
|
+
const inner = normalized.slice(0, -2).trim();
|
|
94
|
+
return `List<${this._mapTsTypeToDart(inner)}>`;
|
|
95
|
+
}
|
|
96
|
+
switch (normalized) {
|
|
97
|
+
case "string":
|
|
98
|
+
case "uuid":
|
|
99
|
+
case "date":
|
|
100
|
+
case "datetime":
|
|
101
|
+
return "String";
|
|
102
|
+
case "number":
|
|
103
|
+
case "float":
|
|
104
|
+
case "double":
|
|
105
|
+
return "double";
|
|
106
|
+
case "integer":
|
|
107
|
+
case "int":
|
|
108
|
+
case "long":
|
|
109
|
+
return "int";
|
|
110
|
+
case "boolean":
|
|
111
|
+
case "bool":
|
|
112
|
+
return "bool";
|
|
113
|
+
case "any":
|
|
114
|
+
case "object":
|
|
115
|
+
return "dynamic";
|
|
116
|
+
case "null":
|
|
117
|
+
case "undefined":
|
|
118
|
+
return "Null";
|
|
119
|
+
default:
|
|
120
|
+
// per tipi personalizzati (es. modelli) restituisci con PascalCase
|
|
121
|
+
return Utils.toPascalCase(type);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Utils } from "../utils.js";
|
|
2
|
+
export class Normalizator {
|
|
3
|
+
// public static normalizeModelName(modelName: string): string {
|
|
4
|
+
// let normalizeModelName = modelName.split('.').pop()!;
|
|
5
|
+
// return Utils.toDartClassName(filename) ?? filename;
|
|
6
|
+
// }
|
|
7
|
+
// subPath = model.name.split('.').slice(0, -1).join('');
|
|
8
|
+
// subPath = `${Utils.toDartFileName(subPath)}/models`;
|
|
9
|
+
static getNormalizedInfo(model) {
|
|
10
|
+
let subPath = '';
|
|
11
|
+
let filename = '';
|
|
12
|
+
let modelName = '';
|
|
13
|
+
if (model.name && model.name.includes('.')) {
|
|
14
|
+
subPath = model.name.split('.').slice(0, -1).join('');
|
|
15
|
+
subPath = `${Utils.toDartFileName(subPath)}/models`;
|
|
16
|
+
filename = model.name.split('.').pop();
|
|
17
|
+
modelName = Utils.toDartClassName(filename) ?? filename;
|
|
18
|
+
filename = Utils.toDartFileName(filename);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
subPath = '';
|
|
22
|
+
filename = Utils.toDartFileName(model.name);
|
|
23
|
+
modelName = Utils.toDartClassName(model.name) ?? model.name;
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
filename: filename,
|
|
27
|
+
subPath: subPath,
|
|
28
|
+
modelName: modelName,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
static getNormalizedTypeName(typeName) {
|
|
32
|
+
let formattedTypeName = typeName.split('.').pop();
|
|
33
|
+
return Utils.toDartClassName(formattedTypeName) ?? typeName;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -14,7 +14,7 @@ export class ApiNextJsWriter {
|
|
|
14
14
|
this._writeFile(apiString);
|
|
15
15
|
}
|
|
16
16
|
_apiString(api) {
|
|
17
|
-
let apiNameNormalized = Utils.toCamelCase(Utils.
|
|
17
|
+
let apiNameNormalized = Utils.toCamelCase(Utils.getNormalizedApiPath(api.name));
|
|
18
18
|
let parametersString = this._parameters(api);
|
|
19
19
|
let queryParametersPreparation = this._queryParametersPreparation(api);
|
|
20
20
|
let requestPreparation = this._requestPreparation(api);
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
1
3
|
export class Utils {
|
|
2
|
-
static
|
|
4
|
+
static getNormalizedApiPath(apiName) {
|
|
3
5
|
let normalizedApiName = apiName.replace('/api/v{version}/', '').replaceAll('/', '_');
|
|
4
6
|
if (normalizedApiName.charAt(0) == '_') {
|
|
5
7
|
normalizedApiName = normalizedApiName.slice(1);
|
|
6
8
|
}
|
|
7
|
-
|
|
9
|
+
normalizedApiName = normalizedApiName.replace(/-([a-zA-Z])/g, (_, char) => char.toUpperCase());
|
|
10
|
+
normalizedApiName = this.toCamelCase(normalizedApiName);
|
|
11
|
+
normalizedApiName = this.toFirstLetterLowercase(normalizedApiName);
|
|
12
|
+
normalizedApiName = normalizedApiName.replaceAll('_', '');
|
|
13
|
+
return normalizedApiName;
|
|
8
14
|
}
|
|
9
15
|
static toFirstLetterLowercase(value) {
|
|
10
16
|
return value.charAt(0).toLowerCase() + value.slice(1);
|
|
@@ -12,9 +18,44 @@ export class Utils {
|
|
|
12
18
|
static toCamelCase(input) {
|
|
13
19
|
return input.replace(/_([a-zA-Z])/g, (_, letter) => letter.toUpperCase());
|
|
14
20
|
}
|
|
21
|
+
static toPascalCase(input) {
|
|
22
|
+
return input
|
|
23
|
+
.replace(/[_\-\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
|
|
24
|
+
.replace(/^(.)/, (_, c) => c.toUpperCase());
|
|
25
|
+
}
|
|
15
26
|
static isDate(schema) {
|
|
16
27
|
if (!schema)
|
|
17
28
|
return false;
|
|
18
29
|
return schema.type == 'string' && schema.format == 'date-time';
|
|
19
30
|
}
|
|
31
|
+
static toDartFileName(name) {
|
|
32
|
+
return name
|
|
33
|
+
.replace(/\./g, '_') // sostituisce i punti con underscore
|
|
34
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2') // aggiunge _ tra camelCase
|
|
35
|
+
.toLowerCase();
|
|
36
|
+
}
|
|
37
|
+
static toDartClassName(name) {
|
|
38
|
+
if (!name)
|
|
39
|
+
return undefined;
|
|
40
|
+
return name.replace(/\./g, ''); // rimuove i punti per ottenere PascalCase
|
|
41
|
+
}
|
|
42
|
+
static async ensureDirectorySync(dirPath) {
|
|
43
|
+
if (!fs.existsSync(dirPath)) {
|
|
44
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
static async clearDirectory(dirPath) {
|
|
48
|
+
if (!fs.existsSync(dirPath))
|
|
49
|
+
return;
|
|
50
|
+
for (const file of fs.readdirSync(dirPath)) {
|
|
51
|
+
const fullPath = path.join(dirPath, file);
|
|
52
|
+
const stat = fs.statSync(fullPath);
|
|
53
|
+
if (stat.isDirectory()) {
|
|
54
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
fs.unlinkSync(fullPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
20
61
|
}
|