@0xtorch/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/import/accounts/index.d.ts +2 -0
- package/dist/import/accounts/index.d.ts.map +1 -0
- package/dist/import/accounts/types/account.d.ts +6 -0
- package/dist/import/accounts/types/account.d.ts.map +1 -0
- package/dist/import/accounts/types/index.d.ts +2 -0
- package/dist/import/accounts/types/index.d.ts.map +1 -0
- package/dist/import/actions/index.d.ts +2 -0
- package/dist/import/actions/index.d.ts.map +1 -0
- package/dist/import/actions/types/addLiquidity.d.ts +7 -0
- package/dist/import/actions/types/addLiquidity.d.ts.map +1 -0
- package/dist/import/actions/types/atomicArbitrage.d.ts +5 -0
- package/dist/import/actions/types/atomicArbitrage.d.ts.map +1 -0
- package/dist/import/actions/types/bridgeFrom.d.ts +6 -0
- package/dist/import/actions/types/bridgeFrom.d.ts.map +1 -0
- package/dist/import/actions/types/bridgeTo.d.ts +6 -0
- package/dist/import/actions/types/bridgeTo.d.ts.map +1 -0
- package/dist/import/actions/types/buyNft.d.ts +7 -0
- package/dist/import/actions/types/buyNft.d.ts.map +1 -0
- package/dist/import/actions/types/common.d.ts +50 -0
- package/dist/import/actions/types/common.d.ts.map +1 -0
- package/dist/import/actions/types/deposit.d.ts +6 -0
- package/dist/import/actions/types/deposit.d.ts.map +1 -0
- package/dist/import/actions/types/depositWithBond.d.ts +7 -0
- package/dist/import/actions/types/depositWithBond.d.ts.map +1 -0
- package/dist/import/actions/types/freeMintNft.d.ts +8 -0
- package/dist/import/actions/types/freeMintNft.d.ts.map +1 -0
- package/dist/import/actions/types/income.d.ts +5 -0
- package/dist/import/actions/types/income.d.ts.map +1 -0
- package/dist/import/actions/types/index.d.ts +24 -0
- package/dist/import/actions/types/index.d.ts.map +1 -0
- package/dist/import/actions/types/move.d.ts +5 -0
- package/dist/import/actions/types/move.d.ts.map +1 -0
- package/dist/import/actions/types/nftRoyalty.d.ts +7 -0
- package/dist/import/actions/types/nftRoyalty.d.ts.map +1 -0
- package/dist/import/actions/types/removeLiquidity.d.ts +7 -0
- package/dist/import/actions/types/removeLiquidity.d.ts.map +1 -0
- package/dist/import/actions/types/sellNft.d.ts +6 -0
- package/dist/import/actions/types/sellNft.d.ts.map +1 -0
- package/dist/import/actions/types/spam.d.ts +6 -0
- package/dist/import/actions/types/spam.d.ts.map +1 -0
- package/dist/import/actions/types/swapIncome.d.ts +4 -0
- package/dist/import/actions/types/swapIncome.d.ts.map +1 -0
- package/dist/import/actions/types/swapNft.d.ts +6 -0
- package/dist/import/actions/types/swapNft.d.ts.map +1 -0
- package/dist/import/actions/types/swapTransfer.d.ts +4 -0
- package/dist/import/actions/types/swapTransfer.d.ts.map +1 -0
- package/dist/import/actions/types/trade.d.ts +7 -0
- package/dist/import/actions/types/trade.d.ts.map +1 -0
- package/dist/import/actions/types/transactionFee.d.ts +7 -0
- package/dist/import/actions/types/transactionFee.d.ts.map +1 -0
- package/dist/import/actions/types/transfer.d.ts +8 -0
- package/dist/import/actions/types/transfer.d.ts.map +1 -0
- package/dist/import/actions/types/withdraw.d.ts +7 -0
- package/dist/import/actions/types/withdraw.d.ts.map +1 -0
- package/dist/import/actions/types/withdrawWithBond.d.ts +7 -0
- package/dist/import/actions/types/withdrawWithBond.d.ts.map +1 -0
- package/dist/import/apps/index.d.ts +3 -0
- package/dist/import/apps/index.d.ts.map +1 -0
- package/dist/import/apps/types.d.ts +11 -0
- package/dist/import/apps/types.d.ts.map +1 -0
- package/dist/import/assets/constants.d.ts +2 -0
- package/dist/import/assets/constants.d.ts.map +1 -0
- package/dist/import/assets/creates/createCryptoCurrency.d.ts +3 -0
- package/dist/import/assets/creates/createCryptoCurrency.d.ts.map +1 -0
- package/dist/import/assets/creates/createFiatCurrency.d.ts +3 -0
- package/dist/import/assets/creates/createFiatCurrency.d.ts.map +1 -0
- package/dist/import/assets/creates/index.d.ts +3 -0
- package/dist/import/assets/creates/index.d.ts.map +1 -0
- package/dist/import/assets/definitions/astar.d.ts +13 -0
- package/dist/import/assets/definitions/astar.d.ts.map +1 -0
- package/dist/import/assets/definitions/avalanche.d.ts +13 -0
- package/dist/import/assets/definitions/avalanche.d.ts.map +1 -0
- package/dist/import/assets/definitions/bnb.d.ts +13 -0
- package/dist/import/assets/definitions/bnb.d.ts.map +1 -0
- package/dist/import/assets/definitions/coingeckoCryptoCurrencyDataSource.d.ts +18 -0
- package/dist/import/assets/definitions/coingeckoCryptoCurrencyDataSource.d.ts.map +1 -0
- package/dist/import/assets/definitions/ethereum.d.ts +13 -0
- package/dist/import/assets/definitions/ethereum.d.ts.map +1 -0
- package/dist/import/assets/definitions/eur.d.ts +8 -0
- package/dist/import/assets/definitions/eur.d.ts.map +1 -0
- package/dist/import/assets/definitions/fantom.d.ts +13 -0
- package/dist/import/assets/definitions/fantom.d.ts.map +1 -0
- package/dist/import/assets/definitions/index.d.ts +17 -0
- package/dist/import/assets/definitions/index.d.ts.map +1 -0
- package/dist/import/assets/definitions/jpy.d.ts +8 -0
- package/dist/import/assets/definitions/jpy.d.ts.map +1 -0
- package/dist/import/assets/definitions/kava.d.ts +13 -0
- package/dist/import/assets/definitions/kava.d.ts.map +1 -0
- package/dist/import/assets/definitions/mantle.d.ts +13 -0
- package/dist/import/assets/definitions/mantle.d.ts.map +1 -0
- package/dist/import/assets/definitions/maticNetwork.d.ts +13 -0
- package/dist/import/assets/definitions/maticNetwork.d.ts.map +1 -0
- package/dist/import/assets/definitions/metis.d.ts +13 -0
- package/dist/import/assets/definitions/metis.d.ts.map +1 -0
- package/dist/import/assets/definitions/moonbeam.d.ts +13 -0
- package/dist/import/assets/definitions/moonbeam.d.ts.map +1 -0
- package/dist/import/assets/definitions/moonriver.d.ts +13 -0
- package/dist/import/assets/definitions/moonriver.d.ts.map +1 -0
- package/dist/import/assets/definitions/ronin.d.ts +13 -0
- package/dist/import/assets/definitions/ronin.d.ts.map +1 -0
- package/dist/import/assets/definitions/usd.d.ts +8 -0
- package/dist/import/assets/definitions/usd.d.ts.map +1 -0
- package/dist/import/assets/externals/coingecko/constants.d.ts +2 -0
- package/dist/import/assets/externals/coingecko/constants.d.ts.map +1 -0
- package/dist/import/assets/externals/coingecko/getAutoRetry.d.ts +4 -0
- package/dist/import/assets/externals/coingecko/getAutoRetry.d.ts.map +1 -0
- package/dist/import/assets/externals/coingecko/getCoinMarketChartRange.d.ts +49 -0
- package/dist/import/assets/externals/coingecko/getCoinMarketChartRange.d.ts.map +1 -0
- package/dist/import/assets/externals/coingecko/getCoinsMarkets.d.ts +58 -0
- package/dist/import/assets/externals/coingecko/getCoinsMarkets.d.ts.map +1 -0
- package/dist/import/assets/externals/coingecko/index.d.ts +3 -0
- package/dist/import/assets/externals/coingecko/index.d.ts.map +1 -0
- package/dist/import/assets/externals/index.d.ts +2 -0
- package/dist/import/assets/externals/index.d.ts.map +1 -0
- package/dist/import/assets/index.d.ts +5 -0
- package/dist/import/assets/index.d.ts.map +1 -0
- package/dist/import/assets/types/cryptoCurrency.d.ts +17 -0
- package/dist/import/assets/types/cryptoCurrency.d.ts.map +1 -0
- package/dist/import/assets/types/cryptoCurrencyPrice.d.ts +10 -0
- package/dist/import/assets/types/cryptoCurrencyPrice.d.ts.map +1 -0
- package/dist/import/assets/types/dataSource.d.ts +18 -0
- package/dist/import/assets/types/dataSource.d.ts.map +1 -0
- package/dist/import/assets/types/fiatCurrency.d.ts +12 -0
- package/dist/import/assets/types/fiatCurrency.d.ts.map +1 -0
- package/dist/import/assets/types/index.d.ts +6 -0
- package/dist/import/assets/types/index.d.ts.map +1 -0
- package/dist/import/assets/types/nft.d.ts +5 -0
- package/dist/import/assets/types/nft.d.ts.map +1 -0
- package/dist/import/index.d.mts +12 -0
- package/dist/import/index.d.mts.map +1 -0
- package/dist/import/index.mjs +2 -0
- package/dist/import/portfolios/createPortfolio.d.ts +2 -0
- package/dist/import/portfolios/createPortfolio.d.ts.map +1 -0
- package/dist/import/portfolios/index.d.ts +3 -0
- package/dist/import/portfolios/index.d.ts.map +1 -0
- package/dist/import/portfolios/type.d.ts +4 -0
- package/dist/import/portfolios/type.d.ts.map +1 -0
- package/dist/import/types.d.ts +11 -0
- package/dist/import/types.d.ts.map +1 -0
- package/dist/import/utils/errors.d.ts +48 -0
- package/dist/import/utils/errors.d.ts.map +1 -0
- package/dist/import/utils/index.d.ts +5 -0
- package/dist/import/utils/index.d.ts.map +1 -0
- package/dist/import/utils/rest.d.ts +14 -0
- package/dist/import/utils/rest.d.ts.map +1 -0
- package/dist/import/utils/stringify.d.ts +2 -0
- package/dist/import/utils/stringify.d.ts.map +1 -0
- package/dist/import/utils/types.d.ts +12 -0
- package/dist/import/utils/types.d.ts.map +1 -0
- package/dist/require/index.cjs +2 -0
- package/dist/require/index.d.cts +2 -0
- package/dist/require/index.d.cts.map +1 -0
- package/package.json +79 -0
- package/src/accounts/index.ts +1 -0
- package/src/accounts/types/account.ts +5 -0
- package/src/accounts/types/index.ts +1 -0
- package/src/actions/index.ts +44 -0
- package/src/actions/schemas/constants.ts +16 -0
- package/src/actions/schemas/swap.ts +7 -0
- package/src/actions/types/addLiquidity.ts +23 -0
- package/src/actions/types/atomicArbitrage.ts +30 -0
- package/src/actions/types/bridgeFrom.ts +23 -0
- package/src/actions/types/bridgeTo.ts +23 -0
- package/src/actions/types/buyNft.ts +34 -0
- package/src/actions/types/common.ts +142 -0
- package/src/actions/types/deposit.ts +23 -0
- package/src/actions/types/depositWithBond.ts +23 -0
- package/src/actions/types/freeMintNft.ts +20 -0
- package/src/actions/types/income.ts +21 -0
- package/src/actions/types/index.ts +53 -0
- package/src/actions/types/move.ts +21 -0
- package/src/actions/types/nftRoyalty.ts +19 -0
- package/src/actions/types/removeLiquidity.ts +23 -0
- package/src/actions/types/sellNft.ts +22 -0
- package/src/actions/types/spam.ts +23 -0
- package/src/actions/types/swapIncome.ts +12 -0
- package/src/actions/types/swapNft.ts +12 -0
- package/src/actions/types/swapTransfer.ts +12 -0
- package/src/actions/types/trade.ts +34 -0
- package/src/actions/types/transactionFee.ts +19 -0
- package/src/actions/types/transfer.ts +36 -0
- package/src/actions/types/withdraw.ts +23 -0
- package/src/actions/types/withdrawWithBond.ts +23 -0
- package/src/apps/index.ts +2 -0
- package/src/apps/types.ts +20 -0
- package/src/assets/constants.ts +1 -0
- package/src/assets/creates/createCryptoCurrency.ts +7 -0
- package/src/assets/creates/createFiatCurrency.ts +10 -0
- package/src/assets/creates/index.ts +2 -0
- package/src/assets/definitions/astar.ts +14 -0
- package/src/assets/definitions/avalanche.ts +14 -0
- package/src/assets/definitions/bnb.ts +14 -0
- package/src/assets/definitions/coingeckoCryptoCurrencyDataSource.test.ts +53 -0
- package/src/assets/definitions/coingeckoCryptoCurrencyDataSource.ts +169 -0
- package/src/assets/definitions/ethereum.ts +14 -0
- package/src/assets/definitions/eur.ts +9 -0
- package/src/assets/definitions/fantom.ts +14 -0
- package/src/assets/definitions/index.ts +16 -0
- package/src/assets/definitions/jpy.ts +9 -0
- package/src/assets/definitions/kava.ts +14 -0
- package/src/assets/definitions/mantle.ts +14 -0
- package/src/assets/definitions/maticNetwork.ts +14 -0
- package/src/assets/definitions/metis.ts +14 -0
- package/src/assets/definitions/moonbeam.ts +14 -0
- package/src/assets/definitions/moonriver.ts +14 -0
- package/src/assets/definitions/ronin.ts +14 -0
- package/src/assets/definitions/usd.ts +9 -0
- package/src/assets/externals/coingecko/constants.ts +1 -0
- package/src/assets/externals/coingecko/getAutoRetry.ts +35 -0
- package/src/assets/externals/coingecko/getCoinMarketChartRange.test.ts +28 -0
- package/src/assets/externals/coingecko/getCoinMarketChartRange.ts +88 -0
- package/src/assets/externals/coingecko/getCoinsMarkets.test.ts +11 -0
- package/src/assets/externals/coingecko/getCoinsMarkets.ts +106 -0
- package/src/assets/externals/coingecko/index.ts +2 -0
- package/src/assets/externals/index.ts +1 -0
- package/src/assets/index.ts +27 -0
- package/src/assets/types/cryptoCurrency.ts +17 -0
- package/src/assets/types/cryptoCurrencyPrice.ts +14 -0
- package/src/assets/types/dataSource.ts +26 -0
- package/src/assets/types/fiatCurrency.ts +21 -0
- package/src/assets/types/index.ts +9 -0
- package/src/assets/types/nft.ts +5 -0
- package/src/index.cts +1 -0
- package/src/index.mts +79 -0
- package/src/portfolios/createPortfolio.test.ts +7 -0
- package/src/portfolios/createPortfolio.ts +3 -0
- package/src/portfolios/index.ts +2 -0
- package/src/portfolios/type.ts +3 -0
- package/src/tests/constants.ts +1 -0
- package/src/tests/index.ts +2 -0
- package/src/tests/utils.ts +26 -0
- package/src/types.ts +11 -0
- package/src/utils/errors.ts +130 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/rest.test.ts +19 -0
- package/src/utils/rest.ts +138 -0
- package/src/utils/stringify.test.ts +24 -0
- package/src/utils/stringify.ts +11 -0
- package/src/utils/types.ts +12 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
export type ErrorType<name extends string = 'Error'> = Error & { name: name }
|
|
2
|
+
|
|
3
|
+
type BaseErrorParameters = {
|
|
4
|
+
metaMessages?: string[]
|
|
5
|
+
} & (
|
|
6
|
+
| {
|
|
7
|
+
cause?: never
|
|
8
|
+
details?: string
|
|
9
|
+
}
|
|
10
|
+
| {
|
|
11
|
+
cause: BaseError | Error
|
|
12
|
+
details?: never
|
|
13
|
+
}
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
class BaseError extends Error {
|
|
17
|
+
details: string
|
|
18
|
+
metaMessages?: string[]
|
|
19
|
+
shortMessage: string
|
|
20
|
+
|
|
21
|
+
override name = 'BaseError'
|
|
22
|
+
|
|
23
|
+
constructor(shortMessage: string, arguments_: BaseErrorParameters = {}) {
|
|
24
|
+
super()
|
|
25
|
+
|
|
26
|
+
const details =
|
|
27
|
+
arguments_.cause instanceof BaseError
|
|
28
|
+
? arguments_.cause.details
|
|
29
|
+
: // eslint-disable-next-line unicorn/no-nested-ternary
|
|
30
|
+
arguments_.cause?.message !== undefined &&
|
|
31
|
+
arguments_.cause?.message.length > 0
|
|
32
|
+
? arguments_.cause.message
|
|
33
|
+
: arguments_.details!
|
|
34
|
+
|
|
35
|
+
this.message = [
|
|
36
|
+
shortMessage.length > 0 ? shortMessage : 'An error occurred.',
|
|
37
|
+
'',
|
|
38
|
+
...(arguments_.metaMessages === undefined
|
|
39
|
+
? []
|
|
40
|
+
: [...arguments_.metaMessages, '']),
|
|
41
|
+
...(details.length > 0 ? [`Details: ${details}`] : []),
|
|
42
|
+
].join('\n')
|
|
43
|
+
|
|
44
|
+
if (arguments_.cause !== undefined) this.cause = arguments_.cause
|
|
45
|
+
this.details = details
|
|
46
|
+
this.metaMessages = arguments_.metaMessages
|
|
47
|
+
this.shortMessage = shortMessage
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
walk(): Error
|
|
51
|
+
walk(function_: (error: unknown) => boolean): Error | null
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
+
walk(function_?: any): any {
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
55
|
+
return walk(this, function_)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const walk = (
|
|
60
|
+
error: unknown,
|
|
61
|
+
function_?: (error_: unknown) => boolean,
|
|
62
|
+
): unknown => {
|
|
63
|
+
if (function_?.(error) === true) return error
|
|
64
|
+
if (
|
|
65
|
+
error !== undefined &&
|
|
66
|
+
error !== null &&
|
|
67
|
+
typeof error === 'object' &&
|
|
68
|
+
'cause' in error
|
|
69
|
+
)
|
|
70
|
+
return walk(error.cause, function_)
|
|
71
|
+
return function_ === undefined ? error : undefined
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export class HttpRequestError extends BaseError {
|
|
75
|
+
override name = 'HttpRequestError'
|
|
76
|
+
|
|
77
|
+
body?: string
|
|
78
|
+
status?: number
|
|
79
|
+
url: string
|
|
80
|
+
|
|
81
|
+
constructor({
|
|
82
|
+
body,
|
|
83
|
+
details,
|
|
84
|
+
status,
|
|
85
|
+
url,
|
|
86
|
+
}: {
|
|
87
|
+
body?: string
|
|
88
|
+
details?: string
|
|
89
|
+
status?: number
|
|
90
|
+
url: string
|
|
91
|
+
}) {
|
|
92
|
+
super('HTTP request failed.', {
|
|
93
|
+
details,
|
|
94
|
+
metaMessages: [
|
|
95
|
+
...(status === undefined ? [] : [`Status: ${status}`]),
|
|
96
|
+
`URL: ${url}`,
|
|
97
|
+
...(body === undefined || body === null
|
|
98
|
+
? []
|
|
99
|
+
: [`Request body: ${body}`]),
|
|
100
|
+
],
|
|
101
|
+
})
|
|
102
|
+
this.body = body
|
|
103
|
+
this.status = status
|
|
104
|
+
this.url = url
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type HttpRequestErrorType = HttpRequestError & {
|
|
109
|
+
name: 'HttpRequestError'
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export class TimeoutError extends BaseError {
|
|
113
|
+
override name = 'TimeoutError'
|
|
114
|
+
|
|
115
|
+
constructor({ body, url }: { body?: string; url: string }) {
|
|
116
|
+
super('The request took too long to respond.', {
|
|
117
|
+
details: 'The request timed out.',
|
|
118
|
+
metaMessages: [
|
|
119
|
+
`URL: ${url}`,
|
|
120
|
+
...(body === undefined || body === null
|
|
121
|
+
? []
|
|
122
|
+
: [`Request body: ${body}`]),
|
|
123
|
+
],
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type TimeoutErrorType = TimeoutError & {
|
|
129
|
+
name: 'TimeoutError'
|
|
130
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { isIntegrationTest } from '../tests'
|
|
4
|
+
import { rest } from './rest'
|
|
5
|
+
|
|
6
|
+
describe('rest', () => {
|
|
7
|
+
it.if(isIntegrationTest)('Get HTML response', async () => {
|
|
8
|
+
const html = await rest('https://example.com', { schema: z.string() })
|
|
9
|
+
expect(html).toInclude('<html>')
|
|
10
|
+
})
|
|
11
|
+
it.if(isIntegrationTest)('Should return validated object', async () => {
|
|
12
|
+
const json = await rest('https://api.coingecko.com/api/v3/ping', {
|
|
13
|
+
schema: z.object({
|
|
14
|
+
gecko_says: z.string(),
|
|
15
|
+
}),
|
|
16
|
+
})
|
|
17
|
+
expect(json.gecko_says.length).toBeGreaterThan(0)
|
|
18
|
+
})
|
|
19
|
+
})
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { ZodError } from 'zod'
|
|
2
|
+
|
|
3
|
+
import type { Logger } from '../types'
|
|
4
|
+
import { HttpRequestError, TimeoutError } from './errors'
|
|
5
|
+
import { stringify } from './stringify'
|
|
6
|
+
|
|
7
|
+
export type Schema<TData> = {
|
|
8
|
+
parse: (data: unknown) => TData
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type RestOptions<TData> = {
|
|
12
|
+
// Request configuration to pass to `fetch`.
|
|
13
|
+
fetchOptions?: RequestInit
|
|
14
|
+
// The timeout (in ms) for the request.
|
|
15
|
+
timeout?: number
|
|
16
|
+
schema: Schema<TData>
|
|
17
|
+
logger?: Logger
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const rest = async <TData>(
|
|
21
|
+
url: string,
|
|
22
|
+
{ fetchOptions = {}, timeout = 10_000, schema, logger }: RestOptions<TData>,
|
|
23
|
+
): Promise<TData> => {
|
|
24
|
+
const { body, headers, method, signal: signal_ } = fetchOptions
|
|
25
|
+
|
|
26
|
+
if (logger !== undefined) {
|
|
27
|
+
logger.info(`[${method?.toUpperCase() ?? 'GET'}] ${url}`)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const response = await withTimeout(
|
|
32
|
+
async ({ signal }) =>
|
|
33
|
+
await fetch(url, {
|
|
34
|
+
...fetchOptions,
|
|
35
|
+
headers: {
|
|
36
|
+
...(headers as Record<string, string>),
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
},
|
|
39
|
+
signal: signal_ ?? (timeout > 0 ? signal : undefined),
|
|
40
|
+
}),
|
|
41
|
+
{
|
|
42
|
+
errorInstance: new TimeoutError({
|
|
43
|
+
body: body === undefined ? undefined : stringify(body),
|
|
44
|
+
url,
|
|
45
|
+
}),
|
|
46
|
+
timeout,
|
|
47
|
+
signal: true,
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
51
|
+
const data =
|
|
52
|
+
response.headers.get('Content-Type')?.startsWith('application/json') ===
|
|
53
|
+
true
|
|
54
|
+
? await response.json()
|
|
55
|
+
: await response.text()
|
|
56
|
+
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const errorStringify =
|
|
59
|
+
typeof data === 'object' && data !== null && 'error' in data
|
|
60
|
+
? // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
61
|
+
stringify(data.error)
|
|
62
|
+
: ''
|
|
63
|
+
throw new HttpRequestError({
|
|
64
|
+
body: body === undefined ? undefined : stringify(body),
|
|
65
|
+
details:
|
|
66
|
+
errorStringify.length > 0 ? errorStringify : response.statusText,
|
|
67
|
+
status: response.status,
|
|
68
|
+
url,
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return schema.parse(data)
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (
|
|
75
|
+
error instanceof TimeoutError ||
|
|
76
|
+
error instanceof HttpRequestError ||
|
|
77
|
+
error instanceof ZodError
|
|
78
|
+
) {
|
|
79
|
+
throw error
|
|
80
|
+
} else if (error instanceof Error) {
|
|
81
|
+
throw new HttpRequestError({
|
|
82
|
+
body: body === undefined ? undefined : stringify(body),
|
|
83
|
+
details: error.message,
|
|
84
|
+
url,
|
|
85
|
+
})
|
|
86
|
+
} else {
|
|
87
|
+
throw error
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const withTimeout = <TData>(
|
|
93
|
+
function_: ({
|
|
94
|
+
signal,
|
|
95
|
+
}: {
|
|
96
|
+
signal?: AbortController['signal']
|
|
97
|
+
}) => Promise<TData>,
|
|
98
|
+
{
|
|
99
|
+
errorInstance = new Error('timed out'),
|
|
100
|
+
timeout,
|
|
101
|
+
signal,
|
|
102
|
+
}: {
|
|
103
|
+
// The error instance to throw when the timeout is reached.
|
|
104
|
+
errorInstance?: Error
|
|
105
|
+
// The timeout (in ms).
|
|
106
|
+
timeout: number
|
|
107
|
+
// Whether or not the timeout should use an abort signal.
|
|
108
|
+
signal?: boolean
|
|
109
|
+
},
|
|
110
|
+
): Promise<TData> =>
|
|
111
|
+
new Promise((resolve, reject) => {
|
|
112
|
+
let mut_timeoutId: Timer | undefined
|
|
113
|
+
try {
|
|
114
|
+
const controller = new AbortController()
|
|
115
|
+
if (timeout > 0) {
|
|
116
|
+
mut_timeoutId = setTimeout(() => {
|
|
117
|
+
if (signal === undefined) {
|
|
118
|
+
reject(errorInstance)
|
|
119
|
+
} else {
|
|
120
|
+
controller.abort()
|
|
121
|
+
}
|
|
122
|
+
}, timeout)
|
|
123
|
+
}
|
|
124
|
+
function_({ signal: controller.signal })
|
|
125
|
+
.then((value) => {
|
|
126
|
+
resolve(value)
|
|
127
|
+
})
|
|
128
|
+
.catch((error) => {
|
|
129
|
+
reject(error)
|
|
130
|
+
})
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (error instanceof Error && error.name === 'AbortError')
|
|
133
|
+
reject(errorInstance)
|
|
134
|
+
reject(error)
|
|
135
|
+
} finally {
|
|
136
|
+
clearTimeout(mut_timeoutId)
|
|
137
|
+
}
|
|
138
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { stringify } from './stringify'
|
|
4
|
+
|
|
5
|
+
describe('stringify', () => {
|
|
6
|
+
it('Should stringify a string', () => {
|
|
7
|
+
expect(stringify('string')).toEqual('"string"')
|
|
8
|
+
})
|
|
9
|
+
it('Should stringify a number', () => {
|
|
10
|
+
expect(stringify(123)).toEqual('123')
|
|
11
|
+
})
|
|
12
|
+
it('Should stringify a boolean', () => {
|
|
13
|
+
expect(stringify(true)).toEqual('true')
|
|
14
|
+
})
|
|
15
|
+
it('Should stringify a bigint', () => {
|
|
16
|
+
expect(stringify(BigInt(123))).toEqual('"123"')
|
|
17
|
+
})
|
|
18
|
+
it('Should stringify an array', () => {
|
|
19
|
+
expect(stringify([1, 2, 3])).toEqual('[1,2,3]')
|
|
20
|
+
})
|
|
21
|
+
it('Should stringify an object', () => {
|
|
22
|
+
expect(stringify({ a: 1, b: 2, c: 3 })).toEqual('{"a":1,"b":2,"c":3}')
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const stringify: typeof JSON.stringify = (value, replacer, space) =>
|
|
2
|
+
JSON.stringify(
|
|
3
|
+
value,
|
|
4
|
+
(key, value_) => {
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
6
|
+
const value = typeof value_ === 'bigint' ? value_.toString() : value_
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
8
|
+
return typeof replacer === 'function' ? replacer(key, value) : value
|
|
9
|
+
},
|
|
10
|
+
space,
|
|
11
|
+
)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Combines members of an intersection into a readable type.
|
|
3
|
+
*
|
|
4
|
+
* @see {@link https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg}
|
|
5
|
+
* @example
|
|
6
|
+
* Prettify<{ a: string } & { b: string } & { c: number, d: bigint }>
|
|
7
|
+
* => { a: string, b: string, c: number, d: bigint }
|
|
8
|
+
*/
|
|
9
|
+
export type Prettify<T> = {
|
|
10
|
+
[K in keyof T]: T[K]
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
12
|
+
} & {}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"allowJs": true,
|
|
9
|
+
|
|
10
|
+
// Bundler mode
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
|
|
16
|
+
// Best practices
|
|
17
|
+
"strict": true,
|
|
18
|
+
"skipLibCheck": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
|
|
21
|
+
// Some stricter flags (disabled by default)
|
|
22
|
+
"noUnusedLocals": false,
|
|
23
|
+
"noUnusedParameters": false,
|
|
24
|
+
"noPropertyAccessFromIndexSignature": false,
|
|
25
|
+
|
|
26
|
+
"types": ["bun-types"]
|
|
27
|
+
}
|
|
28
|
+
}
|