@siggn/react 0.1.4 → 0.2.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 CHANGED
@@ -166,6 +166,24 @@ function LocalComponent() {
166
166
  }
167
167
  ```
168
168
 
169
+ ### Using Middleware
170
+
171
+ You can use the `useMiddleware` hook to register middleware for a `Siggn` instance. The middleware intercepts messages before they are delivered to subscribers and is automatically unregistered when the component unmounts.
172
+
173
+ ```tsx
174
+ import { useMiddleware } from '@siggn/react';
175
+ import { siggn } from '../siggn';
176
+
177
+ function LoggerComponent() {
178
+ useMiddleware(siggn, (msg, next) => {
179
+ console.log('Middleware:', msg);
180
+ next();
181
+ });
182
+
183
+ return null;
184
+ }
185
+ ```
186
+
169
187
  ## API
170
188
 
171
189
  ### `useSiggn<T>()`
@@ -176,12 +194,21 @@ Creates and returns a `Siggn` instance that persists for the lifetime of the com
176
194
 
177
195
  Returns a `Siggn<T>` instance.
178
196
 
179
- ### `useSubscribe(options, setup, deps)`
197
+ ### `useSubscribe(options, type, callback, deps)`
198
+
199
+ Subscribes to a single message type and automatically unsubscribes when the component unmounts.
200
+
201
+ - `options`: A `Siggn` instance or an object `{ instance: Siggn<T>; id?: string; }`.
202
+ - `type`: The message type to subscribe to.
203
+ - `callback`: The function to call when the message is received.
204
+ - `deps` (optional): A dependency array to control when the subscription is re-created.
205
+
206
+ ### `useSubscribeMany(options, setup, deps)`
180
207
 
181
- Subscribes to messages and automatically unsubscribes when the component unmounts.
208
+ Subscribes to multiple message types and automatically unsubscribes when the component unmounts.
182
209
 
183
210
  - `options`: A `Siggn` instance or an object `{ instance: Siggn<T>; id?: string; }`.
184
- - `setup`: A function that receives a `subscribe` helper to define subscriptions, similar to `subscribeMany` in `@siggn/core`.
211
+ - `setup`: A function that receives a `subscribe` helper to define subscriptions.
185
212
  - `deps` (optional): A dependency array to control when the subscriptions are re-created.
186
213
 
187
214
  ### `useSubscribeAll(options, callback, deps)`
@@ -189,9 +216,16 @@ Subscribes to messages and automatically unsubscribes when the component unmount
189
216
  Subscribes to all messages and automatically unsubscribes when the component unmounts.
190
217
 
191
218
  - `options`: A `Siggn` instance or an object `{ instance: Siggn<T>; id?: string; }`.
192
- - `callback`: A function that will be called with every message.
193
219
  - `deps` (optional): A dependency array to control when the subscriptions are re-created.
194
220
 
221
+ ### `useMiddleware(instance, middleware, deps)`
222
+
223
+ Registers a middleware and automatically unregisters it when the component unmounts.
224
+
225
+ - `instance`: A `Siggn` instance.
226
+ - `middleware`: The middleware function.
227
+ - `deps` (optional): A dependency array to control when the middleware is re-registered.
228
+
195
229
  ## License
196
230
 
197
231
  This project is licensed under the [MIT License](LICENSE).
package/dist/hooks.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Msg, Siggn } from '@siggn/core';
1
+ import { Middleware, Msg, Siggn } from '@siggn/core';
2
2
  import { SubscriptionOptions } from 'packages/react/src/types';
3
3
  import { DependencyList } from 'react';
4
4
  /**
@@ -91,5 +91,30 @@ export declare function useSubscribe<M extends Msg, T extends M['type']>(options
91
91
  * }
92
92
  * ```
93
93
  */
94
- export declare function useSubscribeAll<T extends Msg>(options: SubscriptionOptions<T>, callback: (msg: T) => void, deps?: DependencyList): void;
94
+ export declare function useSubscribeAll<M extends Msg>(options: SubscriptionOptions<M>, callback: (msg: M) => void, deps?: DependencyList): void;
95
+ /**
96
+ * Adds a middleware to a `Siggn` instance that persists for the lifetime of the component.
97
+ * Automatically removes the middleware when the component unmounts.
98
+ *
99
+ * @template M A union of all possible message types.
100
+ * @param options A `Siggn` instance or an object with the instance.
101
+ * @param middleware The middleware function to add.
102
+ * @param deps An optional dependency array to control when the middleware is re-added.
103
+ * @category Middleware
104
+ * @since 0.0.6
105
+ * @example
106
+ *
107
+ * ```tsx
108
+ * import { siggn } from './siggn';
109
+ *
110
+ * function LoggerComponent() {
111
+ * useMiddleware(siggn, async (msg, next) => {
112
+ * console.log('Middleware:', msg);
113
+ * next();
114
+ * }, []);
115
+ * // ...
116
+ * }
117
+ * ```
118
+ */
119
+ export declare function useMiddleware<M extends Msg>(instance: Siggn<M>, middleware: Middleware<M>, deps?: React.DependencyList): void;
95
120
  //# sourceMappingURL=hooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAE1E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAGlD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,GAAG,EAC5C,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC/B,KAAK,EAAE,CACL,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,KAAK,IAAI,KAC7C,IAAI,KACN,IAAI,EACT,IAAI,GAAE,cAAmB,QAe1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC7D,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC/B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,KAAK,IAAI,EAChD,IAAI,GAAE,cAAmB,QAe1B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,GAAG,EAC3C,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC/B,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAC1B,IAAI,GAAE,cAAmB,QAe1B"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAE1E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAGlD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,GAAG,EAC5C,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC/B,KAAK,EAAE,CACL,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,KAAK,IAAI,KAC7C,IAAI,KACN,IAAI,EACT,IAAI,GAAE,cAAmB,QAe1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC7D,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC/B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,KAAK,IAAI,EAChD,IAAI,GAAE,cAAmB,QAe1B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,GAAG,EAC3C,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC/B,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAC1B,IAAI,GAAE,cAAmB,QAe1B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,GAAG,EACzC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAClB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EACzB,IAAI,GAAE,KAAK,CAAC,cAAmB,QAMhC"}
