serverless-openapi-documenter 0.0.26 → 0.0.30

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.
@@ -16,7 +16,7 @@ jobs:
16
16
 
17
17
  strategy:
18
18
  matrix:
19
- node-version: [14.x, 16.x]
19
+ node-version: [14.x, 16.x, 18.x]
20
20
  # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
21
21
 
22
22
  steps:
package/README.md CHANGED
@@ -63,6 +63,7 @@ Options:
63
63
  | externalDocs.url | custom.documentation.externalDocumentation.url |
64
64
  | servers[].description | custom.documentation.servers.description |
65
65
  | servers[].url | custom.documentation.servers.url |
66
+ | servers[].variables | custom.documentation.servers.variables |
66
67
  | tags[].name | custom.documentation.tags.name |
67
68
  | tags[].description | custom.documentation.tags.description |
68
69
  | tags[].externalDocs.url | custom.documentation.tags.externalDocumentation.url |
@@ -121,8 +122,15 @@ custom:
121
122
  url: https://google.com
122
123
  description: A link to google
123
124
  servers:
124
- url: https://example.com
125
+ url: https://example.com:{port}/
125
126
  description: The server
127
+ variables:
128
+ port:
129
+ enum:
130
+ - 4000
131
+ - 3000
132
+ default: 3000
133
+ description: The port the server operates on
126
134
  tags:
127
135
  - name: tag1
128
136
  description: this is a tag
@@ -222,6 +230,39 @@ custom:
222
230
  type: "string"
223
231
  ```
224
232
 
233
+ ##### Model re-use
234
+
235
+ Through the magic of YAML, you can re-use models:
236
+
237
+ ```yml
238
+ custom:
239
+ documentation:
240
+ ...
241
+ models:
242
+ - name: "ErrorResponse"
243
+ description: "This is an error"
244
+ content:
245
+ application/json:
246
+ schema: &ErrorItem
247
+ type: object
248
+ properties:
249
+ message:
250
+ type: string
251
+ code:
252
+ type: integer
253
+
254
+ - name: "PutDocumentResponse"
255
+ description: "PUT Document response model (external reference example)"
256
+ content:
257
+ application/json:
258
+ schema:
259
+ type: array
260
+ items: *ErrorItem
261
+ ```
262
+
263
+ `&ErrorItem` in the above example creates a node anchor (&ErrorItem) to the `ErrorResponse` schema which then can be used in the `PutDocumentResponse` schema via the reference (*ErrorItem). The node anchor needs to be declared first before it can be used elsewhere via the reference, swapping the above example around would result in an error.
264
+
265
+
225
266
  #### Functions
226
267
 
227
268
  To define the documentation for a given function event, you need to create a `documentation` attribute for your http event in your `serverless.yml` file.
@@ -238,6 +279,7 @@ The `documentation` section of the event configuration can contain the following
238
279
  * `queryParams`: a list of query parameters (see [queryParams](#queryparams) below)
239
280
  * `pathParams`: a list of path parameters (see [pathParams](#pathparams) below)
240
281
  * `cookieParams`: a list of cookie parameters (see [cookieParams](#cookieparams) below)
282
+ * `headerParams`: a list of headers (see [headerParams](#headerparams---request-headers) below)
241
283
  * `methodResponses`: an array of response models and applicable status codes
242
284
  * `statusCode`: applicable http status code (ie. 200/404/500 etc.)
243
285
  * `responseBody`: contains description of the response
@@ -285,12 +327,22 @@ functions:
285
327
  description: "A Session ID variable"
286
328
  schema:
287
329
  type: "string"
330
+ headerParams:
331
+ name: "Content-Type"
332
+ description: "The content type"
333
+ schema:
334
+ type: "string"
288
335
  methodResponses:
289
336
  - statusCode: 201
290
337
  responseBody:
291
338
  description: "A user object along with generated API Keys"
292
339
  responseModels:
293
340
  application/json: "PutDocumentResponse"
341
+ responseHeaders:
342
+ X-Rate-Limit-Limit:
343
+ description: The number of allowed requests in the current period
344
+ schema:
345
+ type: integer
294
346
  - statusCode: 500
295
347
  responseBody:
296
348
  description: "An error message when creating a new user"
@@ -320,8 +372,8 @@ queryParams:
320
372
 
321
373
  Path parameters can be described as follow:
322
374
 
323
- * `name`: the name of the query variable
324
- * `description`: a description of the query variable
375
+ * `name`: the name of the path parameter
376
+ * `description`: a description of the path parameter
325
377
  * `schema`: JSON schema (inline, file or externally hosted)
326
378
 
327
379
  ```yml
@@ -336,9 +388,9 @@ pathParams:
336
388
 
337
389
  Cookie parameters can be described as follow:
338
390
 
339
- * `name`: the name of the query variable
340
- * `description`: a description of the query variable
341
- * `required`: whether the query parameter is mandatory (boolean)
391
+ * `name`: the name of the cookie parameter
392
+ * `description`: a description of the cookie parameter
393
+ * `required`: whether the cookie parameter is mandatory (boolean)
342
394
  * `schema`: JSON schema (inline, file or externally hosted)
343
395
 
344
396
  ```yml
@@ -354,9 +406,9 @@ cookieParams:
354
406
 
355
407
  Request Headers can be described as follow:
356
408
 
357
- * `name`: the name of the query variable
358
- * `description`: a description of the query variable
359
- * `required`: whether the query parameter is mandatory (boolean)
409
+ * `name`: the name of the header
410
+ * `description`: a description of the header
411
+ * `required`: whether the header is mandatory (boolean)
360
412
  * `schema`: JSON schema (inline, file or externally hosted)
361
413
 
362
414
  ```yml
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverless-openapi-documenter",
3
- "version": "0.0.26",
3
+ "version": "0.0.30",
4
4
  "description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -28,21 +28,21 @@
28
28
  },
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
- "@apidevtools/json-schema-ref-parser": "^9.0.9",
31
+ "@apidevtools/json-schema-ref-parser": "^9.1.0",
32
32
  "chalk": "^4.1.2",
33
33
  "js-yaml": "^4.1.0",
34
- "json-schema-for-openapi": "^0.2.1",
34
+ "json-schema-for-openapi": "^0.3.0",
35
35
  "oas-validator": "^5.0.8",
36
- "openapi-to-postmanv2": "^4.1.0",
36
+ "openapi-to-postmanv2": "^4.4.1",
37
37
  "swagger2openapi": "^7.0.8",
38
- "uuid": "^8.3.2"
38
+ "uuid": "^9.0.0"
39
39
  },
40
40
  "engines": {
41
41
  "node": ">=14"
42
42
  },
43
43
  "devDependencies": {
44
- "chai": "^4.3.6",
45
- "mocha": "^10.0.0",
46
- "sinon": "^14.0.0"
44
+ "chai": "^4.3.7",
45
+ "mocha": "^10.1.0",
46
+ "sinon": "^15.0.0"
47
47
  }
48
48
  }
@@ -410,6 +410,14 @@ class DefinitionGenerator {
410
410
  return params;
411
411
  }
412
412
 
