serverless-openapi-documenter 0.0.68 → 0.0.69

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/README.md CHANGED
@@ -114,7 +114,7 @@ Options:
114
114
  | path[path].[operation].parameters.name | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params.name |
115
115
  | path[path].[operation].parameters.in | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params |
116
116
  | path[path].[operation].parameters.description | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params.description |
117
- | path[path].[operation].parameters.required | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params.required |
117
+ | path[path].[operation].parameters.required | functions.functions.[http OR httpApi].documentation.[query/cookie/header]Params.required |
118
118
  | path[path].[operation].parameters.deprecated | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params.deprecated |
119
119
  | path[path].[operation].parameters.allowEmptyValue | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params.allowEmptyValue |
120
120
  | path[path].[operation].parameters.style | functions.functions.[http OR httpApi].documentation.[path/query/cookie/header]Params.style |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverless-openapi-documenter",
3
- "version": "0.0.68",
3
+ "version": "0.0.69",
4
4
  "description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -1,195 +1,235 @@
1
- 'use strict'
1
+ "use strict";
2
2
 
3
- const path = require('path')
3
+ const path = require("path");
4
4
 
5
- const $RefParser = require("@apidevtools/json-schema-ref-parser")
6
- const SchemaConvertor = require('json-schema-for-openapi')
7
- const isEqual = require('lodash.isequal')
8
- const { v4: uuid } = require('uuid')
5
+ const $RefParser = require("@apidevtools/json-schema-ref-parser");
6
+ const SchemaConvertor = require("json-schema-for-openapi");
7
+ const isEqual = require("lodash.isequal");
8
+ const { v4: uuid } = require("uuid");
9
9
 
