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

@northsea4/extension-runtime

v1.1.0

Published

Safe rule runtime for browser extensions (MV3-friendly)

Downloads

9

Readme

@northsea4/extension-runtime

一个面向浏览器扩展(尤其 MV3)的规则运行时。

  • 默认使用安全表达式模式(expr
  • 支持沙盒 JS 模式(js,需宿主注入执行器)
  • 提供统一 run() API、超时控制、策略校验与结果标准化

安装

pnpm add @northsea4/extension-runtime

快速开始

import { createRuntime } from '@northsea4/extension-runtime'

const runtime = createRuntime()

const result = await runtime.run(
  {
    id: 'rule-1',
    name: 'Upper Case',
    version: '1.0.0',
    mode: 'expr',
    code: 'upper(input.name)',
    helpers: ['upper']
  },
  {
    input: { name: 'clouddrive' },
    env: {},
    now: new Date().toISOString()
  }
)

if (result.ok) {
  console.log(result.output) // "CLOUDDRIVE"
}

也可以使用便捷调用(默认 js 模式):

const result = await runtime.exec('return { upper: String(ctx.input.name).toUpperCase() }', {
  name: 'clouddrive'
})

// 明确指定模式也可以:
const exprResult = await runtime.execExpr(
  'upper(input.name)',
  { name: 'clouddrive' },
  { helpers: ['upper'] }
)
const jsResult = await runtime.execJs('return { ok: true, name: ctx.input.name }', {
  name: 'clouddrive'
})

// 透传 traceId(便于日志关联)
const traced = await runtime.exec('return { ok: true }', {}, { traceId: 'trace-20260318-001' })
console.log(traced.traceId) // trace-20260318-001

// 支持取消执行(AbortSignal)
const controller = new AbortController()
const task = runtime.exec('return { ok: true }', {}, { signal: controller.signal })
controller.abort()
const canceled = await task
console.log(canceled.error?.code) // CANCELED

两种模式

expr(推荐默认)

  • 适合大多数可配置规则
  • 通过 AST 解释执行,不依赖 eval/new Function
  • 安全边界更清晰,可控性更高

js(高级兜底)

  • 适合复杂自定义逻辑
  • 必须在 createRuntime 时传入 sandboxExecutor
  • 运行时会做策略校验与超时约束
import { createRuntime } from '@northsea4/extension-runtime'

const runtime = createRuntime({
  sandboxExecutor: async ({ code, ctx }) => {
    // 在宿主侧实现 postMessage -> sandbox page 的执行链路
    return { code, input: ctx.input }
  },
  logger: console
})

Helper

可通过 registerHelper 注册自定义 helper:

runtime.registerHelper('suffix', (v, s) => `${String(v)}${String(s)}`)

表达式工具(同步 API)

除了 execExpr(统一结果结构、异步)外,也提供同步工具,便于需要“同步判定/编译缓存”的场景:

import { compileExpr, evalExpr, parseExpression } from '@northsea4/extension-runtime'

const ast = parseExpression('input.count > 0')
const ok = evalExpr('input.count > 0', { count: 1 }) // true

const compiled = compileExpr<{ count: number }, boolean>('input.count > 10')
const pass = compiled({ count: 12 }) // true

输出结果

run() 返回统一结构:

  • ok: 是否成功
  • output: 成功结果
  • error: 失败信息(含错误码)
  • traceId: 本次执行链路 ID(可透传或自动生成)
  • metrics: 执行耗时和模式信息

开启 logger 后,debug/warn 日志会带统一字段:

  • mode
  • channel
  • elapsedMs
  • ruleId
  • traceId

常见错误码(节选):

  • TIMEOUT: 执行超时
  • CANCELED: 执行被取消
  • PARSE_ERROR: 表达式解析失败
  • POLICY_DENIED: 策略或配置不允许
  • SERIALIZE_ERROR: 消息或结果不可序列化
  • UNSUPPORTED_ENV: 当前上下文不支持所需 API(如无 DOM / 无 runtime API)
  • SANDBOX_INIT_FAILED: sandbox iframe 初始化失败
  • SANDBOX_UNAVAILABLE: sandbox 目标窗口不可用
  • RELAY_UNAVAILABLE: tab relay 通道不可用
  • OFFSCREEN_UNAVAILABLE: offscreen 通道不可用

开发

pnpm --filter @northsea4/extension-runtime build
pnpm --filter @northsea4/extension-runtime test

发布文档

示例

  • 原生扩展示例位于 examples/browser-extension/

  • 先执行 pnpm --filter @northsea4/extension-runtime build

  • 同步 vendor 文件(推荐):

    pnpm --filter @northsea4/extension-runtime sync:browser-example
  • 或手动同步:

    cp packages/extension-runtime/lib/playground.js packages/extension-runtime/examples/browser-extension/vendor/extension-runtime.js
  • 打开 Chrome 扩展管理页(chrome://extensions),开启开发者模式

  • 点击“加载已解压的扩展程序”,选择 packages/extension-runtime/examples/browser-extension

  • 在扩展卡片里点击“详情” -> “扩展程序选项”,打开 options 页测试 expr/js 规则执行

Extension 集成示例(更具体)

下面给 3 种常见接入方式。你可以按环境选一种,不需要全上。

最小文件结构

src/
  entrypoints/
    popup/main.ts
    sandbox/main.ts
    content/main.ts
    background/main.ts
    offscreen/main.ts

场景 A:扩展页直连 sandbox(popup/options/content 有 DOM)

1) sandbox 页面(执行端)

// src/entrypoints/sandbox/main.ts
import { registerHtmlSandboxHandler } from '@northsea4/extension-runtime/extension'

registerHtmlSandboxHandler({
  helpers: {
    concat: (a, b) => `${String(a)}${String(b)}`
  }
})

2) popup/options 页面(调用端)

