@devlearning/swagger-generator 1.1.16 → 1.1.18
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 +28 -28
- package/README-OLD.md +209 -209
- package/README.md +277 -277
- package/dist/api.constants.js +22 -22
- package/dist/generator.d.ts +4 -0
- package/dist/generator.js +118 -4
- package/dist/generators-writers/angular/api-angular-writer.js +38 -38
- package/dist/generators-writers/angular/constants.js +24 -24
- package/dist/generators-writers/angular/model-angular-writer.js +6 -6
- package/dist/generators-writers/dart/model-dart-writer.d.ts +1 -0
- package/dist/generators-writers/dart/model-dart-writer.js +15 -14
- package/dist/generators-writers/dart/templates/api.mustache +143 -143
- package/dist/generators-writers/dart/templates/enum.mustache +14 -14
- package/dist/generators-writers/dart/templates/model.mustache +20 -23
- package/dist/generators-writers/nextjs/api-nextjs-writer.js +12 -12
- package/dist/generators-writers/nextjs/constants.js +4 -4
- package/dist/generators-writers/nextjs/model-nextjs-writer.js +6 -6
- package/dist/models/swagger/swagger-component.d.ts +2 -2
- package/dist/models/swagger/swagger-schema.d.ts +1 -0
- package/package.json +49 -49
- package/src/api.constants.ts +26 -26
- package/src/generator-old.ts +449 -449
- package/src/generator.ts +752 -625
- package/src/generators-writers/angular/api-angular-writer.ts +187 -187
- package/src/generators-writers/angular/constants.ts +36 -36
- package/src/generators-writers/angular/model-angular-writer.ts +65 -65
- package/src/generators-writers/angular/normalizator.ts +41 -41
- package/src/generators-writers/dart/api-dart-writer.ts +303 -303
- package/src/generators-writers/dart/model-dart-writer.ts +212 -209
- package/src/generators-writers/dart/models/import-definition-dart.ts +5 -5
- package/src/generators-writers/dart/normalizator.ts +72 -72
- package/src/generators-writers/dart/templates/api.mustache +143 -143
- package/src/generators-writers/dart/templates/enum.mustache +14 -14
- package/src/generators-writers/dart/templates/model.mustache +20 -23
- package/src/generators-writers/nextjs/api-nextjs-writer.ts +157 -157
- package/src/generators-writers/nextjs/constants.ts +5 -5
- package/src/generators-writers/nextjs/model-nextjs-writer.ts +61 -61
- package/src/generators-writers/utils.ts +93 -93
- package/src/index.ts +103 -103
- package/src/models/api-dto.ts +17 -17
- package/src/models/enum-value-dto.ts +3 -3
- package/src/models/model-dto.ts +9 -9
- package/src/models/parameter-dto.ts +7 -7
- package/src/models/property-dto.ts +4 -4
- package/src/models/swagger/swagger-component-property.ts +11 -11
- package/src/models/swagger/swagger-component.ts +17 -17
- package/src/models/swagger/swagger-content.ts +4 -4
- package/src/models/swagger/swagger-info.ts +3 -3
- package/src/models/swagger/swagger-method.ts +7 -7
- package/src/models/swagger/swagger-schema.ts +21 -20
- package/src/models/swagger/swagger.ts +38 -38
- package/src/models/type-dto.ts +7 -7
- package/src/swagger-downloader.ts +46 -46
- package/src/utils/logger.ts +73 -73
- package/src/utils/swagger-validator.ts +89 -89
- package/tsconfig.json +33 -33
- package/dist/templates/api.mustache +0 -29
- package/dist/templates/model.mustache +0 -18
package/dist/generator.js
CHANGED
|
@@ -103,6 +103,18 @@ export class Generator {
|
|
|
103
103
|
for (let index = 0; index < Object.getOwnPropertyNames(this._swagger.components.schemas).length; index++) {
|
|
104
104
|
const modelName = Object.getOwnPropertyNames(this._swagger.components.schemas)[index];
|
|
105
105
|
const swaggerComponent = this._swagger.components.schemas[modelName];
|
|
106
|
+
// Flutter target: support enums of type string/integer and inline property enums.
|
|
107
|
+
if (this._commandLineArgs.target === TargetGeneration.Flutter) {
|
|
108
|
+
const isEnumSchema = swaggerComponent.enum != null && (swaggerComponent.type === 'string' || swaggerComponent.type === 'integer');
|
|
109
|
+
this._models.push({
|
|
110
|
+
typeName: modelName,
|
|
111
|
+
modelType: isEnumSchema ? 'enum' : 'class',
|
|
112
|
+
name: modelName,
|
|
113
|
+
properties: (swaggerComponent.type === 'object') ? this.retrieveComponentPropertiesFlutter(modelName, swaggerComponent) : [],
|
|
114
|
+
enumValues: isEnumSchema ? this.retrieveEnumValuesFlexible(swaggerComponent.enum) : [],
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
106
118
|
this._models.push({
|
|
107
119
|
typeName: modelName,
|
|
108
120
|
modelType: swaggerComponent.type == 'integer' ? 'enum' : 'class',
|
|
@@ -427,7 +439,7 @@ export class Generator {
|
|
|
427
439
|
let properties = [];
|
|
428
440
|
for (let index = 0; index < Object.getOwnPropertyNames(swaggerComponent.properties).length; index++) {
|
|
429
441
|
const propertyName = Object.getOwnPropertyNames(swaggerComponent.properties)[index];
|
|
430
|
-
const required = swaggerComponent.required && swaggerComponent.required.includes(propertyName);
|
|
442
|
+
const required = !!(swaggerComponent.required && swaggerComponent.required.includes(propertyName));
|
|
431
443
|
const type = this.retrieveType(swaggerComponent.properties[propertyName]);
|
|
432
444
|
properties.push({
|
|
433
445
|
...type,
|
|
@@ -437,6 +449,107 @@ export class Generator {
|
|
|
437
449
|
}
|
|
438
450
|
return properties;
|
|
439
451
|
}
|
|
452
|
+
retrieveComponentPropertiesFlutter(parentModelName, swaggerComponent) {
|
|
453
|
+
if (swaggerComponent.properties == null)
|
|
454
|
+
return [];
|
|
455
|
+
let properties = [];
|
|
456
|
+
for (let index = 0; index < Object.getOwnPropertyNames(swaggerComponent.properties).length; index++) {
|
|
457
|
+
const propertyName = Object.getOwnPropertyNames(swaggerComponent.properties)[index];
|
|
458
|
+
const required = !!(swaggerComponent.required && swaggerComponent.required.includes(propertyName));
|
|
459
|
+
const schema = swaggerComponent.properties[propertyName];
|
|
460
|
+
// Inline enum on property.
|
|
461
|
+
const inlineEnum = schema?.enum;
|
|
462
|
+
if (inlineEnum != null && (schema.type === 'string' || schema.type === 'integer')) {
|
|
463
|
+
const enumTypeName = `${parentModelName}${Utils.toPascalCase(propertyName)}`;
|
|
464
|
+
this.ensureEnumModel(enumTypeName, inlineEnum);
|
|
465
|
+
properties.push({
|
|
466
|
+
typeName: enumTypeName,
|
|
467
|
+
isTypeReference: true,
|
|
468
|
+
isNativeType: false,
|
|
469
|
+
nullable: required || (schema.nullable ?? false),
|
|
470
|
+
isArray: false,
|
|
471
|
+
isVoid: false,
|
|
472
|
+
name: propertyName,
|
|
473
|
+
});
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
// Array of enums.
|
|
477
|
+
if (schema?.type === 'array' && schema.items?.enum != null && (schema.items.type === 'string' || schema.items.type === 'integer')) {
|
|
478
|
+
const enumTypeName = `${parentModelName}${Utils.toPascalCase(propertyName)}Item`;
|
|
479
|
+
this.ensureEnumModel(enumTypeName, schema.items.enum);
|
|
480
|
+
properties.push({
|
|
481
|
+
typeName: enumTypeName,
|
|
482
|
+
isTypeReference: true,
|
|
483
|
+
isNativeType: false,
|
|
484
|
+
nullable: required || (schema.nullable ?? false),
|
|
485
|
+
isArray: true,
|
|
486
|
+
isVoid: false,
|
|
487
|
+
name: propertyName,
|
|
488
|
+
});
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
const type = this.retrieveType(schema);
|
|
492
|
+
properties.push({
|
|
493
|
+
...type,
|
|
494
|
+
name: propertyName,
|
|
495
|
+
nullable: required || type.nullable,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
return properties;
|
|
499
|
+
}
|
|
500
|
+
ensureEnumModel(typeName, enumValues) {
|
|
501
|
+
if (this._models.findIndex(m => m.typeName === typeName) !== -1)
|
|
502
|
+
return;
|
|
503
|
+
this._models.push({
|
|
504
|
+
typeName,
|
|
505
|
+
modelType: 'enum',
|
|
506
|
+
name: typeName,
|
|
507
|
+
properties: [],
|
|
508
|
+
enumValues: this.retrieveEnumValuesFlexible(enumValues),
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
retrieveEnumValuesFlexible(enumValues) {
|
|
512
|
+
if (enumValues == null)
|
|
513
|
+
return [];
|
|
514
|
+
const values = [];
|
|
515
|
+
for (let index = 0; index < enumValues.length; index++) {
|
|
516
|
+
const raw = enumValues[index];
|
|
517
|
+
if (raw == null)
|
|
518
|
+
continue;
|
|
519
|
+
// Legacy format: "NAME-1" (kept for backward compatibility)
|
|
520
|
+
const asString = String(raw);
|
|
521
|
+
if (asString.includes('-')) {
|
|
522
|
+
const parts = asString.split('-');
|
|
523
|
+
const namePart = parts[0]?.trim();
|
|
524
|
+
const valuePart = parts.slice(1).join('-').trim();
|
|
525
|
+
if (namePart && valuePart) {
|
|
526
|
+
values.push({
|
|
527
|
+
name: namePart,
|
|
528
|
+
value: valuePart,
|
|
529
|
+
});
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// Standard OpenAPI string/number enum values.
|
|
534
|
+
// Many APIs expose ALL_CAPS_UNDERSCORE values; normalize to lowerCamelCase.
|
|
535
|
+
const normalizedForName = asString.toLowerCase();
|
|
536
|
+
const enumCaseName = this.sanitizeEnumCaseName(Utils.toFirstLetterLowercase(Utils.toPascalCase(normalizedForName)));
|
|
537
|
+
const literal = typeof raw === 'number' ? String(raw) : JSON.stringify(asString);
|
|
538
|
+
values.push({
|
|
539
|
+
name: enumCaseName,
|
|
540
|
+
value: literal,
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
return values;
|
|
544
|
+
}
|
|
545
|
+
sanitizeEnumCaseName(name) {
|
|
546
|
+
if (!name)
|
|
547
|
+
return 'value';
|
|
548
|
+
// Dart identifiers cannot start with a digit.
|
|
549
|
+
if (/^\d/.test(name))
|
|
550
|
+
return `v${name}`;
|
|
551
|
+
return name;
|
|
552
|
+
}
|
|
440
553
|
retrieveSchemaProperties(schema) {
|
|
441
554
|
if (schema.properties == null)
|
|
442
555
|
return [];
|
|
@@ -459,9 +572,10 @@ export class Generator {
|
|
|
459
572
|
let values = [];
|
|
460
573
|
for (let index = 0; index < swaggerCopmponent.enum.length; index++) {
|
|
461
574
|
try {
|
|
575
|
+
const item = String(swaggerCopmponent.enum[index]);
|
|
462
576
|
values.push({
|
|
463
|
-
name:
|
|
464
|
-
value:
|
|
577
|
+
name: item.split('-')[0].trim(),
|
|
578
|
+
value: item.split('-')[1].trim(),
|
|
465
579
|
});
|
|
466
580
|
}
|
|
467
581
|
catch (error) {
|
|
@@ -498,7 +612,7 @@ export class Generator {
|
|
|
498
612
|
}
|
|
499
613
|
if (nestedUsedType != '' && usedTypes.findIndex(x => x.typeName == nestedUsedType) == -1) {
|
|
500
614
|
let nested = this._swagger.components.schemas[nestedUsedType];
|
|
501
|
-
const required = swaggerComponent.required && swaggerComponent.required.includes(propertyName);
|
|
615
|
+
const required = !!(swaggerComponent.required && swaggerComponent.required.includes(propertyName));
|
|
502
616
|
usedTypes.push({
|
|
503
617
|
typeName: nestedUsedType,
|
|
504
618
|
isTypeReference: nested.type == 'object',
|
|
@@ -27,14 +27,14 @@ export class ApiAngularWriter {
|
|
|
27
27
|
if (apiNameNormalized.includes('TicketFile')) {
|
|
28
28
|
debugger;
|
|
29
29
|
}
|
|
30
|
-
let apiString = `
|
|
31
|
-
public ${apiNameNormalized}(${parametersString}): Observable<${returnTypeString}> {
|
|
32
|
-
${queryParametersPreparation}${requestPreparation}return this._http.${method}<${returnTypeString}>(\`\${this._baseUrl}${api.url}${queryParameters}\`${haveRequest ? ', wrappedRequest' : ''}, ${httpOptions})
|
|
33
|
-
.pipe(
|
|
34
|
-
map(x => this._handleResponse(x)),
|
|
35
|
-
catchError((err, obs) => this._handleError(err, obs, skipErrorHandling))
|
|
36
|
-
);
|
|
37
|
-
}
|
|
30
|
+
let apiString = `
|
|
31
|
+
public ${apiNameNormalized}(${parametersString}): Observable<${returnTypeString}> {
|
|
32
|
+
${queryParametersPreparation}${requestPreparation}return this._http.${method}<${returnTypeString}>(\`\${this._baseUrl}${api.url}${queryParameters}\`${haveRequest ? ', wrappedRequest' : ''}, ${httpOptions})
|
|
33
|
+
.pipe(
|
|
34
|
+
map(x => this._handleResponse(x)),
|
|
35
|
+
catchError((err, obs) => this._handleError(err, obs, skipErrorHandling))
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
38
|
`;
|
|
39
39
|
return apiString;
|
|
40
40
|
}
|
|
@@ -68,21 +68,21 @@ export class ApiAngularWriter {
|
|
|
68
68
|
_queryParametersPreparationStatement(parameter) {
|
|
69
69
|
if (parameter.nullable) {
|
|
70
70
|
if (Utils.isDate(parameter.swaggerParameter?.schema)) {
|
|
71
|
-
return `let ${parameter.name}Param: string = ${parameter.name} != null && ${parameter.name} != undefined && ${parameter.name}.isValid() ? encodeURIComponent(this._momentToString(${parameter.name})) : '';
|
|
71
|
+
return `let ${parameter.name}Param: string = ${parameter.name} != null && ${parameter.name} != undefined && ${parameter.name}.isValid() ? encodeURIComponent(this._momentToString(${parameter.name})) : '';
|
|
72
72
|
`;
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
|
-
return `let ${parameter.name}Param: string = ${parameter.name} != null && ${parameter.name} != undefined ? encodeURIComponent('' + ${parameter.name}) : '';
|
|
75
|
+
return `let ${parameter.name}Param: string = ${parameter.name} != null && ${parameter.name} != undefined ? encodeURIComponent('' + ${parameter.name}) : '';
|
|
76
76
|
`;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
80
80
|
if (Utils.isDate(parameter.swaggerParameter?.schema)) {
|
|
81
|
-
return `let ${parameter.name}Param: string = encodeURIComponent(this._momentToString(${parameter.name}));
|
|
81
|
+
return `let ${parameter.name}Param: string = encodeURIComponent(this._momentToString(${parameter.name}));
|
|
82
82
|
`;
|
|
83
83
|
}
|
|
84
84
|
else {
|
|
85
|
-
return `let ${parameter.name}Param: string = encodeURIComponent('' + ${parameter.name});
|
|
85
|
+
return `let ${parameter.name}Param: string = encodeURIComponent('' + ${parameter.name});
|
|
86
86
|
`;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -111,44 +111,44 @@ export class ApiAngularWriter {
|
|
|
111
111
|
return '';
|
|
112
112
|
}
|
|
113
113
|
if (api.isMultiPart) {
|
|
114
|
-
return `let wrappedRequest = this._handleMultipart(request);
|
|
114
|
+
return `let wrappedRequest = this._handleMultipart(request);
|
|
115
115
|
`;
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
118
|
-
return `let wrappedRequest = this._handleRequest(request);
|
|
118
|
+
return `let wrappedRequest = this._handleRequest(request);
|
|
119
119
|
`;
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
_writeFile(apis) {
|
|
123
123
|
const className = this._commandLineArgs.apiClientName || 'ApiAutogeneratedService';
|
|
124
124
|
const apiPre = this._getApiPre(className);
|
|
125
|
-
fs.writeFileSync(this._commandLineArgs.outputDirectory + "/api.autogenerated.ts", `${apiPre}
|
|
126
|
-
${apis}
|
|
125
|
+
fs.writeFileSync(this._commandLineArgs.outputDirectory + "/api.autogenerated.ts", `${apiPre}
|
|
126
|
+
${apis}
|
|
127
127
|
${API_POST}`, { flag: 'w' });
|
|
128
128
|
}
|
|
129
129
|
_getApiPre(className) {
|
|
130
|
-
return `import { HttpClient } from '@angular/common/http';
|
|
131
|
-
import { Observable, catchError, map } from 'rxjs';
|
|
132
|
-
import * as Models from './model.autogenerated';
|
|
133
|
-
import { HttpHeaders } from "@angular/common/http";
|
|
134
|
-
|
|
135
|
-
export const httpOptions = {
|
|
136
|
-
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export const httpOptionsMultipart = {};
|
|
140
|
-
|
|
141
|
-
export abstract class ${className} {
|
|
142
|
-
constructor(
|
|
143
|
-
public _http: HttpClient,
|
|
144
|
-
public _baseUrl: string,
|
|
145
|
-
) { }
|
|
146
|
-
|
|
147
|
-
protected abstract _momentToString(moment: moment.Moment): string;
|
|
148
|
-
protected abstract _handleRequest<T>(request: T): T;
|
|
149
|
-
protected abstract _handleMultipart<T>(request: T): FormData;
|
|
150
|
-
protected abstract _handleResponse<T>(response: T): T;
|
|
151
|
-
protected abstract _handleError(error: any, obs: any): Observable<never>;
|
|
130
|
+
return `import { HttpClient } from '@angular/common/http';
|
|
131
|
+
import { Observable, catchError, map } from 'rxjs';
|
|
132
|
+
import * as Models from './model.autogenerated';
|
|
133
|
+
import { HttpHeaders } from "@angular/common/http";
|
|
134
|
+
|
|
135
|
+
export const httpOptions = {
|
|
136
|
+
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const httpOptionsMultipart = {};
|
|
140
|
+
|
|
141
|
+
export abstract class ${className} {
|
|
142
|
+
constructor(
|
|
143
|
+
public _http: HttpClient,
|
|
144
|
+
public _baseUrl: string,
|
|
145
|
+
) { }
|
|
146
|
+
|
|
147
|
+
protected abstract _momentToString(moment: moment.Moment): string;
|
|
148
|
+
protected abstract _handleRequest<T>(request: T): T;
|
|
149
|
+
protected abstract _handleMultipart<T>(request: T): FormData;
|
|
150
|
+
protected abstract _handleResponse<T>(response: T): T;
|
|
151
|
+
protected abstract _handleError(error: any, obs: any): Observable<never>;
|
|
152
152
|
`;
|
|
153
153
|
}
|
|
154
154
|
}
|
|
@@ -1,28 +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<T>(error: any, obs: Observable<T>, skipErrorHandling: boolean): Observable<never>;
|
|
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<T>(error: any, obs: Observable<T>, skipErrorHandling: boolean): Observable<never>;
|
|
23
23
|
`;
|
|
24
24
|
export const API_POST = `}`;
|
|
25
|
-
export const MODEL_PRE = `import * as moment from 'moment';
|
|
25
|
+
export const MODEL_PRE = `import * as moment from 'moment';
|
|
26
26
|
`;
|
|
27
|
-
export const MODEL_POST = `
|
|
27
|
+
export const MODEL_POST = `
|
|
28
28
|
`;
|
|
@@ -15,10 +15,10 @@ export class ModelAngularWriter {
|
|
|
15
15
|
this._writeFile(modelString);
|
|
16
16
|
}
|
|
17
17
|
_modelString(model) {
|
|
18
|
-
let modelString = `
|
|
19
|
-
export ${model.modelType} ${Utils.toPascalCase(model.name)} {
|
|
20
|
-
${this._properties(model)}${this._enumValues(model)}
|
|
21
|
-
}
|
|
18
|
+
let modelString = `
|
|
19
|
+
export ${model.modelType} ${Utils.toPascalCase(model.name)} {
|
|
20
|
+
${this._properties(model)}${this._enumValues(model)}
|
|
21
|
+
}
|
|
22
22
|
`;
|
|
23
23
|
return modelString;
|
|
24
24
|
}
|
|
@@ -41,8 +41,8 @@ ${this._properties(model)}${this._enumValues(model)}
|
|
|
41
41
|
return enumValuesString.trimEnd();
|
|
42
42
|
}
|
|
43
43
|
_writeFile(models) {
|
|
44
|
-
fs.writeFileSync(this._outputDirectory + "/model.autogenerated.ts", `${MODEL_PRE}
|
|
45
|
-
${models}
|
|
44
|
+
fs.writeFileSync(this._outputDirectory + "/model.autogenerated.ts", `${MODEL_PRE}
|
|
45
|
+
${models}
|
|
46
46
|
${MODEL_POST}`, { flag: 'w' });
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -47,28 +47,16 @@ export class ModelDartWriter {
|
|
|
47
47
|
var fieldTypeName = Normalizator.mapTsTypeToDart(property.typeName);
|
|
48
48
|
fieldTypeName = Normalizator.getNormalizedTypeName(fieldTypeName);
|
|
49
49
|
const isFileField = property.typeName === 'File';
|
|
50
|
-
const isFileArrayField = isFileField && property.isArray === true;
|
|
51
50
|
const jsonKeyAnnotation = isFileField
|
|
52
51
|
? "@JsonKey(includeFromJson: false, includeToJson: false)"
|
|
53
52
|
: undefined;
|
|
54
|
-
const defaultAnnotation = isFileArrayField
|
|
55
|
-
? "@Default(<File>[])"
|
|
56
|
-
: undefined;
|
|
57
|
-
// File fields are excluded from JSON serialization; they must not be `required` for fromJson.
|
|
58
|
-
const nullable = isFileField && !property.isArray
|
|
59
|
-
? '?'
|
|
60
|
-
: (property.nullable && !property.isArray ? '?' : '');
|
|
61
|
-
const required = isFileField
|
|
62
|
-
? ''
|
|
63
|
-
: (property.nullable && !property.isArray ? '' : 'required ');
|
|
64
53
|
dartModel.fields.push({
|
|
65
54
|
name: property.name,
|
|
66
55
|
type: property.isArray ? `List<${fieldTypeName}>` : fieldTypeName,
|
|
67
56
|
typeName: property.typeName,
|
|
68
|
-
nullable,
|
|
69
|
-
required,
|
|
57
|
+
nullable: property.nullable && !property.isArray ? '?' : '',
|
|
58
|
+
required: property.nullable && !property.isArray ? '' : 'required ',
|
|
70
59
|
jsonKeyAnnotation,
|
|
71
|
-
defaultAnnotation,
|
|
72
60
|
});
|
|
73
61
|
if (property.isTypeReference) {
|
|
74
62
|
if (imports.findIndex(x => x.type.typeName == property.typeName) == -1) {
|
|
@@ -104,10 +92,12 @@ export class ModelDartWriter {
|
|
|
104
92
|
}
|
|
105
93
|
models.forEach(model => {
|
|
106
94
|
const normalizedInfo = Normalizator.getNormalizedInfo(model);
|
|
95
|
+
const valueType = this._inferDartEnumValueType(model.enumValues);
|
|
107
96
|
const dartModel = {
|
|
108
97
|
enumName: normalizedInfo.modelName,
|
|
109
98
|
path: this._commandLineArgs.outputDirectory,
|
|
110
99
|
fields: [],
|
|
100
|
+
valueType,
|
|
111
101
|
};
|
|
112
102
|
model.enumValues.forEach(enumItem => {
|
|
113
103
|
dartModel.fields.push({
|
|
@@ -124,6 +114,17 @@ export class ModelDartWriter {
|
|
|
124
114
|
writeFileSync(`${destinationPath}/${normalizedInfo.filename}.dart`, result, 'utf-8');
|
|
125
115
|
});
|
|
126
116
|
}
|
|
117
|
+
_inferDartEnumValueType(enumValues) {
|
|
118
|
+
// If values are unquoted and numeric, assume int; otherwise String.
|
|
119
|
+
// Generator will quote string enums using JSON.stringify ("...").
|
|
120
|
+
if (!enumValues || enumValues.length === 0)
|
|
121
|
+
return 'String';
|
|
122
|
+
const allNumeric = enumValues.every(v => {
|
|
123
|
+
const trimmed = (v.value ?? '').trim();
|
|
124
|
+
return /^-?\d+$/.test(trimmed);
|
|
125
|
+
});
|
|
126
|
+
return allNumeric ? 'int' : 'String';
|
|
127
|
+
}
|
|
127
128
|
_buildImportPath(importDirectory, subPath, filename) {
|
|
128
129
|
// Rimuove slash iniziali e finali da ogni parte
|
|
129
130
|
const parts = [importDirectory, subPath]
|