package/dist/index.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react");class t{nextId=0;subscriptions;globalSubscriptions;middlewares;constructor(){this.subscriptions=new Map,this.globalSubscriptions=[],this.middlewares=[]}use(s){this.middlewares.push(s)}createClone(){return new t}makeId(s){return s??`sub_${(this.nextId++).toString(36)}`}make(s){return{subscribe:(e,u)=>{this.subscribe(s,e,u)},unsubscribe:()=>{this.unsubscribe(s)},subscribeMany:e=>{this.subscribeMany(s,e)},subscribeAll:e=>{this.subscribeAll(s,e)}}}subscribeMany(s,e){e((u,b)=>this.subscribe(s,u,b))}subscribe(s,e,u){this.subscriptions.has(e)||this.subscriptions.set(e,[]),this.subscriptions.get(e)?.push({id:s,ref:u})}subscribeAll(s,e){this.globalSubscriptions.push({id:s,ref:e})}publish(s){this.globalSubscriptions.forEach(e=>{e.ref(s)}),this.subscriptions.has(s.type)&&this.subscriptions.get(s.type)?.forEach(e=>{e.ref(s)})}unsubscribe(s){this.unsubscribeGlobal(s);for(const[e,u]of this.subscriptions)this.subscriptions.set(e,u.filter(b=>b.id!==s))}unsubscribeGlobal(s){this.globalSubscriptions=this.globalSubscriptions.filter(e=>e.id!==s)}}function n(){const[i]=r.useState(new t);return i}function a(i,s,e=[]){const u=r.useMemo(()=>i instanceof t?i:i.instance,[i]),b=r.useMemo(()=>u.makeId("id"in i?i.id:void 0),[u]);r.useEffect(()=>(u.subscribeMany(b,s),()=>{u.unsubscribe(b)}),[u,b,...e])}function l(i,s,e,u=[]){const b=r.useMemo(()=>i instanceof t?i:i.instance,[i]),c=r.useMemo(()=>b.makeId("id"in i?i.id:void 0),[b]);r.useEffect(()=>(b.subscribe(c,s,e),()=>{b.unsubscribe(c)}),[b,c,...u])}function o(i,s,e=[]){const u=r.useMemo(()=>i instanceof t?i:i.instance,[i]),b=r.useMemo(()=>u.makeId("id"in i?i.id:void 0),[u]);r.useEffect(()=>(u.subscribeAll(b,s),()=>{u.unsubscribeGlobal(b)}),[u,b,...e])}exports.Siggn=t;exports.useSiggn=n;exports.useSubscribe=l;exports.useSubscribeAll=o;exports.useSubscribeMany=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("@siggn/core"),n=require("react");function b(){const[e]=n.useState(new i.Siggn);return e}function a(e,s,r=[]){const u=n.useMemo(()=>e instanceof i.Siggn?e:e.instance,[e]),c=n.useMemo(()=>u.makeId("id"in e?e.id:void 0),[u]);n.useEffect(()=>(u.subscribeMany(c,s),()=>{u.unsubscribe(c)}),[u,c,...r])}function d(e,s,r,u=[]){const c=n.useMemo(()=>e instanceof i.Siggn?e:e.instance,[e]),t=n.useMemo(()=>c.makeId("id"in e?e.id:void 0),[c]);n.useEffect(()=>(c.subscribe(t,s,r),()=>{c.unsubscribe(t)}),[c,t,...u])}function f(e,s,r=[]){const u=n.useMemo(()=>e instanceof i.Siggn?e:e.instance,[e]),c=n.useMemo(()=>u.makeId("id"in e?e.id:void 0),[u]);n.useEffect(()=>(u.subscribeAll(c,s),()=>{u.unsubscribeGlobal(c)}),[u,c,...r])}function l(e,s,r=[]){n.useEffect(()=>e.use(s),[e,s,...r])}exports.useMiddleware=l;exports.useSiggn=b;exports.useSubscribe=d;exports.useSubscribeAll=f;exports.useSubscribeMany=a;Object.keys(i).forEach(e=>{e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:()=>i[e]})});
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../core/dist/index.es.js","../src/hooks.ts"],"sourcesContent":["class r {\n nextId = 0;\n subscriptions;\n globalSubscriptions;\n middlewares;\n /**\n * Creates a new Siggn instance.\n * @category Lifecycle\n * @since 0.0.5\n */\n constructor() {\n this.subscriptions = /* @__PURE__ */ new Map(), this.globalSubscriptions = [], this.middlewares = [];\n }\n use(s) {\n this.middlewares.push(s);\n }\n /**\n * Creates a new, independent `Siggn` instance that inherits the message\n * types of its parent and adds new ones.\n *\n * @template C The new message types to add.\n * @returns A new `Siggn` instance with combined message types.\n * @category Lifecycle\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const baseSiggn = new Siggn<{ type: 'A' }>();\n * const childSiggn = baseSiggn.createClone<{ type: 'B' }>();\n * // childSiggn can now publish and subscribe to types 'A' and 'B'.\n * ```\n */\n createClone() {\n return new r();\n }\n /**\n * Generates a unique ID for a subscriber.\n * If an ID is provided, it will be used; otherwise, a new one is generated.\n *\n * @param id An optional ID to use.\n * @returns A unique subscriber ID.\n * @category Utilities\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn();\n * const id1 = siggn.makeId(); // e.g., \"sub_0\"\n * const id2 = siggn.makeId('custom-id'); // \"custom-id\"\n * ```\n */\n makeId(s) {\n return s ?? `sub_${(this.nextId++).toString(36)}`;\n }\n /**\n * Creates a subscription helper object that is pre-configured with a\n * specific subscriber ID. This simplifies managing multiple subscriptions\n * for a single component or service.\n *\n * @param id The subscriber ID to use for all subscriptions.\n * @returns An object with `subscribe`, `unsubscribe`, `subscribeMany`, and `subscribeAll` methods.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'event' }>();\n * const component = siggn.make('my-component');\n * component.subscribe('event', () => console.log('event received!'));\n * component.unsubscribe();\n * ```\n */\n make(s) {\n return {\n subscribe: (i, t) => {\n this.subscribe(s, i, t);\n },\n unsubscribe: () => {\n this.unsubscribe(s);\n },\n subscribeMany: (i) => {\n this.subscribeMany(s, i);\n },\n subscribeAll: (i) => {\n this.subscribeAll(s, i);\n }\n };\n }\n /**\n * Subscribes to multiple message types using a single subscriber ID.\n *\n * @param id The subscriber ID.\n * @param setup A function that receives a `subscribe` helper to register callbacks.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'A' } | { type: 'B' }>();\n * siggn.subscribeMany('subscriber-1', (subscribe) => {\n * subscribe('A', () => console.log('A received'));\n * subscribe('B', () => console.log('B received'));\n * });\n * ```\n */\n subscribeMany(s, i) {\n i((t, b) => this.subscribe(s, t, b));\n }\n /**\n * Subscribes to a specific message type.\n *\n * @param id The subscriber ID.\n * @param type The message type to subscribe to.\n * @param callback The function to call when a message of the specified type is published.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event', payload: string }>();\n * siggn.subscribe('subscriber-1', 'my-event', (msg) => {\n * console.log(msg.payload);\n * });\n * ```\n */\n subscribe(s, i, t) {\n this.subscriptions.has(i) || this.subscriptions.set(i, []), this.subscriptions.get(i)?.push({ id: s, ref: t });\n }\n /**\n * Subscribes to all message types. The callback will be invoked for every\n * message published on the bus.\n *\n * @param id The subscriber ID.\n * @param callback The function to call for any message.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'A' } | { type: 'B' }>();\n * siggn.subscribeAll('logger', (msg) => {\n * console.log(`Received message of type: ${msg.type}`);\n * });\n * ```\n */\n subscribeAll(s, i) {\n this.globalSubscriptions.push({ id: s, ref: i });\n }\n /**\n * Publishes a message to all relevant subscribers.\n *\n * @param msg The message to publish.\n * @category Publishing\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event' }>();\n * siggn.subscribe('sub-1', 'my-event', () => console.log('received'));\n * siggn.publish({ type: 'my-event' }); // \"received\"\n * ```\n */\n publish(s) {\n this.globalSubscriptions.forEach((i) => {\n i.ref(s);\n }), this.subscriptions.has(s.type) && this.subscriptions.get(s.type)?.forEach((i) => {\n i.ref(s);\n });\n }\n /**\n * Removes all subscriptions (both specific and global) for a given\n * subscriber ID.\n *\n * @param id The subscriber ID to unsubscribe.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event' }>();\n * siggn.subscribe('sub-1', 'my-event', () => console.log('received'));\n * siggn.unsubscribe('sub-1');\n * siggn.publish({ type: 'my-event' }); // (nothing is logged)\n * ```\n */\n unsubscribe(s) {\n this.unsubscribeGlobal(s);\n for (const [i, t] of this.subscriptions)\n this.subscriptions.set(\n i,\n t.filter((b) => b.id !== s)\n );\n }\n /**\n * Removes a global subscription for a given subscriber ID.\n *\n * @param id The subscriber ID to unsubscribe.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event' }>();\n * siggn.subscribeAll('logger', console.log);\n * siggn.unsubscribeGlobal('logger');\n * siggn.publish({ type: 'my-event' }); // (nothing is logged)\n * ```\n */\n unsubscribeGlobal(s) {\n this.globalSubscriptions = this.globalSubscriptions.filter((i) => i.id !== s);\n }\n}\nexport {\n r as Siggn\n};\n//# sourceMappingURL=index.es.js.map\n","import { type Msg, Siggn } from '@siggn/core';\nimport type { SubscriptionOptions } from 'packages/react/src/types';\nimport { useEffect, useMemo, useState, type DependencyList } from 'react';\n\n/**\n * Creates and returns a `Siggn` instance that persists for the lifetime of the component.\n * This is useful for creating a message bus scoped to a component and its children.\n *\n * @template T A union of all possible message types for the new instance.\n * @returns A `Siggn<T>` instance.\n * @category Lifecycle\n * @since 0.0.1\n * @example\n * \n```tsx\n * function MyComponent() {\n * const localSiggn = useSiggn<{ type: 'local-event' }>();\n * // ...\n * }\n * ```\n */\nexport function useSiggn<T extends Msg>(): Siggn<T> {\n const [siggn] = useState(new Siggn<T>());\n return siggn;\n}\n\n/**\n * Subscribes to multiple messages and automatically unsubscribes when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribeMany(siggn, (subscribe) => {\n * subscribe('user-created', (msg) => console.log(msg.name));\n * subscribe('user-updated', (msg) => console.log(msg.name));\n * });\n * // ...\n * }\n * ```\n */\nexport function useSubscribeMany<M extends Msg>(\n options: SubscriptionOptions<M>,\n setup: (\n subscribe: <T extends M['type']>(\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n ) => void,\n ) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeMany(id, setup);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to a single message and automatically unsubscribe when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribe(siggn, 'user-created', (msg) => console.log(msg.name));\n * // ...\n * }\n * ```\n */\nexport function useSubscribe<M extends Msg, T extends M['type']>(\n options: SubscriptionOptions<M>,\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribe(id, type, callback);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to all messages on a `Siggn` instance and automatically unsubscribes\n * when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param callback The function to call for any message.\n * @param deps An optional dependency array to control when the subscription is re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn';\n *\n * function LoggerComponent() {\n * useSubscribeAll(siggn, (msg) => {\n * console.log(`[LOG]: ${msg.type}`);\n * }, []);\n * // ...\n * }\n * ```\n */\nexport function useSubscribeAll<T extends Msg>(\n options: SubscriptionOptions<T>,\n callback: (msg: T) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeAll(id, callback);\n\n return () => {\n instance.unsubscribeGlobal(id);\n };\n }, [instance, id, ...deps]);\n}\n"],"names":["r","i","t","useSiggn","siggn","useState","Siggn","useSubscribeMany","options","setup","deps","instance","useMemo","id","useEffect","useSubscribe","type","callback","useSubscribeAll"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/hooks.ts"],"sourcesContent":["import { type Middleware, type Msg, Siggn } from '@siggn/core';\nimport type { SubscriptionOptions } from 'packages/react/src/types';\n\nimport { useEffect, useMemo, useState, type DependencyList } from 'react';\n\n/**\n * Creates and returns a `Siggn` instance that persists for the lifetime of the component.\n * This is useful for creating a message bus scoped to a component and its children.\n *\n * @template T A union of all possible message types for the new instance.\n * @returns A `Siggn<T>` instance.\n * @category Lifecycle\n * @since 0.0.1\n * @example\n * \n```tsx\n * function MyComponent() {\n * const localSiggn = useSiggn<{ type: 'local-event' }>();\n * // ...\n * }\n * ```\n */\nexport function useSiggn<T extends Msg>(): Siggn<T> {\n const [siggn] = useState(new Siggn<T>());\n return siggn;\n}\n\n/**\n * Subscribes to multiple messages and automatically unsubscribes when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribeMany(siggn, (subscribe) => {\n * subscribe('user-created', (msg) => console.log(msg.name));\n * subscribe('user-updated', (msg) => console.log(msg.name));\n * });\n * // ...\n * }\n * ```\n */\nexport function useSubscribeMany<M extends Msg>(\n options: SubscriptionOptions<M>,\n setup: (\n subscribe: <T extends M['type']>(\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n ) => void,\n ) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeMany(id, setup);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to a single message and automatically unsubscribe when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribe(siggn, 'user-created', (msg) => console.log(msg.name));\n * // ...\n * }\n * ```\n */\nexport function useSubscribe<M extends Msg, T extends M['type']>(\n options: SubscriptionOptions<M>,\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribe(id, type, callback);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to all messages on a `Siggn` instance and automatically unsubscribes\n * when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param callback The function to call for any message.\n * @param deps An optional dependency array to control when the subscription is re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn';\n *\n * function LoggerComponent() {\n * useSubscribeAll(siggn, (msg) => {\n * console.log(`[LOG]: ${msg.type}`);\n * }, []);\n * // ...\n * }\n * ```\n */\nexport function useSubscribeAll<M extends Msg>(\n options: SubscriptionOptions<M>,\n callback: (msg: M) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeAll(id, callback);\n\n return () => {\n instance.unsubscribeGlobal(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Adds a middleware to a `Siggn` instance that persists for the lifetime of the component.\n * Automatically removes the middleware when the component unmounts.\n *\n * @template M A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance.\n * @param middleware The middleware function to add.\n * @param deps An optional dependency array to control when the middleware is re-added.\n * @category Middleware\n * @since 0.0.6\n * @example\n *\n * ```tsx\n * import { siggn } from './siggn';\n *\n * function LoggerComponent() {\n * useMiddleware(siggn, async (msg, next) => {\n * console.log('Middleware:', msg);\n * next();\n * }, []);\n * // ...\n * }\n * ```\n */\nexport function useMiddleware<M extends Msg>(\n instance: Siggn<M>,\n middleware: Middleware<M>,\n deps: React.DependencyList = [],\n) {\n useEffect(() => {\n const cleanup = instance.use(middleware);\n return cleanup;\n }, [instance, middleware, ...deps]);\n}\n"],"names":["useSiggn","siggn","useState","Siggn","useSubscribeMany","options","setup","deps","instance","useMemo","id","useEffect","useSubscribe","type","callback","useSubscribeAll","useMiddleware","middleware"],"mappings":"kIAsBO,SAASA,GAAoC,CAClD,KAAM,CAACC,CAAK,EAAIC,WAAS,IAAIC,EAAAA,KAAU,EACvC,OAAOF,CACT,CAyBO,SAASG,EACdC,EACAC,EAMAC,EAAuB,CAAA,EACvB,CACA,MAAMC,EAAWC,EAAAA,QACf,IAAOJ,aAAmBF,EAAAA,MAAQE,EAAUA,EAAQ,SACpD,CAACA,CAAO,CAAA,EAEJK,EAAKD,EAAAA,QAAQ,IAAMD,EAAS,OAAO,OAAQH,EAAUA,EAAQ,GAAK,MAAS,EAAG,CAACG,CAAQ,CAAC,EAE9FG,EAAAA,UAAU,KACRH,EAAS,cAAcE,EAAIJ,CAAK,EAEzB,IAAM,CACXE,EAAS,YAAYE,CAAE,CACzB,GACC,CAACF,EAAUE,EAAI,GAAGH,CAAI,CAAC,CAC5B,CAsBO,SAASK,EACdP,EACAQ,EACAC,EACAP,EAAuB,CAAA,EACvB,CACA,MAAMC,EAAWC,EAAAA,QACf,IAAOJ,aAAmBF,EAAAA,MAAQE,EAAUA,EAAQ,SACpD,CAACA,CAAO,CAAA,EAEJK,EAAKD,EAAAA,QAAQ,IAAMD,EAAS,OAAO,OAAQH,EAAUA,EAAQ,GAAK,MAAS,EAAG,CAACG,CAAQ,CAAC,EAE9FG,EAAAA,UAAU,KACRH,EAAS,UAAUE,EAAIG,EAAMC,CAAQ,EAE9B,IAAM,CACXN,EAAS,YAAYE,CAAE,CACzB,GACC,CAACF,EAAUE,EAAI,GAAGH,CAAI,CAAC,CAC5B,CAyBO,SAASQ,EACdV,EACAS,EACAP,EAAuB,CAAA,EACvB,CACA,MAAMC,EAAWC,EAAAA,QACf,IAAOJ,aAAmBF,EAAAA,MAAQE,EAAUA,EAAQ,SACpD,CAACA,CAAO,CAAA,EAEJK,EAAKD,EAAAA,QAAQ,IAAMD,EAAS,OAAO,OAAQH,EAAUA,EAAQ,GAAK,MAAS,EAAG,CAACG,CAAQ,CAAC,EAE9FG,EAAAA,UAAU,KACRH,EAAS,aAAaE,EAAII,CAAQ,EAE3B,IAAM,CACXN,EAAS,kBAAkBE,CAAE,CAC/B,GACC,CAACF,EAAUE,EAAI,GAAGH,CAAI,CAAC,CAC5B,CA0BO,SAASS,EACdR,EACAS,EACAV,EAA6B,CAAA,EAC7B,CACAI,EAAAA,UAAU,IACQH,EAAS,IAAIS,CAAU,EAEtC,CAACT,EAAUS,EAAY,GAAGV,CAAI,CAAC,CACpC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './hooks.js';
2
+ export * from './types.js';
2
3
  export * from '@siggn/core';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
