Skip to content
This repository has been archived by the owner on Oct 10, 2022. It is now read-only.

Commit

Permalink
Improve OpenAPI logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Sep 11, 2019
1 parent 3d40ef4 commit 713caff
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 78 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const client = new NetlifyAPI('1234myAccessToken')
const sites = await client.listSites()
```

## Using Open API methods
## Using Open API operations

```js
const NetlifyAPI = require('netlify')
Expand Down Expand Up @@ -67,9 +67,9 @@ A getter that returns the formatted base URL of the endpoint the client is confi

### Open API Client methods

The client is dynamically generated from the [open-api](https://github.com/netlify/open-api) definition file. Each method is is named after the `operationId` name of each endpoint action. **To see list of available operations see the [open-api website](https://open-api.netlify.com/)**.
The client is dynamically generated from the [open-api](https://github.com/netlify/open-api) definition file. Each method is is named after the `operationId` name of each operation. **To see list of available operations see the [open-api website](https://open-api.netlify.com/)**.

Every open-api method has the following signature:
Every open-api operation has the following signature:

#### `promise(response) = client.operationId([params], [opts])`

Expand Down Expand Up @@ -103,7 +103,7 @@ Optional `opts` can include any property you want passed to `node-fetch`. The `h
}
```

All methods are conveniently consumed with async/await:
All operations are conveniently consumed with async/await:

```js
async function getSomeData() {
Expand All @@ -123,7 +123,7 @@ If the request response includes `json` in the `contentType` header, fetch will

### API Flow Methods

Some methods have been added in addition to the open API methods that make certain actions simpler to perform.
Some methods have been added in addition to the open API operations that make certain actions simpler to perform.

#### `promise(accessToken) = client.getAccessToken(ticket, [opts])`

Expand Down
10 changes: 6 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const set = require('lodash.set')
const get = require('lodash.get')
const dfn = require('@netlify/open-api')
const { methods, generateMethod } = require('./open-api')
const { generateOperation } = require('./open-api')
const { getOperations } = require('./operations')
const pWaitFor = require('p-wait-for')
const deploy = require('./deploy')
const debug = require('debug')('netlify')
Expand Down Expand Up @@ -109,12 +110,13 @@ class NetlifyAPI {
}
}

methods.forEach(method => {
const operations = getOperations()
operations.forEach(operation => {
// Generate open-api methods
/* {param1, param2, body, ... }, [opts] */
NetlifyAPI.prototype[method.operationId] = generateMethod(method)
NetlifyAPI.prototype[operation.operationId] = generateOperation(operation)
})

module.exports = NetlifyAPI

module.exports.methods = methods
module.exports.methods = operations
16 changes: 7 additions & 9 deletions src/open-api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,20 @@ const debug = require('debug')('netlify:open-api')
const { existy, sleep, unixNow } = require('./util')
const isStream = require('is-stream')

exports.methods = require('./shape-swagger')

// open-api 2.0
exports.generateMethod = method => {
exports.generateOperation = operation => {
//
// Warning: Expects `this`. These methods expect to live on the client prototype
//
return async function(params, opts) {
opts = Object.assign({}, opts)
params = Object.assign({}, this.globalParams, params)

let path = this.basePath + method.path
let path = this.basePath + operation.path
debug(`path template: ${path}`)

// Path parameters
Object.values(method.parameters.path).forEach(param => {
Object.values(operation.parameters.path).forEach(param => {
const val = params[param.name] || params[camelCase(param.name)]
if (existy(val)) {
path = path.replace(`{${param.name}}`, val)
Expand All @@ -37,7 +35,7 @@ exports.generateMethod = method => {

// qs parameters
let qs
Object.values(method.parameters.query).forEach(param => {
Object.values(operation.parameters.query).forEach(param => {
const val = params[param.name] || params[camelCase(param.name)]
if (existy(val)) {
if (!qs) qs = {}
Expand All @@ -56,7 +54,7 @@ exports.generateMethod = method => {
let bodyType = 'json'
if (params.body) {
body = params.body
Object.values(method.parameters.body).forEach(param => {
Object.values(operation.parameters.body).forEach(param => {
const type = get(param, 'schema.format')
if (type === 'binary') {
bodyType = 'binary'
Expand Down Expand Up @@ -84,8 +82,8 @@ exports.generateMethod = method => {
debug('specialHeaders: %O', specialHeaders)

opts.headers = new Headers(Object.assign({}, this.defaultHeaders, specialHeaders, opts.headers))
opts.method = method.verb.toUpperCase()
debug(`method: ${opts.method}`)
opts.method = operation.verb.toUpperCase()
debug(`HTTP method: ${opts.method}`)

// TODO: Consider using micro-api-client when it supports node-fetch

Expand Down
28 changes: 0 additions & 28 deletions src/open-api/shape-swagger.js

This file was deleted.

32 changes: 0 additions & 32 deletions src/open-api/util.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,3 @@
const set = require('lodash.set')

exports.sortParams = (parameters = []) => {
const paramSet = {
// minimum param set
path: {},
query: {},
body: {}
}

parameters.forEach(param => {
set(paramSet, `${param.in}.${param.name}`, param)
})

return paramSet
}

exports.mergeParams = (...params) => {
const merged = {}

params.forEach(paramSet => {
Object.entries(paramSet).forEach(([type, params]) => {
if (!merged[type]) merged[type] = {} // preserve empty objects
Object.values(params).forEach((param, index) => {
set(merged, `${param.in}.${param.name}`, Object.assign(param, { index }))
})
})
})

return merged
}

exports.existy = val => val != null

// Async sleep. A whole new WORLD!
Expand Down
29 changes: 29 additions & 0 deletions src/operations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const { paths } = require('@netlify/open-api')

// Retrieve all OpenAPI operations
const getOperations = function() {
return [].concat(
...Object.entries(paths).map(([path, pathItem]) => {
const pathParameters = pathItem.parameters
const operations = Object.assign({}, pathItem)
delete operations.parameters
return Object.entries(operations).map(([method, operation]) => {
const parameters = getParameters(pathParameters, operation.parameters)
return Object.assign({}, operation, { verb: method, path, parameters })
})
})
)
}

const getParameters = function(verbsParameters = [], propsParameters = []) {
const parameters = [...verbsParameters, ...propsParameters]
return parameters.reduce(addParameter, { path: {}, query: {}, body: {} })
}

const addParameter = function(parameters, param) {
return Object.assign({}, parameters, {
[param.in]: Object.assign({}, parameters[param.in], { [param.name]: param })
})
}

module.exports = { getOperations }

0 comments on commit 713caff

Please sign in to comment.