npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fefeding/common

v1.0.74

Published

models utils

Readme

@fefeding/common

npm version License: MIT

通用工具库,提供数据模型、HTTP 请求封装、API Token 生成、装饰器、远程日志、腾讯云 COS 操作、随机字符串等常用功能。

目录

安装

npm install @fefeding/common
# 或
pnpm add @fefeding/common

使用方式

本库通过 默认导出 暴露一个按源码目录结构组织的命名空间对象,所有 API 都挂在 Common.utils.*Common.models.* 下:

// ESM
import Common from '@fefeding/common';

// CommonJS
const Common = require('@fefeding/common');

访问规则:

  • export function / export const / export class 形式导出的成员,可直接从命名空间解构。
  • export default 形式导出的模块(如 apidecoratorlogger、各默认导出模型),需通过 .default 获取。
// utils —— 命名导出直接解构
const { requestApi, requestServer } = Common.utils.axios;
const { randString, stringToNumber } = Common.utils.rand;
const {
  createClient, uploadFile, putObject, getFile, getObjectUrl, checkExists
} = Common.utils.s3;

// utils —— 默认导出模块取 .default
const decorators      = Common.utils.decorator.default;
const api             = Common.utils.api.default;
const RemotePinoLogger = Common.utils.logger.default;

// models —— 默认导出取 .default,命名导出直接取
const Account          = Common.models.account.account.default;
const { User, EGender } = Common.models.account.user;
const { Session, LoginByCodeReq } = Common.models.account.session;

工具类 (utils)

HTTP 请求 (axios)

对 Axios 的封装,支持直接传入请求 URL,或传入带有 @api 装饰器的请求模型(自动解析装饰器中定义的 URL)。

| 导出 | 说明 | |------|------| | requestServer(url, option?) | 发送请求,返回完整的 Axios 响应对象(AxiosResponse)。url 可为字符串或请求模型对象。 | | requestApi(url, option?) | 等价于 requestServer,但只返回响应体 res.data(无数据时返回 null)。 | | default | 原始 axios 实例,可直接使用。 |

import Common from '@fefeding/common';
const { requestApi, requestServer } = Common.utils.axios;

// 直接传入 URL
const data = await requestApi('/api/user/info', { method: 'GET' });

// 传入带 @api 装饰器的请求模型,自动解析 URL
const res = await requestApi(
  new Common.models.account.user.QuerUserReq({ name: 'Tom' })
);

装饰器 (decorator)

基于 reflect-metadata 的装饰器,用于 API 路由映射与权限标记。

| 导出 | 说明 | |------|------| | api(options) | 类装饰器,标记类的 API 路由配置(如 { url })。 | | getApi(target) | 获取类/实例的 API 配置。 | | checkApiToken(isCheck = true) | 方法装饰器,标记接口需要 Token 校验。 | | getApiToken(target, key) | 获取方法是否设置了 Token 校验。 | | checkApiLogin(isCheck = true) | 方法装饰器,标记接口需要登录态校验。 | | getApiLogin(target, key) | 获取方法是否设置了登录态校验。 | | req(options) | 类装饰器,标记类为请求对象实例。 | | getReq(target) | 获取类是否标记为请求对象实例。 |

import Common from '@fefeding/common';
const decorators = Common.utils.decorator.default;
const Request = Common.models.base.request.default;

// 标记 API 路由
@decorators.api({ url: '/api/user/save' })
export class SaveUserReq extends Request {
  data: any;
}

// 权限校验标记
@decorators.checkApiToken()
async saveUser() { /* ... */ }

@decorators.checkApiLogin()
async getUserInfo() { /* ... */ }

// 运行时读取元数据
decorators.getApi(SaveUserReq);          // => { url: '/api/user/save' }
decorators.getApiToken(target, 'saveUser');
decorators.getApiLogin(target, 'getUserInfo');

API Token (api)

基于时间戳与 MD5 的 API 校验 Token 生成工具,用于服务端接口安全校验。

| 导出 | 说明 | |------|------| | default | 模块对象,包含 createApiToken。 | | createApiToken(accessKey, timestamp?) | 返回 { sign: string, timestamp: string }timestamp 默认当前时间戳。 |

import Common from '@fefeding/common';
const api = Common.utils.api.default;

const token = api.createApiToken('your-access-key');
// => { sign: 'md5签名', timestamp: '1719465600000' }

远程日志 (logger)

基于 pino 的日志记录器,支持本地日志输出与远程日志服务同步。

| 导出 | 说明 | |------|------| | default | RemotePinoLogger 类。 | | LoggerOption | 类型:remoteUrlserviceNamelogLevelrequestIdloginIduserIdclientIPserverIPapiKeyurlext。 |

