1.0.0 • Published 5 years ago

@zakkudo/open-api-tree v1.0.0

Weekly downloads
-
License
BSD-3-Clause
Repository
github
Last release
5 years ago

@zakkudo/open-api-tree

Make working with backend api trees enjoyable from swagger/openapi.

Build Status Coverage Status Known Vulnerabilities Node License

Generate an easy to use api tree that includes format checking using JSON Schema for the body and params with only a single configuration object. Network calls are executed using a thin convenience wrapper around fetch.

This library is a thin wrapper for @zakkudo/api-tree if you need the same functionality but don't use Swagger.

Why use this?

  • Consistancy with simplicity
  • No longer need to maintain a set of functions for accessing apis
  • Automatic validation of the body/params against the Swagger definition
  • Support for Swagger 1.2, Swagger 2.0 and OpenApi 3.0.x definitions
  • Leverages native fetch, adding a thin convenience layer in the form of Fetch Functions
  • Share authorization handling using a single location that can be updated dynamically
  • Share a single transform for the responses and request in a location that can be updated dynamically
  • Supports overloading the tree methods so that you can use the same method for getting a single item or a collection of items

The api tree is based off of the path name

  • [POST] /users -> api.users.post({body: data})
  • [GET] /users/{id} -> api.users.get({params: {id: 1}})
  • [GET] /users -> api.users.get()
  • [PUT] /users/{id} -> api.users.put({params: {id: 1}, body: data})
  • [GET] /users/{userId}/roles/{roleId} -> api.users.roles.get({params: {userId: 1, roleId: 3}})

Install

# Install using npm
npm install @zakkudo/open-api-tree
# Install using yarn
yarn add @zakkudo/open-api-tree

Examples

Parse a swagger schema at runtime

import OpenApiTree from '@zakkudo/open-api-tree';
import fetch from '@zakkudo/fetch';

fetch('https://petstore.swagger.io/v2/swagger.json').then((configuration) => {
    const api = new OpenApiTree(configuration, {
        headers: {
             'X-AUTH-TOKEN': '1234'
        }
    });

    // GET http://petstore.swagger.io/api/pets?limit=10
    api.pets.get({params: {limit: 10}})

    // GET http://petstore.swagger.io/api/pets/1
    api.pets.get({params: {id: 1}})

    // POST http://petstore.swagger.io/api/pets
    api.pets.post({})

    // DELETE http://petstore.swagger.io/api/pets/1
    api.pets.delete({params: {id: 1}});
});

Parse a swagger schema at buildtime in webpack

//In webpack.conf.js////////////////////////////
import ApiTree from '@zakkudo/api-tree';

