Skip to content

Commit 6a23b40

Browse files
committed
refactor: split out a requests library
1 parent a12625e commit 6a23b40

20 files changed

+281
-33
lines changed

.changeset/slow-ties-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@siafoundation/request': minor
3+
---
4+
5+
Introduced a new request library for shared request and network code.

libs/react-core/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"swr": "^2.1.1",
99
"axios": "^0.27.2",
1010
"use-local-storage-state": "^18.3.3",
11-
"@siafoundation/next": "^0.1.3"
11+
"@siafoundation/next": "^0.1.3",
12+
"@siafoundation/request": "0.0.0"
1213
},
1314
"dependencies": {
1415
"detect-gpu": "^5.0.34"

libs/react-core/src/request.ts

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ import { AxiosRequestConfig, AxiosResponse, AxiosResponseHeaders } from 'axios'
22
import { MutatorCallback, MutatorOptions } from 'swr'
33
import { SWROptions } from './types'
44
import { AppSettings } from './useAppSettings'
5-
6-
export type RequestParams = Record<
7-
string,
8-
string | string[] | number | boolean
9-
> | void
5+
import { RequestParams, parameterizeRoute } from '@siafoundation/request'
106

117
export type RequestConfig<Payload, Result> = {
128
swr?: SWROptions<Result>
@@ -238,28 +234,6 @@ export function buildAxiosConfig<Params extends RequestParams, Payload, Result>(
238234
} as AxiosRequestConfig<Payload>
239235
}
240236

241-
function parameterizeRoute(
242-
route: string | null,
243-
params: RequestParams
244-
): string | null {
245-
if (route && params) {
246-
const paramKeys = Object.keys(params)
247-
for (const key of paramKeys) {
248-
const value = String(params[key])
249-
if (route.includes(`:${key}`)) {
250-
route = route.replace(`:${key}`, value)
251-
} else {
252-
if (!route.includes('?')) {
253-
route += `?${key}=${encodeURIComponent(value)}`
254-
} else {
255-
route += `&${key}=${encodeURIComponent(value)}`
256-
}
257-
}
258-
}
259-
}
260-
return route
261-
}
262-
263237
export function buildRouteWithParams<
264238
Params extends RequestParams,
265239
Payload,

libs/react-core/src/useDelete.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import {
88
buildRouteWithParams,
99
InternalCallbackArgs,
1010
mergeInternalCallbackArgs,
11-
RequestParams,
1211
Response,
1312
InternalHookArgsCallback,
1413
mergeInternalHookArgsCallback,
1514
After,
1615
getPathFromKey,
1716
} from './request'
1817
import { useAppSettings } from './useAppSettings'
18+
import { RequestParams } from '@siafoundation/request'
1919

2020
type DeleteFunc<Params extends RequestParams, Result> = {
2121
delete: (

libs/react-core/src/useGet.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
buildRouteWithParams,
99
InternalCallbackArgs,
1010
mergeInternalCallbackArgs,
11-
RequestParams,
1211
Response,
1312
mergeInternalHookArgsCallback,
1413
InternalHookArgsSwr,
@@ -18,6 +17,7 @@ import {
1817
import { SWRError } from './types'
1918
import { useAppSettings } from './useAppSettings'
2019
import { keyOrNull } from './utils'
20+
import { RequestParams } from '@siafoundation/request'
2121

2222
export function useGetSwr<Params extends RequestParams, Result>(
2323
args: InternalHookArgsSwr<Params, Result>

libs/react-core/src/usePatch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
InternalCallbackArgs,
1010
InternalHookArgsCallback,
1111
mergeInternalCallbackArgs,
12-
RequestParams,
1312
Response,
1413
mergeInternalHookArgsCallback,
1514
getPathFromKey,
@@ -22,6 +21,7 @@ import { useAppSettings } from './useAppSettings'
2221
import { useMemo } from 'react'
2322
import { keyOrNull } from './utils'
2423
import { SWRError } from './types'
24+
import { RequestParams } from '@siafoundation/request'
2525

2626
export function usePatchSwr<Params extends RequestParams, Payload, Result>(
2727
args: InternalHookArgsWithPayloadSwr<Params, Payload, Result>

libs/react-core/src/usePost.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
buildRouteWithParams,
99
InternalCallbackArgs,
1010
mergeInternalCallbackArgs,
11-
RequestParams,
1211
Response,
1312
InternalHookArgsCallback,
1413
mergeInternalHookArgsCallback,
@@ -22,6 +21,7 @@ import { SWRError } from './types'
2221
import { useAppSettings } from './useAppSettings'
2322
import { keyOrNull } from './utils'
2423
import { useWorkflows } from './workflows'
24+
import { RequestParams } from '@siafoundation/request'
2525

2626
export function usePostSwr<Params extends RequestParams, Payload, Result>(
2727
args: InternalHookArgsWithPayloadSwr<Params, Payload, Result>

libs/react-core/src/usePut.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
InternalCallbackArgs,
1010
InternalHookArgsCallback,
1111
mergeInternalCallbackArgs,
12-
RequestParams,
1312
Response,
1413
mergeInternalHookArgsCallback,
1514
getPathFromKey,
@@ -22,6 +21,7 @@ import { useAppSettings } from './useAppSettings'
2221
import { useMemo } from 'react'
2322
import { keyOrNull } from './utils'
2423
import { SWRError } from './types'
24+
import { RequestParams } from '@siafoundation/request'
2525

2626
export function usePutSwr<Params extends RequestParams, Payload, Result>(
2727
args: InternalHookArgsWithPayloadSwr<Params, Payload, Result>

libs/request/.babelrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"presets": [
3+
[
4+
"@nx/react/babel",
5+
{
6+
"runtime": "automatic",
7+
"useBuiltIns": "usage"
8+
}
9+
]
10+
],
11+
"plugins": []
12+
}

libs/request/.eslintrc.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"rules": {
5+
"@nx/dependency-checks": [
6+
"error",
7+
{
8+
"ignoredFiles": ["libs/request/rollup.config.js"]
9+
}
10+
]
11+
},
12+
"overrides": [
13+
{
14+
"files": ["*.json"],
15+
"parser": "jsonc-eslint-parser",
16+
"rules": {
17+
"@nx/dependency-checks": "error"
18+
}
19+
}
20+
]
21+
}

libs/request/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# request
2+
3+
Core library for building request APIs.

libs/request/jest.config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'request',
4+
preset: '../../jest.preset.js',
5+
transform: {
6+
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest',
7+
'^.+\\.[tj]sx?$': [
8+
'babel-jest',
9+
{
10+
presets: ['@nx/next/babel'],
11+
plugins: ['@babel/plugin-transform-private-methods'],
12+
},
13+
],
14+
},
15+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
16+
coverageDirectory: '../../coverage/libs/request',
17+
}

libs/request/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@siafoundation/request",
3+
"description": "Core library for building request APIs.",
4+
"version": "0.0.0",
5+
"license": "MIT",
6+
"dependencies": {
7+
"axios": "^0.27.2"
8+
},
9+
"types": "./src/index.d.ts"
10+
}

libs/request/project.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "request",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/request/src",
5+
"projectType": "library",
6+
"tags": [],
7+
"targets": {
8+
"build": {
9+
"executor": "@nx/rollup:rollup",
10+
"outputs": ["{options.outputPath}"],
11+
"options": {
12+
"outputPath": "dist/libs/request",
13+
"tsConfig": "libs/request/tsconfig.lib.json",
14+
"project": "libs/request/package.json",
15+
"entryFile": "libs/request/src/index.ts",
16+
"external": ["react/jsx-runtime"],
17+
"compiler": "tsc",
18+
"outputFileName": "index.js",
19+
"rollupConfig": "libs/request/rollup.config.js",
20+
"assets": [
21+
{
22+
"glob": "libs/request/*.md",
23+
"input": ".",
24+
"output": "."
25+
}
26+
]
27+
},
28+
"configurations": {}
29+
},
30+
"lint": {
31+
"executor": "@nx/eslint:lint",
32+
"outputs": ["{options.outputFile}"]
33+
},
34+
"test": {
35+
"executor": "@nx/jest:jest",
36+
"outputs": ["{workspaceRoot}/coverage/libs/request"],
37+
"options": {
38+
"jestConfig": "libs/request/jest.config.ts"
39+
}
40+
}
41+
}
42+
}

libs/request/rollup.config.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// eslint-disable-next-line @typescript-eslint/no-var-requires
2+
const preserveDirectives = require('rollup-plugin-preserve-directives')
3+
4+
// https://github.com/rollup/rollup/issues/4699#issuecomment-1465302665
5+
function getRollupOptions(options) {
6+
return {
7+
...options,
8+
output: {
9+
...options.output,
10+
preserveModules: true,
11+
format: 'esm',
12+
sourcemap: true,
13+
},
14+
plugins: options.plugins.concat(preserveDirectives.default()),
15+
}
16+
}
17+
18+
module.exports = getRollupOptions

libs/request/src/index.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Axios, AxiosRequestConfig, AxiosRequestHeaders } from 'axios'
2+
3+
export type RequestParams = Record<
4+
string,
5+
string | string[] | number | boolean
6+
> | void
7+
8+
export function parameterizeRoute(
9+
route: string | null,
10+
params: RequestParams
11+
): string | null {
12+
if (route && params) {
13+
const paramKeys = Object.keys(params)
14+
for (const key of paramKeys) {
15+
const value = String(params[key])
16+
if (route.includes(`:${key}`)) {
17+
route = route.replace(`:${key}`, value)
18+
} else {
19+
if (!route.includes('?')) {
20+
route += `?${key}=${encodeURIComponent(value)}`
21+
} else {
22+
route += `&${key}=${encodeURIComponent(value)}`
23+
}
24+
}
25+
}
26+
}
27+
return route
28+
}
29+
30+
type Method = 'get' | 'post' | 'patch' | 'put' | 'delete'
31+
32+
export function buildRequestHandler<
33+
Params = void,
34+
Data = void,
35+
Response = void
36+
>(axios: Axios, method: Method, route: string) {
37+
type Args = Params extends void
38+
? Data extends void
39+
? { config?: AxiosRequestConfig<Data> }
40+
: { data: Data; config?: AxiosRequestConfig<Data> }
41+
: Data extends void
42+
? {
43+
params: Params
44+
config?: AxiosRequestConfig<Data>
45+
}
46+
: {
47+
params: Params
48+
data: Data
49+
config?: AxiosRequestConfig<Data>
50+
}
51+
52+
return (args: Args) => {
53+
// args is sometimes undefined
54+
const a = args || ({} as Args)
55+
const paramRoute =
56+
'params' in a
57+
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
58+
parameterizeRoute(route, a.params as RequestParams)!
59+
: route
60+
61+
const data = 'data' in a ? a.data : undefined
62+
63+
return axios[method]<Response>(paramRoute, data, a?.config)
64+
}
65+
}
66+
67+
export function initAxios(api: string, password?: string): Axios {
68+
const headers: AxiosRequestHeaders = {
69+
'Content-Type': 'application/json',
70+
}
71+
if (password) {
72+
headers['Authorization'] = `Basic ${btoa(`:${password}`)}`
73+
}
74+
return new Axios({
75+
baseURL: api,
76+
headers,
77+
})
78+
}

libs/request/tsconfig.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"jsx": "react-jsx",
5+
"allowJs": true,
6+
"esModuleInterop": true,
7+
"allowSyntheticDefaultImports": true,
8+
"forceConsistentCasingInFileNames": true,
9+
"strict": true,
10+
"noImplicitOverride": true,
11+
"noPropertyAccessFromIndexSignature": true,
12+
"noImplicitReturns": true,
13+
"noFallthroughCasesInSwitch": true
14+
},
15+
"files": [],
16+
"include": [],
17+
"references": [
18+
{
19+
"path": "./tsconfig.lib.json"
20+
},
21+
{
22+
"path": "./tsconfig.spec.json"
23+
}
24+
]
25+
}

libs/request/tsconfig.lib.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/out-tsc",
5+
"types": [
6+
"node",
7+
"@nx/react/typings/cssmodule.d.ts",
8+
"@nx/react/typings/image.d.ts"
9+
]
10+
},
11+
"exclude": [
12+
"**/*.spec.ts",
13+
"**/*.test.ts",
14+
"**/*.spec.tsx",
15+
"**/*.test.tsx",
16+
"**/*.spec.js",
17+
"**/*.test.js",
18+
"**/*.spec.jsx",
19+
"**/*.test.jsx"
20+
],
21+
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
22+
}

0 commit comments

Comments
 (0)