swaggular 0.5.0 → 0.6.1

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/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.main = main;
5
5
  const swagger_parser_1 = require("./parsers/swagger-parser");
6
+ const location_factory_1 = require("./utils/location-factory");
6
7
  const generate_interface_1 = require("./renderers/generate-interface");
7
8
  const generate_service_1 = require("./renderers/generate-service");
8
9
  const args_1 = require("./cli/args");
@@ -18,10 +19,11 @@ async function main() {
18
19
  segmentsToIgnore: variables.segmentsToIgnore,
19
20
  ignoreVariables: true,
20
21
  });
22
+ const locations = (0, location_factory_1.computeLocations)();
21
23
  (0, generate_interface_1.generateInterfaces)(variables);
22
24
  (0, generate_service_1.generateServices)();
23
- const interfaceFiles = (0, generate_interface_1.generateInterfacesFiles)(undefined, variables);
24
- const serviceFiles = (0, generate_service_1.generateServiceFiles)(undefined, variables.templates);
25
+ const interfaceFiles = (0, generate_interface_1.generateInterfacesFiles)(locations, variables);
26
+ const serviceFiles = (0, generate_service_1.generateServiceFiles)(locations, variables.templates);
25
27
  if (variables.noGenerate) {
26
28
  console.log('Files not generated');
27
29
  return;
@@ -20,7 +20,7 @@ function generateInterfaceComments(param) {
20
20
  comments.push(`maximum: ${param.maximum}`);
21
21
  }
22
22
  if (comments.length > 0) {
23
- return ` /**\n * ${comments.join('\n * ')}\n */`;
23
+ return `/**\n * ${comments.join('\n * ')}\n */`;
24
24
  }
25
25
  return '';
26
26
  }
@@ -1,13 +1,11 @@
1
1
  import { OpenAPIV3 } from 'openapi-types';
2
2
  import { FileContent } from '../types/file-content';
3
- import { GroupedPath } from '../types/grouped-paths';
4
3
  import { InterfaceData, InterfaceDataProperty } from '../types/interface-data';
5
4
  import { SwaggularConfig } from '../types/config';
6
5
  export declare function parametersToIProperties(parameters: (OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject)[]): InterfaceDataProperty[];
7
6
  export declare function propertiesToIProperties(properties: Record<string, OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject>): InterfaceDataProperty[];
8
7
  export declare function generateInterfaces(templatesConfig?: SwaggularConfig): void;
9
8
  export declare function generateWithParameters(templatesConfig?: SwaggularConfig): void;
10
- export declare function computeParametersName(method: string, innerPath: string, groupedPath: GroupedPath): string;
11
9
  export declare function generateComponentsSchemas(templatesConfig?: SwaggularConfig): void;
12
10
  export declare function generateInterfacesFiles(locations?: Record<string, string[]>, templatesConfig?: SwaggularConfig): FileContent[];
13
11
  export declare function generateContent(interfaceData: InterfaceData, deep?: number): string;
@@ -4,7 +4,6 @@ exports.parametersToIProperties = parametersToIProperties;
4
4
  exports.propertiesToIProperties = propertiesToIProperties;
5
5
  exports.generateInterfaces = generateInterfaces;
6
6
  exports.generateWithParameters = generateWithParameters;
7
- exports.computeParametersName = computeParametersName;
8
7
  exports.generateComponentsSchemas = generateComponentsSchemas;
9
8
  exports.generateInterfacesFiles = generateInterfacesFiles;
10
9
  exports.generateContent = generateContent;
