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.
Files changed (60) hide show
  1. package/README.md +53 -55
  2. package/dist/{action-Bdfp-Wvd.d.ts → action-creator-DOWcbXpy.d.ts} +79 -73
  3. package/dist/actions.d.ts +75 -6
  4. package/dist/actions.js +1 -1
  5. package/dist/bus-BAs9x7IQ.js +1 -0
  6. package/dist/{context-DlA80GOA.js → context-CK0ZomWt.js} +1 -1
  7. package/dist/context-plugin-B0sLWOxR.d.ts +34 -0
  8. package/dist/dev.d.ts +2 -2
  9. package/dist/effects.d.ts +153 -56
  10. package/dist/effects.js +1 -1
  11. package/dist/index.d.ts +3 -2
  12. package/dist/index.js +1 -1
  13. package/dist/{module-I1ixyJzx.d.ts → module-DCJl-qfi.d.ts} +24 -9
  14. package/dist/notrace/{action-Bdfp-Wvd.d.ts → action-creator-DOWcbXpy.d.ts} +79 -73
  15. package/dist/notrace/actions.d.ts +97 -13
  16. package/dist/notrace/actions.js +1 -1
  17. package/dist/notrace/bus-Bdk0YyFQ.js +1 -0
  18. package/dist/notrace/{context-yAWj0BFZ.js → context-CctVmHLC.js} +1 -1
  19. package/dist/notrace/context-plugin-B0sLWOxR.d.ts +34 -0
  20. package/dist/notrace/{delay-Cgvn16oY.js → delay-B_W1tnkS.js} +1 -1
  21. package/dist/notrace/effects.d.ts +153 -56
  22. package/dist/notrace/effects.js +1 -1
  23. package/dist/notrace/index.d.ts +3 -2
  24. package/dist/notrace/index.js +1 -1
  25. package/dist/notrace/policies.d.ts +1 -1
  26. package/dist/notrace/policies.js +1 -1
  27. package/dist/notrace/redux.d.ts +18 -20
  28. package/dist/notrace/redux.js +1 -1
  29. package/dist/observable.d.ts +1 -1
  30. package/dist/policies.d.ts +1 -1
  31. package/dist/policies.js +1 -1
  32. package/dist/react.d.ts +50 -0
  33. package/dist/react.js +1 -0
  34. package/dist/redux.d.ts +18 -20
  35. package/dist/redux.js +1 -1
  36. package/dist/trace.d.ts +1 -1
  37. package/docs/README.md +30 -9
  38. package/docs/actions.md +117 -41
  39. package/docs/context.md +48 -7
  40. package/docs/effects.md +229 -73
  41. package/docs/errors.md +23 -10
  42. package/docs/guide.md +238 -129
  43. package/docs/hmr.md +25 -13
  44. package/docs/migrating-from-effector.md +293 -0
  45. package/docs/migrating-from-rxjs.md +127 -0
  46. package/docs/migrating-from-saga.md +93 -0
  47. package/docs/observable.md +11 -9
  48. package/docs/package.md +24 -0
  49. package/docs/policies.md +93 -30
  50. package/docs/react.md +157 -0
  51. package/docs/semantics.md +5 -3
  52. package/docs/stores.md +488 -25
  53. package/docs/tracing.md +69 -54
  54. package/docs/typescript.md +153 -0
  55. package/llms-full.txt +2645 -0
  56. package/llms.txt +48 -0
  57. package/package.json +39 -9
  58. package/dist/bus-CRnlwmQ4.js +0 -1
  59. package/dist/notrace/bus-Dx0l9X6h.js +0 -1
  60. 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.3.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.2 kB gzip.",
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.2 kB"
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.3 kB"
171
+ "limit": "2.45 kB"
158
172
  },
159
173
  {
160
174
  "name": "actions (all)",
161
175
  "path": "dist/actions.js",
162
- "limit": "1.8 kB"
176
+ "limit": "1850 B"
163
177
  },
164
178
  {
165
179
  "name": "redux",
166
180
  "path": "dist/redux.js",
167
- "limit": "1.5 kB"
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
  }
@@ -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};