holidayextras/jsonapi-server

View on GitHub
lib/swagger/resources.js

Summary

Maintainability
C
1 day
Test Coverage
'use strict'
const swaggerPaths = module.exports = { }
const jsonApi = require('../../')

swaggerPaths.getResourceDefinitions = () => {
  const resourceDefinitions = { }

  for (const resource in jsonApi._resources) {
    resourceDefinitions[resource] = swaggerPaths._getResourceDefinition(jsonApi._resources[resource])
  }
  resourceDefinitions.error = swaggerPaths._getErrorDefinition()

  return resourceDefinitions
}

swaggerPaths._getResourceDefinition = resourceConfig => {
  if (Object.keys(resourceConfig.handlers || { }).length === 0) return undefined

  const resourceDefinition = {
    description: resourceConfig.description,
    type: 'object',
    // required: [ "id", "type", "attributes", "relationships", "links" ],
    properties: {
      'id': {
        type: 'string'
      },
      'type': {
        type: 'string'
      },
      'attributes': {
        type: 'object',
        properties: { }
      },
      'relationships': {
        type: 'object',
        properties: { }
      },
      'links': {
        type: 'object',
        properties: {
          self: {
            type: 'string'
          }
        }
      },
      'meta': {
        type: 'object'
      }
    }
  }
  const attributeShortcut = resourceDefinition.properties.attributes.properties
  const relationshipsShortcut = resourceDefinition.properties.relationships.properties

  const attributes = resourceConfig.attributes
  for (const attribute in attributes) {
    if ((attribute === 'id') || (attribute === 'type') || (attribute === 'meta')) continue

    const joiScheme = attributes[attribute]

    let swaggerScheme = { }
    if (joiScheme._description) {
      swaggerScheme.description = joiScheme._description
    }

    if (!joiScheme._settings) {
      swaggerScheme.type = joiScheme._type
      if (swaggerScheme.type === 'date') {
        swaggerScheme.type = 'string'
        swaggerScheme.format = 'date'
      }
      attributeShortcut[attribute] = swaggerScheme

      if ((joiScheme._flags || { }).presence === 'required') {
        resourceDefinition.properties.attributes.required = resourceDefinition.properties.attributes.required || [ ]
        resourceDefinition.properties.attributes.required.push(attribute)
      }
    } else {
      if (joiScheme._settings.as) continue

      swaggerScheme = {
        type: 'object',
        properties: {
          meta: {
            type: 'object'
          },
          links: {
            type: 'object',
            properties: {
              self: {
                type: 'string'
              },
              related: {
                type: 'string'
              }
            }
          },
          data: {
            type: 'object',
            required: [ 'type', 'id' ],
            properties: {
              type: {
                type: 'string'
              },
              id: {
                type: 'string'
              },
              meta: {
                type: 'object'
              }
            }
          }
        }
      }

      if (joiScheme._settings.__many) {
        swaggerScheme.properties.data = {
          type: 'array',
          items: swaggerScheme.properties.data
        }
      }

      if ((joiScheme._flags || { }).presence === 'required') {
        if (joiScheme._settings.__many) {
          swaggerScheme.required = true
        } else {
          swaggerScheme.required = [ 'type', 'id' ]
        }
      }
      relationshipsShortcut[attribute] = swaggerScheme
    }
  }

  return resourceDefinition
}

swaggerPaths._getErrorDefinition = () => ({
  type: 'object',
  required: [ 'jsonapi', 'meta', 'links', 'errors' ],

  properties: {
    jsonapi: {
      type: 'object',
      required: [ 'version' ],
      properties: {
        version: {
          type: 'string'
        }
      }
    },
    meta: {
      type: 'object'
    },
    links: {
      type: 'object',
      properties: {
        self: {
          type: 'string'
        }
      }
    },
    errors: {
      type: 'array',
      items: {
        type: 'object',
        required: [
          'status', 'code', 'title', 'detail'
        ],
        properties: {
          status: {
            type: 'string'
          },
          code: {
            type: 'string'
          },
          title: {
            type: 'string'
          },
          detail: {
            type: 'object'
          }
        }
      }
    }
  }
})