@lovrabet/fetch
v1.0.11
Published
Lovrabet fetch sdk
Keywords
Readme
fetch
云兔前端请求库 - 基于现代标准构建的轻量级 HTTP 客户端
特性
- 🚀 轻量级,零依赖
- 📦 完整的 TypeScript 支持
- 📊 内置表格数据类型支持
- 🎯 简洁的 API 设计
安装
pnpm add @lovrabet/fetch快速开始
import { LovrabetFetch } from "@lovrabet/fetch";
// 创建实例
const fetcher = new LovrabetFetch();
// 发送 POST 请求
const result = await fetcher.post("/api/getList", {
currentPage: 1,
pageSize: 20,
});
// 发送 GET 请求
const data = await fetcher.get("/api/getOne", { id: 1 });语言 Header(x-hng)
get/post 会自动尝试携带 x-hng 请求头:
x-hng: lang=zh-CN&domain=a.lovrabet.com优先级如下:
- 调用请求时显式传入的
x-hng init.reqHeaders中的x-hng- 浏览器环境自动生成(语言 + 当前域名)
浏览器自动生成时,语言来源优先级:
- 通过
setYTFetchLangProvider设置的 provider
可以通过导出的 API 设置 provider:
import { setYTFetchLangProvider } from "@lovrabet/fetch";
setYTFetchLangProvider(() => "zh-CN");在外部需要直接复用 x-hng header 时,可使用:
import { getXHngHeader } from "@lovrabet/fetch";
// 返回 { "x-hng": "lang=zh-CN&domain=a.lovrabet.com" } 或 {}
const headers = {
...getXHngHeader(),
"Content-Type": "application/json",
};Rabetbase 配置解析(.rabetbase.json)
构建脚本(如 vite.config.ts)常需要从 .rabetbase.json 读取应用与地区信息。本库提供一组纯函数,不读取文件,只解析传入的配置对象:
import {
loadRabetbaseConfig,
getRabetbaseAppCode,
getRabetbaseRegion,
getCdnBase,
getRabetbaseCdnBase,
REGION_BASE_DOMAINS,
} from "@lovrabet/fetch";
// Node / Bun 环境可直接读取当前项目配置:
// 从 cwd 逐级向上查找 .rabetbase.json,未显式配置 region 时从全局 ~/.rabetbase.json 继承
const config = await loadRabetbaseConfig();
// 解析 App Code:defaultApp 指向的 profile 的 appcode;
// 单 profile 时可省略 defaultApp,自动选中
const appCode = getRabetbaseAppCode(config);
// 解析 region(缺省 cn),非法值抛错
const region = getRabetbaseRegion(config); // "cn" | "id"
// region 对应的 CDN 公开访问 origin
getCdnBase(region); // https://g.lovrabet.com 或 https://g.lovrabet.id
getRabetbaseCdnBase(config); // 同上,直接从配置解析loadRabetbaseConfig 依赖文件系统,只能在 Node / Bun 环境使用;浏览器环境请显式传入配置对象。所有 get* 函数均为纯函数,不读取文件。
REGION_BASE_DOMAINS 提供 region 到站点根域名的映射(cn → lovrabet.com、id → lovrabet.id)。
getRegionDomains(region) 在此基础上推导官方站点域名集合,构建脚本可据此生成项目路由,无需为每个官方 region 维护配置文件:
import { getRegionDomains } from "@lovrabet/fetch";
getRegionDomains("id");
// {
// baseDomain: "lovrabet.id",
// cdn: "https://g.lovrabet.id",
// user: "https://user.lovrabet.id",
// app: "https://app.lovrabet.id",
// runtime: "https://runtime.lovrabet.id",
// api: "https://api.lovrabet.id",
// dev: "https://dev.lovrabet.id",
// devCertificateUrl: "https://g.lovrabet.id/cert/lovrabet-dev.json",
// }该函数是纯函数,不读取文件、环境变量或 location,只返回生产环境 origin;daily 与浏览器运行期解析请继续使用 getApiPrefix / getRuntimeApiPrefix / getUserApiPrefix / getBaseDomain。
环境判定(hostname)
getEnv / getNormalizedEnv 在浏览器里直接读 location.hostname,无法注入 hostname,也就不便单测。getEnvFromHostname(hostname) 把同一套规则抽成纯函数,规则由 KNOWN_BASE_DOMAINS 驱动,因此对全部官方区域一致:
import { getEnvFromHostname } from "@lovrabet/fetch";
getEnvFromHostname("dev.lovrabet.id"); // "local"
getEnvFromHostname("web-admin.daily.lovrabet.com"); // "daily"
getEnvFromHostname("web-admin-daily.lovrabet.id"); // "daily"
getEnvFromHostname("web-admin.lovrabet.id"); // undefined(无法判定,调用方自行回退生产)getEnv() 内部复用该函数,行为不变:Node 环境按 NODE_ENV,浏览器先看 window.__GLOBAL__.ENV,再看 hostname,最后回退 online。
CDN 产物上传(仅 Node / Bun)
lovrabetCdnUpload 将本地构建产物上传到 Lovrabet CDN(pan 发布服务):遍历目录 → 计算并归一化发布 key → 校验 dist/<project>/<version>/<path> 或 app/<appcode>/assets/<version>/<path> → 分批请求预签名地址 → 并发直传对象存储。
发布 key 与 pan Go CLI(yt upload)规则对齐:key = 上传根目录前缀(相对 cwd,如 ./dist → dist;上传 cwd 本身时为空;cwd 之外退化为目录名)+ 相对路径,随后归一化——已合法的 dist/... / app/... 原样保留;否则剥离开头多余路径段,暴露首个合法的 app/<appcode>/... 发布根(如 dist/app/<appcode>/assets/<version>/x.js → app/<appcode>/assets/<version>/x.js)。因此 dist/<project>/<version>/ 布局直接 --dir dist 即可,无需再嵌套一层目录。
import { lovrabetCdnUpload } from "@lovrabet/fetch";
const { uploaded, urls } = await lovrabetCdnUpload({
dir: "dist", // 默认 dist
region: "cn", // 缺省 cn,决定 pan 服务与 CDN 地址
apiKey: "<publish-api-key>", // 缺省不携带鉴权头
});| 选项 | 默认值 | 说明 |
|-|-|-|
| dir | "dist" | 待上传的本地产物目录 |
| region | "cn" | cn / id,pan 服务地址按此推导 |
| server | 无 | pan API 服务地址覆盖(本地调试用),缺省按 region 推导 |
| apiKey | 无 | 发布 API Key,缺省不携带鉴权头 |
| batchSize | 500 | 每批预签名文件数 |
| workers | 8 | 并发上传数 |
| log | true | 是否打印进度日志 |
该函数依赖文件系统与网络直传,只能在 Node / Bun 环境使用;浏览器环境调用会抛出错误。所有配置通过参数显式传入,不读取环境变量。
安装后也可直接使用命令行工具(支持 --dir/--region/--server/--no-log):
lovrabet-cdn-upload
lovrabet-cdn-upload --dir dist --region cn
lovrabet-cdn-upload --dir dist --server http://127.0.0.1:8080 # 本地调试子路径按需引入
构建产物提供多个入口,支持 exports 子路径解析(moduleResolution: bundler / node16+)的环境可按需引入,避免拉入不需要的模块:
// 全量入口
import { LovrabetFetch, lovrabetCdnUpload } from "@lovrabet/fetch";
// 仅 CDN 上传(Node / Bun)
import { lovrabetCdnUpload } from "@lovrabet/fetch/cdn-upload";
// 仅 .rabetbase.json 配置解析
import { loadRabetbaseConfig } from "@lovrabet/fetch/rabetbase-config";moduleResolution: node(node10)的环境请继续使用根入口 @lovrabet/fetch。
API 文档
构造函数选项
interface LovrabetFetchOptions {
// 该实例的请求 origin。新应用应从项目路由快照解析后显式传入。
// 不传时保留历史自动解析行为,已解析值可通过只读的
// `instance.baseURL` 读取。
baseURL?: string;
// 实例级 credentials 配置
credentials?: RequestCredentials;
}credentials 的优先级:单次请求传入 > 实例配置 > 默认行为(已知站点域名 lovrabet.com / lovrabet.id 强制 "include",其余域名不设置)。
// 实例级:该实例所有请求使用 same-origin
const fetcher = new LovrabetFetch({ credentials: "same-origin" });
// 请求级:覆盖实例配置与已知域名的默认 include
await fetcher.get("/api/getOne", { id: 1 }, { credentials: "omit" });请求方法
get(url, params?)- GET 请求post(url, data?)- POST 请求
类型定义
基础响应类型
import type { IResponse } from "@lovrabet/fetch";
interface IResponse<T = any> {
data: T;
code: number;
message: string;
}表格响应类型
import type { ITableResponse } from "@lovrabet/fetch";
interface ITableResponse<ListItem = any> {
tableData: ListItem[];
paging: {
/**
* 当前页码
*/
currentPage: number;
/**
* 总页数
*/
totalCount: number;
/**
* 每页条数
*/
pageSize: number;
};
tableColumns: Record<string, unknown>[];
}使用示例
处理表格数据
import type { ITableResponse } from "@lovrabet/fetch";
interface User {
id: number;
name: string;
email: string;
}
const data = await fetcher.post<ITableResponse<User>>("api/users", {
currentPage: 1,
pageSize: 10,
});
console.log(data.tableData); // User[]
console.log(data.paging.totalCount); // number错误处理
try {
const data = await fetcher.get("/api/data");
console.log(data);
} catch (error) {
console.error("请求失败:", error);
}开发
安装依赖
bun install运行示例
bun run index.ts构建
bun run build测试
bun test路线图
- [ ] 内置埋点功能
- [ ] 缓存机制
- [ ] 重试机制
- [ ] 取消请求功能
