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

@yeez-tech/dos-sdk

v0.1.1

Published

Dianshu Object Storage (DOS) SDK — Node.js upload client with COS protocol, pause/resume and checkpoint persistence

Readme

@yeez-tech/dos-sdk

典枢对象存储(DOS)Node.js SDK。封装业务侧 putObject 上传流程:向 DOSBackendService 申请端点 → 按协议直传(当前仅 腾讯云 COS)→ 上报完成,并统一 暂停 / 恢复 与断点续传。

本期独立交付。后续由 dianshu-file-transfer 接入本 SDK,再由客户端接入 file-transfer。
运行时:仅 Node(Electron main / 客户端侧),不面向浏览器。

Install

npm i @yeez-tech/dos-sdk

Peer / native 依赖说明:

  • cos-nodejs-sdk-v5 — COS 直传
  • better-sqlite3 — 上传 checkpoint 持久化(需能编译原生模块)

Quick start

import { createDosClient } from "@yeez-tech/dos-sdk";

const client = createDosClient({
  baseUrl: "https://dos.example.com", // DOSBackendService,主域名待定
  token: "<jwt>",
  clientVersion: "1.0.0",
  businessCode: "dianshu-test",
  // checkpointDbPath: "/path/to/checkpoints.db", // 默认 cwd/.dos-sdk/checkpoints.db
});

const result = await client.putObject({
  objectId: "biz-globally-unique-id",
  filePath: "/data/payload.bin",
  // businessCode: "dianshu-test", // 可覆盖 client 级默认值
  storagePreference: "COS",
  onProgress: (p) => console.log(p.percent, p.speed),
});

console.log(result.objectUrl); // dos://...

Pause / resume / cancel

await client.pause(objectId);
await client.resume(objectId, { onProgress });
await client.cancel(objectId); // 不再续传;可选 { forget: true } 删除 checkpoint

上层只面对统一语义;SDK 内部按 COS 任务是否仍在本进程,自动选择 restartTaskuploadFile 续传。

Parallel uploads(同一 DosClient)

同一个 client 上对不同 objectId 并发 putObject 即可,无需再建第二个 SDK:

const [a, b] = await Promise.all([
  client.putObject({
    objectId: "biz/file-a",
    filePath: "/data/a.bin",
    onProgress: (p) => console.log("a", p.percent),
  }),
  client.putObject({
    objectId: "biz/file-b",
    filePath: "/data/b.bin",
    onProgress: (p) => console.log("b", p.percent),
  }),
]);

await client.pause("biz/file-a"); // 只暂停 a,b 继续
await client.resume("biz/file-a");

内部按 objectId 隔离 COS 会话与 STS,进度 / pause / cancel 都按 objectId 路由。

Events & callbacks

任务回调(putObject / resume)与 Client 事件可同时使用;事件 payload 均带 objectId

| 事件 | 含义 | |------|------| | progress | 字节进度(含 percent / loaded / total / speed) | | progress-text | 阶段文案(phase + text不落盘) | | object-upload-speed | 上传速率 | | complete | 上传成功 | | error | 传输终态失败(同时触发 onError;Promise 仍 reject) | | action-error | pause / resume / cancel / putObject 控制路径失败 | | stop | 暂停或取消(reason: paused \| canceled) |

import { DosClientEvent } from "@yeez-tech/dos-sdk";

client.on(DosClientEvent.ProgressText, ({ objectId, phase, text }) => {
  console.log(objectId, phase, text);
});
client.on(DosClientEvent.Stop, ({ objectId, reason }) => {
  console.log(objectId, reason);
});

await client.putObject({
  objectId: "biz-1",
  filePath: "/data/a.bin",
  onProgress: (p) => console.log(p.objectId, p.percent),
  onError: (e) => console.error(e.code, e.error),
});

Protocol extension

COS 是内置 ProtocolUploader。按 getUploadEndpoint.protocol 选型;可用 registerProtocol() 或构造参数 protocolUploaders 注册 TUS/S3 等适配器,公开 putObject / pause / resume / cancel 不变。

Dynamic STS(上传中刷新凭证)

开始上传后,COS getAuthorization 会 POST parameter.dynamicData.url(getCosTmpCredential,body 带 cosKey)刷新 STS;bucket / region / cosKey 仍用首次 endpoint(checkpoint),不随刷新改 Key。

COS SDK 自身会缓存 STS(剩余有效期 >60s 时不回调),因此不会每个分片都打 DOS。

objectId 语义

| 概念 | 谁提供 | 说明 | |------|--------|------| | objectId | 业务侧(推荐业务后端发号) | 逻辑对象 ID,上传前必须已有;全局唯一由业务保证 | | businessCode | 业务侧 / SDK 默认配置 | 当前上传接口可选但部署上通常固定,如测试环境 dianshu-test | | parameter.cosKey / COS Key | getUploadEndpoint 返回 | 物理存储路径,SDK 默认直接使用 | | parameter.dynamicData.url | getUploadEndpoint 返回 | 动态 STS:getCosTmpCredential | | UploadId | 腾讯云 COS multipartInit | 分片会话 ID;业务 / SDK 不构造,由 cos-nodejs-sdk-v5 缓存与复用 | | dos://... | finishUploadObject 返回 | 上传完成后的逻辑地址 |