10
10
  class SchemaHandler {
11
- constructor(serverless, openAPI) {
12
- this.apiGatewayModels = serverless.service?.provider?.apiGateway?.request?.schemas || {}
13
- this.documentation = serverless.service.custom.documentation
14
- this.openAPI = openAPI
11
+ constructor(serverless, openAPI) {
12
+ this.apiGatewayModels =
13
+ serverless.service?.provider?.apiGateway?.request?.schemas || {};
14
+ this.documentation = serverless.service.custom.documentation;
15
+ this.openAPI = openAPI;
15
16
 
16
- this.modelReferences = {}
17
+ this.modelReferences = {};
17
18
 
18
- this.__standardiseModels()
19
+ this.__standardiseModels();
19
20
 
20
- try {
21
- this.refParserOptions = require(path.resolve('options', 'ref-parser.js'))
22
- } catch (err) {
23
- this.refParserOptions = {}
24
- }
21
+ try {
22
+ this.refParserOptions = require(path.resolve("options", "ref-parser.js"));
23
+ } catch (err) {
24
+ this.refParserOptions = {};
25
25
  }
26
-
27
- /**
28
- * Standardises the models to a specific format
29
- */
30
- __standardiseModels() {
31
- const standardModel = (model) => {
32
- if (model.schema) {
33
- return model
26
+ }
27
+
28
+ /**
29
+ * Standardises the models to a specific format
30
+ */
31
+ __standardiseModels() {
32
+ const standardModel = (model) => {
33
+ if (model.schema) {
34
+ return model;
35
+ }
36
+
37
+ const contentType = Object.keys(model.content)[0];
38
+ model.contentType = contentType;
39
+ model.schema = model.content[contentType].schema;
40
+
41
+ return model;
42
+ };
43
+
44
+ const standardisedModels =
45
+ this.documentation?.models?.map(standardModel) || [];
46
+ const standardisedModelsList =
47
+ this.documentation?.modelsList?.map(standardModel) || [];
48
+
49
+ const standardisedGatewayModels =
50
+ Object.keys(this.apiGatewayModels).flatMap((key) => {
51
+ const gatewayModel = this.apiGatewayModels[key];
52
+ return standardModel(gatewayModel);
53
+ }) || [];
54
+
55
+ this.models = standardisedModels.concat(
56
+ standardisedModelsList,
57
+ standardisedGatewayModels
58
+ );
59
+ }
60
+
61
+ async addModelsToOpenAPI() {
62
+ for (const model of this.models) {
63
+ const modelName = model.name;
64
+ const modelSchema = model.schema;
65
+
66
+ const dereferencedSchema = await this.__dereferenceSchema(
67
+ modelSchema
68
+ ).catch((err) => {
69
+ if (err.errors) {
70
+ for (const error of err?.errors) {
71
+ if (error.message.includes("HTTP ERROR")) {
72
+ // throw err;
73
+ throw new Error(
74
+ `There was an error dereferencing ${
75
+ model.name
76
+ } schema. \n\n dereferencing message: ${
77
+ error.message
78
+ } \n\n Model received: ${JSON.stringify(model)}`
79
+ );
34
80
  }
35
-
36
- const contentType = Object.keys(model.content)[0]
37
- model.contentType = contentType
38
- model.schema = model.content[contentType].schema
39
-
40
- return model
81
+ }
41
82
  }
42
-
43
- const standardisedModels = this.documentation?.models?.map(standardModel) || []
44
- const standardisedModelsList = this.documentation?.modelsList?.map(standardModel) || []
45
-
46
- const standardisedGatewayModels = Object.keys(this.apiGatewayModels).flatMap(key => {
47
- const gatewayModel = this.apiGatewayModels[key]
48
- return standardModel(gatewayModel)
49
- }) || []
50
-
51
- this.models = standardisedModels.concat(standardisedModelsList, standardisedGatewayModels)
52
- }
53
-
54
- async addModelsToOpenAPI() {
55
- for (const model of this.models) {
56
- const modelName = model.name
57
- const modelSchema = model.schema
58
-
59
- const dereferencedSchema = await this.__dereferenceSchema(modelSchema)
60
- .catch(err => {
61
- if(err.errors) {
62
- for (const error of err?.errors) {
63
- if (error.message.includes('HTTP ERROR')) {
64
- throw err
65
- }
66
- }
67
- }
68
- return modelSchema
69
- })
70
-
71
- const convertedSchemas = SchemaConvertor.convert(dereferencedSchema, modelName)
72
-
73
- for (const [schemaName, schemaValue] of Object.entries(convertedSchemas.schemas)) {
74
- if (schemaName === modelName) {
75
- this.modelReferences[schemaName] = `#/components/schemas/${modelName}`
76
- }
77
-
78
- this.__addToComponents('schemas', schemaValue, schemaName)
79
- }
83
+ return modelSchema;
84
+ });
85
+
86
+ const convertedSchemas = SchemaConvertor.convert(
87
+ dereferencedSchema,
88
+ modelName
89
+ );
90
+
91
+ if (
92
+ typeof convertedSchemas.schemas === "object" &&
93
+ !Array.isArray(convertedSchemas.schemas) &&
94
+ convertedSchemas.schemas !== null
95
+ ) {
96
+ for (const [schemaName, schemaValue] of Object.entries(
97
+ convertedSchemas.schemas
98
+ )) {
99
+ if (schemaName === modelName) {
100
+ this.modelReferences[
101
+ schemaName
102
+ ] = `#/components/schemas/${modelName}`;
103
+ }
104
+
105
+ this.__addToComponents("schemas", schemaValue, schemaName);
80
106
  }
107
+ } else {
108
+ throw new Error(
109
+ `There was an error converting the ${
110
+ model.name
111
+ } schema. Model received looks like: \n\n${JSON.stringify(model)}`
112
+ );
113
+ }
81
114
  }
115
+ }
82
116
 
83
- async createSchema(name, schema) {
84
- let originalName = name;
85
- let finalName = name;
86
-
87
- if (this.modelReferences[name] && schema === undefined) {
88
- return this.modelReferences[name]
89
- }
90
-
91
- const dereferencedSchema = await this.__dereferenceSchema(schema)
92
- .catch(err => {
93
- throw err
94
- })
95
-
96
- const convertedSchemas = SchemaConvertor.convert(dereferencedSchema, name)
97
-
98
- for (const [schemaName, schemaValue] of Object.entries(convertedSchemas.schemas)) {
99
- if (this.__existsInComponents(schemaName)) {
100
- if (this.__isTheSameSchema(schemaValue, schemaName) === false) {
101
- if (schemaName === originalName) {
102
- finalName = `${schemaName}-${uuid()}`
103
- this.__addToComponents('schemas', schemaValue, finalName)
104
- } else {
105
- this.__addToComponents('schemas', schemaValue, schemaName)
106
- }
107
- }
108
- } else {
109
- this.__addToComponents('schemas', schemaValue, schemaName)
110
- }
111
- }
117
+ async createSchema(name, schema) {
118
+ let originalName = name;
119
+ let finalName = name;
112
120
 
113
- return `#/components/schemas/${finalName}`
121
+ if (this.modelReferences[name] && schema === undefined) {
122
+ return this.modelReferences[name];
114
123
  }
115
124
 
116
- async __dereferenceSchema(schema) {
117
- const bundledSchema = await $RefParser.bundle(schema, this.refParserOptions)
118
- .catch(err => {
119
- throw err
120
- })
121
-
122
- let deReferencedSchema = await $RefParser.dereference(bundledSchema, this.refParserOptions)
123
- .catch(err => {
124
- throw err
125
- })
126
-
127
- // deal with schemas that have been de-referenced poorly: naive
128
- if (deReferencedSchema?.$ref === '#') {
129
- const oldRef = bundledSchema.$ref
130
- const path = oldRef.split('/')
131
-
132
- const pathTitle = path[path.length - 1]
133
- const referencedProperties = deReferencedSchema.definitions[pathTitle]
134
-
135
- Object.assign(deReferencedSchema, { ...referencedProperties })
136
-
137
- delete deReferencedSchema.$ref
138
- deReferencedSchema = await this.__dereferenceSchema(deReferencedSchema)
139
- .catch((err) => {
140
- throw err
141
- })
125
+ const dereferencedSchema = await this.__dereferenceSchema(schema).catch(
126
+ (err) => {
127
+ throw err;
128
+ }
129
+ );
130
+
131
+ const convertedSchemas = SchemaConvertor.convert(dereferencedSchema, name);
132
+
133
+ for (const [schemaName, schemaValue] of Object.entries(
134
+ convertedSchemas.schemas
135
+ )) {
136
+ if (this.__existsInComponents(schemaName)) {
137
+ if (this.__isTheSameSchema(schemaValue, schemaName) === false) {
138
+ if (schemaName === originalName) {
139
+ finalName = `${schemaName}-${uuid()}`;
140
+ this.__addToComponents("schemas", schemaValue, finalName);
141
+ } else {
142
+ this.__addToComponents("schemas", schemaValue, schemaName);
143
+ }
142
144
  }
143
-
144
- return deReferencedSchema
145
- }
146
-
147
- /**
148
- * @function existsInComponents
149
- * @param {string} name - The name of the Schema
150
- * @returns {boolean} Whether it exists in components already
151
- */
152
- __existsInComponents(name) {
153
- return Boolean(this.openAPI?.components?.schemas?.[name])
145
+ } else {
146
+ this.__addToComponents("schemas", schemaValue, schemaName);
147
+ }
154
148
  }
155
149
 
156
- /**
157
- * @function isTheSameSchema
158
- * @param {object} schema - The schema value
159
- * @param {string} otherSchemaName - The name of the schema
160
- * @returns {boolean} Whether the schema provided is the same one as in components already
161
- */
162
- __isTheSameSchema(schema, otherSchemaName) {
163
- return isEqual(schema, this.openAPI.components.schemas[otherSchemaName])
150
+ return `#/components/schemas/${finalName}`;
151
+ }
152
+
153
+ async __dereferenceSchema(schema) {
154
+ const bundledSchema = await $RefParser
155
+ .bundle(schema, this.refParserOptions)
156
+ .catch((err) => {
157
+ throw err;
158
+ });
159
+
160
+ let deReferencedSchema = await $RefParser
161
+ .dereference(bundledSchema, this.refParserOptions)
162
+ .catch((err) => {
163
+ throw err;
164
+ });
165
+
166
+ // deal with schemas that have been de-referenced poorly: naive
167
+ if (deReferencedSchema?.$ref === "#") {
168
+ const oldRef = bundledSchema.$ref;
169
+ const path = oldRef.split("/");
170
+
171
+ const pathTitle = path[path.length - 1];
172
+ const referencedProperties = deReferencedSchema.definitions[pathTitle];
173
+
174
+ Object.assign(deReferencedSchema, { ...referencedProperties });
175
+
176
+ delete deReferencedSchema.$ref;
177
+ deReferencedSchema = await this.__dereferenceSchema(
178
+ deReferencedSchema
179
+ ).catch((err) => {
180
+ throw err;
181
+ });
164
182
  }
165
183
 
166
- /**
167
- * @function addToComponents
168
- * @param {string} type - The component type
169
- * @param {object} schema - The schema
170
- * @param {string} name - The name of the schema
171
- */
172
- __addToComponents(type, schema, name) {
173
- const schemaObj = {
174
- [name]: schema
175
- }
176
-
177
- if (this.openAPI?.components) {
178
- if (this.openAPI.components[type]) {
179
- Object.assign(this.openAPI.components[type], schemaObj)
180
- } else {
181
- Object.assign(this.openAPI.components, { [type]: schemaObj })
182
- }
183
- } else {
184
- const components = {
185
- components: {
186
- [type]: schemaObj
187
- }
188
- }
189
-
190
- Object.assign(this.openAPI, components)
191
- }
184
+ return deReferencedSchema;
185
+ }
186
+
187
+ /**
188
+ * @function existsInComponents
189
+ * @param {string} name - The name of the Schema
190
+ * @returns {boolean} Whether it exists in components already
191
+ */
192
+ __existsInComponents(name) {
193
+ return Boolean(this.openAPI?.components?.schemas?.[name]);
194
+ }
195
+
196
+ /**
197
+ * @function isTheSameSchema
198
+ * @param {object} schema - The schema value
199
+ * @param {string} otherSchemaName - The name of the schema
200
+ * @returns {boolean} Whether the schema provided is the same one as in components already
201
+ */
202
+ __isTheSameSchema(schema, otherSchemaName) {
203
+ return isEqual(schema, this.openAPI.components.schemas[otherSchemaName]);
204
+ }
205
+
206
+ /**
207
+ * @function addToComponents
208
+ * @param {string} type - The component type
209
+ * @param {object} schema - The schema
210
+ * @param {string} name - The name of the schema
211
+ */
212
+ __addToComponents(type, schema, name) {
213
+ const schemaObj = {
214
+ [name]: schema,
215
+ };
216
+
217
+ if (this.openAPI?.components) {
218
+ if (this.openAPI.components[type]) {
219
+ Object.assign(this.openAPI.components[type], schemaObj);
220
+ } else {
221
+ Object.assign(this.openAPI.components, { [type]: schemaObj });
222
+ }
223
+ } else {
224
+ const components = {
225
+ components: {
226
+ [type]: schemaObj,
227
+ },
228
+ };
229
+
230
+ Object.assign(this.openAPI, components);
192
231
  }
232
+ }
193
233
  }
194
234
 
195
235
  module.exports = SchemaHandler;