serverless-openapi-documenter 0.0.50 → 0.0.52

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
@@ -295,12 +295,22 @@ custom:
295
295
  contentType: "application/json"
296
296
  schema:
297
297
  $schema: "http://json-schema.org/draft-04/schema#"
298
+ type: object
298
299
  properties:
299
300
  SomeObject:
300
301
  type: "object"
301
302
  properties:
302
303
  SomeAttribute:
303
304
  type: "string"
305
+ examples:
306
+ - name: someObjectInlineExample
307
+ summary: an example of a request
308
+ description: a longer string than the summary
309
+ value: {SomeObject: {SomeAttribute: 'attribute'}}
310
+ - name: someObjectExternalExample
311
+ summary: an example of a request external
312
+ description: a longer string than the summary
313
+ externalValue: https://example.com/external.json
304
314
  ```
305
315
 
306
316
  The Second way of writing the models:
@@ -329,12 +339,22 @@ custom:
329
339
  application/json:
330
340
  schema:
331
341
  $schema: "http://json-schema.org/draft-04/schema#"
342
+ type: object
332
343
  properties:
333
344
  SomeObject:
334
345
  type: "object"
335
346
  properties:
336
347
  SomeAttribute:
337
348
  type: "string"
349
+ examples:
350
+ - name: someObjectInlineExample
351
+ summary: an example of a request
352
+ description: a longer string than the summary
353
+ value: {SomeObject: {SomeAttribute: 'attribute'}}
354
+ - name: someObjectExternalExample
355
+ summary: an example of a request external
356
+ description: a longer string than the summary
357
+ externalValue: https://example.com/external.json
338
358
  ```
339
359
 
340
360
  ##### Model re-use
@@ -403,6 +423,7 @@ functions:
403
423
  - http:
404
424
  path: create
405
425
  method: post
426
+ cors: true
406
427
  summary:
407
428
  documentation:
408
429
  summary: "Create User"
@@ -645,6 +666,12 @@ responseHeaders:
645
666
  type: integer
