Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version: [18, 20, 22, 24, 26]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm test
- run: npm pack --dry-run
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Contributing

Thanks for helping improve `hy-event-store`.

1. Search existing issues before opening a new one.
2. For bug reports, include the package version and a minimal reproduction.
3. Keep pull requests focused and add or update tests for behavior changes.
4. Run `npm test` before submitting a pull request.

Security vulnerabilities should be reported through the process in
[`SECURITY.md`](SECURITY.md), not through a public issue.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021-present coderwhy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
67 changes: 39 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
# hy-event-store
An event-based global state management tool for vue, react, mini-program, etc.

一个基于事件的全局状态管理工具,可以在Vue、React、小程序等任何地方使用。


[![npm version](https://img.shields.io/npm/v/hy-event-store.svg)](https://www.npmjs.com/package/hy-event-store)
[![npm downloads](https://img.shields.io/npm/dm/hy-event-store.svg)](https://www.npmjs.com/package/hy-event-store)
[![CI](https://github.com/coderwhy/hy-event-store/actions/workflows/ci.yml/badge.svg)](https://github.com/coderwhy/hy-event-store/actions/workflows/ci.yml)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

A small, zero-dependency event bus and global state store for Vue, React,
Mini Programs, and vanilla JavaScript.

一个基于事件的全局状态管理工具,可以在Vue、React、小程序等任何地方使用。

# 设计灵感
## Why this project

在项目中找到一个更加方便快捷的数据共享方案:

* 后续会完善文档和增加更多好用功能;
* 欢迎star、issue、pull requests,会进行更多改变;
- 同一套 API 可以用于不同前端框架和小程序;
- 核心包零运行时依赖,便于审查和集成;
- 欢迎通过 Issue 和 Pull Request 改进正确性、兼容性与文档。

## Install


# 如何使用呢?

## 1、npm安装依赖
安装 npm 依赖:

```shell
npm install hy-event-store
```



## 2、事件总线(event-bus)
## Event bus / 事件总线

```js
const { HYEventBus } = require('hy-event-store')
Expand All @@ -38,7 +38,7 @@ const whyCallback1 = (...payload) => {
}

const whyCallback2 = (...payload) => {
console.log("whyCallback1:", payload)
console.log("whyCallback2:", payload)
}

const lileiCallback1 = (...payload) => {
Expand Down Expand Up @@ -68,11 +68,9 @@ setTimeout(() => {
}, 3000);
```

The event bus also provides `once`, `off`, `clear`, and `hasEvent`.




## 3、数据共享(event-store)
## Shared state / 数据共享

```js
const { HYEventStore } = require("hy-event-store")
Expand All @@ -86,15 +84,14 @@ const eventStore = new HYEventStore({
recommends: []
},
actions: {
getHomeMultidata(ctx) {
console.log(ctx)
axios.get("http://123.207.32.32:8000/home/multidata").then(res => {
const banner = res.data.data.banner
const recommend = res.data.data.recommend
// 赋值
ctx.banners = banner
ctx.recommends = recommend
})
async getHomeMultidata(ctx) {
const res = await axios.get("https://example.com/home/multidata")
const banner = res.data.data.banner
const recommend = res.data.data.recommend
// 赋值
ctx.banners = banner
ctx.recommends = recommend
return { banner, recommend }
}
}
})
Expand Down Expand Up @@ -125,5 +122,19 @@ setTimeout(() => {
eventStore.dispatch("getHomeMultidata")
```

`dispatch` returns the action's result, so asynchronous actions can be awaited:

```js
const result = await eventStore.dispatch("getHomeMultidata")
```

State keys must be declared in the initial `state` object. Calling `setState`
with an unknown key throws an error instead of creating an unobservable value.

## Maintenance and security

- Run the regression suite with `npm test`.
- Run the source coverage report with `npm run test:coverage`.
- See [`CONTRIBUTING.md`](CONTRIBUTING.md) before opening a pull request.
- Report suspected vulnerabilities through [`SECURITY.md`](SECURITY.md), not a public issue.
- Released under the [MIT License](LICENSE).
38 changes: 38 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Roadmap

`hy-event-store` is returning to active maintenance through small, reviewable
changes. The immediate goal is to improve correctness and project health while
keeping the public API compatible.

## v1.4.0 — stability and maintenance

- Fix `clear`, `hasEvent`, and safe listener removal in the event bus
([#30](https://github.com/coderwhy/hy-event-store/issues/30),
[#33](https://github.com/coderwhy/hy-event-store/issues/33)).
- Return synchronous and asynchronous action results from `dispatch`
([#29](https://github.com/coderwhy/hy-event-store/issues/29),
[#31](https://github.com/coderwhy/hy-event-store/issues/31),
[#32](https://github.com/coderwhy/hy-event-store/pull/32)).
- Add automated regression tests and a supported Node.js CI matrix.
- Improve package metadata, security reporting, contribution guidance, and API
documentation.

## After v1.4.0

These items need API design or compatibility research before implementation:

- Add first-party TypeScript declarations
([#25](https://github.com/coderwhy/hy-event-store/issues/25)).
- Document and test CommonJS, ESM, and Mini Program import paths
([#27](https://github.com/coderwhy/hy-event-store/issues/27)).
- Evaluate a read-only state getter
([#26](https://github.com/coderwhy/hy-event-store/issues/26)).
- Explore an opt-in full snapshot for `onStates`
([#24](https://github.com/coderwhy/hy-event-store/issues/24)).

## Maintenance principles

- Prefer focused pull requests with regression tests.
- Preserve backward compatibility unless a major release is justified.
- Document behavior changes and migration steps in release notes.
- Treat Issue and Pull Request triage as part of project maintenance.
11 changes: 11 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Security Policy

The latest published release is the supported version of `hy-event-store`.

Please do not open a public issue for a suspected vulnerability. Send a report
to `coderwhy@gmail.com` with the subject `[hy-event-store security]`. Include
the affected version, impact, reproduction steps, and any suggested fix. Do
not include credentials, tokens, or unrelated personal data.

We will acknowledge a complete report, investigate it, and coordinate a fix
and disclosure when the issue is confirmed.
84 changes: 84 additions & 0 deletions Test/event-bus.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const test = require("node:test")
const assert = require("node:assert/strict")

const { HYEventBus } = require("../src")

test("on and emit deliver every payload with the configured context", () => {
const bus = new HYEventBus()
const calls = []
const context = { name: "context" }

assert.equal(bus.on("update", function(...payload) {
calls.push([this, ...payload])
}, context), bus)
assert.equal(bus.emit("update", "name", 42), bus)

assert.deepEqual(calls, [[context, "name", 42]])
})

test("once does not skip the next handler", () => {
const bus = new HYEventBus()
const calls = []

bus.once("update", () => calls.push("once"))
bus.on("update", () => calls.push("always"))

bus.emit("update")
bus.emit("update")

assert.deepEqual(calls, ["once", "always", "always"])
})

test("off is safe for missing events and removes matching handlers", () => {
const bus = new HYEventBus()
const callback = () => {}
let survivorCalls = 0
const survivor = () => survivorCalls++

assert.equal(bus.off("missing", callback), bus)
bus.on("update", callback)
bus.on("update", survivor)
assert.equal(bus.hasEvent("update"), true)
bus.off("update", callback)
bus.emit("update")
assert.equal(survivorCalls, 1)
bus.off("update", survivor)
assert.equal(bus.hasEvent("update"), false)
})

test("clear removes every registered event", () => {
const bus = new HYEventBus()

bus.on("one", () => {})
bus.on("two", () => {})
assert.equal(bus.clear(), bus)
assert.equal(bus.hasEvent("one"), false)
assert.equal(bus.hasEvent("two"), false)
})

test("event names cannot collide with object prototype properties", () => {
const bus = new HYEventBus()
const calls = []

for (const eventName of ["constructor", "toString", "__proto__"]) {
bus.on(eventName, () => calls.push(eventName))
bus.emit(eventName)
}

assert.deepEqual(calls, ["constructor", "toString", "__proto__"])
})

test("public methods validate event names and callbacks", () => {
const bus = new HYEventBus()
const invalidName = 42
const invalidCallback = "callback"

assert.throws(() => bus.on(invalidName, () => {}), /event name/)
assert.throws(() => bus.on("event", invalidCallback), /event callback/)
assert.throws(() => bus.once(invalidName, () => {}), /event name/)
assert.throws(() => bus.once("event", invalidCallback), /event callback/)
assert.throws(() => bus.emit(invalidName), /event name/)
assert.throws(() => bus.off(invalidName, () => {}), /event name/)
assert.throws(() => bus.off("event", invalidCallback), /event callback/)
assert.throws(() => bus.hasEvent(invalidName), /event name/)
})
Loading