@devlearning/swagger-generator 1.1.21 → 1.1.23

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 (56) hide show
  1. package/.vscode/launch.json +28 -28
  2. package/README-OLD.md +209 -209
  3. package/README.md +277 -277
  4. package/dist/api.constants.d.ts +1 -1
  5. package/dist/api.constants.js +22 -22
  6. package/dist/generators-writers/angular/api-angular-writer.js +38 -38
  7. package/dist/generators-writers/angular/constants.js +24 -24
  8. package/dist/generators-writers/angular/model-angular-writer.js +6 -6
  9. package/dist/generators-writers/dart/model-dart-writer.js +11 -4
  10. package/dist/generators-writers/dart/templates/api.mustache +143 -143
  11. package/dist/generators-writers/dart/templates/enum.mustache +14 -14
  12. package/dist/generators-writers/dart/templates/model.mustache +23 -23
  13. package/dist/generators-writers/nextjs/api-nextjs-writer.js +12 -12
  14. package/dist/generators-writers/nextjs/constants.js +4 -4
  15. package/dist/generators-writers/nextjs/model-nextjs-writer.js +6 -6
  16. package/dist/generators-writers/utils.d.ts +1 -0
  17. package/dist/generators-writers/utils.js +16 -4
  18. package/dist/templates/api.mustache +29 -0
  19. package/dist/templates/model.mustache +18 -0
  20. package/package.json +49 -49
  21. package/src/api.constants.ts +26 -26
  22. package/src/generator-old.ts +449 -449
  23. package/src/generator.ts +752 -752
  24. package/src/generators-writers/angular/api-angular-writer.ts +187 -187
  25. package/src/generators-writers/angular/constants.ts +36 -36
  26. package/src/generators-writers/angular/model-angular-writer.ts +65 -65
  27. package/src/generators-writers/angular/normalizator.ts +41 -41
  28. package/src/generators-writers/dart/api-dart-writer.ts +303 -303
  29. package/src/generators-writers/dart/model-dart-writer.ts +226 -219
  30. package/src/generators-writers/dart/models/import-definition-dart.ts +5 -5
  31. package/src/generators-writers/dart/normalizator.ts +72 -72
  32. package/src/generators-writers/dart/templates/api.mustache +143 -143
  33. package/src/generators-writers/dart/templates/enum.mustache +14 -14
  34. package/src/generators-writers/dart/templates/model.mustache +23 -23
  35. package/src/generators-writers/nextjs/api-nextjs-writer.ts +157 -157
  36. package/src/generators-writers/nextjs/constants.ts +5 -5
  37. package/src/generators-writers/nextjs/model-nextjs-writer.ts +61 -61
  38. package/src/generators-writers/utils.ts +111 -93
  39. package/src/index.ts +103 -103
  40. package/src/models/api-dto.ts +17 -17
  41. package/src/models/enum-value-dto.ts +3 -3
  42. package/src/models/model-dto.ts +9 -9
  43. package/src/models/parameter-dto.ts +7 -7
  44. package/src/models/property-dto.ts +4 -4
  45. package/src/models/swagger/swagger-component-property.ts +11 -11
  46. package/src/models/swagger/swagger-component.ts +17 -17
  47. package/src/models/swagger/swagger-content.ts +4 -4
  48. package/src/models/swagger/swagger-info.ts +3 -3
  49. package/src/models/swagger/swagger-method.ts +7 -7
  50. package/src/models/swagger/swagger-schema.ts +21 -21
  51. package/src/models/swagger/swagger.ts +38 -38
  52. package/src/models/type-dto.ts +7 -7
  53. package/src/swagger-downloader.ts +46 -46
  54. package/src/utils/logger.ts +73 -73
  55. package/src/utils/swagger-validator.ts +89 -89
  56. package/tsconfig.json +33 -33