当前典枢客户端旧链路(cos/tmp/credential + cos/upload/completed没有 objectId 语义;接入本 SDK 时需要业务后端增加「上传前发号」或由调用方自行生成并与业务对账。

Upload sequence

对齐设计文档 / 流程图:

  1. POST /dos/api/getUploadEndpoint — 返回 protocol=cos + version + objectUrl + parameter.{bucket,region,cosKey,dynamicData.url}
  2. POST /dos/api/startUploadObject — 后端创建 dos_object,状态 UPLOADING
  3. SDK 直传 COS;签名时 POST dynamicData.url(getCosTmpCredential,{ cosKey })取 STS
  4. SDK 计算 hash(默认 MD5,可插拔)
  5. POST /dos/api/finishUploadObject — 传 contentLength / contentHash,后端 placement READY,返回 dos://...

Pause / resume 策略(COS)

腾讯云 Node SDK 行为要点(本仓库 MockCos 按同样规则模拟):

| API | 效果 | |-----|------| | pauseTask | 停止传输;清除 UploadId 的内存 using 标记 | | restartTask | 仅当任务仍在当前进程队列且状态为 paused / error 时有效 | | cancelTask | 清除 using;磁盘上的 UploadId 缓存仍保留 | | 再次 uploadFile | 若 UploadId 仍被 using → 跳过并 重新开 multipart(从头传);若已释放 → 按缓存 UploadId 断点续传 |

本 SDK 对上层统一 pause / resume,与 dianshu-website 上传暂停语义对齐:

  1. 暂停pausecancelTask(释放 UploadId using)+ 落盘 checkpoint=paused
  2. 恢复resume → 刷新 STS 后再次 uploadFile,依赖 COS 本地 UploadId 缓存续传分片
  3. 进程退出 / 崩溃:同 2;restartTask 仅在队列里仍有 paused/error 任务时作为兜底
  4. Checkpoint 使用 SQLite:通用列(objectId / status / filePath / protocol…)+ 协议私有 protocol_state_json(COS:bucket / region / cosKey / taskId)。STS 与事件不落盘。

暂停需要 FilePath 上传。COS 对 stream Body 不支持 pauseTask

UploadId 本地缓存键(SDK 内部,与腾讯实现一致)依赖:同一 FilePath、size / mtime / ctime、ChunkSizeBucketKey。续传时这些必须保持不变。

Auth

默认 TokenAuthProvider,请求头对齐当前 DOS 接口:

  • Authorization: Bearer <jwt>
  • token
  • User-Agent: DataPubToolClient/<version>
  • Client-Version
  • Referer: app://.

可注入自定义 AuthProviderCasdoorNodeAuthProvider 为业务后端节点体系预留(暂未实现,调用会抛 NOT_IMPLEMENTED)。

import { DosClient, TokenAuthProvider } from "@yeez-tech/dos-sdk";

new DosClient({
  baseUrl,
  auth: new TokenAuthProvider({ token, clientVersion: "1.0.0" }),
});

Hash

默认 Md5HashProvider。实现 HashProvideralgorithm + hashFile)即可替换。

Options 摘要

| 字段 | 说明 | |------|------| | baseUrl | DOSBackendService 根地址 | | token / auth | 鉴权;tokenTokenAuthProvider 快捷方式 | | businessCode | client 级默认业务编码,可在 putObject 时覆盖 | | userAgent / clientVersion | UA 与 Client-Version | | hashProvider | 可插拔哈希 | | checkpointStore / checkpointDbPath | checkpoint 存储;默认 SQLite | | cosSliceSize | 触发分片上传的阈值(默认 5MB) | | cosUploader | 可选注入,生产无需传;测例用来挂 Mock COS |

Testing

npm i
npm test
npm run build
npm run typecheck

测例结构:

test/
  sdk.test.ts                      # 基础:hash / sqlite / auth / 简单 putObject
  cos.mock.test.ts                 # MockCos:UploadId / using / pause / cancel / 跨进程
  client.upload.test.ts            # 普通上传、软暂停、崩溃 reopen、并发、cancel
  client.interrupt.worker.test.ts  # SIGKILL(断电)/ SIGTERM(优雅)后 resume
  workers/interrupt-upload-worker.ts
  support/
    mockCos.ts                     # 对齐腾讯语义的 COS mock(状态可落盘)
    mockDosServer.ts               # 本地 mock DOS HTTP
    interruptWorker.ts             # node --import tsx 拉起 worker
    harness.ts

Worker 中断约定(对齐 dianshu-file-transfer)

跨进程中断必须用:

node --import tsx <worker.ts> <config.json>

不要tsx/cli 起 worker:tsx 会再 fork 一层,对 wrapper 发 SIGKILL 后真实上传进程可能仍存活,导致和父进程 resume 抢同一份状态。
test/support/interruptWorker.tsspawnTsWorker 已按上述方式实现。

  • 断电 / 不优雅:worker 上传到中段 → 父进程 SIGKILL → 同 checkpointDbPath + mock COS 状态文件 reopen → resume
  • 优雅退出:worker 收 SIGTERMpause → 打出 graceful-exit → 父进程 reopen → resume

Project layout

src/
  client/DosClient.ts      # putObject / pause / resume / cancel
  api/DosBackendApi.ts     # /dos/api/*
  auth/                    # AuthProvider + Token / Casdoor stub
  hash/                    # HashProvider + Md5
  protocol/cos/            # CosUploader
  store/                   # CheckpointStore + Sqlite
test/                      # 见上方 Testing

Scripts

npm i
npm test
npm run build
npm run typecheck

License

MIT