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

fluffy-oss-sdk

v0.3.1

Published

Fluffy OSS upload client SDK — upload files with signature auth and progress tracking

Readme

fluffy-oss-sdk

Fluffy OSS 文件上传客户端 SDK。签名认证、上传进度、UniApp App-Plus 原生上传适配,内置纯 JS 同步签名通道——App 端无需任何外部 crypto 垫片。

API 冻结声明(0.3.0):upload() 入参、UploadProgress 形态与进度回调时序、错误类集合及 code/details 字段、signHeaders() 返回 Promise<SignedHeaders>,自此版本起保持不变;调用侧代码升级到 0.3.0 后不再需要跟随 SDK 变动。

安装

npm install fluffy-oss-sdk@^0.3.0

如果需要在 Node.js 中获取上传进度,请额外安装可选的 Axios 依赖:

npm install axios

快速开始

import { FluffyOssClient } from 'fluffy-oss-sdk'

const client = new FluffyOssClient({
  baseUrl: 'https://your-backend.example/api',
  appId: 'your-app-id',
  secret: 'your-app-secret',
})

const result = await client.upload(file, {
  applicationId: '1',
  onProgress: ({ percent }) => console.log(`${percent}%`),
})

运行环境与传输方式

SDK 同时服务 H5(浏览器)、Node.js 与 UniApp,运行时由交叉验证自动判定(uni.uploadFile 且无 window → uniapp;process.versions.node 且无 window/uni → node;有 window → browser;H5 版 uni-app 暴露 uni + window,正确识别为 browser)。

| 运行环境 | 输入类型 | 上传方式 | | --- | --- | --- | | 浏览器(含 H5) | File | 需要进度时 XMLHttpRequest,否则 fetch | | Node.js | Buffer、Uint8Array 或本地文件路径 | fetch;Axios 可提供上传进度 | | UniApp App-Plus | 非空本地临时文件路径字符串 | adapterUni: true 时优先 plus.uploader,缺失时回退 uni.uploadFile |

UniApp App-Plus

仅在真正的 App-Plus 构建中启用 adapterUni,并将选择器返回的本地文件路径原样传入:

const client = new FluffyOssClient({
  baseUrl: 'https://your-backend.example/api',
  appId: 'your-app-id',
  secret: 'your-app-secret',
  adapterUni: true,
})

const result = await client.upload(tempFilePath, {
  applicationId: '1',
  timeout: 60_000,
  onProgress: ({ percent, loaded, total }) => console.log(`${percent}%`),
})

原生上传会提交 file、applicationId 和可选的 callbackUrl 字段;filename 和 mime 参数在原生上传中被忽略。适配器拒绝非字符串或空白路径,不会回退到浏览器或 Node.js 上传方式。

传输分层:

  • plus.uploader.createUpload(主路径,App-Plus 必然可用):监听底层任务态(statechanged),完成回调携带 HTTP 状态码与响应文本,提供字节级 uploadedSize/totalSize 进度,abort() 对接超时与 AbortSignal。原生超时始终显式设置(调用方 timeout 毫秒换算为秒;未传时取规范默认 120 秒),不受 app-service JS 挂起影响。已知限制:Android 端不开启分块时原生进度会失真(可能从 0 直接跳到完成);本后端为普通 multipart POST 不支持分块,故进度粒度受限,但任务态与完成信号不受影响。
  • uni.uploadFile(降级路径,plus 缺失时):透传 timeout 参数(社区标注 App 2.10.0+ 支持,请真机验证一次),并特性检测 task.onStateChange(非标准 API,仅显式 fail 态终止上传)。无论是否传参,App 端 manifest.json 的 networkTimeout.uploadFile(默认 60000ms,HBuilderX 2.5.10+)在原生层始终生效。

SDK 永不自动重试上传:重试 multipart 请求可能导致服务端创建重复任务;plus.uploader 的默认重试(3 次)被显式固定为 0。

watchdog 配置

const client = new FluffyOssClient({ ..., adapterUni: true, watchdog: 'off' })
  • "auto"(默认):JS watchdog(setTimeout)与原生超时双层兜底。App 切后台时 JS 定时器随引擎挂起、回前台后立即补触发,因此超时错误可能晚于 wall-clock 时点抛出,但 Promise 必落定。
  • "off":只依赖原生超时。plus.uploader 有规范内置超时所以始终可用;uni.uploadFile 降级路径无 SDK 可验证的原生超时,此时若也未传 timeout,上传会直接抛 WATCHDOG_UNAVAILABLE 而不是静默悬挂。

签名通道

签名算法与后端 SignatureGuard 完全一致:secretHash = SHA-256(secret)(hex),signature = HMAC-SHA256(secretHash, appId + timestamp + nonce)(hex)。