方法:info(message, data?)warn(...)error(...)debug(...)(均为异步发送、无需 await)、setOptions(options)

import Common from '@fefeding/common';
const RemotePinoLogger = Common.utils.logger.default;

const logger = new RemotePinoLogger({
  remoteUrl: 'https://log-server.com/api/log',
  serviceName: 'my-service',
  logLevel: 'info',
  apiKey: 'your-api-key'
});

logger.info('操作成功', { userId: 123 });
logger.error('发生错误', { error: err.message });

配置了 remoteUrl 且设置 apiKey 时,会以 x-api-token / x-api-timestamp 头携带签名发送到远程。

随机字符串 (rand)

| 导出 | 说明 | |------|------| | randString(id = 0, len = 0) | 基于 ID 与随机时间戳生成唯一短码(36 进制拼接)。len > 0 时截断长度,id = 0 时不关联 ID。 | | stringToNumber(str) | 将字符串按字符编码求和转换为数字,可用于哈希计算。 |

import Common from '@fefeding/common';
const { randString, stringToNumber } = Common.utils.rand;

const code = randString(123, 8);   // 基于 ID 生成唯一短码
const num  = stringToNumber('abc'); // 字符编码求和

对象存储 (s3,S3 兼容)

基于 AWS SDK v3(@aws-sdk/client-s3@aws-sdk/lib-storage@aws-sdk/s3-request-presigner)实现的 S3 兼容对象存储封装。通过自定义 endpoint 即可对接任意 S3 兼容服务,不再局限于腾讯云 COS:

| 服务 | endpoint | forcePathStyle | |------|-----------|------------------| | AWS S3(官方) | 省略(默认 https://s3.amazonaws.com) | false | | 腾讯云 COS(兼容模式) | https://cos.<region>.myqcloud.com | true | | 阿里云 OSS(兼容模式) | https://oss-<region>.aliyuncs.com | true | | MinIO | http://localhost:9000 | true |

每个方法均接受 paramscosS3Client 实例或连接配置对象;传配置对象时会自动 createClient)。

| 导出 | 说明 | |------|------| | createClient(option) | 创建 S3 客户端。option: accessKeyIdsecretAccessKeyregion?endpoint?forcePathStyle?bucket?。 | | uploadFile(params, cos) | 分片上传(适合大文件),内部自动处理 multipart。 | | putObject(params, cos) | 简单上传(适合小文件)。 | | getFile(params, cos) | 获取对象,返回 S3 响应(Body 为可读流)。 | | getObjectUrl(params, cos) | 获取对象 URL。Sign: true 时返回带签名的预签名 URL;否则按 endpoint 拼接公开 URL。 | | checkExists(params, cos) | 检查对象是否存在(404 / 403 或异常时返回 false)。 |

import Common from '@fefeding/common';
const { createClient, uploadFile, putObject, getFile, getObjectUrl, checkExists } = Common.utils.s3;

// 对接 MinIO(同理可对接 腾讯云 COS / 阿里云 OSS / AWS S3)
const s3 = createClient({
  accessKeyId: 'xxx',
  secretAccessKey: 'xxx',
  endpoint: 'https://cos.ap-guangzhou.myqcloud.com',
  forcePathStyle: true
});

await uploadFile({ Bucket, Key, Body: buffer }, s3);
await putObject({ Bucket, Key, Body: buffer }, s3);

const url    = await getObjectUrl({ Bucket, Key, Sign: true }, s3);
const exists = await checkExists({ Bucket, Key }, s3);

