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

@lanyunit/uploader

v2.0.6

Published

Integrate local, Tencent Cloud COS, Alibaba Cloud OSS, extendable drivers.

Readme

@lanyunit/uploader

Latest Version on Packagist Total Downloads

Integrate local, Tencent Cloud COS, Alibaba Cloud OSS uploads

安装

pnpm add @lanyunit/uploader

注册拉配置并上传

import { onGetConfig, send, type ResponseConfig } from '@lanyunit/uploader'

onGetConfig(['image', 'video', 'file'], async ({ type }) => {
    const res = await fetch(`https://api.example.com/upload/config?kind=${encodeURIComponent(type)}`)

    return (await res.json()) as ResponseConfig
})

await send({
    type: 'image',
    file,
    fileKey: 'gallery/123.png',
    data: { token: '1234567890' },
    headers: { Authorization: 'Bearer xxx' },
    onSuccess: (data) => console.log(data),
    onFail: (err) => console.error(err),
    onProgress: ({ loaded, total, percent }) => {}
})

说明:

  • resolver:返回 ResponseConfigPromise<ResponseConfig>
  • types:单字符串或字符串数组;另支持通配 onGetConfig('*', resolver):仅在没有更精确的 type 注册项时使用。
  • send({ type }):与注册的 type 关联,并按 type 缓存最近一次有效的服务端配置快照。
  • fetchUploadConfig(type):与 send 相同的路径解析策略(命中有效缓存或调用 onGetConfig),返回 Promise<ResponseConfig | undefined>,用于在选文件、调用 send 之前读取约束字段。

服务端 ResponseConfig

interface ResponseConfig {
    driver: string // 如 'local' | 'aliyun' | 'tencent' 或自定义 driver id
    config: Record<string, unknown>
}

config 中常见字段由各 driver 文档约定(如 hostprefixexpire_timemime_typesmax_sizealiyun / tencent 子对象等)。

主动拉取策略(fetchUploadConfig

若需在打开文件选择器或展示表单前,根据服务端下发的 mime_typesmax_size 做提示或拦截,可先调用 fetchUploadConfig(需已为对应 UploadType 注册 onGetConfig,且 prepare 能成功创建客户端,行为与 send 内解析一致)。

import { fetchUploadConfig } from '@lanyunit/uploader'

const rc = await fetchUploadConfig('image')
if (!rc) {
    // 未注册 resolver、请求失败、或 driver prepare 失败
    return
}

const { mime_types, max_size } = rc.config as {
    mime_types?: string | string[]
    max_size?: number
}

// 例如:结合 file.type / file.size 做前置校验;实际上传仍建议走 send(send 内会再次校验 mime 与大小)

未命中 onGetConfig 或拉取失败时返回 undefined。成功时会写入与同 type 一致的配置缓存,随后的 send({ type }) 可直接复用。

自定义 driver(示例:axios

import { registerDriver } from '@lanyunit/uploader'
import axios from 'axios'

registerDriver('custom', {
    prepare: (config) =>
        axios.create({
            baseURL: String(config.baseURL ?? ''),
            headers: typeof config.token === 'string' ? { Authorization: `Bearer ${config.token}` } : {}
        }),
    send: (payload) => {
        ;(payload.implementation as ReturnType<typeof axios.create>)
            .post('/upload', payload.data ?? {}, {
                headers: payload.headers,
                onUploadProgress: (ev) => {
                    const total = ev.total ?? payload.file.size
                    payload.onProgress?.({
                        loaded: ev.loaded,
                        total,
                        percent: total > 0 ? (ev.loaded / total) * 100 : 0
                    })
                }
            })
            .then((res) => payload.onSuccess?.(res.data as never))
            .catch((err) => payload.onFail?.(err instanceof Error ? err : new Error(String(err))))
    }
})

服务端返回 driver: 'custom' 时,prepare 创建的实例会传入 payload.implementation

缓存与卸载

  • unregisterOnGetConfig(types?):卸载已注册的 resolver;不传参表示清空。
  • clearUploadCache / getUploadCacheForType / primeUploadCacheForType:与同 UploadType 的配置快照配合使用(调试、预热或手写缓存)。fetchUploadConfig 命中成功时也会更新该缓存。

OSS 等政策过期导致需重签时,aliyun 内置实现可触发 retrySendsend 会清该 type 的缓存并按当前选项再走一遍流程。

其它工具

  • computeQetagNormal(file, blockBytes?):仅计算 QETag 字符串(不写存储)。
  • setDefaultEtagBlockSize / getDefaultEtagBlockSize:全局默认分块大小;也可用 send({ etagBlockSize }) 单次覆盖。

开发(Vite+)

vp install
vp check
vp test
vp pack

仓库内参阅 AGENTS.mdVite+ 文档