nanoeffects 0.28.0 → 0.29.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 (76) hide show
  1. package/dist/{action-creator-CcAEvUnw.d.ts → action-creator-jeEqIKgK.d.ts} +34 -32
  2. package/dist/actions.d.ts +18 -18
  3. package/dist/actions.js +1 -1
  4. package/dist/bus-0uYn_kRj.js +1 -0
  5. package/dist/context-DtUnzC-1.js +1 -0
  6. package/dist/context-types-Bme1mzkn.d.ts +31 -0
  7. package/dist/context.d.ts +8 -3
  8. package/dist/context.js +1 -1
  9. package/dist/{delay-18LJ8jSk.js → delay-5OhJZZQ0.js} +1 -1
  10. package/dist/dev.d.ts +2 -2
  11. package/dist/effects.d.ts +2 -2
  12. package/dist/effects.js +1 -1
  13. package/dist/index.d.ts +2 -2
  14. package/dist/index.js +1 -1
  15. package/dist/match.d.ts +3 -3
  16. package/dist/match.js +1 -1
  17. package/dist/{module-C_oEXw1n.d.ts → module-BWMW83qk.d.ts} +38 -38
  18. package/dist/notrace/{action-creator-DxOvVo8I.d.ts → action-creator-xpQ_I2h8.d.ts} +34 -32
  19. package/dist/notrace/actions.d.ts +52 -52
  20. package/dist/notrace/actions.js +1 -1
  21. package/dist/notrace/{bus-DmKn4SDD.js → bus-37nlVljc.js} +1 -1
  22. package/dist/notrace/effects.d.ts +2 -2
  23. package/dist/notrace/index.d.ts +2 -2
  24. package/dist/notrace/index.js +1 -1
  25. package/dist/notrace/{plugin-lJjjd-SN.d.ts → plugin-6LhNx0th.d.ts} +1 -1
  26. package/dist/notrace/policies.d.ts +1 -1
  27. package/dist/notrace/redux.d.ts +1 -1
  28. package/dist/observable.d.ts +43 -1
  29. package/dist/observable.js +1 -1
  30. package/dist/onAbort-BgMfspK4.js +1 -0
  31. package/dist/oop.d.ts +3 -3
  32. package/dist/oop.js +1 -1
  33. package/dist/{plugin-CuvIgjnX.d.ts → plugin-BaErevLy.d.ts} +2 -2
  34. package/dist/policies.d.ts +2 -2
  35. package/dist/policies.js +1 -1
  36. package/dist/react.d.ts +2 -2
  37. package/dist/react.js +1 -1
  38. package/dist/redux.d.ts +1 -1
  39. package/dist/scope.d.ts +9 -9
  40. package/dist/signal-field-key-CWT-3OXC.js +1 -0
  41. package/dist/signal.d.ts +34 -6
  42. package/dist/signal.js +1 -1
  43. package/dist/svelte.d.ts +1 -1
  44. package/dist/trace.d.ts +20 -5
  45. package/dist/trace.js +1 -1
  46. package/dist/{types-FV8fuvI9.d.ts → types-D5xsR37j.d.ts} +2 -2
  47. package/dist/vue.d.ts +1 -1
  48. package/dist/{with-policy-3bhFLEXs.d.ts → with-policy-BZVRBUOm.d.ts} +1 -1
  49. package/dist/{with-policy-D-SQRkPh.js → with-policy-C6BIiPIi.js} +1 -1
  50. package/docs/README.md +13 -1
  51. package/docs/actions.md +27 -1
  52. package/docs/chat-example.md +12 -0
  53. package/docs/chat-widget.md +7 -7
  54. package/docs/context.md +33 -1
  55. package/docs/effects.md +20 -9
  56. package/docs/guide.md +20 -2
  57. package/docs/migrating-from-effector.md +11 -0
  58. package/docs/observable.md +43 -0
  59. package/docs/oop.md +17 -0
  60. package/docs/package.md +22 -13
  61. package/docs/plugins.md +69 -11
  62. package/docs/query-libraries.md +273 -5
  63. package/docs/react.md +12 -2
  64. package/docs/scope.md +14 -2
  65. package/docs/semantics.md +10 -0
  66. package/docs/server.md +3 -3
  67. package/docs/stability.md +2 -2
  68. package/docs/tracing.md +74 -6
  69. package/docs/typescript.md +1 -1
  70. package/llms-full.txt +671 -66
  71. package/llms.txt +7 -7
  72. package/package.json +4 -4
  73. package/skills/nanoeffects/SKILL.md +2 -2
  74. package/dist/bus-DlpEluzd.js +0 -1
  75. package/dist/context-UcmrAIhP.js +0 -1
  76. package/dist/context-types-hCKgU8sC.d.ts +0 -14
