nanoeffects 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -55
- package/dist/{action-Bdfp-Wvd.d.ts → action-creator-DOWcbXpy.d.ts} +79 -73
- package/dist/actions.d.ts +75 -6
- package/dist/actions.js +1 -1
- package/dist/bus-BAs9x7IQ.js +1 -0
- package/dist/{context-DlA80GOA.js → context-CK0ZomWt.js} +1 -1
- package/dist/context-plugin-B0sLWOxR.d.ts +34 -0
- package/dist/dev.d.ts +2 -2
- package/dist/effects.d.ts +153 -56
- package/dist/effects.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/{module-I1ixyJzx.d.ts → module-DCJl-qfi.d.ts} +24 -9
- package/dist/notrace/{action-Bdfp-Wvd.d.ts → action-creator-DOWcbXpy.d.ts} +79 -73
- package/dist/notrace/actions.d.ts +97 -13
- package/dist/notrace/actions.js +1 -1
- package/dist/notrace/bus-Bdk0YyFQ.js +1 -0
- package/dist/notrace/{context-yAWj0BFZ.js → context-CctVmHLC.js} +1 -1
- package/dist/notrace/context-plugin-B0sLWOxR.d.ts +34 -0
- package/dist/notrace/{delay-Cgvn16oY.js → delay-B_W1tnkS.js} +1 -1
- package/dist/notrace/effects.d.ts +153 -56
- package/dist/notrace/effects.js +1 -1
- package/dist/notrace/index.d.ts +3 -2
- package/dist/notrace/index.js +1 -1
- package/dist/notrace/policies.d.ts +1 -1
- package/dist/notrace/policies.js +1 -1
- package/dist/notrace/redux.d.ts +18 -20
- package/dist/notrace/redux.js +1 -1
- package/dist/observable.d.ts +1 -1
- package/dist/policies.d.ts +1 -1
- package/dist/policies.js +1 -1
- package/dist/react.d.ts +50 -0
- package/dist/react.js +1 -0
- package/dist/redux.d.ts +18 -20
- package/dist/redux.js +1 -1
- package/dist/trace.d.ts +1 -1
- package/docs/README.md +30 -9
- package/docs/actions.md +117 -41
- package/docs/context.md +48 -7
- package/docs/effects.md +229 -73
- package/docs/errors.md +23 -10
- package/docs/guide.md +238 -129
- package/docs/hmr.md +25 -13
- package/docs/migrating-from-effector.md +293 -0
- package/docs/migrating-from-rxjs.md +127 -0
- package/docs/migrating-from-saga.md +93 -0
- package/docs/observable.md +11 -9
- package/docs/package.md +24 -0
- package/docs/policies.md +93 -30
- package/docs/react.md +157 -0
- package/docs/semantics.md +5 -3
- package/docs/stores.md +488 -25
- package/docs/tracing.md +69 -54
- package/docs/typescript.md +153 -0
- package/llms-full.txt +2645 -0
- package/llms.txt +48 -0
- package/package.json +39 -9
- package/dist/bus-CRnlwmQ4.js +0 -1
- package/dist/notrace/bus-Dx0l9X6h.js +0 -1
- package/dist/notrace/event-0RIBGYqS.js +0 -1
package/llms.txt
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# nanoeffects
|
|
2
|
+
|
|
3
|
+
> A small typed event bus for JavaScript and TypeScript apps. Each handler runs as a task with an `AbortSignal`, so in-flight work can be cancelled. Policies (`latest`, `debounce`, ...) and effects (`retry`, `timeout`, ...) are plain functions.
|
|
4
|
+
|
|
5
|
+
Rules that generated code often gets wrong:
|
|
6
|
+
|
|
7
|
+
- The package is ESM only. There is no default export and no `require`.
|
|
8
|
+
- `const unbind = bus.on("event", handler)` subscribes and returns the unsubscribe function. There is no `subscribe` or `addListener`.
|
|
9
|
+
- A handler gets the payload and a task context: `(payload, ctx)`. The context has `signal`, `emit`, `on`, `run`. Pass `ctx.signal` to `fetch`.
|
|
10
|
+
- Effects take `ctx` as the first argument: `retry(ctx, fn, options)`, `timeout(ctx, ms, fn)`, `take(ctx, "event")`.
|
|
11
|
+
- Policies wrap a handler: `bus.on("search", latest(async (query, ctx) => { ... }))`.
|
|
12
|
+
- Each part is imported from its own path: `nanoeffects` (`createBus`), `nanoeffects/policies`, `nanoeffects/effects`, `nanoeffects/actions`, `nanoeffects/redux`, `nanoeffects/observable`, `nanoeffects/react` (`reactPlugin`, adds `bus.useEmitter`; needs React), `nanoeffects/trace`, `nanoeffects/dev`.
|
|
13
|
+
- `bus.emit(command(payload))` runs the command's handler and returns its result. Plain events return nothing.
|
|
14
|
+
|
|
15
|
+
## Start here
|
|
16
|
+
|
|
17
|
+
- [Guide](docs/guide.md): bus, handler context, policies, effects, commands and modules, step by step
|
|
18
|
+
- [Package entries](docs/package.md): which import holds what
|
|
19
|
+
|
|
20
|
+
## Async UI and unreliable networks
|
|
21
|
+
|
|
22
|
+
- [Policies](docs/policies.md): `latest`, `leading`, `debounce`, `throttle`, `queue`, and `key`
|
|
23
|
+
- [Effects and cancellation](docs/effects.md): `retry`, `timeout`, `poll`, `take`, `all`, `race`, `backoff`
|
|
24
|
+
- [Errors and unheard events](docs/errors.md): `onError`, `onUnhandled`
|
|
25
|
+
|
|
26
|
+
## Domain logic and stores
|
|
27
|
+
|
|
28
|
+
- [Actions, commands, jobs and modules](docs/actions.md): `createAction`, `createCommand`, `createJob`, `createModule`
|
|
29
|
+
- [Connect Redux, Zustand, MobX, or Pinia](docs/stores.md): the Redux middleware and callbacks of other stores
|
|
30
|
+
- [Build a sign-up form in React](docs/react.md): a form with a username check, a submit that cannot fire twice, and retry
|
|
31
|
+
- [Context fields](docs/context.md): put a store or client on every task
|
|
32
|
+
|
|
33
|
+
## TypeScript
|
|
34
|
+
|
|
35
|
+
- [TypeScript in many files](docs/typescript.md): keep the types of the bus in commands and modules
|
|
36
|
+
|
|
37
|
+
## Coming from another library
|
|
38
|
+
|
|
39
|
+
- [Coming from redux-saga](docs/migrating-from-saga.md)
|
|
40
|
+
- [Coming from Effector](docs/migrating-from-effector.md)
|
|
41
|
+
- [Use nanoeffects next to RxJS](docs/migrating-from-rxjs.md)
|
|
42
|
+
|
|
43
|
+
## Reference
|
|
44
|
+
|
|
45
|
+
- [Semantics](docs/semantics.md): exact rules of emit, abort and ordering
|
|
46
|
+
- [Trace tasks](docs/tracing.md): loggers, Redux DevTools, the `notrace` build
|
|
47
|
+
- [Turn events into Observables](docs/observable.md): `createObserve`
|
|
48
|
+
- [Hot reload and development diagnostics](docs/hmr.md): `devPlugin`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nanoeffects",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Typed event bus where every handler is a task with an AbortSignal, plus policies (latest, debounce, throttle, queue), effects (retry, timeout, poll) and tracing. About 1.
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Typed event bus where every handler is a task with an AbortSignal, plus policies (latest, debounce, throttle, queue), effects (retry, timeout, poll) and tracing. About 1.3 kB gzip.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"event-bus",
|
|
7
7
|
"event-emitter",
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
|
+
"llms.txt",
|
|
37
|
+
"llms-full.txt",
|
|
36
38
|
"README.md",
|
|
37
39
|
"LICENSE",
|
|
38
40
|
"docs"
|
|
@@ -88,6 +90,10 @@
|
|
|
88
90
|
"types": "./dist/observable.d.ts",
|
|
89
91
|
"import": "./dist/observable.js"
|
|
90
92
|
},
|
|
93
|
+
"./react": {
|
|
94
|
+
"types": "./dist/react.d.ts",
|
|
95
|
+
"import": "./dist/react.js"
|
|
96
|
+
},
|
|
91
97
|
"./dev": {
|
|
92
98
|
"production": {
|
|
93
99
|
"types": "./dist/dev.d.ts",
|
|
@@ -98,7 +104,7 @@
|
|
|
98
104
|
}
|
|
99
105
|
},
|
|
100
106
|
"scripts": {
|
|
101
|
-
"build": "tsdown && node scripts/notrace-types.mjs",
|
|
107
|
+
"build": "tsdown && node scripts/notrace-types.mjs && node scripts/llms-full.mjs",
|
|
102
108
|
"prepublishOnly": "pnpm build",
|
|
103
109
|
"check": "biome check ./src ./examples ./integration ./scripts",
|
|
104
110
|
"format": "npx @biomejs/biome check --write --unsafe ./src ./examples ./integration ./scripts",
|
|
@@ -108,8 +114,10 @@
|
|
|
108
114
|
"prepare": "lefthook install",
|
|
109
115
|
"lint:package": "publint && attw --pack . --profile esm-only",
|
|
110
116
|
"size": "size-limit",
|
|
111
|
-
"verify": "pnpm tsgo && pnpm check && pnpm test && pnpm build && pnpm test:integration && pnpm smoke && pnpm lint:package && pnpm size",
|
|
117
|
+
"verify": "pnpm tsgo && pnpm check && pnpm docs:check && pnpm llms:check && pnpm test && pnpm build && pnpm test:integration && pnpm smoke && pnpm lint:package && pnpm size",
|
|
112
118
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
119
|
+
"docs:check": "node scripts/docs-check.mjs",
|
|
120
|
+
"llms:check": "node scripts/llms-full.mjs --check",
|
|
113
121
|
"smoke": "node scripts/smoke.mjs && node scripts/smoke.mjs --notrace",
|
|
114
122
|
"consumer-check": "node scripts/consumer-check.mjs"
|
|
115
123
|
},
|
|
@@ -121,11 +129,17 @@
|
|
|
121
129
|
"@reduxjs/toolkit": "^2.13.0",
|
|
122
130
|
"@size-limit/esbuild": "^14.2.0",
|
|
123
131
|
"@size-limit/file": "^14.2.0",
|
|
132
|
+
"@types/react": "^19.3.0",
|
|
133
|
+
"@types/react-dom": "^19.3.0",
|
|
134
|
+
"archunit": "^2.5.4",
|
|
135
|
+
"happy-dom": "^21.0.4",
|
|
124
136
|
"jotai": "^3.0.1",
|
|
125
137
|
"lefthook": "2.2.1",
|
|
126
138
|
"lodash": "4.17.21",
|
|
127
139
|
"mobx": "^7.0.6",
|
|
128
140
|
"publint": "^0.3.25",
|
|
141
|
+
"react": "^19.3.1",
|
|
142
|
+
"react-dom": "^19.3.1",
|
|
129
143
|
"redux": "^5.0.1",
|
|
130
144
|
"size-limit": "^14.2.0",
|
|
131
145
|
"tsdown": "0.23.1",
|
|
@@ -144,7 +158,7 @@
|
|
|
144
158
|
"name": "createBus",
|
|
145
159
|
"path": "dist/index.js",
|
|
146
160
|
"import": "{ createBus }",
|
|
147
|
-
"limit": "1.
|
|
161
|
+
"limit": "1.3 kB"
|
|
148
162
|
},
|
|
149
163
|
{
|
|
150
164
|
"name": "policies (all)",
|
|
@@ -154,23 +168,31 @@
|
|
|
154
168
|
{
|
|
155
169
|
"name": "effects (all)",
|
|
156
170
|
"path": "dist/effects.js",
|
|
157
|
-
"limit": "2.
|
|
171
|
+
"limit": "2.45 kB"
|
|
158
172
|
},
|
|
159
173
|
{
|
|
160
174
|
"name": "actions (all)",
|
|
161
175
|
"path": "dist/actions.js",
|
|
162
|
-
"limit": "
|
|
176
|
+
"limit": "1850 B"
|
|
163
177
|
},
|
|
164
178
|
{
|
|
165
179
|
"name": "redux",
|
|
166
180
|
"path": "dist/redux.js",
|
|
167
|
-
"limit": "1.
|
|
181
|
+
"limit": "1.55 kB"
|
|
168
182
|
},
|
|
169
183
|
{
|
|
170
184
|
"name": "observable",
|
|
171
185
|
"path": "dist/observable.js",
|
|
172
186
|
"limit": "0.5 kB"
|
|
173
187
|
},
|
|
188
|
+
{
|
|
189
|
+
"name": "react",
|
|
190
|
+
"path": "dist/react.js",
|
|
191
|
+
"ignore": [
|
|
192
|
+
"react"
|
|
193
|
+
],
|
|
194
|
+
"limit": "320 B"
|
|
195
|
+
},
|
|
174
196
|
{
|
|
175
197
|
"name": "dev",
|
|
176
198
|
"path": "dist/dev.js",
|
|
@@ -181,5 +203,13 @@
|
|
|
181
203
|
"path": "dist/production/dev.js",
|
|
182
204
|
"limit": "100 B"
|
|
183
205
|
}
|
|
184
|
-
]
|
|
206
|
+
],
|
|
207
|
+
"peerDependencies": {
|
|
208
|
+
"react": ">=18"
|
|
209
|
+
},
|
|
210
|
+
"peerDependenciesMeta": {
|
|
211
|
+
"react": {
|
|
212
|
+
"optional": true
|
|
213
|
+
}
|
|
214
|
+
}
|
|
185
215
|
}
|
package/dist/bus-CRnlwmQ4.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./onAbort-BgMfspK4.js";import{a as t,n,r}from"./context-DlA80GOA.js";import{n as i}from"./promise-CSLpzwSR.js";import{n as a,t as o}from"./event-0RIBGYqS.js";const s=`*`,c=()=>{let e={},t=/* @__PURE__ */ new WeakSet,n=n=>{let r=e[n]??[];if(!t.has(r))return e[n]=r,r;let i=[...r];return e[n]=i,i},r=(t,r)=>{if(!r){e[t]=[];return}let i=(e[t]??[]).indexOf(r);i>=0&&n(t).splice(i,1)};return{get:n=>{let r=e[n]??[];return t.add(r),r},add:(e,t)=>(n(e).push(t),()=>{r(e,t)}),remove:r}},l=(e,t,n)=>Reflect.apply(e,null,[t,n]),u=(s={})=>{let u=c(),d=(e,t)=>u.add(o(e),t),f=(e,t)=>u.remove(o(e),t),p=(t,a)=>{let{onError:o}=s,{ctx:c}=n({event:a,bus:m,tracer:s.trace,parent:{ref:r()}});if(!o){t(a.payload,c);return}let l=t=>{try{o(t,a)}catch(t){e(`onError failed`,t)}};try{let e=t(a.payload,c);i(e)&&Promise.resolve(e).catch(l)}catch(e){l(e)}},m={on:d,off:f,emit:(e,i)=>{let c=o(e),d=a(e,i),f={type:c,payload:d},h=[...u.get(c),...u.get(`*`)];h.length===0&&typeof e!=`function`&&s.onUnhandled?.(f);for(let e of h)p(e,f);if(typeof e==`function`){let{ctx:i}=n({event:f,bus:m,tracer:s.trace,parent:{ref:r()}}),a=m.commands?.run??l;return t(i,`command`,()=>a(e,d,i))}},use:e=>e(m),context:s.context,trace:s.trace};return m};export{s as n,u as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e,c as t,n,r}from"./context-yAWj0BFZ.js";import{n as i}from"./promise-CSLpzwSR.js";import{n as a,t as o}from"./event-0RIBGYqS.js";const s=`*`,c=()=>{let e={},t=/* @__PURE__ */ new WeakSet,n=n=>{let r=e[n]??[];if(!t.has(r))return e[n]=r,r;let i=[...r];return e[n]=i,i},r=(t,r)=>{if(!r){e[t]=[];return}let i=(e[t]??[]).indexOf(r);i>=0&&n(t).splice(i,1)};return{get:n=>{let r=e[n]??[];return t.add(r),r},add:(e,t)=>(n(e).push(t),()=>{r(e,t)}),remove:r}},l=(e,t,n)=>Reflect.apply(e,null,[t,n]),u=(s={})=>{let u=c(),d=(e,t)=>u.add(o(e),t),f=(e,t)=>u.remove(o(e),t),p=(e,a)=>{let{onError:o}=s,{ctx:c}=n({event:a,bus:m,tracer:s.trace,parent:{ref:r()}});if(!o){e(a.payload,c);return}let l=e=>{try{o(e,a)}catch(e){t(`onError failed`,e)}};try{let t=e(a.payload,c);i(t)&&Promise.resolve(t).catch(l)}catch(e){l(e)}},m={on:d,off:f,emit:(t,i)=>{let c=o(t),d=a(t,i),f={type:c,payload:d},h=[...u.get(c),...u.get(`*`)];h.length===0&&typeof t!=`function`&&s.onUnhandled?.(f);for(let e of h)p(e,f);if(typeof t==`function`){let{ctx:i}=n({event:f,bus:m,tracer:s.trace,parent:{ref:r()}}),a=m.commands?.run??l;return e(i,`command`,()=>a(t,d,i))}},use:e=>e(m),context:s.context,trace:s.trace};return m};export{s as n,u as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e=e=>typeof e==`string`?e:e.type,t=(e,t)=>typeof e==`object`?e.payload:t;export{t as n,e as t};
|