@zakkudo/open-api-tree
v1.0.0
Published
Make working with swagger/openapi api trees enjoyable.
Downloads
70
Maintainers
Readme
@zakkudo/open-api-tree
Make working with backend api trees enjoyable from swagger/openapi.
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
- ~OpenApiTree
- new OpenApiTree(schema, [options], [include])
- ~FetchFunction : function
- ~Options : Object
new OpenApiTree(schema, [options], [include])
Returns: Object - The generated api tree
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| schema | Object | | The swagger/openapi schema, usually accessible from a url path like v2/swagger.json
where swagger is run |
| [options] | Options | | Options modifying the network call, mostly analogous to fetch |
| [include] | Object | | Modifiers for the conversion of the swagger schema to an api tree schema |
| [include.validation] | Boolean | true | Set 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
| Param | Type | Default | Description | | --- | --- | --- | --- | | [options] | Options | | The override options for the final network call | | [validate] | Boolean | true | Set 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
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| [options.method] | String | 'GET' | GET, POST, PUT, DELETE, etc. |
| [options.mode] | String | 'same-origin' | no-cors, cors, same-origin |
| [options.cache] | String | 'default' | default, no-cache, reload, force-cache, only-if-cached |
| [options.credentials] | String | 'omit' | include, same-origin, omit |
| [options.headers] | String | | "application/json; charset=utf-8". |
| [options.redirect] | String | 'follow' | manual, follow, error |
| [options.referrer] | String | 'client' | no-referrer, client |
| [options.body] | String | Object | | JSON.stringify
is automatically run for non-string types |
| [options.params] | String | Object | | Query 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.unsafe] | Boolean | | Disable escaping of params in the url |
| [options.transformRequest] | function | 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.transformResponse] | function | Array.<function()> | | Transform the response. Also accepts promises as return values for asynchronous work. |
| [options.transformError] | function | 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
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| schema | Object | | The schema as such that comes from swagger.json
|
| [include] | Object | | Modifiers for the conversion of the swagger schema to an api tree schema |
| [include.validation] | Boolean | true | Set 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