646
667
  ```
647
668
 
669
+ ###### CORS
670
+
671
+ You can automatically generate CORS response headers by setting `cors` at the function level. Serverless allows you to modify how CORS is setup, so you can have the default options with `cors: true`, or you can modify the settings as shown in the [serverless documentation for CORS](https://www.serverless.com/framework/docs/providers/aws/events/apigateway#enabling-cors).
672
+
673
+ The generator will interpret your settings for CORS and automatically add the response headers. If for whatever reason you wish to override these, you can set them via the above `responseHeaders` setting and it'll apply your overrides.
674
+
648
675
  ## Example configuration
649
676
 
650
677
  Please view the example [serverless.yml](test/serverless-tests/serverless%202/serverless.yml).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverless-openapi-documenter",
3
- "version": "0.0.50",
3
+ "version": "0.0.52",
4
4
  "description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -35,6 +35,24 @@ class DefinitionGenerator {
35
35
  securitySchemes: 'securitySchemes'
36
36
  }
37
37
 
38
+ this.DEFAULT_CORS_HEADERS = {
39
+ 'Access-Control-Allow-Origin': {
40
+ description: 'The Access-Control-Allow-Origin response header indicates whether the response can be shared with requesting code from the given origin.',
41
+ schema: {
42
+ type: 'string',
43
+ default: '*',
44
+ example: 'https://developer.mozilla.org'
45
+ }
46
+ },
47
+ 'Access-Control-Allow-Credentials': {
48
+ description: `The Access-Control-Allow-Credentials response header tells browsers whether to expose the response to the frontend JavaScript code when the request's credentials mode (Request.credentials) is include`,
49
+ schema: {
50
+ type: 'boolean',
51
+ default: true
52
+ }
53
+ }
54
+ }
55
+
38
56
  try {
39
57
  this.refParserOptions = require(path.resolve('options', 'ref-parser.js'))
40
58
  } catch (err) {
@@ -123,6 +141,7 @@ class DefinitionGenerator {
123
141
  for (const httpFunction of httpFunctions) {
124
142
  for (const event of httpFunction.event) {
125
143
  if (event?.http?.documentation || event?.httpApi?.documentation) {
144
+ this.currentEvent = event?.http || event?.httpApi
126
145
  const documentation = event?.http?.documentation || event?.httpApi?.documentation
127
146
 
128
147
  this.currentFunctionName = httpFunction.functionInfo.name
@@ -328,14 +347,68 @@ class DefinitionGenerator {
328
347
  })
329
348
  }
330
349
 
350
+
351
+ const corsHeaders = await this.corsHeaders()
352
+ .catch(err => {
353
+ throw err;
354
+ })
355
+
356
+ if (obj.headers) {
357
+ for (const key in corsHeaders) {
358
+ if (!(key in obj.headers) && (obj.headers[key] = {})) {
359
+ obj.headers[key] = corsHeaders[key]
360
+ }
361
+ }
362
+ } else {
363
+ obj.headers = corsHeaders
364
+ }
365
+
331
366
  Object.assign(responses,{[response.statusCode]: obj})
332
367
  }
333
368
 
334
369
  return responses
335
370
  }
336
371
 
372
+ async corsHeaders() {
373
+ let headers = {}
374
+ if (this.currentEvent?.cors === true) {
375
+ headers = await this.createResponseHeaders(this.DEFAULT_CORS_HEADERS)
376
+ .catch(err => {
377
+ throw err;
378
+ })
379
+ } else if (this.currentEvent.cors) {
380
+ const newHeaders = {}
381
+ for (const key of Object.keys(this.DEFAULT_CORS_HEADERS)) {
382
+ if (key === 'Access-Control-Allow-Credentials' &&
383
+ this.currentEvent.cors.allowCredentials === undefined || this.currentEvent.cors?.allowCredentials === false) {
384
+ continue
385
+ }
386
+
387
+ const obj = JSON.parse(JSON.stringify(this.DEFAULT_CORS_HEADERS[key]))
388
+
389
+ if (key === 'Access-Control-Allow-Origin') {
390
+ if (this.currentEvent.cors?.origins || this.currentEvent.cors?.origin) {
391
+ obj.schema.example = this.currentEvent.cors?.origins?.toString() || this.currentEvent.cors?.origin?.toString()
392
+ } else if (this.currentEvent.cors?.allowedOrigins) {
393
+ obj.schema.example = this.currentEvent.cors.allowedOrigins.toString()
394
+ }
395
+ }
396
+
397
+ Object.assign(newHeaders, {[key]: obj})
398
+ }
399
+
400
+ headers = await this.createResponseHeaders(newHeaders)
401
+ .catch(err => {
402
+ throw err;
403
+ })
404
+ }
405
+
406
+ return headers;
407
+ }
408
+
337
409
  async createResponseHeaders(headers) {
338
410
  const obj = {}
411
+
339
412
  for (const header of Object.keys(headers)) {
340
413
  const newHeader = {}
341
414
  newHeader.description = headers[header].description || ''
@@ -385,16 +458,22 @@ class DefinitionGenerator {
385
458
  }
386
459
  const obj = {}
387
460
 
388
- if (mediaTypeDocumentation.example)
389
- obj.example = mediaTypeDocumentation.example
390
-
391
- if (mediaTypeDocumentation.examples)
392
- obj.examples = this.createExamples(mediaTypeDocumentation.examples)
393
-
394
461
  let schema
395
462
  if (mediaTypeDocumentation?.content) {
463
+ if (mediaTypeDocumentation.content[contentKey]?.example)
464
+ obj.example = mediaTypeDocumentation.content[contentKey].example
465
+
466
+ if (mediaTypeDocumentation.content[contentKey]?.examples)
467
+ obj.examples = this.createExamples(mediaTypeDocumentation.content[contentKey].examples)
468
+
396
469
  schema = mediaTypeDocumentation.content[contentKey].schema
397
470
  } else if (mediaTypeDocumentation?.contentType && mediaTypeDocumentation.schema) {
471
+ if (mediaTypeDocumentation?.example)
472
+ obj.example = mediaTypeDocumentation.example
473
+
474
+ if (mediaTypeDocumentation?.examples)
475
+ obj.examples = this.createExamples(mediaTypeDocumentation.examples)
476
+
398
477
  schema = mediaTypeDocumentation.schema
399
478
  }
400
479
 
@@ -675,6 +754,7 @@ class DefinitionGenerator {
675
754
 
676
755
  for(const example of examples) {
677
756
  Object.assign(examplesObj, {[example.name]: example})
757
+ delete examplesObj[example.name].name
678
758
  }
679
759
 
680
760
  return examplesObj;