├── .editorconfig ├── .gitignore ├── .node-version ├── .npmignore ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── scripts ├── build.bash └── prepareTests.bash ├── src ├── DefinitionGenerator.ts ├── ServerlessOpenApiDocumentation.ts ├── __tests__ │ └── DefinitionGenerator.spec.ts ├── index.ts ├── types.ts └── utils.ts ├── test └── project │ ├── good.yml │ ├── models │ ├── ErrorResponse.json │ └── PutDocumentResponse.json │ ├── openapi.yml │ ├── package.json │ ├── serverless.docs.yml │ ├── serverless.yml │ └── yarn.lock ├── tsconfig.json ├── tslint.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | charset = "utf-8" 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /npm-* 3 | /build 4 | .coverage 5 | .directory 6 | .DS_STORE* 7 | *.log 8 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 6 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | **/__tests__/** 2 | .* 3 | tslint.json 4 | tsconfig.json 5 | jest.config.js 6 | yarn.lock 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: ["6"] 3 | 4 | install: 5 | - yarn install 6 | 7 | script: 8 | - yarn lint 9 | - yarn build 10 | - yarn test:build 11 | - DEBUG=true yarn test:coverage 12 | 13 | before_deploy: 14 | - echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" > ~/.npmrc 15 | 16 | deploy: 17 | - provider: script 18 | skip_cleanup: true 19 | script: npm run release 20 | on: 21 | tags: true 22 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "compounds": [ 7 | { 8 | "name": "Compound", 9 | "configurations": [ 10 | "Project1" 11 | ] 12 | } 13 | ], 14 | "configurations": [ 15 | { 16 | "type": "node", 17 | "request": "attach", 18 | "name": "Attach (Inspector Protocol)", 19 | "port": 9229, 20 | "protocol": "inspector" 21 | }, 22 | { 23 | "type": "node", 24 | "request": "launch", 25 | "protocol": "legacy", 26 | "name": "Jest (Legacy)", 27 | "cwd": "${workspaceRoot}", 28 | "stopOnEntry": false, 29 | "runtimeExecutable": null, 30 | "runtimeArgs": [ 31 | "--debug-brk", 32 | "${workspaceRoot}/node_modules/.bin/jest", 33 | "-i", 34 | "-c", ".jestrc" 35 | ], 36 | "smartStep": true, 37 | "outDir": null, 38 | "sourceMaps": true, 39 | "port": 5858, 40 | "address": "127.0.0.1", 41 | "skipFiles": [ 42 | "/**/*.js", 43 | "node_modules/**/*.js" 44 | ] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "./node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "tsc", 4 | "isShellCommand": true, 5 | "args": [], 6 | "showOutput": "silent", 7 | "problemMatcher": "$tsc" 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.4.0][] - 2018-04-04 11 | 12 | - Various changes 13 | 14 | ## [0.3.0][] - 2017-08-30 15 | 16 | ### Changed 17 | 18 | - Plugin now generates OpenAPI documentation with a version of `3.0.0` instead of `3.0.0-RC2`. 19 | - Operation now supports `deprecated` and `tags` properties. 20 | - Parameters now support the `content` property. 21 | - Updated various build dependencies. 22 | - OpenAPI definition will now be smaller in most cases, choosing to omit optional properties instead of using empty defaults. 23 | 24 | ### Fixed 25 | 26 | - Handle when `models` is not iterable. 27 | - Handle when `models` have no `schema`. 28 | - Always lowercase the HTTP method to conform to OpenAPI spec. 29 | 30 | ## [v0.2.1] - 2017-07-07 31 | 32 | Last release prior to CHANGELOG being added. 33 | 34 | 35 | [Unreleased]: https://github.com/temando/serverless-openapi-documentation/compare/v0.4.0...HEAD 36 | [0.4.0]: https://github.com/temando/serverless-openapi-documentation/compare/v0.4.0...v0.4.0 37 | [0.4.0]: https://github.com/temando/serverless-openapi-documentation/compare/v0.3.0...v0.4.0 38 | [0.3.0]: https://github.com/temando/serverless-openapi-documentation/tree/v0.3.0 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Temando 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serverless OpenAPI Documentation Plugin 2 | 3 | [![NPM](https://img.shields.io/npm/v/serverless-openapi-documentation.svg)](https://npmjs.org/packages/serverless-openapi-documentation/) 4 | [![Travis CI](https://img.shields.io/travis/temando/serverless-openapi-documentation.svg)](https://travis-ci.org/temando/serverless-openapi-documentation) 5 | [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) 6 | 7 | Generates [**OpenAPI 3.0.0**](https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md) documentation from serverless configuration files. OpenAPI is formerly known as Swagger. The configuration is inspired by the format used in [serverless-aws-documentation](https://www.npmjs.com/package/serverless-aws-documentation). 8 | 9 | Works well with [Lincoln OpenAPI Renderer](https://github.com/temando/open-api-renderer). 10 | 11 | --- 12 | 13 | - [Usage](#usage) 14 | - [Options](#options) 15 | - [Configuration](#configuration) 16 | - [Models](#models) 17 | - [Functions](#functions) 18 | - [`queryParams`](#queryparams) 19 | - [`pathParams`](#pathparams) 20 | - [`cookieParams`](#cookieparams) 21 | - [`requestModels`](#requestmodels) 22 | - [`methodResponses`](#methodresponses) 23 | - [Example Configuration](#example-configuration) 24 | - [Install](#install) 25 | 26 | --- 27 | 28 | ## Usage 29 | 30 | This plugin requires additional configuration to use, see the "[Configuration](#configuration)" section for how to configure the plugin to generate documentation. 31 | 32 | Below are the commandline options to run the generator: 33 | 34 | ```bash 35 | serverless openapi generate [options] 36 | ``` 37 | 38 | ### Options 39 | 40 | ```bash 41 | Plugin: ServerlessOpenAPIDocumentation 42 | openapi generate ...................... Generate OpenAPI v3 Documentation 43 | --output / -o ...................... Output file location [default: openapi.yml|json] 44 | --format / -f ...................... OpenAPI file format (yml|json) [default: yml] 45 | --indent / -i ...................... File indentation in spaces [default: 2] 46 | --help / -h ...................... Help 47 | ``` 48 | 49 | ### Configuration 50 | 51 | To configure this plugin to generate valid OpenAPI documentation there are two places you'll need to modify in your `serverless.yml` file, the `custom` variables section and the `http` event section for each given function in your service. 52 | 53 | This plugin is compatible with the same documentation configuration structure in [serverless-aws-documentation](https://www.npmjs.com/package/serverless-aws-documentation) and can run beside it. 54 | 55 | The `custom` section of your `serverless.yml` can be configured as below: 56 | 57 | ```yml 58 | custom: 59 | documentation: 60 | version: '1' 61 | title: 'My API' 62 | description: 'This is my API' 63 | models: {} 64 | ``` 65 | 66 | These configurations can be quite verbose; you can separate it out into it's own file, such as `serverless.doc.yml` as below: 67 | 68 | ```yml 69 | custom: 70 | documentation: ${file(serverless.doc.yml):documentation} 71 | 72 | functions: 73 | myFunc: 74 | events: 75 | - http: 76 | path: getStuff 77 | method: get 78 | documentation: ${file(serverless.doc.yml):endpoints.myFunc} 79 | ``` 80 | 81 | For more info on `serverless.yml` syntax, see their docs. 82 | 83 | #### Models 84 | 85 | Models contain additional information that you can use to define schemas for endpoints. You must define the *content type* for each schema that you provide in the models. 86 | 87 | The *required* directives for the models section are as follow: 88 | 89 | * `name`: the name of the schema 90 | * `description`: a description of the schema 91 | * `contentType`: the content type of the described request/response (ie. `application/json` or `application/xml`). 92 | * `schema`: The JSON Schema ([website](http://json-schema.org/)) that describes the model. You can either use inline `YAML` to define these, or refer to an external schema file as below 93 | 94 | ```yml 95 | custom: 96 | documentation: 97 | models: 98 | - name: "ErrorResponse" 99 | description: "This is an error" 100 | contentType: "application/json" 101 | schema: ${file(models/ErrorResponse.json)} 102 | - name: "PutDocumentResponse" 103 | description: "PUT Document response model (external reference example)" 104 | contentType: "application/json" 105 | schema: ${file(models/PutDocumentResponse.json)} 106 | - name: "PutDocumentRequest" 107 | description: "PUT Document request model (inline example)" 108 | contentType: "application/json" 109 | schema: 110 | $schema: "http://json-schema.org/draft-04/schema#" 111 | properties: 112 | SomeObject: 113 | type: "object" 114 | properties: 115 | SomeAttribute: 116 | type: "string" 117 | ``` 118 | 119 | #### Functions 120 | 121 | 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. 122 | 123 | The `documentation` section of the event configuration can contain the following attributes: 124 | 125 | * `summary`: a short description of the method 126 | * `description`: a detailed description of the method 127 | * `tags`: an array of tags for this event 128 | * `deprecated`: boolean indicator that indicates clients should migrate away from this function 129 | * `requestBody`: contains description of the request 130 | * `description`: a description of the request body 131 | * `requestModels`: a list of models to describe the request bodies (see [requestModels](#requestmodels) below) 132 | * `queryParams`: a list of query parameters (see [queryParams](#queryparams) below) 133 | * `pathParams`: a list of path parameters (see [pathParams](#pathparams) below) 134 | * `cookieParams`: a list of cookie parameters (see [cookieParams](#cookieparams) below) 135 | * `methodResponses`: an array of response models and applicable status codes 136 | * `statusCode`: applicable http status code (ie. 200/404/500 etc.) 137 | * `responseBody`: contains description of the response 138 | * `description`: a description of the body response 139 | * `responseHeaders`: a list of response headers (see [responseHeaders](#responseheaders) below) 140 | * `responseModels`: a list of models to describe the request bodies (see [responseModels](#responsemodels) below) for each `Content-Type` 141 | 142 | ```yml 143 | functions: 144 | createUser: 145 | handler: "handler.create" 146 | events: 147 | - http: 148 | path: "create" 149 | method: "post" 150 | documentation: 151 | summary: "Create User" 152 | description: "Creates a user and then sends a generated password email" 153 | requestBody: 154 | description: "A user information object" 155 | requestModels: 156 | application/json: "PutDocumentRequest" 157 | pathParams: 158 | - name: "username" 159 | description: "The username for a user to create" 160 | schema: 161 | type: "string" 162 | pattern: "^[-a-z0-9_]+$" 163 | queryParams: 164 | - name: "membershipType" 165 | description: "The user's Membership Type" 166 | schema: 167 | type: "string" 168 | enum: 169 | - "premium" 170 | - "standard" 171 | cookieParams: 172 | - name: "SessionId" 173 | description: "A Session ID variable" 174 | schema: 175 | type: "string" 176 | methodResponses: 177 | - statusCode: 201 178 | responseBody: 179 | description: "A user object along with generated API Keys" 180 | responseModels: 181 | application/json: "PutDocumentResponse" 182 | - statusCode: 500 183 | responseBody: 184 | description: "An error message when creating a new user" 185 | responseModels: 186 | application/json: "ErrorResponse" 187 | ``` 188 | 189 | #### `queryParams` 190 | 191 | Query parameters can be described as follow: 192 | 193 | * `name`: the name of the query variable 194 | * `description`: a description of the query variable 195 | * `required`: whether the query parameter is mandatory (boolean) 196 | * `schema`: JSON schema (inline or file) 197 | 198 | ```yml 199 | queryParams: 200 | - name: "filter" 201 | description: "The filter parameter" 202 | required: true 203 | schema: 204 | type: "string" 205 | ``` 206 | 207 | #### `pathParams` 208 | 209 | Path parameters can be described as follow: 210 | 211 | * `name`: the name of the query variable 212 | * `description`: a description of the query variable 213 | * `schema`: JSON schema (inline or file) 214 | 215 | ```yml 216 | pathParams: 217 | - name: "usernameId" 218 | description: "The usernameId parameter" 219 | schema: 220 | type: "string" 221 | ``` 222 | 223 | #### `cookieParams` 224 | 225 | Cookie parameters can be described as follow: 226 | 227 | * `name`: the name of the query variable 228 | * `description`: a description of the query variable 229 | * `required`: whether the query parameter is mandatory (boolean) 230 | * `schema`: JSON schema (inline or file) 231 | 232 | ```yml 233 | cookieParams: 234 | - name: "sessionId" 235 | description: "The sessionId parameter" 236 | required: true 237 | schema: 238 | type: "string" 239 | ``` 240 | 241 | #### `requestModels` 242 | 243 | The `requestModels` property allows you to define models for the HTTP Request of the function event. You can define a different model for each different `Content-Type`. You can define a reference to the relevant request model named in the `models` section of your configuration (see [Defining Models](#models) section). 244 | 245 | ```yml 246 | requestModels: 247 | application/json: "CreateRequest" 248 | application/xml: "CreateRequestXML" 249 | ``` 250 | 251 | #### `methodResponses` 252 | 253 | You can define the response schemas by defining properties for your function event. 254 | 255 | For an example of a `methodResponses` configuration for an event see below: 256 | 257 | ```yml 258 | methodResponse: 259 | - statusCode: 200 260 | responseHeaders: 261 | - name: "Content-Type" 262 | description: "Content Type header" 263 | schema: 264 | type: "string" 265 | responseModels: 266 | application/json: "CreateResponse" 267 | application/xml: "CreateResponseXML" 268 | ``` 269 | 270 | ##### `responseModels` 271 | 272 | The `responseModels` property allows you to define models for the HTTP Response of the function event. You can define a different model for each different `Content-Type`. You can define a reference to the relevant response model named in the `models` section of your configuration (see [Defining Models](#models) section). 273 | 274 | ```yml 275 | responseModels: 276 | application/json: "CreateResponse" 277 | application/xml: "CreateResponseXML" 278 | ``` 279 | 280 | ##### `responseHeaders` and `requestHeaders` 281 | 282 | The `responseHeaders/requestHeaders` section of the configuration allows you to define the HTTP headers for the function event. 283 | 284 | The attributes for a header are as follow: 285 | 286 | * `name`: the name of the HTTP Header 287 | * `description`: a description of the HTTP Header 288 | * `schema`: JSON schema (inline or file) 289 | 290 | ```yml 291 | responseHeaders: 292 | - name: "Content-Type" 293 | description: "Content Type header" 294 | schema: 295 | type: "string" 296 | requestHeaders: 297 | - name: "Content-Type" 298 | description: "Content Type header" 299 | schema: 300 | type: "string" 301 | ``` 302 | 303 | ## Example configuration 304 | 305 | Please view the example [serverless.yml](test/project/serverless.yml). 306 | 307 | ## Install 308 | 309 | This plugin works for Serverless 1.x and up. Serverless 0.5 is not supported. 310 | 311 | To add this plugin to your package.json: 312 | 313 | **Using npm:** 314 | ```bash 315 | npm install serverless-openapi-documentation --save-dev 316 | ``` 317 | 318 | **Using Yarn:** 319 | ```bash 320 | yarn add serverless-openapi-documentation --dev 321 | ``` 322 | 323 | Next you need to add the plugin to the `plugins` section of your `serverless.yml` file. 324 | 325 | ```yml 326 | plugins: 327 | - serverless-openapi-documentation 328 | ``` 329 | 330 | You can confirm the plugin is correctly installed by running: 331 | 332 | ```bash 333 | serverless | grep -i "ServerlessOpenAPIDocumentation" 334 | ``` 335 | 336 | It should return `ServerlessOpenAPIDocumentation` as one of the plugins on the list. 337 | 338 | > Note: Add this plugin _after_ `serverless-offline` to prevent issues with `String.replaceAll` being overridden incorrectly. 339 | 340 | ## License 341 | 342 | MIT 343 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "verbose": true, 3 | "transform": { ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js" }, 4 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", 5 | "moduleFileExtensions": [ "ts", "tsx", "js" ], 6 | "coverageDirectory": ".coverage", 7 | "testPathIgnorePatterns": [ 8 | "/node_modules/", 9 | "/build/", 10 | "d.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serverless-openapi-documentation", 3 | "version": "0.4.0", 4 | "description": "Serverless 1.0 plugin to generate OpenAPI V3 documentation from serverless configuration", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/temando/serverless-openapi-documentation.git" 9 | }, 10 | "bugs": "https://github.com/temando/serverless-openapi-documentation/issues", 11 | "author": "Abilio Henrique ", 12 | "contributors": [ 13 | "Abilio Henrique ", 14 | "nfour " 15 | ], 16 | "keywords": [ 17 | "OpenAPI", 18 | "swagger", 19 | "serverless" 20 | ], 21 | "license": "MIT", 22 | "scripts": { 23 | "test": "jest", 24 | "test:build": "jest -c '{}' build", 25 | "test:coverage": "jest --coverage", 26 | "lint": "tslint -p tsconfig.json --type-check -c tslint.json", 27 | "preversion": "yarn lint && yarn build && yarn test:build && changelog-verify CHANGELOG.md", 28 | "version": "version-changelog CHANGELOG.md && changelog-verify CHANGELOG.md && git add CHANGELOG.md", 29 | "release": "cd build && npm publish", 30 | "test:project": "cd test/project && yarn sls openapi generate", 31 | "test:prepare": "scripts/prepareTests.bash", 32 | "build:link": "yarn build && cd build && yarn link", 33 | "build:watch": "yarn build && tsc --watch", 34 | "build": "scripts/build.bash" 35 | }, 36 | "devDependencies": { 37 | "@types/bluebird": "^3.5.8", 38 | "@types/chalk": "^0.4.31", 39 | "@types/fs-extra": "^4.0.0", 40 | "@types/jest": "^20.0.2", 41 | "@types/js-yaml": "^3.5.31", 42 | "@types/node": "^8.0.7", 43 | "@types/uuid": "^3.0.0", 44 | "changelog-verify": "^1.0.4", 45 | "jest": "^20.0.4", 46 | "serverless": "^1.16.1", 47 | "ts-jest": "^20.0.6", 48 | "ts-node": "^3.1.0", 49 | "tslint": "^5.4.3", 50 | "tslint-config-temando": "^1.1.4", 51 | "typescript": "^2.4.1", 52 | "version-changelog": "^2.1.0" 53 | }, 54 | "dependencies": { 55 | "@jdw/jst": "^2.0.0-beta.9", 56 | "bluebird": "^3.5.0", 57 | "chalk": "^2.0.1", 58 | "fs-extra": "^4.0.1", 59 | "js-yaml": "^3.8.4", 60 | "lutils": "^2.4.0", 61 | "swagger2openapi": "^2.5.0", 62 | "uuid": "^3.1.0" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scripts/build.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Clean 4 | rm -rf build 5 | mkdir build 6 | 7 | # Copy latent, belonging to the index module 8 | rsync -am . ./build --exclude '*/*' --include '*' 9 | 10 | # Copy latent files from source, recursively 11 | rsync -am ./src/* ./build --exclude '*.ts' 12 | 13 | # Build typescript 14 | yarn tsc 15 | -------------------------------------------------------------------------------- /scripts/prepareTests.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | yarn build:link \ 5 | && cd test/project \ 6 | && yarn \ 7 | && yarn link serverless-openapi-documentation 8 | -------------------------------------------------------------------------------- /src/DefinitionGenerator.ts: -------------------------------------------------------------------------------- 1 | import { dereference } from '@jdw/jst'; 2 | // tslint:disable-next-line no-submodule-imports 3 | import { validateSync as openApiValidatorSync } from 'swagger2openapi/validate'; 4 | import * as uuid from 'uuid'; 5 | import { IDefinition, IDefinitionConfig, IOperation, IParameterConfig, IServerlessFunctionConfig } from './types'; 6 | import { clone, isIterable, merge } from './utils'; 7 | 8 | export class DefinitionGenerator { 9 | // The OpenAPI version we currently validate against 10 | public version = '3.0.0'; 11 | 12 | // Base configuration object 13 | public definition = { 14 | openapi: this.version, 15 | components: {}, 16 | }; 17 | 18 | public config: IDefinitionConfig; 19 | 20 | /** 21 | * Constructor 22 | * @param serviceDescriptor IServiceDescription 23 | */ 24 | constructor (config: IDefinitionConfig) { 25 | this.config = clone(config); 26 | } 27 | 28 | public parse () { 29 | const { 30 | title = '', 31 | description = '', 32 | version = uuid.v4(), 33 | models, 34 | } = this.config; 35 | 36 | merge(this.definition, { 37 | openapi: this.version, 38 | info: { title, description, version }, 39 | paths: {}, 40 | components: { 41 | schemas: {}, 42 | securitySchemes: {}, 43 | }, 44 | }); 45 | 46 | if (isIterable(models)) { 47 | for (const model of models) { 48 | if (!model.schema) { 49 | continue; 50 | } 51 | 52 | this.definition.components.schemas[model.name] = this.cleanSchema( 53 | dereference(model.schema), 54 | ); 55 | } 56 | } 57 | 58 | return this; 59 | } 60 | 61 | public validate (): { valid: boolean, context: string[], warnings: any[], error?: any[] } { 62 | const payload: any = {}; 63 | 64 | try { 65 | openApiValidatorSync(this.definition, payload); 66 | } catch (error) { 67 | payload.error = error.message; 68 | } 69 | 70 | return payload; 71 | } 72 | 73 | /** 74 | * Add Paths to OpenAPI Configuration from Serverless function documentation 75 | * @param config Add 76 | */ 77 | public readFunctions (config: IServerlessFunctionConfig[]): void { 78 | // loop through function configurations 79 | for (const funcConfig of config) { 80 | // loop through http events 81 | for (const httpEvent of this.getHttpEvents(funcConfig.events)) { 82 | const httpEventConfig = httpEvent.http; 83 | 84 | if (httpEventConfig.documentation) { 85 | // Build OpenAPI path configuration structure for each method 86 | const pathConfig = { 87 | [`/${httpEventConfig.path}`]: { 88 | [httpEventConfig.method.toLowerCase()]: this.getOperationFromConfig( 89 | funcConfig._functionName, 90 | httpEventConfig.documentation, 91 | ), 92 | }, 93 | }; 94 | 95 | // merge path configuration into main configuration 96 | merge(this.definition.paths, pathConfig); 97 | } 98 | } 99 | } 100 | } 101 | 102 | /** 103 | * Cleans schema objects to make them OpenAPI compatible 104 | * @param schema JSON Schema Object 105 | */ 106 | private cleanSchema (schema) { 107 | // Clone the schema for manipulation 108 | const cleanedSchema = clone(schema); 109 | 110 | // Strip $schema from schemas 111 | if (cleanedSchema.$schema) { 112 | delete cleanedSchema.$schema; 113 | } 114 | 115 | // Return the cleaned schema 116 | return cleanedSchema; 117 | } 118 | 119 | /** 120 | * Generate Operation objects from the Serverless Config. 121 | * 122 | * @link https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#operationObject 123 | * @param funcName 124 | * @param documentationConfig 125 | */ 126 | private getOperationFromConfig (funcName: string, documentationConfig): IOperation { 127 | const operationObj: IOperation = { 128 | operationId: funcName, 129 | }; 130 | 131 | if (documentationConfig.summary) { 132 | operationObj.summary = documentationConfig.summary; 133 | } 134 | 135 | if (documentationConfig.description) { 136 | operationObj.description = documentationConfig.description; 137 | } 138 | 139 | if (documentationConfig.tags) { 140 | operationObj.tags = documentationConfig.tags; 141 | } 142 | 143 | if (documentationConfig.deprecated) { 144 | operationObj.deprecated = true; 145 | } 146 | 147 | if (operationObj.requestBody) { 148 | operationObj.requestBody = this.getRequestBodiesFromConfig(documentationConfig); 149 | } 150 | 151 | if (operationObj.parameters) { 152 | operationObj.parameters = this.getParametersFromConfig(documentationConfig); 153 | } 154 | 155 | operationObj.responses = this.getResponsesFromConfig(documentationConfig); 156 | 157 | return operationObj; 158 | } 159 | 160 | /** 161 | * Derives Path, Query and Request header parameters from Serverless documentation 162 | * @param documentationConfig 163 | */ 164 | private getParametersFromConfig (documentationConfig): IParameterConfig[] { 165 | const parameters: IParameterConfig[] = []; 166 | 167 | // Build up parameters from configuration for each parameter type 168 | for (const type of ['path', 'query', 'header', 'cookie']) { 169 | let paramBlock; 170 | if (type === 'path' && documentationConfig.pathParams) { 171 | paramBlock = documentationConfig.pathParams; 172 | } else if (type === 'query' && documentationConfig.queryParams) { 173 | paramBlock = documentationConfig.queryParams; 174 | } else if (type === 'header' && documentationConfig.requestHeaders) { 175 | paramBlock = documentationConfig.requestHeaders; 176 | } else if (type === 'cookie' && documentationConfig.cookieParams) { 177 | paramBlock = documentationConfig.cookieParams; 178 | } else { 179 | continue; 180 | } 181 | 182 | // Loop through each parameter in a parameter block and add parameters to array 183 | for (const parameter of paramBlock) { 184 | const parameterConfig: IParameterConfig = { 185 | name: parameter.name, 186 | in: type, 187 | description: parameter.description || '', 188 | required: parameter.required || false, // Note: all path parameters must be required 189 | }; 190 | 191 | // if type is path, then required must be true (@see OpenAPI 3.0-RC1) 192 | if (type === 'path') { 193 | parameterConfig.required = true; 194 | } else if (type === 'query') { 195 | parameterConfig.allowEmptyValue = parameter.allowEmptyValue || false; // OpenAPI default is false 196 | 197 | if ('allowReserved' in parameter) { 198 | parameterConfig.allowReserved = parameter.allowReserved || false; 199 | } 200 | } 201 | 202 | if ('deprecated' in parameter) { 203 | parameterConfig.deprecated = parameter.deprecated; 204 | } 205 | 206 | if ('style' in parameter) { 207 | parameterConfig.style = parameter.style; 208 | 209 | parameterConfig.explode = parameter.explode 210 | ? parameter.explode 211 | : parameter.style === 'form'; 212 | } 213 | 214 | if (parameter.schema) { 215 | parameterConfig.schema = this.cleanSchema(parameter.schema); 216 | } 217 | 218 | if (parameter.example) { 219 | parameterConfig.example = parameter.example; 220 | } else if (parameter.examples && Array.isArray(parameter.examples)) { 221 | parameterConfig.examples = parameter.examples; 222 | } 223 | 224 | if (parameter.content) { 225 | parameterConfig.content = parameter.content; 226 | } 227 | 228 | parameters.push(parameterConfig); 229 | } 230 | } 231 | 232 | return parameters; 233 | } 234 | 235 | /** 236 | * Derives request body schemas from event documentation configuration 237 | * @param documentationConfig 238 | */ 239 | private getRequestBodiesFromConfig (documentationConfig) { 240 | const requestBodies = {}; 241 | 242 | if (!documentationConfig.requestModels) { 243 | throw new Error(`Required requestModels in: ${JSON.stringify(documentationConfig, null, 2)}`); 244 | } 245 | 246 | // Does this event have a request model? 247 | if (documentationConfig.requestModels) { 248 | // For each request model type (Sorted by "Content-Type") 249 | for (const requestModelType of Object.keys(documentationConfig.requestModels)) { 250 | // get schema reference information 251 | const requestModel = this.config.models.filter( 252 | (model) => model.name === documentationConfig.requestModels[requestModelType], 253 | ).pop(); 254 | 255 | if (requestModel) { 256 | const reqModelConfig = { 257 | schema: { 258 | $ref: `#/components/schemas/${documentationConfig.requestModels[requestModelType]}`, 259 | }, 260 | }; 261 | 262 | this.attachExamples(requestModel, reqModelConfig); 263 | 264 | const reqBodyConfig: { content: object, description?: string } = { 265 | content: { 266 | [requestModelType]: reqModelConfig, 267 | }, 268 | }; 269 | 270 | if (documentationConfig.requestBody && 'description' in documentationConfig.requestBody) { 271 | reqBodyConfig.description = documentationConfig.requestBody.description; 272 | } 273 | 274 | merge(requestBodies, reqBodyConfig); 275 | } 276 | } 277 | } 278 | 279 | return requestBodies; 280 | } 281 | 282 | private attachExamples (target, config) { 283 | if (target.examples && Array.isArray(target.examples)) { 284 | merge(config, { examples: clone(target.examples) }); 285 | } else if (target.example) { 286 | merge(config, { example: clone(target.example) }); 287 | } 288 | } 289 | 290 | /** 291 | * Gets response bodies from documentation config 292 | * @param documentationConfig 293 | */ 294 | private getResponsesFromConfig (documentationConfig) { 295 | const responses = {}; 296 | if (documentationConfig.methodResponses) { 297 | for (const response of documentationConfig.methodResponses) { 298 | const methodResponseConfig: { description: any, content: object, headers?: object } = { 299 | description: ( 300 | (response.responseBody && 'description' in response.responseBody) 301 | ? response.responseBody.description 302 | : `Status ${response.statusCode} Response` 303 | ), 304 | content: this.getResponseContent(response.responseModels), 305 | }; 306 | 307 | if (response.responseHeaders) { 308 | methodResponseConfig.headers = {}; 309 | for (const header of response.responseHeaders) { 310 | methodResponseConfig.headers[header.name] = { 311 | description: header.description || `${header.name} header`, 312 | }; 313 | if (header.schema) { 314 | methodResponseConfig.headers[header.name].schema = this.cleanSchema(header.schema); 315 | } 316 | } 317 | } 318 | 319 | merge(responses, { 320 | [response.statusCode]: methodResponseConfig, 321 | }); 322 | } 323 | } 324 | 325 | return responses; 326 | } 327 | 328 | private getResponseContent (response) { 329 | const content = {}; 330 | 331 | for (const responseKey of Object.keys(response)) { 332 | const responseModel = this.config.models.find((model) => 333 | model.name === response[responseKey], 334 | ); 335 | 336 | if (responseModel) { 337 | const resModelConfig = { 338 | schema: { 339 | $ref: `#/components/schemas/${response[responseKey]}`, 340 | }, 341 | }; 342 | 343 | this.attachExamples(responseModel, resModelConfig); 344 | 345 | merge(content, { [responseKey] : resModelConfig }); 346 | } 347 | } 348 | 349 | return content; 350 | } 351 | 352 | private getHttpEvents (funcConfig) { 353 | return funcConfig.filter((event) => event.http ? true : false); 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /src/ServerlessOpenApiDocumentation.ts: -------------------------------------------------------------------------------- 1 | import * as c from 'chalk'; 2 | import * as fs from 'fs'; 3 | import * as YAML from 'js-yaml'; 4 | import { inspect } from 'util'; 5 | import { DefinitionGenerator } from './DefinitionGenerator'; 6 | import { IDefinitionType, ILog } from './types'; 7 | import { merge } from './utils'; 8 | 9 | export class ServerlessOpenApiDocumentation { 10 | public hooks; 11 | public commands; 12 | /** Serverless Instance */ 13 | private serverless; 14 | /** CLI options */ 15 | private options; 16 | /** Serverless Service Custom vars */ 17 | private customVars; 18 | 19 | /** 20 | * Constructor 21 | * @param serverless 22 | * @param options 23 | */ 24 | constructor (serverless, options) { 25 | // pull the serverless instance into our class vars 26 | this.serverless = serverless; 27 | // pull the CLI options into our class vars 28 | this.options = options; 29 | // Serverless service custom variables 30 | this.customVars = this.serverless.variables.service.custom; 31 | 32 | // Declare the commands this plugin exposes for the Serverless CLI 33 | this.commands = { 34 | openapi: { 35 | commands: { 36 | generate: { 37 | lifecycleEvents: [ 38 | 'serverless', 39 | ], 40 | usage: 'Generate OpenAPI v3 Documentation', 41 | options: { 42 | output: { 43 | usage: 'Output file location [default: openapi.yml|json]', 44 | shortcut: 'o', 45 | }, 46 | format: { 47 | usage: 'OpenAPI file format (yml|json) [default: yml]', 48 | shortcut: 'f', 49 | }, 50 | indent: { 51 | usage: 'File indentation in spaces [default: 2]', 52 | shortcut: 'i', 53 | }, 54 | }, 55 | }, 56 | }, 57 | }, 58 | }; 59 | 60 | // Declare the hooks our plugin is interested in 61 | this.hooks = { 62 | 'openapi:generate:serverless': this.generate.bind(this), 63 | }; 64 | } 65 | 66 | log: ILog = (...str: string[]) => { 67 | process.stdout.write(str.join(' ')); 68 | } 69 | 70 | /** 71 | * Processes CLI input by reading the input from serverless 72 | * @returns config IConfigType 73 | */ 74 | private processCliInput (): IDefinitionType { 75 | const config: IDefinitionType = { 76 | format: 'yaml', 77 | file: 'openapi.yml', 78 | indent: 2, 79 | }; 80 | 81 | config.indent = this.serverless.processedInput.options.indent || 2; 82 | config.format = this.serverless.processedInput.options.format || 'yaml'; 83 | 84 | if (['yaml', 'json'].indexOf(config.format.toLowerCase()) < 0) { 85 | throw new Error('Invalid Output Format Specified - must be one of "yaml" or "json"'); 86 | } 87 | 88 | config.file = this.serverless.processedInput.options.output || 89 | ((config.format === 'yaml') ? 'openapi.yml' : 'openapi.json'); 90 | 91 | this.log( 92 | `${c.bold.green('[OPTIONS]')}`, 93 | `format: "${c.bold.red(config.format)}",`, 94 | `output file: "${c.bold.red(config.file)}",`, 95 | `indentation: "${c.bold.red(String(config.indent))}"\n\n`, 96 | ); 97 | 98 | return config; 99 | } 100 | 101 | /** 102 | * Generates OpenAPI Documentation based on serverless configuration and functions 103 | */ 104 | private generate () { 105 | this.log(c.bold.underline('OpenAPI v3 Documentation Generator\n\n')); 106 | // Instantiate DocumentGenerator 107 | const generator = new DefinitionGenerator(this.customVars.documentation); 108 | 109 | generator.parse(); 110 | 111 | // Map function configurations 112 | const funcConfigs = this.serverless.service.getAllFunctions().map((functionName) => { 113 | const func = this.serverless.service.getFunction(functionName); 114 | return merge({ _functionName: functionName }, func); 115 | }); 116 | 117 | // Add Paths to OpenAPI Output from Function Configuration 118 | generator.readFunctions(funcConfigs); 119 | 120 | // Process CLI Input options 121 | const config = this.processCliInput(); 122 | 123 | this.log(`${ c.bold.yellow('[VALIDATION]') } Validating OpenAPI generated output\n`); 124 | 125 | const validation = generator.validate(); 126 | 127 | if (validation.valid) { 128 | this.log(`${ c.bold.green('[VALIDATION]') } OpenAPI valid: ${c.bold.green('true')}\n\n`); 129 | } else { 130 | this.log(`${c.bold.red('[VALIDATION]')} Failed to validate OpenAPI document: \n\n`); 131 | this.log(`${c.bold.green('Context:')} ${JSON.stringify(validation.context, null, 2)}\n`); 132 | 133 | if (typeof validation.error === 'string') { 134 | this.log(`${validation.error}\n\n`); 135 | } else { 136 | for (const info of validation.error) { 137 | this.log(c.grey('\n\n--------\n\n')); 138 | this.log(' ', c.blue(info.dataPath), '\n'); 139 | this.log(' ', info.schemaPath, c.bold.yellow(info.message)); 140 | this.log(c.grey('\n\n--------\n\n')); 141 | this.log(`${inspect(info, { colors: true, depth: 2 })}\n\n`); 142 | } 143 | } 144 | } 145 | 146 | const { definition } = generator; 147 | 148 | // Output the OpenAPI document to the correct format 149 | 150 | let output; 151 | switch (config.format.toLowerCase()) { 152 | case 'json': 153 | output = JSON.stringify(definition, null, config.indent); 154 | break; 155 | case 'yaml': 156 | default: 157 | output = YAML.safeDump(definition, { indent: config.indent }); 158 | break; 159 | } 160 | 161 | fs.writeFileSync(config.file, output); 162 | 163 | this.log(`${ c.bold.green('[OUTPUT]') } To "${c.bold.red(config.file)}"\n`); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/__tests__/DefinitionGenerator.spec.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as Serverless from 'serverless'; 3 | import { DefinitionGenerator } from '../DefinitionGenerator'; 4 | 5 | class ServerlessInterface extends Serverless { 6 | public service: any = {}; 7 | public config: any = {}; 8 | public yamlParser: any = {}; 9 | public pluginManager: any = {}; 10 | public variables: any = {}; 11 | } 12 | 13 | describe('OpenAPI Documentation Generator', () => { 14 | it('Generates OpenAPI document', async () => { 15 | const servicePath = path.join(__dirname, '../../test/project'); 16 | const serverlessYamlPath = path.join(servicePath, './serverless.yml'); 17 | const sls: ServerlessInterface = new Serverless(); 18 | 19 | sls.config.update({ 20 | servicePath, 21 | }); 22 | 23 | const config = await sls.yamlParser.parse(serverlessYamlPath); 24 | sls.pluginManager.cliOptions = { stage: 'dev' }; 25 | 26 | await sls.service.load(config); 27 | await sls.variables.populateService(); 28 | 29 | if ('documentation' in sls.service.custom) { 30 | const docGen = new DefinitionGenerator(sls.service.custom.documentation); 31 | 32 | expect(docGen).not.toBeNull(); 33 | } else { 34 | throw new Error('Cannot find "documentation" in custom section of "serverless.yml"'); 35 | } 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { ServerlessOpenApiDocumentation } from './ServerlessOpenApiDocumentation'; 2 | 3 | // tslint:disable-next-line no-default-export 4 | export default ServerlessOpenApiDocumentation; 5 | module.exports = ServerlessOpenApiDocumentation; 6 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface IModels { 3 | name: string; 4 | description: string; 5 | contentType: string; 6 | schema: object | any[]; 7 | examples: any[]; 8 | example: object; 9 | } 10 | 11 | export interface IDefinitionConfig { 12 | title: string; 13 | description: string; 14 | version?: string; 15 | models: IModels[]; 16 | } 17 | 18 | export interface IDefinitionType { 19 | file: string; 20 | format: 'yaml' | 'json'; 21 | indent: number; 22 | } 23 | 24 | export interface IServerlessFunctionConfig { 25 | _functionName: string; 26 | handler: string; 27 | description?: string; 28 | environment?: object; 29 | events?: any[]; 30 | } 31 | 32 | // TODO: We could use another TS based OpenAPI project to get type information 33 | // for OpenAPI definitions. 34 | // @see https://github.com/Mermade/awesome-openapi3#parsersmodelsvalidators 35 | 36 | // @see https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#operation-object 37 | export interface IOperation { 38 | tags?: string[]; 39 | summary?: string; 40 | description?: string; 41 | externalDocs?: any; 42 | operationId?: string; 43 | parameters?: IParameterConfig[]; 44 | requestBody?: any; 45 | responses?: any; 46 | callbacks?: any; 47 | deprecated?: boolean; 48 | security?: any[]; 49 | servers?: any[]; 50 | } 51 | 52 | // @see https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#parameterObject 53 | export interface IParameterConfig { 54 | name: string; 55 | in: 'path' | 'query' | 'header' | 'cookie'; 56 | description: string; 57 | required?: boolean; 58 | schema?: object; 59 | deprecated?: boolean; 60 | allowEmptyValue?: boolean; 61 | style?: 'form' | 'simple'; 62 | explode?: boolean; 63 | allowReserved?: boolean; 64 | example?: any; 65 | examples?: any[]; 66 | content?: Map; 67 | } 68 | 69 | // FIXME: 70 | export interface IDefinition { 71 | openapi: string; 72 | info: any; 73 | servers?: any[]; 74 | paths: any; 75 | components?: any; 76 | security?: any[]; 77 | tags?: any[]; 78 | externalDocs: any; 79 | } 80 | 81 | export type ILog = (...str: string[]) => void; 82 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { Clone, IMerge, Merge } from 'lutils'; 2 | 3 | export const merge: IMerge = new Merge({ depth: 100 }).merge; 4 | export const clone = new Clone({ depth: 100 }).clone; 5 | 6 | export function isIterable (obj) { 7 | if (obj === null || obj === undefined) { 8 | return false; 9 | } 10 | 11 | return typeof obj[Symbol.iterator] === 'function'; 12 | } 13 | -------------------------------------------------------------------------------- /test/project/good.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0-RC1 2 | description: '' 3 | version: 0.0.0 4 | title: '' 5 | paths: 6 | /dock: 7 | get: 8 | operationId: dockSearch 9 | summary: Search Documents 10 | description: Searches documents in storage 11 | responses: 12 | '200': 13 | description: Status 200 Response 14 | content: 15 | application/json: 16 | schema: 17 | $ref: '#/components/schemas/SearchDocumentsResponse' 18 | '422': 19 | description: Status 422 Response 20 | content: 21 | application/json: 22 | schema: 23 | $ref: '#/components/schemas/ErrorResponse' 24 | '500': 25 | description: Status 500 Response 26 | content: 27 | application/json: 28 | schema: 29 | $ref: '#/components/schemas/ErrorResponse' 30 | parameters: 31 | - name: Content-Type 32 | in: header 33 | description: Content Type Header (should always be 'application/json') 34 | required: false 35 | schema: 36 | type: string 37 | requestBody: 38 | content: 39 | application/json: 40 | schema: 41 | $ref: '#/components/schemas/SearchDocumentsRequest' 42 | '/dock/{proxy+}': 43 | head: 44 | operationId: dockCheck 45 | summary: Document Existence 46 | description: Check the existence of a document 47 | responses: 48 | '206': 49 | description: Status 206 Response 50 | content: 51 | application/json: 52 | schema: 53 | $ref: '#/components/schemas/EmptyResponse' 54 | '404': 55 | description: Status 404 Response 56 | content: 57 | application/json: 58 | schema: 59 | $ref: '#/components/schemas/EmptyResponse' 60 | '500': 61 | description: Status 500 Response 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/ErrorResponse' 66 | parameters: 67 | - name: proxy+ 68 | in: path 69 | description: >- 70 | The Path of the document you wish to check the existence of. e.g 71 | accounts/39838/users/username 72 | required: true 73 | schema: 74 | type: string 75 | pattern: '^(?!/)[-a-z0-9/]+$' 76 | - name: Content-Type 77 | in: header 78 | description: Content Type Header (should always be 'application/json') 79 | required: false 80 | schema: 81 | type: string 82 | requestBody: {} 83 | get: 84 | operationId: dockRetrieve 85 | summary: Get Document 86 | description: Gets document by path 87 | responses: 88 | '200': 89 | description: Status 200 Response 90 | content: 91 | application/json: 92 | schema: 93 | $ref: '#/components/schemas/GetDocumentResponse' 94 | '404': 95 | description: Status 404 Response 96 | content: 97 | application/json: 98 | schema: 99 | $ref: '#/components/schemas/ErrorResponse' 100 | '500': 101 | description: Status 500 Response 102 | content: 103 | application/json: 104 | schema: 105 | $ref: '#/components/schemas/ErrorResponse' 106 | parameters: 107 | - name: proxy+ 108 | in: path 109 | description: >- 110 | The Path of the document you wish to retrieve. e.g 111 | accounts/39838/users/username.json 112 | required: true 113 | schema: 114 | type: string 115 | pattern: '^(?!/)[-a-z0-9/]+$' 116 | - name: Content-Type 117 | in: header 118 | description: Content Type Header (should always be 'application/json') 119 | required: false 120 | schema: 121 | type: string 122 | requestBody: {} 123 | put: 124 | operationId: dockStore 125 | summary: Store Document 126 | description: Stores a document by path 127 | responses: 128 | '201': 129 | description: Status 201 Response 130 | content: 131 | application/json: 132 | schema: 133 | $ref: '#/components/schemas/GetDocumentResponse' 134 | '422': 135 | description: Status 422 Response 136 | content: 137 | application/json: 138 | schema: 139 | $ref: '#/components/schemas/ErrorResponse' 140 | '500': 141 | description: Status 500 Response 142 | content: 143 | application/json: 144 | schema: 145 | $ref: '#/components/schemas/ErrorResponse' 146 | parameters: 147 | - name: proxy+ 148 | in: path 149 | description: >- 150 | The Path of the document you wish to store. e.g 151 | accounts/39838/users/username 152 | required: true 153 | schema: 154 | type: string 155 | pattern: '^(?!/)[-a-z0-9/]+$' 156 | - name: Content-Type 157 | in: header 158 | description: Content Type Header (should always be 'application/json') 159 | required: false 160 | schema: 161 | type: string 162 | requestBody: 163 | content: 164 | application/json: 165 | schema: 166 | $ref: '#/components/schemas/PutDocumentRequest' 167 | patch: 168 | operationId: dockPatch 169 | summary: Patch Document 170 | description: Patches a document by path 171 | responses: 172 | '201': 173 | description: Status 201 Response 174 | content: 175 | application/json: 176 | schema: 177 | $ref: '#/components/schemas/GetDocumentResponse' 178 | '422': 179 | description: Status 422 Response 180 | content: 181 | application/json: 182 | schema: 183 | $ref: '#/components/schemas/ErrorResponse' 184 | '500': 185 | description: Status 500 Response 186 | content: 187 | application/json: 188 | schema: 189 | $ref: '#/components/schemas/ErrorResponse' 190 | parameters: 191 | - name: proxy+ 192 | in: path 193 | description: >- 194 | The Path of the document you wish to patch. e.g 195 | accounts/39838/users/username 196 | required: true 197 | schema: 198 | type: string 199 | pattern: '^(?!/)[-a-z0-9/]+$' 200 | - name: Content-Type 201 | in: header 202 | description: Content Type Header (should always be 'application/json') 203 | required: false 204 | schema: 205 | type: string 206 | requestBody: 207 | content: 208 | application/json: 209 | schema: 210 | $ref: '#/components/schemas/PatchDocumentRequest' 211 | delete: 212 | operationId: dockDestroy 213 | summary: Delete document 214 | description: Deletes a document 215 | responses: 216 | '204': 217 | description: Status 204 Response 218 | content: 219 | application/json: 220 | schema: 221 | $ref: '#/components/schemas/EmptyResponse' 222 | '404': 223 | description: Status 404 Response 224 | content: 225 | application/json: 226 | schema: 227 | $ref: '#/components/schemas/EmptyResponse' 228 | '500': 229 | description: Status 500 Response 230 | content: 231 | application/json: 232 | schema: 233 | $ref: '#/components/schemas/ErrorResponse' 234 | parameters: 235 | - name: proxy+ 236 | in: path 237 | description: >- 238 | The Path of the document you wish to check the existence of. e.g 239 | accounts/39838/users/username 240 | required: true 241 | schema: 242 | type: string 243 | pattern: '^(?!/)[-a-z0-9/]+$' 244 | - name: Content-Type 245 | in: header 246 | description: Content Type Header (should always be 'application/json') 247 | required: false 248 | schema: 249 | type: string 250 | requestBody: {} 251 | /batch-get: 252 | post: 253 | operationId: dockRetrieveMultiple 254 | summary: Get Multiple Documents 255 | description: Gets documents by array of paths 256 | responses: 257 | '200': 258 | description: Status 200 Response 259 | content: 260 | application/json: 261 | schema: 262 | $ref: '#/components/schemas/GetDocumentsResponse' 263 | '500': 264 | description: Status 500 Response 265 | content: 266 | application/json: 267 | schema: 268 | $ref: '#/components/schemas/ErrorResponse' 269 | parameters: 270 | - name: Content-Type 271 | in: header 272 | description: Content Type Header (should always be 'application/json') 273 | required: false 274 | schema: 275 | type: string 276 | requestBody: 277 | content: 278 | application/json: 279 | schema: 280 | $ref: '#/components/schemas/GetDocumentsRequest' 281 | components: 282 | schemas: 283 | ErrorResponse: 284 | title: JSON API Schema 285 | description: >- 286 | This is a schema for responses in the JSON API format. For more, see 287 | http://jsonapi.org 288 | type: object 289 | required: 290 | - errors 291 | properties: 292 | errors: 293 | type: array 294 | items: 295 | type: object 296 | properties: 297 | id: 298 | description: >- 299 | A unique identifier for this particular occurrence of the 300 | problem. 301 | type: string 302 | links: 303 | description: >- 304 | A resource object **MAY** contain references to other resource 305 | objects ("relationships"). Relationships may be to-one or 306 | to-many. Relationships can be specified by including a member 307 | in a resource's links object. 308 | type: object 309 | properties: 310 | self: 311 | description: >- 312 | A `self` member, whose value is a URL for the relationship 313 | itself (a "relationship URL"). This URL allows the client 314 | to directly manipulate the relationship. For example, it 315 | would allow a client to remove an `author` from an 316 | `article` without deleting the people resource itself. 317 | type: string 318 | format: uri 319 | related: 320 | description: >- 321 | A link **MUST** be represented as either: a string 322 | containing the link's URL or a link object. 323 | oneOf: 324 | - description: A string containing the link's URL. 325 | type: string 326 | format: uri 327 | - type: object 328 | required: 329 | - href 330 | properties: 331 | href: 332 | description: A string containing the link's URL. 333 | type: string 334 | format: uri 335 | meta: 336 | description: >- 337 | Non-standard meta-information that can not be 338 | represented as an attribute or relationship. 339 | type: object 340 | additionalProperties: true 341 | additionalProperties: true 342 | status: 343 | description: >- 344 | The HTTP status code applicable to this problem, expressed as 345 | a string value. 346 | type: string 347 | code: 348 | description: >- 349 | An application-specific error code, expressed as a string 350 | value. 351 | type: string 352 | title: 353 | description: >- 354 | A short, human-readable summary of the problem. It **SHOULD 355 | NOT** change from occurrence to occurrence of the problem, 356 | except for purposes of localization. 357 | type: string 358 | detail: 359 | description: >- 360 | A human-readable explanation specific to this occurrence of 361 | the problem. 362 | type: string 363 | source: 364 | type: object 365 | properties: 366 | pointer: 367 | description: >- 368 | A JSON Pointer [RFC6901] to the associated entity in the 369 | request document [e.g. "/data" for a primary data object, 370 | or "/data/attributes/title" for a specific attribute]. 371 | type: string 372 | parameter: 373 | description: >- 374 | A string indicating which query parameter caused the 375 | error. 376 | type: string 377 | meta: 378 | description: >- 379 | Non-standard meta-information that can not be represented as 380 | an attribute or relationship. 381 | type: object 382 | additionalProperties: true 383 | additionalProperties: false 384 | uniqueItems: true 385 | meta: 386 | description: >- 387 | Non-standard meta-information that can not be represented as an 388 | attribute or relationship. 389 | type: object 390 | additionalProperties: true 391 | links: 392 | description: >- 393 | A resource object **MAY** contain references to other resource 394 | objects ("relationships"). Relationships may be to-one or to-many. 395 | Relationships can be specified by including a member in a resource's 396 | links object. 397 | type: object 398 | properties: 399 | self: 400 | description: >- 401 | A `self` member, whose value is a URL for the relationship 402 | itself (a "relationship URL"). This URL allows the client to 403 | directly manipulate the relationship. For example, it would 404 | allow a client to remove an `author` from an `article` without 405 | deleting the people resource itself. 406 | type: string 407 | format: uri 408 | related: 409 | description: >- 410 | A link **MUST** be represented as either: a string containing 411 | the link's URL or a link object. 412 | oneOf: 413 | - description: A string containing the link's URL. 414 | type: string 415 | format: uri 416 | - type: object 417 | required: 418 | - href 419 | properties: 420 | href: 421 | description: A string containing the link's URL. 422 | type: string 423 | format: uri 424 | meta: 425 | description: >- 426 | Non-standard meta-information that can not be 427 | represented as an attribute or relationship. 428 | type: object 429 | additionalProperties: true 430 | additionalProperties: true 431 | additionalProperties: false 432 | GetDocumentResponse: 433 | properties: 434 | Attributes: 435 | type: object 436 | properties: 437 | Origin: 438 | description: String to describe the service that created this document 439 | title: The service of origin 440 | type: string 441 | Sovereignty: 442 | default: global 443 | title: The Sovereignty schema. 444 | type: string 445 | enum: 446 | - global 447 | - au 448 | - eu 449 | - asia 450 | - us 451 | Type: 452 | description: The type of document that this is 453 | title: Document Type 454 | type: string 455 | required: 456 | - Origin 457 | - Sovereignty 458 | - Type 459 | Content: {} 460 | Path: 461 | description: The path of the document stored 462 | title: Document Path 463 | type: string 464 | required: 465 | - Path 466 | - Attributes 467 | - Content 468 | type: object 469 | GetDocumentsRequest: 470 | items: 471 | description: An array of document paths to retrieve 472 | title: Array of Document Paths 473 | type: string 474 | minItems: 1 475 | type: array 476 | GetDocumentsResponse: 477 | required: 478 | - Results 479 | properties: 480 | Results: 481 | type: array 482 | items: 483 | type: object 484 | properties: 485 | Attributes: 486 | type: object 487 | properties: 488 | Origin: 489 | description: String to describe the service that created this document 490 | title: The service of origin 491 | type: string 492 | Sovereignty: 493 | default: global 494 | title: The Sovereignty schema. 495 | type: string 496 | enum: 497 | - global 498 | - au 499 | - eu 500 | - asia 501 | - us 502 | Type: 503 | description: The type of document that this is 504 | title: Document Type 505 | type: string 506 | required: 507 | - Origin 508 | - Sovereignty 509 | - Type 510 | Content: {} 511 | Path: 512 | description: The path of the document stored 513 | title: Document Path 514 | type: string 515 | required: 516 | - Path 517 | - Attributes 518 | - Content 519 | PutDocumentRequest: 520 | properties: 521 | Attributes: 522 | type: object 523 | properties: 524 | Origin: 525 | description: String to describe the service that created this document 526 | title: The service of origin 527 | type: string 528 | Sovereignty: 529 | default: global 530 | title: The Sovereignty schema. 531 | type: string 532 | enum: 533 | - global 534 | - au 535 | - eu 536 | - asia 537 | - us 538 | Type: 539 | description: The type of document that this is 540 | title: Document Type 541 | type: string 542 | required: 543 | - Origin 544 | - Sovereignty 545 | - Type 546 | Content: {} 547 | required: 548 | - Attributes 549 | - Content 550 | type: object 551 | PatchDocumentRequest: 552 | title: JSON schema for JSONPatch files 553 | type: array 554 | items: 555 | type: object 556 | required: 557 | - op 558 | - path 559 | allOf: 560 | - properties: 561 | path: 562 | description: A JSON Pointer path. 563 | type: string 564 | oneOf: 565 | - required: 566 | - value 567 | properties: 568 | op: 569 | description: The operation to perform. 570 | type: string 571 | enum: 572 | - add 573 | - replace 574 | - test 575 | value: 576 | description: 'The value to add, replace or test.' 577 | - properties: 578 | op: 579 | description: The operation to perform. 580 | type: string 581 | enum: 582 | - remove 583 | - required: 584 | - from 585 | properties: 586 | op: 587 | description: The operation to perform. 588 | type: string 589 | enum: 590 | - move 591 | - copy 592 | from: 593 | description: >- 594 | A JSON Pointer path pointing to the location to move/copy 595 | from. 596 | type: string 597 | SearchDocumentsRequest: {} 598 | SearchDocumentsResponse: {} 599 | EmptyResponse: 600 | title: Empty Schema 601 | type: object 602 | securitySchemes: {} 603 | servers: [] 604 | info: 605 | title: Storage V2 Service 606 | description: The Storage V2 service is Temando's storage platform 607 | version: 2.0.7 608 | -------------------------------------------------------------------------------- /test/project/models/ErrorResponse.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "JSON API Schema", 4 | "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org", 5 | "type": "object", 6 | "required": [ 7 | "errors" 8 | ], 9 | "properties": { 10 | "errors": { 11 | "type": "array", 12 | "items": { 13 | "$ref": "#/definitions/error" 14 | }, 15 | "uniqueItems": true 16 | }, 17 | "meta": { 18 | "$ref": "#/definitions/meta" 19 | }, 20 | "links": { 21 | "$ref": "#/definitions/links" 22 | } 23 | }, 24 | "additionalProperties": false, 25 | "definitions": { 26 | "meta": { 27 | "description": "Non-standard meta-information that can not be represented as an attribute or relationship.", 28 | "type": "object", 29 | "additionalProperties": true 30 | }, 31 | "links": { 32 | "description": "A resource object **MAY** contain references to other resource objects (\"relationships\"). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object.", 33 | "type": "object", 34 | "properties": { 35 | "self": { 36 | "description": "A `self` member, whose value is a URL for the relationship itself (a \"relationship URL\"). This URL allows the client to directly manipulate the relationship. For example, it would allow a client to remove an `author` from an `article` without deleting the people resource itself.", 37 | "type": "string", 38 | "format": "uri" 39 | }, 40 | "related": { 41 | "$ref": "#/definitions/link" 42 | } 43 | }, 44 | "additionalProperties": true 45 | }, 46 | "link": { 47 | "description": "A link **MUST** be represented as either: a string containing the link's URL or a link object.", 48 | "oneOf": [ 49 | { 50 | "description": "A string containing the link's URL.", 51 | "type": "string", 52 | "format": "uri" 53 | }, 54 | { 55 | "type": "object", 56 | "required": [ 57 | "href" 58 | ], 59 | "properties": { 60 | "href": { 61 | "description": "A string containing the link's URL.", 62 | "type": "string", 63 | "format": "uri" 64 | }, 65 | "meta": { 66 | "$ref": "#/definitions/meta" 67 | } 68 | } 69 | } 70 | ] 71 | }, 72 | "error": { 73 | "type": "object", 74 | "properties": { 75 | "id": { 76 | "description": "A unique identifier for this particular occurrence of the problem.", 77 | "type": "string" 78 | }, 79 | "links": { 80 | "$ref": "#/definitions/links" 81 | }, 82 | "status": { 83 | "description": "The HTTP status code applicable to this problem, expressed as a string value.", 84 | "type": "string" 85 | }, 86 | "code": { 87 | "description": "An application-specific error code, expressed as a string value.", 88 | "type": "string" 89 | }, 90 | "title": { 91 | "description": "A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization.", 92 | "type": "string" 93 | }, 94 | "detail": { 95 | "description": "A human-readable explanation specific to this occurrence of the problem.", 96 | "type": "string" 97 | }, 98 | "source": { 99 | "type": "object", 100 | "properties": { 101 | "pointer": { 102 | "description": "A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. \"/data\" for a primary data object, or \"/data/attributes/title\" for a specific attribute].", 103 | "type": "string" 104 | }, 105 | "parameter": { 106 | "description": "A string indicating which query parameter caused the error.", 107 | "type": "string" 108 | } 109 | } 110 | }, 111 | "meta": { 112 | "$ref": "#/definitions/meta" 113 | } 114 | }, 115 | "additionalProperties": false 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /test/project/models/PutDocumentResponse.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title" : "Empty Schema", 4 | "type" : "object" 5 | } 6 | -------------------------------------------------------------------------------- /test/project/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0-RC1 2 | components: 3 | schemas: 4 | ErrorResponse: 5 | title: JSON API Schema 6 | description: >- 7 | This is a schema for responses in the JSON API format. For more, see 8 | http://jsonapi.org 9 | type: object 10 | required: 11 | - errors 12 | properties: 13 | errors: 14 | type: array 15 | items: 16 | type: object 17 | properties: 18 | id: 19 | description: >- 20 | A unique identifier for this particular occurrence of the 21 | problem. 22 | type: string 23 | links: 24 | description: >- 25 | A resource object **MAY** contain references to other resource 26 | objects ("relationships"). Relationships may be to-one or 27 | to-many. Relationships can be specified by including a member 28 | in a resource's links object. 29 | type: object 30 | properties: 31 | self: 32 | description: >- 33 | A `self` member, whose value is a URL for the relationship 34 | itself (a "relationship URL"). This URL allows the client 35 | to directly manipulate the relationship. For example, it 36 | would allow a client to remove an `author` from an 37 | `article` without deleting the people resource itself. 38 | type: string 39 | format: uri 40 | related: 41 | description: >- 42 | A link **MUST** be represented as either: a string 43 | containing the link's URL or a link object. 44 | oneOf: 45 | - description: A string containing the link's URL. 46 | type: string 47 | format: uri 48 | - type: object 49 | required: 50 | - href 51 | properties: 52 | href: 53 | description: A string containing the link's URL. 54 | type: string 55 | format: uri 56 | meta: 57 | description: >- 58 | Non-standard meta-information that can not be 59 | represented as an attribute or relationship. 60 | type: object 61 | additionalProperties: true 62 | additionalProperties: true 63 | status: 64 | description: >- 65 | The HTTP status code applicable to this problem, expressed as 66 | a string value. 67 | type: string 68 | code: 69 | description: >- 70 | An application-specific error code, expressed as a string 71 | value. 72 | type: string 73 | title: 74 | description: >- 75 | A short, human-readable summary of the problem. It **SHOULD 76 | NOT** change from occurrence to occurrence of the problem, 77 | except for purposes of localization. 78 | type: string 79 | detail: 80 | description: >- 81 | A human-readable explanation specific to this occurrence of 82 | the problem. 83 | type: string 84 | source: 85 | type: object 86 | properties: 87 | pointer: 88 | description: >- 89 | A JSON Pointer [RFC6901] to the associated entity in the 90 | request document [e.g. "/data" for a primary data object, 91 | or "/data/attributes/title" for a specific attribute]. 92 | type: string 93 | parameter: 94 | description: >- 95 | A string indicating which query parameter caused the 96 | error. 97 | type: string 98 | meta: 99 | description: >- 100 | Non-standard meta-information that can not be represented as 101 | an attribute or relationship. 102 | type: object 103 | additionalProperties: true 104 | additionalProperties: false 105 | uniqueItems: true 106 | meta: 107 | description: >- 108 | Non-standard meta-information that can not be represented as an 109 | attribute or relationship. 110 | type: object 111 | additionalProperties: true 112 | links: 113 | description: >- 114 | A resource object **MAY** contain references to other resource 115 | objects ("relationships"). Relationships may be to-one or to-many. 116 | Relationships can be specified by including a member in a resource's 117 | links object. 118 | type: object 119 | properties: 120 | self: 121 | description: >- 122 | A `self` member, whose value is a URL for the relationship 123 | itself (a "relationship URL"). This URL allows the client to 124 | directly manipulate the relationship. For example, it would 125 | allow a client to remove an `author` from an `article` without 126 | deleting the people resource itself. 127 | type: string 128 | format: uri 129 | related: 130 | description: >- 131 | A link **MUST** be represented as either: a string containing 132 | the link's URL or a link object. 133 | oneOf: 134 | - description: A string containing the link's URL. 135 | type: string 136 | format: uri 137 | - type: object 138 | required: 139 | - href 140 | properties: 141 | href: 142 | description: A string containing the link's URL. 143 | type: string 144 | format: uri 145 | meta: 146 | description: >- 147 | Non-standard meta-information that can not be 148 | represented as an attribute or relationship. 149 | type: object 150 | additionalProperties: true 151 | additionalProperties: true 152 | additionalProperties: false 153 | PutDocumentResponse: 154 | title: Empty Schema 155 | type: object 156 | PutDocumentRequest: 157 | properties: 158 | SomeObject: 159 | type: object 160 | properties: 161 | SomeAttribute: 162 | type: string 163 | securitySchemes: {} 164 | info: 165 | title: '' 166 | description: '' 167 | version: 442d95b9-dcc5-4e6e-a354-a561b8904c08 168 | paths: 169 | /create: 170 | post: 171 | operationId: createUser 172 | summary: Create User 173 | description: Creates a user and then sends a generated password email 174 | responses: 175 | '201': 176 | description: A user object along with generated API Keys 177 | content: 178 | application/json: 179 | schema: 180 | $ref: '#/components/schemas/PutDocumentResponse' 181 | '500': 182 | description: An error message when creating a new user 183 | content: 184 | application/json: 185 | schema: 186 | $ref: '#/components/schemas/ErrorResponse' 187 | parameters: 188 | - name: username 189 | in: path 190 | description: The username for a user to create 191 | required: true 192 | schema: 193 | type: string 194 | pattern: '^[-a-z0-9_]+$' 195 | - name: membershipType 196 | in: query 197 | description: The user's Membership Type 198 | required: false 199 | allowEmptyValue: false 200 | schema: 201 | type: string 202 | enum: 203 | - premium 204 | - standard 205 | - name: SessionId 206 | in: cookie 207 | description: A Session ID variable 208 | required: false 209 | schema: 210 | type: string 211 | requestBody: 212 | content: 213 | application/json: 214 | schema: 215 | $ref: '#/components/schemas/PutDocumentRequest' 216 | description: A user information object 217 | -------------------------------------------------------------------------------- /test/project/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openapi-test-package", 3 | "devDependencies": { 4 | "serverless": "^1.16.1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/project/serverless.docs.yml: -------------------------------------------------------------------------------- 1 | endpoints: 2 | createUser: 3 | summary: Create User 4 | description: Creates a user and then sends a generated password email 5 | requestBody: 6 | description: A user information object 7 | requestModels: 8 | application/json: PutDocumentRequest 9 | pathParams: 10 | - name: username 11 | description: The username for a user to create 12 | schema: 13 | type: string 14 | pattern: "^[-a-z0-9_]+$" 15 | queryParams: 16 | - name: membershipType 17 | description: The user's Membership Type 18 | schema: 19 | type: string 20 | enum: 21 | - premium 22 | - standard 23 | cookieParams: 24 | - name: SessionId 25 | description: A Session ID variable 26 | schema: 27 | type: string 28 | methodResponses: 29 | - statusCode: 201 30 | responseBody: 31 | description: A user object along with generated API Keys 32 | responseModels: 33 | application/json: PutDocumentResponse 34 | - statusCode: 500 35 | responseBody: 36 | description: An error message when creating a new user 37 | responseModels: 38 | application/json: ErrorResponse 39 | 40 | documentation: 41 | models: 42 | - name: ErrorResponse 43 | description: This is an error 44 | contentType: application/json 45 | schema: ${file(models/ErrorResponse.json)} 46 | 47 | - name: PutDocumentResponse 48 | description: PUT Document response model (external reference example) 49 | contentType: application/json 50 | schema: ${file(models/PutDocumentResponse.json)} 51 | 52 | - name: PutDocumentRequest 53 | description: PUT Document request model (inline example) 54 | contentType: application/json 55 | schema: 56 | $schema: http://json-schema.org/draft-04/schema# 57 | properties: 58 | SomeObject: 59 | type: object 60 | properties: 61 | SomeAttribute: 62 | type: string 63 | -------------------------------------------------------------------------------- /test/project/serverless.yml: -------------------------------------------------------------------------------- 1 | service: serverless-openapi-doc-demo 2 | frameworkVersion: ">=1.1.0 < 2.0.0" 3 | provider: 4 | name: aws 5 | runtime: nodejs6.10 6 | 7 | plugins: 8 | - serverless-openapi-documentation 9 | 10 | functions: 11 | createUser: 12 | handler: handler.create 13 | events: 14 | - http: 15 | path: create 16 | method: post 17 | documentation: 18 | summary: Create User 19 | description: Creates a user and then sends a generated password email 20 | requestBody: 21 | description: A user information object 22 | requestModels: 23 | application/json: PutDocumentRequest 24 | pathParams: 25 | - name: username 26 | description: The username for a user to create 27 | schema: 28 | type: string 29 | pattern: "^[-a-z0-9_]+$" 30 | queryParams: 31 | - name: membershipType 32 | description: The user's Membership Type 33 | schema: 34 | type: string 35 | enum: 36 | - premium 37 | - standard 38 | cookieParams: 39 | - name: SessionId 40 | description: A Session ID variable 41 | schema: 42 | type: string 43 | methodResponses: 44 | - statusCode: 201 45 | responseBody: 46 | description: A user object along with generated API Keys 47 | responseModels: 48 | application/json: PutDocumentResponse 49 | - statusCode: 500 50 | responseBody: 51 | description: An error message when creating a new user 52 | responseModels: 53 | application/json: ErrorResponse 54 | 55 | custom: 56 | documentation: 57 | models: 58 | - name: ErrorResponse 59 | description: This is an error 60 | contentType: application/json 61 | schema: ${file(models/ErrorResponse.json)} 62 | 63 | - name: PutDocumentResponse 64 | description: PUT Document response model (external reference example) 65 | contentType: application/json 66 | schema: ${file(models/PutDocumentResponse.json)} 67 | 68 | - name: PutDocumentRequest 69 | description: PUT Document request model (inline example) 70 | contentType: application/json 71 | schema: 72 | $schema: http://json-schema.org/draft-04/schema# 73 | properties: 74 | SomeObject: 75 | type: object 76 | properties: 77 | SomeAttribute: 78 | type: string 79 | -------------------------------------------------------------------------------- /test/project/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/async@^2.0.31": 6 | version "2.0.40" 7 | resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.40.tgz#ac02de68e66c004a61b7cb16df8b1db3a254cca9" 8 | 9 | "@types/graphql@^0.9.0": 10 | version "0.9.3" 11 | resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.3.tgz#4a2a888e110c796eb7671bf8f9ecef229ad67749" 12 | 13 | "@types/isomorphic-fetch@0.0.34": 14 | version "0.0.34" 15 | resolved "https://registry.yarnpkg.com/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.34.tgz#3c3483e606c041378438e951464f00e4e60706d6" 16 | 17 | agent-base@2: 18 | version "2.1.1" 19 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" 20 | dependencies: 21 | extend "~3.0.0" 22 | semver "~5.0.1" 23 | 24 | ansi-escapes@^1.1.0: 25 | version "1.4.0" 26 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 27 | 28 | ansi-regex@^2.0.0: 29 | version "2.1.1" 30 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 31 | 32 | ansi-styles@^2.2.1: 33 | version "2.2.1" 34 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 35 | 36 | ansi@^0.3.0, ansi@~0.3.1: 37 | version "0.3.1" 38 | resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" 39 | 40 | apollo-client@^1.4.2: 41 | version "1.7.0" 42 | resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.7.0.tgz#3d6fdf6ead0a07d3e02d32d9191f26cbcfb6e4f6" 43 | dependencies: 44 | graphql "^0.10.0" 45 | graphql-anywhere "^3.0.1" 46 | graphql-tag "^2.0.0" 47 | redux "^3.4.0" 48 | symbol-observable "^1.0.2" 49 | whatwg-fetch "^2.0.0" 50 | optionalDependencies: 51 | "@types/async" "^2.0.31" 52 | "@types/graphql" "^0.9.0" 53 | "@types/isomorphic-fetch" "0.0.34" 54 | 55 | archiver-utils@^1.3.0: 56 | version "1.3.0" 57 | resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" 58 | dependencies: 59 | glob "^7.0.0" 60 | graceful-fs "^4.1.0" 61 | lazystream "^1.0.0" 62 | lodash "^4.8.0" 63 | normalize-path "^2.0.0" 64 | readable-stream "^2.0.0" 65 | 66 | archiver@^1.1.0: 67 | version "1.3.0" 68 | resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22" 69 | dependencies: 70 | archiver-utils "^1.3.0" 71 | async "^2.0.0" 72 | buffer-crc32 "^0.2.1" 73 | glob "^7.0.0" 74 | lodash "^4.8.0" 75 | readable-stream "^2.0.0" 76 | tar-stream "^1.5.0" 77 | walkdir "^0.0.11" 78 | zip-stream "^1.1.0" 79 | 80 | are-we-there-yet@~1.1.2: 81 | version "1.1.4" 82 | resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" 83 | dependencies: 84 | delegates "^1.0.0" 85 | readable-stream "^2.0.6" 86 | 87 | argparse@^1.0.7: 88 | version "1.0.9" 89 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" 90 | dependencies: 91 | sprintf-js "~1.0.2" 92 | 93 | array-union@^1.0.1: 94 | version "1.0.2" 95 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 96 | dependencies: 97 | array-uniq "^1.0.1" 98 | 99 | array-uniq@^1.0.1: 100 | version "1.0.3" 101 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 102 | 103 | async@^1.5.2: 104 | version "1.5.2" 105 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 106 | 107 | async@^2.0.0: 108 | version "2.5.0" 109 | resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d" 110 | dependencies: 111 | lodash "^4.14.0" 112 | 113 | asynckit@^0.4.0: 114 | version "0.4.0" 115 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 116 | 117 | aws-sdk@^2.7.13: 118 | version "2.80.0" 119 | resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.80.0.tgz#61ced747eb981609483aec53e8d654d3cc9d1435" 120 | dependencies: 121 | buffer "4.9.1" 122 | crypto-browserify "1.0.9" 123 | jmespath "0.15.0" 124 | querystring "0.2.0" 125 | sax "1.2.1" 126 | url "0.10.3" 127 | uuid "3.0.1" 128 | xml2js "0.4.17" 129 | xmlbuilder "4.2.1" 130 | 131 | balanced-match@^1.0.0: 132 | version "1.0.0" 133 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 134 | 135 | base64-js@0.0.8: 136 | version "0.0.8" 137 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" 138 | 139 | base64-js@^1.0.2: 140 | version "1.2.1" 141 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" 142 | 143 | bl@^1.0.0: 144 | version "1.2.1" 145 | resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" 146 | dependencies: 147 | readable-stream "^2.0.5" 148 | 149 | bluebird@^3.4.0: 150 | version "3.5.0" 151 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" 152 | 153 | brace-expansion@^1.1.7: 154 | version "1.1.8" 155 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 156 | dependencies: 157 | balanced-match "^1.0.0" 158 | concat-map "0.0.1" 159 | 160 | buffer-crc32@^0.2.1, buffer-crc32@~0.2.3: 161 | version "0.2.13" 162 | resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" 163 | 164 | buffer@4.9.1: 165 | version "4.9.1" 166 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" 167 | dependencies: 168 | base64-js "^1.0.2" 169 | ieee754 "^1.1.4" 170 | isarray "^1.0.0" 171 | 172 | buffer@^3.0.1: 173 | version "3.6.0" 174 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" 175 | dependencies: 176 | base64-js "0.0.8" 177 | ieee754 "^1.1.4" 178 | isarray "^1.0.0" 179 | 180 | capture-stack-trace@^1.0.0: 181 | version "1.0.0" 182 | resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" 183 | 184 | caw@^2.0.0: 185 | version "2.0.0" 186 | resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.0.tgz#11f8bddc2f801469952d5e3225ba98495a2fa0ff" 187 | dependencies: 188 | get-proxy "^1.0.1" 189 | tunnel-agent "^0.4.0" 190 | 191 | chalk@^1.0.0, chalk@^1.1.1: 192 | version "1.1.3" 193 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 194 | dependencies: 195 | ansi-styles "^2.2.1" 196 | escape-string-regexp "^1.0.2" 197 | has-ansi "^2.0.0" 198 | strip-ansi "^3.0.0" 199 | supports-color "^2.0.0" 200 | 201 | ci-info@^1.0.0: 202 | version "1.0.0" 203 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534" 204 | 205 | cli-cursor@^1.0.1: 206 | version "1.0.2" 207 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 208 | dependencies: 209 | restore-cursor "^1.0.1" 210 | 211 | cli-width@^2.0.0: 212 | version "2.1.0" 213 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" 214 | 215 | code-point-at@^1.0.0: 216 | version "1.1.0" 217 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 218 | 219 | combined-stream@^1.0.5: 220 | version "1.0.5" 221 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" 222 | dependencies: 223 | delayed-stream "~1.0.0" 224 | 225 | commander@^2.9.0: 226 | version "2.11.0" 227 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 228 | 229 | commander@~2.8.1: 230 | version "2.8.1" 231 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" 232 | dependencies: 233 | graceful-readlink ">= 1.0.0" 234 | 235 | component-emitter@^1.2.0: 236 | version "1.2.1" 237 | resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" 238 | 239 | compress-commons@^1.2.0: 240 | version "1.2.0" 241 | resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.0.tgz#58587092ef20d37cb58baf000112c9278ff73b9f" 242 | dependencies: 243 | buffer-crc32 "^0.2.1" 244 | crc32-stream "^2.0.0" 245 | normalize-path "^2.0.0" 246 | readable-stream "^2.0.0" 247 | 248 | concat-map@0.0.1: 249 | version "0.0.1" 250 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 251 | 252 | concat-stream@^1.4.7: 253 | version "1.6.0" 254 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" 255 | dependencies: 256 | inherits "^2.0.3" 257 | readable-stream "^2.2.2" 258 | typedarray "^0.0.6" 259 | 260 | cookie@0.3.1: 261 | version "0.3.1" 262 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" 263 | 264 | cookiejar@^2.0.6: 265 | version "2.1.1" 266 | resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a" 267 | 268 | core-util-is@~1.0.0: 269 | version "1.0.2" 270 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 271 | 272 | crc32-stream@^2.0.0: 273 | version "2.0.0" 274 | resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4" 275 | dependencies: 276 | crc "^3.4.4" 277 | readable-stream "^2.0.0" 278 | 279 | crc@^3.4.4: 280 | version "3.4.4" 281 | resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" 282 | 283 | create-error-class@^3.0.0: 284 | version "3.0.2" 285 | resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" 286 | dependencies: 287 | capture-stack-trace "^1.0.0" 288 | 289 | crypto-browserify@1.0.9: 290 | version "1.0.9" 291 | resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-1.0.9.tgz#cc5449685dfb85eb11c9828acc7cb87ab5bbfcc0" 292 | 293 | debug@2, debug@^2.2.0: 294 | version "2.6.8" 295 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" 296 | dependencies: 297 | ms "2.0.0" 298 | 299 | decompress-tar@^4.0.0, decompress-tar@^4.1.0: 300 | version "4.1.0" 301 | resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.0.tgz#1f092ab698440558c72fc78e77d246d3ecb453b0" 302 | dependencies: 303 | file-type "^3.8.0" 304 | is-stream "^1.1.0" 305 | tar-stream "^1.5.2" 306 | 307 | decompress-tarbz2@^4.0.0: 308 | version "4.1.0" 309 | resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.0.tgz#fbab58d5de73f3fd213cac3af1c18334f51cb891" 310 | dependencies: 311 | decompress-tar "^4.1.0" 312 | file-type "^3.8.0" 313 | is-stream "^1.1.0" 314 | pify "^2.3.0" 315 | seek-bzip "^1.0.5" 316 | unbzip2-stream "^1.0.9" 317 | 318 | decompress-targz@^4.0.0: 319 | version "4.1.0" 320 | resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.0.tgz#475b9c406be621ae836274802d9b25f9913ead59" 321 | dependencies: 322 | decompress-tar "^4.0.0" 323 | file-type "^4.3.0" 324 | is-stream "^1.1.0" 325 | 326 | decompress-unzip@^4.0.1: 327 | version "4.0.1" 328 | resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" 329 | dependencies: 330 | file-type "^3.8.0" 331 | get-stream "^2.2.0" 332 | pify "^2.3.0" 333 | yauzl "^2.4.2" 334 | 335 | decompress@^4.0.0: 336 | version "4.2.0" 337 | resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" 338 | dependencies: 339 | decompress-tar "^4.0.0" 340 | decompress-tarbz2 "^4.0.0" 341 | decompress-targz "^4.0.0" 342 | decompress-unzip "^4.0.1" 343 | graceful-fs "^4.1.10" 344 | make-dir "^1.0.0" 345 | pify "^2.3.0" 346 | strip-dirs "^2.0.0" 347 | 348 | deep-extend@~0.4.0: 349 | version "0.4.2" 350 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" 351 | 352 | delayed-stream@~1.0.0: 353 | version "1.0.0" 354 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 355 | 356 | delegates@^1.0.0: 357 | version "1.0.0" 358 | resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" 359 | 360 | download@^5.0.2: 361 | version "5.0.3" 362 | resolved "https://registry.yarnpkg.com/download/-/download-5.0.3.tgz#63537f977f99266a30eb8a2a2fbd1f20b8000f7a" 363 | dependencies: 364 | caw "^2.0.0" 365 | decompress "^4.0.0" 366 | filenamify "^2.0.0" 367 | get-stream "^3.0.0" 368 | got "^6.3.0" 369 | mkdirp "^0.5.1" 370 | pify "^2.3.0" 371 | 372 | duplexer3@^0.1.4: 373 | version "0.1.4" 374 | resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" 375 | 376 | encoding@^0.1.11: 377 | version "0.1.12" 378 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 379 | dependencies: 380 | iconv-lite "~0.4.13" 381 | 382 | end-of-stream@^1.0.0: 383 | version "1.4.0" 384 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" 385 | dependencies: 386 | once "^1.4.0" 387 | 388 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 389 | version "1.0.5" 390 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 391 | 392 | esprima@^3.1.1: 393 | version "3.1.3" 394 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" 395 | 396 | exit-hook@^1.0.0: 397 | version "1.1.1" 398 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 399 | 400 | extend@3, extend@^3.0.0, extend@~3.0.0: 401 | version "3.0.1" 402 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" 403 | 404 | external-editor@^1.1.0: 405 | version "1.1.1" 406 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-1.1.1.tgz#12d7b0db850f7ff7e7081baf4005700060c4600b" 407 | dependencies: 408 | extend "^3.0.0" 409 | spawn-sync "^1.0.15" 410 | tmp "^0.0.29" 411 | 412 | fd-slicer@~1.0.1: 413 | version "1.0.1" 414 | resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" 415 | dependencies: 416 | pend "~1.2.0" 417 | 418 | figures@^1.3.5: 419 | version "1.7.0" 420 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 421 | dependencies: 422 | escape-string-regexp "^1.0.5" 423 | object-assign "^4.1.0" 424 | 425 | file-type@^3.8.0: 426 | version "3.9.0" 427 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" 428 | 429 | file-type@^4.3.0: 430 | version "4.4.0" 431 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" 432 | 433 | filename-reserved-regex@^2.0.0: 434 | version "2.0.0" 435 | resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" 436 | 437 | filenamify@^2.0.0: 438 | version "2.0.0" 439 | resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.0.0.tgz#bd162262c0b6e94bfbcdcf19a3bbb3764f785695" 440 | dependencies: 441 | filename-reserved-regex "^2.0.0" 442 | strip-outer "^1.0.0" 443 | trim-repeated "^1.0.0" 444 | 445 | filesize@^3.3.0: 446 | version "3.5.10" 447 | resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.10.tgz#fc8fa23ddb4ef9e5e0ab6e1e64f679a24a56761f" 448 | 449 | form-data@^2.1.1: 450 | version "2.2.0" 451 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.2.0.tgz#9a5e3b9295f980b2623cf64fa238b14cebca707b" 452 | dependencies: 453 | asynckit "^0.4.0" 454 | combined-stream "^1.0.5" 455 | mime-types "^2.1.12" 456 | 457 | formidable@^1.1.1: 458 | version "1.1.1" 459 | resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9" 460 | 461 | fs-extra@^0.26.7: 462 | version "0.26.7" 463 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.26.7.tgz#9ae1fdd94897798edab76d0918cf42d0c3184fa9" 464 | dependencies: 465 | graceful-fs "^4.1.2" 466 | jsonfile "^2.1.0" 467 | klaw "^1.0.0" 468 | path-is-absolute "^1.0.0" 469 | rimraf "^2.2.8" 470 | 471 | fs.realpath@^1.0.0: 472 | version "1.0.0" 473 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 474 | 475 | gauge@~1.2.5: 476 | version "1.2.7" 477 | resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" 478 | dependencies: 479 | ansi "^0.3.0" 480 | has-unicode "^2.0.0" 481 | lodash.pad "^4.1.0" 482 | lodash.padend "^4.1.0" 483 | lodash.padstart "^4.1.0" 484 | 485 | get-proxy@^1.0.1: 486 | version "1.1.0" 487 | resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-1.1.0.tgz#894854491bc591b0f147d7ae570f5c678b7256eb" 488 | dependencies: 489 | rc "^1.1.2" 490 | 491 | get-stdin@^5.0.1: 492 | version "5.0.1" 493 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" 494 | 495 | get-stream@^2.2.0: 496 | version "2.3.1" 497 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" 498 | dependencies: 499 | object-assign "^4.0.1" 500 | pinkie-promise "^2.0.0" 501 | 502 | get-stream@^3.0.0: 503 | version "3.0.0" 504 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 505 | 506 | glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: 507 | version "7.1.2" 508 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 509 | dependencies: 510 | fs.realpath "^1.0.0" 511 | inflight "^1.0.4" 512 | inherits "2" 513 | minimatch "^3.0.4" 514 | once "^1.3.0" 515 | path-is-absolute "^1.0.0" 516 | 517 | globby@^6.1.0: 518 | version "6.1.0" 519 | resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" 520 | dependencies: 521 | array-union "^1.0.1" 522 | glob "^7.0.3" 523 | object-assign "^4.0.1" 524 | pify "^2.0.0" 525 | pinkie-promise "^2.0.0" 526 | 527 | got@^6.3.0: 528 | version "6.7.1" 529 | resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" 530 | dependencies: 531 | create-error-class "^3.0.0" 532 | duplexer3 "^0.1.4" 533 | get-stream "^3.0.0" 534 | is-redirect "^1.0.0" 535 | is-retry-allowed "^1.0.0" 536 | is-stream "^1.0.0" 537 | lowercase-keys "^1.0.0" 538 | safe-buffer "^5.0.1" 539 | timed-out "^4.0.0" 540 | unzip-response "^2.0.1" 541 | url-parse-lax "^1.0.0" 542 | 543 | graceful-fs@^4.1.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: 544 | version "4.1.11" 545 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 546 | 547 | "graceful-readlink@>= 1.0.0": 548 | version "1.0.1" 549 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 550 | 551 | graphlib@^2.1.1: 552 | version "2.1.1" 553 | resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.1.tgz#42352c52ba2f4d035cb566eb91f7395f76ebc951" 554 | dependencies: 555 | lodash "^4.11.1" 556 | 557 | graphql-anywhere@^3.0.1: 558 | version "3.1.0" 559 | resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96" 560 | 561 | graphql-tag@^2.0.0, graphql-tag@^2.4.0: 562 | version "2.4.2" 563 | resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.4.2.tgz#6a63297d8522d03a2b72d26f1b239aab343840cd" 564 | 565 | graphql@^0.10.0, graphql@^0.10.1: 566 | version "0.10.3" 567 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.3.tgz#c313afd5518e673351bee18fb63e2a0e487407ab" 568 | dependencies: 569 | iterall "^1.1.0" 570 | 571 | has-ansi@^2.0.0: 572 | version "2.0.0" 573 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 574 | dependencies: 575 | ansi-regex "^2.0.0" 576 | 577 | has-unicode@^2.0.0: 578 | version "2.0.1" 579 | resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" 580 | 581 | https-proxy-agent@^1.0.0: 582 | version "1.0.0" 583 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" 584 | dependencies: 585 | agent-base "2" 586 | debug "2" 587 | extend "3" 588 | 589 | iconv-lite@~0.4.13: 590 | version "0.4.18" 591 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" 592 | 593 | ieee754@^1.1.4: 594 | version "1.1.8" 595 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" 596 | 597 | imurmurhash@^0.1.4: 598 | version "0.1.4" 599 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 600 | 601 | inflight@^1.0.4: 602 | version "1.0.6" 603 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 604 | dependencies: 605 | once "^1.3.0" 606 | wrappy "1" 607 | 608 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 609 | version "2.0.3" 610 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 611 | 612 | ini@~1.3.0: 613 | version "1.3.4" 614 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" 615 | 616 | inquirer@^1.0.2: 617 | version "1.2.3" 618 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-1.2.3.tgz#4dec6f32f37ef7bb0b2ed3f1d1a5c3f545074918" 619 | dependencies: 620 | ansi-escapes "^1.1.0" 621 | chalk "^1.0.0" 622 | cli-cursor "^1.0.1" 623 | cli-width "^2.0.0" 624 | external-editor "^1.1.0" 625 | figures "^1.3.5" 626 | lodash "^4.3.0" 627 | mute-stream "0.0.6" 628 | pinkie-promise "^2.0.0" 629 | run-async "^2.2.0" 630 | rx "^4.1.0" 631 | string-width "^1.0.1" 632 | strip-ansi "^3.0.0" 633 | through "^2.3.6" 634 | 635 | is-fullwidth-code-point@^1.0.0: 636 | version "1.0.0" 637 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 638 | dependencies: 639 | number-is-nan "^1.0.0" 640 | 641 | is-natural-number@^4.0.1: 642 | version "4.0.1" 643 | resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" 644 | 645 | is-promise@^2.1.0: 646 | version "2.1.0" 647 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 648 | 649 | is-redirect@^1.0.0: 650 | version "1.0.0" 651 | resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" 652 | 653 | is-retry-allowed@^1.0.0: 654 | version "1.1.0" 655 | resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" 656 | 657 | is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: 658 | version "1.1.0" 659 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 660 | 661 | is-wsl@^1.1.0: 662 | version "1.1.0" 663 | resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" 664 | 665 | isarray@^1.0.0, isarray@~1.0.0: 666 | version "1.0.0" 667 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 668 | 669 | iterall@^1.1.0: 670 | version "1.1.1" 671 | resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.1.tgz#f7f0af11e9a04ec6426260f5019d9fcca4d50214" 672 | 673 | jmespath@0.15.0: 674 | version "0.15.0" 675 | resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" 676 | 677 | js-tokens@^3.0.0: 678 | version "3.0.2" 679 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 680 | 681 | js-yaml@^3.6.1, js-yaml@^3.8.3: 682 | version "3.8.4" 683 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" 684 | dependencies: 685 | argparse "^1.0.7" 686 | esprima "^3.1.1" 687 | 688 | json-refs@^2.1.5: 689 | version "2.1.7" 690 | resolved "https://registry.yarnpkg.com/json-refs/-/json-refs-2.1.7.tgz#b9eb01fe29f5ea3e92878f15aea10ad38b5acf89" 691 | dependencies: 692 | commander "^2.9.0" 693 | graphlib "^2.1.1" 694 | js-yaml "^3.8.3" 695 | native-promise-only "^0.8.1" 696 | path-loader "^1.0.2" 697 | slash "^1.0.0" 698 | uri-js "^3.0.2" 699 | 700 | json-stringify-safe@5.0.1: 701 | version "5.0.1" 702 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 703 | 704 | jsonfile@^2.1.0: 705 | version "2.4.0" 706 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" 707 | optionalDependencies: 708 | graceful-fs "^4.1.6" 709 | 710 | jwt-decode@^2.2.0: 711 | version "2.2.0" 712 | resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79" 713 | 714 | klaw@^1.0.0: 715 | version "1.3.1" 716 | resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" 717 | optionalDependencies: 718 | graceful-fs "^4.1.9" 719 | 720 | lazystream@^1.0.0: 721 | version "1.0.0" 722 | resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" 723 | dependencies: 724 | readable-stream "^2.0.5" 725 | 726 | lodash-es@^4.2.1: 727 | version "4.17.4" 728 | resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" 729 | 730 | lodash.difference@^4.5.0: 731 | version "4.5.0" 732 | resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" 733 | 734 | lodash.pad@^4.1.0: 735 | version "4.5.1" 736 | resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" 737 | 738 | lodash.padend@^4.1.0: 739 | version "4.6.1" 740 | resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" 741 | 742 | lodash.padstart@^4.1.0: 743 | version "4.6.1" 744 | resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" 745 | 746 | lodash.uniq@^4.5.0: 747 | version "4.5.0" 748 | resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" 749 | 750 | lodash@^4.0.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0: 751 | version "4.17.4" 752 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 753 | 754 | loose-envify@^1.1.0: 755 | version "1.3.1" 756 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" 757 | dependencies: 758 | js-tokens "^3.0.0" 759 | 760 | lowercase-keys@^1.0.0: 761 | version "1.0.0" 762 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" 763 | 764 | lsmod@1.0.0: 765 | version "1.0.0" 766 | resolved "https://registry.yarnpkg.com/lsmod/-/lsmod-1.0.0.tgz#9a00f76dca36eb23fa05350afe1b585d4299e64b" 767 | 768 | make-dir@^1.0.0: 769 | version "1.0.0" 770 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" 771 | dependencies: 772 | pify "^2.3.0" 773 | 774 | methods@^1.1.1: 775 | version "1.1.2" 776 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 777 | 778 | mime-db@~1.27.0: 779 | version "1.27.0" 780 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" 781 | 782 | mime-types@^2.1.12: 783 | version "2.1.15" 784 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" 785 | dependencies: 786 | mime-db "~1.27.0" 787 | 788 | mime@^1.3.4: 789 | version "1.3.6" 790 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" 791 | 792 | minimatch@^3.0.4: 793 | version "3.0.4" 794 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 795 | dependencies: 796 | brace-expansion "^1.1.7" 797 | 798 | minimist@0.0.8: 799 | version "0.0.8" 800 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 801 | 802 | minimist@^1.2.0: 803 | version "1.2.0" 804 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 805 | 806 | mkdirp@^0.5.1: 807 | version "0.5.1" 808 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 809 | dependencies: 810 | minimist "0.0.8" 811 | 812 | moment@^2.13.0: 813 | version "2.18.1" 814 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" 815 | 816 | ms@2.0.0: 817 | version "2.0.0" 818 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 819 | 820 | mute-stream@0.0.6: 821 | version "0.0.6" 822 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" 823 | 824 | native-promise-only@^0.8.1: 825 | version "0.8.1" 826 | resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" 827 | 828 | node-fetch@^1.6.0: 829 | version "1.7.1" 830 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.1.tgz#899cb3d0a3c92f952c47f1b876f4c8aeabd400d5" 831 | dependencies: 832 | encoding "^0.1.11" 833 | is-stream "^1.0.1" 834 | 835 | normalize-path@^2.0.0: 836 | version "2.1.1" 837 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" 838 | dependencies: 839 | remove-trailing-separator "^1.0.1" 840 | 841 | npmlog@^2.0.3: 842 | version "2.0.4" 843 | resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" 844 | dependencies: 845 | ansi "~0.3.1" 846 | are-we-there-yet "~1.1.2" 847 | gauge "~1.2.5" 848 | 849 | number-is-nan@^1.0.0: 850 | version "1.0.1" 851 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 852 | 853 | object-assign@^4.0.1, object-assign@^4.1.0: 854 | version "4.1.1" 855 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 856 | 857 | once@^1.3.0, once@^1.4.0: 858 | version "1.4.0" 859 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 860 | dependencies: 861 | wrappy "1" 862 | 863 | onetime@^1.0.0: 864 | version "1.1.0" 865 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 866 | 867 | opn@^5.0.0: 868 | version "5.1.0" 869 | resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" 870 | dependencies: 871 | is-wsl "^1.1.0" 872 | 873 | os-shim@^0.1.2: 874 | version "0.1.3" 875 | resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" 876 | 877 | os-tmpdir@~1.0.1: 878 | version "1.0.2" 879 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 880 | 881 | path-is-absolute@^1.0.0: 882 | version "1.0.1" 883 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 884 | 885 | path-loader@^1.0.2: 886 | version "1.0.2" 887 | resolved "https://registry.yarnpkg.com/path-loader/-/path-loader-1.0.2.tgz#cd5c73e7e39a91011be148d6bfdd8a85bb931ef9" 888 | dependencies: 889 | native-promise-only "^0.8.1" 890 | superagent "^3.5.2" 891 | 892 | pend@~1.2.0: 893 | version "1.2.0" 894 | resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" 895 | 896 | pify@^2.0.0, pify@^2.3.0: 897 | version "2.3.0" 898 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 899 | 900 | pinkie-promise@^2.0.0: 901 | version "2.0.1" 902 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 903 | dependencies: 904 | pinkie "^2.0.0" 905 | 906 | pinkie@^2.0.0: 907 | version "2.0.4" 908 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 909 | 910 | prepend-http@^1.0.1: 911 | version "1.0.4" 912 | resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" 913 | 914 | process-nextick-args@~1.0.6: 915 | version "1.0.7" 916 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 917 | 918 | punycode@1.3.2: 919 | version "1.3.2" 920 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" 921 | 922 | punycode@^2.1.0: 923 | version "2.1.0" 924 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" 925 | 926 | qs@^6.1.0: 927 | version "6.5.0" 928 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" 929 | 930 | querystring@0.2.0: 931 | version "0.2.0" 932 | resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" 933 | 934 | raven@^1.2.1: 935 | version "1.2.1" 936 | resolved "https://registry.yarnpkg.com/raven/-/raven-1.2.1.tgz#949c134db028a190b7bbf8f790aae541b7c020bd" 937 | dependencies: 938 | cookie "0.3.1" 939 | json-stringify-safe "5.0.1" 940 | lsmod "1.0.0" 941 | stack-trace "0.0.9" 942 | uuid "3.0.0" 943 | 944 | rc@^1.1.2, rc@^1.1.6: 945 | version "1.2.1" 946 | resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" 947 | dependencies: 948 | deep-extend "~0.4.0" 949 | ini "~1.3.0" 950 | minimist "^1.2.0" 951 | strip-json-comments "~2.0.1" 952 | 953 | readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2: 954 | version "2.3.3" 955 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" 956 | dependencies: 957 | core-util-is "~1.0.0" 958 | inherits "~2.0.3" 959 | isarray "~1.0.0" 960 | process-nextick-args "~1.0.6" 961 | safe-buffer "~5.1.1" 962 | string_decoder "~1.0.3" 963 | util-deprecate "~1.0.1" 964 | 965 | redux@^3.4.0: 966 | version "3.7.1" 967 | resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.1.tgz#bfc535c757d3849562ead0af18ac52122cd7268e" 968 | dependencies: 969 | lodash "^4.2.1" 970 | lodash-es "^4.2.1" 971 | loose-envify "^1.1.0" 972 | symbol-observable "^1.0.3" 973 | 974 | remove-trailing-separator@^1.0.1: 975 | version "1.0.2" 976 | resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" 977 | 978 | replaceall@^0.1.6: 979 | version "0.1.6" 980 | resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" 981 | 982 | restore-cursor@^1.0.1: 983 | version "1.0.1" 984 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 985 | dependencies: 986 | exit-hook "^1.0.0" 987 | onetime "^1.0.0" 988 | 989 | rimraf@^2.2.8: 990 | version "2.6.1" 991 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" 992 | dependencies: 993 | glob "^7.0.5" 994 | 995 | run-async@^2.2.0: 996 | version "2.3.0" 997 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 998 | dependencies: 999 | is-promise "^2.1.0" 1000 | 1001 | rx@^4.1.0: 1002 | version "4.1.0" 1003 | resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" 1004 | 1005 | safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1006 | version "5.1.1" 1007 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 1008 | 1009 | sax@1.2.1, sax@>=0.6.0: 1010 | version "1.2.1" 1011 | resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" 1012 | 1013 | seek-bzip@^1.0.5: 1014 | version "1.0.5" 1015 | resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" 1016 | dependencies: 1017 | commander "~2.8.1" 1018 | 1019 | semver-regex@^1.0.0: 1020 | version "1.0.0" 1021 | resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" 1022 | 1023 | semver@^5.0.3: 1024 | version "5.3.0" 1025 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" 1026 | 1027 | semver@~5.0.1: 1028 | version "5.0.3" 1029 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" 1030 | 1031 | serverless@^1.16.1: 1032 | version "1.16.1" 1033 | resolved "https://registry.yarnpkg.com/serverless/-/serverless-1.16.1.tgz#070d2638890c5418bea74ce6e9fcaa09ebe8dc38" 1034 | dependencies: 1035 | apollo-client "^1.4.2" 1036 | archiver "^1.1.0" 1037 | async "^1.5.2" 1038 | aws-sdk "^2.7.13" 1039 | bluebird "^3.4.0" 1040 | chalk "^1.1.1" 1041 | ci-info "^1.0.0" 1042 | download "^5.0.2" 1043 | filesize "^3.3.0" 1044 | fs-extra "^0.26.7" 1045 | get-stdin "^5.0.1" 1046 | globby "^6.1.0" 1047 | graphql "^0.10.1" 1048 | graphql-tag "^2.4.0" 1049 | https-proxy-agent "^1.0.0" 1050 | js-yaml "^3.6.1" 1051 | json-refs "^2.1.5" 1052 | jwt-decode "^2.2.0" 1053 | lodash "^4.13.1" 1054 | minimist "^1.2.0" 1055 | moment "^2.13.0" 1056 | node-fetch "^1.6.0" 1057 | opn "^5.0.0" 1058 | raven "^1.2.1" 1059 | rc "^1.1.6" 1060 | replaceall "^0.1.6" 1061 | semver "^5.0.3" 1062 | semver-regex "^1.0.0" 1063 | shelljs "^0.6.0" 1064 | tabtab "^2.2.2" 1065 | uuid "^2.0.2" 1066 | write-file-atomic "^2.1.0" 1067 | 1068 | shelljs@^0.6.0: 1069 | version "0.6.1" 1070 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" 1071 | 1072 | slash@^1.0.0: 1073 | version "1.0.0" 1074 | resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" 1075 | 1076 | slide@^1.1.5: 1077 | version "1.1.6" 1078 | resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" 1079 | 1080 | spawn-sync@^1.0.15: 1081 | version "1.0.15" 1082 | resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" 1083 | dependencies: 1084 | concat-stream "^1.4.7" 1085 | os-shim "^0.1.2" 1086 | 1087 | sprintf-js@~1.0.2: 1088 | version "1.0.3" 1089 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1090 | 1091 | stack-trace@0.0.9: 1092 | version "0.0.9" 1093 | resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" 1094 | 1095 | string-width@^1.0.1: 1096 | version "1.0.2" 1097 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1098 | dependencies: 1099 | code-point-at "^1.0.0" 1100 | is-fullwidth-code-point "^1.0.0" 1101 | strip-ansi "^3.0.0" 1102 | 1103 | string_decoder@~1.0.3: 1104 | version "1.0.3" 1105 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 1106 | dependencies: 1107 | safe-buffer "~5.1.0" 1108 | 1109 | strip-ansi@^3.0.0: 1110 | version "3.0.1" 1111 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1112 | dependencies: 1113 | ansi-regex "^2.0.0" 1114 | 1115 | strip-dirs@^2.0.0: 1116 | version "2.0.0" 1117 | resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.0.0.tgz#610cdb2928200da0004f41dcb90fc95cd919a0b6" 1118 | dependencies: 1119 | is-natural-number "^4.0.1" 1120 | 1121 | strip-json-comments@~2.0.1: 1122 | version "2.0.1" 1123 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1124 | 1125 | strip-outer@^1.0.0: 1126 | version "1.0.0" 1127 | resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.0.tgz#aac0ba60d2e90c5d4f275fd8869fd9a2d310ffb8" 1128 | dependencies: 1129 | escape-string-regexp "^1.0.2" 1130 | 1131 | superagent@^3.5.2: 1132 | version "3.5.2" 1133 | resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.5.2.tgz#3361a3971567504c351063abeaae0faa23dbf3f8" 1134 | dependencies: 1135 | component-emitter "^1.2.0" 1136 | cookiejar "^2.0.6" 1137 | debug "^2.2.0" 1138 | extend "^3.0.0" 1139 | form-data "^2.1.1" 1140 | formidable "^1.1.1" 1141 | methods "^1.1.1" 1142 | mime "^1.3.4" 1143 | qs "^6.1.0" 1144 | readable-stream "^2.0.5" 1145 | 1146 | supports-color@^2.0.0: 1147 | version "2.0.0" 1148 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1149 | 1150 | symbol-observable@^1.0.2, symbol-observable@^1.0.3: 1151 | version "1.0.4" 1152 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" 1153 | 1154 | tabtab@^2.2.2: 1155 | version "2.2.2" 1156 | resolved "https://registry.yarnpkg.com/tabtab/-/tabtab-2.2.2.tgz#7a047f143b010b4cbd31f857e82961512cbf4e14" 1157 | dependencies: 1158 | debug "^2.2.0" 1159 | inquirer "^1.0.2" 1160 | lodash.difference "^4.5.0" 1161 | lodash.uniq "^4.5.0" 1162 | minimist "^1.2.0" 1163 | mkdirp "^0.5.1" 1164 | npmlog "^2.0.3" 1165 | object-assign "^4.1.0" 1166 | 1167 | tar-stream@^1.5.0, tar-stream@^1.5.2: 1168 | version "1.5.4" 1169 | resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016" 1170 | dependencies: 1171 | bl "^1.0.0" 1172 | end-of-stream "^1.0.0" 1173 | readable-stream "^2.0.0" 1174 | xtend "^4.0.0" 1175 | 1176 | through@^2.3.6: 1177 | version "2.3.8" 1178 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1179 | 1180 | timed-out@^4.0.0: 1181 | version "4.0.1" 1182 | resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" 1183 | 1184 | tmp@^0.0.29: 1185 | version "0.0.29" 1186 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" 1187 | dependencies: 1188 | os-tmpdir "~1.0.1" 1189 | 1190 | trim-repeated@^1.0.0: 1191 | version "1.0.0" 1192 | resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" 1193 | dependencies: 1194 | escape-string-regexp "^1.0.2" 1195 | 1196 | tunnel-agent@^0.4.0: 1197 | version "0.4.3" 1198 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" 1199 | 1200 | typedarray@^0.0.6: 1201 | version "0.0.6" 1202 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1203 | 1204 | unbzip2-stream@^1.0.9: 1205 | version "1.2.4" 1206 | resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.4.tgz#8c84c84d5b4cc28fc1f9f577203bbd3cb860a16a" 1207 | dependencies: 1208 | buffer "^3.0.1" 1209 | through "^2.3.6" 1210 | 1211 | unzip-response@^2.0.1: 1212 | version "2.0.1" 1213 | resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" 1214 | 1215 | uri-js@^3.0.2: 1216 | version "3.0.2" 1217 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-3.0.2.tgz#f90b858507f81dea4dcfbb3c4c3dbfa2b557faaa" 1218 | dependencies: 1219 | punycode "^2.1.0" 1220 | 1221 | url-parse-lax@^1.0.0: 1222 | version "1.0.0" 1223 | resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" 1224 | dependencies: 1225 | prepend-http "^1.0.1" 1226 | 1227 | url@0.10.3: 1228 | version "0.10.3" 1229 | resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" 1230 | dependencies: 1231 | punycode "1.3.2" 1232 | querystring "0.2.0" 1233 | 1234 | util-deprecate@~1.0.1: 1235 | version "1.0.2" 1236 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1237 | 1238 | uuid@3.0.0: 1239 | version "3.0.0" 1240 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728" 1241 | 1242 | uuid@3.0.1: 1243 | version "3.0.1" 1244 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" 1245 | 1246 | uuid@^2.0.2: 1247 | version "2.0.3" 1248 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" 1249 | 1250 | walkdir@^0.0.11: 1251 | version "0.0.11" 1252 | resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532" 1253 | 1254 | whatwg-fetch@^2.0.0: 1255 | version "2.0.3" 1256 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" 1257 | 1258 | wrappy@1: 1259 | version "1.0.2" 1260 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1261 | 1262 | write-file-atomic@^2.1.0: 1263 | version "2.1.0" 1264 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.1.0.tgz#1769f4b551eedce419f0505deae2e26763542d37" 1265 | dependencies: 1266 | graceful-fs "^4.1.11" 1267 | imurmurhash "^0.1.4" 1268 | slide "^1.1.5" 1269 | 1270 | xml2js@0.4.17: 1271 | version "0.4.17" 1272 | resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" 1273 | dependencies: 1274 | sax ">=0.6.0" 1275 | xmlbuilder "^4.1.0" 1276 | 1277 | xmlbuilder@4.2.1, xmlbuilder@^4.1.0: 1278 | version "4.2.1" 1279 | resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5" 1280 | dependencies: 1281 | lodash "^4.0.0" 1282 | 1283 | xtend@^4.0.0: 1284 | version "4.0.1" 1285 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 1286 | 1287 | yauzl@^2.4.2: 1288 | version "2.8.0" 1289 | resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.8.0.tgz#79450aff22b2a9c5a41ef54e02db907ccfbf9ee2" 1290 | dependencies: 1291 | buffer-crc32 "~0.2.3" 1292 | fd-slicer "~1.0.1" 1293 | 1294 | zip-stream@^1.1.0: 1295 | version "1.2.0" 1296 | resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" 1297 | dependencies: 1298 | archiver-utils "^1.3.0" 1299 | compress-commons "^1.2.0" 1300 | lodash "^4.8.0" 1301 | readable-stream "^2.0.0" 1302 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "outDir": "./build", 7 | "sourceMap": true, 8 | "declaration": true, 9 | "noUnusedLocals": true, 10 | "downlevelIteration": true, 11 | "lib": [ 12 | "es6", 13 | "es7", 14 | "dom", 15 | "esnext.asynciterable" 16 | ] 17 | }, 18 | "include": [ "src/**/*" ], 19 | "exclude": [ "node_modules" ] 20 | } 21 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends":[ 3 | "tslint-config-temando" 4 | ] 5 | } 6 | --------------------------------------------------------------------------------