Skip to content
This repository was archived by the owner on Oct 10, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ module.exports = {
'fp/no-class': 0,
'fp/no-let': 0,
'fp/no-loops': 0,
'fp/no-mutating-assign': 0,
'fp/no-mutating-methods': 0,
'fp/no-mutation': 0,
'fp/no-this': 0,
Expand Down
8 changes: 5 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ const dfn = require('@netlify/open-api')
const pWaitFor = require('p-wait-for')

const deploy = require('./deploy')
const { addMethods } = require('./methods')
const { getMethods } = require('./methods')
const { getOperations } = require('./operations')

class NetlifyAPI {
constructor(accessToken, opts) {
addMethods(this)

// variadic arguments
if (typeof accessToken === 'object') {
opts = accessToken
Expand Down Expand Up @@ -36,6 +34,10 @@ class NetlifyAPI {
this.globalParams = opts.globalParams
this.accessToken = opts.accessToken
this.agent = opts.agent

const methods = getMethods(this)
// eslint-disable-next-line fp/no-mutating-assign
Object.assign(this, methods)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to run after options have been assigned.

}

get accessToken() {
Expand Down
43 changes: 19 additions & 24 deletions src/methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,34 @@ const { getUrl } = require('./url.js')

// For each OpenAPI operation, add a corresponding method.
// The `operationId` is the method name.
const addMethods = function (NetlifyApi) {
const methods = getMethods(NetlifyApi)
Object.assign(NetlifyApi, methods)
}

const getMethods = function (NetlifyApi) {
const getMethods = function ({ basePath, defaultHeaders, agent, globalParams }) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make options passing more explicit.

const operations = getOperations()
const methods = operations.map((method) => getMethod(method, NetlifyApi))
const methods = operations.map((method) => getMethod({ method, basePath, defaultHeaders, agent, globalParams }))
return Object.assign({}, ...methods)
}

const getMethod = function (method, NetlifyApi) {
const getMethod = function ({ method, basePath, defaultHeaders, agent, globalParams }) {
return {
[method.operationId](params, opts) {
return callMethod(method, NetlifyApi, params, opts)
return callMethod({ method, basePath, defaultHeaders, agent, globalParams, params, opts })
},
}
}

const callMethod = async function (method, NetlifyApi, params, opts) {
const requestParams = { ...NetlifyApi.globalParams, ...params }
const url = getUrl(method, NetlifyApi, requestParams)
const response = await makeRequestOrRetry({ url, method, NetlifyApi, requestParams, opts })
const callMethod = async function ({ method, basePath, defaultHeaders, agent, globalParams, params, opts }) {
const requestParams = { ...globalParams, ...params }
const url = getUrl(method, basePath, requestParams)
const response = await makeRequestOrRetry({ url, method, defaultHeaders, agent, requestParams, opts })

const parsedResponse = await parseResponse(response)
return parsedResponse
}

const getOpts = function ({ verb, parameters }, NetlifyApi, { body }, opts) {
const getOpts = function ({ method: { verb, parameters }, defaultHeaders, agent, requestParams: { body }, opts }) {
const optsA = addHttpMethod(verb, opts)
const optsB = addDefaultHeaders(NetlifyApi, optsA)
const optsB = addDefaultHeaders(defaultHeaders, optsA)
const optsC = addBody(body, parameters, optsB)
const optsD = addAgent(NetlifyApi, optsC)
const optsD = addAgent(agent, optsC)
return optsD
}

Expand All @@ -53,21 +48,21 @@ const addHttpMethod = function (verb, opts) {
}

// Assign default HTTP headers
const addDefaultHeaders = function (NetlifyApi, opts) {
return { ...opts, headers: { ...NetlifyApi.defaultHeaders, ...opts.headers } }
const addDefaultHeaders = function (defaultHeaders, opts) {
return { ...opts, headers: { ...defaultHeaders, ...opts.headers } }
}

// Assign fetch agent (like for example HttpsProxyAgent) if there is one
const addAgent = function (NetlifyApi, opts) {
if (NetlifyApi.agent) {
return { ...opts, agent: NetlifyApi.agent }
const addAgent = function (agent, opts) {
if (agent) {
return { ...opts, agent }
}
return opts
}

const makeRequestOrRetry = async function ({ url, method, NetlifyApi, requestParams, opts }) {
const makeRequestOrRetry = async function ({ url, method, defaultHeaders, agent, requestParams, opts }) {
for (let index = 0; index <= MAX_RETRY; index++) {
const optsA = getOpts(method, NetlifyApi, requestParams, opts)
const optsA = getOpts({ method, defaultHeaders, agent, requestParams, opts })
const { response, error } = await makeRequest(url, optsA)

if (shouldRetry({ response, error }) && index !== MAX_RETRY) {
Expand All @@ -93,4 +88,4 @@ const makeRequest = async function (url, opts) {
}
}

module.exports = { addMethods }
module.exports = { getMethods }
4 changes: 3 additions & 1 deletion src/methods/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ const parseJsonResponse = function (response, textResponse, responseType) {

const getFetchError = function (error, url, opts) {
const data = omit(opts, ['Authorization'])
Object.assign(error, { name: 'FetchError', url, data })
error.name = 'FetchError'
error.url = url
error.data = data
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We allow direct mutations on variables that are known to be mutable by design. For example, errors should be directly mutated to keep the Error prototype. We allow those variables by variable names: https://github.com/netlify/eslint-config-node/blob/d76bd7afca8611d0a00277bdd24435adfdeca38b/.eslintrc.js#L181

However, the exceptions option is not available for this specific rule (about Object.assign()), so we need to use direct property mutations instead to fix linting.

return error
}

Expand Down
4 changes: 2 additions & 2 deletions src/methods/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const queryString = require('qs')

// Replace path parameters and query parameters in the URI, using the OpenAPI
// definition
const getUrl = function ({ path, parameters }, NetlifyApi, requestParams) {
const url = `${NetlifyApi.basePath}${path}`
const getUrl = function ({ path, parameters }, basePath, requestParams) {
const url = `${basePath}${path}`
const urlA = addPathParams(url, parameters, requestParams)
const urlB = addQueryParams(urlA, parameters, requestParams)
return urlB
Expand Down