Skip to content

@bubblesjs/request ​

@bubblesjs/request is a small Alova-based request wrapper. It centralizes common headers, response transformation, business-code checks, message hooks, cache adapters, and per-request behavior switches.

Installation ​

bash
pnpm add @bubblesjs/request alova
bash
npm install @bubblesjs/request alova
bash
yarn add @bubblesjs/request alova
bash
bun add @bubblesjs/request alova

Quick Start ​

ts
import { createInstance } from '@bubblesjs/request'

const request = createInstance({
  baseUrl: '/api',
  commonHeaders: {
    'Content-Type': 'application/json',
    Authorization: async () => `Bearer ${await getToken()}`,
  },
  successMessageFunc: (message) => toast.success(message),
  errorMessageFunc: (message) => toast.error(message),
  unAuthorizedResponseFunc: () => router.push('/login'),
})

const user = await request.Get('/user/info')
const result = await request.Post('/user/update', {
  body: { name: 'John' },
})

By default, a successful wrapped response is expected to look like this:

ts
{
  code: 200,
  data: { id: 1 },
  message: 'ok'
}

The returned value is the field configured by responseDataKey, so the example above resolves to { id: 1 }.

Dual Call Instance ​

createDualCallInstance returns a default Alova instance that can also be called as a function to create a temporary instance with merged options.

ts
import { createDualCallInstance } from '@bubblesjs/request'

const request = createDualCallInstance({
  baseUrl: '/api',
  isShowSuccessMessage: false,
  errorMessageFunc: (message) => toast.error(message),
})

await request.Get('/user/profile')

await request({
  isShowSuccessMessage: true,
  successMessageFunc: (message) => toast.success(message),
}).Post('/user/create', {
  body: { name: 'Jane' },
})

Configuration ​

OptionTypeDefaultDescription
baseUrlstring'/'Base URL passed to Alova as baseURL.
timeoutnumberundefinedRequest timeout.
commonHeadersRecord<string, HeaderValue>{}Common headers. Values can be static or async functions.
statusMapStatusMap{ success: 200, unAuthorized: 401 }HTTP status matchers.
codeMapCodeMap{ success: [200], unAuthorized: [401] }Business-code matchers.
responseCodeKeystring'code'Business-code field in wrapped responses.
responseDataKeystring'data'Data field in wrapped responses.
responseMessageKeystring'message'Message field in wrapped responses.
isWrappedbooleantrueWhether the response uses { code, data, message } style wrapping.
isTransformResponsebooleantrueWhether to transform responses in responded.onSuccess.
isShowSuccessMessagebooleanfalseWhether to call successMessageFunc after business success.
successDefaultMessagestring'操作成功'Fallback success message.
isShowErrorMessagebooleantrueWhether to call errorMessageFunc on HTTP, business, or network errors.
errorDefaultMessagestring'服务异常'Fallback error message.
successMessageFunc(message: string) => voidundefinedSuccess message hook.
errorMessageFunc(message: string) => voidundefinedError message hook.
unAuthorizedResponseFunc() => voidundefinedCalled for unauthorized HTTP status or business code.
statesHookStatesHookundefinedAlova state hook for React, Vue, and other integrations.
requestAdapterAlovaRequestAdapteradapterFetch()Alova request adapter.
cacheForGlobalCacheConfig | nullnullAlova global cache config.
cacheLoggerbooleantrueAlova cache logging switch.
l1CacheAlovaGlobalCacheAdapterundefinedAlova L1 cache adapter.
l2CacheAlovaGlobalCacheAdapterundefinedAlova L2 cache adapter.
storageAdapterAlovaGlobalCacheAdapterundefinedBackward-compatible alias for l2Cache.

Matching Rules ​

statusMap.success and statusMap.unAuthorized accept a number, an array of numbers, or a function:

ts
const request = createInstance({
  statusMap: {
    success: [200, 201, 204],
    unAuthorized: (status) => status === 401 || status === 419,
  },
})

codeMap.success and codeMap.unAuthorized accept arrays of numbers or strings:

ts
const request = createInstance({
  responseCodeKey: 'status',
  responseMessageKey: 'msg',
  codeMap: {
    success: [0, 'OK'],
    unAuthorized: [401, 'TOKEN_EXPIRED'],
  },
})

Per-Request Meta ​

The following options can be overridden on a single request through meta:

  • isWrapped
  • isTransformResponse
  • isShowSuccessMessage
  • isShowErrorMessage
ts
const rawResponse = await request.Get('/download/file', {
  meta: {
    isTransformResponse: false,
    isShowErrorMessage: false,
  },
})

const rawUploadData = await request.Post('/upload', {
  body: formData,
  meta: {
    isWrapped: false,
  },
})

Response Shapes ​

The default fetch adapter returns a Response, which is parsed according to the content-type header. JSON responses are read with json(), text responses are read with text(), and JSON strings are parsed when possible.

Axios-style and Taro-style responses are also supported:

ts
// Axios-style
{
  status: 200,
  data: { code: 200, data: [], message: 'loaded' }
}

// Taro-style
{
  statusCode: 200,
  data: { code: 200, data: { ok: true }, msg: 'done' }
}

For Taro upload APIs that return data as a JSON string, the string is parsed before codeMap and responseDataKey are applied.

Custom Adapter ​

Any Alova request adapter can be passed through requestAdapter. If the adapter also exposes a cache adapter, pass it as l2Cache or storageAdapter.

ts
import { createInstance } from '@bubblesjs/request'
import { adapterTaro } from '@alova/adapter-taro'

const taroAdapter = adapterTaro()

const request = createInstance({
  baseUrl: '/api',
  requestAdapter: taroAdapter.requestAdapter,
  storageAdapter: taroAdapter.storageAdapter,
  responseMessageKey: 'msg',
})

Types ​

ts
type MaybePromise<T> = T | Promise<T>

type HeaderValue =
  | string
  | number
  | boolean
  | null
  | undefined
  | (() => MaybePromise<string | number | boolean | null | undefined>)

type StatusMatcher<RE> = number | number[] | ((status: number, response: RE) => boolean)

type CodeMatcher = Array<number | string>

interface StatusMap<RE = unknown> {
  success?: StatusMatcher<RE>
  unAuthorized?: StatusMatcher<RE>
}

interface CodeMap {
  success?: CodeMatcher
  unAuthorized?: CodeMatcher
}

interface RequestMeta {
  isWrapped?: boolean
  isTransformResponse?: boolean
  isShowSuccessMessage?: boolean
  isShowErrorMessage?: boolean
}

Released under the MIT License