From 3dce0b56f31adab1a24f234056e6f8bb24849ebb Mon Sep 17 00:00:00 2001 From: Alex Freska Date: Mon, 15 Apr 2024 10:19:15 -0400 Subject: [PATCH] refactor: split out a requests library --- libs/react-core/src/request.ts | 28 +------------- libs/request/.babelrc | 12 ++++++ libs/request/.eslintrc.json | 21 +++++++++++ libs/request/README.md | 3 ++ libs/request/jest.config.ts | 17 +++++++++ libs/request/package.json | 10 +++++ libs/request/project.json | 42 +++++++++++++++++++++ libs/request/rollup.config.js | 18 +++++++++ libs/request/src/index.ts | 67 +++++++++++++++++++++++++++++++++ libs/request/tsconfig.json | 25 ++++++++++++ libs/request/tsconfig.lib.json | 22 +++++++++++ libs/request/tsconfig.spec.json | 19 ++++++++++ tsconfig.base.json | 1 + 13 files changed, 258 insertions(+), 27 deletions(-) create mode 100644 libs/request/.babelrc create mode 100644 libs/request/.eslintrc.json create mode 100644 libs/request/README.md create mode 100644 libs/request/jest.config.ts create mode 100644 libs/request/package.json create mode 100644 libs/request/project.json create mode 100644 libs/request/rollup.config.js create mode 100644 libs/request/src/index.ts create mode 100644 libs/request/tsconfig.json create mode 100644 libs/request/tsconfig.lib.json create mode 100644 libs/request/tsconfig.spec.json diff --git a/libs/react-core/src/request.ts b/libs/react-core/src/request.ts index 6caf008e1..12de715fc 100644 --- a/libs/react-core/src/request.ts +++ b/libs/react-core/src/request.ts @@ -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 = { swr?: SWROptions @@ -238,28 +234,6 @@ export function buildAxiosConfig( } as AxiosRequestConfig } -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, diff --git a/libs/request/.babelrc b/libs/request/.babelrc new file mode 100644 index 000000000..1ea870ead --- /dev/null +++ b/libs/request/.babelrc @@ -0,0 +1,12 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [] +} diff --git a/libs/request/.eslintrc.json b/libs/request/.eslintrc.json new file mode 100644 index 000000000..ceb87bdfb --- /dev/null +++ b/libs/request/.eslintrc.json @@ -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" + } + } + ] +} diff --git a/libs/request/README.md b/libs/request/README.md new file mode 100644 index 000000000..870c5bb82 --- /dev/null +++ b/libs/request/README.md @@ -0,0 +1,3 @@ +# request + +Core library for building request APIs. diff --git a/libs/request/jest.config.ts b/libs/request/jest.config.ts new file mode 100644 index 000000000..70be72b6f --- /dev/null +++ b/libs/request/jest.config.ts @@ -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', +} diff --git a/libs/request/package.json b/libs/request/package.json new file mode 100644 index 000000000..8b6dc9395 --- /dev/null +++ b/libs/request/package.json @@ -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" +} diff --git a/libs/request/project.json b/libs/request/project.json new file mode 100644 index 000000000..041e7ff61 --- /dev/null +++ b/libs/request/project.json @@ -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" + } + } + } +} diff --git a/libs/request/rollup.config.js b/libs/request/rollup.config.js new file mode 100644 index 000000000..3f5e4e997 --- /dev/null +++ b/libs/request/rollup.config.js @@ -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 diff --git a/libs/request/src/index.ts b/libs/request/src/index.ts new file mode 100644 index 000000000..74554ed68 --- /dev/null +++ b/libs/request/src/index.ts @@ -0,0 +1,67 @@ +import { Axios } 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 +} + +export function buildRequestHandler< + Params = void, + Payload = void, + Response = void +>( + axios: Axios, + method: 'get' | 'post' | 'patch' | 'put' | 'delete', + route: string +) { + type ParamsArg = Params extends void + ? Record + : { params: Params } + type PayloadArg = Payload extends void + ? Record + : { payload: Payload } + + return ( + ...args: Params extends void + ? Payload extends void + ? [] + : [PayloadArg] + : [ + ParamsArg & + (Payload extends void + ? Record + : { payload?: Payload }) + ] + ) => { + const arg = args[0] || {} + const paramRoute = + 'params' in arg + ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + parameterizeRoute(route, arg.params as RequestParams)! + : route + const payload = 'payload' in arg ? arg.payload : undefined + return axios[method](paramRoute, payload) + } +} diff --git a/libs/request/tsconfig.json b/libs/request/tsconfig.json new file mode 100644 index 000000000..4c089585e --- /dev/null +++ b/libs/request/tsconfig.json @@ -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" + } + ] +} diff --git a/libs/request/tsconfig.lib.json b/libs/request/tsconfig.lib.json new file mode 100644 index 000000000..d73537814 --- /dev/null +++ b/libs/request/tsconfig.lib.json @@ -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"] +} diff --git a/libs/request/tsconfig.spec.json b/libs/request/tsconfig.spec.json new file mode 100644 index 000000000..503e9a83d --- /dev/null +++ b/libs/request/tsconfig.spec.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index b78eaf5e7..83f3665b6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -15,6 +15,7 @@ "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { + "@siafoundation/request": ["libs/request/src/index.ts"], "@siafoundation/data-sources": ["libs/data-sources/src/index.ts"], "@siafoundation/design-system": ["libs/design-system/src/index.ts"], "@siafoundation/fonts": ["libs/fonts/src/index.ts"],