向后兼容 txCosCommon.utils.txCos 保留腾讯云 COS 的原始调用接口createClient({ SecretId, SecretKey, Region })getObjectUrl({ Region, Sign }) 等),内部自动映射到本 S3 实现(SecretId→accessKeyIdSecretKey→secretAccessKey、按 Region 拼接 https://cos.<region>.myqcloud.com、公开 URL 采用虚拟主机风格 https://<bucket>.cos.<region>.myqcloud.com/<key> 与原 SDK 一致)。旧项目无需改动即可继续工作;新项目建议直接使用 Common.utils.s3

PDF 处理 (pdf)

⚠️ 当前 已禁用:实现代码已注释,该模块暂不导出任何运行时 API,保留以用于后续功能扩展。

数据模型 (models)

所有模型默认继承 Model(支持 fromJSON 复制初始化、fromArray 数组转换)。TypeORM 实体类继承 BaseORM / ORMBaseFields

基础模型 (base)

| 模块 | 导出 | 说明 | |------|------|------| | model | default Model / ORMBaseFields | 基础模型类(JSON 复制 + 数组转换);ORMBaseFieldsvalidcreatorupdatercreateTimemodifyTime。 | | baseORM | default BaseORM | TypeORM 实体基类,映射字段 FvalidFcreatorFupdaterFcreate_timeFmodify_time。 | | request | default Request | API 请求基类:api_tokentimestamprequest_id。 | | response | default Response<T> | API 响应基类:ret(0=OK)、msgdata。 | | pagination | PageRequest<T>PageResponse<T> | 分页请求(querypage=1size=20);分页响应(data[]pagetotal)。 | | enumType | EValidEStatus | EValid: Valid=1Unvalid=0EStatus: ACTIVED=1DISABLED=2OFFLINE=3INACTIVATED=4。 | | cos | TextAuditingReqTextAuditingRes | 腾讯云文本审核请求/响应(@api '/api/cos/textAuditing')及结果接口 ITextAuditingResult。 |

账户模型 (account)

| 模块 | 导出 | 说明 | |------|------|------| | account | default Account | 登录账号:loginIduserIdappIdopenIdaccountunionIdpassworduserfromJSON 会清空 password,避免外泄。 | | user | default User / EGenderEEnable 及各类 Req/Res | 用户信息:idnamemobilegender(EGender)emailavatartelephoneenable(EEnable)status(EStatus)aliasaddressext。API 模型:QuerUserReq/ResSaveUserReq/ResDeleteUserReq/ResGetUserByIdReq/Res。 | | session | SessionAuthMapEAuthMapStatus 及登录 Req/Res | 会话管理。枚举 EAuthMapStatus: ACTIVED=1DISABLED=2。登录接口:LoginByCodeLoginByPhoneCheckSessionCreateSessionLogoutGetLoginSessionGetSessionSetStatusLoginByWeWorkLoginByUserNameGetCodeBySessionTokenLoginByWxLoginByAccount。 | | message | default Message / EMsgStatus | 消息:titlecontentstatus(EMsgStatus)appIdurltoUserEMsgStatus: SUCCESS=0FAIL=1TRANS=2OTHER=3。 | | app | AppEAppType 及 API Req/Res | 应用配置:idnametype(EAppType)appIdappKeysecretremarkextEAppType: Own=0WxGzh=1WxMiniApp=2WxWeb=3QQ=4BaiduOCR=5WkWeb=6WkMiniApp=7BaiduAccount=8。API 模型:QuerAppSaveAppDeleteAppGetAppGetCompanyBaseAppGetLoginApp。 | | verificationCode | VerificationCodeEStatusECodeType 及 API Req/Res | 验证码:idtargetIdreceiverstatuscodeTypecodeEStatus(本模块): Active=0Fail=1Success=2ECodeType: Image=0Phone=1Mail=2。API 模型:VerificationCodeCreateValidateSendSMSCode。 | | wx | 各类 Req/Res | 微信相关接口:GetAccessTokenByAppIdGetApiTicketByAppIdGetAppTicketByAppIdGetJSSDKParams。 |

AI 模型 (ai)

| 模块 | 导出 | 说明 | |------|------|------| | message | Message (interface) | AI 对话消息体:indexrolecontent。 |

开发

环境要求

  • Node.js >= 16
  • pnpm(推荐)

构建

pnpm install   # 安装依赖
pnpm build     # 构建(生成 dist/)
pnpm clean     # 清理构建产物

测试

pnpm test          # 运行测试
pnpm test:watch    # 监听模式
pnpm test:coverage # 测试覆盖率

项目结构

├── src/
│   ├── models/                  # 数据模型
│   │   ├── base/                # 基础模型(model / baseORM / request / response / pagination / enumType / cos)
│   │   ├── account/             # 账户模型(account / user / session / message / app / verificationCode / wx)
│   │   └── ai/                  # AI 模型(message)
│   └── utils/                   # 工具类
│       ├── api.ts               # API Token 生成
│       ├── axios.ts             # HTTP 请求封装
│       ├── decorator.ts         # 装饰器(api / checkApiToken / checkApiLogin 等)
│       ├── logger.ts            # 远程日志记录器
│       ├── pdf.ts               # PDF 处理(当前已禁用)
│       ├── rand.ts              # 随机字符串生成
│       ├── s3.ts                # 对象存储(S3 兼容:AWS / 腾讯云 COS / 阿里云 OSS / MinIO 等)
│       └── txCos.ts             # 腾讯云 COS 向后兼容适配层(保留原接口,内部映射至 s3)
├── test/                        # 测试文件
├── dist/                        # 构建产物(默认导出命名空间对象)
├── build.js                     # 构建脚本
├── gulpfile.js                  # Gulp 构建配置
└── tsconfig.json                # TypeScript 配置

License

MIT © fefeding