@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.
Files changed (52) hide show
  1. package/.vscode/launch.json +6 -0
  2. package/README.md +4 -2
  3. package/autogen/identity/api/identity_api.dart +82 -0
  4. package/autogen/identity/models/auth_activate_command.dart +14 -0
  5. package/autogen/identity/models/auth_app_authenticate_command.dart +16 -0
  6. package/autogen/identity/models/auth_generate_reset_password_code_command.dart +15 -0
  7. package/autogen/identity/models/auth_refresh_token_command.dart +15 -0
  8. package/autogen/identity/models/auth_reset_password_command.dart +16 -0
  9. package/autogen/identity/models/auth_user_authenticate_command.dart +15 -0
  10. package/autogen/identity/models/auth_user_dto.dart +18 -0
  11. package/autogen/identity/models/auth_verify_reset_password_code_command.dart +14 -0
  12. package/autogen/identity/models/authentication_token.dart +17 -0
  13. package/autogen/mvc/models/problem_details.dart +17 -0
  14. package/autogen/service_defaults/models/application_exception.dart +14 -0
  15. package/autogen/service_defaults/models/result.dart +17 -0
  16. package/autogen/user_profile/api/user_profile_api.dart +46 -0
  17. package/autogen/user_profile/models/test_list_query.dart +13 -0
  18. package/autogen/user_profile/models/test_read_query.dart +13 -0
  19. package/autogen/user_profile/models/test_save_command.dart +13 -0
  20. package/autogen/user_profile/models/user_general_info_save_command.dart +13 -0
  21. package/dist/generator.js +63 -31
  22. package/dist/generators-writers/angular/api-angular-writer.js +1 -1
  23. package/dist/generators-writers/dart/api-dart-writer.js +110 -0
  24. package/dist/generators-writers/dart/model-dart-writer.js +124 -0
  25. package/dist/generators-writers/dart/models/import-definition-dart.js +1 -0
  26. package/dist/generators-writers/dart/normalizator.js +35 -0
  27. package/dist/generators-writers/nextjs/api-nextjs-writer.js +1 -1
  28. package/dist/generators-writers/utils.js +43 -2
  29. package/dist/index.js +72 -16
  30. package/dist/models/swagger/swagger-component-property.js +10 -0
  31. package/dist/models/swagger/swagger-component.js +1 -0
  32. package/dist/models/swagger/swagger-schema.js +1 -0
  33. package/package.json +11 -5
  34. package/src/generator.ts +67 -38
  35. package/src/generators-writers/angular/api-angular-writer.ts +1 -1
  36. package/src/generators-writers/dart/api-dart-writer.ts +164 -0
  37. package/src/generators-writers/dart/model-dart-writer.ts +176 -0
  38. package/src/generators-writers/dart/models/import-definition-dart.ts +6 -0
  39. package/src/generators-writers/dart/normalizator.ts +44 -0
  40. package/src/generators-writers/dart/templates/api.mustache +29 -0
  41. package/src/generators-writers/dart/templates/model.mustache +18 -0
  42. package/src/generators-writers/nextjs/api-nextjs-writer.ts +1 -1
  43. package/src/generators-writers/utils.ts +54 -2
  44. package/src/index.ts +80 -16
  45. package/src/models/api-dto.ts +1 -0
  46. package/src/models/model-dto.ts +1 -0
  47. package/src/models/swagger/swagger-component-property.ts +10 -9
  48. package/src/models/swagger/swagger-component.ts +11 -2
  49. package/src/models/swagger/swagger-schema.ts +18 -6
  50. package/src/models/swagger/swagger.ts +1 -0
  51. package/autogeneration/output/api.autogenerated.ts +0 -95
  52. 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
- _outputDirectory;
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, outputDirectory, outputFormat, dateLibrary) {
31
+ constructor(swagger, commandLineArgs) {
30
32
  this._swagger = swagger;
31
- this._outputDirectory = outputDirectory;
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._outputFormat == 'angular') {
134
- const apiWriter = new ApiAngularWriter(this._outputDirectory);
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._outputFormat == 'next') {
138
- const apiWriter = new ApiNextJsWriter(this._outputDirectory);
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
- this._barApis.update(this._apis.length, { message: `Api gerated` });
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._outputFormat == 'angular') {
147
- const apiWriter = new ModelAngularWriter(this._outputDirectory);
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._outputFormat == 'next') {
151
- const apiWriter = new ModelNextJsWriter(this._outputDirectory);
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: swaggerMethod.requestBody.content[contentTypeApplicationJson].schema.$ref.replace('#/components/schemas/', ''),
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: parameter.schema.$ref.replace('#/components/schemas/', ''),
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.$ref != null) {
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
- if (swaggerComponentProperty.type != null && swaggerComponentProperty.type == 'array')
306
- if (swaggerComponentProperty.items.$ref != null)
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
- else
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
- if (swaggerComponentProperty.type != null)
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
- if (swaggerComponentProperty.type == null)
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].$ref != null) {
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].type == 'array' && swaggerComponent.properties[propertyName].items.$ref != null) {
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._dateLibrary == 'moment' ? 'moment.Moment' : 'Date';
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.getApiNameNormalized(api.name);
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,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.getApiNameNormalized(api.name));
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 getApiNameNormalized(apiName) {
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
- return this.toFirstLetterLowercase(normalizedApiName);
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
  }