package/llms.txt CHANGED
@@ -10,11 +10,11 @@ Rules that generated code often gets wrong:
10
10
  - Effects take `ctx` as the first argument: `retry(ctx, fn, options)`, `timeout(ctx, ms, fn)`, `take(ctx, "event")`.
11
11
  - Policies wrap a handler: `bus.on("search", latest(async (query, ctx) => { ... }))`.
12
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` and `bus.useEventState`; `usePolicy`; needs React), `nanoeffects/svelte` (`sveltePlugin`, adds `bus.eventStore`; needs Svelte), `nanoeffects/vue` (`vuePlugin`, adds `bus.watchEmitter` and `bus.useEventRef`; needs Vue), `nanoeffects/trace` (`createTracer`, loggers, `tracePlugin`), `nanoeffects/dev`.
13
- - `bus.emit(command(payload))` runs the command's handler and returns its result. Plain events return nothing.
13
+ - `bus.emit(action(payload))` runs the action's handler and returns its result. Plain events return nothing.
14
14
 
15
15
  ## Start here
16
16
 
17
- - [Guide](docs/guide.md): bus, handler context, policies, effects, commands and modules, step by step
17
+ - [Guide](docs/guide.md): bus, handler context, policies, effects, actions and modules, step by step
18
18
  - [Start a project from a template](docs/starter.md): `npm create nanoeffects` makes a Vite project (`vanilla`, `react`, `vue-ts`, `svelte-ts` and others, in JavaScript or TypeScript) with a bus, `debounce` and `latest`
19
19
  - [Why nanoeffects exists](docs/motivation.md): logic and side effects outside UI components as plain async functions, no dependencies and no global state for SDKs and Module Federation, and why not redux-saga, RxJS, Redux or Effector
20
20
  - [Package entries](docs/package.md): which import holds what
@@ -32,9 +32,9 @@ Rules that generated code often gets wrong:
32
32
 
33
33
  ## Domain logic and stores
34
34
 
35
- - [Actions, jobs and modules](docs/actions.md): `createAction`, `createAction`, `createJob`, `createModule`
35
+ - [Actions, jobs and modules](docs/actions.md): `createAction` (with or without a handler), `createJob`, `createModule`
36
36
  - [Connect Redux, Zustand, MobX, or Pinia](docs/stores.md): the Redux middleware and callbacks of other stores
37
- - [Use nanoeffects with React Query and SWR](docs/query-libraries.md): call a command from `queryFn` or the SWR fetcher; `signalPlugin` passes the abort of the library to the task
37
+ - [Use nanoeffects with React Query, SWR and RTK Query](docs/query-libraries.md): call an action from `queryFn` or the SWR fetcher; `signalPlugin` passes the abort of the library to the task; `fromSignal` clients, a live stream into the cache with `events`, refetch on a bus event
38
38
  - [Stop work on a server when the client leaves](docs/server.md): one `AbortController` for each request or socket, `signalPlugin`, a clean shutdown, and a queue worker; Fastify examples
39
39
  - [Build a sign-up form in React](docs/react.md): a form with a username check, a submit that cannot fire twice, and retry; `useEventState` shows an event as state, `usePolicy` keeps a debounced handler between renders
40
40
  - [Build a chat with entities, features, modules and a small server](docs/chat-example.md): rooms, a history under `latest`, a send under `queue` and `retry`, a search with `allSettled` and `timeout`, new messages polled with `poll`
@@ -42,12 +42,12 @@ Rules that generated code often gets wrong:
42
42
  - [Use nanoeffects in a Vue app](docs/vue.md): `vuePlugin` adds `watchEmitter` (a value of a component to the bus) and `useEventRef` (an event as a ref)
43
43
  - [Use nanoeffects in a Svelte app](docs/svelte.md): `sveltePlugin` adds `eventStore` (an event as a Svelte store)
44
44
  - [Context fields](docs/context.md): put a store or client on every task
45
- - [Scopes](docs/scope.md): fields for one command, action, job, module or `emit`, and a way to replace them in a test
45
+ - [Scopes](docs/scope.md): fields for one action, job, module or `emit`, and a way to replace them in a test
46
46
  - [Use the bus from a class](docs/oop.md): `Emitter`, `extendBus`, `@WithBus`, `@On`, `@Once`, and `dispose()` for the subscriptions of an instance
47
47
 
48
48
  ## TypeScript
49
49
 
50
- - [TypeScript in many files](docs/typescript.md): keep the types of the bus in commands and modules
50
+ - [TypeScript in many files](docs/typescript.md): keep the types of the bus in actions and modules
51
51
 
52
52
  ## Coming from another library
53
53
 
@@ -60,5 +60,5 @@ Rules that generated code often gets wrong:
60
60
 
61
61
  - [Semantics](docs/semantics.md): exact rules of emit, abort and ordering
62
62
  - [Trace tasks](docs/tracing.md): loggers, Redux DevTools, the `notrace` build
63
- - [Turn events into Observables](docs/observable.md): `createObserve`, `Subject`
63
+ - [Turn events into Observables](docs/observable.md): `createObserve`, `Subject`, `events` (an event as a `for await` loop)
64
64
  - [Hot reload and development diagnostics](docs/hmr.md): `devPlugin`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nanoeffects",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Business logic and side effects outside UI components, as plain async functions. Tiny, no dependencies.",
5
5
  "keywords": [
6
6
  "event-bus",
@@ -236,12 +236,12 @@
236
236
  {
237
237
  "name": "signal (plugin)",
238
238
  "path": "dist/signal.js",
239
- "limit": "0.6 kB"
239
+ "limit": "0.7 kB"
240
240
  },
241
241
  {
242
242
  "name": "context (plugin)",
243
243
  "path": "dist/context.js",
244
- "limit": "0.2 kB"
244
+ "limit": "0.4 kB"
245
245
  },
246
246
  {
247
247
  "name": "oop (class entry)",
@@ -261,7 +261,7 @@
261
261
  {
262
262
  "name": "observable",
263
263
  "path": "dist/observable.js",
264
- "limit": "0.5 kB"
264
+ "limit": "0.85 kB"
265
265
  },
266
266
  {
267
267
  "name": "react",
@@ -26,7 +26,7 @@ Do not write the setup by hand. `npm create nanoeffects@latest my-app -- --templ
26
26
 
