@wirestate/react-signals 0.6.1 → 0.7.0-experimental.1
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/CHANGELOG.md +29 -1
- package/README.md +15 -287
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## 0.7.0
|
|
2
|
+
|
|
3
|
+
- Add `useScope` in `@wirestate/react`
|
|
4
|
+
- New lit elements modules - `@wirestate/lit` and `@wirestate/lit-signals`
|
|
5
|
+
- `EventBus`: add `unsubscribe` method for explicit handler removal by reference
|
|
6
|
+
- `QueryBus`: add `unregister` method for explicit handler removal by type and reference
|
|
7
|
+
- `CommandBus`: add `unregister` method for explicit handler removal by type and reference
|
|
8
|
+
- `WireScope`: add new event/command/query subscribe-unsubscribe methods
|
|
9
|
+
- Export more alias / methods from `@wirestate/core`
|
|
10
|
+
- Export more alias / methods from `@wirestate/react-mobx`
|
|
11
|
+
- Export missing methods typing for `@wirestate/core`
|
|
12
|
+
- Extensive JSDoc coverage for wirestate packages
|
|
13
|
+
- `createIocContainer`: Added ability to instantly provide and activate entries, targeted seeds
|
|
14
|
+
- `createInjectablesProvider`: Removed.
|
|
15
|
+
- `IocProvider`: Removed
|
|
16
|
+
- `useRootContainer`: Added separate hook for store management in React tree
|
|
17
|
+
- `ContainerProvider`: Simpler provider for containers.
|
|
18
|
+
- `SubContainerProvider`: Added component solving problems of removed `createInjectablesProvider`
|
|
19
|
+
- `ContainerActivator`: Added separate activation component
|
|
20
|
+
|
|
21
|
+
## 0.6.3
|
|
22
|
+
|
|
23
|
+
- Update readme files for each module
|
|
24
|
+
|
|
25
|
+
## 0.6.2
|
|
26
|
+
|
|
27
|
+
- Corrected build system, react package structure
|
|
28
|
+
|
|
1
29
|
## 0.6.1
|
|
2
30
|
|
|
3
31
|
- React related types moved to react lib
|
|
@@ -51,6 +79,6 @@
|
|
|
51
79
|
- useService -> useInjection
|
|
52
80
|
- AbstractService::getService -> AbstractService::resolve
|
|
53
81
|
|
|
54
|
-
## 0.1.
|
|
82
|
+
## 0.1.0
|
|
55
83
|
|
|
56
84
|
- Initial release
|
package/README.md
CHANGED
|
@@ -1,319 +1,47 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @wirestate/react-signals [[monorepo](https://github.com/Neloreck/wirestate)] [[docs](https://neloreck.github.io/wirestate/)]
|
|
2
2
|
|
|
3
|
-
[](https://github.com/Neloreck/wirestate/search?l=typescript)
|
|
3
|
+
[](https://www.npmjs.com/package/@wirestate/react-signals)
|
|
5
4
|
[](https://github.com/Neloreck/wirestate/blob/master/LICENSE)
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
providing IOC/DI/indirection based architecture based on concepts of Services, Events, Commands, and Queries.
|
|
9
|
-
|
|
10
|
-
It optionally works with **MobX**, **Signals**, or other custom reactivity implementations.
|
|
11
|
-
|
|
12
|
-
## Architecture & Core Concepts
|
|
13
|
-
|
|
14
|
-
Designed for complex applications, `wirestate` enforces a clear separation of concerns:
|
|
15
|
-
|
|
16
|
-
- **Services**: Singleton-scoped logic units that hold state and business logic.
|
|
17
|
-
- **Dependency Injection**: First-class InversifyJS integration for decoupled, testable code.
|
|
18
|
-
- **Reactivity**: Independent state tracking (optional integration with MobX, Signals, etc.).
|
|
19
|
-
- **Events**: Fire-and-forget communication for cross-service side effects.
|
|
20
|
-
- **Commands**: Encapsulated write operations with standardized execution status (pending, settled, error).
|
|
21
|
-
- **Queries**: Synchronous or asynchronous request-response patterns for data retrieval.
|
|
22
|
-
- **Lifecycle Management**: Automated services provision within react tree, activation/deactivation lifecycle.
|
|
23
|
-
|
|
24
|
-
## Requirements
|
|
25
|
-
|
|
26
|
-
- `react >= 16.8.0`
|
|
27
|
-
- `reflect-metadata` (must be imported at application entry)
|
|
6
|
+
Re-exports `@preact/signals-react` for use with wirestate services.
|
|
28
7
|
|
|
29
8
|
## Installation
|
|
30
9
|
|
|
31
10
|
```bash
|
|
32
|
-
npm install
|
|
11
|
+
npm install @wirestate/react-signals @preact/signals-react
|
|
33
12
|
```
|
|
34
13
|
|
|
35
|
-
|
|
14
|
+
For automatic component subscription without manual `useSignal` calls, add the Babel or SWC transform:
|
|
36
15
|
|
|
37
16
|
```bash
|
|
38
|
-
npm install --save @wirestate/react @wirestate/react-mobx mobx mobx-react-lite
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### For signals
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npm install --save @wirestate/react @wirestate/react-signals @preact/signals-react
|
|
45
17
|
npm install --save-dev @preact/signals-react-transform
|
|
46
18
|
```
|
|
47
19
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
### 1. Define a Service
|
|
51
|
-
|
|
52
|
-
Services are standard classes decorated with `@Injectable`. Use `WireScope` to interact with the framework.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
import { Injectable, Inject, WireScope, OnEvent, OnCommand, OnQuery } from '@wirestate/core';
|
|
56
|
-
import { makeObservable, Observable, Action } from '@wirestate/react-mobx';
|
|
57
|
-
|
|
58
|
-
@Injectable()
|
|
59
|
-
export class CounterService {
|
|
60
|
-
@Observable()
|
|
61
|
-
public count: number = 0;
|
|
62
|
-
|
|
63
|
-
public constructor(
|
|
64
|
-
@Inject(WireScope)
|
|
65
|
-
private scope: WireScope
|
|
66
|
-
) {
|
|
67
|
-
makeObservable(this);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
@Action()
|
|
71
|
-
public increment(amount: number = 1): void {
|
|
72
|
-
this.count += amount;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@Action()
|
|
76
|
-
public reset(): void {
|
|
77
|
-
this.count = 0;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
@OnCommand('INCREMENT')
|
|
81
|
-
public onIncrementCommand(amount: number = 1): void {
|
|
82
|
-
this.increment(amount);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
@OnQuery('GET_TOTAL')
|
|
86
|
-
public onGetTotal(): number {
|
|
87
|
-
return this.count;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
@OnEvent('RESET')
|
|
91
|
-
public onResetEvent(): void {
|
|
92
|
-
this.reset();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### 2. Configure the Provider
|
|
98
|
-
|
|
99
|
-
Bind services at any level of the component tree.
|
|
100
|
-
Lifetimes are managed automatically.
|
|
20
|
+
## Usage
|
|
101
21
|
|
|
102
|
-
```
|
|
103
|
-
import {
|
|
104
|
-
import { CounterService } from './CounterService';
|
|
105
|
-
|
|
106
|
-
const MainProvider = createInjectablesProvider([CounterService]);
|
|
107
|
-
|
|
108
|
-
export function Application() {
|
|
109
|
-
return (
|
|
110
|
-
<IocProvider>
|
|
111
|
-
<MainProvider>
|
|
112
|
-
<CounterView />
|
|
113
|
-
</MainProvider>
|
|
114
|
-
</IocProvider>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
22
|
+
```ts
|
|
23
|
+
import { signal, computed, effect, Signal, ReadonlySignal } from "@wirestate/react-signals";
|
|
117
24
|
```
|
|
118
25
|
|
|
119
|
-
|
|
26
|
+
Example service:
|
|
120
27
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```tsx
|
|
125
|
-
import { useInjection, useCommandCaller, useEventEmitter } from '@wirestate/react';
|
|
126
|
-
import { observer } from '@wirestate/react-mobx';
|
|
127
|
-
import { CounterService } from './CounterService';
|
|
128
|
-
|
|
129
|
-
export const CounterView = observer(() => {
|
|
130
|
-
const service = useInjection(CounterService);
|
|
131
|
-
const call = useCommandCaller();
|
|
132
|
-
const emit = useEventEmitter();
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<div>
|
|
136
|
-
<p>Count: {service.count}</p>
|
|
137
|
-
<button onClick={() => service.increment(5)}>Add 1 (Method)</button>
|
|
138
|
-
<button onClick={() => call('INCREMENT', 5)}>Add 5 (Command)</button>
|
|
139
|
-
<button onClick={() => service.reset()}>Reset (Method)</button>
|
|
140
|
-
<button onClick={() => emit('RESET')}>Reset (Event)</button>
|
|
141
|
-
</div>
|
|
142
|
-
);
|
|
143
|
-
});
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Quick Start with signals
|
|
147
|
-
|
|
148
|
-
### 1. Define a Service
|
|
149
|
-
|
|
150
|
-
Services use `signal` and `computed` for state management.
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
import { Injectable, Inject, WireScope, OnEvent, OnCommand, OnQuery } from '@wirestate/core';
|
|
154
|
-
import { signal, computed, Signal, ReadonlySignal } from '@wirestate/react-signals';
|
|
28
|
+
```ts
|
|
29
|
+
import { Injectable, Inject, WireScope } from "@wirestate/core";
|
|
30
|
+
import { signal, computed, Signal, ReadonlySignal } from "@wirestate/react-signals";
|
|
155
31
|
|
|
156
32
|
@Injectable()
|
|
157
33
|
export class CounterService {
|
|
158
34
|
public readonly count: Signal<number> = signal(0);
|
|
159
35
|
public readonly isEven: ReadonlySignal<boolean> = computed(() => this.count.value % 2 === 0);
|
|
160
36
|
|
|
161
|
-
public constructor(
|
|
162
|
-
@Inject(WireScope)
|
|
163
|
-
private scope: WireScope
|
|
164
|
-
) {}
|
|
165
|
-
|
|
166
|
-
public increment(amount: number = 1): void {
|
|
167
|
-
this.count.value += amount;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public reset(): void {
|
|
171
|
-
this.count.value = 0;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
@OnCommand('INCREMENT')
|
|
175
|
-
public onIncrementCommand(amount: number = 1): void {
|
|
176
|
-
this.increment(amount);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
@OnQuery('GET_TOTAL')
|
|
180
|
-
public onGetTotal(): number {
|
|
181
|
-
return this.count.value;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
@OnEvent('RESET')
|
|
185
|
-
public onResetEvent(): void {
|
|
186
|
-
this.reset();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### 2. Configure the Provider
|
|
192
|
-
|
|
193
|
-
The provider configuration remains the same regardless of the reactivity implementation.
|
|
194
|
-
|
|
195
|
-
```tsx
|
|
196
|
-
import { IocProvider, createInjectablesProvider } from '@wirestate/react';
|
|
197
|
-
import { CounterService } from './CounterService';
|
|
198
|
-
|
|
199
|
-
const MainProvider = createInjectablesProvider([CounterService]);
|
|
200
|
-
|
|
201
|
-
export function Application() {
|
|
202
|
-
return (
|
|
203
|
-
<IocProvider>
|
|
204
|
-
<MainProvider>
|
|
205
|
-
<CounterView />
|
|
206
|
-
</MainProvider>
|
|
207
|
-
</IocProvider>
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### 3. Consume in Components
|
|
213
|
-
|
|
214
|
-
Access signals directly in components. Reactivity is handled by the signals transform or manual subscription.
|
|
215
|
-
|
|
216
|
-
```tsx
|
|
217
|
-
import { useInjection, useCommandCaller, useEventEmitter } from '@wirestate/react';
|
|
218
|
-
import { CounterService } from './CounterService';
|
|
219
|
-
|
|
220
|
-
export function CounterView() {
|
|
221
|
-
const service = useInjection(CounterService);
|
|
222
|
-
const call = useCommandCaller();
|
|
223
|
-
const emit = useEventEmitter();
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<div>
|
|
227
|
-
<p>Count: {service.count}</p>
|
|
228
|
-
<p>Even: {service.isEven.value ? 'Yes' : 'No'}</p>
|
|
229
|
-
<button onClick={() => service.increment(5)}>Add 1 (Method)</button>
|
|
230
|
-
<button onClick={() => call('INCREMENT', 5)}>Add 5 (Command)</button>
|
|
231
|
-
<button onClick={() => service.reset()}>Reset (Method)</button>
|
|
232
|
-
<button onClick={() => emit('RESET')}>Reset (Event)</button>
|
|
233
|
-
</div>
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
## Advanced Usage
|
|
239
|
-
|
|
240
|
-
### Seeding Shared Initial State
|
|
241
|
-
|
|
242
|
-
`wirestate` supports providing initial data (seeds) to services during activation.
|
|
243
|
-
|
|
244
|
-
```tsx
|
|
245
|
-
const MainProvider = createInjectablesProvider([CounterService]);
|
|
246
|
-
|
|
247
|
-
<IocProvider>
|
|
248
|
-
<MainProvider seed={{ initialCount: 100 }}>
|
|
249
|
-
<CounterView />
|
|
250
|
-
</MainProvider>
|
|
251
|
-
</IocProvider>
|
|
252
|
-
```
|
|
37
|
+
public constructor(@Inject(WireScope) private scope: WireScope) {}
|
|
253
38
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
import { Injectable, Inject, SEED } from 'wirestate';
|
|
258
|
-
|
|
259
|
-
@Injectable()
|
|
260
|
-
export class CounterService {
|
|
261
|
-
// ...
|
|
262
|
-
public constructor(
|
|
263
|
-
@Inject(SEED)
|
|
264
|
-
initialState: { initialCount: number }
|
|
265
|
-
) {
|
|
266
|
-
this.count = seed.initialCount;
|
|
39
|
+
public increment(): void {
|
|
40
|
+
this.count.value++;
|
|
267
41
|
}
|
|
268
42
|
}
|
|
269
43
|
```
|
|
270
44
|
|
|
271
|
-
### Seeding Bound Initial State
|
|
272
|
-
|
|
273
|
-
`wirestate` supports providing initial data (seeds) to services during activation.
|
|
274
|
-
|
|
275
|
-
```tsx
|
|
276
|
-
const MainProvider = createInjectablesProvider([CounterService]);
|
|
277
|
-
|
|
278
|
-
<IocProvider>
|
|
279
|
-
<MainProvider seeds={[[CounterService, { count: 10 }]]}>
|
|
280
|
-
<CounterView />
|
|
281
|
-
</MainProvider>
|
|
282
|
-
</IocProvider>
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
In the service:
|
|
286
|
-
|
|
287
|
-
```typescript
|
|
288
|
-
import { Injectable, Inject, WireScope } from 'wirestate';
|
|
289
|
-
|
|
290
|
-
@Injectable()
|
|
291
|
-
export class CounterService {
|
|
292
|
-
// ...
|
|
293
|
-
public constructor(@Inject(WireScope) scope: WireScope) {
|
|
294
|
-
this.count = scope.getSeed(CounterService).count;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Service Lifecycle
|
|
300
|
-
|
|
301
|
-
Use decorators to handle initialization and cleanup.
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
import { OnActivated, OnDeactivation } from 'wirestate';
|
|
305
|
-
|
|
306
|
-
@OnActivated()
|
|
307
|
-
public onActivated(): void {
|
|
308
|
-
// Start polling, fetch initial data, etc.
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
@OnDeactivation()
|
|
312
|
-
public onDeactivation(): void {
|
|
313
|
-
// Cleanup subscriptions
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
45
|
## License
|
|
318
46
|
|
|
319
47
|
MIT
|