// src/entrypoints/popup/main.ts
import { createRuntime } from '@northsea4/extension-runtime'
import { createHtmlSandboxExecutor } from '@northsea4/extension-runtime/extension'
import Browser from 'webextension-polyfill'

const sandboxExecutor = createHtmlSandboxExecutor({
  sandboxUrl: Browser.runtime.getURL('sandbox.html'),
  iframeId: 'runtime-sandbox-frame',
  warmupOnCreate: true
})
// 也可手动控制预热时机(例如首屏空闲时)
// await sandboxExecutor.warmup()

const runtime = createRuntime({
  sandboxExecutor
})

const result = await runtime.execJs(
  "return { msg: concat(ctx.input.name, '-ok') }",
  { name: 'clouddrive' },
  {
    id: 'popup-js-rule',
    helpers: ['concat'],
    env: { source: 'popup' }
  }
)

console.log(result)

createHtmlSandboxExecutortargetOrigin 默认自动推断:

  • 普通网页 URL:使用精确 origin
  • 扩展/opaque 场景(如 chrome-extension://... 的 sandbox):自动回退为 *
  • 如需降低首次 execJs 延迟,可开启 warmupOnCreate 或在业务空闲期调用 warmup()

场景 B:background 通过 tab relay(依赖 content script)

1) content script 注册 relay 服务

// src/entrypoints/content/main.ts
import {
  createHtmlSandboxExecutor,
  registerTabRelaySandboxService
} from '@northsea4/extension-runtime/extension'
import Browser from 'webextension-polyfill'

const cleanup = await registerTabRelaySandboxService({
  execute: createHtmlSandboxExecutor({
    sandboxUrl: Browser.runtime.getURL('sandbox.html'),
    iframeId: 'runtime-sandbox-relay-frame'
  })
})

window.addEventListener('beforeunload', cleanup)

2) background 使用 relay executor

// src/entrypoints/background/main.ts
import { createRuntime } from '@northsea4/extension-runtime'
import { createTabRelaySandboxExecutor } from '@northsea4/extension-runtime/extension'

const runtime = createRuntime({
  sandboxExecutor: createTabRelaySandboxExecutor({
    targetTabId: 123,
    retry: {
      maxRetries: 1,
      retryDelayMs: 50
    }
  })
})

const result = await runtime.exec(
  "return { from: 'relay', upper: String(ctx.input.name).toUpperCase() }",
  { name: 'clouddrive' },
  {
    id: 'bg-relay-js-rule',
    env: { source: 'background' }
  }
)

console.log(result)

场景 C:background 走 offscreen(不依赖 tab)

说明:offscreen 主要是 Chromium 能力,跨浏览器项目建议加降级方案(例如回退到 tab relay)。

1) offscreen 页面注册处理器

// src/entrypoints/offscreen/main.ts
import { registerOffscreenSandboxHandler } from '@northsea4/extension-runtime/extension'
import { createHtmlSandboxExecutor } from '@northsea4/extension-runtime/extension'
import Browser from 'webextension-polyfill'

registerOffscreenSandboxHandler({
  execute: createHtmlSandboxExecutor({
    sandboxUrl: Browser.runtime.getURL('sandbox.html'),
    iframeId: 'runtime-offscreen-sandbox-frame'
  })
})

2) background 调用 offscreen executor

// src/entrypoints/background/main.ts
import { createRuntime } from '@northsea4/extension-runtime'
import { createOffscreenSandboxExecutor } from '@northsea4/extension-runtime/extension'

const runtime = createRuntime({
  sandboxExecutor: createOffscreenSandboxExecutor({
    documentPath: 'offscreen.html',
    reason: 'DOM_PARSER',
    justification: 'Execute extension-runtime js rules',
    retry: {
      maxRetries: 1,
      retryDelayMs: 50
    }
  })
})

const result = await runtime.exec(
  "return { from: 'offscreen', total: Number(ctx.input.a) + Number(ctx.input.b) }",
  { a: 2, b: 3 },
  {
    id: 'bg-offscreen-js-rule',
    env: { source: 'background' }
  }
)

console.log(result)

Extension API 列表

@northsea4/extension-runtime/extension 提供:

  • createHtmlSandboxExecutor
  • registerHtmlSandboxHandler
  • createTabRelaySandboxExecutor
  • registerTabRelaySandboxService
  • createOffscreenSandboxExecutor
  • registerOffscreenSandboxHandler