27
27
  - `vanilla`, `react`: JavaScript, one search handler with `debounce` and `latest`.
28
28
  - `vanilla-ts`, `react-ts`: the same apps in TypeScript.
29
- - `domains-ts`: React and TypeScript with the logic split by domain (commands, a job, modules). Pick it for an app with several features.
29
+ - `domains-ts`: React and TypeScript with the logic split by domain (actions, a job, modules). Pick it for an app with several features.
30
30
 
31
31
  In an existing project, start from `docs/cancel-stale-requests.md` (races) or `docs/guide.md`.
32
32
 
@@ -38,7 +38,7 @@ In an existing project, start from `docs/cancel-stale-requests.md` (races) or `d
38
38
  - Effects take `ctx` first: `retry(ctx, fn, options)`, `timeout(ctx, ms, fn)`, `take(ctx, "event")`. The wrapper form is `retry(fn, options)`.
39
39
  - Policies wrap a handler: `bus.on("search", latest(async (query, ctx) => { ... }))`.
40
40
  - Import each part from its path: `nanoeffects`, `nanoeffects/policies`, `nanoeffects/effects`, `nanoeffects/actions`, `nanoeffects/redux`, `nanoeffects/react`.
41
- - `bus.emit(command(payload))` returns the command's result. Plain events return nothing.
41
+ - `bus.emit(action(payload))` returns the action's result. Plain events return nothing.
42
42
  - The bus keeps no values: an event emitted before a listener exists is lost. `useEventState(event, initial)` (`nanoeffects/react`) is state of one component, not a store. Share a value through a Context provider at the root or a state manager.
43
43
 
44
44
  ## Where to read more
@@ -1 +0,0 @@
1
- import{d as e,n as t,o as n,r}from"./context-UcmrAIhP.js";import{n as i,t as a}from"./event-DVcW0mME.js";const o=()=>{let e={},t={},n=n=>(t[n]=void 0,e[n]??=/* @__PURE__ */ new Map,e[n]),r=(e,t)=>{let r=n(e),i=r.get(t)??0;i>1?r.set(t,i-1):t?r.delete(t):r.clear()},i=()=>{e={},t={}},a=n=>n===void 0?Object.keys(e).flatMap(a):(t[n]??=[...e[n]??[]].flatMap(([e,t])=>Array(t).fill(e)),t[n]);return{get:a,add:(e,t)=>{let i=n(e);return i.set(t,(i.get(t)??0)+1),()=>r(e,t)},remove:r,clear:i}},s=Symbol(),c=(e,t,n)=>{let r={type:t,payload:n};return Object.defineProperty(r,s,{value:e,enumerable:!1}),r},l=e=>{if(typeof e==`function`)return e;if(typeof e==`object`&&e&&s in e)return e[s]},u=(e,t,n)=>Reflect.apply(e,null,[t,n]),d=(s={})=>{let c=o(),d=(e,t)=>c.add(a(e),t),f=(e,t)=>{let n=d(e,(e,r)=>(n(),t(e,r)));return n},p=(e,t)=>{e===void 0?c.clear():c.remove(a(e),t)},m=e=>t({event:e,bus:g,tracer:s.trace,parent:{ref:r()}}).ctx,h=(t,n)=>{let{onError:r}=s,i=m(n);if(!r){t(n.payload,i);return}let a=t=>{try{r(t,n)}catch(t){e(`onError failed`,t)}};try{let e=t(n.payload,i);typeof e?.then==`function`&&Promise.resolve(e).catch(a)}catch(e){a(e)}},g={get:c.get,on:d,off:p,once:f,emit:(e,t)=>{let r=a(e),o=i(e,t),d={type:r,payload:o},f=l(e);f||=g.actions?.bound?.(r);let p=[...c.get(r),...c.get(`*`)];p.length===0&&!f&&s.onUnhandled?.(d);for(let e of p)h(e,d);if(f){let e=m(d),t=g.actions?.run??u;return n(e,`command`,()=>t(f,o,e))}},use:e=>e(g),ctx:s.context,trace:s.trace};return g};export{d as n,c as r,l as t};
@@ -1 +0,0 @@
1
- const e=(e,t)=>{globalThis.console?.error(`[nanoeffects] ${e}`,t)},t=()=>{},n=/* @__PURE__ */ new WeakMap,r=t=>{let r=n.get(t);if(r)return r;let i=/* @__PURE__ */ new Set;return n.set(t,i),t.addEventListener(`abort`,()=>{let n=[...i];i.clear();for(let{fn:r}of n)try{r(t.reason)}catch(t){e(`abort callback failed`,t)}},{once:!0}),i},i=(e,n)=>{let{signal:i}=e;if(!i)return t;if(i.aborted)return n(i.reason),t;let a=r(i),o={fn:n};return a.add(o),()=>{a.delete(o)}},a=e=>{let t=new AbortController;return{controller:t,unlink:i({signal:e},e=>t.abort(e))}},o=Symbol(),s=typeof __NANOEFFECTS_TRACE__>`u`||__NANOEFFECTS_TRACE__,c=/* @__PURE__ */ new WeakMap;let l;const u=()=>l,d=()=>{},f=(e,t,n,r)=>{let i=s&&c.get(e);i&&i.tracer.report(i.ref,t,n,r)},p=(e,t)=>{let n=s&&c.get(e);n&&n.tracer.rename?.(n.ref,t)},m=(e,t)=>{let n=s&&c.get(e);return n?n.tracer.settler(n.ref,t):d},h=(e,t,n)=>{let r=s&&c.get(e);return r?r.tracer.run(r.ref,t,e.signal,n):n()},g=Symbol(`nanoeffects.addContext`),_=(e,t)=>typeof e==`function`?e(t):e,v=({event:e,bus:t,tracer:n,parent:r})=>{let{controller:u,unlink:f}=a(r?.signal),{signal:p}=u,m=s&&n?{tracer:n,ref:n.task(e,r?.ref)}:void 0,y=(...e)=>{if(p.aborted&&!S[o])return;let n=t?.emit,r=l;l=m?.ref;try{return n?.(...e)}finally{l=r}},b=(...e)=>{if(p.aborted)return d;let n=t?.on,r=n?.(...e);if(!r)return d;let a=i({signal:p},r);return()=>{a(),r()}},x=async(r,...i)=>{p.throwIfAborted();let a=i[0],o=v({event:{type:e.type,payload:a},bus:t,tracer:n,parent:{signal:p,ref:m?.ref}});try{return await h(o.ctx,`run`,()=>r(a,o.ctx))}finally{o.unlink()}},S={..._(t?.ctx,e),type:e.type,payload:e.payload,signal:p,abort:e=>u.abort(e),emit:y,on:b,off:t?.off??d,run:x,[g]:t?.addContext};return t?.addContext?.(S),m&&c.set(S,m),{ctx:S,unlink:f}},y=(e,t)=>{let n=s?c.get(e):void 0;return v({event:{type:t??e.type??``,payload:e.payload},bus:{emit:e.emit,on:e.on,off:e.off,ctx:e,addContext:Reflect.get(e,g)},tracer:n?.tracer,parent:{signal:e.signal,ref:n?.ref}})};export{p as a,s as c,e as d,y as i,o as l,v as n,h as o,u as r,f as s,m as t,i as u};
@@ -1,14 +0,0 @@
1
- import { C as ContextOf, H as EventMap } from "./action-creator-CcAEvUnw.js";
2
- //#region src/core/context-types.d.ts
3
- /** What a function that makes the fields of a task gets to see. */
4
- type ContextTask = {
5
- type: string;
6
- payload?: unknown;
7
- };
8
- /**
9
- * `unknown` when none of the `fields` is already a context field of the bus,
10
- * else `never`: the call does not compile. Used as `bus: Bus<E> & NoClash<…>`.
11
- */
12
- type NoClash<Fields extends object, E extends EventMap> = [keyof Fields & keyof ContextOf<E>] extends [never] ? unknown : never;
13
- //#endregion
14
- export { NoClash as n, ContextTask as t };