引擎顺序:Web Crypto → 纯 JS 同步核心。

  • 浏览器 / Node:优先 Web Crypto(digest 与 HMAC 各有 3 秒内部期限,超时抛 SIGN_TIMEOUT;Web Crypto 存在但损坏时静默落回纯 JS 核心)。
  • UniApp(adapterUni: true 或检测为 uniapp 运行时):强制走纯 JS 同步核心,全程零 await,从根上绕开 app-service 中 Web Crypto Promise 与定时器派发的不可靠性。
  • 纯 JS 核心自带 UTF-8 编码与 SHA-256/HMAC 实现,无 TextEncoder、无 Web Crypto、无 Node crypto 的裸 JS 环境同样可用(已用 node:crypto 验算一致性);调用侧无需再引入任何 app-crypto 之类的垫片。

nonce 随机源说明:优先 crypto.getRandomValues;完全缺失时降级为「时间戳 + 单调计数器 + Math.random」播种的 PRNG。nonce 在后端仅承担 Redis 一次性防重放去重职责(重复即 401,Redis 故障时跳过),且作为 HMAC 输入参与签名——可预测性不构成攻击面,唯一性才是硬要求,故该降级仅影响随机数质量、不影响签名安全;冲突后果为一次可重试的 401。H5 环境全量支持 getRandomValues,降级路径不可达。

环境自检

const report = FluffyOssClient.probe({ adapterUni: true })
// { webCrypto, textEncoder, adapter, nativeTimeout, watchdog }

webCrypto / textEncoder 为能力布尔值;adapter 为判定出的运行时;nativeTimeout 在 App-Plus 主路径为 true、uni.uploadFile 降级路径为 'unknown'(需真机确认);watchdog 表示 SDK 定时器已被观测到触发(或非 uniapp 运行时)。仅用于 dev 诊断,替代调用侧手写探针与 Toast 路标。

上传选项

| 选项 | 类型 | 说明 | | --- | --- | --- | | applicationId | string | 目标应用 ID。为保持兼容性,默认值为 "1"。 | | callbackUrl | string | 随上传请求发送的可选回调地址。 | | filename | string | Node.js 上传时使用的自定义文件名。在 UniApp 中会被忽略。 | | mime | string | Node.js 上传时使用的自定义 MIME 类型。在 UniApp 中会被忽略。 | | onProgress | (progress: UploadProgress) => void | 上传进度回调。settled 后不再回调;App-Plus 主路径提供真实字节,uni.uploadFile 与浏览器路径为百分比 + 字节。 | | timeout | number | 上传超时时间,单位为毫秒,必须为正数。 | | signal | AbortSignal | 当信号被中止时取消上传。 |

错误处理

所有错误继承 FluffyOssError,携带稳定 code(0.3.0 定稿)与可选 cause / details,供 release 包(console 被剥离)下凭 Toast 文案 + code 定位:

import { FluffyOssError } from 'fluffy-oss-sdk'

try {
  await client.upload(file, { applicationId: '1', timeout: 60_000 })
} catch (error) {
  if (error instanceof FluffyOssError) {
    console.error(error.code, error.message, error.details)
  }
}

| code | 含义 | 排查动作 | | --- | --- | --- | | SIGN_TIMEOUT | Web Crypto 签名超时(3s/步) | 运行时 Web Crypto 异常,SDK 已降级场景之外出现即上报;已自动落回纯 JS 的不受影响 | | SIGN_UNSUPPORTED | 签名前置条件缺失(理论兜底) | 检查运行时是否极端受限 | | API_ERROR | 服务端返回失败(status + 信封 message) | 按 HTTP 状态与后端 message 查鉴权/时间窗/签名/参数 | | NETWORK_ERROR | 未收到可用响应 | details 含 errMsg/errno/taskState/statusCode/transport,查 DNS、TLS 证书、明文 HTTP 策略、服务端可用性 | | UPLOAD_TIMEOUT | 超过配置的 timeout | details.timeoutMs;App 后台挂起场景会延迟到回前台抛出 | | UPLOAD_CANCELED | AbortSignal 被中止 | 预期行为 | | WATCHDOG_UNAVAILABLE | watchdog 关闭且无任何可确认超时层 | 传 timeout 或恢复 watchdog: 'auto' | | INVALID_INPUT | 参数不合法(空白路径、非法 timeout 等) | 修正调用参数 |

开发命令

npm run typecheck
npm test
npm run build
npm pack --dry-run

测试覆盖:NIST/RFC 向量与 node:crypto 交叉验证、裸 JS 环境签名(无 Web Crypto / 无 TextEncoder)、运行时探测矩阵、dist 产物卫生(禁止 node:crypto、Node 动态导入必须带运行时守卫)、plus/uni 双轨传输行为与黑洞场景。