serverless-openapi-documenter 0.0.107 → 0.0.108

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverless-openapi-documenter",
3
- "version": "0.0.107",
3
+ "version": "0.0.108",
4
4
  "description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -27,7 +27,8 @@
27
27
  "Api Gateway",
28
28
  "APIGateway",
29
29
  "AWSAPIGateway",
30
- "Serverless OpenAPI"
30
+ "Serverless OpenAPI",
31
+ "serverless openapi"
31
32
  ],
32
33
  "scripts": {
33
34
  "test": "mocha --config './test/.mocharc.js'"
@@ -15,7 +15,9 @@ const SchemaHandler = require("./schemaHandler");
15
15
  const oWASP = require("./owasp");
16
16
 
17
17
  class DefinitionGenerator {
18
- constructor(serverless, options = {}) {
18
+ constructor(serverless, logger) {
19
+ this.logger = logger;
20
+
19
21
  this.version =
20
22
  serverless?.processedInput?.options?.openApiVersion || "3.0.0";
21
23
 
@@ -70,6 +72,12 @@ class DefinitionGenerator {
70
72
  };
71
73
 
72
74
  try {
75
+ this.logger.verbose(
76
+ `Trying to resolve Redocly rules from: ${path.resolve(
77
+ "options",
78
+ "redocly.json"
79
+ )}`
80
+ );
73
81
  this.REDOCLY_RULES = require(path.resolve("options", "redocly.json"));
74
82
  } catch (err) {
75
83
  this.REDOCLY_RULES = {
@@ -83,6 +91,12 @@ class DefinitionGenerator {
83
91
  }
84
92
 
85
93
  try {
94
+ this.logger.verbose(
95
+ `Trying to resolve Ref-Parser options from: ${path.resolve(
96
+ "options",
97
+ "ref-parser.js"
98
+ )}`
99
+ );
86
100
  this.refParserOptions = require(path.resolve("options", "ref-parser.js"));
87
101
  } catch (err) {
88
102
  this.refParserOptions = {};
package/src/logger.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ class Logger {
4
+ constructor(serverless, log) {
5
+ this.serverless = serverless;
6
+ this.logOutput = log;
7
+
8
+ this.logTypes = {
9
+ NOTICE: "notice",
10
+ DEBUG: "debug",
11
+ ERROR: "error",
12
+ WARNING: "warning",
13
+ INFO: "info",
14
+ VERBOSE: "verbose",
15
+ SUCCESS: "success",
16
+ };
17
+
18
+ this.defaultLog = this.logTypes.NOTICE;
19
+ }
20
+
21
+ log(str, type = this.defaultLog) {
22
+ switch (this.serverless.version[0]) {
23
+ case "2":
24
+ let colouredString = str;
25
+ if (type === "error") {
26
+ colouredString = chalk.bold.red(`✖ ${str}`);
27
+ } else if (type === "success") {
28
+ colouredString = chalk.bold.green(`✓ ${str}`);
29
+ }
30
+
31
+ this.serverless.cli.log(colouredString);
32
+ break;
33
+
34
+ case "4":
35
+ case "3":
36
+ this.logOutput[type](str);
37
+ break;
38
+
39
+ default:
40
+ process.stdout.write(str.join(" "));
41
+ break;
42
+ }
43
+ }
44
+
45
+ debug(str) {
46
+ this.log(str, this.logTypes.DEBUG);
47
+ }
48
+
49
+ error(str) {
50
+ this.log(str, this.logTypes.ERROR);
51
+ }
52
+
53
+ info(str) {
54
+ this.log(str, this.logTypes.INFO);
55
+ }
56
+
57
+ notice(str) {
58
+ this.log(str, this.logTypes.NOTICE);
59
+ }
60
+
61
+ success(str) {
62
+ this.log(str, this.logTypes.SUCCESS);
63
+ }
64
+
65
+ verbose(str) {
66
+ this.log(str, this.logTypes.VERBOSE);
67
+ }
68
+
69
+ warning(str) {
70
+ this.log(str, this.logTypes.WARNING);
71
+ }
72
+ }
73
+
74
+ module.exports = Logger;
@@ -5,6 +5,7 @@ const yaml = require("js-yaml");
5
5
  const chalk = require("chalk");
6
6
 
7
7
  const DefinitionGenerator = require("./definitionGenerator");
8
+ const Logger = require("./logger");
8
9
  const PostmanGenerator = require("openapi-to-postmanv2");
9
10
 
10
11
  class OpenAPIGenerator {
@@ -12,18 +13,7 @@ class OpenAPIGenerator {
12
13
  this.logOutput = log;
13
14
  this.serverless = serverless;
14
15
  this.options = options;
15
-
16
- this.logTypes = {
17
- NOTICE: "notice",
18
- DEBUG: "debug",
19
- ERROR: "error",
20
- WARNING: "warning",
21
- INFO: "info",
22
- VERBOSE: "verbose",
23
- SUCCESS: "success",
24
- };
25
-
26
- this.defaultLog = this.logTypes.NOTICE;
16
+ this.logger = new Logger(this.serverless, this.logOutput);
27
17
 
28
18
  this.commands = {
29
19
  openapi: {
@@ -145,7 +135,9 @@ class OpenAPIGenerator {
145
135
  }
146
136
 
147
137
  async generate() {
148
- this.log(chalk.bold.underline("OpenAPI v3 Description Generation"));
138
+ this.logger.notice(
139
+ chalk.bold.underline("OpenAPI v3 Description Generation")
140
+ );
149
141
  this.processCliInput();
150
142
 
151
143
  const validOpenAPI = await this.generationAndValidation().catch((err) => {
@@ -168,37 +160,31 @@ class OpenAPIGenerator {
168
160
  }
169
161
  try {
170
162
  fs.writeFileSync(this.config.file, output);
171
- this.log(
172
- "OpenAPI v3 Description Successfully Written",
173
- this.logTypes.SUCCESS
174
- );
163
+ this.logger.success("OpenAPI v3 Description Successfully Written");
175
164
  } catch (err) {
176
- this.log(
177
- `ERROR: An error was thrown whilst writing the OpenAPI Description`,
178
- this.logTypes.ERROR
165
+ this.logger.error(
166
+ `ERROR: An error was thrown whilst writing the OpenAPI Description`
179
167
  );
180
168
  throw new this.serverless.classes.Error(err);
181
169
  }
182
170
  }
183
171
 
184
172
  async generationAndValidation() {
185
- const generator = new DefinitionGenerator(this.serverless);
173
+ const generator = new DefinitionGenerator(this.serverless, this.logger);
186
174
 
187
- this.log(`Generating OpenAPI Description`, this.logTypes.NOTICE);
175
+ this.logger.notice(`Generating OpenAPI Description`);
188
176
  await generator.parse().catch((err) => {
189
- this.log(
190
- `ERROR: An error was thrown generating the OpenAPI v3 Description`,
191
- this.logTypes.ERROR
177
+ this.logger.error(
178
+ `ERROR: An error was thrown generating the OpenAPI v3 Description`
192
179
  );
193
180
  throw new this.serverless.classes.Error(err);
194
181
  });
195
182
 
196
- this.log(`Validating generated OpenAPI Description`, this.logTypes.NOTICE);
183
+ this.logger.notice(`Validating generated OpenAPI Description`);
197
184
 
198
185
  const validationResults = await generator.validate().catch((err) => {
199
- this.log(
200
- `ERROR: An error was thrown validating the OpenAPI v3 Description`,
201
- this.logTypes.ERROR
186
+ this.logger.error(
187
+ `ERROR: An error was thrown validating the OpenAPI v3 Description`
202
188
  );
203
189
 
204
190
  throw new this.serverless.classes.Error(err);
@@ -219,10 +205,7 @@ class OpenAPIGenerator {
219
205
  if (shouldThrow) throw new this.serverless.classes.Error(message);
220
206
  }
221
207
 
222
- this.log(
223
- "OpenAPI v3 Description Successfully Generated",
224
- this.logTypes.SUCCESS
225
- );
208
+ this.logger.success("OpenAPI v3 Description Successfully Generated");
226
209
 
227
210
  return generator.openAPI;
228
211
  }
@@ -230,31 +213,29 @@ class OpenAPIGenerator {
230
213
  createPostman(openAPI) {
231
214
  const postmanGeneration = (err, result) => {
232
215
  if (err) {
233
- this.log(
234
- `ERROR: An error was thrown when generating the postman collection`,
235
- this.logTypes.ERROR
216
+ this.logger.error(
217
+ `ERROR: An error was thrown when generating the postman collection`
236
218
  );
237
219
  throw new this.serverless.classes.Error(err);
238
220
  }
239
221
 
240
- this.log(
241
- "postman collection v2 Documentation Successfully Generated",
242
- this.logTypes.SUCCESS
222
+ this.logger.success(
223
+ "postman collection v2 Documentation Successfully Generated"
243
224
  );
225
+
244
226
  try {
245
227
  fs.writeFileSync(
246
228
  this.config.postmanCollection,
247
229
  JSON.stringify(result.output[0].data)
248
230
  );
249
- this.log(
250
- "postman collection v2 Documentation Successfully Written",
251
- this.logTypes.SUCCESS
231
+ this.logger.success(
232
+ "postman collection v2 Documentation Successfully Written"
252
233
  );
253
234
  } catch (err) {
254
- this.log(
255
- `ERROR: An error was thrown whilst writing the postman collection`,
256
- this.logTypes.ERROR
235
+ this.logger.error(
236
+ `ERROR: An error was thrown whilst writing the postman collection`
257
237
  );
238
+
258
239
  throw new this.serverless.classes.Error(err);
259
240
  }
260
241
  };
@@ -295,7 +276,7 @@ class OpenAPIGenerator {
295
276
  this.serverless.processedInput.options.output ||
296
277
  (config.format === "yaml" ? "openapi.yml" : "openapi.json");
297
278
 
298
- this.log(
279
+ this.logger.notice(
299
280
  `${chalk.bold.green("[OPTIONS]")}
300
281
  openApiVersion: "${chalk.bold.green(String(config.openApiVersion))}"
301
282
  format: "${chalk.bold.green(config.format)}"
@@ -314,26 +295,18 @@ class OpenAPIGenerator {
314
295
 
315
296
  validationErrorDetails(validationErrors) {
316
297
  if (validationErrors.length) {
317
- this.log(
298
+ this.logger.error(
318
299
  `${chalk.bold.yellow(
319
300
  "[VALIDATION]"
320
- )} Validation errors found in OpenAPI Description: \n`,
321
- this.logTypes.ERROR
301
+ )} Validation errors found in OpenAPI Description: \n`
322
302
  );
323
303
 
324
304
  for (const error of validationErrors) {
325
- this.log(
326
- `${chalk.bold.red("Severity:")} ${error.severity}`,
327
- this.logTypes.ERROR
328
- );
329
- this.log(
330
- `${chalk.bold.yellow("Message:")} ${error.message}`,
331
- this.logTypes.ERROR
332
- );
305
+ this.logger.error(`${chalk.bold.red("Severity:")} ${error.severity}`);
306
+ this.logger.error(`${chalk.bold.yellow("Message:")} ${error.message}`);
333
307
  for (const location of error.location) {
334
- this.log(
335
- `${chalk.bold.yellow("found at location:")} ${location.pointer}`,
336
- this.logTypes.ERROR
308
+ this.logger.error(
309
+ `${chalk.bold.yellow("found at location:")} ${location.pointer}`
337
310
  );
338
311
  }
339
312
  }
@@ -26,7 +26,11 @@ describe("DefinitionGenerator", () => {
26
26
 
27
27
  describe("constructor", () => {
28
28
  it("should return a definitionGenerator", function () {
29
- const expected = new DefinitionGenerator(mockServerless, {});
29
+ const expected = new DefinitionGenerator(mockServerless, {
30
+ verbose: (str) => {
31
+ console.log(str);
32
+ },
33
+ });
30
34
  expect(expected).to.be.an.instanceOf(DefinitionGenerator);
31
35
  });
32
36
 
@@ -35,48 +39,73 @@ describe("DefinitionGenerator", () => {
35
39
  JSON.stringify(mockServerless)
36
40
  );
37
41
  delete serverlessWithoutOpenAPIVersion.processedInput;
38
- let expected = new DefinitionGenerator(
39
- serverlessWithoutOpenAPIVersion,
40
- {}
41
- );
42
+ let expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
43
+ verbose: (str) => {
44
+ console.log(str);
45
+ },
46
+ });
42
47
  expect(expected.version).to.be.equal("3.0.0");
43
48
 
44
49
  Object.assign(serverlessWithoutOpenAPIVersion, { processedInput: {} });
45
- expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {});
50
+ expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
51
+ verbose: (str) => {
52
+ console.log(str);
53
+ },
54
+ });
46
55
  expect(expected.version).to.be.equal("3.0.0");
47
56
 
48
57
  serverlessWithoutOpenAPIVersion.processedInput = {
49
58
  options: {},
50
59
  };
51
- expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {});
60
+ expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
61
+ verbose: (str) => {
62
+ console.log(str);
63
+ },
64
+ });
52
65
  expect(expected.version).to.be.equal("3.0.0");
53
66
 
54
67
  serverlessWithoutOpenAPIVersion.processedInput.options = {
55
68
  test: "abc",
56
69
  };
57
70
 
58
- expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {});
71
+ expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
72
+ verbose: (str) => {
73
+ console.log(str);
74
+ },
75
+ });
59
76
  expect(expected.version).to.be.equal("3.0.0");
60
77
 
61
78
  serverlessWithoutOpenAPIVersion.processedInput.options = {
62
79
  openApiVersion: null,
63
80
  };
64
81
 
65
- expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {});
82
+ expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
83
+ verbose: (str) => {
84
+ console.log(str);
85
+ },
86
+ });
66
87
  expect(expected.version).to.be.equal("3.0.0");
67
88
 
68
89
  serverlessWithoutOpenAPIVersion.processedInput.options = {
69
90
  openApiVersion: undefined,
70
91
  };
71
92
 
72
- expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {});
93
+ expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
94
+ verbose: (str) => {
95
+ console.log(str);
96
+ },
97
+ });
73
98
  expect(expected.version).to.be.equal("3.0.0");
74
99
 
75
100
  serverlessWithoutOpenAPIVersion.processedInput.options = {
76
101
  openapiVersion: undefined,
77
102
  };
78
103
 
79
- expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {});
104
+ expected = new DefinitionGenerator(serverlessWithoutOpenAPIVersion, {
105
+ verbose: (str) => {
106
+ console.log(str);
107
+ },
108
+ });
80
109
  expect(expected.version).to.be.equal("3.0.0");
81
110
  });
82
111
 
@@ -86,12 +115,20 @@ describe("DefinitionGenerator", () => {
86
115
  );
87
116
  serverlessWithOpenAPIVersion.processedInput.options.openApiVersion =
88
117
  "3.0.2";
89
- let expected = new DefinitionGenerator(serverlessWithOpenAPIVersion, {});
118
+ let expected = new DefinitionGenerator(serverlessWithOpenAPIVersion, {
119
+ verbose: (str) => {
120
+ console.log(str);
121
+ },
122
+ });
90
123
  expect(expected.version).to.be.equal("3.0.2");
91
124
 
92
125
  serverlessWithOpenAPIVersion.processedInput.options.openApiVersion =
93
126
  "3.0.1";
94
- expected = new DefinitionGenerator(serverlessWithOpenAPIVersion, {});
127
+ expected = new DefinitionGenerator(serverlessWithOpenAPIVersion, {
128
+ verbose: (str) => {
129
+ console.log(str);
130
+ },
131
+ });
95
132
  expect(expected.version).to.be.equal("3.0.1");
96
133
  });
97
134
 
@@ -111,7 +148,11 @@ describe("DefinitionGenerator", () => {
111
148
  throw err;
112
149
  });
113
150
 
114
- const expected = new DefinitionGenerator(mockServerless, {});
151
+ const expected = new DefinitionGenerator(mockServerless, {
152
+ verbose: (str) => {
153
+ console.log(str);
154
+ },
155
+ });
115
156
 
116
157
  expect(expected.REDOCLY_RULES).to.have.property(
117
158
  "operation-2xx-response",
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+
3
+ const expect = require("chai").expect;
4
+ const sinon = require("sinon");
5
+
6
+ const Logger = require("../../src/logger");
7
+
8
+ describe(`Logger`, function () {
9
+ let sls, logOutput;
10
+
11
+ beforeEach(function () {
12
+ sls = {
13
+ service: {
14
+ service: "test-service",
15
+ provider: {
16
+ stage: "test",
17
+ },
18
+ getAllFunctions: () => {},
19
+ getFunction: () => {},
20
+ },
21
+ version: "3.0.0",
22
+ variables: {
23
+ service: {
24
+ custom: {},
25
+ },
26
+ },
27
+ configSchemaHandler: {
28
+ defineFunctionEventProperties: () => {},
29
+ defineFunctionProperties: () => {},
30
+ defineCustomProperties: () => {},
31
+ },
32
+ classes: {
33
+ Error: class ServerlessError {
34
+ constructor(err) {
35
+ return new Error(err);
36
+ }
37
+ },
38
+ },
39
+ processedInput: {
40
+ options: {
41
+ postmanCollection: "postman.json",
42
+ },
43
+ },
44
+ };
45
+
46
+ logOutput = {
47
+ log: {
48
+ debug: (str) => {},
49
+ error: (str) => {},
50
+ info: (str) => {},
51
+ notice: (str) => {},
52
+ success: (str) => {},
53
+ verbose: (str) => {},
54
+ warning: (str) => {},
55
+ },
56
+ };
57
+ });
58
+
59
+ describe(`debug`, function () {
60
+ it(`should log a debug log type when debug is called`, function () {
61
+ const logger = new Logger(sls, logOutput.log);
62
+ const spy = sinon.spy(logger, "log");
63
+
64
+ logger.debug("Testing");
65
+
66
+ expect(spy.called).to.be.true;
67
+
68
+ spy.restore();
69
+ });
70
+ });
71
+
72
+ describe(`error`, function () {
73
+ it(`should log a error log type when error is called`, function () {
74
+ const logger = new Logger(sls, logOutput.log);
75
+ const spy = sinon.spy(logger, "log");
76
+
77
+ logger.error("Testing");
78
+
79
+ expect(spy.called).to.be.true;
80
+
81
+ spy.restore();
82
+ });
83
+ });
84
+
85
+ describe(`info`, function () {
86
+ it(`should log a info log type when info is called`, function () {
87
+ const logger = new Logger(sls, logOutput.log);
88
+ const spy = sinon.spy(logger, "log");
89
+
90
+ logger.info("Testing");
91
+
92
+ expect(spy.called).to.be.true;
93
+
94
+ spy.restore();
95
+ });
96
+ });
97
+
98
+ describe(`notice`, function () {
99
+ it(`should log a notice log type when log is called without a log type`, function () {
100
+ const logger = new Logger(sls, logOutput.log);
101
+ const spy = sinon.spy(logger, "log");
102
+
103
+ logger.log("Testing");
104
+
105
+ expect(spy.called).to.be.true;
106
+
107
+ spy.restore();
108
+ });
109
+
110
+ it(`should log a notice log type when notice is called`, function () {
111
+ const logger = new Logger(sls, logOutput.log);
112
+ const spy = sinon.spy(logger, "log");
113
+
114
+ logger.notice("Testing");
115
+
116
+ expect(spy.called).to.be.true;
117
+
118
+ spy.restore();
119
+ });
120
+ });
121
+
122
+ describe(`success`, function () {
123
+ it(`should log a success log type when success is called`, function () {
124
+ const logger = new Logger(sls, logOutput.log);
125
+ const spy = sinon.spy(logger, "log");
126
+
127
+ logger.success("Testing");
128
+
129
+ expect(spy.called).to.be.true;
130
+
131
+ spy.restore();
132
+ });
133
+ });
134
+
135
+ describe(`verbose`, function () {
136
+ it(`should log a verbose log type when verbose is called`, function () {
137
+ const logger = new Logger(sls, logOutput.log);
138
+ const spy = sinon.spy(logger, "log");
139
+
140
+ logger.verbose("Testing");
141
+
142
+ expect(spy.called).to.be.true;
143
+
144
+ spy.restore();
145
+ });
146
+ });
147
+
148
+ describe(`warning`, function () {
149
+ it(`should log a warning log type when warning is called`, function () {
150
+ const logger = new Logger(sls, logOutput.log);
151
+ const spy = sinon.spy(logger, "log");
152
+
153
+ logger.warning("Testing");
154
+
155
+ expect(spy.called).to.be.true;
156
+
157
+ spy.restore();
158
+ });
159
+ });
160
+ });