@@ -1,304 +1,304 @@
1
- import fs, { writeFileSync } from 'fs';
2
- import { ApiDto } from '../../models/api-dto.js';
3
- import { Utils } from '../utils.js';
4
- import { ParameterDto } from '../../models/parameter-dto.js';
5
- import Mustache from 'mustache';
6
- import { CommandLineArgs } from '../../index.js';
7
- import { ModelDto } from '../../models/model-dto.js';
8
- import { TypeDto } from '../../models/type-dto.js';
9
- import { ImportDefinitionDart } from './models/import-definition-dart.js';
10
- import { Normalizator } from './normalizator.js';
11
- import path from 'path';
12
- import { fileURLToPath } from 'url';
13
- import { logger } from '../../utils/logger.js';
14
-
15
- interface ApiDefinitionDart {
16
- package: string;
17
- outputDirectory: string;
18
- filename: string;
19
- apiClassName: string;
20
- imports: string[];
21
- endpoints: EndpointDefinitionDart[];
22
- }
23
-
24
- interface EndpointDefinitionDart {
25
- methodName: string;
26
- httpMethod: HttpMethodDart;
27
- path: string;
28
- responseType: string;
29
- isResponseNativeType: boolean;
30
- haveRequest: boolean;
31
- requestType?: string; // solo se haveRequest è true
32
- queryParams?: Parameter[],
33
- pathParams?: Parameter[],
34
- isMultiPart: boolean;
35
- multipartFields?: MultipartFieldDefinitionDart[];
36
- }
37
-
38
- interface MultipartFieldDefinitionDart {
39
- name: string;
40
- isFile: boolean;
41
- isArray: boolean;
42
- nullable: boolean;
43
- }
44
-
45
- interface Parameter {
46
- name: string;
47
- type: string; // "string", "int", ecc
48
- nullable: boolean;
49
- }
50
-
51
- type HttpMethodDart = 'get' | 'post' | 'put' | 'delete' | 'patch';
52
-
53
-
54
- export class ApiDartWriter {
55
- private _commandLineArgs: CommandLineArgs;
56
-
57
- constructor(commandLineArgs: CommandLineArgs) {
58
- this._commandLineArgs = commandLineArgs;
59
- }
60
-
61
- write(apis: ApiDto[], models: ModelDto[]) {
62
- const __filename = fileURLToPath(import.meta.url);
63
- const __dirname = path.dirname(__filename);
64
- const templatePath = path.join(__dirname, 'templates', 'api.mustache');
65
- const template = fs.readFileSync(templatePath, 'utf-8');
66
- let importDirectory = this._commandLineArgs.outputDirectory;
67
- if (importDirectory.startsWith('lib/')) {
68
- importDirectory = importDirectory.slice('lib/'.length);
69
- }
70
-
71
- // Se è specificato apiClientName, genera una singola classe unificata
72
- if (this._commandLineArgs.apiClientName) {
73
- this._writeUnifiedApi(apis, models, template, importDirectory);
74
- } else {
75
- // Altrimenti suddividi per tag come prima
76
- this._writeApisByTag(apis, models, template, importDirectory);
77
- }
78
- }
79
-
80
- private _writeUnifiedApi(apis: ApiDto[], models: ModelDto[], template: string, importDirectory: string) {
81
- const apiClassName = this._commandLineArgs.apiClientName!;
82
- const filename = Utils.toDartFileName(apiClassName);
83
-
84
- console.log(`Api: Unified API Client - ${apiClassName}`);
85
-
86
- var apiDefinition = <ApiDefinitionDart>{
87
- package: this._commandLineArgs.package,
88
- outputDirectory: this._commandLineArgs.outputDirectory,
89
- filename: filename,
90
- apiClassName: apiClassName,
91
- }
92
-
93
- var endpoints = <EndpointDefinitionDart[]>[];
94
- var imports = <ImportDefinitionDart[]>[];
95
-
96
- // Processa tutte le API senza raggruppamento
97
- for (const api of apis) {
98
- const endpointData = this._createEndpoint(api, models, imports, importDirectory);
99
- endpoints.push(endpointData.endpoint);
100
- }
101
-
102
- apiDefinition.endpoints = endpoints;
103
- apiDefinition.imports = imports.map(i => i.import);
104
-
105
- let destinationPath = `${this._commandLineArgs.outputDirectory}/api`;
106
-
107
- Utils.ensureDirectorySync(`${destinationPath}`);
108
-
109
- var result = Mustache.render(template, apiDefinition);
110
- writeFileSync(`${destinationPath}/${apiDefinition.filename}.dart`, result, 'utf-8');
111
- }
112
-
113
- private _writeApisByTag(apis: ApiDto[], models: ModelDto[], template: string, importDirectory: string) {
114
- const grouped = this._groupByTag(apis);
115
-
116
- for (const [tag, apis] of Object.entries(grouped)) {
117
- logger.progress(`Generating Dart API: ${tag}`);
118
-
119
- let subPath = '';
120
- let filename = '';
121
- let apiClassName = '';
122
-
123
- subPath = Utils.toDartFileName(tag);
124
- filename = `${Utils.toDartFileName(tag + 'Api')}`;
125
- apiClassName = `${Utils.toDartClassName(tag + 'Api')}`;
126
-
127
- var apiDefinition = <ApiDefinitionDart>{
128
- package: this._commandLineArgs.package,
129
- outputDirectory: this._commandLineArgs.outputDirectory,
130
- filename: filename,
131
- apiClassName: apiClassName,
132
- }
133
-
134
- var endpoints = <EndpointDefinitionDart[]>[];
135
- var imports = <ImportDefinitionDart[]>[];
136
-
137
- for (const api of apis) {
138
- const endpointData = this._createEndpoint(api, models, imports, importDirectory, tag);
139
- endpoints.push(endpointData.endpoint);
140
- }
141
-
142
- apiDefinition.endpoints = endpoints;
143
- apiDefinition.imports = imports.map(i => i.import);
144
-
145
- let destinationPath = `${this._commandLineArgs.outputDirectory}/${subPath}/api`;
146
-
147
- Utils.ensureDirectorySync(`${destinationPath}`);
148
-
149
- var result = Mustache.render(template, apiDefinition);
150
- writeFileSync(`${destinationPath}/${apiDefinition.filename}.dart`, result, 'utf-8');
151
- }
152
- }
153
-
154
- private _createEndpoint(api: ApiDto, models: ModelDto[], imports: ImportDefinitionDart[], importDirectory: string, tag?: string): { endpoint: EndpointDefinitionDart } {
155
- var requestType: string | undefined = undefined;
156
- requestType = api.haveRequest ? api.parameters[0]?.typeName || 'void' : undefined;
157
- requestType = requestType?.split('.').pop()!
158
- requestType = Utils.toDartClassName(requestType);
159
-
160
- var responseType: string = 'void';
161
- responseType = api.returnType ? api.returnType.typeName : 'void';
162
- responseType = responseType?.split('.').pop()!;
163
- if (api.returnType?.isNativeType) {
164
- responseType = Normalizator.mapTsTypeToDart(responseType);
165
- } else {
166
- responseType = Utils.toDartClassName(responseType) ?? responseType;
167
- }
168
-
169
- var methodName = Utils.getNormalizedApiPathDart(api.name);
170
- if (tag && methodName.startsWith(Utils.toFirstLetterLowercase(tag))) {
171
- methodName = methodName.slice(tag.length);
172
- methodName = Utils.toFirstLetterLowercase(methodName);
173
- }
174
-
175
- // console.debug(`\tAPI - ${apiName} - ${apiMethod}`);
176
- if (methodName.toLowerCase().indexOf("productsave") >= 0) {
177
- debugger
178
- }
179
-
180
- const pathParams: Parameter[] = (api.parameters ?? [])
181
- .filter(p => p.name !== 'request' && p.isQuery === false)
182
- .map(p => ({
183
- name: p.name,
184
- type: p.typeName ? Normalizator.mapTsTypeToDart(p.typeName)! : 'String',
185
- nullable: false,
186
- }));
187
-
188
- // Build a Dart-interpolated path string (e.g. '/x/{id}' -> '/x/$id')
189
- const pathExpression = api.url.replace(/\{([^}]+)\}/g, (_, rawName) => {
190
- const varName = Utils.toFirstLetterLowercase(rawName);
191
- return `\$${varName}`;
192
- });
193
-
194
- const endpoint = <EndpointDefinitionDart>{
195
- methodName: methodName,
196
- httpMethod: api.method.toLowerCase() as HttpMethodDart,
197
- path: pathExpression,
198
- responseType: responseType,
199
- isResponseNativeType: api.returnType ? api.returnType.isNativeType : true,
200
- haveRequest: api.haveRequest,
201
- requestType: requestType,
202
- pathParams,
203
- isMultiPart: api.isMultiPart === true,
204
- };
205
-
206
- if (api.parameters && api.parameters.length > 0 && !api.haveRequest) {
207
- endpoint.queryParams = api.parameters
208
- .filter(p => p.isQuery === true)
209
- .map(p => ({
210
- name: p.name,
211
- type: p.typeName ? Normalizator.mapTsTypeToDart(p.typeName)! : 'String',
212
- nullable: p.nullable
213
- }));
214
- }
215
-
216
- if (api.haveRequest && api.parameters[0]?.typeName) {
217
- if (imports.findIndex(x => x.type.typeName == api.parameters[0]?.typeName) == -1) {
218
- models.forEach(model => {
219
- if (model.typeName === api.parameters[0]?.typeName) {
220
- const normalizedInfo = Normalizator.getNormalizedInfo(model);
221
- const importPath = this._buildImportPath(importDirectory, normalizedInfo.subPath, normalizedInfo.filename);
222
- imports.push({
223
- type: api.parameters[0],
224
- import: `import 'package:${this._commandLineArgs.package}/${importPath}';`
225
- });
226
- }
227
- });
228
- }
229
- }
230
-
231
- // Multipart: include request model fields so template can build FormData
232
- if (endpoint.isMultiPart && api.haveRequest && api.parameters[0]?.typeName) {
233
- const requestModelTypeName = api.parameters[0].typeName;
234
- const requestModel = models.find(m => m.typeName === requestModelTypeName);
235
- if (requestModel) {
236
- endpoint.multipartFields = requestModel.properties.map(p => ({
237
- name: p.name,
238
- isFile: p.typeName === 'File',
239
- isArray: p.isArray === true,
240
- nullable: p.nullable === true,
241
- }));
242
- } else {
243
- endpoint.multipartFields = [];
244
- }
245
- }
246
-
247
- if (api.returnType && !api.returnType.isNativeType) {
248
- if (imports.findIndex(x => x.type.typeName == api.returnType!.typeName) == -1) {
249
- models.forEach(model => {
250
- if (model.typeName === api.returnType!.typeName) {
251
- const normalizedInfo = Normalizator.getNormalizedInfo(model);
252
- const importPath = this._buildImportPath(importDirectory, normalizedInfo.subPath, normalizedInfo.filename);
253
- imports.push({
254
- type: api.returnType!,
255
- import: `import 'package:${this._commandLineArgs.package}/${importPath}';`
256
- });
257
- }
258
- });
259
- }
260
- }
261
-
262
- return { endpoint };
263
- }
264
-
265
- private _buildImportPath(importDirectory: string, subPath: string, filename: string): string {
266
- // Rimuove slash iniziali e finali da ogni parte
267
- const parts = [importDirectory, subPath]
268
- .filter(p => p && p.length > 0)
269
- .map(p => p.replace(/^\/+|\/+$/g, ''));
270
-
271
- // Aggiunge il filename alla fine
272
- parts.push(`${filename}.dart`);
273
-
274
- // Unisce con un singolo slash
275
- return parts.join('/');
276
- }
277
-
278
- private _toPascalCase(input: string): string {
279
- return input
280
- .replace(/[_\- ]+/g, ' ') // sostituisce underscore, dash e spazi con uno spazio singolo
281
- .trim() // rimuove spazi iniziali/finali
282
- .split(' ') // divide in parole
283
- .map(word =>
284
- word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
285
- )
286
- .join('');
287
- }
288
-
289
- private _normalizeApiClassName(input: string): string {
290
- return input
291
- .replace(/\./g, '');
292
- }
293
-
294
- private _groupByTag(apis: ApiDto[]) {
295
- const groupedByRole = apis.reduce<Record<string, ApiDto[]>>((acc, api) => {
296
- if (!acc[api.tag]) {
297
- acc[api.tag] = [];
298
- }
299
- acc[api.tag].push(api);
300
- return acc;
301
- }, {});
302
- return groupedByRole;
303
- }
1
+ import fs, { writeFileSync } from 'fs';
2
+ import { ApiDto } from '../../models/api-dto.js';
3
+ import { Utils } from '../utils.js';
4
+ import { ParameterDto } from '../../models/parameter-dto.js';
5
+ import Mustache from 'mustache';
6
+ import { CommandLineArgs } from '../../index.js';
7
+ import { ModelDto } from '../../models/model-dto.js';
8
+ import { TypeDto } from '../../models/type-dto.js';
9
+ import { ImportDefinitionDart } from './models/import-definition-dart.js';
10
+ import { Normalizator } from './normalizator.js';
11
+ import path from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { logger } from '../../utils/logger.js';
14
+
15
+ interface ApiDefinitionDart {
16
+ package: string;
17
+ outputDirectory: string;
18
+ filename: string;
19
+ apiClassName: string;
20
+ imports: string[];
21
+ endpoints: EndpointDefinitionDart[];
22
+ }
23
+
24
+ interface EndpointDefinitionDart {
25
+ methodName: string;
26
+ httpMethod: HttpMethodDart;
27
+ path: string;
28
+ responseType: string;
29
+ isResponseNativeType: boolean;
30
+ haveRequest: boolean;
31
+ requestType?: string; // solo se haveRequest è true
32
+ queryParams?: Parameter[],
33
+ pathParams?: Parameter[],
34
+ isMultiPart: boolean;
35
+ multipartFields?: MultipartFieldDefinitionDart[];
36
+ }
37
+
38
+ interface MultipartFieldDefinitionDart {
39
+ name: string;
40
+ isFile: boolean;
41
+ isArray: boolean;
42
+ nullable: boolean;
43
+ }
44
+
45
+ interface Parameter {
46
+ name: string;
47
+ type: string; // "string", "int", ecc
48
+ nullable: boolean;
49
+ }
50
+
51
+ type HttpMethodDart = 'get' | 'post' | 'put' | 'delete' | 'patch';
52
+
53
+
54
+ export class ApiDartWriter {
55
+ private _commandLineArgs: CommandLineArgs;
56
+
57
+ constructor(commandLineArgs: CommandLineArgs) {
58
+ this._commandLineArgs = commandLineArgs;
59
+ }
60
+
61
+ write(apis: ApiDto[], models: ModelDto[]) {
62
+ const __filename = fileURLToPath(import.meta.url);
63
+ const __dirname = path.dirname(__filename);
64
+ const templatePath = path.join(__dirname, 'templates', 'api.mustache');
65
+ const template = fs.readFileSync(templatePath, 'utf-8');
66
+ let importDirectory = this._commandLineArgs.outputDirectory;
67
+ if (importDirectory.startsWith('lib/')) {
68
+ importDirectory = importDirectory.slice('lib/'.length);
69
+ }
70
+
71
+ // Se è specificato apiClientName, genera una singola classe unificata
72
+ if (this._commandLineArgs.apiClientName) {
73
+ this._writeUnifiedApi(apis, models, template, importDirectory);
74
+ } else {
75
+ // Altrimenti suddividi per tag come prima
76
+ this._writeApisByTag(apis, models, template, importDirectory);
77
+ }
78
+ }
79
+
80
+ private _writeUnifiedApi(apis: ApiDto[], models: ModelDto[], template: string, importDirectory: string) {
81
+ const apiClassName = this._commandLineArgs.apiClientName!;
82
+ const filename = Utils.toDartFileName(apiClassName);
83
+
84
+ console.log(`Api: Unified API Client - ${apiClassName}`);
85
+
86
+ var apiDefinition = <ApiDefinitionDart>{
87
+ package: this._commandLineArgs.package,
88
+ outputDirectory: this._commandLineArgs.outputDirectory,
89
+ filename: filename,
90
+ apiClassName: apiClassName,
91
+ }
92
+
93
+ var endpoints = <EndpointDefinitionDart[]>[];
94
+ var imports = <ImportDefinitionDart[]>[];
95
+
96
+ // Processa tutte le API senza raggruppamento
97
+ for (const api of apis) {
98
+ const endpointData = this._createEndpoint(api, models, imports, importDirectory);
99
+ endpoints.push(endpointData.endpoint);
100
+ }
101
+
102
+ apiDefinition.endpoints = endpoints;
103
+ apiDefinition.imports = imports.map(i => i.import);
104
+
105
+ let destinationPath = `${this._commandLineArgs.outputDirectory}/api`;
106
+
107
+ Utils.ensureDirectorySync(`${destinationPath}`);
108
+
109
+ var result = Mustache.render(template, apiDefinition);
110
+ writeFileSync(`${destinationPath}/${apiDefinition.filename}.dart`, result, 'utf-8');
111
+ }
112
+
113
+ private _writeApisByTag(apis: ApiDto[], models: ModelDto[], template: string, importDirectory: string) {
114
+ const grouped = this._groupByTag(apis);
115
+
116
+ for (const [tag, apis] of Object.entries(grouped)) {
117
+ logger.progress(`Generating Dart API: ${tag}`);
118
+
119
+ let subPath = '';
120
+ let filename = '';
121
+ let apiClassName = '';
122
+
123
+ subPath = Utils.toDartFileName(tag);
124
+ filename = `${Utils.toDartFileName(tag + 'Api')}`;
125
+ apiClassName = `${Utils.toDartClassName(tag + 'Api')}`;
126
+
127
+ var apiDefinition = <ApiDefinitionDart>{
128
+ package: this._commandLineArgs.package,
129
+ outputDirectory: this._commandLineArgs.outputDirectory,
130
+ filename: filename,
131
+ apiClassName: apiClassName,
132
+ }
133
+
134
+ var endpoints = <EndpointDefinitionDart[]>[];
135
+ var imports = <ImportDefinitionDart[]>[];
136
+
137
+ for (const api of apis) {
138
+ const endpointData = this._createEndpoint(api, models, imports, importDirectory, tag);
139
+ endpoints.push(endpointData.endpoint);
140
+ }
141
+
142
+ apiDefinition.endpoints = endpoints;
143
+ apiDefinition.imports = imports.map(i => i.import);
144
+
145
+ let destinationPath = `${this._commandLineArgs.outputDirectory}/${subPath}/api`;
146
+
147
+ Utils.ensureDirectorySync(`${destinationPath}`);
148
+
149
+ var result = Mustache.render(template, apiDefinition);
150
+ writeFileSync(`${destinationPath}/${apiDefinition.filename}.dart`, result, 'utf-8');
151
+ }
152
+ }
153
+
154
+ private _createEndpoint(api: ApiDto, models: ModelDto[], imports: ImportDefinitionDart[], importDirectory: string, tag?: string): { endpoint: EndpointDefinitionDart } {
155
+ var requestType: string | undefined = undefined;
156
+ requestType = api.haveRequest ? api.parameters[0]?.typeName || 'void' : undefined;
157
+ requestType = requestType?.split('.').pop()!
158
+ requestType = Utils.toDartClassName(requestType);
159
+
160
+ var responseType: string = 'void';
161
+ responseType = api.returnType ? api.returnType.typeName : 'void';
162
+ responseType = responseType?.split('.').pop()!;
163
+ if (api.returnType?.isNativeType) {
164
+ responseType = Normalizator.mapTsTypeToDart(responseType);
165
+ } else {
166
+ responseType = Utils.toDartClassName(responseType) ?? responseType;
167
+ }
168
+
169
+ var methodName = Utils.getNormalizedApiPathDart(api.name);
170
+ if (tag && methodName.startsWith(Utils.toFirstLetterLowercase(tag))) {
171
+ methodName = methodName.slice(tag.length);
172
+ methodName = Utils.toFirstLetterLowercase(methodName);
173
+ }
174
+
175
+ // console.debug(`\tAPI - ${apiName} - ${apiMethod}`);
176
+ if (methodName.toLowerCase().indexOf("productsave") >= 0) {
177
+ debugger
178
+ }
179
+
180
+ const pathParams: Parameter[] = (api.parameters ?? [])
181
+ .filter(p => p.name !== 'request' && p.isQuery === false)
182
+ .map(p => ({
183
+ name: p.name,
184
+ type: p.typeName ? Normalizator.mapTsTypeToDart(p.typeName)! : 'String',
185
+ nullable: false,
186
+ }));
187
+
188
+ // Build a Dart-interpolated path string (e.g. '/x/{id}' -> '/x/$id')
189
+ const pathExpression = api.url.replace(/\{([^}]+)\}/g, (_, rawName) => {
190
+ const varName = Utils.toFirstLetterLowercase(rawName);
191
+ return `\$${varName}`;
192
+ });
193
+
194
+ const endpoint = <EndpointDefinitionDart>{
195
+ methodName: methodName,
196
+ httpMethod: api.method.toLowerCase() as HttpMethodDart,
197
+ path: pathExpression,
198
+ responseType: responseType,
199
+ isResponseNativeType: api.returnType ? api.returnType.isNativeType : true,
200
+ haveRequest: api.haveRequest,
201
+ requestType: requestType,
202
+ pathParams,
203
+ isMultiPart: api.isMultiPart === true,
204
+ };
205
+
206
+ if (api.parameters && api.parameters.length > 0 && !api.haveRequest) {
207
+ endpoint.queryParams = api.parameters
208
+ .filter(p => p.isQuery === true)
209
+ .map(p => ({
210
+ name: p.name,
211
+ type: p.typeName ? Normalizator.mapTsTypeToDart(p.typeName)! : 'String',
212
+ nullable: p.nullable
213
+ }));
214
+ }
215
+
216
+ if (api.haveRequest && api.parameters[0]?.typeName) {
217
+ if (imports.findIndex(x => x.type.typeName == api.parameters[0]?.typeName) == -1) {
218
+ models.forEach(model => {
219
+ if (model.typeName === api.parameters[0]?.typeName) {
220
+ const normalizedInfo = Normalizator.getNormalizedInfo(model);
221
+ const importPath = this._buildImportPath(importDirectory, normalizedInfo.subPath, normalizedInfo.filename);
222
+ imports.push({
223
+ type: api.parameters[0],
224
+ import: `import 'package:${this._commandLineArgs.package}/${importPath}';`
225
+ });
226
+ }
227
+ });
228
+ }
229
+ }
230
+
231
+ // Multipart: include request model fields so template can build FormData
232
+ if (endpoint.isMultiPart && api.haveRequest && api.parameters[0]?.typeName) {
233
+ const requestModelTypeName = api.parameters[0].typeName;
234
+ const requestModel = models.find(m => m.typeName === requestModelTypeName);
235
+ if (requestModel) {
236
+ endpoint.multipartFields = requestModel.properties.map(p => ({
237
+ name: p.name,
238
+ isFile: p.typeName === 'File',
239
+ isArray: p.isArray === true,
240
+ nullable: p.nullable === true,
241
+ }));
242
+ } else {
243
+ endpoint.multipartFields = [];
244
+ }
245
+ }
246
+
247
+ if (api.returnType && !api.returnType.isNativeType) {
248
+ if (imports.findIndex(x => x.type.typeName == api.returnType!.typeName) == -1) {
249
+ models.forEach(model => {
250
+ if (model.typeName === api.returnType!.typeName) {
251
+ const normalizedInfo = Normalizator.getNormalizedInfo(model);
252
+ const importPath = this._buildImportPath(importDirectory, normalizedInfo.subPath, normalizedInfo.filename);
253
+ imports.push({
254
+ type: api.returnType!,
255
+ import: `import 'package:${this._commandLineArgs.package}/${importPath}';`
256
+ });
257
+ }
258
+ });
259
+ }
260
+ }
261
+
262
+ return { endpoint };
263
+ }
264
+
265
+ private _buildImportPath(importDirectory: string, subPath: string, filename: string): string {
266
+ // Rimuove slash iniziali e finali da ogni parte
267
+ const parts = [importDirectory, subPath]
268
+ .filter(p => p && p.length > 0)
269
+ .map(p => p.replace(/^\/+|\/+$/g, ''));
270
+
271
+ // Aggiunge il filename alla fine
272
+ parts.push(`${filename}.dart`);
273
+
274
+ // Unisce con un singolo slash
275
+ return parts.join('/');
276
+ }
277
+
278
+ private _toPascalCase(input: string): string {
279
+ return input
280
+ .replace(/[_\- ]+/g, ' ') // sostituisce underscore, dash e spazi con uno spazio singolo
281
+ .trim() // rimuove spazi iniziali/finali
282
+ .split(' ') // divide in parole
283
+ .map(word =>
284
+ word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
285
+ )
286
+ .join('');
287
+ }
288
+
289
+ private _normalizeApiClassName(input: string): string {
290
+ return input
291
+ .replace(/\./g, '');
292
+ }
293
+
294
+ private _groupByTag(apis: ApiDto[]) {
295
+ const groupedByRole = apis.reduce<Record<string, ApiDto[]>>((acc, api) => {
296
+ if (!acc[api.tag]) {
297
+ acc[api.tag] = [];
298
+ }
299
+ acc[api.tag].push(api);
300
+ return acc;
301
+ }, {});
302
+ return groupedByRole;
303
+ }
304
304
  }