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

@ablogcms/events

v3.2.28-beta.0

Published

管理画面 JS 拡張基盤の型付きイベントバス

Downloads

151

Readme

@ablogcms/events

管理画面 JS 拡張基盤の中核となる、型付きイベントバス(ACMS.events)を提供するパッケージ。

拡張ポイントの一覧(イベント・Slot・レジストリの対応表)は ../plugins/HOOKS.md を参照。

使い方

interface AcmsEvents {
  on<K extends AcmsEventType>(type: K | K[], handler: AcmsHandler<K>): Unsubscribe;
  off<K extends AcmsEventType>(type: K, handler: AcmsHandler<K>): boolean;
  emit<K extends AcmsEventType>(type: K, payload: AcmsPayload<K>): Promise<EmitResult<K>>;
  cancel(reason?: string): CancelToken;
  handlerCount(type: string): number;
}
  • on(type | type[], handler): イベントを購読する。戻り値の関数で購読解除できる。
  • off(type, handler): 指定したハンドラの購読を解除する。
  • emit(type, payload): イベントを発火する。ゲートイベント(*.before)は全ハンドラを await し、 { canceled, reason?, error?, event } を返す。reason はビジネスキャンセルの理由(cancel(reason) 経由のみ)、error はハンドラが throw / reject した場合の生例外。
  • cancel(reason?): ゲートハンドラから返すキャンセルトークンを生成する。理由なしキャンセルは return false を使う。
  • handlerCount(type): 登録ハンドラ数を返す。

4つの意味論

イベント名が {domain}.{action}.before の形(ゲート)かどうかで挙動が変わる。

// 通知: 購読するだけ。戻り値は無視される
ACMS.events.on('media.upload.success', (event) => console.log(event.items));

// 値変更: event を書き換えて return すると次のハンドラ・コアへ反映される
ACMS.events.on('media.upload.before', (event) => ({ ...event, files: event.files.filter((f) => f.size < LIMIT) }));

// キャンセル: return false(理由なし)、または ACMS.events.cancel(reason) を return(理由あり)
ACMS.events.on('media.upload.before', (event) => (event.files.length === 0 ? ACMS.events.cancel('ファイルが空です') : undefined));

// 非同期ゲート: Promise を返すとバスが解決を待つ
ACMS.events.on('media.upload.before', async (event) => ((await confirm()) ? event : false));

event.error にメッセージを設定して return する旧方式は廃止した(正常系の判断であるキャンセルと、 異常系のハンドラ例外が 1 つのプロパティに混線していたため)。cancel(reason)unique symbol で ブランド化された名目的型のトークンを返すため、{ reason: '...' } のようなプレーンオブジェクトを そのまま return してもキャンセル扱いにはならない。

型付け

イベント名 → ペイロード型は module augmentation で宣言する。

declare module '@ablogcms/events' {
  interface AcmsEventMap {
    'media.upload.before': AcmsGateEvent<{ files: File[] }>;
    'media.upload.success': AcmsNotifyEvent<{ items: MediaItem[] }>;
  }
}

2つのエントリ

| エントリ | 内容 | |---|---| | @ablogcms/events | window.ACMS.events へのグローバル委譲ファサード | | @ablogcms/events/core | createEventBus() の純粋実装(グローバル非依存。ユニットテストに便利) |