Skip to content

Commit

Permalink
feat(open-payments): replace axios with ky (#461)
Browse files Browse the repository at this point in the history
* chore: use node 20

* chore: update @types/node

* chore(ci): update actions

* feat(open-payments): use ky as httpclient

* chore(open-payments): fix request signing

* feat(open-payments): add validateResponses flag to optionally disable openapi schema validation

* chore(open-payments): dont parse DELETE response body

* chore(open-payments): handle DELETE body parsing

* chore(open-payments): handle DELETE body parsing

* chore(open-payments): handle DELETE body parsing

* chore(open-payments): only try parsing DELETE body if its not a 204 response

* chore(open-payments): only try parsing DELETE body if its not a 204 response

* feat(open-payments): finalize and test requests

* chore(open-payments): update nock and ky usage in jest

* chore(open-payments): fix tests after update to ky

* Revert "feat(open-payments): add validateResponses flag to optionally disable openapi schema validation"

This reverts commit b5f986a.

# Conflicts:
#	packages/open-payments/src/client/requests.test.ts
#	packages/open-payments/src/client/requests.ts

* chore(open-payments): cleanup files after commit revert

* chore(ci): update actions

* chore: use node 20

* chore(ci): update actions

* chore(open-payments): use dynamic import to resolve ky package

* chore(open-payments): allow nock to patch global.fetch

* chore(open-payments): allow nock to patch global.fetch in global setup

* chore(open-payments): fix test & lint

* chore(open-payments): continue nock cleanup

* chore: add changeset

* chore: update jest in workspace

* Revert "chore(open-payments): allow nock to patch global.fetch in global setup"

This reverts commit 9285d60.

* chore: update @swc/jest

* chore(open-payments): nock cleanup

* chore(open-payments): address comments

* chore(open-payments): handling unexpected error case
  • Loading branch information
mkurapov authored Apr 29, 2024
1 parent 7135e40 commit 8950c21
Show file tree
Hide file tree
Showing 17 changed files with 1,410 additions and 1,100 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-gifts-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@interledger/open-payments': minor
---

Replace axios with [ky](https://github.com/sindresorhus/ky) (a wrapper around native fetch)
2 changes: 1 addition & 1 deletion jest.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module.exports = {
transform: {
'^.+\\.tsx?$': ['@swc/jest']
'^.+\\.(t|j)sx?$': ['@swc/jest']
},
testEnvironment: 'node',
moduleDirectories: ['node_modules', './'],
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@
"@changesets/cli": "^2.26.1",
"@commitlint/cli": "^17.4.4",
"@commitlint/config-conventional": "^17.4.4",
"@swc/jest": "^0.2.24",
"@types/jest": "^29.4.4",
"@swc/core": "^1.5.0",
"@swc/jest": "^0.2.36",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.7.0",
"husky": "^8.0.3",
"jest": "^29.5.0",
"jest": "^29.7.0",
"prettier": "^2.8.4",
"ts-node-dev": "^2.0.0",
"typescript": "^4.9.5"
Expand Down
5 changes: 4 additions & 1 deletion packages/open-payments/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const baseConfig = require('../../jest.config.base.js')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const packageName = 'open-payments'

const esModules = ['ky']

module.exports = {
...baseConfig,
clearMocks: true,
Expand All @@ -13,5 +15,6 @@ module.exports = {
modulePaths: [`<rootDir>/packages/${packageName}/src/`],
id: packageName,
displayName: packageName,
rootDir: '../..'
rootDir: '../..',
transformIgnorePatterns: [`node_modules/(?!.pnpm|${esModules.join('|')})`]
}
4 changes: 2 additions & 2 deletions packages/open-payments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@
"devDependencies": {
"@types/node": "^20.12.7",
"@types/uuid": "^9.0.0",
"nock": "^13.3.0",
"nock": "14.0.0-beta.5",
"openapi-typescript": "^4.5.0",
"typescript": "^4.9.5"
},
"dependencies": {
"@interledger/http-signature-utils": "workspace:2.0.2",
"@interledger/openapi": "workspace:2.0.1",
"axios": "^1.6.0",
"base64url": "^3.0.1",
"http-message-signatures": "^0.1.2",
"ky": "^1.2.3",
"pino": "^8.11.0",
"uuid": "^9.0.0"
}
Expand Down
4 changes: 3 additions & 1 deletion packages/open-payments/src/client/grant.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createTestDeps, mockGrantRequest } from '../test/helpers'
import * as requestors from './requests'
import { v4 as uuid } from 'uuid'
import { getAuthServerOpenAPI } from '../openapi'
import { BaseDeps } from '.'

jest.mock('./requests', () => ({
...jest.requireActual('./requests.ts'),
Expand All @@ -15,12 +16,13 @@ jest.mock('./requests', () => ({

describe('grant', (): void => {
let openApi: OpenAPI
let deps: BaseDeps

beforeAll(async () => {
openApi = await getAuthServerOpenAPI()
deps = await createTestDeps()
})

const deps = createTestDeps()
const client = 'https://example.com/.well-known/pay'

describe('routes', () => {
Expand Down
22 changes: 11 additions & 11 deletions packages/open-payments/src/client/incoming-payment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { getRSPath } from '../types'
import { OpenPaymentsClientError } from './error'
import assert from 'assert'
import { getResourceServerOpenAPI } from '../openapi'
import { BaseDeps } from '.'

jest.mock('./requests', () => {
return {
Expand All @@ -37,12 +38,13 @@ jest.mock('./requests', () => {

describe('incoming-payment', (): void => {
let openApi: OpenAPI
let deps: BaseDeps

beforeAll(async () => {
openApi = await getResourceServerOpenAPI()
deps = await createTestDeps()
})

const deps = createTestDeps()
const walletAddress = 'http://localhost:1000/alice/.well-known/pay'
const serverAddress = 'http://localhost:1000'
const accessToken = 'accessToken'
Expand All @@ -64,7 +66,7 @@ describe('incoming-payment', (): void => {
},
openApiValidators.successfulValidator
)
expect(result).toStrictEqual(incomingPayment)
expect(result).toEqual(incomingPayment)
})

test('throws if incoming payment does not pass validation', async (): Promise<void> => {
Expand Down Expand Up @@ -133,7 +135,7 @@ describe('incoming-payment', (): void => {
},
openApiValidators.successfulValidator
)
expect(result).toStrictEqual(publicIncomingPayment)
expect(result).toEqual(publicIncomingPayment)
})

test('throws if incoming payment does not pass open api validation', async (): Promise<void> => {
Expand Down Expand Up @@ -266,7 +268,7 @@ describe('incoming-payment', (): void => {

scope.done()

expect(result).toStrictEqual(incomingPayment)
expect(result).toEqual(incomingPayment)
})

test('throws if the incoming payment does not pass validation', async (): Promise<void> => {
Expand Down Expand Up @@ -364,7 +366,7 @@ describe('incoming-payment', (): void => {
}
)

expect(result).toStrictEqual(incomingPaymentPaginationResult)
expect(result).toEqual(incomingPaymentPaginationResult)
scope.done()
}
)
Expand Down Expand Up @@ -407,7 +409,7 @@ describe('incoming-payment', (): void => {
}
)

expect(result).toStrictEqual(incomingPaymentPaginationResult)
expect(result).toEqual(incomingPaymentPaginationResult)
scope.done()
}
)
Expand Down Expand Up @@ -498,9 +500,7 @@ describe('incoming-payment', (): void => {
completed: true
})

expect(validateIncomingPayment(incomingPayment)).toStrictEqual(
incomingPayment
)
expect(validateIncomingPayment(incomingPayment)).toEqual(incomingPayment)
})

test('throws if receiving and incoming amount asset scales are different', async (): Promise<void> => {
Expand Down Expand Up @@ -557,7 +557,7 @@ describe('incoming-payment', (): void => {
}
})

expect(validateCreatedIncomingPayment(incomingPayment)).toStrictEqual(
expect(validateCreatedIncomingPayment(incomingPayment)).toEqual(
incomingPayment
)
})
Expand Down Expand Up @@ -593,7 +593,7 @@ describe('incoming-payment', (): void => {
completed: true
})

expect(validateCompletedIncomingPayment(incomingPayment)).toStrictEqual(
expect(validateCompletedIncomingPayment(incomingPayment)).toEqual(
incomingPayment
)
})
Expand Down
30 changes: 13 additions & 17 deletions packages/open-payments/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ import {
createWalletAddressRoutes,
WalletAddressRoutes
} from './wallet-address'
import {
createAxiosInstance,
createCustomAxiosInstance,
InterceptorFn
} from './requests'
import { AxiosInstance } from 'axios'
import { createHttpClient, HttpClient, InterceptorFn } from './requests'

import { createGrantRoutes, GrantRoutes } from './grant'
import {
createOutgoingPaymentRoutes,
Expand All @@ -37,7 +33,7 @@ import {
export * from './error'

export interface BaseDeps {
axiosInstance: AxiosInstance
httpClient: HttpClient
logger: Logger
useHttp: boolean
}
Expand All @@ -52,7 +48,7 @@ interface AuthenticatedClientDeps extends UnauthenticatedClientDeps {
}

export interface RouteDeps extends BaseDeps {
axiosInstance: AxiosInstance
httpClient: HttpClient
openApi: OpenAPI
logger: Logger
}
Expand Down Expand Up @@ -140,7 +136,7 @@ const createUnauthenticatedDeps = async ({
logger.level = args.logLevel
}

const axiosInstance = createAxiosInstance({
const httpClient = await createHttpClient({
requestTimeoutMs:
args?.requestTimeoutMs ?? config.DEFAULT_REQUEST_TIMEOUT_MS
})
Expand All @@ -149,7 +145,7 @@ const createUnauthenticatedDeps = async ({
const resourceServerOpenApi = await getResourceServerOpenAPI()

return {
axiosInstance,
httpClient,
walletAddressServerOpenApi,
resourceServerOpenApi,
logger,
Expand Down Expand Up @@ -183,20 +179,20 @@ const createAuthenticatedClientDeps = async ({
})
}

let axiosInstance: AxiosInstance | undefined
let httpClient: HttpClient

if ('authenticatedRequestInterceptor' in args) {
axiosInstance = createCustomAxiosInstance({
httpClient = await createHttpClient({
requestTimeoutMs:
args?.requestTimeoutMs ?? config.DEFAULT_REQUEST_TIMEOUT_MS,
authenticatedRequestInterceptor: args.authenticatedRequestInterceptor
})
} else {
axiosInstance = createAxiosInstance({
privateKey,
keyId: args.keyId,
httpClient = await createHttpClient({
requestTimeoutMs:
args?.requestTimeoutMs ?? config.DEFAULT_REQUEST_TIMEOUT_MS
args?.requestTimeoutMs ?? config.DEFAULT_REQUEST_TIMEOUT_MS,
privateKey,
keyId: args.keyId
})
}

Expand All @@ -205,7 +201,7 @@ const createAuthenticatedClientDeps = async ({
const authServerOpenApi = await getAuthServerOpenAPI()

return {
axiosInstance,
httpClient,
walletAddressServerOpenApi,
resourceServerOpenApi,
authServerOpenApi,
Expand Down
14 changes: 7 additions & 7 deletions packages/open-payments/src/client/outgoing-payment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { OpenPaymentsClientError } from './error'
import assert from 'assert'
import { getResourceServerOpenAPI } from '../openapi'
import { CreateOutgoingPaymentArgs } from '../types'
import { BaseDeps } from '.'

jest.mock('./requests', () => {
return {
Expand All @@ -30,12 +31,13 @@ jest.mock('./requests', () => {

describe('outgoing-payment', (): void => {
let openApi: OpenAPI
let deps: BaseDeps

beforeAll(async () => {
openApi = await getResourceServerOpenAPI()
deps = await createTestDeps()
})

const deps = createTestDeps()
const walletAddress = `http://localhost:1000/.well-known/pay`
const serverAddress = 'http://localhost:1000'
const openApiValidators = mockOpenApiResponseValidators()
Expand All @@ -56,7 +58,7 @@ describe('outgoing-payment', (): void => {
},
openApiValidators.successfulValidator
)
expect(result).toStrictEqual(outgoingPayment)
expect(result).toEqual(outgoingPayment)
scope.done()
})

Expand Down Expand Up @@ -160,7 +162,7 @@ describe('outgoing-payment', (): void => {
cursor
}
)
expect(result).toStrictEqual(outgoingPaymentPaginationResult)
expect(result).toEqual(outgoingPaymentPaginationResult)
scope.done()
}
)
Expand Down Expand Up @@ -202,7 +204,7 @@ describe('outgoing-payment', (): void => {
cursor
}
)
expect(result).toStrictEqual(outgoingPaymentPaginationResult)
expect(result).toEqual(outgoingPaymentPaginationResult)
scope.done()
}
)
Expand Down Expand Up @@ -408,9 +410,7 @@ describe('outgoing-payment', (): void => {
test('returns outgoing payment if passes validation', async (): Promise<void> => {
const outgoingPayment = mockOutgoingPayment()

expect(validateOutgoingPayment(outgoingPayment)).toStrictEqual(
outgoingPayment
)
expect(validateOutgoingPayment(outgoingPayment)).toEqual(outgoingPayment)
})

test('throws if send amount and sent amount asset scales are different', async (): Promise<void> => {
Expand Down
9 changes: 6 additions & 3 deletions packages/open-payments/src/client/quote.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,25 @@ import nock from 'nock'
import * as requestors from './requests'
import { getRSPath } from '../types'
import { getResourceServerOpenAPI } from '../openapi'
import { BaseDeps } from '.'

jest.mock('./requests', () => {
return {
// https://jestjs.io/docs/jest-object#jestmockmodulename-factory-options
__esModule: true,
...jest.requireActual('./requests')
}
})

describe('quote', (): void => {
let openApi: OpenAPI
let deps: BaseDeps

beforeAll(async () => {
openApi = await getResourceServerOpenAPI()
deps = await createTestDeps()
})

const deps = createTestDeps()
const quote = mockQuote()
const baseUrl = 'http://localhost:1000'
const openApiValidators = mockOpenApiResponseValidators()
Expand All @@ -42,7 +45,7 @@ describe('quote', (): void => {
},
openApiValidators.successfulValidator
)
expect(result).toStrictEqual(quote)
expect(result).toEqual(quote)
scope.done()
})

Expand Down Expand Up @@ -75,7 +78,7 @@ describe('quote', (): void => {
openApiValidators.successfulValidator,
{ receiver: quote.receiver, method: 'ilp', walletAddress }
)
expect(result).toStrictEqual(quote)
expect(result).toEqual(quote)
scope.done()
})

Expand Down
Loading

0 comments on commit 8950c21

Please sign in to comment.