Skip to content

Repository files navigation

@cc-heart/utils

Docs

A library of JavaScript tools

Install

npm install @cc-heart/utils

Usage

import{capitalize}from'@cc-heart/utils'capitalize('string')// String

Request — composable best practices

import{Request}from'@cc-heart/utils'importtype{RequestInterceptor}from'@cc-heart/utils'

Principle: small instances + composition

Prefer small focused instances over one instance with all interceptors. Combine them with factory functions:

// ── Building blocks: interceptors are pure functions ──constaddAuth: RequestInterceptor=(config)=>({
...config,headers: { ...config.headers,Authorization: `Bearer ${getToken()}`}})constaddLang: RequestInterceptor=(config)=>({
...config,headers: { ...config.headers,'Accept-Language': 'zh-CN'}})consthandleError=(err: unknown)=>{toast.error(err)returnerr}// ── Compose: each instance handles one concern ──constauthApi=newRequest('https://api.example.com')authApi.useRequestInterceptor(addAuth)authApi.useRequestInterceptor(addLang)authApi.useErrorInterceptor(handleError)constpublicApi=newRequest('https://open.api.com')// ── Or use helper functions ──functionwithInterceptors(req: Request,interceptors: RequestInterceptor[]): Request{interceptors.forEach((i)=>req.useRequestInterceptor(i))returnreq}functionwithBaseUrl(url: string): Request{returnnewRequest(url)}constapi=withInterceptors(withBaseUrl('https://api.example.com'),[addAuth,addLang,])

Four calling styles

constapi=newRequest('https://api.example.com')// Style 1: async/await (recommended)try{constuser=awaitapi.get<User>('/users/1')setUser(user)}catch(e){if((easError).name==='AbortError')return// user cancelledtoast.error(e)}// Style 2: lifecycle callbacks (React setState friendly)api.get('/users',{onSuccess: setUsers,onError: toast.error,onFinally: ()=>setLoading(false),})// Style 3: promise chainingapi.get<number>('/count').then(n=>n*2).then(setCount).catch(toast.error)// Style 4: mixed (await + callbacks, non-conflicting)constdata=awaitapi.get('/users',{onFinally: ()=>setLoading(false)})

Entity — group by domain

// entities/user.tsconstapi=newRequest('/api')exportconstUserApi={list: (page: number)=>api.get<User[]>('/users',{ page }),get: (id: number)=>api.get<User>(`/users/${id}`),create: (data: CreateUserDto)=>api.post<User>('/users',data,{onSuccess: ()=>toast.success('created')}),}// Usageconstusers=awaitUserApi.list(1)

Cache & dedup — isolated per instance

constcachedApi=newRequest('/api')// cache and dedup are instance-level, different Request instances are isolatedconstdata1=awaitcachedApi.get('/users',{},{cache: {ttl: 5000}})constdata2=awaitcachedApi.get('/users',{},{cache: {ttl: 5000}})// cache hitconstotherApi=newRequest('/api')// isolated cache

SSE (Server-Sent Events)

Supports SSE streaming requests, built on Fetch API with these advantages over native EventSource:

  • ✅ Custom Headers support
  • ✅ POST requests support
  • ✅ All HTTP methods supported

Basic usage

import{Request}from'@cc-heart/utils'constapi=newRequest('https://api.example.com')// GET SSEconsthandle=api.sse('/events',{onMessage(event){console.log('Received:',event.data)},onOpen(){console.log('Connection opened')},onError(error){console.error('Connection error:',error)},onClose(){console.log('Connection closed')}})// Cancel connectionhandle.abort()

POST SSE (e.g., AI streaming chat)

consthandle=api.sse('/chat/completions',{method: 'POST',data: {prompt: 'Hello',model: 'gpt-4'},onMessage(event){// Parse JSON datatry{constdata=JSON.parse(event.data)console.log('AI reply:',data.content)}catch{console.log('Raw data:',event.data)}},onError(err){console.error('Request failed:',err)}})

With interceptors

importtype{RequestInterceptor}from'@cc-heart/utils'constaddAuth: RequestInterceptor=(config)=>({
...config,headers: {
...config.headers,Authorization: `Bearer ${getToken()}`}})constapi=newRequest('https://api.example.com')api.useRequestInterceptor(addAuth)// SSE requests automatically include interceptor headersconsthandle=api.sse('/protected/events',{onMessage(event){console.log(event.data)}})

SSE Type definitions

interfaceSSEMessageEvent{event?: string// Event typedata: string// Message dataid?: string// Last event IDretry?: number// Retry interval (ms)}interfaceSSECallbacks{onMessage?: (event: SSEMessageEvent)=>voidonOpen?: ()=>voidonError?: (error: unknown)=>voidonClose?: ()=>void}

LICENSE

@cc-heart/utils is licensed under the MIT License.

About

a javascript library

Topics

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages