@alwatr/signal 9.10.1 → 9.12.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 +367 -0
- package/dist/core/channel-signal.d.ts +177 -0
- package/dist/core/channel-signal.d.ts.map +1 -0
- package/dist/core/signal-base.d.ts +1 -0
- package/dist/core/signal-base.d.ts.map +1 -1
- package/dist/creators/channel.d.ts +39 -0
- package/dist/creators/channel.d.ts.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +3 -3
- package/dist/main.js.map +6 -4
- package/package.json +10 -10
- package/src/core/channel-signal.ts +263 -0
- package/src/core/signal-base.ts +24 -7
- package/src/creators/channel.ts +44 -0
- package/src/main.ts +2 -0
package/README.md
CHANGED
|
@@ -31,6 +31,8 @@ There is also a fourth type for stateless events:
|
|
|
31
31
|
|
|
32
32
|
4. **`EventSignal`**: A stateless signal for dispatching one-off events that don't have a persistent value.
|
|
33
33
|
|
|
34
|
+
5. **`ChannelSignal`**: A stateless, typed message bus. Unlike `EventSignal` (one signal = one event type), a single `ChannelSignal` carries multiple named message types — each with its own payload type — and routes them in **O(1)** to the right subscribers.
|
|
35
|
+
|
|
34
36
|
---
|
|
35
37
|
|
|
36
38
|
## Getting Started: A Practical Example
|
|
@@ -128,6 +130,179 @@ User: Jane has clicked 0 times.
|
|
|
128
130
|
User: Jane has clicked 1 times.
|
|
129
131
|
```
|
|
130
132
|
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## ChannelSignal: A Typed Message Bus
|
|
136
|
+
|
|
137
|
+
### Why ChannelSignal?
|
|
138
|
+
|
|
139
|
+
In real-world applications, you often need to dispatch many different types of events or messages — for example, `'open-drawer'`, `'close-drawer'`, `'show-toast'`, `'navigate'`, etc. You could create a separate `EventSignal` for each one, but that quickly becomes unwieldy:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// ❌ Verbose and hard to manage
|
|
143
|
+
const openDrawerSignal = new EventSignal<{panel: string}>({name: 'open-drawer'});
|
|
144
|
+
const closeDrawerSignal = new EventSignal({name: 'close-drawer'});
|
|
145
|
+
const showToastSignal = new EventSignal<{message: string; type: 'info' | 'error'}>({name: 'show-toast'});
|
|
146
|
+
// ... and so on for every action in your app
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**`ChannelSignal` solves this problem.** It's a single signal that acts as a **typed message bus** — one channel, many named message types. Think of it as a Go-style channel or a pub/sub topic with full TypeScript type safety.
|
|
150
|
+
|
|
151
|
+
### Architecture: O(1) Routing
|
|
152
|
+
|
|
153
|
+
Internally, `ChannelSignal` uses a `Map<name, Set<handler>>` to route messages. When you dispatch a message with name `'A'`, only the handlers registered for `'A'` are invoked — **O(1) lookup**, regardless of how many other names are subscribed. This is a critical performance optimization for applications with hundreds or thousands of directives/components listening to different actions.
|
|
154
|
+
|
|
155
|
+
### Creating a ChannelSignal
|
|
156
|
+
|
|
157
|
+
First, define a **message map** — a TypeScript interface that maps every valid message name to its payload type:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import {ChannelSignal} from '@alwatr/signal';
|
|
161
|
+
|
|
162
|
+
// Define the message map for your application
|
|
163
|
+
interface AppMessages {
|
|
164
|
+
'open-drawer': {panel: string};
|
|
165
|
+
'close-drawer': void; // no payload
|
|
166
|
+
'show-toast': {message: string; type: 'info' | 'error'};
|
|
167
|
+
'navigate': {path: string};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Create the channel
|
|
171
|
+
const appChannel = new ChannelSignal<AppMessages>({name: 'app-channel'});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Subscribing to Named Messages
|
|
175
|
+
|
|
176
|
+
Use `.on(name, handler)` to subscribe to a specific message. The handler receives the **payload directly** (not the full `{name, payload}` envelope) — since the name is already known at subscription time, passing it again would be redundant.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Subscribe to 'open-drawer' messages
|
|
180
|
+
appChannel.on('open-drawer', (payload) => {
|
|
181
|
+
console.log(`Opening drawer: ${payload!.panel}`);
|
|
182
|
+
// TypeScript knows payload is {panel: string} | undefined
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Subscribe to 'show-toast' messages
|
|
186
|
+
appChannel.on('show-toast', (payload) => {
|
|
187
|
+
toast.show(payload!.message, payload!.type);
|
|
188
|
+
// TypeScript knows payload is {message: string; type: 'info' | 'error'} | undefined
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Subscribe to 'close-drawer' (no payload)
|
|
192
|
+
appChannel.on('close-drawer', (payload) => {
|
|
193
|
+
console.log('Closing drawer');
|
|
194
|
+
// TypeScript knows payload is void | undefined
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Dispatching Messages
|
|
199
|
+
|
|
200
|
+
Use `.dispatch(name, payload)` to send a message. TypeScript enforces that the payload matches the type declared for that name in the message map.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Dispatch with payload
|
|
204
|
+
appChannel.dispatch('open-drawer', {panel: 'settings'}); // ✅ Type-safe
|
|
205
|
+
appChannel.dispatch('show-toast', {message: 'Saved!', type: 'info'}); // ✅
|
|
206
|
+
|
|
207
|
+
// Dispatch without payload
|
|
208
|
+
appChannel.dispatch('close-drawer'); // ✅
|
|
209
|
+
|
|
210
|
+
// ❌ TypeScript errors:
|
|
211
|
+
appChannel.dispatch('open-drawer', {panel: 123}); // Error: panel must be string
|
|
212
|
+
appChannel.dispatch('show-toast', {message: 'Hi'}); // Error: missing 'type'
|
|
213
|
+
appChannel.dispatch('unknown-action'); // Error: 'unknown-action' is not in AppMessages
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Unsubscribing
|
|
217
|
+
|
|
218
|
+
Just like other signals, `.on()` returns a `SubscribeResult` with an `unsubscribe()` method:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const sub = appChannel.on('navigate', (payload) => {
|
|
222
|
+
router.push(payload!.path);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Later, when the component is destroyed:
|
|
226
|
+
sub.unsubscribe();
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### One-Time Subscriptions
|
|
230
|
+
|
|
231
|
+
Use the `once` option to automatically unsubscribe after the first message:
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
appChannel.on(
|
|
235
|
+
'app-ready',
|
|
236
|
+
() => {
|
|
237
|
+
console.log('App initialized!');
|
|
238
|
+
},
|
|
239
|
+
{once: true},
|
|
240
|
+
);
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Raw Stream Subscription (for Logging/Middleware)
|
|
244
|
+
|
|
245
|
+
If you need to observe **all** messages regardless of name — for example, for logging, analytics, or middleware — use `.subscribe()` instead of `.on()`. This receives the full `{name, payload}` envelope:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// Log every message for debugging
|
|
249
|
+
appChannel.subscribe((msg) => {
|
|
250
|
+
console.log(`[channel] ${String(msg.name)}`, msg.payload);
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Important:** `.subscribe()` is **not** filtered by name — it receives every message. For normal use cases, prefer `.on(name, handler)` to keep subscriptions focused and performant.
|
|
255
|
+
|
|
256
|
+
### Use Cases
|
|
257
|
+
|
|
258
|
+
`ChannelSignal` is ideal for:
|
|
259
|
+
|
|
260
|
+
- **Action layers** in Unidirectional Data Flow architectures (like `@alwatr/action`)
|
|
261
|
+
- **Event buses** in component-based UIs (e.g., a global app event channel)
|
|
262
|
+
- **Command dispatching** in CQRS-style systems
|
|
263
|
+
- **Pub/sub messaging** where you have many distinct message types but want a single, centralized channel
|
|
264
|
+
|
|
265
|
+
### Example: A Complete Action System
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import {ChannelSignal} from '@alwatr/signal';
|
|
269
|
+
|
|
270
|
+
// Define all app actions
|
|
271
|
+
interface AppActions {
|
|
272
|
+
'user-login': {username: string};
|
|
273
|
+
'user-logout': void;
|
|
274
|
+
'cart-add-item': {productId: number; quantity: number};
|
|
275
|
+
'cart-remove-item': {productId: number};
|
|
276
|
+
'navigate': {path: string};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const actionChannel = new ChannelSignal<AppActions>({name: 'app-actions'});
|
|
280
|
+
|
|
281
|
+
// Business logic subscribes to actions
|
|
282
|
+
actionChannel.on('user-login', (payload) => {
|
|
283
|
+
authService.login(payload!.username);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
actionChannel.on('cart-add-item', (payload) => {
|
|
287
|
+
cartService.addItem(payload!.productId, payload!.quantity);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
actionChannel.on('navigate', (payload) => {
|
|
291
|
+
router.push(payload!.path);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// UI dispatches actions (e.g., from button clicks)
|
|
295
|
+
loginButton.addEventListener('click', () => {
|
|
296
|
+
actionChannel.dispatch('user-login', {username: 'ali'});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
addToCartButton.addEventListener('click', () => {
|
|
300
|
+
actionChannel.dispatch('cart-add-item', {productId: 42, quantity: 1});
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
131
306
|
## Advanced Topics
|
|
132
307
|
|
|
133
308
|
### Lifecycle Management and Memory Leaks
|
|
@@ -199,6 +374,14 @@ The `subscribe` method accepts an optional second argument to customize its beha
|
|
|
199
374
|
- `config.name`: `string`
|
|
200
375
|
- **`.dispatch(payload: T)`**: Dispatches an event to all listeners.
|
|
201
376
|
|
|
377
|
+
### `ChannelSignal<TMap>`
|
|
378
|
+
|
|
379
|
+
- **`constructor(config)`**: Creates a new channel signal.
|
|
380
|
+
- `config.name`: `string`
|
|
381
|
+
- **`.dispatch(name, payload?)`**: Dispatches a named message. TypeScript enforces the correct payload type for each name.
|
|
382
|
+
- **`.on(name, handler, options?)`**: Subscribes to a specific named message. The handler receives the `payload` directly (not the full envelope). Uses an internal `Map` for **O(1)** routing. Supports `once` option.
|
|
383
|
+
- **`.subscribe(callback, options?)`**: Subscribes to the **raw message stream** — receives every `{name, payload}` envelope regardless of name. Useful for logging and middleware.
|
|
384
|
+
|
|
202
385
|
### Common Methods
|
|
203
386
|
|
|
204
387
|
- **`.subscribe(callback, options?)`**: Subscribes a listener. Returns `{ unsubscribe: () => void }`.
|
|
@@ -252,6 +435,10 @@ Contributions are welcome! Please read our [contribution guidelines](https://git
|
|
|
252
435
|
|
|
253
436
|
4. **`EventSignal`**: یک سیگنال بدون حالت برای ارسال رویدادهای یکباره که مقدار پایداری ندارند.
|
|
254
437
|
|
|
438
|
+
و یک نوع پنجم برای مسیریابی پیامهای چندگانه:
|
|
439
|
+
|
|
440
|
+
5. **`ChannelSignal`**: یک Message Bus تایپشده و بدون حالت. برخلاف `EventSignal` (یک سیگنال = یک نوع رویداد)، یک `ChannelSignal` واحد چندین نوع پیام با نامهای مختلف را حمل میکند — هر کدام با نوع payload مخصوص خودشان — و آنها را با سرعت **O(1)** به subscriberهای مناسب هدایت میکند.
|
|
441
|
+
|
|
255
442
|
---
|
|
256
443
|
|
|
257
444
|
## شروع به کار: یک مثال عملی
|
|
@@ -349,6 +536,178 @@ User: Jane has clicked 0 times.
|
|
|
349
536
|
User: Jane has clicked 1 times.
|
|
350
537
|
```
|
|
351
538
|
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## ChannelSignal: یک Message Bus تایپشده
|
|
542
|
+
|
|
543
|
+
### چرا ChannelSignal؟
|
|
544
|
+
|
|
545
|
+
در برنامههای واقعی، اغلب نیاز دارید انواع مختلفی از رویدادها یا پیامها را dispatch کنید — مثلاً `'open-drawer'`، `'close-drawer'`، `'show-toast'`، `'navigate'` و غیره. میتوانید برای هر کدام یک `EventSignal` جداگانه بسازید، اما این رویکرد به سرعت دستوپاگیر میشود:
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
// ❌ پرحجم و سخت برای مدیریت
|
|
549
|
+
const openDrawerSignal = new EventSignal<{panel: string}>({name: 'open-drawer'});
|
|
550
|
+
const closeDrawerSignal = new EventSignal({name: 'close-drawer'});
|
|
551
|
+
const showToastSignal = new EventSignal<{message: string; type: 'info' | 'error'}>({name: 'show-toast'});
|
|
552
|
+
// ... و به همین ترتیب برای هر action در برنامه
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**`ChannelSignal` این مشکل را حل میکند.** یک سیگنال واحد است که به عنوان یک **Message Bus تایپشده** عمل میکند — یک کانال، انواع پیامهای مختلف. مثل یک Go-style channel یا یک pub/sub topic با ایمنی کامل TypeScript.
|
|
556
|
+
|
|
557
|
+
### معماری: مسیریابی O(1)
|
|
558
|
+
|
|
559
|
+
در داخل، `ChannelSignal` از یک `Map<name, Set<handler>>` برای مسیریابی پیامها استفاده میکند. وقتی پیامی با نام `'A'` dispatch میشود، فقط handlerهایی که برای `'A'` ثبت شدهاند فراخوانی میشوند — **جستجوی O(1)**، صرفنظر از اینکه چه تعداد نام دیگری subscribe شده باشند. این یک بهینهسازی حیاتی برای برنامههایی است که صدها یا هزاران directive/component دارند که به actionهای مختلف گوش میدهند.
|
|
560
|
+
|
|
561
|
+
### ساخت یک ChannelSignal
|
|
562
|
+
|
|
563
|
+
ابتدا یک **message map** تعریف کنید — یک interface در TypeScript که هر نام پیام معتبر را به نوع payload آن نگاشت میکند:
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
import {ChannelSignal} from '@alwatr/signal';
|
|
567
|
+
|
|
568
|
+
// تعریف message map برای برنامه
|
|
569
|
+
interface AppMessages {
|
|
570
|
+
'open-drawer': {panel: string};
|
|
571
|
+
'close-drawer': void; // بدون payload
|
|
572
|
+
'show-toast': {message: string; type: 'info' | 'error'};
|
|
573
|
+
'navigate': {path: string};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// ساخت channel
|
|
577
|
+
const appChannel = new ChannelSignal<AppMessages>({name: 'app-channel'});
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Subscribe به پیامهای نامدار
|
|
581
|
+
|
|
582
|
+
از `.on(name, handler)` برای subscribe به یک پیام خاص استفاده کنید. handler مستقیماً **payload** را دریافت میکند (نه envelope کامل `{name, payload}`) — چون نام در زمان subscribe مشخص است، ارسال مجدد آن اضافی خواهد بود.
|
|
583
|
+
|
|
584
|
+
```typescript
|
|
585
|
+
// Subscribe به پیامهای 'open-drawer'
|
|
586
|
+
appChannel.on('open-drawer', (payload) => {
|
|
587
|
+
console.log(`Opening drawer: ${payload!.panel}`);
|
|
588
|
+
// TypeScript میداند payload از نوع {panel: string} | undefined است
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// Subscribe به پیامهای 'show-toast'
|
|
592
|
+
appChannel.on('show-toast', (payload) => {
|
|
593
|
+
toast.show(payload!.message, payload!.type);
|
|
594
|
+
// TypeScript میداند payload از نوع {message: string; type: 'info' | 'error'} | undefined است
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
// Subscribe به 'close-drawer' (بدون payload)
|
|
598
|
+
appChannel.on('close-drawer', () => {
|
|
599
|
+
console.log('Closing drawer');
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### Dispatch پیامها
|
|
604
|
+
|
|
605
|
+
از `.dispatch(name, payload)` برای ارسال پیام استفاده کنید. TypeScript اعمال میکند که payload با نوع تعریفشده برای آن نام در message map مطابقت داشته باشد.
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
// Dispatch با payload
|
|
609
|
+
appChannel.dispatch('open-drawer', {panel: 'settings'}); // ✅ Type-safe
|
|
610
|
+
appChannel.dispatch('show-toast', {message: 'ذخیره شد!', type: 'info'}); // ✅
|
|
611
|
+
|
|
612
|
+
// Dispatch بدون payload
|
|
613
|
+
appChannel.dispatch('close-drawer'); // ✅
|
|
614
|
+
|
|
615
|
+
// ❌ خطاهای TypeScript:
|
|
616
|
+
appChannel.dispatch('open-drawer', {panel: 123}); // خطا: panel باید string باشد
|
|
617
|
+
appChannel.dispatch('show-toast', {message: 'سلام'}); // خطا: 'type' وجود ندارد
|
|
618
|
+
appChannel.dispatch('unknown-action'); // خطا: 'unknown-action' در AppMessages نیست
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### Unsubscribe کردن
|
|
622
|
+
|
|
623
|
+
مثل سایر سیگنالها، `.on()` یک `SubscribeResult` با متد `unsubscribe()` برمیگرداند:
|
|
624
|
+
|
|
625
|
+
```typescript
|
|
626
|
+
const sub = appChannel.on('navigate', (payload) => {
|
|
627
|
+
router.push(payload!.path);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// بعداً، وقتی کامپوننت destroy میشود:
|
|
631
|
+
sub.unsubscribe();
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### Subscribe یکباره
|
|
635
|
+
|
|
636
|
+
از گزینه `once` برای unsubscribe خودکار بعد از اولین پیام استفاده کنید:
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
appChannel.on(
|
|
640
|
+
'app-ready',
|
|
641
|
+
() => {
|
|
642
|
+
console.log('برنامه آماده است!');
|
|
643
|
+
},
|
|
644
|
+
{once: true},
|
|
645
|
+
);
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### Subscribe به جریان خام (برای لاگگیری/Middleware)
|
|
649
|
+
|
|
650
|
+
اگر نیاز دارید **همه** پیامها را صرفنظر از نام مشاهده کنید — مثلاً برای لاگگیری، analytics یا middleware — از `.subscribe()` به جای `.on()` استفاده کنید. این متد envelope کامل `{name, payload}` را دریافت میکند:
|
|
651
|
+
|
|
652
|
+
```typescript
|
|
653
|
+
// لاگ کردن همه پیامها برای debugging
|
|
654
|
+
appChannel.subscribe((msg) => {
|
|
655
|
+
console.log(`[channel] ${String(msg.name)}`, msg.payload);
|
|
656
|
+
});
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
**نکته مهم:** `.subscribe()` بر اساس نام فیلتر **نمیشود** — هر پیامی را دریافت میکند. برای موارد عادی، `.on(name, handler)` را ترجیح دهید تا subscriptionها متمرکز و کارآمد بمانند.
|
|
660
|
+
|
|
661
|
+
### موارد استفاده
|
|
662
|
+
|
|
663
|
+
`ChannelSignal` برای موارد زیر ایدهآل است:
|
|
664
|
+
|
|
665
|
+
- **لایه Action** در معماریهای Unidirectional Data Flow (مثل `@alwatr/action`)
|
|
666
|
+
- **Event Bus** در UIهای مبتنی بر کامپوننت (مثلاً یک کانال رویداد سراسری برنامه)
|
|
667
|
+
- **Command Dispatching** در سیستمهای CQRS-style
|
|
668
|
+
- **Pub/Sub Messaging** جایی که انواع پیامهای مختلف دارید اما میخواهید یک کانال مرکزی داشته باشید
|
|
669
|
+
|
|
670
|
+
### مثال کامل: یک سیستم Action
|
|
671
|
+
|
|
672
|
+
```typescript
|
|
673
|
+
import {ChannelSignal} from '@alwatr/signal';
|
|
674
|
+
|
|
675
|
+
// تعریف همه actionهای برنامه
|
|
676
|
+
interface AppActions {
|
|
677
|
+
'user-login': {username: string};
|
|
678
|
+
'user-logout': void;
|
|
679
|
+
'cart-add-item': {productId: number; quantity: number};
|
|
680
|
+
'cart-remove-item': {productId: number};
|
|
681
|
+
'navigate': {path: string};
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const actionChannel = new ChannelSignal<AppActions>({name: 'app-actions'});
|
|
685
|
+
|
|
686
|
+
// منطق تجاری به actionها subscribe میکند
|
|
687
|
+
actionChannel.on('user-login', (payload) => {
|
|
688
|
+
authService.login(payload!.username);
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
actionChannel.on('cart-add-item', (payload) => {
|
|
692
|
+
cartService.addItem(payload!.productId, payload!.quantity);
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
actionChannel.on('navigate', (payload) => {
|
|
696
|
+
router.push(payload!.path);
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
// UI اقدام به dispatch action میکند (مثلاً از کلیک دکمه)
|
|
700
|
+
loginButton.addEventListener('click', () => {
|
|
701
|
+
actionChannel.dispatch('user-login', {username: 'ali'});
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
addToCartButton.addEventListener('click', () => {
|
|
705
|
+
actionChannel.dispatch('cart-add-item', {productId: 42, quantity: 1});
|
|
706
|
+
});
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
---
|
|
710
|
+
|
|
352
711
|
## مباحث پیشرفته
|
|
353
712
|
|
|
354
713
|
### مدیریت چرخه حیات و نشت حافظه
|
|
@@ -420,6 +779,14 @@ Alwatr Signal از یک مدل ناهمزمان قابل پیشبینی بر
|
|
|
420
779
|
- `config.name`: `string`
|
|
421
780
|
- **`.dispatch(payload: T)`**: یک رویداد را به تمام شنوندگان ارسال میکند.
|
|
422
781
|
|
|
782
|
+
### `ChannelSignal<TMap>`
|
|
783
|
+
|
|
784
|
+
- **`constructor(config)`**: یک channel signal جدید ایجاد میکند.
|
|
785
|
+
- `config.name`: `string`
|
|
786
|
+
- **`.dispatch(name, payload?)`**: یک پیام با نام مشخص ارسال میکند. TypeScript نوع صحیح payload را برای هر نام اعمال میکند.
|
|
787
|
+
- **`.on(name, handler, options?)`**: به یک پیام با نام مشخص subscribe میکند. handler مستقیماً `payload` را دریافت میکند (نه envelope کامل). از یک `Map` داخلی برای routing **O(1)** استفاده میکند. از گزینه `once` پشتیبانی میکند.
|
|
788
|
+
- **`.subscribe(callback, options?)`**: به **جریان خام پیامها** subscribe میکند — هر envelope `{name, payload}` را صرفنظر از نام دریافت میکند. برای لاگگیری و middleware مفید است.
|
|
789
|
+
|
|
423
790
|
### متدهای مشترک
|
|
424
791
|
|
|
425
792
|
- **`.subscribe(callback, options?)`**: یک شنونده را مشترک میکند. `{ unsubscribe: () => void }` را برمیگرداند.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { type AlwatrLogger } from '@alwatr/logger';
|
|
2
|
+
import { SignalBase } from './signal-base.js';
|
|
3
|
+
import type { SignalConfig, SubscribeOptions, SubscribeResult, ListenerCallback } from '../type.js';
|
|
4
|
+
/**
|
|
5
|
+
* A single message dispatched through a `ChannelSignal`.
|
|
6
|
+
*
|
|
7
|
+
* `name` identifies the message type (e.g. `'open-drawer'`, `'add-to-cart'`).
|
|
8
|
+
* `payload` is the optional value attached to the message — its type is narrowed
|
|
9
|
+
* by the generic map `TMap` at the class level.
|
|
10
|
+
*
|
|
11
|
+
* @template TMap A record mapping message names to their payload types.
|
|
12
|
+
* @template K The specific message name key (inferred, not set manually).
|
|
13
|
+
*/
|
|
14
|
+
export type ChannelMessage<TMap extends Record<string, unknown>, K extends keyof TMap = keyof TMap> = K extends keyof TMap ? {
|
|
15
|
+
name: K;
|
|
16
|
+
payload?: TMap[K];
|
|
17
|
+
} : never;
|
|
18
|
+
/**
|
|
19
|
+
* A typed handler for a specific named message on a `ChannelSignal`.
|
|
20
|
+
* Receives only the `payload` — the name is already known at subscription time.
|
|
21
|
+
*
|
|
22
|
+
* @template TMap A record mapping message names to their payload types.
|
|
23
|
+
* @template K The specific message name key.
|
|
24
|
+
*/
|
|
25
|
+
export type ChannelHandler<TMap extends Record<string, unknown>, K extends keyof TMap> = (payload: TMap[K] | undefined) => void | Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Configuration for creating a `ChannelSignal`.
|
|
28
|
+
*/
|
|
29
|
+
export interface ChannelSignalConfig extends SignalConfig {
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A stateless multi-channel signal that acts as a typed O(1) message bus.
|
|
33
|
+
*
|
|
34
|
+
* `ChannelSignal` is ideal when you need a single signal to carry multiple
|
|
35
|
+
* distinct message types — each identified by a `name` — rather than creating
|
|
36
|
+
* a separate `EventSignal` for every event.
|
|
37
|
+
*
|
|
38
|
+
* ### Routing architecture
|
|
39
|
+
*
|
|
40
|
+
* Internally, `on()` subscriptions are stored in a per-name `Map` of handler
|
|
41
|
+
* sets. When a message is dispatched, only the handlers registered for that
|
|
42
|
+
* specific name are invoked — O(1) lookup regardless of how many distinct
|
|
43
|
+
* names are subscribed. The inherited `SignalBase` observer list is used
|
|
44
|
+
* exclusively by `subscribe()`, which receives the raw message stream for
|
|
45
|
+
* logging or middleware purposes.
|
|
46
|
+
*
|
|
47
|
+
* ### Type safety
|
|
48
|
+
*
|
|
49
|
+
* The generic parameter `TMap` is a record that maps every valid message name
|
|
50
|
+
* to its payload type. TypeScript enforces the correct payload type at both
|
|
51
|
+
* `dispatch` and `on` call sites.
|
|
52
|
+
*
|
|
53
|
+
* @template TMap A record mapping message names to their payload types.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* interface AppMessages {
|
|
58
|
+
* 'open-drawer': {panel: string};
|
|
59
|
+
* 'close-drawer': void;
|
|
60
|
+
* 'show-toast': {message: string; type: 'info' | 'error'};
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* const appChannel = new ChannelSignal<AppMessages>({name: 'app-channel'});
|
|
64
|
+
*
|
|
65
|
+
* // Subscribe to a specific message — handler receives payload directly
|
|
66
|
+
* appChannel.on('open-drawer', (payload) => {
|
|
67
|
+
* openDrawer(payload!.panel);
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Dispatch a typed message
|
|
71
|
+
* appChannel.dispatch('open-drawer', {panel: 'settings'});
|
|
72
|
+
* appChannel.dispatch('close-drawer'); // no payload needed
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare class ChannelSignal<TMap extends Record<string, unknown>> extends SignalBase<ChannelMessage<TMap>> {
|
|
76
|
+
/**
|
|
77
|
+
* The logger instance for this signal.
|
|
78
|
+
* @protected
|
|
79
|
+
*/
|
|
80
|
+
protected logger_: AlwatrLogger;
|
|
81
|
+
/**
|
|
82
|
+
* Per-name handler registry for O(1) routing.
|
|
83
|
+
*
|
|
84
|
+
* Each key is a message name; the value is a Set of `{handler, once}` entries
|
|
85
|
+
* registered via `on()`. Kept separate from `SignalBase`'s observer list so
|
|
86
|
+
* that `subscribe()` (raw stream) and `on()` (named routing) never interfere.
|
|
87
|
+
*
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
private readonly namedHandlers__;
|
|
91
|
+
constructor(config: ChannelSignalConfig);
|
|
92
|
+
/**
|
|
93
|
+
* Dispatches a named message to:
|
|
94
|
+
* 1. All handlers registered via `on(name, …)` for this specific name — O(1).
|
|
95
|
+
* 2. All raw-stream subscribers registered via `subscribe()` — O(N subscribers).
|
|
96
|
+
*
|
|
97
|
+
* The notification is scheduled as a microtask to ensure non-blocking,
|
|
98
|
+
* consistent delivery — matching the behavior of `EventSignal`.
|
|
99
|
+
*
|
|
100
|
+
* TypeScript enforces that `payload` matches the type declared for `name`
|
|
101
|
+
* in `TMap`. If the payload type is `void` or `undefined`, the argument can
|
|
102
|
+
* be omitted entirely.
|
|
103
|
+
*
|
|
104
|
+
* @param name The message name (must be a key of `TMap`).
|
|
105
|
+
* @param payload The optional payload for the message.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* channel.dispatch('open-drawer', {panel: 'settings'});
|
|
110
|
+
* channel.dispatch('close-drawer'); // no payload needed
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
dispatch<K extends keyof TMap>(name: K, payload?: TMap[K]): void;
|
|
114
|
+
/**
|
|
115
|
+
* Subscribes to a specific named message on this channel.
|
|
116
|
+
*
|
|
117
|
+
* Uses an internal per-name handler map for O(1) routing — dispatching a
|
|
118
|
+
* message with name `'A'` will never invoke handlers registered for `'B'`.
|
|
119
|
+
*
|
|
120
|
+
* The handler receives the `payload` directly (not the full `{name, payload}`
|
|
121
|
+
* envelope) — since the name is already known at subscription time, passing
|
|
122
|
+
* it again would be redundant.
|
|
123
|
+
*
|
|
124
|
+
* @param name The message name to listen for.
|
|
125
|
+
* @param handler Callback invoked with the payload each time the named message
|
|
126
|
+
* is dispatched.
|
|
127
|
+
* @param options Standard subscribe options. Only `once` is supported here;
|
|
128
|
+
* `priority` applies to `subscribe()` (raw stream) only.
|
|
129
|
+
* @returns A `SubscribeResult` with an `unsubscribe()` method for cleanup.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* const sub = channel.on('open-drawer', (payload) => {
|
|
134
|
+
* openDrawer(payload!.panel);
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* // Stop listening when the component is destroyed
|
|
138
|
+
* sub.unsubscribe();
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
on<K extends keyof TMap>(name: K, handler: ChannelHandler<TMap, K>, options?: Pick<SubscribeOptions, 'once'>): SubscribeResult;
|
|
142
|
+
/**
|
|
143
|
+
* Subscribes to **all** messages dispatched on this channel, regardless of name.
|
|
144
|
+
*
|
|
145
|
+
* Use this when you need to observe the raw message stream — for example,
|
|
146
|
+
* for logging, debugging, or middleware-style processing.
|
|
147
|
+
*
|
|
148
|
+
* Prefer `on(name, handler)` for normal use cases to keep subscriptions
|
|
149
|
+
* focused and type-safe.
|
|
150
|
+
*
|
|
151
|
+
* @param callback The function called with every `ChannelMessage`.
|
|
152
|
+
* @param options Standard subscribe options.
|
|
153
|
+
* @returns A `SubscribeResult` with an `unsubscribe()` method.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* // Log every message for debugging
|
|
158
|
+
* channel.subscribe((msg) => console.log('[channel]', msg.name, msg.payload));
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
subscribe(callback: ListenerCallback<ChannelMessage<TMap>>, options?: SubscribeOptions): SubscribeResult;
|
|
162
|
+
/**
|
|
163
|
+
* Core routing method — called inside the microtask scheduled by `dispatch`.
|
|
164
|
+
*
|
|
165
|
+
* 1. Looks up the per-name handler set in O(1).
|
|
166
|
+
* 2. Invokes each handler, removing `once` entries after their first call.
|
|
167
|
+
* 3. Notifies raw-stream subscribers via `SignalBase.notify_()`.
|
|
168
|
+
*
|
|
169
|
+
* @private
|
|
170
|
+
*/
|
|
171
|
+
private route__;
|
|
172
|
+
/**
|
|
173
|
+
* Destroys the signal, clearing all named handlers and raw-stream subscribers.
|
|
174
|
+
*/
|
|
175
|
+
destroy(): void;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=channel-signal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-signal.d.ts","sourceRoot":"","sources":["../../src/core/channel-signal.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAC,MAAM,YAAY,CAAC;AAIlG;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,GAAG,MAAM,IAAI,IAChG,CAAC,SAAS,MAAM,IAAI,GAAG;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;CAAC,GAAG,KAAK,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,IAAI,CACvF,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,KACzB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,YAAY;CAAG;AAI5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBAAa,aAAa,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACvG;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAEhC;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CACpB;gBAEA,MAAM,EAAE,mBAAmB;IAMvC;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI;IAMvE;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACI,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,EAC5B,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,EAChC,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,GACvC,eAAe;IA2BlB;;;;;;;;;;;;;;;;;;OAkBG;IACa,SAAS,CACvB,QAAQ,EAAE,gBAAgB,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAChD,OAAO,CAAC,EAAE,gBAAgB,GACzB,eAAe;IAKlB;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAO;IAyBf;;OAEG;IACa,OAAO,IAAI,IAAI;CAIhC"}
|
|
@@ -68,6 +68,7 @@ export declare abstract class SignalBase<T> {
|
|
|
68
68
|
* Executes a given observer's callback with the provided value, handling both synchronous and asynchronous callbacks.
|
|
69
69
|
*/
|
|
70
70
|
private executeObserver__;
|
|
71
|
+
private pendingRejects__;
|
|
71
72
|
/**
|
|
72
73
|
* Returns a Promise that resolves with the next value dispatched by the signal.
|
|
73
74
|
* This provides an elegant way to wait for a single, future event using `async/await`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-base.d.ts","sourceRoot":"","sources":["../../src/core/signal-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAC7G,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAEjD;;;;;GAKG;AACH,8BAAsB,UAAU,CAAC,CAAC;IAoCpB,SAAS,CAAC,OAAO,EAAE,YAAY;IAnC3C;;;OAGG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAEzC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,kBAAkB,oBAA2B;IAChE,SAAS,CAAC,QAAQ,CAAC,UAAU,oBAA2B;IAExD;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;;;;OAKG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;gBAEqB,OAAO,EAAE,YAAY;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAYvD;;;;;;;;OAQG;IACI,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe;IAkB5F;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAiBjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;;;;;;;OAYG;IACI,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"signal-base.d.ts","sourceRoot":"","sources":["../../src/core/signal-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAC7G,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAEjD;;;;;GAKG;AACH,8BAAsB,UAAU,CAAC,CAAC;IAoCpB,SAAS,CAAC,OAAO,EAAE,YAAY;IAnC3C;;;OAGG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAEzC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,kBAAkB,oBAA2B;IAChE,SAAS,CAAC,QAAQ,CAAC,UAAU,oBAA2B;IAExD;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;;;;OAKG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;gBAEqB,OAAO,EAAE,YAAY;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAYvD;;;;;;;;OAQG;IACI,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe;IAkB5F;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAiBjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,gBAAgB,CAAqC;IAE7D;;;;;;;;;;;;OAYG;IACI,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC;IAmB9B;;;;;;OAMG;IACI,OAAO,IAAI,IAAI;IAqBtB;;;;OAIG;IACH,SAAS,CAAC,eAAe,IAAI,IAAI;CAMlC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ChannelSignal } from '../core/channel-signal.js';
|
|
2
|
+
import type { ChannelSignalConfig } from '../core/channel-signal.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a stateless multi-channel signal that acts as a typed message bus.
|
|
5
|
+
*
|
|
6
|
+
* `ChannelSignal` is ideal when you need a single signal to carry multiple
|
|
7
|
+
* distinct message types — each identified by a `name` — rather than creating
|
|
8
|
+
* a separate `EventSignal` for every event.
|
|
9
|
+
*
|
|
10
|
+
* The generic parameter `TMap` is a record that maps every valid message name
|
|
11
|
+
* to its payload type, giving you full type safety at both dispatch and subscribe sites.
|
|
12
|
+
*
|
|
13
|
+
* @template TMap A record mapping message names to their payload types.
|
|
14
|
+
*
|
|
15
|
+
* @param config The configuration for the channel signal.
|
|
16
|
+
* @returns A new instance of `ChannelSignal`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* interface AppMessages {
|
|
21
|
+
* 'open-drawer': {panel: string};
|
|
22
|
+
* 'close-drawer': void;
|
|
23
|
+
* 'show-toast': {message: string; type: 'info' | 'error'};
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* const appChannel = createChannelSignal<AppMessages>({name: 'app-channel'});
|
|
27
|
+
*
|
|
28
|
+
* // Subscribe to a specific message
|
|
29
|
+
* appChannel.on('show-toast', (payload) => {
|
|
30
|
+
* toast.show(payload!.message, payload!.type);
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Dispatch a message
|
|
34
|
+
* appChannel.dispatch('show-toast', {message: 'Saved!', type: 'info'});
|
|
35
|
+
* appChannel.dispatch('close-drawer');
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function createChannelSignal<TMap extends Record<string, unknown>>(config: ChannelSignalConfig): ChannelSignal<TMap>;
|
|
39
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/creators/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,2BAA2B,CAAC;AAExD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,2BAA2B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtE,MAAM,EAAE,mBAAmB,GAC1B,aAAa,CAAC,IAAI,CAAC,CAErB"}
|
package/dist/main.d.ts
CHANGED
|
@@ -5,12 +5,14 @@ export * from './core/computed-signal.js';
|
|
|
5
5
|
export * from './core/effect-signal.js';
|
|
6
6
|
export * from './core/persistent-state-signal.js';
|
|
7
7
|
export * from './core/session-state-signal.js';
|
|
8
|
+
export * from './core/channel-signal.js';
|
|
8
9
|
export * from './creators/event.js';
|
|
9
10
|
export * from './creators/state.js';
|
|
10
11
|
export * from './creators/computed.js';
|
|
11
12
|
export * from './creators/effect.js';
|
|
12
13
|
export * from './creators/persistent-state.js';
|
|
13
14
|
export * from './creators/session-state.js';
|
|
15
|
+
export * from './creators/channel.js';
|
|
14
16
|
export * from './operators/debounce.js';
|
|
15
17
|
export * from './operators/filter.js';
|
|
16
18
|
export * from './operators/map.js';
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AAEzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AAEtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AAEnC,mBAAmB,WAAW,CAAC"}
|