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

@mm-player/player-enterprise

v0.1.2

Published

mm-player 企业级插件生态(Marketplace/Runtime/EventBus/Hooks/Remote/Inspector)

Downloads

96

Readme

@mm-player/player-enterprise

mm-player 企业级插件生态:Marketplace / Runtime Isolation / EventBus / Hook / Remote / Inspector。依赖 @mm-player/player-core@mm-player/player-ui,不反向依赖。

模块用途

为播放器提供企业插件基础设施:插件注册与依赖解析、受限宿主上下文、插件间事件总线、10 个生命周期 Hook、远程插件加载与缓存、全景诊断。它与 PlayerUI.addPlugin() 的宿主插件机制相互独立,可按业务需要组合。

适用场景

  • 需要可插拔、可热加载的插件体系。
  • 需要插件间通信(EventBus)与生命周期 Hook。
  • 需要远程分发插件并缓存。
  • 需要诊断插件全景(依赖、权限、事件、Hook、运行状态)。

引入

pnpm add @mm-player/player-enterprise

完整生命周期示例

import {
  PluginEventBus,
  PluginHookSystem,
  PluginHost,
  PluginInspector,
  PluginInstaller,
  PluginRegistry,
  PluginRuntime,
  type PluginContext,
  type PluginPackage
} from '@mm-player/player-enterprise';
import { PlayerUI } from '@mm-player/player-ui';

const player = new PlayerUI({ container: '#player' });

const registry = new PluginRegistry();
const installer = new PluginInstaller(registry);
const runtime = new PluginRuntime();
const bus = new PluginEventBus();
const hooks = new PluginHookSystem();

const analyticsPackage = {
  manifest: {
    name: 'analytics',
    version: '1.0.0',
    category: 'analytics',
    dependencies: [],
    permissions: ['state']
  },
  factory: () => ({
    start(context: PluginContext) {
      bus.emit('analytics:start', context.host.call('getStatus'));
    },
    stop() {
      bus.emit('analytics:stop');
    }
  })
} satisfies PluginPackage;

// 1. 校验依赖与清单并登记插件包
const errors = installer.install(analyticsPackage);
if (errors.length > 0) throw new Error(errors.join('; '));

// 2. 宿主只暴露允许插件调用的公开方法
const host = new PluginHost({ getStatus: () => player.getCore().getSnapshot().status });
const context = runtime.start('analytics', host, ['state']);

// 3. Enterprise 提供基础设施,工厂和业务生命周期由宿主明确调用
const instance = analyticsPackage.factory();
instance.start(context);

// 4. 查看 Registry / Runtime / EventBus / Hooks 的组合状态
const report = PluginInspector.inspect(registry, runtime, bus, hooks);
console.log(report.plugins, report.running);

// 5. 对称停止并释放
instance.stop();
runtime.stop('analytics');
hooks.unregister('analytics');
bus.clear();
installer.uninstall('analytics');
await player.destroy();

仓库 examples/ 的“Enterprise 插件平台”区域可视化展示上述 Registry、Installer、Runtime、EventBus、Hooks 与 Inspector 组合流程。

关键 API

| 模块 | 主要导出 | 说明 | | --- | --- | --- | | Marketplace | PluginRegistry / PluginInstaller / DependencyResolver / PluginLoader;类型 PluginManifest / PluginPackagevalidateManifest | 插件注册、安装、依赖解析、加载 | | Runtime | PluginRuntime / PluginContext / PluginScope / PluginHost | 插件运行时隔离与作用域 | | EventBus | PluginEventBuson / once / off / emit / broadcast / clear / events) | 插件间通信,不操作 CommandBus | | Hooks | PluginHookSystem(10 hooks + 优先级);类型 HookName / HookEntry | 生命周期 Hook | | Remote | RemotePluginLoader / PluginCache | 远程插件加载与 TTL 缓存 | | Inspector | PluginInspector.inspect(静态);类型 PluginInspectorReport | 全景诊断报告 |

Hook 名称(10 个):beforeRender / afterRender / beforeTheme / afterTheme / beforeOverlay / afterOverlay / beforeSlot / afterSlot / beforeDestroy / afterDestroy

生命周期与资源释放

  • PluginEventBus 不操作 CommandBus;播放命令仍经 PlayerUI -> CommandBus
  • 远程插件经 RemotePluginLoader 加载并由 PluginCache(TTL)缓存;卸载时清除缓存与引用。
  • 插件宿主 API 边界由 PluginScope / PluginHost 约束;PluginRuntime.running() 返回运行中插件名列表。
  • 释放时清除 EventBus 监听(clear)与 Hook 注册,避免泄漏。

线程与回调约束

  • 单线程事件循环;EventBus 同步派发,监听器异常会影响同事件后续监听器。
  • broadcast 遍历当前事件名快照,遍历中新增的事件不会被本轮广播触发。
  • Hook 按优先级顺序执行。

常见错误与注意事项

  • 插件 Manifest 必须含 nameversionvalidateManifest 返回非空数组表示不合法。
  • EventBus 不替代 CommandBus:媒体控制必须经 PlayerUI/PlayerCore 派发。
  • PluginInstaller.install() 只校验、登记插件包,不调用 factory()PluginRuntime.start() 只创建上下文,不自动调用插件实例的 start() / stop()
  • PluginScope / PluginHost 是宿主 API 约束,不创建 Worker、iframe 或独立 Realm,不是用于执行不可信代码的浏览器安全沙箱
  • RemotePluginLoader 不会自动校验 signature;远程插件必须来自可信来源,并由调用方在执行前完成验签。
  • Inspector 报告中的 Hook 列表为固定 10 个生命周期点。

相关文档