@@ -94,6 +93,9 @@ function computeExtendsFromType(data, extendsTypes) {
94
93
  if (extendsFromTypePropertiesReq.some((p) => !dataPropertiesReq.includes(p))) {
95
94
  continue;
96
95
  }
96
+ if (!extendsFromType.properties.some((ep) => data.properties.some((dp) => dp.name === ep.name))) {
97
+ continue;
98
+ }
97
99
  const extensionProperties = extendsFromType.properties.map((p) => p.name.toLowerCase());
98
100
  return {
99
101
  ...data,
@@ -135,7 +137,7 @@ function generateWithParameters(templatesConfig) {
135
137
  const properties = parametersToIProperties(parameters);
136
138
  if (properties.length === 0)
137
139
  continue;
138
- const interfaceName = computeParametersName(httpMethod, innerPath, groupedPath);
140
+ const interfaceName = (0, path_utils_1.computeParametersName)(httpMethod, innerPath, groupedPath);
139
141
  const interData = {
140
142
  name: interfaceName,
141
143
  type: 'interface',
@@ -152,24 +154,6 @@ function generateWithParameters(templatesConfig) {
152
154
  }
153
155
  interface_state_1.interfaceState.addInterfaces(interfacesData);
154
156
  }
155
- function computeParametersName(method, innerPath, groupedPath) {
156
- const dict = {
157
- get: '',
158
- post: 'Create',
159
- put: 'Update',
160
- delete: 'Delete',
161
- patch: 'Patch',
162
- };
163
- const name = dict[method];
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('')));
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';
172
- }
173
157
  function generateComponentsSchemas(templatesConfig) {
174
158
  const schemas = swagger_state_1.swaggerState.getSchemas();
175
159
  if (!schemas)
@@ -305,14 +289,14 @@ function generateContent(interfaceData, deep = 0) {
305
289
  .map((p) => p.type.replace('[]', ''));
306
290
  const content = `${importsTemplate}\n\nexport interface ${interfaceData.name}${genericTypes.length > 0 ? `<${genericTypes.join(', ')}>` : ''} ${interfaceData.extendsFrom && interfaceData.extendsFrom.length > 0 ? `extends ${interfaceData.extendsFrom.join(', ')}` : ''} {
307
291
  ${interfaceData.properties
308
- .map((p) => `${p.comments}\n\t${(0, string_utils_1.lowerFirst)(p.name)}${p.optional ? '?' : ''}: ${p.type};`)
292
+ .map((p) => `${p.comments}\n ${(0, string_utils_1.lowerFirst)(p.name)}${p.optional ? '?' : ''}: ${p.type};`)
309
293
  .join('\n')}
310
294
  }`;
311
295
  return content;
312
296
  }
313
297
  if (interfaceData.type === 'enum') {
314
298
  const content = `export enum ${interfaceData.name} {
315
- ${interfaceData.properties.map((p) => `${p.comments}\n\t${p.name} = '${p.type}',`).join('\n')}
299
+ ${interfaceData.properties.map((p) => `${p.comments}\n ${p.name} = '${p.type}',`).join('\n')}
316
300
  }`;
317
301
  return content;
318
302
  }
@@ -11,7 +11,7 @@ const string_utils_1 = require("../utils/string-utils");
11
11
  const type_guard_1 = require("../utils/type-guard");
12
12
  const generate_comments_1 = require("./generate-comments");
13
13
  const object_utils_1 = require("../utils/object-utils");
14
- const generate_interface_1 = require("./generate-interface");
14
+ const path_utils_2 = require("../utils/path-utils");
15
15
  const interface_state_1 = require("../core/state/interface-state");
16
16
  const template_renderer_1 = require("../utils/template-renderer");
17
17
  /**
@@ -82,13 +82,15 @@ function generateServiceFiles(locations, templatesConfig) {
82
82
  baseUrl: service.baseUrl,
83
83
  methods: methods,
84
84
  imports: allImports.join(', '),
85
- modelImports: allImports.length > 0 ? `import { ${allImports.join(', ')} } from '../models';` : '',
85
+ modelImports: allImports.length > 0
86
+ ? `import { ${allImports.join(', ')} } from '${'../'.repeat(location.length)}models';`
87
+ : '',
86
88
  hasHttpParamsHandler: hasHttpParams,
87
89
  httpParamsHandler: serviceTemplateConfig?.options?.httpParamsHandler,
88
90
  httpParamsHandlerImport: hasHttpParams
89
91
  ? serviceTemplateConfig?.options?.httpParamsHandlerImport
90
92
  : '',
91
- extraAngularImports: hasHttpParams ? ', HttpParams' : '',
93
+ extraAngularImports: hasHttpParams && !serviceTemplateConfig?.options?.httpParamsHandler ? ', HttpParams' : '',
92
94
  };
93
95
  const content = (0, template_renderer_1.renderServiceTemplate)(templatePath, templateParams);
94
96
  filesContent.push({
@@ -116,7 +118,7 @@ function buildMethods(groupedPath, pathData, serviceName) {
116
118
  const queryParams = parameters.filter((p) => p.in === 'query');
117
119
  let queryParamType;
118
120
  if (queryParams.length > 0) {
119
- queryParamType = (0, generate_interface_1.computeParametersName)(method, path, groupedPath);
121
+ queryParamType = (0, path_utils_2.computeParametersName)(method, path, groupedPath);
120
122
  }
121
123
  const commentParams = parameters.filter((p) => p.in !== 'query');
122
124
  if (queryParamType) {
@@ -359,7 +361,7 @@ function buildMethodTemplate(method, httpParamsHandlerTemplate) {
359
361
  let paramsLogic = '';
360
362
  if (method.queryParamType) {
361
363
  if (httpParamsHandlerTemplate) {
362
- paramsLogic = `\n\t\t${httpParamsHandlerTemplate.replace('${params}', 'queryParams')}`;
364
+ paramsLogic = `\n ${httpParamsHandlerTemplate.replace('${params}', 'queryParams')}`;
363
365
  }
364
366
  else {
365
367
  paramsLogic = `
@@ -0,0 +1 @@
1
+ export declare function computeLocations(): Record<string, string[]>;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeLocations = computeLocations;
4
+ const swagger_state_1 = require("../core/state/swagger-state");
5
+ const string_utils_1 = require("./string-utils");
6
+ const path_utils_1 = require("./path-utils");
7
+ function computeLocations() {
8
+ const swagger = swagger_state_1.swaggerState.getSwagger();
9
+ const groupedPaths = swagger_state_1.swaggerState.getPathsGroupedByScope();
10
+ const locations = {};
11
+ if (!swagger || !swagger.paths) {
12
+ return locations;
13
+ }
14
+ const processSchema = (dtoName, location) => {
15
+ if (locations[dtoName])
16
+ return;
17
+ if (isEnum(dtoName))
18
+ return;
19
+ locations[dtoName] = location;
20
+ const schemas = swagger_state_1.swaggerState.getSchemas();
21
+ if (!schemas || !schemas[dtoName])
22
+ return;
23
+ const schema = schemas[dtoName];
24
+ const refs = getReferences(schema);
25
+ for (const ref of refs) {
26
+ const childName = ref.split('/').pop();
27
+ if (childName) {
28
+ processSchema(childName, location);
29
+ }
30
+ }
31
+ };
32
+ if (groupedPaths) {
33
+ for (const [groupName, group] of Object.entries(groupedPaths)) {
34
+ if (group.baseSegments && group.baseSegments.length > 0) {
35
+ const folder = (0, string_utils_1.toKebabCase)(group.baseSegments[0]);
36
+ if (!locations[groupName]) {
37
+ locations[groupName] = [folder];
38
+ }
39
+ }
40
+ }
41
+ }
42
+ // 1. Map Generated Parameter Interfaces
43
+ if (groupedPaths) {
44
+ for (const groupedPath of Object.values(groupedPaths)) {
45
+ for (const innerPath of groupedPath.paths) {
46
+ const pathInfo = swagger.paths[innerPath];
47
+ if (!pathInfo)
48
+ continue;
49
+ const methods = ['get', 'post', 'put', 'delete', 'patch'];
50
+ for (const method of methods) {
51
+ const operation = pathInfo[method];
52
+ if (!operation)
53
+ continue;
54
+ // Check if parameters exist (similar condition to generate-interface)
55
+ if (operation.parameters && operation.parameters.length > 0) {
56
+ const interfaceName = (0, path_utils_1.computeParametersName)(method, innerPath, groupedPath);
57
+ if (operation.tags && operation.tags.length > 0) {
58
+ const tag = operation.tags[0];
59
+ const folder = (0, string_utils_1.toKebabCase)(tag);
60
+ if (!locations[interfaceName]) {
61
+ locations[interfaceName] = [folder];
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ // 2. Map DTOs and Services
70
+ for (const pathItem of Object.values(swagger.paths)) {
71
+ if (!pathItem)
72
+ continue;
73
+ const operations = [
74
+ pathItem.get,
75
+ pathItem.put,
76
+ pathItem.post,
77
+ pathItem.delete,
78
+ pathItem.options,
79
+ pathItem.head,
80
+ pathItem.patch,
81
+ pathItem.trace,
82
+ ];
83
+ for (const operation of operations) {
84
+ if (!operation || !operation.tags || operation.tags.length === 0) {
85
+ continue;
86
+ }
87
+ const tag = operation.tags[0];
88
+ const folder = (0, string_utils_1.toKebabCase)(tag);
89
+ const location = [folder];
90
+ // Map Service (Tag) to location
91
+ if (!locations[tag]) {
92
+ locations[tag] = location;
93
+ }
94
+ // Map DTOs used in this operation
95
+ const refs = getReferences(operation);
96
+ for (const ref of refs) {
97
+ const dtoName = ref.split('/').pop();
98
+ if (dtoName) {
99
+ processSchema(dtoName, location);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return locations;
105
+ }
106
+ function isEnum(name) {
107
+ const schemas = swagger_state_1.swaggerState.getSchemas();
108
+ if (!schemas)
109
+ return false;
110
+ const schema = schemas[name];
111
+ if (!schema)
112
+ return false;
113
+ if ('$ref' in schema)
114
+ return false;
115
+ return !!schema.enum;
116
+ }
117
+ function getReferences(obj) {
118
+ const refs = [];
119
+ if (!obj || typeof obj !== 'object') {
120
+ return refs;
121
+ }
122
+ if (Array.isArray(obj)) {
123
+ for (const item of obj) {
124
+ refs.push(...getReferences(item));
125
+ }
126
+ return refs;
127
+ }
128
+ for (const key of Object.keys(obj)) {
129
+ if (key === '$ref' && typeof obj[key] === 'string') {
130
+ refs.push(obj[key]);
131
+ }
132
+ else {
133
+ refs.push(...getReferences(obj[key]));
134
+ }
135
+ }
136
+ return refs;
137
+ }
@@ -1,6 +1,8 @@
1
+ import { GroupedPath } from '../types/grouped-paths';
1
2
  export declare function isVariable(segment: string): boolean;
2
3
  export declare function getExtraSegments(fullPath: string, baseUrl: string): string[];
3
4
  export declare function removeVariablesFromPath(path: string): string;
4
5
  export declare function createBaseUrl(baseSegments: string[]): string;
5
6
  export declare function findCommonBaseUrl(paths: string[]): string;
6
7
  export declare function standarizedPath(path: string): string;
8
+ export declare function computeParametersName(method: string, innerPath: string, groupedPath: GroupedPath): string;
@@ -6,6 +6,8 @@ exports.removeVariablesFromPath = removeVariablesFromPath;
6
6
  exports.createBaseUrl = createBaseUrl;
7
7
  exports.findCommonBaseUrl = findCommonBaseUrl;
8
8
  exports.standarizedPath = standarizedPath;
9
+ exports.computeParametersName = computeParametersName;
10
+ const string_utils_1 = require("./string-utils");
9
11
  function isVariable(segment) {
10
12
  return /^\{.+\}$/.test(segment);
11
13
  }
@@ -63,3 +65,21 @@ function standarizedPath(path) {
63
65
  const filtered = splitted.filter((p) => p !== '').map((p) => p.toLowerCase());
64
66
  return filtered.join('/');
65
67
  }
68
+ function computeParametersName(method, innerPath, groupedPath) {
69
+ const dict = {
70
+ get: '',
71
+ post: 'Create',
72
+ put: 'Update',
73
+ delete: 'Delete',
74
+ patch: 'Patch',
75
+ };
76
+ const name = dict[method];
77
+ const extra = (0, string_utils_1.kebabToPascalCase)(removeVariablesFromPath(getExtraSegments(innerPath, createBaseUrl(groupedPath.baseSegments)).join('')));
78
+ // Avoid duplication if extra starts with groupName
79
+ let suffix = extra;
80
+ const groupName = groupedPath.groupName;
81
+ if (suffix.startsWith(groupName)) {
82
+ suffix = suffix.substring(groupName.length);
83
+ }
84
+ return name + groupName + (0, string_utils_1.upFirst)(suffix) + 'Params';
85
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swaggular",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "bin": {