swaggular 0.2.2 → 0.2.4

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.
@@ -1,302 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateServices = generateServices;
4
- exports.generateServiceFiles = generateServiceFiles;
5
- exports.buildMethods = buildMethods;
6
- exports.buildMethod = buildMethod;
7
- exports.computeName = computeName;
8
- const services_store_1 = require("../stores/services-store");
9
- const swagger_store_1 = require("../stores/swagger-store");
10
- const angular_template_1 = require("../templates/services/angular-template");
11
- const build_types_1 = require("../utils/build-types");
12
- const path_utils_1 = require("../utils/path-utils");
13
- const string_utils_1 = require("../utils/string-utils");
14
- const type_guard_1 = require("../utils/type-guard");
15
- const generate_interface_1 = require("./generate-interface");
16
- const generate_comments_1 = require("./generate-comments");
17
- /**
18
- * Pick the paths grouped by scope and generate services for them.
19
- * Each group will generate one service data.
20
- * Each service data will contain the methods for the paths.
21
- *
22
- * The name will be the group name concatenated with Service
23
- *
24
- * The imports will be the types used in the methods. Including
25
- * the response type and the parameters types.
26
- *
27
- * The base url will be the base url of the group compound by the
28
- * base segments of the group.
29
- *
30
- * Each method will be generated based on a path
31
- *
32
- * The method name will be computed based on the path.
33
- * It has to follow some stantardized rules.
34
- *
35
- * The method parameters will be computed based on the path parameters
36
- * The method path will be computed based on the path, but it will be
37
- * computed as `${this.baseUrl}/something/else/{id}`
38
- * The method response type will be computed based on the path response
39
- * The method parameters will be computed based on the path parameters
40
- * The method parameter name will be computed based on the path parameter name if
41
- * the parameters has the property "in" set to "path". If the parameter has the property
42
- * "in" set to "query", it will be computed as "parameters" and query parameters should be grouped
43
- * in the same object. Check computeParametersName() method in generate-interface.ts to
44
- * understand how the name is computed.
45
- *
46
- * The method parameter in property will be computed based on the path parameter "in" property
47
- * The method parameter type will be computed based on the path parameter type property.
48
- * Check computeParametersName() method in generate-interface.ts to
49
- * understand how the name is computed.
50
- * The method parameter required will be computed based on the path parameter required property
51
- * @returns ServiceData[]
52
- */
53
- function generateServices() {
54
- const servicesData = [];
55
- const groupedPaths = swagger_store_1.swaggerStore.getPathsGroupedByScope();
56
- const paths = swagger_store_1.swaggerStore.getPaths();
57
- if (!groupedPaths || !paths)
58
- return;
59
- for (const [key, value] of Object.entries(groupedPaths)) {
60
- const methods = buildMethods(value);
61
- const importsSet = new Set();
62
- methods.forEach((method) => {
63
- const allTypes = [
64
- method.responseType,
65
- ...method.parameters.map((p) => p.type),
66
- ];
67
- allTypes.forEach((t) => {
68
- const identifiers = t.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || [];
69
- identifiers.forEach((id) => {
70
- if (!(0, type_guard_1.isNativeType)(id) && id !== "void") {
71
- importsSet.add(id);
72
- }
73
- });
74
- });
75
- });
76
- const serviceData = {
77
- name: key + "Service",
78
- imports: Array.from(importsSet),
79
- baseUrl: value.baseUrl,
80
- methods: methods,
81
- };
82
- servicesData.push(serviceData);
83
- }
84
- services_store_1.serviceStore.addServices(servicesData);
85
- }
86
- function generateServiceFiles(locations) {
87
- const services = Object.values(services_store_1.serviceStore.services);
88
- const filesContent = [];
89
- for (const service of services) {
90
- const methodsString = service.methods
91
- .map((method) => generateMethodString(method))
92
- .join("\n\n");
93
- const templateParams = {
94
- name: service.name.replace("Service", ""),
95
- baseUrl: service.baseUrl,
96
- methods: methodsString,
97
- imports: service.imports.join(", "),
98
- hasHttpParamsHandler: service.methods.some((m) => m.parameters.some((p) => p.in === "query")),
99
- };
100
- // If imports are empty, we might want to clean up the template later,
101
- // but for now we follow the existing template structure.
102
- filesContent.push({
103
- location: ["services", ...(locations?.[service.name] ?? [])],
104
- name: (0, string_utils_1.toKebabCase)(service.name.replace("Service", "")) + ".service",
105
- content: (0, angular_template_1.angularServiceTemplate)(templateParams),
106
- extension: "ts",
107
- });
108
- }
109
- return filesContent;
110
- }
111
- function generateMethodString(method) {
112
- const paramsSignature = method.parameters
113
- .map((p) => `${p.name}${p.required ? "" : "?"}: ${p.type}`)
114
- .join(", ");
115
- const httpMethod = method.method.toLowerCase();
116
- const responseType = method.responseType;
117
- // Convert {id} to ${id} in path
118
- let path = method.path.replace(/{([^}]+)}/g, "${$1}");
119
- if (!path.startsWith("`")) {
120
- // Remove the first $
121
- path = `\`${path.slice(1)}\``;
122
- }
123
- let body = "";
124
- const queryParam = method.parameters.find((p) => p.in === "query");
125
- if (queryParam) {
126
- body += ` const params = HttpHelper.toHttpParams(${queryParam.name} ?? {});\n`;
127
- }
128
- const options = [];
129
- if (queryParam)
130
- options.push("params");
131
- if (responseType === "Blob" || responseType === "File") {
132
- options.push("responseType: 'blob'");
133
- }
134
- if (httpMethod === "delete" &&
135
- method.parameters.some((p) => p.in === "body")) {
136
- options.push("body: " + method.parameters.find((p) => p.in === "body")?.name);
137
- }
138
- const optionsString = options.length > 0 ? `, { ${options.join(", ")} }` : "";
139
- if (httpMethod === "get" || httpMethod === "delete") {
140
- body += ` return this.http.${httpMethod}<${responseType}>(${path}${optionsString});`;
141
- }
142
- else {
143
- // post, put, patch
144
- const dataParam = method.parameters.find((p) => p.in === "body")?.name || "null";
145
- body += ` return this.http.${httpMethod}<${responseType}>(${path}, ${dataParam}${optionsString});`;
146
- }
147
- return `${method.comments}\n public ${method.name}(${paramsSignature}): Observable<${responseType}> {
148
- ${body}
149
- }`;
150
- }
151
- function buildMethods(groupedPath) {
152
- const methods = [];
153
- const pathData = swagger_store_1.swaggerStore.getPaths();
154
- const usedNames = [];
155
- for (const path of groupedPath.paths) {
156
- if (!pathData || !pathData[path])
157
- continue;
158
- for (const [httpMethod, pathInfo] of Object.entries(pathData[path])) {
159
- if (typeof pathInfo !== "object")
160
- continue;
161
- const method = buildMethod(path, httpMethod, pathInfo, groupedPath, usedNames);
162
- methods.push(method);
163
- usedNames.push(method.name);
164
- }
165
- }
166
- return methods;
167
- }
168
- function buildMethod(path, httpMethod, pathInfo, groupedPath, usedNames) {
169
- const baseUrl = groupedPath.baseUrl;
170
- const extraSegments = (0, path_utils_1.getExtraSegments)(path, baseUrl).join("/");
171
- const methodPath = extraSegments
172
- ? `\${this.baseUrl}/${extraSegments}`
173
- : `\${this.baseUrl}`;
174
- const responseType = getMethodResponseType(pathInfo);
175
- const parameters = getMethodParameters(path, httpMethod, pathInfo, groupedPath);
176
- const method = {
177
- name: computeName(path, httpMethod, usedNames),
178
- path: methodPath,
179
- method: httpMethod,
180
- parameters: parameters,
181
- responseType: responseType,
182
- comments: (0, generate_comments_1.generateServiceComments)(pathInfo.summary || "", responseType, parameters),
183
- };
184
- return method;
185
- }
186
- function getMethodResponseType(pathInfo) {
187
- const responses = pathInfo.responses;
188
- if (!responses)
189
- return "void";
190
- const successResponse = responses["200"] || responses["201"] || responses["default"];
191
- if (!successResponse)
192
- return "void";
193
- if ((0, type_guard_1.isReference)(successResponse)) {
194
- return "any";
195
- }
196
- const content = successResponse.content;
197
- if (!content || !content["application/json"])
198
- return "void";
199
- const schema = content["application/json"].schema;
200
- if (!schema)
201
- return "void";
202
- return (0, build_types_1.switchTypeJson)(schema);
203
- }
204
- function getMethodParameters(path, httpMethod, pathInfo, groupedPath) {
205
- const parameters = [];
206
- const openApiParameters = pathInfo.parameters || [];
207
- // Path parameters
208
- openApiParameters.forEach((param) => {
209
- if ((0, type_guard_1.isReference)(param))
210
- return;
211
- if (param.in === "path") {
212
- parameters.push({
213
- name: param.name,
214
- in: "path",
215
- required: param.required || false,
216
- type: (0, build_types_1.switchTypeJson)(param.schema),
217
- });
218
- }
219
- });
220
- // Query parameters (grouped)
221
- const queryParams = openApiParameters.filter((param) => !(0, type_guard_1.isReference)(param) && param.in === "query");
222
- if (queryParams.length > 0) {
223
- parameters.push({
224
- name: "parameters",
225
- in: "query",
226
- required: queryParams.some((p) => p.required),
227
- type: (0, generate_interface_1.computeParametersName)(httpMethod, path, groupedPath),
228
- });
229
- }
230
- // Request Body
231
- if (pathInfo.requestBody) {
232
- let bodyType = "any";
233
- if ((0, type_guard_1.isReference)(pathInfo.requestBody)) {
234
- bodyType = pathInfo.requestBody.$ref.split("/").pop();
235
- }
236
- else {
237
- const content = pathInfo.requestBody.content;
238
- if (content && content["application/json"]) {
239
- const schema = content["application/json"].schema;
240
- if (schema) {
241
- bodyType = (0, build_types_1.switchTypeJson)(schema);
242
- }
243
- }
244
- }
245
- parameters.push({
246
- name: "data",
247
- in: "body",
248
- required: true,
249
- type: bodyType,
250
- });
251
- }
252
- return parameters;
253
- }
254
- function computeName(path, httpMethod, usedNames) {
255
- const dict = {
256
- get: "get",
257
- post: "create",
258
- put: "update",
259
- delete: "delete",
260
- patch: "patch",
261
- };
262
- const parts = path.split("/").filter((p) => p);
263
- const endsInVariable = (0, path_utils_1.isVariable)(parts[parts.length - 1]);
264
- if (endsInVariable) {
265
- const name = dict[httpMethod];
266
- if (usedNames.includes(name)) {
267
- return name + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 2]);
268
- }
269
- return name;
270
- }
271
- if (httpMethod === "get" || httpMethod === "put" || httpMethod === "patch") {
272
- let name = dict[httpMethod] + "All";
273
- if (!usedNames.includes(name)) {
274
- return name;
275
- }
276
- name = dict[httpMethod] + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
277
- if (!usedNames.includes(name)) {
278
- return name;
279
- }
280
- return dict[httpMethod] + "By" + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
281
- }
282
- if (httpMethod === "post") {
283
- let name = dict[httpMethod];
284
- if (!usedNames.includes(name)) {
285
- return name;
286
- }
287
- name = (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
288
- if (!usedNames.includes(name)) {
289
- return name;
290
- }
291
- name = "createBy" + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
292
- if (!usedNames.includes(name)) {
293
- return name;
294
- }
295
- return "create" + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
296
- }
297
- const name = dict[httpMethod];
298
- if (usedNames.includes(name)) {
299
- return name + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
300
- }
301
- return name + "By" + (0, string_utils_1.kebabToPascalCase)(parts[parts.length - 1]);
302
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AngularRequestType = exports.AngularResponseType = exports.NativeType = void 0;
4
- var NativeType;
5
- (function (NativeType) {
6
- NativeType["String"] = "string";
7
- NativeType["Number"] = "number";
8
- NativeType["Boolean"] = "boolean";
9
- NativeType["Array"] = "Array";
10
- NativeType["Date"] = "Date";
11
- NativeType["File"] = "File";
12
- NativeType["Any"] = "any";
13
- NativeType["Void"] = "void";
14
- })(NativeType || (exports.NativeType = NativeType = {}));
15
- var AngularResponseType;
16
- (function (AngularResponseType) {
17
- AngularResponseType["Json"] = "json";
18
- AngularResponseType["Text"] = "text";
19
- AngularResponseType["Blob"] = "blob";
20
- AngularResponseType["ArrayBuffer"] = "arrayBuffer";
21
- })(AngularResponseType || (exports.AngularResponseType = AngularResponseType = {}));
22
- var AngularRequestType;
23
- (function (AngularRequestType) {
24
- AngularRequestType["Get"] = "get";
25
- AngularRequestType["Post"] = "post";
26
- AngularRequestType["Put"] = "put";
27
- AngularRequestType["Delete"] = "delete";
28
- AngularRequestType["Patch"] = "patch";
29
- })(AngularRequestType || (exports.AngularRequestType = AngularRequestType = {}));
@@ -1,62 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.interfaceDataStore = void 0;
4
- class InterfaceDataStore {
5
- genericInterfaces = {};
6
- baseInterfaces = {};
7
- generatedInterfaces = {};
8
- generatedEnums = {};
9
- componentsSchemas = {};
10
- constructor() { }
11
- setComponentsSchemas(componentsSchemas) {
12
- this.componentsSchemas = componentsSchemas;
13
- }
14
- getComponentsSchema(name) {
15
- return this.componentsSchemas[name];
16
- }
17
- exists(name) {
18
- return (this.genericInterfaces[name] !== undefined ||
19
- this.baseInterfaces[name] !== undefined ||
20
- this.generatedInterfaces[name] !== undefined ||
21
- this.generatedEnums[name] !== undefined);
22
- }
23
- addInterfaces(interfacesData) {
24
- for (const inter of interfacesData) {
25
- this.generatedInterfaces[inter.name] = inter;
26
- }
27
- }
28
- computeExtendsFrom(properties) {
29
- if (properties.length === 0)
30
- return { extendsFrom: undefined, properties: [] };
31
- const currentPropertiesNames = new Set(properties.map((p) => p.name));
32
- for (const [name, schema] of Object.entries(this.baseInterfaces)) {
33
- if (schema.properties.length !== properties.length)
34
- continue;
35
- const required = schema.properties
36
- .filter((p) => !p.optional)
37
- .map((p) => p.name);
38
- if (required.some((r) => !currentPropertiesNames.has(r))) {
39
- continue;
40
- }
41
- const optional = schema.properties
42
- .filter((p) => p.optional)
43
- .map((p) => p.name);
44
- const remainingProperties = properties
45
- .filter((p) => !required.includes(p.name))
46
- .filter((p) => !optional.includes(p.name));
47
- if (remainingProperties.length === 0 &&
48
- schema.properties.some((p) => p.type === "generic")) {
49
- return {
50
- extendsFrom: name,
51
- properties: [],
52
- };
53
- }
54
- return {
55
- extendsFrom: name,
56
- properties: remainingProperties,
57
- };
58
- }
59
- return { extendsFrom: undefined, properties };
60
- }
61
- }
62
- exports.interfaceDataStore = new InterfaceDataStore();
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serviceStore = void 0;
4
- class ServiceStore {
5
- services = {};
6
- addService(name, content) {
7
- this.services[name] = content;
8
- }
9
- addServices(services) {
10
- services.forEach((service) => {
11
- this.services[service.name] = service;
12
- });
13
- }
14
- getService(name) {
15
- return this.services[name];
16
- }
17
- }
18
- exports.serviceStore = new ServiceStore();