@portento/core 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/LICENSE +21 -0
- package/README.md +475 -0
- package/dist/index.d.mts +93 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +774 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +732 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Luca Leone
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
# Portento Core
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@portento/core)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
Lightweight dependency injection framework for React and React Native with seamless MobX integration. Build scalable applications with clean architecture using decorators and IoC patterns.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- ๐ฏ **Three-tier DI scoping** - Root, Router, and Component-level dependency management
|
|
12
|
+
- โก **MobX Integration** - Automatic observer wrapping for reactive components
|
|
13
|
+
- ๐จ **Decorator-based API** - Clean, declarative syntax with `@Injectable`, `@Component`, `@Router`
|
|
14
|
+
- ๐ **Automatic Resolution** - Smart dependency injection with hierarchical fallback
|
|
15
|
+
- ๐งช **Testing Utilities** - Reset scopes for isolated unit tests
|
|
16
|
+
- ๐ฆ **TypeScript-first** - Full type safety and IntelliSense support
|
|
17
|
+
- ๐ **Framework Agnostic** - Works with React, React Native, and Angular
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add @portento/core react mobx mobx-react tsyringe reflect-metadata
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or with npm:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @portento/core react mobx mobx-react tsyringe reflect-metadata
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## TypeScript Configuration
|
|
32
|
+
|
|
33
|
+
Enable decorators in your `tsconfig.json`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"compilerOptions": {
|
|
38
|
+
"experimentalDecorators": true,
|
|
39
|
+
"emitDecoratorMetadata": true,
|
|
40
|
+
"strict": true
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Import `reflect-metadata` at your app entry point:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import 'reflect-metadata';
|
|
49
|
+
import { AppRegistry } from 'react-native';
|
|
50
|
+
import App from './App';
|
|
51
|
+
|
|
52
|
+
AppRegistry.registerComponent('MyApp', () => App);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
### 1. Create a Service with `@Injectable`
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { Injectable } from '@portento/core';
|
|
61
|
+
import { makeAutoObservable } from 'mobx';
|
|
62
|
+
|
|
63
|
+
@Injectable({ providedIn: 'root' })
|
|
64
|
+
class AuthService {
|
|
65
|
+
public isAuthenticated = false;
|
|
66
|
+
|
|
67
|
+
constructor() {
|
|
68
|
+
makeAutoObservable(this);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
login(username: string) {
|
|
72
|
+
this.isAuthenticated = true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
logout() {
|
|
76
|
+
this.isAuthenticated = false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 2. Create a Component with `@Component`
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import React from 'react';
|
|
85
|
+
import { View, Text, Button } from 'react-native';
|
|
86
|
+
import { Component, IoComponent } from '@portento/core';
|
|
87
|
+
|
|
88
|
+
@Component({
|
|
89
|
+
selector: 'home-screen',
|
|
90
|
+
providers: []
|
|
91
|
+
})
|
|
92
|
+
class HomeScreen implements IoComponent {
|
|
93
|
+
constructor(
|
|
94
|
+
private authService: AuthService
|
|
95
|
+
) {}
|
|
96
|
+
|
|
97
|
+
render() {
|
|
98
|
+
return (
|
|
99
|
+
<View>
|
|
100
|
+
<Text>
|
|
101
|
+
{this.authService.isAuthenticated ? 'Logged In' : 'Not Logged In'}
|
|
102
|
+
</Text>
|
|
103
|
+
<Button
|
|
104
|
+
title="Login"
|
|
105
|
+
onPress={() => this.authService.login('user')}
|
|
106
|
+
/>
|
|
107
|
+
</View>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const HomeScreenComponent = Component.$provider(HomeScreen);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 3. Use in Your App
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { HomeScreenComponent } from './HomeScreen';
|
|
119
|
+
|
|
120
|
+
export default function App() {
|
|
121
|
+
return <HomeScreenComponent />;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Dependency Injection Scoping
|
|
126
|
+
|
|
127
|
+
Portento Core provides a three-tier scoping hierarchy for dependency management:
|
|
128
|
+
|
|
129
|
+
### 1. Root Scope (Singleton)
|
|
130
|
+
|
|
131
|
+
Services registered at root scope are singletons shared across the entire application:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
@Injectable({ providedIn: 'root' })
|
|
135
|
+
class UserStore {
|
|
136
|
+
public username = 'Guest';
|
|
137
|
+
|
|
138
|
+
constructor() {
|
|
139
|
+
makeAutoObservable(this);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 2. Router Scope (Feature-level)
|
|
145
|
+
|
|
146
|
+
Services shared across components within the same router:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
@Injectable()
|
|
150
|
+
class SharedNavStore {
|
|
151
|
+
public currentTab = 0;
|
|
152
|
+
|
|
153
|
+
constructor() {
|
|
154
|
+
makeAutoObservable(this);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@Router({
|
|
159
|
+
selector: 'main-nav-router',
|
|
160
|
+
components: [HomeScreen, ProfileScreen],
|
|
161
|
+
providers: [SharedNavStore]
|
|
162
|
+
})
|
|
163
|
+
class MainNavRouter implements IoComponent {
|
|
164
|
+
render() {
|
|
165
|
+
return (
|
|
166
|
+
<View>
|
|
167
|
+
<HomeScreen.$provider />
|
|
168
|
+
<ProfileScreen.$provider />
|
|
169
|
+
</View>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 3. Component Scope (Local)
|
|
176
|
+
|
|
177
|
+
Services isolated to a single component instance:
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
@Injectable()
|
|
181
|
+
class FormValidator {
|
|
182
|
+
public errors: string[] = [];
|
|
183
|
+
|
|
184
|
+
validate(value: string) {
|
|
185
|
+
// Validation logic
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@Component({
|
|
190
|
+
selector: 'login-form',
|
|
191
|
+
providers: [FormValidator]
|
|
192
|
+
})
|
|
193
|
+
class LoginForm implements IoComponent {
|
|
194
|
+
constructor(private validator: FormValidator) {}
|
|
195
|
+
|
|
196
|
+
render() {
|
|
197
|
+
// Component implementation
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Resolution Hierarchy
|
|
203
|
+
|
|
204
|
+
Dependencies are resolved with automatic fallback:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
Component Scope โ Router Scope โ Root Scope
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
If a dependency isn't found in the component's providers, it searches the router's providers, then falls back to root scope.
|
|
211
|
+
|
|
212
|
+
## MobX Integration
|
|
213
|
+
|
|
214
|
+
All components are automatically wrapped with MobX's `observer()` HOC for reactive updates:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
@Injectable({ providedIn: 'root' })
|
|
218
|
+
class CounterStore {
|
|
219
|
+
public count = 0;
|
|
220
|
+
|
|
221
|
+
constructor() {
|
|
222
|
+
makeAutoObservable(this);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
increment() {
|
|
226
|
+
this.count++; // Component automatically re-renders
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@Component({
|
|
231
|
+
selector: 'counter',
|
|
232
|
+
providers: []
|
|
233
|
+
})
|
|
234
|
+
class Counter implements IoComponent {
|
|
235
|
+
constructor(private store: CounterStore) {}
|
|
236
|
+
|
|
237
|
+
render() {
|
|
238
|
+
return (
|
|
239
|
+
<View>
|
|
240
|
+
<Text>{this.store.count}</Text>
|
|
241
|
+
<Button title="+" onPress={() => this.store.increment()} />
|
|
242
|
+
</View>
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Component Export Patterns
|
|
249
|
+
|
|
250
|
+
### Pattern 1: Direct Decoration
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
@Component({
|
|
254
|
+
selector: 'home-screen',
|
|
255
|
+
providers: []
|
|
256
|
+
})
|
|
257
|
+
class HomeScreen implements IoComponent {
|
|
258
|
+
render() {
|
|
259
|
+
return <View>...</View>;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Usage in JSX:
|
|
264
|
+
<HomeScreen.$provider />
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Pattern 2: Separate Class & Export (Recommended)
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
@Component({
|
|
271
|
+
selector: 'settings-screen',
|
|
272
|
+
providers: []
|
|
273
|
+
})
|
|
274
|
+
class Settings implements IoComponent {
|
|
275
|
+
render() {
|
|
276
|
+
return <View>...</View>;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export const SettingsScreen = Component.$provider(Settings);
|
|
281
|
+
|
|
282
|
+
// Usage in JSX (cleaner):
|
|
283
|
+
<SettingsScreen />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Lifecycle Methods
|
|
287
|
+
|
|
288
|
+
Components support standard React lifecycle methods:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
@Component({
|
|
292
|
+
selector: 'my-component',
|
|
293
|
+
providers: []
|
|
294
|
+
})
|
|
295
|
+
class MyComponent implements IoComponent {
|
|
296
|
+
componentDidMount() {
|
|
297
|
+
console.log('Component mounted');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
componentDidUpdate(prevProps, prevState) {
|
|
301
|
+
console.log('Component updated');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
componentWillUnmount() {
|
|
305
|
+
console.log('Component unmounting');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
render() {
|
|
309
|
+
return <View>...</View>;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Testing Utilities
|
|
315
|
+
|
|
316
|
+
Reset dependency instances for isolated unit tests:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { resetScope, resetClass, resetAll } from '@portento/core';
|
|
320
|
+
|
|
321
|
+
// Reset all root scope instances
|
|
322
|
+
resetScope('root');
|
|
323
|
+
|
|
324
|
+
// Reset specific router scope
|
|
325
|
+
resetScope('router', 'main-nav-router');
|
|
326
|
+
|
|
327
|
+
// Reset component scope
|
|
328
|
+
resetScope('component', 'home-screen');
|
|
329
|
+
|
|
330
|
+
// Reset specific class (conceptually)
|
|
331
|
+
resetClass('AuthService');
|
|
332
|
+
|
|
333
|
+
// Reset everything
|
|
334
|
+
resetAll();
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## API Reference
|
|
338
|
+
|
|
339
|
+
### `@Injectable(params)`
|
|
340
|
+
|
|
341
|
+
Register a class as an injectable service.
|
|
342
|
+
|
|
343
|
+
**Parameters:**
|
|
344
|
+
- `providedIn?: 'root'` - Register as root-scoped singleton
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
@Injectable({ providedIn: 'root' })
|
|
348
|
+
class MyService {}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### `@Component(params)`
|
|
352
|
+
|
|
353
|
+
Create a React component with dependency injection.
|
|
354
|
+
|
|
355
|
+
**Parameters:**
|
|
356
|
+
- `selector: string` - Unique component identifier
|
|
357
|
+
- `providers?: Array<Class>` - Component-scoped services
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
@Component({
|
|
361
|
+
selector: 'my-component',
|
|
362
|
+
providers: [LocalService]
|
|
363
|
+
})
|
|
364
|
+
class MyComponent implements IoComponent {}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### `@Router(params)`
|
|
368
|
+
|
|
369
|
+
Create a router component that groups child components with shared dependencies.
|
|
370
|
+
|
|
371
|
+
**Parameters:**
|
|
372
|
+
- `selector: string` - Unique router identifier
|
|
373
|
+
- `components: Array<Class>` - Child components
|
|
374
|
+
- `providers?: Array<Class>` - Router-scoped services
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
@Router({
|
|
378
|
+
selector: 'main-router',
|
|
379
|
+
components: [ScreenA, ScreenB],
|
|
380
|
+
providers: [SharedStore]
|
|
381
|
+
})
|
|
382
|
+
class MainRouter implements IoComponent {}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### `IoComponent` Interface
|
|
386
|
+
|
|
387
|
+
Base interface for all components:
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
interface IoComponent<Props = any, State = any> {
|
|
391
|
+
state?: State;
|
|
392
|
+
componentDidMount?(): void;
|
|
393
|
+
componentDidUpdate?(prevProps: Props, prevState: State): void;
|
|
394
|
+
componentWillUnmount?(): void;
|
|
395
|
+
render(): React.ReactNode;
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### `Controller` Type
|
|
400
|
+
|
|
401
|
+
Access React component state and methods:
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
interface Controller<Props = any, State = any> {
|
|
405
|
+
props: Props;
|
|
406
|
+
state: State;
|
|
407
|
+
setState: (state: Partial<State> | ((prevState: State) => State)) => void;
|
|
408
|
+
forceUpdate: () => void;
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Inject the controller:
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
@Component({
|
|
416
|
+
selector: 'stateful-component',
|
|
417
|
+
providers: []
|
|
418
|
+
})
|
|
419
|
+
class StatefulComponent implements IoComponent {
|
|
420
|
+
constructor(private controller: Controller) {}
|
|
421
|
+
|
|
422
|
+
updateState() {
|
|
423
|
+
this.controller.setState({ counter: 1 });
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Examples
|
|
429
|
+
|
|
430
|
+
Complete usage examples are available in the [@portento/core-examples](https://www.npmjs.com/package/@portento/core-examples) package:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
yarn add @portento/core-examples
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Examples include:
|
|
437
|
+
- **StoreExample** - MobX observable stores with different scopes
|
|
438
|
+
- **ScopingExample** - Dependency injection hierarchy demonstration
|
|
439
|
+
- **RouterScopeExample** - Shared state across router components
|
|
440
|
+
- **ResetExample** - Cleanup utilities for testing
|
|
441
|
+
|
|
442
|
+
## Troubleshooting
|
|
443
|
+
|
|
444
|
+
### Decorators not working
|
|
445
|
+
|
|
446
|
+
Ensure `experimentalDecorators` and `emitDecoratorMetadata` are enabled in `tsconfig.json`.
|
|
447
|
+
|
|
448
|
+
### "Design:paramtypes" metadata missing
|
|
449
|
+
|
|
450
|
+
Import `reflect-metadata` at your app entry point before any other imports.
|
|
451
|
+
|
|
452
|
+
### MobX observables not triggering re-renders
|
|
453
|
+
|
|
454
|
+
Make sure your stores use `makeAutoObservable(this)` in the constructor.
|
|
455
|
+
|
|
456
|
+
### Dependency not found
|
|
457
|
+
|
|
458
|
+
Check the resolution order: component providers โ router providers โ root scope. Ensure the service is registered at the appropriate level.
|
|
459
|
+
|
|
460
|
+
## Architecture Documentation
|
|
461
|
+
|
|
462
|
+
For detailed architecture information, see:
|
|
463
|
+
- [USAGE_PATTERNS.md](./docs/USAGE_PATTERNS.md) - Component patterns
|
|
464
|
+
|
|
465
|
+
## License
|
|
466
|
+
|
|
467
|
+
MIT ยฉ Luca Leone
|
|
468
|
+
|
|
469
|
+
## Contributing
|
|
470
|
+
|
|
471
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
472
|
+
|
|
473
|
+
## Repository
|
|
474
|
+
|
|
475
|
+
[https://github.com/luca-leone/portento-core](https://github.com/luca-leone/portento-core)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React$1 from 'react';
|
|
2
|
+
|
|
3
|
+
type Ctor<T> = new (...args: Array<any>) => T;
|
|
4
|
+
interface Controller<Props = unknown, State = unknown> {
|
|
5
|
+
props: Props;
|
|
6
|
+
state: State;
|
|
7
|
+
setState<S = State>(state: S | ((prevState: S) => S)): void;
|
|
8
|
+
forceUpdate(): void;
|
|
9
|
+
}
|
|
10
|
+
type InjectableParams = {
|
|
11
|
+
providedIn: 'root';
|
|
12
|
+
};
|
|
13
|
+
type ComponentParams = {
|
|
14
|
+
selector: string;
|
|
15
|
+
providers?: Array<Ctor<unknown>>;
|
|
16
|
+
};
|
|
17
|
+
type RouterParams = {
|
|
18
|
+
selector: string;
|
|
19
|
+
components: Array<Ctor<unknown> | React.FC>;
|
|
20
|
+
providers?: Array<Ctor<unknown>>;
|
|
21
|
+
};
|
|
22
|
+
interface IoComponent<Props = unknown, State = unknown> {
|
|
23
|
+
state?: State;
|
|
24
|
+
componentDidMount?(): void;
|
|
25
|
+
componentDidUpdate?(prevProps: Props, prevState: State): void;
|
|
26
|
+
componentWillUnmount?(): void;
|
|
27
|
+
render(): React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
type ComponentWrapperProps = Record<string, unknown>;
|
|
30
|
+
type ComponentWrapperState = Record<string, unknown>;
|
|
31
|
+
type RouterWrapperProps = Record<string, unknown>;
|
|
32
|
+
type RouterWrapperState = Record<string, unknown>;
|
|
33
|
+
|
|
34
|
+
type ComponentDecoratorFunction = {
|
|
35
|
+
<T extends Ctor<IoComponent>>(Entity: T): T;
|
|
36
|
+
$provider: <T extends Ctor<IoComponent>>(Entity: T) => React$1.FC;
|
|
37
|
+
};
|
|
38
|
+
declare function Component(params: ComponentParams): ComponentDecoratorFunction;
|
|
39
|
+
declare namespace Component {
|
|
40
|
+
var $provider: <T extends Ctor<IoComponent>>(Entity: T) => React$1.FC;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare function Injectable(params?: InjectableParams): ClassDecorator;
|
|
44
|
+
|
|
45
|
+
type RouterDecoratorFunction = <T extends Ctor<IoComponent>>(Entity: T) => T;
|
|
46
|
+
declare function Router(params: RouterParams): RouterDecoratorFunction;
|
|
47
|
+
declare namespace Router {
|
|
48
|
+
var $provider: <T extends Ctor<IoComponent>>(Entity: T) => React$1.FC;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Reset all dependency instances in a specific scope
|
|
53
|
+
* Note: Due to tsyringe limitations, this resets ALL scopes.
|
|
54
|
+
* Useful for cleanup after logout, between tests, or when navigating away from features.
|
|
55
|
+
* All providers are automatically re-registered and will be re-instantiated on next access.
|
|
56
|
+
*
|
|
57
|
+
* @param _scope - Scope type (for API compatibility, currently resets all)
|
|
58
|
+
* @param _selector - Scope selector (for API compatibility, currently resets all)
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Clean up on logout
|
|
62
|
+
* resetScope('root');
|
|
63
|
+
*
|
|
64
|
+
* // Clean up when unmounting router
|
|
65
|
+
* resetScope('router', 'main-nav-router');
|
|
66
|
+
*
|
|
67
|
+
* // Clean up component scope
|
|
68
|
+
* resetScope('component', 'home-screen');
|
|
69
|
+
*/
|
|
70
|
+
declare function resetScope(_scope: "root" | "router" | "component", _selector?: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Reset all dependency instances
|
|
73
|
+
* Note: Due to tsyringe limitations, this resets ALL instances, not just the specified class.
|
|
74
|
+
* Useful for targeted cleanup scenarios. All providers are automatically re-registered.
|
|
75
|
+
*
|
|
76
|
+
* @param _className - Class name (for API compatibility, currently resets all)
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Conceptually reset SharedNavStore
|
|
80
|
+
* resetClass('SharedNavStore');
|
|
81
|
+
*/
|
|
82
|
+
declare function resetClass(_className: string): void;
|
|
83
|
+
/**
|
|
84
|
+
* Reset all instances in all scopes
|
|
85
|
+
* Warning: This will clear all cached singletons
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Clear everything (useful between tests)
|
|
89
|
+
* resetAll();
|
|
90
|
+
*/
|
|
91
|
+
declare function resetAll(): void;
|
|
92
|
+
|
|
93
|
+
export { Component, type ComponentParams, type ComponentWrapperProps, type ComponentWrapperState, type Controller, type Ctor, Injectable, type InjectableParams, type IoComponent, Router, type RouterParams, type RouterWrapperProps, type RouterWrapperState, resetAll, resetClass, resetScope };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React$1 from 'react';
|
|
2
|
+
|
|
3
|
+
type Ctor<T> = new (...args: Array<any>) => T;
|
|
4
|
+
interface Controller<Props = unknown, State = unknown> {
|
|
5
|
+
props: Props;
|
|
6
|
+
state: State;
|
|
7
|
+
setState<S = State>(state: S | ((prevState: S) => S)): void;
|
|
8
|
+
forceUpdate(): void;
|
|
9
|
+
}
|
|
10
|
+
type InjectableParams = {
|
|
11
|
+
providedIn: 'root';
|
|
12
|
+
};
|
|
13
|
+
type ComponentParams = {
|
|
14
|
+
selector: string;
|
|
15
|
+
providers?: Array<Ctor<unknown>>;
|
|
16
|
+
};
|
|
17
|
+
type RouterParams = {
|
|
18
|
+
selector: string;
|
|
19
|
+
components: Array<Ctor<unknown> | React.FC>;
|
|
20
|
+
providers?: Array<Ctor<unknown>>;
|
|
21
|
+
};
|
|
22
|
+
interface IoComponent<Props = unknown, State = unknown> {
|
|
23
|
+
state?: State;
|
|
24
|
+
componentDidMount?(): void;
|
|
25
|
+
componentDidUpdate?(prevProps: Props, prevState: State): void;
|
|
26
|
+
componentWillUnmount?(): void;
|
|
27
|
+
render(): React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
type ComponentWrapperProps = Record<string, unknown>;
|
|
30
|
+
type ComponentWrapperState = Record<string, unknown>;
|
|
31
|
+
type RouterWrapperProps = Record<string, unknown>;
|
|
32
|
+
type RouterWrapperState = Record<string, unknown>;
|
|
33
|
+
|
|
34
|
+
type ComponentDecoratorFunction = {
|
|
35
|
+
<T extends Ctor<IoComponent>>(Entity: T): T;
|
|
36
|
+
$provider: <T extends Ctor<IoComponent>>(Entity: T) => React$1.FC;
|
|
37
|
+
};
|
|
38
|
+
declare function Component(params: ComponentParams): ComponentDecoratorFunction;
|
|
39
|
+
declare namespace Component {
|
|
40
|
+
var $provider: <T extends Ctor<IoComponent>>(Entity: T) => React$1.FC;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare function Injectable(params?: InjectableParams): ClassDecorator;
|
|
44
|
+
|
|
45
|
+
type RouterDecoratorFunction = <T extends Ctor<IoComponent>>(Entity: T) => T;
|
|
46
|
+
declare function Router(params: RouterParams): RouterDecoratorFunction;
|
|
47
|
+
declare namespace Router {
|
|
48
|
+
var $provider: <T extends Ctor<IoComponent>>(Entity: T) => React$1.FC;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Reset all dependency instances in a specific scope
|
|
53
|
+
* Note: Due to tsyringe limitations, this resets ALL scopes.
|
|
54
|
+
* Useful for cleanup after logout, between tests, or when navigating away from features.
|
|
55
|
+
* All providers are automatically re-registered and will be re-instantiated on next access.
|
|
56
|
+
*
|
|
57
|
+
* @param _scope - Scope type (for API compatibility, currently resets all)
|
|
58
|
+
* @param _selector - Scope selector (for API compatibility, currently resets all)
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Clean up on logout
|
|
62
|
+
* resetScope('root');
|
|
63
|
+
*
|
|
64
|
+
* // Clean up when unmounting router
|
|
65
|
+
* resetScope('router', 'main-nav-router');
|
|
66
|
+
*
|
|
67
|
+
* // Clean up component scope
|
|
68
|
+
* resetScope('component', 'home-screen');
|
|
69
|
+
*/
|
|
70
|
+
declare function resetScope(_scope: "root" | "router" | "component", _selector?: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Reset all dependency instances
|
|
73
|
+
* Note: Due to tsyringe limitations, this resets ALL instances, not just the specified class.
|
|
74
|
+
* Useful for targeted cleanup scenarios. All providers are automatically re-registered.
|
|
75
|
+
*
|
|
76
|
+
* @param _className - Class name (for API compatibility, currently resets all)
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Conceptually reset SharedNavStore
|
|
80
|
+
* resetClass('SharedNavStore');
|
|
81
|
+
*/
|
|
82
|
+
declare function resetClass(_className: string): void;
|
|
83
|
+
/**
|
|
84
|
+
* Reset all instances in all scopes
|
|
85
|
+
* Warning: This will clear all cached singletons
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Clear everything (useful between tests)
|
|
89
|
+
* resetAll();
|
|
90
|
+
*/
|
|
91
|
+
declare function resetAll(): void;
|
|
92
|
+
|
|
93
|
+
export { Component, type ComponentParams, type ComponentWrapperProps, type ComponentWrapperState, type Controller, type Ctor, Injectable, type InjectableParams, type IoComponent, Router, type RouterParams, type RouterWrapperProps, type RouterWrapperState, resetAll, resetClass, resetScope };
|