@wirestate/core 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 +186 -232
- package/cjs/development/index.js +325 -91
- package/cjs/development/index.js.map +1 -1
- package/cjs/development/lib.js +1033 -248
- package/cjs/development/lib.js.map +1 -1
- package/cjs/development/test-utils.js +95 -32
- package/cjs/development/test-utils.js.map +1 -1
- package/cjs/production/index.js +1 -1
- package/cjs/production/index.js.map +1 -1
- package/cjs/production/lib.js +1 -1
- package/cjs/production/lib.js.map +1 -1
- package/cjs/production/test-utils.js +1 -1
- package/cjs/production/test-utils.js.map +1 -1
- package/esm/development/alias.js +10 -1
- package/esm/development/alias.js.map +1 -1
- package/esm/development/bind/bind-constant.js +25 -4
- package/esm/development/bind/bind-constant.js.map +1 -1
- package/esm/development/bind/bind-dynamic-value.js +27 -7
- package/esm/development/bind/bind-dynamic-value.js.map +1 -1
- package/esm/development/bind/bind-entry.js +50 -17
- package/esm/development/bind/bind-entry.js.map +1 -1
- package/esm/development/bind/bind-service.js +71 -19
- package/esm/development/bind/bind-service.js.map +1 -1
- package/esm/development/bind/get-entry-token.js +21 -5
- package/esm/development/bind/get-entry-token.js.map +1 -1
- package/esm/development/commands/command-bus.js +93 -46
- package/esm/development/commands/command-bus.js.map +1 -1
- package/esm/development/commands/command-optional.js +28 -5
- package/esm/development/commands/command-optional.js.map +1 -1
- package/esm/development/commands/command.js +26 -5
- package/esm/development/commands/command.js.map +1 -1
- package/esm/development/commands/get-command-handler-metadata.js +8 -3
- package/esm/development/commands/get-command-handler-metadata.js.map +1 -1
- package/esm/development/commands/on-command.js +19 -3
- package/esm/development/commands/on-command.js.map +1 -1
- package/esm/development/container/create-base-container.js +57 -0
- package/esm/development/container/create-base-container.js.map +1 -0
- package/esm/development/container/create-container.js +78 -0
- package/esm/development/container/create-container.js.map +1 -0
- package/esm/development/container/wire-scope.js +236 -54
- package/esm/development/container/wire-scope.js.map +1 -1
- package/esm/development/error/error-code.js +2 -1
- package/esm/development/error/error-code.js.map +1 -1
- package/esm/development/error/wirestate-error.js +25 -4
- package/esm/development/error/wirestate-error.js.map +1 -1
- package/esm/development/events/build-event-dispatcher.js +20 -2
- package/esm/development/events/build-event-dispatcher.js.map +1 -1
- package/esm/development/events/emit-event.js +18 -5
- package/esm/development/events/emit-event.js.map +1 -1
- package/esm/development/events/event-bus.js +58 -9
- package/esm/development/events/event-bus.js.map +1 -1
- package/esm/development/events/get-event-handler-metadata.js +19 -4
- package/esm/development/events/get-event-handler-metadata.js.map +1 -1
- package/esm/development/events/on-event.js +31 -2
- package/esm/development/events/on-event.js.map +1 -1
- package/esm/development/index.js +5 -4
- package/esm/development/index.js.map +1 -1
- package/esm/development/queries/get-query-handler-metadata.js +20 -4
- package/esm/development/queries/get-query-handler-metadata.js.map +1 -1
- package/esm/development/queries/on-query.js +24 -2
- package/esm/development/queries/on-query.js.map +1 -1
- package/esm/development/queries/query-bus.js +82 -31
- package/esm/development/queries/query-bus.js.map +1 -1
- package/esm/development/queries/query-optional.js +19 -5
- package/esm/development/queries/query-optional.js.map +1 -1
- package/esm/development/queries/query.js +25 -5
- package/esm/development/queries/query.js.map +1 -1
- package/esm/development/registry.js +81 -24
- package/esm/development/registry.js.map +1 -1
- package/esm/development/seeds/apply-seeds.js +19 -5
- package/esm/development/seeds/apply-seeds.js.map +1 -1
- package/esm/development/seeds/apply-shared-seed.js +16 -4
- package/esm/development/seeds/apply-shared-seed.js.map +1 -1
- package/esm/development/seeds/tokens.js +31 -0
- package/esm/development/seeds/tokens.js.map +1 -0
- package/esm/development/seeds/unapply-seeds.js +16 -5
- package/esm/development/seeds/unapply-seeds.js.map +1 -1
- package/esm/development/service/get-activated-handler-metadata.js +16 -4
- package/esm/development/service/get-activated-handler-metadata.js.map +1 -1
- package/esm/development/service/get-deactivation-handler-metadata.js +16 -4
- package/esm/development/service/get-deactivation-handler-metadata.js.map +1 -1
- package/esm/development/service/on-activated.js +22 -2
- package/esm/development/service/on-activated.js.map +1 -1
- package/esm/development/service/on-deactivation.js +22 -2
- package/esm/development/service/on-deactivation.js.map +1 -1
- package/esm/development/test-utils/mock-bind-entry.js +17 -7
- package/esm/development/test-utils/mock-bind-entry.js.map +1 -1
- package/esm/development/test-utils/mock-bind-service.js +17 -7
- package/esm/development/test-utils/mock-bind-service.js.map +1 -1
- package/esm/development/test-utils/mock-container.js +25 -8
- package/esm/development/test-utils/mock-container.js.map +1 -1
- package/esm/development/test-utils/mock-service.js +18 -5
- package/esm/development/test-utils/mock-service.js.map +1 -1
- package/esm/development/test-utils/mock-unbind-service.js +16 -3
- package/esm/development/test-utils/mock-unbind-service.js.map +1 -1
- package/esm/development/types/commands.js +6 -1
- package/esm/development/types/commands.js.map +1 -1
- package/esm/production/alias.js +1 -1
- package/esm/production/alias.js.map +1 -1
- package/esm/production/bind/bind-constant.js +1 -1
- package/esm/production/bind/bind-constant.js.map +1 -1
- package/esm/production/bind/bind-dynamic-value.js +1 -1
- package/esm/production/bind/bind-dynamic-value.js.map +1 -1
- package/esm/production/bind/bind-entry.js +1 -1
- package/esm/production/bind/bind-entry.js.map +1 -1
- package/esm/production/bind/bind-service.js.map +1 -1
- package/esm/production/bind/get-entry-token.js.map +1 -1
- package/esm/production/commands/command-bus.js +1 -1
- package/esm/production/commands/command-bus.js.map +1 -1
- package/esm/production/commands/command-optional.js.map +1 -1
- package/esm/production/commands/command.js.map +1 -1
- package/esm/production/commands/get-command-handler-metadata.js.map +1 -1
- package/esm/production/commands/on-command.js.map +1 -1
- package/esm/production/container/create-base-container.js +1 -0
- package/esm/production/container/create-base-container.js.map +1 -0
- package/esm/production/container/create-container.js +1 -0
- package/esm/production/container/create-container.js.map +1 -0
- package/esm/production/container/wire-scope.js +1 -1
- package/esm/production/container/wire-scope.js.map +1 -1
- package/esm/production/error/error-code.js +1 -1
- package/esm/production/error/error-code.js.map +1 -1
- package/esm/production/error/wirestate-error.js.map +1 -1
- package/esm/production/events/build-event-dispatcher.js.map +1 -1
- package/esm/production/events/emit-event.js.map +1 -1
- package/esm/production/events/event-bus.js +1 -1
- package/esm/production/events/event-bus.js.map +1 -1
- package/esm/production/events/get-event-handler-metadata.js.map +1 -1
- package/esm/production/events/on-event.js.map +1 -1
- package/esm/production/index.js +1 -1
- package/esm/production/queries/get-query-handler-metadata.js.map +1 -1
- package/esm/production/queries/on-query.js.map +1 -1
- package/esm/production/queries/query-bus.js +1 -1
- package/esm/production/queries/query-bus.js.map +1 -1
- package/esm/production/queries/query-optional.js.map +1 -1
- package/esm/production/queries/query.js.map +1 -1
- package/esm/production/registry.js +1 -1
- package/esm/production/registry.js.map +1 -1
- package/esm/production/seeds/apply-seeds.js +1 -1
- package/esm/production/seeds/apply-seeds.js.map +1 -1
- package/esm/production/seeds/apply-shared-seed.js +1 -1
- package/esm/production/seeds/apply-shared-seed.js.map +1 -1
- package/esm/production/seeds/tokens.js +1 -0
- package/esm/production/seeds/tokens.js.map +1 -0
- package/esm/production/seeds/unapply-seeds.js +1 -1
- package/esm/production/seeds/unapply-seeds.js.map +1 -1
- package/esm/production/service/get-activated-handler-metadata.js.map +1 -1
- package/esm/production/service/get-deactivation-handler-metadata.js.map +1 -1
- package/esm/production/service/on-activated.js.map +1 -1
- package/esm/production/service/on-deactivation.js.map +1 -1
- package/esm/production/test-utils/mock-bind-entry.js +1 -1
- package/esm/production/test-utils/mock-bind-entry.js.map +1 -1
- package/esm/production/test-utils/mock-bind-service.js +1 -1
- package/esm/production/test-utils/mock-bind-service.js.map +1 -1
- package/esm/production/test-utils/mock-container.js +1 -1
- package/esm/production/test-utils/mock-container.js.map +1 -1
- package/esm/production/test-utils/mock-service.js.map +1 -1
- package/esm/production/test-utils/mock-unbind-service.js.map +1 -1
- package/esm/production/types/commands.js.map +1 -1
- package/index.d.ts +1159 -229
- package/lib.d.ts +128 -9
- package/package.json +1 -2
- package/test-utils.d.ts +140 -40
- package/esm/development/container/create-ioc-container.js +0 -35
- package/esm/development/container/create-ioc-container.js.map +0 -1
- package/esm/production/container/create-ioc-container.js +0 -1
- package/esm/production/container/create-ioc-container.js.map +0 -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,317 +1,271 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @wirestate/core [[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/core)
|
|
5
4
|
[](https://github.com/Neloreck/wirestate/blob/master/LICENSE)
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Core package for wirestate.
|
|
7
|
+
Provides the DI container, service primitives, and event/command/query buses.
|
|
8
|
+
React integration is in [`@wirestate/react`](https://www.npmjs.com/package/@wirestate/react).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Installation
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
```bash
|
|
13
|
+
npm install @wirestate/core reflect-metadata
|
|
14
|
+
```
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Import `reflect-metadata` once at your application entry point, before any wirestate imports:
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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.
|
|
18
|
+
```ts
|
|
19
|
+
import "reflect-metadata";
|
|
20
|
+
```
|
|
23
21
|
|
|
24
|
-
##
|
|
22
|
+
## Services
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
- `reflect-metadata` (must be imported at application entry)
|
|
24
|
+
Services are plain classes decorated with `@Injectable`. Each service may inject a `WireScope` which provides access to the event, command, and query buses and to other services in the container.
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
```ts
|
|
27
|
+
import { Injectable, Inject, WireScope } from "@wirestate/core";
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
@Injectable()
|
|
30
|
+
export class CounterService {
|
|
31
|
+
public count = 0;
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
public constructor(@Inject(WireScope) private scope: WireScope) {}
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
public increment(): void {
|
|
36
|
+
this.count++;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
## Container
|
|
42
42
|
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
npm install --save-dev @preact/signals-react-transform
|
|
46
|
-
```
|
|
43
|
+
```ts
|
|
44
|
+
import { createIocContainer, bindService } from "@wirestate/core";
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
const container = createIocContainer({
|
|
47
|
+
seed: { baseUrl: "https://example.com" },
|
|
48
|
+
entries: [CounterService],
|
|
49
|
+
});
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
bindService(container, AnotherService);
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
const counterService = container.get(CounterService);
|
|
54
|
+
const anotherService = container.get(AnotherService);
|
|
55
|
+
```
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
import { makeObservable, Observable, Action } from '@wirestate/react-mobx';
|
|
57
|
+
`bindService` binds a class in singleton scope by default.
|
|
58
|
+
Use `bindConstant` to bind a value, `bindEntry` to bind under a custom token.
|
|
57
59
|
|
|
58
|
-
|
|
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
|
-
}
|
|
60
|
+
## Events
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
public increment(amount: number = 1): void {
|
|
72
|
-
this.count += amount;
|
|
73
|
-
}
|
|
62
|
+
Events are fire-and-forget messages. Any service can emit or subscribe.
|
|
74
63
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.count = 0;
|
|
78
|
-
}
|
|
64
|
+
```ts
|
|
65
|
+
import { OnEvent, WireScope, Inject } from "@wirestate/core";
|
|
79
66
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
67
|
+
@Injectable()
|
|
68
|
+
export class SenderService {
|
|
69
|
+
public constructor(@Inject(WireScope) private scope: WireScope) {}
|
|
84
70
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return this.count;
|
|
71
|
+
public notify(): void {
|
|
72
|
+
this.scope.emitEvent("USER_LOGGED_OUT");
|
|
88
73
|
}
|
|
74
|
+
}
|
|
89
75
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
76
|
+
@Injectable()
|
|
77
|
+
export class ReceiverService {
|
|
78
|
+
@OnEvent("USER_LOGGED_OUT")
|
|
79
|
+
public onLogout(): void {
|
|
80
|
+
// handle logout
|
|
93
81
|
}
|
|
94
82
|
}
|
|
95
83
|
```
|
|
96
84
|
|
|
97
|
-
|
|
85
|
+
`@OnEvent()` with no argument subscribes to all events.
|
|
98
86
|
|
|
99
|
-
|
|
100
|
-
Lifetimes are managed automatically.
|
|
87
|
+
## Commands
|
|
101
88
|
|
|
102
|
-
|
|
103
|
-
import { IocProvider, createInjectablesProvider } from '@wirestate/react';
|
|
104
|
-
import { CounterService } from './CounterService';
|
|
89
|
+
Commands are write operations dispatched by token. A single handler is expected per command type.
|
|
105
90
|
|
|
106
|
-
|
|
91
|
+
```ts
|
|
92
|
+
import { OnCommand, WireScope, Inject } from "@wirestate/core";
|
|
107
93
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
</IocProvider>
|
|
115
|
-
);
|
|
94
|
+
@Injectable()
|
|
95
|
+
export class AuthService {
|
|
96
|
+
@OnCommand("LOGIN")
|
|
97
|
+
public async onLogin(payload: { username: string }): Promise<void> {
|
|
98
|
+
// perform login
|
|
99
|
+
}
|
|
116
100
|
}
|
|
117
|
-
```
|
|
118
101
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
});
|
|
102
|
+
@Injectable()
|
|
103
|
+
export class AnotherService {
|
|
104
|
+
public constructor(@Inject(WireScope) private scope: WireScope) {}
|
|
105
|
+
|
|
106
|
+
public async login(): Promise<void> {
|
|
107
|
+
await this.scope.executeCommand("LOGIN").task;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
144
110
|
```
|
|
145
111
|
|
|
146
|
-
|
|
112
|
+
Use `commandOptional` when a handler may not be registered — returns `null` instead of throwing.
|
|
147
113
|
|
|
148
|
-
|
|
114
|
+
## Queries
|
|
149
115
|
|
|
150
|
-
|
|
116
|
+
Queries are request-response operations. A single handler is expected per query type.
|
|
151
117
|
|
|
152
|
-
```
|
|
153
|
-
import {
|
|
154
|
-
import { signal, computed, Signal, ReadonlySignal } from '@wirestate/react-signals';
|
|
118
|
+
```ts
|
|
119
|
+
import { OnQuery, WireScope, Inject } from "@wirestate/core";
|
|
155
120
|
|
|
156
121
|
@Injectable()
|
|
157
|
-
export class
|
|
158
|
-
|
|
159
|
-
public readonly isEven: ReadonlySignal<boolean> = computed(() => this.count.value % 2 === 0);
|
|
122
|
+
export class StoreService {
|
|
123
|
+
private items: Array<string> = [];
|
|
160
124
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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);
|
|
125
|
+
@OnQuery("STORE_ITEMS")
|
|
126
|
+
public onGetItems(): Array<string> {
|
|
127
|
+
return this.items;
|
|
177
128
|
}
|
|
129
|
+
}
|
|
178
130
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
131
|
+
@Injectable()
|
|
132
|
+
export class AnotherService {
|
|
133
|
+
public constructor(@Inject(WireScope) private scope: WireScope) {}
|
|
183
134
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this.
|
|
135
|
+
public async someActionRequiringItems(): Promise<void> {
|
|
136
|
+
const asyncItems: Array<string> = await this.scope.queryData("STORE_ITEMS");
|
|
137
|
+
const syncItems: Array<string> = await this.scope.queryData("STORE_ITEMS");
|
|
187
138
|
}
|
|
188
139
|
}
|
|
189
140
|
```
|
|
190
141
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
The provider configuration remains the same regardless of the reactivity implementation.
|
|
142
|
+
## Seeds
|
|
194
143
|
|
|
195
|
-
|
|
196
|
-
import { IocProvider, createInjectablesProvider } from '@wirestate/react';
|
|
197
|
-
import { CounterService } from './CounterService';
|
|
144
|
+
Seeds pass initial data to services when they are activated.
|
|
198
145
|
|
|
199
|
-
|
|
146
|
+
```ts
|
|
147
|
+
import { SEED, Injectable, Inject } from "@wirestate/core";
|
|
200
148
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<CounterView />
|
|
206
|
-
</MainProvider>
|
|
207
|
-
</IocProvider>
|
|
208
|
-
);
|
|
149
|
+
// Shared seed — same object injected into all services in the tree:
|
|
150
|
+
@Injectable()
|
|
151
|
+
export class MyService {
|
|
152
|
+
public constructor(@Inject(SEED) private seed: { theme: string }) {}
|
|
209
153
|
}
|
|
210
|
-
```
|
|
211
154
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
);
|
|
155
|
+
// Per-service seed — each service gets its own seed value:
|
|
156
|
+
@Injectable()
|
|
157
|
+
export class OtherService {
|
|
158
|
+
public constructor(@Inject(WireScope) scope: WireScope) {
|
|
159
|
+
const { count } = scope.getSeed(OtherService) as { count: number };
|
|
160
|
+
}
|
|
235
161
|
}
|
|
236
162
|
```
|
|
237
163
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
### Seeding Shared Initial State
|
|
164
|
+
Seeds are applied via `applySeeds` / `applySharedSeed` and removed via `unapplySeeds`.
|
|
165
|
+
In React, pass them as `seed` or `seeds` props to the provider — see `@wirestate/react`.
|
|
241
166
|
|
|
242
|
-
|
|
167
|
+
## Lifecycle
|
|
243
168
|
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
<IocProvider>
|
|
248
|
-
<MainProvider seed={{ initialCount: 100 }}>
|
|
249
|
-
<CounterView />
|
|
250
|
-
</MainProvider>
|
|
251
|
-
</IocProvider>
|
|
252
|
-
```
|
|
169
|
+
```ts
|
|
170
|
+
import { OnActivated, OnDeactivation } from "@wirestate/core";
|
|
253
171
|
|
|
254
|
-
|
|
172
|
+
@Injectable()
|
|
173
|
+
export class PollingService {
|
|
174
|
+
private timer?: ReturnType<typeof setInterval>;
|
|
255
175
|
|
|
256
|
-
|
|
257
|
-
|
|
176
|
+
@OnActivated()
|
|
177
|
+
public onActivated(): void {
|
|
178
|
+
this.timer = setInterval(() => console.info("interval execution"), 5000);
|
|
179
|
+
}
|
|
258
180
|
|
|
259
|
-
@
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
public constructor(
|
|
263
|
-
@Inject(SEED)
|
|
264
|
-
initialState: { initialCount: number }
|
|
265
|
-
) {
|
|
266
|
-
this.count = seed.initialCount;
|
|
181
|
+
@OnDeactivation()
|
|
182
|
+
public onDeactivation(): void {
|
|
183
|
+
clearInterval(this.timer);
|
|
267
184
|
}
|
|
268
185
|
}
|
|
269
186
|
```
|
|
270
187
|
|
|
271
|
-
|
|
188
|
+
`@OnActivated` runs after the service is bound and all dependencies are resolved.
|
|
189
|
+
`@OnDeactivation` runs when the container scope is disposed.
|
|
190
|
+
|
|
191
|
+
## WireScope API
|
|
192
|
+
|
|
193
|
+
`WireScope` is injected per-service and exposes:
|
|
194
|
+
|
|
195
|
+
| Method | Description |
|
|
196
|
+
| ----------------------------------------- | --------------------------------------------------------------- |
|
|
197
|
+
| `getContainer()` | Access the raw IoC container |
|
|
198
|
+
| `resolve(token)` | Resolve a service or value by token |
|
|
199
|
+
| `resolveOptional(token)` | Resolve a service or value, returns `null` if not bound |
|
|
200
|
+
| `getSeed(token?)` | Get the per-service or shared seed |
|
|
201
|
+
| `emitEvent(type, payload?, from?)` | Emit an event |
|
|
202
|
+
| `subscribeToEvent(handler)` | Subscribe a handler to all events; returns unsubscribe function |
|
|
203
|
+
| `unsubscribeFromEvent(handler)` | Remove a specific event subscription by handler reference |
|
|
204
|
+
| `queryData(type, data?)` | Dispatch a query and return the result |
|
|
205
|
+
| `queryOptionalData(type, data?)` | Dispatch a query; returns `null` if no handler is registered |
|
|
206
|
+
| `registerQueryHandler(type, handler)` | Register a query handler; returns unregister function |
|
|
207
|
+
| `unregisterQueryHandler(type, handler)` | Remove a specific query handler by type and reference |
|
|
208
|
+
| `executeCommand(type, data?)` | Dispatch a command and return a descriptor |
|
|
209
|
+
| `executeOptionalCommand(type, data?)` | Dispatch a command; returns `null` if no handler is registered |
|
|
210
|
+
| `registerCommandHandler(type, handler)` | Register a command handler; returns unregister function |
|
|
211
|
+
| `unregisterCommandHandler(type, handler)` | Remove a specific command handler by type and reference |
|
|
212
|
+
|
|
213
|
+
## Test utilities
|
|
214
|
+
|
|
215
|
+
Available via `@wirestate/core/test-utils`:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
import {
|
|
219
|
+
mockContainer,
|
|
220
|
+
mockService,
|
|
221
|
+
mockBindService,
|
|
222
|
+
mockBindEntry,
|
|
223
|
+
mockUnbindService,
|
|
224
|
+
} from "@wirestate/core/test-utils";
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### `mockContainer(options?)`
|
|
272
228
|
|
|
273
|
-
|
|
229
|
+
Creates a configured IoC container for testing. Accepts an optional object:
|
|
274
230
|
|
|
275
|
-
|
|
276
|
-
|
|
231
|
+
| Option | Type | Description |
|
|
232
|
+
| --------------- | ---------------------------------------- | --------------------------------------------- |
|
|
233
|
+
| `entries` | `Array<Newable \| InjectableDescriptor>` | Services or descriptors to bind |
|
|
234
|
+
| `activate` | `Array<ServiceIdentifier>` | Tokens to resolve immediately after binding |
|
|
235
|
+
| `skipLifecycle` | `boolean` | Skip `@OnActivated` / `@OnDeactivation` hooks |
|
|
277
236
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
237
|
+
```ts
|
|
238
|
+
const container = mockContainer({
|
|
239
|
+
entries: [CounterService, LoggerService],
|
|
240
|
+
activate: [CounterService],
|
|
241
|
+
});
|
|
283
242
|
```
|
|
284
243
|
|
|
285
|
-
|
|
244
|
+
### `mockService(ServiceClass, container?, options?)`
|
|
286
245
|
|
|
287
|
-
|
|
288
|
-
import { Injectable, Inject, WireScope } from 'wirestate';
|
|
246
|
+
Binds a service class to a container and returns its instance. Creates a new `mockContainer` if none is provided.
|
|
289
247
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
this.count = scope.getSeed(CounterService).count;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
248
|
+
```ts
|
|
249
|
+
const counter = mockService(CounterService);
|
|
250
|
+
counter.increment();
|
|
251
|
+
expect(counter.count).toBe(1);
|
|
297
252
|
```
|
|
298
253
|
|
|
299
|
-
###
|
|
254
|
+
### `mockBindService(container, ServiceClass, options?)`
|
|
300
255
|
|
|
301
|
-
|
|
256
|
+
Binds a service class to an existing container. Accepts `{ skipLifecycle?: boolean }`.
|
|
302
257
|
|
|
303
|
-
|
|
304
|
-
import { OnActivated, OnDeactivation } from 'wirestate';
|
|
258
|
+
### `mockBindEntry(container, entry, options?)`
|
|
305
259
|
|
|
306
|
-
|
|
307
|
-
public onActivated(): void {
|
|
308
|
-
// Start polling, fetch initial data, etc.
|
|
309
|
-
}
|
|
260
|
+
Binds a service class or `InjectableDescriptor` to an existing container. Accepts `{ skipLifecycle?: boolean }`.
|
|
310
261
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
262
|
+
### `mockUnbindService(container, ServiceClass)`
|
|
263
|
+
|
|
264
|
+
Removes a service binding from the container. Useful for overriding registrations between tests.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
mockUnbindService(container, CounterService);
|
|
268
|
+
mockBindEntry(container, { token: CounterService, useValue: fakeCounter });
|
|
315
269
|
```
|
|
316
270
|
|
|
317
271
|
## License
|