swaggular 0.3.0 → 0.5.0
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/dist/cli/args.js +6 -0
- package/dist/cli/variables.js +19 -4
- package/dist/core/data/types-data.d.ts +0 -0
- package/dist/core/data/types-data.js +1 -0
- package/dist/core/state/interface-state.d.ts +3 -0
- package/dist/core/state/interface-state.js +7 -0
- package/dist/core/state/swagger-state.d.ts +1 -0
- package/dist/core/state/swagger-state.js +3 -0
- package/dist/index.js +3 -3
- package/dist/renderers/generate-interface.d.ts +5 -4
- package/dist/renderers/generate-interface.js +132 -23
- package/dist/renderers/generate-service.d.ts +2 -1
- package/dist/renderers/generate-service.js +63 -43
- package/dist/templates/services/angular-template.d.ts +3 -7
- package/dist/templates/services/angular-template.js +10 -2
- package/dist/types/config.d.ts +22 -0
- package/dist/types/config.js +2 -0
- package/dist/types/parsed-args.d.ts +5 -2
- package/dist/types/template.d.ts +11 -0
- package/dist/types/template.js +2 -0
- package/dist/utils/build-types.js +5 -12
- package/dist/utils/config-loader.d.ts +2 -0
- package/dist/utils/config-loader.js +53 -0
- package/dist/utils/string-utils.d.ts +0 -5
- package/dist/utils/string-utils.js +0 -5
- package/dist/utils/template-renderer.d.ts +2 -0
- package/dist/utils/template-renderer.js +72 -0
- package/package.json +1 -1
package/dist/cli/args.js
CHANGED
package/dist/cli/variables.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toVariables = toVariables;
|
|
4
|
+
const config_loader_1 = require("../utils/config-loader");
|
|
4
5
|
function toVariables(parsed) {
|
|
5
6
|
const variables = {};
|
|
6
7
|
if (parsed.args.mode) {
|
|
@@ -11,11 +12,25 @@ function toVariables(parsed) {
|
|
|
11
12
|
variables.segmentsToIgnore = parsed.args.segmentsToIgnore.split(',');
|
|
12
13
|
}
|
|
13
14
|
}
|
|
15
|
+
const configPath = parsed.args.config;
|
|
16
|
+
const fileConfig = (0, config_loader_1.loadConfig)(configPath);
|
|
17
|
+
const mergedConfig = { ...fileConfig, ...variables };
|
|
14
18
|
return {
|
|
15
|
-
input: parsed.args.input ||
|
|
16
|
-
|
|
19
|
+
input: parsed.args.input ||
|
|
20
|
+
parsed.args.i ||
|
|
21
|
+
parsed.positional[0] ||
|
|
22
|
+
mergedConfig.input ||
|
|
23
|
+
'swagger.json',
|
|
24
|
+
output: parsed.args.output ||
|
|
25
|
+
parsed.args.o ||
|
|
26
|
+
parsed.positional[1] ||
|
|
27
|
+
mergedConfig.output ||
|
|
28
|
+
'results',
|
|
17
29
|
noGenerate: parsed.args.noGenerate || false,
|
|
18
|
-
groupingMode: variables.groupingMode || 'path',
|
|
19
|
-
segmentsToIgnore: variables.segmentsToIgnore || ['api'],
|
|
30
|
+
groupingMode: variables.groupingMode || mergedConfig.groupingMode || 'path',
|
|
31
|
+
segmentsToIgnore: variables.segmentsToIgnore || mergedConfig.segmentsToIgnore || ['api'],
|
|
32
|
+
// Pass entire config if needed for templates
|
|
33
|
+
templates: mergedConfig.templates,
|
|
34
|
+
types: mergedConfig.types,
|
|
20
35
|
};
|
|
21
36
|
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -7,12 +7,15 @@ export interface InterfaceStateI {
|
|
|
7
7
|
declare class InterfaceState implements InterfaceStateI {
|
|
8
8
|
generatedInterfaces: Record<string, InterfaceData>;
|
|
9
9
|
generatedEnums: Record<string, InterfaceData>;
|
|
10
|
+
typeMappings: Record<string, string>;
|
|
10
11
|
componentsSchemas: Record<string, IJsonSchema>;
|
|
11
12
|
constructor();
|
|
12
13
|
setComponentsSchemas(componentsSchemas: Record<string, IJsonSchema>): void;
|
|
13
14
|
getComponentsSchema(name: string): IJsonSchema | undefined;
|
|
14
15
|
addInterfaces(interfacesData: InterfaceData[]): void;
|
|
15
16
|
getInterface(name: string): InterfaceData | undefined;
|
|
17
|
+
addTypeMapping(original: string, mapped: string): void;
|
|
18
|
+
getTypeMapping(original: string): string | undefined;
|
|
16
19
|
}
|
|
17
20
|
export declare const interfaceState: InterfaceState;
|
|
18
21
|
export {};
|
|
@@ -4,6 +4,7 @@ exports.interfaceState = void 0;
|
|
|
4
4
|
class InterfaceState {
|
|
5
5
|
generatedInterfaces = {};
|
|
6
6
|
generatedEnums = {};
|
|
7
|
+
typeMappings = {};
|
|
7
8
|
componentsSchemas = {};
|
|
8
9
|
constructor() { }
|
|
9
10
|
setComponentsSchemas(componentsSchemas) {
|
|
@@ -20,5 +21,11 @@ class InterfaceState {
|
|
|
20
21
|
getInterface(name) {
|
|
21
22
|
return this.generatedInterfaces[name] || this.generatedEnums[name];
|
|
22
23
|
}
|
|
24
|
+
addTypeMapping(original, mapped) {
|
|
25
|
+
this.typeMappings[original] = mapped;
|
|
26
|
+
}
|
|
27
|
+
getTypeMapping(original) {
|
|
28
|
+
return this.typeMappings[original];
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
exports.interfaceState = new InterfaceState();
|
|
@@ -8,6 +8,7 @@ export declare class SwaggerState {
|
|
|
8
8
|
setPathsGroupedByScope(pathsGroupedByScope: GroupedPaths): void;
|
|
9
9
|
getPaths(): OpenAPIV3.PathsObject | undefined;
|
|
10
10
|
getSchemas(): Record<string, OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject> | undefined;
|
|
11
|
+
getParameters(): Record<string, OpenAPIV3.ReferenceObject | OpenAPIV3.ParameterObject> | undefined;
|
|
11
12
|
getPathsGroupedByScope(): GroupedPaths | undefined;
|
|
12
13
|
getGroupByPath(path: string): import("../../types/grouped-paths").GroupedPath | undefined;
|
|
13
14
|
}
|
package/dist/index.js
CHANGED
|
@@ -18,10 +18,10 @@ async function main() {
|
|
|
18
18
|
segmentsToIgnore: variables.segmentsToIgnore,
|
|
19
19
|
ignoreVariables: true,
|
|
20
20
|
});
|
|
21
|
-
(0, generate_interface_1.generateInterfaces)();
|
|
21
|
+
(0, generate_interface_1.generateInterfaces)(variables);
|
|
22
22
|
(0, generate_service_1.generateServices)();
|
|
23
|
-
const interfaceFiles = (0, generate_interface_1.generateInterfacesFiles)();
|
|
24
|
-
const serviceFiles = (0, generate_service_1.generateServiceFiles)();
|
|
23
|
+
const interfaceFiles = (0, generate_interface_1.generateInterfacesFiles)(undefined, variables);
|
|
24
|
+
const serviceFiles = (0, generate_service_1.generateServiceFiles)(undefined, variables.templates);
|
|
25
25
|
if (variables.noGenerate) {
|
|
26
26
|
console.log('Files not generated');
|
|
27
27
|
return;
|
|
@@ -2,11 +2,12 @@ import { OpenAPIV3 } from 'openapi-types';
|
|
|
2
2
|
import { FileContent } from '../types/file-content';
|
|
3
3
|
import { GroupedPath } from '../types/grouped-paths';
|
|
4
4
|
import { InterfaceData, InterfaceDataProperty } from '../types/interface-data';
|
|
5
|
+
import { SwaggularConfig } from '../types/config';
|
|
5
6
|
export declare function parametersToIProperties(parameters: (OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject)[]): InterfaceDataProperty[];
|
|
6
7
|
export declare function propertiesToIProperties(properties: Record<string, OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject>): InterfaceDataProperty[];
|
|
7
|
-
export declare function generateInterfaces(): void;
|
|
8
|
-
export declare function generateWithParameters(): void;
|
|
8
|
+
export declare function generateInterfaces(templatesConfig?: SwaggularConfig): void;
|
|
9
|
+
export declare function generateWithParameters(templatesConfig?: SwaggularConfig): void;
|
|
9
10
|
export declare function computeParametersName(method: string, innerPath: string, groupedPath: GroupedPath): string;
|
|
10
|
-
export declare function generateComponentsSchemas(): void;
|
|
11
|
-
export declare function generateInterfacesFiles(locations?: Record<string, string[]
|
|
11
|
+
export declare function generateComponentsSchemas(templatesConfig?: SwaggularConfig): void;
|
|
12
|
+
export declare function generateInterfacesFiles(locations?: Record<string, string[]>, templatesConfig?: SwaggularConfig): FileContent[];
|
|
12
13
|
export declare function generateContent(interfaceData: InterfaceData, deep?: number): string;
|
|
@@ -10,8 +10,6 @@ exports.generateInterfacesFiles = generateInterfacesFiles;
|
|
|
10
10
|
exports.generateContent = generateContent;
|
|
11
11
|
const interface_state_1 = require("../core/state/interface-state");
|
|
12
12
|
const swagger_state_1 = require("../core/state/swagger-state");
|
|
13
|
-
const extends_from_types_1 = require("../templates/types/extends-from-types");
|
|
14
|
-
const generic_types_1 = require("../templates/types/generic-types");
|
|
15
13
|
const build_types_1 = require("../utils/build-types");
|
|
16
14
|
const object_utils_1 = require("../utils/object-utils");
|
|
17
15
|
const path_utils_1 = require("../utils/path-utils");
|
|
@@ -23,12 +21,22 @@ function parametersToIProperties(parameters) {
|
|
|
23
21
|
for (const param of parameters) {
|
|
24
22
|
if ((0, type_guard_1.isReference)(param)) {
|
|
25
23
|
const ref = param.$ref.split('/').pop();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
if (param.$ref.includes('/components/parameters/')) {
|
|
25
|
+
const parameters = swagger_state_1.swaggerState.getParameters();
|
|
26
|
+
const parameter = parameters?.[ref];
|
|
27
|
+
if (parameter && !(0, type_guard_1.isReference)(parameter)) {
|
|
28
|
+
if (parameter.in !== 'query')
|
|
29
|
+
continue;
|
|
30
|
+
const tsType = parameter.schema ? (0, build_types_1.switchTypeJson)(parameter.schema) : 'any';
|
|
31
|
+
properties.push({
|
|
32
|
+
name: (0, string_utils_1.lowerFirst)(parameter.name),
|
|
33
|
+
type: tsType,
|
|
34
|
+
optional: !parameter.required,
|
|
35
|
+
comments: (0, generate_comments_1.generateInterfaceComments)(parameter.schema),
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
32
40
|
continue;
|
|
33
41
|
}
|
|
34
42
|
if (param.in !== 'query')
|
|
@@ -65,16 +73,49 @@ function propertiesToIProperties(properties) {
|
|
|
65
73
|
}
|
|
66
74
|
return interfaceDataProperties;
|
|
67
75
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
function isGenericType(data, genericTypes) {
|
|
77
|
+
for (const genericType of genericTypes) {
|
|
78
|
+
if (genericType.properties.length !== data.properties.length)
|
|
79
|
+
continue;
|
|
80
|
+
const dataProperties = data.properties.map((p) => p.name);
|
|
81
|
+
const genericTypeProperties = genericType.properties.map((p) => p.name);
|
|
82
|
+
if (genericTypeProperties.some((p) => !dataProperties.includes(p)))
|
|
83
|
+
continue;
|
|
84
|
+
return true; // Match found
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
function computeExtendsFromType(data, extendsTypes) {
|
|
89
|
+
for (const extendsFromType of extendsTypes) {
|
|
90
|
+
const dataPropertiesReq = data.properties.filter((p) => !p.optional).map((p) => p.name);
|
|
91
|
+
const extendsFromTypePropertiesReq = extendsFromType.properties
|
|
92
|
+
.filter((p) => !p.optional)
|
|
93
|
+
.map((p) => p.name);
|
|
94
|
+
if (extendsFromTypePropertiesReq.some((p) => !dataPropertiesReq.includes(p))) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const extensionProperties = extendsFromType.properties.map((p) => p.name.toLowerCase());
|
|
98
|
+
return {
|
|
99
|
+
...data,
|
|
100
|
+
properties: data.properties.filter((p) => !extensionProperties.includes(p.name.toLowerCase())),
|
|
101
|
+
imports: [...data.imports, extendsFromType.name],
|
|
102
|
+
extendsFrom: [...(data.extendsFrom ?? []), extendsFromType.name],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return data;
|
|
106
|
+
}
|
|
107
|
+
function generateInterfaces(templatesConfig) {
|
|
108
|
+
generateComponentsSchemas(templatesConfig);
|
|
109
|
+
generateWithParameters(templatesConfig);
|
|
71
110
|
}
|
|
72
|
-
function generateWithParameters() {
|
|
111
|
+
function generateWithParameters(templatesConfig) {
|
|
73
112
|
const paths = swagger_state_1.swaggerState.getPaths();
|
|
74
113
|
const groupedPaths = swagger_state_1.swaggerState.getPathsGroupedByScope();
|
|
75
114
|
if (!paths || !groupedPaths)
|
|
76
115
|
return;
|
|
77
116
|
const interfacesData = [];
|
|
117
|
+
const genericTypes = templatesConfig?.types?.generic ?? [];
|
|
118
|
+
const extendsTypes = templatesConfig?.types?.extendsFrom ?? [];
|
|
78
119
|
for (const groupedPath of Object.values(groupedPaths)) {
|
|
79
120
|
for (const innerPath of groupedPath.paths) {
|
|
80
121
|
const pathInfo = paths[innerPath];
|
|
@@ -101,10 +142,10 @@ function generateWithParameters() {
|
|
|
101
142
|
imports: properties.filter((p) => !(0, type_guard_1.isNativeType)(p.type)).map((p) => p.type),
|
|
102
143
|
properties,
|
|
103
144
|
};
|
|
104
|
-
const generic = (
|
|
145
|
+
const generic = isGenericType(interData, genericTypes);
|
|
105
146
|
if (generic)
|
|
106
147
|
continue;
|
|
107
|
-
const interDataWithExtendsFrom = (
|
|
148
|
+
const interDataWithExtendsFrom = computeExtendsFromType(interData, extendsTypes);
|
|
108
149
|
interfacesData.push(interDataWithExtendsFrom);
|
|
109
150
|
}
|
|
110
151
|
}
|
|
@@ -121,13 +162,22 @@ function computeParametersName(method, innerPath, groupedPath) {
|
|
|
121
162
|
};
|
|
122
163
|
const name = dict[method];
|
|
123
164
|
const extra = (0, string_utils_1.kebabToPascalCase)((0, path_utils_1.removeVariablesFromPath)((0, path_utils_1.getExtraSegments)(innerPath, (0, path_utils_1.createBaseUrl)(groupedPath.baseSegments)).join('')));
|
|
124
|
-
|
|
165
|
+
// Avoid duplication if extra starts with groupName
|
|
166
|
+
let suffix = extra;
|
|
167
|
+
const groupName = groupedPath.groupName;
|
|
168
|
+
if (suffix.startsWith(groupName)) {
|
|
169
|
+
suffix = suffix.substring(groupName.length);
|
|
170
|
+
}
|
|
171
|
+
return name + groupName + (0, string_utils_1.upFirst)(suffix) + 'Params';
|
|
125
172
|
}
|
|
126
|
-
function generateComponentsSchemas() {
|
|
173
|
+
function generateComponentsSchemas(templatesConfig) {
|
|
127
174
|
const schemas = swagger_state_1.swaggerState.getSchemas();
|
|
128
175
|
if (!schemas)
|
|
129
176
|
return;
|
|
130
177
|
const interfaces = [];
|
|
178
|
+
const genericMappings = new Map();
|
|
179
|
+
const genericTypes = templatesConfig?.types?.generic ?? [];
|
|
180
|
+
const extendsTypes = templatesConfig?.types?.extendsFrom ?? [];
|
|
131
181
|
for (const [key, value] of Object.entries(schemas)) {
|
|
132
182
|
if ((0, type_guard_1.isReference)(value))
|
|
133
183
|
continue;
|
|
@@ -147,6 +197,29 @@ function generateComponentsSchemas() {
|
|
|
147
197
|
}),
|
|
148
198
|
};
|
|
149
199
|
interfaces.push(interData);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const targetType = (0, build_types_1.switchTypeJson)(value);
|
|
203
|
+
if (targetType) {
|
|
204
|
+
const imports = [];
|
|
205
|
+
const baseType = targetType.replace('[]', '');
|
|
206
|
+
if (!(0, type_guard_1.isNativeType)(baseType)) {
|
|
207
|
+
imports.push(baseType);
|
|
208
|
+
}
|
|
209
|
+
interfaces.push({
|
|
210
|
+
name: key,
|
|
211
|
+
type: 'type',
|
|
212
|
+
imports,
|
|
213
|
+
properties: [
|
|
214
|
+
{
|
|
215
|
+
name: '',
|
|
216
|
+
type: targetType,
|
|
217
|
+
optional: false,
|
|
218
|
+
comments: (0, generate_comments_1.generateInterfaceComments)(value),
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
});
|
|
222
|
+
continue;
|
|
150
223
|
}
|
|
151
224
|
continue;
|
|
152
225
|
}
|
|
@@ -161,24 +234,56 @@ function generateComponentsSchemas() {
|
|
|
161
234
|
}),
|
|
162
235
|
properties,
|
|
163
236
|
};
|
|
164
|
-
const generic = (
|
|
237
|
+
const generic = isGenericType(interData, genericTypes);
|
|
165
238
|
if (generic) {
|
|
239
|
+
const genericType = genericTypes.find((g) => {
|
|
240
|
+
if (g.properties.length !== interData.properties.length)
|
|
241
|
+
return false;
|
|
242
|
+
const gProps = g.properties.map((p) => p.name);
|
|
243
|
+
const dProps = interData.properties.map((p) => p.name);
|
|
244
|
+
return !gProps.some((p) => !dProps.includes(p));
|
|
245
|
+
});
|
|
246
|
+
if (genericType) {
|
|
247
|
+
const genericName = computeGenericType(interData, genericType);
|
|
248
|
+
genericMappings.set(key, genericName);
|
|
249
|
+
interface_state_1.interfaceState.addTypeMapping(key, genericName);
|
|
250
|
+
}
|
|
166
251
|
continue;
|
|
167
252
|
}
|
|
168
|
-
const interDataWithExtendsFrom = (
|
|
253
|
+
const interDataWithExtendsFrom = computeExtendsFromType(interData, extendsTypes);
|
|
169
254
|
interfaces.push(interDataWithExtendsFrom);
|
|
170
255
|
}
|
|
256
|
+
// Update properties of all interfaces to use generic mappings
|
|
257
|
+
for (const inter of interfaces) {
|
|
258
|
+
inter.properties.forEach((p) => {
|
|
259
|
+
if (genericMappings.has(p.type)) {
|
|
260
|
+
p.type = genericMappings.get(p.type);
|
|
261
|
+
}
|
|
262
|
+
else if (p.type.endsWith('[]')) {
|
|
263
|
+
const base = p.type.replace('[]', '');
|
|
264
|
+
if (genericMappings.has(base)) {
|
|
265
|
+
p.type = genericMappings.get(base) + '[]';
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
171
270
|
interface_state_1.interfaceState.addInterfaces(interfaces);
|
|
172
271
|
}
|
|
173
|
-
function
|
|
272
|
+
function computeGenericType(newInterface, genericType) {
|
|
273
|
+
const typeParam = newInterface.name.replace(genericType.name, '');
|
|
274
|
+
return `${genericType.name}<${typeParam}>`;
|
|
275
|
+
}
|
|
276
|
+
function generateInterfacesFiles(locations, templatesConfig) {
|
|
277
|
+
const genericTypes = templatesConfig?.types?.generic ?? [];
|
|
278
|
+
const extendsTypes = templatesConfig?.types?.extendsFrom ?? [];
|
|
174
279
|
const interfacesData = [
|
|
175
|
-
...
|
|
176
|
-
...
|
|
280
|
+
...genericTypes,
|
|
281
|
+
...extendsTypes,
|
|
177
282
|
...Array.from(Object.values(interface_state_1.interfaceState.generatedInterfaces)),
|
|
178
283
|
];
|
|
179
284
|
const filesContent = [];
|
|
180
|
-
for (const
|
|
181
|
-
const location = [value.type === 'enum' ? 'enums' : 'dtos', ...(locations?.[
|
|
285
|
+
for (const value of interfacesData) {
|
|
286
|
+
const location = [value.type === 'enum' ? 'enums' : 'dtos', ...(locations?.[value.name] ?? [])];
|
|
182
287
|
const content = generateContent(value, location.length + 1);
|
|
183
288
|
const extraName = value.type === 'enum' ? 'enum' : 'dto';
|
|
184
289
|
filesContent.push({
|
|
@@ -211,5 +316,9 @@ function generateContent(interfaceData, deep = 0) {
|
|
|
211
316
|
}`;
|
|
212
317
|
return content;
|
|
213
318
|
}
|
|
319
|
+
if (interfaceData.type === 'type') {
|
|
320
|
+
const targetType = interfaceData.properties[0].type;
|
|
321
|
+
return `${importsTemplate}\n\nexport type ${interfaceData.name} = ${targetType};`;
|
|
322
|
+
}
|
|
214
323
|
return '';
|
|
215
324
|
}
|
|
@@ -2,9 +2,10 @@ import { OpenAPIV3 } from 'openapi-types';
|
|
|
2
2
|
import { FileContent } from '../types/file-content';
|
|
3
3
|
import { GroupedPath } from '../types/grouped-paths';
|
|
4
4
|
import { ServiceDataMethod } from '../types/service-data';
|
|
5
|
+
import { SwaggularConfig } from '../types/config';
|
|
5
6
|
/**
|
|
6
7
|
* Pick the paths grouped by scope and generate services for them.
|
|
7
8
|
*/
|
|
8
9
|
export declare function generateServices(): void;
|
|
9
|
-
export declare function generateServiceFiles(locations?: Record<string, string[]
|
|
10
|
+
export declare function generateServiceFiles(locations?: Record<string, string[]>, templatesConfig?: SwaggularConfig['templates']): FileContent[];
|
|
10
11
|
export declare function buildMethods(groupedPath: GroupedPath, pathData: OpenAPIV3.PathsObject, serviceName: string): ServiceDataMethod[];
|
|
@@ -5,7 +5,6 @@ exports.generateServiceFiles = generateServiceFiles;
|
|
|
5
5
|
exports.buildMethods = buildMethods;
|
|
6
6
|
const service_state_1 = require("../core/state/service-state");
|
|
7
7
|
const swagger_state_1 = require("../core/state/swagger-state");
|
|
8
|
-
const angular_template_1 = require("../templates/services/angular-template");
|
|
9
8
|
const build_types_1 = require("../utils/build-types");
|
|
10
9
|
const path_utils_1 = require("../utils/path-utils");
|
|
11
10
|
const string_utils_1 = require("../utils/string-utils");
|
|
@@ -13,8 +12,8 @@ const type_guard_1 = require("../utils/type-guard");
|
|
|
13
12
|
const generate_comments_1 = require("./generate-comments");
|
|
14
13
|
const object_utils_1 = require("../utils/object-utils");
|
|
15
14
|
const generate_interface_1 = require("./generate-interface");
|
|
16
|
-
const http_params_handler_1 = require("../templates/services/http-params-handler");
|
|
17
15
|
const interface_state_1 = require("../core/state/interface-state");
|
|
16
|
+
const template_renderer_1 = require("../utils/template-renderer");
|
|
18
17
|
/**
|
|
19
18
|
* Pick the paths grouped by scope and generate services for them.
|
|
20
19
|
*/
|
|
@@ -64,24 +63,34 @@ function addTypeToImports(type, imports) {
|
|
|
64
63
|
imports.add(baseType);
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
|
-
function generateServiceFiles(locations) {
|
|
66
|
+
function generateServiceFiles(locations, templatesConfig) {
|
|
68
67
|
const services = Object.values(service_state_1.serviceState.services);
|
|
69
68
|
const filesContent = [];
|
|
70
69
|
for (const service of services) {
|
|
71
70
|
const location = ['services', ...(locations?.[service.name] ?? [])];
|
|
71
|
+
const serviceTemplateConfig = templatesConfig?.service;
|
|
72
|
+
const templatePath = serviceTemplateConfig?.path || 'templates/angular-service.template';
|
|
72
73
|
const methods = service.methods
|
|
73
74
|
.map((method) => {
|
|
74
|
-
return buildMethodTemplate(method);
|
|
75
|
+
return buildMethodTemplate(method, serviceTemplateConfig?.options?.httpParamsHandler);
|
|
75
76
|
})
|
|
76
77
|
.join('\n\n');
|
|
78
|
+
const allImports = Array.from(new Set([...service.imports])).sort();
|
|
79
|
+
const hasHttpParams = service.methods.some((m) => !!m.queryParamType);
|
|
77
80
|
const templateParams = {
|
|
78
81
|
name: service.name,
|
|
79
82
|
baseUrl: service.baseUrl,
|
|
80
83
|
methods: methods,
|
|
81
|
-
imports:
|
|
82
|
-
|
|
84
|
+
imports: allImports.join(', '),
|
|
85
|
+
modelImports: allImports.length > 0 ? `import { ${allImports.join(', ')} } from '../models';` : '',
|
|
86
|
+
hasHttpParamsHandler: hasHttpParams,
|
|
87
|
+
httpParamsHandler: serviceTemplateConfig?.options?.httpParamsHandler,
|
|
88
|
+
httpParamsHandlerImport: hasHttpParams
|
|
89
|
+
? serviceTemplateConfig?.options?.httpParamsHandlerImport
|
|
90
|
+
: '',
|
|
91
|
+
extraAngularImports: hasHttpParams ? ', HttpParams' : '',
|
|
83
92
|
};
|
|
84
|
-
const content = (0,
|
|
93
|
+
const content = (0, template_renderer_1.renderServiceTemplate)(templatePath, templateParams);
|
|
85
94
|
filesContent.push({
|
|
86
95
|
location: location,
|
|
87
96
|
content,
|
|
@@ -140,18 +149,7 @@ function pathItemToMethods(pathItem) {
|
|
|
140
149
|
patch: pathItem.patch,
|
|
141
150
|
});
|
|
142
151
|
}
|
|
143
|
-
/**
|
|
144
|
-
* buildMethodName: High-performance semantic naming algorithm.
|
|
145
|
-
*
|
|
146
|
-
* This engine generates clean, non-redundant, and intuitive method names by
|
|
147
|
-
* analyzing the relationship between the base URL and extra path segments.
|
|
148
|
-
*
|
|
149
|
-
* For Mutation methods (POST, PUT, PATCH, DELETE), it prioritizes using the
|
|
150
|
-
* path segments as the method name itself if they describe an action,
|
|
151
|
-
* avoiding generic "create" or "update" prefixes where possible.
|
|
152
|
-
*/
|
|
153
152
|
function buildMethodName(method, path, groupedPath, usedNames, serviceName) {
|
|
154
|
-
// 1. Core mapping of HTTP verbs to professional action prefixes
|
|
155
153
|
const verbMap = {
|
|
156
154
|
get: 'get',
|
|
157
155
|
post: 'create',
|
|
@@ -161,7 +159,6 @@ function buildMethodName(method, path, groupedPath, usedNames, serviceName) {
|
|
|
161
159
|
};
|
|
162
160
|
const defaultVerb = verbMap[method.toLowerCase()] || method.toLowerCase();
|
|
163
161
|
const segments = (0, path_utils_1.getExtraSegments)(path, groupedPath.baseUrl);
|
|
164
|
-
// 2. Redundancy Filtering: Remove segments already implied by the service name
|
|
165
162
|
const serviceWords = serviceName.split(/(?=[A-Z])/).map((w) => w.toLowerCase());
|
|
166
163
|
const cleanSegments = segments.filter((seg) => {
|
|
167
164
|
if ((0, path_utils_1.isVariable)(seg))
|
|
@@ -169,7 +166,6 @@ function buildMethodName(method, path, groupedPath, usedNames, serviceName) {
|
|
|
169
166
|
const segWords = seg.split('-').map((w) => w.toLowerCase());
|
|
170
167
|
return !segWords.every((sw) => serviceWords.includes(sw));
|
|
171
168
|
});
|
|
172
|
-
// 3. Structural Analysis: Identify resources and variable positioning
|
|
173
169
|
const staticBefore = [];
|
|
174
170
|
const variableParts = [];
|
|
175
171
|
const staticAfter = [];
|
|
@@ -187,7 +183,6 @@ function buildMethodName(method, path, groupedPath, usedNames, serviceName) {
|
|
|
187
183
|
}
|
|
188
184
|
}
|
|
189
185
|
const nameParts = [];
|
|
190
|
-
// 4. Logic specific to data fetching (GET)
|
|
191
186
|
if (method.toLowerCase() === 'get') {
|
|
192
187
|
nameParts.push('get');
|
|
193
188
|
if (staticAfter.length > 0) {
|
|
@@ -203,22 +198,18 @@ function buildMethodName(method, path, groupedPath, usedNames, serviceName) {
|
|
|
203
198
|
nameParts.push('ById');
|
|
204
199
|
}
|
|
205
200
|
}
|
|
206
|
-
// 5. Logic for state mutation (POST, PUT, PATCH, DELETE)
|
|
207
201
|
else {
|
|
208
202
|
const actionParts = [...staticBefore, ...staticAfter];
|
|
209
203
|
if (actionParts.length > 0) {
|
|
210
|
-
// If the path contains an action (e.g., /assign, /send-to-user), use it directly.
|
|
211
204
|
nameParts.push((0, string_utils_1.toPascalCase)(actionParts));
|
|
212
205
|
}
|
|
213
206
|
else {
|
|
214
|
-
// No extra segments, use the default verb prefix (e.g., create, update)
|
|
215
207
|
nameParts.push((0, string_utils_1.upFirst)(defaultVerb));
|
|
216
208
|
}
|
|
217
209
|
if (variableParts.length > 0) {
|
|
218
210
|
nameParts.push('ById');
|
|
219
211
|
}
|
|
220
212
|
}
|
|
221
|
-
// 6. Pattern-based Refinement: Detect and prioritize standard REST suffixes
|
|
222
213
|
const normalizedPath = path.toLowerCase();
|
|
223
214
|
const suffixes = [
|
|
224
215
|
{ pattern: '/all', label: 'All' },
|
|
@@ -236,17 +227,13 @@ function buildMethodName(method, path, groupedPath, usedNames, serviceName) {
|
|
|
236
227
|
break;
|
|
237
228
|
}
|
|
238
229
|
}
|
|
239
|
-
// 7. Base candidate assembly
|
|
240
230
|
let candidateName = (0, string_utils_1.lowerFirst)(nameParts.join(''));
|
|
241
|
-
// Simplification for the primary resource GET
|
|
242
231
|
if (candidateName === 'getById' && !usedNames.includes('get')) {
|
|
243
232
|
candidateName = 'get';
|
|
244
233
|
}
|
|
245
|
-
// Fallback for empty/ambiguous names
|
|
246
234
|
if (candidateName === '' || (candidateName === defaultVerb && segments.length > 0)) {
|
|
247
235
|
candidateName = (0, string_utils_1.lowerFirst)(defaultVerb + (0, string_utils_1.toPascalCase)(segments.map((s) => s.replace(/[{}]/g, ''))));
|
|
248
236
|
}
|
|
249
|
-
// 8. Multi-strategy Collision Resolution
|
|
250
237
|
let finalName = candidateName;
|
|
251
238
|
let counter = 0;
|
|
252
239
|
while (usedNames.includes(finalName)) {
|
|
@@ -271,14 +258,26 @@ function buildParameters(operation, pathParameters) {
|
|
|
271
258
|
for (const param of allParams) {
|
|
272
259
|
if ((0, type_guard_1.isReference)(param)) {
|
|
273
260
|
const ref = param.$ref.split('/').pop();
|
|
274
|
-
console.log('🚀 ~ buildParameters ~ ref:', ref);
|
|
275
261
|
const interfaceData = interface_state_1.interfaceState.getInterface(ref);
|
|
276
|
-
|
|
262
|
+
let paramType = interface_state_1.interfaceState.getTypeMapping(ref) || ref;
|
|
263
|
+
let inType = interfaceData?.type !== undefined ? 'query' : 'path';
|
|
264
|
+
let required = true;
|
|
265
|
+
if (param.$ref.includes('/components/parameters/')) {
|
|
266
|
+
const parameters = swagger_state_1.swaggerState.getParameters();
|
|
267
|
+
const parameter = parameters?.[ref];
|
|
268
|
+
if (parameter && !(0, type_guard_1.isReference)(parameter)) {
|
|
269
|
+
inType = parameter.in;
|
|
270
|
+
required = parameter.required ?? false;
|
|
271
|
+
if (parameter.schema) {
|
|
272
|
+
paramType = (0, build_types_1.switchTypeJson)(parameter.schema);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
277
276
|
results.push({
|
|
278
277
|
name: (0, string_utils_1.lowerFirst)(ref),
|
|
279
|
-
in:
|
|
280
|
-
required
|
|
281
|
-
type:
|
|
278
|
+
in: inType,
|
|
279
|
+
required,
|
|
280
|
+
type: paramType,
|
|
282
281
|
});
|
|
283
282
|
continue;
|
|
284
283
|
}
|
|
@@ -308,21 +307,22 @@ function buildParameters(operation, pathParameters) {
|
|
|
308
307
|
type: bodyType,
|
|
309
308
|
});
|
|
310
309
|
}
|
|
311
|
-
console.log('🚀 ~ buildParameters ~ results:', results);
|
|
312
310
|
return results;
|
|
313
311
|
}
|
|
314
312
|
function buildResponseType(responses) {
|
|
315
313
|
const success = responses['200'] || responses['201'] || responses['204'] || responses['default'];
|
|
316
314
|
if (!success)
|
|
317
315
|
return 'any';
|
|
318
|
-
if ((0, type_guard_1.isReference)(success))
|
|
319
|
-
|
|
316
|
+
if ((0, type_guard_1.isReference)(success)) {
|
|
317
|
+
const name = success.$ref.split('/').pop();
|
|
318
|
+
return interface_state_1.interfaceState.getTypeMapping(name) || name;
|
|
319
|
+
}
|
|
320
320
|
const content = success.content?.['application/json'];
|
|
321
321
|
if (!content || !content.schema)
|
|
322
322
|
return 'any';
|
|
323
323
|
return (0, build_types_1.switchTypeJson)(content.schema);
|
|
324
324
|
}
|
|
325
|
-
function buildMethodTemplate(method) {
|
|
325
|
+
function buildMethodTemplate(method, httpParamsHandlerTemplate) {
|
|
326
326
|
const pathParams = method.parameters.filter((p) => p.in === 'path');
|
|
327
327
|
const bodyParam = method.parameters.find((p) => p.in === 'body');
|
|
328
328
|
const methodArgs = [];
|
|
@@ -339,10 +339,8 @@ function buildMethodTemplate(method) {
|
|
|
339
339
|
.map((s) => ((0, path_utils_1.isVariable)(s) ? `\${${(0, string_utils_1.lowerFirst)(s.replace(/[{}]/g, ''))}}` : s))
|
|
340
340
|
.join('/');
|
|
341
341
|
const url = `\`\${this.baseUrl}${pathStr ? '/' + pathStr : ''}\``;
|
|
342
|
-
let handler = '';
|
|
343
342
|
const optionsList = [];
|
|
344
343
|
if (method.queryParamType) {
|
|
345
|
-
handler = `\n\t\t${(0, http_params_handler_1.httpParamsHandler)('queryParams')}`;
|
|
346
344
|
optionsList.push('params');
|
|
347
345
|
}
|
|
348
346
|
if (['Blob', 'File'].includes(method.responseType)) {
|
|
@@ -358,8 +356,30 @@ function buildMethodTemplate(method) {
|
|
|
358
356
|
: ['post', 'put', 'patch'].includes(method.method)
|
|
359
357
|
? `this.http.${method.method}${genericType}(${url}, {}${options})`
|
|
360
358
|
: `this.http.${method.method}${genericType}(${url}${options})`;
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
359
|
+
let paramsLogic = '';
|
|
360
|
+
if (method.queryParamType) {
|
|
361
|
+
if (httpParamsHandlerTemplate) {
|
|
362
|
+
paramsLogic = `\n\t\t${httpParamsHandlerTemplate.replace('${params}', 'queryParams')}`;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
paramsLogic = `
|
|
366
|
+
let params = new HttpParams();
|
|
367
|
+
if (queryParams) {
|
|
368
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
369
|
+
if (value === undefined || value === null) continue;
|
|
370
|
+
if (Array.isArray(value)) {
|
|
371
|
+
value.forEach((v) => (params = params.append(key, v)));
|
|
372
|
+
} else if (typeof value === 'object' && !(value instanceof Date) && !(value instanceof Blob)) {
|
|
373
|
+
params = params.set(key, JSON.stringify(value));
|
|
374
|
+
} else {
|
|
375
|
+
params = params.set(key, value as any);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}`;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return `${method.comments}
|
|
382
|
+
${method.name}(${argsString}): Observable<${method.responseType}> {${paramsLogic}
|
|
383
|
+
return ${methodCall};
|
|
364
384
|
}`;
|
|
365
385
|
}
|
|
@@ -7,12 +7,8 @@ export interface AngularServiceTemplate {
|
|
|
7
7
|
methods: string;
|
|
8
8
|
imports: string;
|
|
9
9
|
hasHttpParamsHandler: boolean;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
parametersTypes: Record<string, {
|
|
14
|
-
method: string;
|
|
15
|
-
parameterType: string;
|
|
16
|
-
}>;
|
|
10
|
+
configImports?: string[];
|
|
11
|
+
httpParamsHandler?: string;
|
|
12
|
+
httpParamsHandlerImport?: string;
|
|
17
13
|
}
|
|
18
14
|
export declare const angularTemplate: (params: AngularServiceTemplate) => string;
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.angularTemplate = void 0;
|
|
4
|
-
const http_params_handler_1 = require("./http-params-handler");
|
|
5
4
|
const angularTemplate = (params) => {
|
|
5
|
+
const configImports = params.configImports
|
|
6
|
+
? params.configImports.map((i) => `import { ${i} } from '@angular/core';`).join('\n') // Placeholder logic, actual imports might be more complex
|
|
7
|
+
: '';
|
|
8
|
+
// Actually, let's keep it simple. The config imports should probably be raw strings or structured.
|
|
9
|
+
// For now, let's assume the template receives the RAW import strings from the config if provided,
|
|
10
|
+
// OR we construct them here.
|
|
11
|
+
// User wants: "can make it so it can work without any custom template (just the most generic one)"
|
|
12
|
+
// and "make it so it works with a JSON configuration".
|
|
13
|
+
const httpParamsHandlerImport = params.httpParamsHandlerImport || '';
|
|
6
14
|
return `
|
|
7
15
|
import { HttpClient } from "@angular/common/http";
|
|
8
16
|
import { Observable } from "rxjs";
|
|
9
17
|
import { inject, Injectable } from '@angular/core';
|
|
10
18
|
import { ${params.imports} } from '../models';
|
|
11
|
-
${
|
|
19
|
+
${httpParamsHandlerImport}
|
|
12
20
|
|
|
13
21
|
@Injectable({
|
|
14
22
|
providedIn: "root"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ServiceTemplateParams } from './template';
|
|
2
|
+
import { InterfaceData } from './interface-data';
|
|
3
|
+
export interface SwaggularConfig {
|
|
4
|
+
types?: {
|
|
5
|
+
extendsFrom?: InterfaceData[];
|
|
6
|
+
generic?: InterfaceData[];
|
|
7
|
+
};
|
|
8
|
+
templates?: {
|
|
9
|
+
service?: {
|
|
10
|
+
path: string;
|
|
11
|
+
options?: Partial<ServiceTemplateParams>;
|
|
12
|
+
transform?: (options: ServiceTemplateParams) => string;
|
|
13
|
+
content?: string;
|
|
14
|
+
httpParamsHandler?: string;
|
|
15
|
+
httpParamsHandlerImport?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
input?: string;
|
|
19
|
+
output?: string;
|
|
20
|
+
groupingMode?: 'tags' | 'path';
|
|
21
|
+
segmentsToIgnore?: string[];
|
|
22
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { SwaggularConfig } from './config';
|
|
1
2
|
export type ParsedArgs = {
|
|
2
3
|
args: Record<string, string | boolean>;
|
|
3
4
|
positional: string[];
|
|
4
5
|
};
|
|
5
6
|
export interface ArgsVariables {
|
|
6
|
-
groupingMode: 'tags' | 'path';
|
|
7
|
-
segmentsToIgnore: string[];
|
|
8
7
|
input: string;
|
|
9
8
|
output: string;
|
|
10
9
|
noGenerate: boolean;
|
|
10
|
+
groupingMode: 'tags' | 'path';
|
|
11
|
+
segmentsToIgnore: string[];
|
|
12
|
+
templates?: SwaggularConfig['templates'];
|
|
13
|
+
types?: SwaggularConfig['types'];
|
|
11
14
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ServiceTemplateParams {
|
|
2
|
+
name: string;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
methods: string;
|
|
5
|
+
imports: string;
|
|
6
|
+
hasHttpParamsHandler: boolean;
|
|
7
|
+
httpParamsHandler?: string;
|
|
8
|
+
httpParamsHandlerImport?: string;
|
|
9
|
+
modelImports?: string;
|
|
10
|
+
extraAngularImports?: string;
|
|
11
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildTypes = buildTypes;
|
|
4
4
|
exports.switchTypeJson = switchTypeJson;
|
|
5
|
+
const interface_state_1 = require("../core/state/interface-state");
|
|
5
6
|
function buildTypes(masterSchema, defaultType = 'any') {
|
|
6
7
|
if (!masterSchema)
|
|
7
8
|
return defaultType;
|
|
@@ -18,12 +19,8 @@ function buildTypes(masterSchema, defaultType = 'any') {
|
|
|
18
19
|
return defaultType;
|
|
19
20
|
const ref = schema?.['$ref'];
|
|
20
21
|
if (ref) {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
if (isPagedResultDto) {
|
|
24
|
-
return `PagedResultDto<${iface.replace('PagedResultDto', '')}>`;
|
|
25
|
-
}
|
|
26
|
-
return iface;
|
|
22
|
+
const name = ref.split('/').pop();
|
|
23
|
+
return interface_state_1.interfaceState.getTypeMapping(name) || name;
|
|
27
24
|
}
|
|
28
25
|
return switchTypeJson(schema);
|
|
29
26
|
}
|
|
@@ -34,12 +31,8 @@ function switchTypeJson(schema) {
|
|
|
34
31
|
const type = schema?.['type'];
|
|
35
32
|
const format = schema?.['format'];
|
|
36
33
|
if (ref) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
if (isPagedResultDto) {
|
|
40
|
-
return `PagedResultDto<${iface.replace('PagedResultDto', '')}>`;
|
|
41
|
-
}
|
|
42
|
-
return iface;
|
|
34
|
+
const name = ref.split('/').pop();
|
|
35
|
+
return interface_state_1.interfaceState.getTypeMapping(name) || name;
|
|
43
36
|
}
|
|
44
37
|
if (type === 'object') {
|
|
45
38
|
return 'any';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadConfig = loadConfig;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
function loadConfig(configPath) {
|
|
40
|
+
const defaultConfigPath = 'swaggular.config.json';
|
|
41
|
+
const resolvedPath = path.resolve(configPath || defaultConfigPath);
|
|
42
|
+
if (fs.existsSync(resolvedPath)) {
|
|
43
|
+
try {
|
|
44
|
+
const fileContent = fs.readFileSync(resolvedPath, 'utf-8');
|
|
45
|
+
return JSON.parse(fileContent);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(`Error parsing config file at ${resolvedPath}:`, error);
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
export declare function kebabToCamelCase(str: string): string;
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* @param str :
|
|
5
|
-
* @returns
|
|
6
|
-
*/
|
|
7
2
|
export declare function kebabToPascalCase(str: string): string;
|
|
8
3
|
export declare function removeAllWhitespace(text: string): string;
|
|
9
4
|
export declare function lowerFirst(str: string): string;
|
|
@@ -11,11 +11,6 @@ exports.toPascalCase = toPascalCase;
|
|
|
11
11
|
function kebabToCamelCase(str) {
|
|
12
12
|
return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* @param str :
|
|
17
|
-
* @returns
|
|
18
|
-
*/
|
|
19
14
|
function kebabToPascalCase(str) {
|
|
20
15
|
const camel = str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
21
16
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.renderServiceTemplate = renderServiceTemplate;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
function renderServiceTemplate(templatePath, params) {
|
|
40
|
+
// 1. Read the template file
|
|
41
|
+
const absolutePath = path.resolve(templatePath);
|
|
42
|
+
let templateContent;
|
|
43
|
+
try {
|
|
44
|
+
if (fs.existsSync(absolutePath)) {
|
|
45
|
+
templateContent = fs.readFileSync(absolutePath, 'utf-8');
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.error(`Template file not found at ${absolutePath}`);
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
console.error(`Error reading template file at ${absolutePath}`, err);
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
// 2. Perform replacements
|
|
57
|
+
// Simple mustache-like replacement: {{variable}}
|
|
58
|
+
// We can use a regex or simple replaceAll if available (Node 15+) or split/join.
|
|
59
|
+
let result = templateContent;
|
|
60
|
+
// Replace known params
|
|
61
|
+
result = result.replace(/{{name}}/g, params.name);
|
|
62
|
+
result = result.replace(/{{baseUrl}}/g, params.baseUrl);
|
|
63
|
+
result = result.replace(/{{methods}}/g, params.methods);
|
|
64
|
+
result = result.replace(/{{modelImports}}/g, params.modelImports || '');
|
|
65
|
+
result = result.replace(/{{imports}}/g, params.imports);
|
|
66
|
+
// Handle conditional logic for httpParamsHandlerImport
|
|
67
|
+
result = result.replace(/{{httpParamsHandlerImport}}/g, params.httpParamsHandlerImport || '');
|
|
68
|
+
result = result.replace(/{{extraAngularImports}}/g, params.extraAngularImports || '');
|
|
69
|
+
// Cleanup excessive newlines (3 or more, potentially with spaces) to just 2
|
|
70
|
+
result = result.replace(/(\r?\n\s*){3,}/g, '\n\n');
|
|
71
|
+
return result;
|
|
72
|
+
}
|