const toApiTreeSchema = require('@zakkudo/open-api-tree/toApiTreeSchema').default;
const execSync = require('child_process').execSync;
const configuration = JSON.parse(String(execSync('curl https://petstore.swagger.io/v2/swagger.json'));

module.exports = {
    plugins: [
        new DefinePlugin({
            __API_CONFIGURATION__: JSON.stringify(toApiTreeSchema(configuration))
        })
    }
}

//In src/api.js////////////////////////////////
import ApiTree from '@zakkudo/api-tree';

export default new ApiTree(__API_CONFIGURATION__);

//In src/index.js////////////////////////////
import api from './api';

// GET http://petstore.swagger.io/api/pets?limit=10
api.pets.get({params: {limit: 10}})

// GET http://petstore.swagger.io/api/pets/1
api.pets.get({params: {id: 1}})

// POST http://petstore.swagger.io/api/pets
api.pets.post({})

// DELETE http://petstore.swagger.io/api/pets/1
api.pets.delete({params: {id: 1}});

Validation error failure example

import ValidationError from '@zakkudo/open-api-tree/ValidationError';

api.pets.get({params: {id: 'lollipops'}}).catch((reason) => {
    if (reason instanceof ValidationError) {
        console.log(reason)
        // ValidationError: [
        //     "<http://petstore.swagger.io/api/pets/:id> .params.id: should be integer"
        // ]
    }

    throw reason;
});

Handling validation errors

import ValidationError from '@zakkudo/open-api-tree/ValidationError';

// Try fetching without an id
api.users.get().catch((reason) => {
    if (reason instanceof ValidationError) {
        console.log(reason); // "params: should have required property 'userId'
    }

    throw reason;
})

// Try using an invalidly formatted id
api.users.get({params: {userId: 'invalid format'}}).catch((reason) => {
    if (reason instanceof ValidationError) {
        console.log(reason); // "params.userId: should match pattern \"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\""
    }

    throw reason;
});

// Skip the validation by passing false to the network call
api.users.get({params: {userId: 'invalid format'}}, false).catch((reason) => {
    if (reason instanceof HttpError) {
        console.log(reason.status); // 500
    }

    throw reason;
});

Don't include validation schemas in api tree

import OpenApiTree from '@zakkudo/open-api-tree';
import HttpError from '@zakkudo/open-api-tree/HttpError';

fetch('https://petstore.swagger.io/v2/swagger.json').then((configuration) => {
    const api = new OpenApiTree(configuration, {
        headers: {
             'X-AUTH-TOKEN': '1234'
        }
    }, {validation: false});

    // Try fetching without an id
    api.users.get().catch((reason) => {
        if (reason instanceof HttpError) {
            console.log(reason.status); // 500
        }

        throw reason;
    })

    // Try using an invalidly formatted id
    api.users.get({params: {userId: 'invalid format'}}).catch((reason) => {
        if (reason instanceof HttpError) {
            console.log(reason.status); // 500
        }

        throw reason;
    });

    // Skip the validation by passing false to the network call
    api.users.get({params: {userId: 'invalid format'}}, false).catch((reason) => {
        if (reason instanceof HttpError) {
            console.log(reason.status); // 500
        }

        throw reason;
    });
});

Handling network errors

import HttpError from '@zakkudo/open-api-tree/HttpError';

// Force execution with an invalidly formatted id
api.users.get({params: {userId: 'invalid format'}}, false).catch((reason) => {
    if (reason instanceof HttpError) {
        console.log(reason.status); // 500
        console.log(reason.response); // response body from the server, often json
    }

    throw reason;
});

Overriding options

import HttpError from '@zakkudo/open-api-tree/HttpError';
import ValidationError from '@zakkudo/open-api-tree/ValidationError';

//Set headers after the fact
api.options.headers['X-AUTH-TOKEN'] = '5678';

//Get 10 users
api.users.get({params: {limit: 10}}).then((users) => {
     console.log(users); // [{id: ...}, ...]
});

//Create a user
api.users.post({first_name: 'John', last_name: 'Doe'}).then((response) => {
     console.log(response); // {id: 'ff599c67-1cac-4167-927e-49c02c93625f', first_name: 'John', last_name: 'Doe'}
});

// Try using a valid id
api.users.get({params: {userId: 'ff599c67-1cac-4167-927e-49c02c93625f'}}).then((user) => {
     console.log(user); // {id: 'ff599c67-1cac-4167-927e-49c02c93625f', first_name: 'john', last_name: 'doe'}
})

// Override the global options at any time
api.users.get({transformResponse: () => 'something else'}).then((response) => {
   console.log(response); // 'something else'
});

API

@zakkudo/open-api-tree~OpenApiTree ⏏

Kind: Exported class

new OpenApiTree(schema, options, include)

Returns: Object - The generated api tree

ParamTypeDefaultDescription
schemaObjectThe swagger/openapi schema, usually accessible from a url path like v2/swagger.json where swagger is run
optionsOptionsOptions modifying the network call, mostly analogous to fetch
includeObjectModifiers for the conversion of the swagger schema to an api tree schema
include.validationBooleantrueSet to false to not include json schemas for client side validation of api requests

OpenApiTree~FetchFunction : function

Executes the network request using the api tree configuration. Generated from the triplets of the form [url, options, jsonschema] where only url is required.

Kind: inner typedef of OpenApiTree

ParamTypeDefaultDescription
optionsOptionsThe override options for the final network call
validateBooleantrueSet to false to force validation to be skipped, even if there is a schema

OpenApiTree~Options : Object

Options modifying the network call, mostly analogous to fetch

Kind: inner typedef of OpenApiTree
Properties

NameTypeDefaultDescription
options.methodString'GET'GET, POST, PUT, DELETE, etc.
options.modeString'same-origin'no-cors, cors, same-origin
options.cacheString'default'default, no-cache, reload, force-cache, only-if-cached
options.credentialsString'omit'include, same-origin, omit
options.headersString"application/json; charset=utf-8".
options.redirectString'follow'manual, follow, error
options.referrerString'client'no-referrer, client
options.bodyString | ObjectJSON.stringify is automatically run for non-string types
options.paramsString | ObjectQuery params to be appended to the url. The url must not already have params. The serialization uses the same rules as used by @zakkudo/query-string
options.unsafeBooleanDisable escaping of params in the url
options.transformRequestfunction | Array.<function()>Transforms for the request body. When not supplied, it by default json serializes the contents if not a simple string. Also accepts promises as return values for asynchronous work.
options.transformResponsefunction | Array.<function()>Transform the response. Also accepts promises as return values for asynchronous work.
options.transformErrorfunction | Array.<function()>Transform the error response. Return the error to keep the error state. Return a non Error to recover from the error in the promise chain. A good place to place a login handler when recieving a 401 from a backend endpoint or redirect to another page. It's preferable to never throw an error here which will break the error transform chain in a non-graceful way. Also accepts promises as return values for asynchronous work.

@zakkudo/open-api-tree/toApiTreeSchema~toApiTreeSchema(schema, include) ⇒ Object

Converts an open-api/swagger schema to an api tree configuration.

Kind: Exported function

Returns: Object - The converted schema that can be passed to ApiTree from @zakkudo/api-tree
Throws:

  • Error when trying to convert an unsupported schema
ParamTypeDefaultDescription
schemaObjectThe schema as such that comes from swagger.json
includeObjectModifiers for the conversion of the swagger schema to an api tree schema
include.validationBooleantrueSet to false to not include json schemas for client side validation of api requests

@zakkudo/open-api-tree/ValidationError~ValidationError ⏏

Aliased error from package @zakkudo/api-tree/ValidationError

Kind: Exported class

@zakkudo/open-api-tree/HttpError~HttpError ⏏

Aliased error from package @zakkudo/api-tree/HttpError

Kind: Exported class

@zakkudo/open-api-tree/UrlError~UrlError ⏏

Aliased error from package @zakkudo/api-tree/UrlError

Kind: Exported class

@zakkudo/open-api-tree/QueryStringError~QueryStringError ⏏

Aliased error from package @zakkudo/api-tree/QueryStringError

Kind: Exported class

1.0.0

5 years ago

0.0.20

6 years ago

0.0.19

6 years ago

0.0.18

6 years ago

0.0.17

6 years ago

0.0.16

6 years ago

0.0.15

6 years ago

0.0.14

6 years ago

0.0.13

6 years ago

0.0.12

6 years ago

0.0.11

6 years ago

0.0.10

6 years ago

0.0.9

6 years ago

0.0.8

6 years ago

0.0.7

6 years ago

0.0.6

6 years ago

0.0.5

6 years ago

0.0.4

6 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago