Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(open-payments): replace axios with ky #461

Merged
merged 39 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
10ca74e
chore: use node 20
mkurapov Apr 12, 2024
930b8c8
chore: update @types/node
mkurapov Apr 12, 2024
bc9beba
chore(ci): update actions
mkurapov Apr 12, 2024
e4ab76b
feat(open-payments): use ky as httpclient
mkurapov Apr 15, 2024
c07b378
chore(open-payments): fix request signing
mkurapov Apr 16, 2024
b5f986a
feat(open-payments): add validateResponses flag to optionally disable…
mkurapov Apr 17, 2024
cd02386
chore(open-payments): dont parse DELETE response body
mkurapov Apr 17, 2024
a96b3d8
chore(open-payments): handle DELETE body parsing
mkurapov Apr 17, 2024
11023d4
chore(open-payments): handle DELETE body parsing
mkurapov Apr 17, 2024
ff1022d
chore(open-payments): handle DELETE body parsing
mkurapov Apr 17, 2024
2867431
chore(open-payments): only try parsing DELETE body if its not a 204 r…
mkurapov Apr 17, 2024
be3f608
chore(open-payments): only try parsing DELETE body if its not a 204 r…
mkurapov Apr 17, 2024
727c37b
feat(open-payments): finalize and test requests
mkurapov Apr 18, 2024
6e74048
chore(open-payments): update nock and ky usage in jest
mkurapov Apr 18, 2024
19f2a2c
chore(open-payments): fix tests after update to ky
mkurapov Apr 18, 2024
00e02d5
Revert "feat(open-payments): add validateResponses flag to optionally…
mkurapov Apr 18, 2024
e528947
chore(open-payments): cleanup files after commit revert
mkurapov Apr 18, 2024
f69571d
chore(ci): update actions
mkurapov Apr 12, 2024
450b69e
Merge branch '458/mk/node-20' into 454/mk/use-ky
mkurapov Apr 18, 2024
4c5559c
chore: use node 20
mkurapov Apr 12, 2024
9d9f0f9
chore(ci): update actions
mkurapov Apr 12, 2024
743751d
Merge branch '458/mk/node-20' into 454/mk/use-ky
mkurapov Apr 18, 2024
6f0077c
Merge branch 'main' into 454/mk/use-ky
mkurapov Apr 18, 2024
c64919f
chore(open-payments): use dynamic import to resolve ky package
mkurapov Apr 19, 2024
8aa37a9
chore(open-payments): allow nock to patch global.fetch
mkurapov Apr 19, 2024
9285d60
chore(open-payments): allow nock to patch global.fetch in global setup
mkurapov Apr 23, 2024
d6e0d66
chore(open-payments): fix test & lint
mkurapov Apr 23, 2024
ea55707
Merge branch 'main' into 454/mk/use-ky
mkurapov Apr 23, 2024
e308f60
Merge branch 'main' into 458/mk/node-20
mkurapov Apr 23, 2024
825bde1
Merge branch '458/mk/node-20' into 454/mk/use-ky
mkurapov Apr 23, 2024
6ff4039
chore(open-payments): continue nock cleanup
mkurapov Apr 23, 2024
86d8c97
Merge branch 'main' into 454/mk/use-ky
mkurapov Apr 23, 2024
fde0c10
chore: add changeset
mkurapov Apr 23, 2024
1506ebd
chore: update jest in workspace
mkurapov Apr 24, 2024
cff2671
Revert "chore(open-payments): allow nock to patch global.fetch in glo…
mkurapov Apr 24, 2024
fa02f89
chore: update @swc/jest
mkurapov Apr 24, 2024
c4f8a42
chore(open-payments): nock cleanup
mkurapov Apr 24, 2024
a327e72
chore(open-payments): address comments
mkurapov Apr 26, 2024
6eb6ade
chore(open-payments): handling unexpected error case
mkurapov Apr 29, 2024
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
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']
Copy link
Contributor Author

@mkurapov mkurapov Apr 18, 2024

Choose a reason for hiding this comment

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

this is so we transpile JS files as well, particularly for the files we need to transform from ESM to CommonJS in transformIgnorePatterns -> node_modules/ky

},
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",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's recommended to add @swc/core explicitly when using @swc/jest: https://swc.rs/docs/usage/jest

"@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('|')})`]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

transpile ESM ky package into CommonJS

Copy link
Contributor Author

@mkurapov mkurapov Apr 25, 2024

Choose a reason for hiding this comment

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

This also means we will need to add the same to the rafiki tests (everywhere where we use the @interledger/open-payments library, since rafiki also uses CJS only

Copy link
Contributor

Choose a reason for hiding this comment

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

How does this relate to the problem w/ the new ESM version of adonis which we couldnt get working in jest?

interledger/rafiki#2334 (comment)

Is this going to be a problem in rafiki for the same reason? Does it clarify that problem at all?

Copy link
Contributor Author

@mkurapov mkurapov Apr 26, 2024

Choose a reason for hiding this comment

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

I think what will end up working is doing the same in Rafiki and by adding the Adonis library to the list of esmModules. Have yet to try, but it follows the same principle

}
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",
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 is the version with experimental support for fetch

"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",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

👋

"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)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you elaborate on why this was necessary? I changed back to toStrictEqual and it fails with serializes to the same string. Something that changed with nock? or?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought this was odd as well, but I think it's the difference between how a response is returned in axios vs fetch. It's possible the order in which the object keys are returned are different?

Someone has an unaswered question related exactly to this: https://stackoverflow.com/questions/76211440/why-does-jests-tostrictequal-fail-to-match-json-responses-made-using-the-fetch

Copy link
Contributor

Choose a reason for hiding this comment

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

huh, yeah that is interesting. Wonder what the difference is. Seems innocent enough though.

})

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
Loading