package/dist/index.es.js CHANGED
@@ -1,252 +1,45 @@
1
- import { useState as a, useMemo as u, useEffect as c } from "react";
2
- class t {
3
- nextId = 0;
4
- subscriptions;
5
- globalSubscriptions;
6
- middlewares;
7
- /**
8
- * Creates a new Siggn instance.
9
- * @category Lifecycle
10
- * @since 0.0.5
11
- */
12
- constructor() {
13
- this.subscriptions = /* @__PURE__ */ new Map(), this.globalSubscriptions = [], this.middlewares = [];
14
- }
15
- use(s) {
16
- this.middlewares.push(s);
17
- }
18
- /**
19
- * Creates a new, independent `Siggn` instance that inherits the message
20
- * types of its parent and adds new ones.
21
- *
22
- * @template C The new message types to add.
23
- * @returns A new `Siggn` instance with combined message types.
24
- * @category Lifecycle
25
- * @since 0.0.5
26
- * @example
27
- *
28
- ```typescript
29
- * const baseSiggn = new Siggn<{ type: 'A' }>();
30
- * const childSiggn = baseSiggn.createClone<{ type: 'B' }>();
31
- * // childSiggn can now publish and subscribe to types 'A' and 'B'.
32
- * ```
33
- */
34
- createClone() {
35
- return new t();
36
- }
37
- /**
38
- * Generates a unique ID for a subscriber.
39
- * If an ID is provided, it will be used; otherwise, a new one is generated.
40
- *
41
- * @param id An optional ID to use.
42
- * @returns A unique subscriber ID.
43
- * @category Utilities
44
- * @since 0.0.5
45
- * @example
46
- *
47
- ```typescript
48
- * const siggn = new Siggn();
49
- * const id1 = siggn.makeId(); // e.g., "sub_0"
50
- * const id2 = siggn.makeId('custom-id'); // "custom-id"
51
- * ```
52
- */
53
- makeId(s) {
54
- return s ?? `sub_${(this.nextId++).toString(36)}`;
55
- }
56
- /**
57
- * Creates a subscription helper object that is pre-configured with a
58
- * specific subscriber ID. This simplifies managing multiple subscriptions
59
- * for a single component or service.
60
- *
61
- * @param id The subscriber ID to use for all subscriptions.
62
- * @returns An object with `subscribe`, `unsubscribe`, `subscribeMany`, and `subscribeAll` methods.
63
- * @category Subscription
64
- * @since 0.0.5
65
- * @example
66
- *
67
- ```typescript
68
- * const siggn = new Siggn<{ type: 'event' }>();
69
- * const component = siggn.make('my-component');
70
- * component.subscribe('event', () => console.log('event received!'));
71
- * component.unsubscribe();
72
- * ```
73
- */
74
- make(s) {
75
- return {
76
- subscribe: (i, b) => {
77
- this.subscribe(s, i, b);
78
- },
79
- unsubscribe: () => {
80
- this.unsubscribe(s);
81
- },
82
- subscribeMany: (i) => {
83
- this.subscribeMany(s, i);
84
- },
85
- subscribeAll: (i) => {
86
- this.subscribeAll(s, i);
87
- }
88
- };
89
- }
90
- /**
91
- * Subscribes to multiple message types using a single subscriber ID.
92
- *
93
- * @param id The subscriber ID.
94
- * @param setup A function that receives a `subscribe` helper to register callbacks.
95
- * @category Subscription
96
- * @since 0.0.5
97
- * @example
98
- *
99
- ```typescript
100
- * const siggn = new Siggn<{ type: 'A' } | { type: 'B' }>();
101
- * siggn.subscribeMany('subscriber-1', (subscribe) => {
102
- * subscribe('A', () => console.log('A received'));
103
- * subscribe('B', () => console.log('B received'));
104
- * });
105
- * ```
106
- */
107
- subscribeMany(s, i) {
108
- i((b, r) => this.subscribe(s, b, r));
109
- }
110
- /**
111
- * Subscribes to a specific message type.
112
- *
113
- * @param id The subscriber ID.
114
- * @param type The message type to subscribe to.
115
- * @param callback The function to call when a message of the specified type is published.
116
- * @category Subscription
117
- * @since 0.0.5
118
- * @example
119
- *
120
- ```typescript
121
- * const siggn = new Siggn<{ type: 'my-event', payload: string }>();
122
- * siggn.subscribe('subscriber-1', 'my-event', (msg) => {
123
- * console.log(msg.payload);
124
- * });
125
- * ```
126
- */
127
- subscribe(s, i, b) {
128
- this.subscriptions.has(i) || this.subscriptions.set(i, []), this.subscriptions.get(i)?.push({ id: s, ref: b });
129
- }
130
- /**
131
- * Subscribes to all message types. The callback will be invoked for every
132
- * message published on the bus.
133
- *
134
- * @param id The subscriber ID.
135
- * @param callback The function to call for any message.
136
- * @category Subscription
137
- * @since 0.0.5
138
- * @example
139
- *
140
- ```typescript
141
- * const siggn = new Siggn<{ type: 'A' } | { type: 'B' }>();
142
- * siggn.subscribeAll('logger', (msg) => {
143
- * console.log(`Received message of type: ${msg.type}`);
144
- * });
145
- * ```
146
- */
147
- subscribeAll(s, i) {
148
- this.globalSubscriptions.push({ id: s, ref: i });
149
- }
150
- /**
151
- * Publishes a message to all relevant subscribers.
152
- *
153
- * @param msg The message to publish.
154
- * @category Publishing
155
- * @since 0.0.5
156
- * @example
157
- *
158
- ```typescript
159
- * const siggn = new Siggn<{ type: 'my-event' }>();
160
- * siggn.subscribe('sub-1', 'my-event', () => console.log('received'));
161
- * siggn.publish({ type: 'my-event' }); // "received"
162
- * ```
163
- */
164
- publish(s) {
165
- this.globalSubscriptions.forEach((i) => {
166
- i.ref(s);
167
- }), this.subscriptions.has(s.type) && this.subscriptions.get(s.type)?.forEach((i) => {
168
- i.ref(s);
169
- });
170
- }
171
- /**
172
- * Removes all subscriptions (both specific and global) for a given
173
- * subscriber ID.
174
- *
175
- * @param id The subscriber ID to unsubscribe.
176
- * @category Subscription
177
- * @since 0.0.5
178
- * @example
179
- *
180
- ```typescript
181
- * const siggn = new Siggn<{ type: 'my-event' }>();
182
- * siggn.subscribe('sub-1', 'my-event', () => console.log('received'));
183
- * siggn.unsubscribe('sub-1');
184
- * siggn.publish({ type: 'my-event' }); // (nothing is logged)
185
- * ```
186
- */
187
- unsubscribe(s) {
188
- this.unsubscribeGlobal(s);
189
- for (const [i, b] of this.subscriptions)
190
- this.subscriptions.set(
191
- i,
192
- b.filter((r) => r.id !== s)
193
- );
194
- }
195
- /**
196
- * Removes a global subscription for a given subscriber ID.
197
- *
198
- * @param id The subscriber ID to unsubscribe.
199
- * @category Subscription
200
- * @since 0.0.5
201
- * @example
202
- *
203
- ```typescript
204
- * const siggn = new Siggn<{ type: 'my-event' }>();
205
- * siggn.subscribeAll('logger', console.log);
206
- * siggn.unsubscribeGlobal('logger');
207
- * siggn.publish({ type: 'my-event' }); // (nothing is logged)
208
- * ```
209
- */
210
- unsubscribeGlobal(s) {
211
- this.globalSubscriptions = this.globalSubscriptions.filter((i) => i.id !== s);
212
- }
213
- }
214
- function h() {
215
- const [e] = a(new t());
1
+ import { Siggn as s } from "@siggn/core";
2
+ export * from "@siggn/core";
3
+ import { useState as a, useMemo as r, useEffect as b } from "react";
4
+ function l() {
5
+ const [e] = a(new s());
216
6
  return e;
217
7
  }
218
- function d(e, s, i = []) {
219
- const b = u(
220
- () => e instanceof t ? e : e.instance,
8
+ function m(e, u, i = []) {
9
+ const n = r(
10
+ () => e instanceof s ? e : e.instance,
221
11
  [e]
222
- ), r = u(() => b.makeId("id" in e ? e.id : void 0), [b]);
223
- c(() => (b.subscribeMany(r, s), () => {
224
- b.unsubscribe(r);
225
- }), [b, r, ...i]);
12
+ ), c = r(() => n.makeId("id" in e ? e.id : void 0), [n]);
13
+ b(() => (n.subscribeMany(c, u), () => {
14
+ n.unsubscribe(c);
15
+ }), [n, c, ...i]);
226
16
  }
227
- function o(e, s, i, b = []) {
228
- const r = u(
229
- () => e instanceof t ? e : e.instance,
17
+ function g(e, u, i, n = []) {
18
+ const c = r(
19
+ () => e instanceof s ? e : e.instance,
230
20
  [e]
231
- ), n = u(() => r.makeId("id" in e ? e.id : void 0), [r]);
232
- c(() => (r.subscribe(n, s, i), () => {
233
- r.unsubscribe(n);
234
- }), [r, n, ...b]);
21
+ ), t = r(() => c.makeId("id" in e ? e.id : void 0), [c]);
22
+ b(() => (c.subscribe(t, u, i), () => {
23
+ c.unsubscribe(t);
24
+ }), [c, t, ...n]);
235
25
  }
236
- function f(e, s, i = []) {
237
- const b = u(
238
- () => e instanceof t ? e : e.instance,
26
+ function S(e, u, i = []) {
27
+ const n = r(
28
+ () => e instanceof s ? e : e.instance,
239
29
  [e]
240
- ), r = u(() => b.makeId("id" in e ? e.id : void 0), [b]);
241
- c(() => (b.subscribeAll(r, s), () => {
242
- b.unsubscribeGlobal(r);
243
- }), [b, r, ...i]);
30
+ ), c = r(() => n.makeId("id" in e ? e.id : void 0), [n]);
31
+ b(() => (n.subscribeAll(c, u), () => {
32
+ n.unsubscribeGlobal(c);
33
+ }), [n, c, ...i]);
34
+ }
35
+ function M(e, u, i = []) {
36
+ b(() => e.use(u), [e, u, ...i]);
244
37
  }
245
38
  export {
246
- t as Siggn,
247
- h as useSiggn,
248
- o as useSubscribe,
249
- f as useSubscribeAll,
250
- d as useSubscribeMany
39
+ M as useMiddleware,
40
+ l as useSiggn,
41
+ g as useSubscribe,
42
+ S as useSubscribeAll,
43
+ m as useSubscribeMany
251
44
  };
252
45
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../../core/dist/index.es.js","../src/hooks.ts"],"sourcesContent":["class r {\n nextId = 0;\n subscriptions;\n globalSubscriptions;\n middlewares;\n /**\n * Creates a new Siggn instance.\n * @category Lifecycle\n * @since 0.0.5\n */\n constructor() {\n this.subscriptions = /* @__PURE__ */ new Map(), this.globalSubscriptions = [], this.middlewares = [];\n }\n use(s) {\n this.middlewares.push(s);\n }\n /**\n * Creates a new, independent `Siggn` instance that inherits the message\n * types of its parent and adds new ones.\n *\n * @template C The new message types to add.\n * @returns A new `Siggn` instance with combined message types.\n * @category Lifecycle\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const baseSiggn = new Siggn<{ type: 'A' }>();\n * const childSiggn = baseSiggn.createClone<{ type: 'B' }>();\n * // childSiggn can now publish and subscribe to types 'A' and 'B'.\n * ```\n */\n createClone() {\n return new r();\n }\n /**\n * Generates a unique ID for a subscriber.\n * If an ID is provided, it will be used; otherwise, a new one is generated.\n *\n * @param id An optional ID to use.\n * @returns A unique subscriber ID.\n * @category Utilities\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn();\n * const id1 = siggn.makeId(); // e.g., \"sub_0\"\n * const id2 = siggn.makeId('custom-id'); // \"custom-id\"\n * ```\n */\n makeId(s) {\n return s ?? `sub_${(this.nextId++).toString(36)}`;\n }\n /**\n * Creates a subscription helper object that is pre-configured with a\n * specific subscriber ID. This simplifies managing multiple subscriptions\n * for a single component or service.\n *\n * @param id The subscriber ID to use for all subscriptions.\n * @returns An object with `subscribe`, `unsubscribe`, `subscribeMany`, and `subscribeAll` methods.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'event' }>();\n * const component = siggn.make('my-component');\n * component.subscribe('event', () => console.log('event received!'));\n * component.unsubscribe();\n * ```\n */\n make(s) {\n return {\n subscribe: (i, t) => {\n this.subscribe(s, i, t);\n },\n unsubscribe: () => {\n this.unsubscribe(s);\n },\n subscribeMany: (i) => {\n this.subscribeMany(s, i);\n },\n subscribeAll: (i) => {\n this.subscribeAll(s, i);\n }\n };\n }\n /**\n * Subscribes to multiple message types using a single subscriber ID.\n *\n * @param id The subscriber ID.\n * @param setup A function that receives a `subscribe` helper to register callbacks.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'A' } | { type: 'B' }>();\n * siggn.subscribeMany('subscriber-1', (subscribe) => {\n * subscribe('A', () => console.log('A received'));\n * subscribe('B', () => console.log('B received'));\n * });\n * ```\n */\n subscribeMany(s, i) {\n i((t, b) => this.subscribe(s, t, b));\n }\n /**\n * Subscribes to a specific message type.\n *\n * @param id The subscriber ID.\n * @param type The message type to subscribe to.\n * @param callback The function to call when a message of the specified type is published.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event', payload: string }>();\n * siggn.subscribe('subscriber-1', 'my-event', (msg) => {\n * console.log(msg.payload);\n * });\n * ```\n */\n subscribe(s, i, t) {\n this.subscriptions.has(i) || this.subscriptions.set(i, []), this.subscriptions.get(i)?.push({ id: s, ref: t });\n }\n /**\n * Subscribes to all message types. The callback will be invoked for every\n * message published on the bus.\n *\n * @param id The subscriber ID.\n * @param callback The function to call for any message.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'A' } | { type: 'B' }>();\n * siggn.subscribeAll('logger', (msg) => {\n * console.log(`Received message of type: ${msg.type}`);\n * });\n * ```\n */\n subscribeAll(s, i) {\n this.globalSubscriptions.push({ id: s, ref: i });\n }\n /**\n * Publishes a message to all relevant subscribers.\n *\n * @param msg The message to publish.\n * @category Publishing\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event' }>();\n * siggn.subscribe('sub-1', 'my-event', () => console.log('received'));\n * siggn.publish({ type: 'my-event' }); // \"received\"\n * ```\n */\n publish(s) {\n this.globalSubscriptions.forEach((i) => {\n i.ref(s);\n }), this.subscriptions.has(s.type) && this.subscriptions.get(s.type)?.forEach((i) => {\n i.ref(s);\n });\n }\n /**\n * Removes all subscriptions (both specific and global) for a given\n * subscriber ID.\n *\n * @param id The subscriber ID to unsubscribe.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event' }>();\n * siggn.subscribe('sub-1', 'my-event', () => console.log('received'));\n * siggn.unsubscribe('sub-1');\n * siggn.publish({ type: 'my-event' }); // (nothing is logged)\n * ```\n */\n unsubscribe(s) {\n this.unsubscribeGlobal(s);\n for (const [i, t] of this.subscriptions)\n this.subscriptions.set(\n i,\n t.filter((b) => b.id !== s)\n );\n }\n /**\n * Removes a global subscription for a given subscriber ID.\n *\n * @param id The subscriber ID to unsubscribe.\n * @category Subscription\n * @since 0.0.5\n * @example\n * \n ```typescript\n * const siggn = new Siggn<{ type: 'my-event' }>();\n * siggn.subscribeAll('logger', console.log);\n * siggn.unsubscribeGlobal('logger');\n * siggn.publish({ type: 'my-event' }); // (nothing is logged)\n * ```\n */\n unsubscribeGlobal(s) {\n this.globalSubscriptions = this.globalSubscriptions.filter((i) => i.id !== s);\n }\n}\nexport {\n r as Siggn\n};\n//# sourceMappingURL=index.es.js.map\n","import { type Msg, Siggn } from '@siggn/core';\nimport type { SubscriptionOptions } from 'packages/react/src/types';\nimport { useEffect, useMemo, useState, type DependencyList } from 'react';\n\n/**\n * Creates and returns a `Siggn` instance that persists for the lifetime of the component.\n * This is useful for creating a message bus scoped to a component and its children.\n *\n * @template T A union of all possible message types for the new instance.\n * @returns A `Siggn<T>` instance.\n * @category Lifecycle\n * @since 0.0.1\n * @example\n * \n```tsx\n * function MyComponent() {\n * const localSiggn = useSiggn<{ type: 'local-event' }>();\n * // ...\n * }\n * ```\n */\nexport function useSiggn<T extends Msg>(): Siggn<T> {\n const [siggn] = useState(new Siggn<T>());\n return siggn;\n}\n\n/**\n * Subscribes to multiple messages and automatically unsubscribes when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribeMany(siggn, (subscribe) => {\n * subscribe('user-created', (msg) => console.log(msg.name));\n * subscribe('user-updated', (msg) => console.log(msg.name));\n * });\n * // ...\n * }\n * ```\n */\nexport function useSubscribeMany<M extends Msg>(\n options: SubscriptionOptions<M>,\n setup: (\n subscribe: <T extends M['type']>(\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n ) => void,\n ) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeMany(id, setup);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to a single message and automatically unsubscribe when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribe(siggn, 'user-created', (msg) => console.log(msg.name));\n * // ...\n * }\n * ```\n */\nexport function useSubscribe<M extends Msg, T extends M['type']>(\n options: SubscriptionOptions<M>,\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribe(id, type, callback);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to all messages on a `Siggn` instance and automatically unsubscribes\n * when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param callback The function to call for any message.\n * @param deps An optional dependency array to control when the subscription is re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn';\n *\n * function LoggerComponent() {\n * useSubscribeAll(siggn, (msg) => {\n * console.log(`[LOG]: ${msg.type}`);\n * }, []);\n * // ...\n * }\n * ```\n */\nexport function useSubscribeAll<T extends Msg>(\n options: SubscriptionOptions<T>,\n callback: (msg: T) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeAll(id, callback);\n\n return () => {\n instance.unsubscribeGlobal(id);\n };\n }, [instance, id, ...deps]);\n}\n"],"names":["r","t","b","useSiggn","siggn","useState","Siggn","useSubscribeMany","options","setup","deps","instance","useMemo","id","useEffect","useSubscribe","type","callback","useSubscribeAll"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/hooks.ts"],"sourcesContent":["import { type Middleware, type Msg, Siggn } from '@siggn/core';\nimport type { SubscriptionOptions } from 'packages/react/src/types';\n\nimport { useEffect, useMemo, useState, type DependencyList } from 'react';\n\n/**\n * Creates and returns a `Siggn` instance that persists for the lifetime of the component.\n * This is useful for creating a message bus scoped to a component and its children.\n *\n * @template T A union of all possible message types for the new instance.\n * @returns A `Siggn<T>` instance.\n * @category Lifecycle\n * @since 0.0.1\n * @example\n * \n```tsx\n * function MyComponent() {\n * const localSiggn = useSiggn<{ type: 'local-event' }>();\n * // ...\n * }\n * ```\n */\nexport function useSiggn<T extends Msg>(): Siggn<T> {\n const [siggn] = useState(new Siggn<T>());\n return siggn;\n}\n\n/**\n * Subscribes to multiple messages and automatically unsubscribes when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribeMany(siggn, (subscribe) => {\n * subscribe('user-created', (msg) => console.log(msg.name));\n * subscribe('user-updated', (msg) => console.log(msg.name));\n * });\n * // ...\n * }\n * ```\n */\nexport function useSubscribeMany<M extends Msg>(\n options: SubscriptionOptions<M>,\n setup: (\n subscribe: <T extends M['type']>(\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n ) => void,\n ) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeMany(id, setup);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to a single message and automatically unsubscribe when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param setup A function that receives a `subscribe` helper to define subscriptions.\n * @param deps An optional dependency array to control when the subscriptions are re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn'; // Your shared instance\n *\n * function MyComponent() {\n * useSubscribe(siggn, 'user-created', (msg) => console.log(msg.name));\n * // ...\n * }\n * ```\n */\nexport function useSubscribe<M extends Msg, T extends M['type']>(\n options: SubscriptionOptions<M>,\n type: T,\n callback: (msg: Extract<M, { type: T }>) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribe(id, type, callback);\n\n return () => {\n instance.unsubscribe(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Subscribes to all messages on a `Siggn` instance and automatically unsubscribes\n * when the component unmounts.\n *\n * @template T A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance and an optional subscriber ID.\n * @param callback The function to call for any message.\n * @param deps An optional dependency array to control when the subscription is re-created.\n * @category Subscription\n * @since 0.0.1\n * @example\n * \n```tsx\n * import { siggn } from './siggn';\n *\n * function LoggerComponent() {\n * useSubscribeAll(siggn, (msg) => {\n * console.log(`[LOG]: ${msg.type}`);\n * }, []);\n * // ...\n * }\n * ```\n */\nexport function useSubscribeAll<M extends Msg>(\n options: SubscriptionOptions<M>,\n callback: (msg: M) => void,\n deps: DependencyList = [],\n) {\n const instance = useMemo(\n () => (options instanceof Siggn ? options : options.instance),\n [options],\n );\n const id = useMemo(() => instance.makeId('id' in options ? options.id : undefined), [instance]);\n\n useEffect(() => {\n instance.subscribeAll(id, callback);\n\n return () => {\n instance.unsubscribeGlobal(id);\n };\n }, [instance, id, ...deps]);\n}\n\n/**\n * Adds a middleware to a `Siggn` instance that persists for the lifetime of the component.\n * Automatically removes the middleware when the component unmounts.\n *\n * @template M A union of all possible message types.\n * @param options A `Siggn` instance or an object with the instance.\n * @param middleware The middleware function to add.\n * @param deps An optional dependency array to control when the middleware is re-added.\n * @category Middleware\n * @since 0.0.6\n * @example\n *\n * ```tsx\n * import { siggn } from './siggn';\n *\n * function LoggerComponent() {\n * useMiddleware(siggn, async (msg, next) => {\n * console.log('Middleware:', msg);\n * next();\n * }, []);\n * // ...\n * }\n * ```\n */\nexport function useMiddleware<M extends Msg>(\n instance: Siggn<M>,\n middleware: Middleware<M>,\n deps: React.DependencyList = [],\n) {\n useEffect(() => {\n const cleanup = instance.use(middleware);\n return cleanup;\n }, [instance, middleware, ...deps]);\n}\n"],"names":["useSiggn","siggn","useState","Siggn","useSubscribeMany","options","setup","deps","instance","useMemo","id","useEffect","useSubscribe","type","callback","useSubscribeAll","useMiddleware","middleware"],"mappings":";;;AAsBO,SAASA,IAAoC;AAClD,QAAM,CAACC,CAAK,IAAIC,EAAS,IAAIC,GAAU;AACvC,SAAOF;AACT;AAyBO,SAASG,EACdC,GACAC,GAMAC,IAAuB,CAAA,GACvB;AACA,QAAMC,IAAWC;AAAA,IACf,MAAOJ,aAAmBF,IAAQE,IAAUA,EAAQ;AAAA,IACpD,CAACA,CAAO;AAAA,EAAA,GAEJK,IAAKD,EAAQ,MAAMD,EAAS,OAAO,QAAQH,IAAUA,EAAQ,KAAK,MAAS,GAAG,CAACG,CAAQ,CAAC;AAE9F,EAAAG,EAAU,OACRH,EAAS,cAAcE,GAAIJ,CAAK,GAEzB,MAAM;AACX,IAAAE,EAAS,YAAYE,CAAE;AAAA,EACzB,IACC,CAACF,GAAUE,GAAI,GAAGH,CAAI,CAAC;AAC5B;AAsBO,SAASK,EACdP,GACAQ,GACAC,GACAP,IAAuB,CAAA,GACvB;AACA,QAAMC,IAAWC;AAAA,IACf,MAAOJ,aAAmBF,IAAQE,IAAUA,EAAQ;AAAA,IACpD,CAACA,CAAO;AAAA,EAAA,GAEJK,IAAKD,EAAQ,MAAMD,EAAS,OAAO,QAAQH,IAAUA,EAAQ,KAAK,MAAS,GAAG,CAACG,CAAQ,CAAC;AAE9F,EAAAG,EAAU,OACRH,EAAS,UAAUE,GAAIG,GAAMC,CAAQ,GAE9B,MAAM;AACX,IAAAN,EAAS,YAAYE,CAAE;AAAA,EACzB,IACC,CAACF,GAAUE,GAAI,GAAGH,CAAI,CAAC;AAC5B;AAyBO,SAASQ,EACdV,GACAS,GACAP,IAAuB,CAAA,GACvB;AACA,QAAMC,IAAWC;AAAA,IACf,MAAOJ,aAAmBF,IAAQE,IAAUA,EAAQ;AAAA,IACpD,CAACA,CAAO;AAAA,EAAA,GAEJK,IAAKD,EAAQ,MAAMD,EAAS,OAAO,QAAQH,IAAUA,EAAQ,KAAK,MAAS,GAAG,CAACG,CAAQ,CAAC;AAE9F,EAAAG,EAAU,OACRH,EAAS,aAAaE,GAAII,CAAQ,GAE3B,MAAM;AACX,IAAAN,EAAS,kBAAkBE,CAAE;AAAA,EAC/B,IACC,CAACF,GAAUE,GAAI,GAAGH,CAAI,CAAC;AAC5B;AA0BO,SAASS,EACdR,GACAS,GACAV,IAA6B,CAAA,GAC7B;AACA,EAAAI,EAAU,MACQH,EAAS,IAAIS,CAAU,GAEtC,CAACT,GAAUS,GAAY,GAAGV,CAAI,CAAC;AACpC;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siggn/react",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "A lightweight type safe message bus system for React",
5
5
  "keywords": [
6
6
  "pub/sub",
@@ -58,7 +58,7 @@
58
58
  "react": ">=18 <20"
59
59
  },
60
60
  "dependencies": {
61
- "@siggn/core": "0.1.1"
61
+ "@siggn/core": "0.2.0"
62
62
  },
63
63
  "scripts": {
64
64
  "dev": "vite build --watch",