413
+ async dereferenceSchema(schema) {
414
+ return await $RefParser.dereference(schema, this.refParserOptions)
415
+ .catch(err => {
416
+ console.error(err)
417
+ throw err
418
+ })
419
+ }
420
+
413
421
  async schemaCreator(schema, name) {
414
422
  const addToComponents = (schema, name) => {
415
423
  const schemaObj = {
@@ -433,14 +441,27 @@ class DefinitionGenerator {
433
441
  }
434
442
  }
435
443
 
436
- const deReferencedSchema = await $RefParser.dereference(schema, this.refParserOptions)
437
- .catch(err => {
438
- console.error(err)
444
+ let deReferencedSchema = await this.dereferenceSchema(schema)
445
+ .catch((err) => {
439
446
  throw err
440
447
  })
441
448
 
449
+ // deal with schemas that have been de-referenced poorly
450
+ if (deReferencedSchema.$ref === '#') {
451
+ const oldRef = schema.$ref
452
+ const path = oldRef.split('/')
453
+
454
+ const pathTitle = path[path.length-1]
455
+ const property = deReferencedSchema.definitions[path[path.length-1]]
456
+ Object.assign(deReferencedSchema, {properties: {[pathTitle]: property}})
457
+ delete deReferencedSchema.$ref
458
+ deReferencedSchema = await this.dereferenceSchema(deReferencedSchema)
459
+ .catch((err) => {
460
+ throw err
461
+ })
462
+ }
442
463
 
443
- const convertedSchema = SchemaConvertor.convert(deReferencedSchema)
464
+ const convertedSchema = SchemaConvertor.convert(deReferencedSchema, name)
444
465
  let schemaName = name
445
466
  if (this.schemaIDs.includes(schemaName))
446
467
  schemaName = `${name}-${uuid()}`
@@ -448,7 +469,7 @@ class DefinitionGenerator {
448
469
  this.schemaIDs.push(schemaName)
449
470
 
450
471
  for (const key of Object.keys(convertedSchema.schemas)) {
451
- if (key === 'main' || key.split('-')[0] === 'main') {
472
+ if (key === name || key.split('-')[0] === name) {
452
473
  let ref = `#/components/schemas/`
453
474
 
454
475
  if (this.openAPI?.components?.schemas?.[name]) {
@@ -458,6 +458,35 @@ describe('DefinitionGenerator', () => {
458
458
  expect(definitionGenerator.openAPI.components.schemas).to.have.property('ContactPutRequest')
459
459
  expect(expected).to.equal('#/components/schemas/ContactPutRequest')
460
460
  });
461
+
462
+ it('should handle a schema that has been improperly dereferenced', async function() {
463
+ const simpleSchema = {
464
+ $schema: 'http://json-schema.org/draft-04/schema#',
465
+ title: 'JSON API Schema',
466
+ $ref: '#/definitions/Error',
467
+ definitions: {
468
+ Error: {
469
+ type: 'string'
470
+ }
471
+ }
472
+ }
473
+ const definitionGenerator = new DefinitionGenerator(mockServerless)
474
+ const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
475
+ .catch((err) => {
476
+ console.error(err)
477
+ })
478
+
479
+ expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
480
+ expect(definitionGenerator.openAPI.components.schemas.simpleSchema).to.deep.equal({
481
+ title: 'JSON API Schema',
482
+ properties: {
483
+ Error: {
484
+ type: 'string'
485
+ }
486
+ }
487
+ })
488
+ expect(expected).to.equal('#/components/schemas/simpleSchema')
489
+ });
461
490
  });
462
491
 
463
492
  describe('schemas that are urls', () => {
@@ -473,9 +502,9 @@ describe('DefinitionGenerator', () => {
473
502
  })
474
503
 
475
504
  expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
476
- expect(definitionGenerator.openAPI.components.schemas).to.have.property('log')
477
- expect(definitionGenerator.openAPI.components.schemas).to.have.property('template')
478
- expect(definitionGenerator.openAPI.components.schemas).to.have.property('database')
505
+ expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('log')
506
+ expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('template')
507
+ expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('database')
479
508
  expect(expected).to.equal('#/components/schemas/LicensedMember')
480
509
 
481
510
  stub.restore()
@@ -485,13 +514,27 @@ describe('DefinitionGenerator', () => {
485
514
  const complexSchema = 'https:///google.com/build/LicensedMember.json'
486
515
  const LicensedMemberJSON = require('../json/complex.json')
487
516
 
488
- const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
517
+ // const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
518
+ const stub = sinon.stub($RefParser, 'dereference')
519
+ .onFirstCall().resolves(LicensedMemberJSON)
520
+ .onSecondCall().resolves({
521
+ type: "object",
522
+ properties: {
523
+ UUID: {
524
+ $ref: "#/definitions/log"
525
+ },
526
+ name: {
527
+ type: "string"
528
+ }
529
+ }
530
+ })
489
531
  const definitionGenerator = new DefinitionGenerator(mockServerless)
490
532
  let expected = await definitionGenerator.schemaCreator(complexSchema, 'LicensedMember')
491
533
  .catch((err) => {
492
534
  console.error(err)
493
535
  })
494
536
 
537
+ // this will fail validation due to a missing definition
495
538
  const simpleSchema = {
496
539
  type: "object",
497
540
  properties: {
@@ -511,10 +554,12 @@ describe('DefinitionGenerator', () => {
511
554
  })
512
555
 
513
556
  expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
514
- expect(definitionGenerator.openAPI.components.schemas).to.have.property('log')
515
- expect(definitionGenerator.openAPI.components.schemas).to.have.property('template')
516
- expect(definitionGenerator.openAPI.components.schemas).to.have.property('database')
557
+ expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('log')
558
+ expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('template')
559
+ expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('database')
517
560
  expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
561
+ expect(definitionGenerator.openAPI.components.schemas.simpleSchema.properties).to.have.property('UUID')
562
+ expect(definitionGenerator.openAPI.components.schemas.simpleSchema.properties).to.have.property('name')
518
563
  expect(expected).to.equal('#/components/schemas/simpleSchema')
519
564
 
520
565
  stub.restore()
@@ -528,6 +573,7 @@ describe('DefinitionGenerator', () => {
528
573
  const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
529
574
  .catch((err) => {
530
575
  console.error(err)
576
+ expect(err).to.be.an('error')
531
577
  })
532
578
 
533
579
  expect(expected).to.be.undefined