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

@s1eke/webpub-streamer

v0.0.2

Published

[English README](./README.en.md)

Readme

@s1eke/webpub-streamer

English README

@s1eke/webpub-streamer 是一个浏览器优先的 ESM 库,用来把本地 epubtxt 输入转换成同源可访问的 publication runtime,底层依赖 Service Worker 和 IndexedDB。

它的目标场景是 Thorium 一类的 Web Publication 消费端:在浏览器中打开本地文件,生成 Readium Web Publication Manifest 和 positions 列表,并把资源挂载到同源运行时 URL,例如 /__webpub_streamer__/pub/{publicationId}/manifest.json

功能概览

  • 支持打开本地 FileBlobArrayBuffer 或带名字的字节源
  • 支持 epubtxt
  • 生成 RWPM manifest 和 Readium positions
  • 使用 IndexedDB 持久化 publication 资源,并通过 lease 管理生命周期
  • 通过 Service Worker 在固定 scope 下提供 publication 资源
  • 支持 root SW 合并 handler 模式,以及无 SW 宿主下的 standalone fallback
  • 提供 parser worker pool、结构化 debug 事件,以及可检查的运行时 store snapshot
  • 提供 manifest / positions / runtime 可达性的测试辅助工具

安装

如果你准备把这个包发布后接入应用,或者在本地 workspace / link 环境中使用:

npm install @s1eke/webpub-streamer

@edrlab/thorium-webreactreact-dom 这些 peer dependency 主要用于本地 harness 或 Thorium 集成测试,不是核心运行时的硬依赖。

推荐接入方式:合并到已有 Root Service Worker

如果宿主应用已经有 root Service Worker,这就是推荐且受支持的接入方式。

在 root Service Worker 中:

import { createPublicationServiceWorkerHandler } from '@s1eke/webpub-streamer/sw';

const publicationHandler = createPublicationServiceWorkerHandler({
  scope: '/__webpub_streamer__/',
  dbName: 's1eke-webpub-streamer',
  mode: 'merged',
});

self.addEventListener('fetch', (event) => {
  if (publicationHandler.matches(event.request)) {
    event.respondWith(publicationHandler.respond(event.request));
  }
});

在页面侧:

import {
  connectServiceWorkerMount,
  createIndexedDbRuntimeStore,
  createWebPubStreamer,
} from '@s1eke/webpub-streamer';

const mount = await connectServiceWorkerMount({
  scope: '/__webpub_streamer__/',
  dbName: 's1eke-webpub-streamer',
});

const store = await createIndexedDbRuntimeStore({
  dbName: mount.dbName,
  gcPolicy: {
    inactiveTtlMs: 7 * 24 * 60 * 60 * 1000,
    maxTotalBytes: 256 * 1024 * 1024,
  },
});

const streamer = await createWebPubStreamer({
  mount,
  store,
  parserWorkerPoolSize: 2,
  debugSink: (event) => {
    console.debug(event.type, event.detail);
  },
});

const runtime = await streamer.open(file, {
  format: 'auto',
  targetProfile: 'epub',
  cachePolicy: 'reuse',
});

console.log(runtime.manifestUrl);

无现有 SW 宿主时的 Standalone Fallback

如果宿主页面当前没有被 root Service Worker 控制,可以使用包内置的 standalone runtime worker:

import {
  ensureServiceWorkerMount,
  createIndexedDbRuntimeStore,
  createWebPubStreamer,
} from '@s1eke/webpub-streamer';

const mount = await ensureServiceWorkerMount({
  scope: '/__webpub_streamer__/',
  dbName: 's1eke-webpub-streamer',
});

const store = await createIndexedDbRuntimeStore({
  dbName: mount.dbName,
});

const streamer = await createWebPubStreamer({
  mount,
  store,
});

如果页面已经被另一个 root Service Worker 控制,ensureServiceWorkerMount() 会直接失败,并明确提示你改用 merged handler 模式。

打开 Publication

const runtime = await streamer.open(file, {
  format: 'auto',
  targetProfile: 'epub',
  cachePolicy: 'reuse',
  txt: {
    chapterDetection: 'auto',
    language: 'en',
  },
});

reader.load(runtime.manifestUrl);

await runtime.release();

PublicationRuntime 主要提供:

  • manifestUrl
  • positionsUrl
  • baseUrl
  • profileHint
  • suggestedLocalDataKey
  • release()
  • destroy()
  • debug.events
  • debug.source
  • debug.txtChapterDiagnostics

读者组件用完一个 runtime 后应调用 release();如果你希望显式删除缓存并销毁 publication,则调用 destroy()

Public API

@s1eke/webpub-streamer

  • createWebPubStreamer(options)
  • connectServiceWorkerMount(options)
  • ensureServiceWorkerMount(options)
  • createIndexedDbRuntimeStore(options)

@s1eke/webpub-streamer/sw

  • createPublicationServiceWorkerHandler(options)
  • defaultServiceWorkerScriptUrl()

@s1eke/webpub-streamer/testing

  • assertManifestConforms(manifest)
  • assertPositionsValid(positions)
  • assertRuntimeFetchable(runtime, options)
  • openInThoriumHarness(runtime, options)

@s1eke/webpub-streamer/debug

  • inspectIndexedDbRuntimeStore({ dbName, timestamp? })
  • StreamerDebugEvent
  • RuntimeStoreDebugSnapshot

当前能力边界

  • 仅支持浏览器环境,要求有 Service Worker、IndexedDB、Web Crypto 和 TextDecoder
  • 输入格式只支持 epubtxt
  • 当前只支持 targetProfile: "epub";传 webPub 会抛出 UnsupportedTargetProfileError
  • 推荐的 SW 拓扑是把 publication handler 合并进已有的 root Service Worker
  • standalone worker 只适用于没有 root Service Worker controller 的宿主
  • 不支持两个独立 Service Worker 协同拦截 publication 资源
  • 加密或 DRM 保护的 EPUB 会被拒绝
  • 当前里程碑下,EPUB 远程资源会被拒绝
  • EPUB 中的 JavaScript 会在物化时被剥离
  • 混淆字体当前仍然采用 warn-and-drop / fail 策略,font deobfuscation 已明确延期到后续里程碑
  • TXT 章节识别支持 autononeregex

开发命令

npm run build
npm run typecheck
npm run lint
npm run test:unit
npm run test:integration

License

本项目采用 MIT License