Skip to content

Commit

Permalink
refactor: split out a requests library
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Apr 15, 2024
1 parent bb19e9a commit 6df9d11
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 33 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-ties-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siafoundation/request': minor
---

Introduced a new request library for shared request and network code.
3 changes: 2 additions & 1 deletion libs/react-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"swr": "^2.1.1",
"axios": "^0.27.2",
"use-local-storage-state": "^18.3.3",
"@siafoundation/next": "^0.1.3"
"@siafoundation/next": "^0.1.3",
"@siafoundation/request": "0.0.0"
},
"dependencies": {
"detect-gpu": "^5.0.34"
Expand Down
28 changes: 1 addition & 27 deletions libs/react-core/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { AxiosRequestConfig, AxiosResponse, AxiosResponseHeaders } from 'axios'
import { MutatorCallback, MutatorOptions } from 'swr'
import { SWROptions } from './types'
import { AppSettings } from './useAppSettings'

export type RequestParams = Record<
string,
string | string[] | number | boolean
> | void
import { RequestParams, parameterizeRoute } from '@siafoundation/request'

export type RequestConfig<Payload, Result> = {
swr?: SWROptions<Result>
Expand Down Expand Up @@ -238,28 +234,6 @@ export function buildAxiosConfig<Params extends RequestParams, Payload, Result>(
} as AxiosRequestConfig<Payload>
}

function parameterizeRoute(
route: string | null,
params: RequestParams
): string | null {
if (route && params) {
const paramKeys = Object.keys(params)
for (const key of paramKeys) {
const value = String(params[key])
if (route.includes(`:${key}`)) {
route = route.replace(`:${key}`, value)
} else {
if (!route.includes('?')) {
route += `?${key}=${encodeURIComponent(value)}`
} else {
route += `&${key}=${encodeURIComponent(value)}`
}
}
}
}
return route
}

export function buildRouteWithParams<
Params extends RequestParams,
Payload,
Expand Down
2 changes: 1 addition & 1 deletion libs/react-core/src/useDelete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import {
buildRouteWithParams,
InternalCallbackArgs,
mergeInternalCallbackArgs,
RequestParams,
Response,
InternalHookArgsCallback,
mergeInternalHookArgsCallback,
After,
getPathFromKey,
} from './request'
import { useAppSettings } from './useAppSettings'
import { RequestParams } from '@siafoundation/request'

type DeleteFunc<Params extends RequestParams, Result> = {
delete: (
Expand Down
2 changes: 1 addition & 1 deletion libs/react-core/src/useGet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
buildRouteWithParams,
InternalCallbackArgs,
mergeInternalCallbackArgs,
RequestParams,
Response,
mergeInternalHookArgsCallback,
InternalHookArgsSwr,
Expand All @@ -18,6 +17,7 @@ import {
import { SWRError } from './types'
import { useAppSettings } from './useAppSettings'
import { keyOrNull } from './utils'
import { RequestParams } from '@siafoundation/request'

export function useGetSwr<Params extends RequestParams, Result>(
args: InternalHookArgsSwr<Params, Result>
Expand Down
2 changes: 1 addition & 1 deletion libs/react-core/src/usePatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
InternalCallbackArgs,
InternalHookArgsCallback,
mergeInternalCallbackArgs,
RequestParams,
Response,
mergeInternalHookArgsCallback,
getPathFromKey,
Expand All @@ -22,6 +21,7 @@ import { useAppSettings } from './useAppSettings'
import { useMemo } from 'react'
import { keyOrNull } from './utils'
import { SWRError } from './types'
import { RequestParams } from '@siafoundation/request'

export function usePatchSwr<Params extends RequestParams, Payload, Result>(
args: InternalHookArgsWithPayloadSwr<Params, Payload, Result>
Expand Down
2 changes: 1 addition & 1 deletion libs/react-core/src/usePost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
buildRouteWithParams,
InternalCallbackArgs,
mergeInternalCallbackArgs,
RequestParams,
Response,
InternalHookArgsCallback,
mergeInternalHookArgsCallback,
Expand All @@ -22,6 +21,7 @@ import { SWRError } from './types'
import { useAppSettings } from './useAppSettings'
import { keyOrNull } from './utils'
import { useWorkflows } from './workflows'
import { RequestParams } from '@siafoundation/request'

export function usePostSwr<Params extends RequestParams, Payload, Result>(
args: InternalHookArgsWithPayloadSwr<Params, Payload, Result>
Expand Down
2 changes: 1 addition & 1 deletion libs/react-core/src/usePut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
InternalCallbackArgs,
InternalHookArgsCallback,
mergeInternalCallbackArgs,
RequestParams,
Response,
mergeInternalHookArgsCallback,
getPathFromKey,
Expand All @@ -22,6 +21,7 @@ import { useAppSettings } from './useAppSettings'
import { useMemo } from 'react'
import { keyOrNull } from './utils'
import { SWRError } from './types'
import { RequestParams } from '@siafoundation/request'

export function usePutSwr<Params extends RequestParams, Payload, Result>(
args: InternalHookArgsWithPayloadSwr<Params, Payload, Result>
Expand Down
12 changes: 12 additions & 0 deletions libs/request/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
21 changes: 21 additions & 0 deletions libs/request/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"rules": {
"@nx/dependency-checks": [
"error",
{
"ignoredFiles": ["libs/request/rollup.config.js"]
}
]
},
"overrides": [
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}
3 changes: 3 additions & 0 deletions libs/request/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# request

Core library for building request APIs.
17 changes: 17 additions & 0 deletions libs/request/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable */
export default {
displayName: 'request',
preset: '../../jest.preset.js',
transform: {
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest',
'^.+\\.[tj]sx?$': [
'babel-jest',
{
presets: ['@nx/next/babel'],
plugins: ['@babel/plugin-transform-private-methods'],
},
],
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/request',
}
10 changes: 10 additions & 0 deletions libs/request/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@siafoundation/request",
"description": "Core library for building request APIs.",
"version": "0.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.27.2"
},
"types": "./src/index.d.ts"
}
42 changes: 42 additions & 0 deletions libs/request/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "request",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/request/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/request",
"tsConfig": "libs/request/tsconfig.lib.json",
"project": "libs/request/package.json",
"entryFile": "libs/request/src/index.ts",
"external": ["react/jsx-runtime"],
"compiler": "tsc",
"outputFileName": "index.js",
"rollupConfig": "libs/request/rollup.config.js",
"assets": [
{
"glob": "libs/request/*.md",
"input": ".",
"output": "."
}
]
},
"configurations": {}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"]
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/libs/request"],
"options": {
"jestConfig": "libs/request/jest.config.ts"
}
}
}
}
18 changes: 18 additions & 0 deletions libs/request/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const preserveDirectives = require('rollup-plugin-preserve-directives')

// https://github.com/rollup/rollup/issues/4699#issuecomment-1465302665
function getRollupOptions(options) {
return {
...options,
output: {
...options.output,
preserveModules: true,
format: 'esm',
sourcemap: true,
},
plugins: options.plugins.concat(preserveDirectives.default()),
}
}

module.exports = getRollupOptions
78 changes: 78 additions & 0 deletions libs/request/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Axios, AxiosRequestConfig, AxiosRequestHeaders } from 'axios'

export type RequestParams = Record<
string,
string | string[] | number | boolean
> | void

export function parameterizeRoute(
route: string | null,
params: RequestParams
): string | null {
if (route && params) {
const paramKeys = Object.keys(params)
for (const key of paramKeys) {
const value = String(params[key])
if (route.includes(`:${key}`)) {
route = route.replace(`:${key}`, value)
} else {
if (!route.includes('?')) {
route += `?${key}=${encodeURIComponent(value)}`
} else {
route += `&${key}=${encodeURIComponent(value)}`
}
}
}
}
return route
}

type Method = 'get' | 'post' | 'patch' | 'put' | 'delete'

export function buildRequestHandler<
Params = void,
Data = void,
Response = void
>(axios: Axios, method: Method, route: string) {
type Args = Params extends void
? Data extends void
? { config?: AxiosRequestConfig<Data> }
: { data: Data; config?: AxiosRequestConfig<Data> }
: Data extends void
? {
params: Params
config?: AxiosRequestConfig<Data>
}
: {
params: Params
data: Data
config?: AxiosRequestConfig<Data>
}

return (args: Args) => {
// args is sometimes undefined
const a = args || ({} as Args)
const paramRoute =
'params' in a
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
parameterizeRoute(route, a.params as RequestParams)!
: route

const data = 'data' in a ? a.data : undefined

return axios[method]<Response>(paramRoute, data, a?.config)
}
}

export function initAxios(api: string, password?: string): Axios {
const headers: AxiosRequestHeaders = {
'Content-Type': 'application/json',
}
if (password) {
headers['Authorization'] = `Basic ${btoa(`:${password}`)}`
}
return new Axios({
baseURL: api,
headers,
})
}
25 changes: 25 additions & 0 deletions libs/request/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
22 changes: 22 additions & 0 deletions libs/request/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts"
]
},
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
}
Loading

0 comments on commit 6df9d11

Please sign in to comment.