@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/dist/index.js
ADDED
|
@@ -0,0 +1,774 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Component: () => Component,
|
|
34
|
+
Injectable: () => Injectable,
|
|
35
|
+
Router: () => Router,
|
|
36
|
+
resetAll: () => resetAll,
|
|
37
|
+
resetClass: () => resetClass,
|
|
38
|
+
resetScope: () => resetScope
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
|
|
42
|
+
// src/DependencyManagement.ts
|
|
43
|
+
var import_tsyringe = require("tsyringe");
|
|
44
|
+
var import_mobx = require("mobx");
|
|
45
|
+
var DependencyManagement = class _DependencyManagement {
|
|
46
|
+
constructor() {
|
|
47
|
+
// Single global container for all registrations
|
|
48
|
+
this.container = import_tsyringe.container.createChildContainer();
|
|
49
|
+
// Scope tracking maps: className -> Symbol token
|
|
50
|
+
this.rootScope = /* @__PURE__ */ new Map();
|
|
51
|
+
// Router scopes: routerSelector -> (className -> Symbol token)
|
|
52
|
+
this.routerScopes = /* @__PURE__ */ new Map();
|
|
53
|
+
// Component scopes: componentSelector -> (className -> Symbol token)
|
|
54
|
+
this.componentScopes = /* @__PURE__ */ new Map();
|
|
55
|
+
// Component-to-Router membership tracking
|
|
56
|
+
this.componentToRouter = /* @__PURE__ */ new Map();
|
|
57
|
+
// Store class references for re-registration after reset
|
|
58
|
+
this.rootClasses = /* @__PURE__ */ new Map();
|
|
59
|
+
this.routerClasses = /* @__PURE__ */ new Map();
|
|
60
|
+
this.componentClasses = /* @__PURE__ */ new Map();
|
|
61
|
+
(0, import_mobx.configure)({ useProxies: "always" });
|
|
62
|
+
this.container.register("DependencyManagement", {
|
|
63
|
+
useValue: this
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
static getInstance() {
|
|
67
|
+
if (!_DependencyManagement.instance) {
|
|
68
|
+
_DependencyManagement.instance = new _DependencyManagement();
|
|
69
|
+
}
|
|
70
|
+
return _DependencyManagement.instance;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Set the current resolution context (used during component instantiation)
|
|
74
|
+
*/
|
|
75
|
+
setContext(selector, routerSelector) {
|
|
76
|
+
this.currentSelector = selector;
|
|
77
|
+
this.currentRouterSelector = routerSelector;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Clear the current resolution context
|
|
81
|
+
*/
|
|
82
|
+
clearContext() {
|
|
83
|
+
this.currentSelector = void 0;
|
|
84
|
+
this.currentRouterSelector = void 0;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get current component selector context
|
|
88
|
+
*/
|
|
89
|
+
getCurrentSelector() {
|
|
90
|
+
return this.currentSelector;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get current router selector context
|
|
94
|
+
*/
|
|
95
|
+
getCurrentRouterSelector() {
|
|
96
|
+
return this.currentRouterSelector;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Generate a unique Symbol token for a class in a specific scope
|
|
100
|
+
*/
|
|
101
|
+
getToken(className, scope) {
|
|
102
|
+
return /* @__PURE__ */ Symbol.for(`${scope}:${className}`);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Setup and register a provider in the root scope
|
|
106
|
+
*/
|
|
107
|
+
setupRootContainer(Entity) {
|
|
108
|
+
const className = Entity.name;
|
|
109
|
+
if (!this.rootScope.has(className)) {
|
|
110
|
+
const scopedToken = this.getToken(className, "root");
|
|
111
|
+
this.rootScope.set(className, scopedToken);
|
|
112
|
+
this.rootClasses.set(className, Entity);
|
|
113
|
+
if (!this.container.isRegistered(scopedToken)) {
|
|
114
|
+
this.container.register(
|
|
115
|
+
scopedToken,
|
|
116
|
+
{ useClass: Entity },
|
|
117
|
+
{ lifecycle: import_tsyringe.Lifecycle.Singleton }
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the root container (for backward compatibility)
|
|
124
|
+
*/
|
|
125
|
+
getRootContainer() {
|
|
126
|
+
return this.container;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Legacy property accessor for backward compatibility
|
|
130
|
+
*/
|
|
131
|
+
get root() {
|
|
132
|
+
return this.container;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Setup and register providers in a component scope
|
|
136
|
+
*/
|
|
137
|
+
setupComponentContainer(selector, Providers = []) {
|
|
138
|
+
if (!this.componentScopes.has(selector)) {
|
|
139
|
+
this.componentScopes.set(selector, /* @__PURE__ */ new Map());
|
|
140
|
+
this.componentClasses.set(selector, /* @__PURE__ */ new Map());
|
|
141
|
+
}
|
|
142
|
+
const scopeMap = this.componentScopes.get(selector);
|
|
143
|
+
const classMap = this.componentClasses.get(selector);
|
|
144
|
+
if (!scopeMap || !classMap) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`Failed to create component scope for selector: ${selector}`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
for (const Provider of Providers) {
|
|
150
|
+
const className = Provider.name;
|
|
151
|
+
if (!scopeMap.has(className)) {
|
|
152
|
+
const scopedToken = this.getToken(
|
|
153
|
+
className,
|
|
154
|
+
`component:${selector}`
|
|
155
|
+
);
|
|
156
|
+
scopeMap.set(className, scopedToken);
|
|
157
|
+
classMap.set(className, Provider);
|
|
158
|
+
if (!this.container.isRegistered(scopedToken)) {
|
|
159
|
+
this.container.register(
|
|
160
|
+
scopedToken,
|
|
161
|
+
{ useClass: Provider },
|
|
162
|
+
{ lifecycle: import_tsyringe.Lifecycle.Singleton }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get a component-level container by selector (backward compatibility)
|
|
170
|
+
*/
|
|
171
|
+
getComponentContainer(selector) {
|
|
172
|
+
if (!this.componentScopes.has(selector)) {
|
|
173
|
+
return void 0;
|
|
174
|
+
}
|
|
175
|
+
return this.container;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Legacy property accessor for backward compatibility
|
|
179
|
+
*/
|
|
180
|
+
get component() {
|
|
181
|
+
const legacyMap = /* @__PURE__ */ new Map();
|
|
182
|
+
for (const selector of this.componentScopes.keys()) {
|
|
183
|
+
legacyMap.set(selector, this.container);
|
|
184
|
+
}
|
|
185
|
+
return legacyMap;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Setup and register providers in a router scope, tracking component membership
|
|
189
|
+
*/
|
|
190
|
+
setupRouterContainer(Components, Providers, selector) {
|
|
191
|
+
if (!this.routerScopes.has(selector)) {
|
|
192
|
+
this.routerScopes.set(selector, /* @__PURE__ */ new Map());
|
|
193
|
+
this.routerClasses.set(selector, /* @__PURE__ */ new Map());
|
|
194
|
+
}
|
|
195
|
+
const scopeMap = this.routerScopes.get(selector);
|
|
196
|
+
const classMap = this.routerClasses.get(selector);
|
|
197
|
+
if (!scopeMap || !classMap) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Failed to create router scope for selector: ${selector}`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
for (const Component2 of Components) {
|
|
203
|
+
const componentName = typeof Component2 === "string" ? Component2 : Component2.name;
|
|
204
|
+
this.componentToRouter.set(componentName, selector);
|
|
205
|
+
}
|
|
206
|
+
for (const Provider of Providers) {
|
|
207
|
+
const className = Provider.name;
|
|
208
|
+
if (!scopeMap.has(className)) {
|
|
209
|
+
const scopedToken = this.getToken(
|
|
210
|
+
className,
|
|
211
|
+
`router:${selector}`
|
|
212
|
+
);
|
|
213
|
+
scopeMap.set(className, scopedToken);
|
|
214
|
+
classMap.set(className, Provider);
|
|
215
|
+
if (!this.container.isRegistered(scopedToken)) {
|
|
216
|
+
this.container.register(
|
|
217
|
+
scopedToken,
|
|
218
|
+
{ useClass: Provider },
|
|
219
|
+
{ lifecycle: import_tsyringe.Lifecycle.Singleton }
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Get the router selector for a component (if registered in a router)
|
|
227
|
+
*/
|
|
228
|
+
getRouterForComponent(componentName) {
|
|
229
|
+
return this.componentToRouter.get(componentName);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Fetch a provider from the router container associated with an entity (backward compatibility)
|
|
233
|
+
*/
|
|
234
|
+
fetchFromRouterContainer(Entity) {
|
|
235
|
+
const routerSelector = this.getRouterForComponent(
|
|
236
|
+
Entity.name
|
|
237
|
+
);
|
|
238
|
+
if (routerSelector && this.routerScopes.has(routerSelector)) {
|
|
239
|
+
return this.container;
|
|
240
|
+
}
|
|
241
|
+
return void 0;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get a router-level container by selector (backward compatibility)
|
|
245
|
+
*/
|
|
246
|
+
getRouterContainer(selector) {
|
|
247
|
+
if (!this.routerScopes.has(selector)) {
|
|
248
|
+
return void 0;
|
|
249
|
+
}
|
|
250
|
+
return this.container;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Legacy property accessor for backward compatibility
|
|
254
|
+
*/
|
|
255
|
+
get router() {
|
|
256
|
+
const legacyMap = /* @__PURE__ */ new Map();
|
|
257
|
+
for (const selector of this.routerScopes.keys()) {
|
|
258
|
+
legacyMap.set(selector, this.container);
|
|
259
|
+
}
|
|
260
|
+
return legacyMap;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Check if a class is a MobX store by looking for MobX symbols
|
|
264
|
+
*/
|
|
265
|
+
isMobxStore(instance) {
|
|
266
|
+
const mobxSymbol = "mobx-stored-annotations";
|
|
267
|
+
const symbols = Object.getOwnPropertySymbols(instance);
|
|
268
|
+
return symbols.some((s) => s.description === mobxSymbol);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Resolve a dependency with strict scope isolation:
|
|
272
|
+
* 1. Component scope (if component explicitly registered the provider)
|
|
273
|
+
* 2. Router scope (ONLY if component is part of that router's components array)
|
|
274
|
+
* 3. Root scope (for @Injectable({ providedIn: 'root' }) services)
|
|
275
|
+
*
|
|
276
|
+
* Scope override behavior:
|
|
277
|
+
* - If a root service is re-registered at router/component level, that scope gets a NEW instance
|
|
278
|
+
* - Router-scoped services are ONLY accessible to components within that router
|
|
279
|
+
* - Parent components cannot access child router services
|
|
280
|
+
*
|
|
281
|
+
* Returns undefined if no provider is found in accessible scopes
|
|
282
|
+
*/
|
|
283
|
+
resolve(className, componentSelector, routerSelector, componentClassName) {
|
|
284
|
+
if (className === "DependencyManagement") {
|
|
285
|
+
return this.container.resolve("DependencyManagement");
|
|
286
|
+
}
|
|
287
|
+
if (componentSelector) {
|
|
288
|
+
const componentScope = this.componentScopes.get(componentSelector);
|
|
289
|
+
const componentToken = componentScope?.get(className);
|
|
290
|
+
if (componentToken && this.container.isRegistered(componentToken)) {
|
|
291
|
+
return this.container.resolve(componentToken);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (routerSelector) {
|
|
295
|
+
const routerScope = this.routerScopes.get(routerSelector);
|
|
296
|
+
const routerToken = routerScope?.get(className);
|
|
297
|
+
if (routerToken && this.container.isRegistered(routerToken)) {
|
|
298
|
+
return this.container.resolve(routerToken);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const parentRouterSelector = componentClassName ? this.getRouterForComponent(componentClassName) : void 0;
|
|
302
|
+
if (parentRouterSelector && parentRouterSelector !== routerSelector) {
|
|
303
|
+
const parentRouterScope = this.routerScopes.get(parentRouterSelector);
|
|
304
|
+
const parentRouterToken = parentRouterScope?.get(className);
|
|
305
|
+
if (parentRouterToken && this.container.isRegistered(parentRouterToken)) {
|
|
306
|
+
return this.container.resolve(parentRouterToken);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const rootToken = this.rootScope.get(className);
|
|
310
|
+
if (rootToken && this.container.isRegistered(rootToken)) {
|
|
311
|
+
return this.container.resolve(rootToken);
|
|
312
|
+
}
|
|
313
|
+
return void 0;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Convenience method for resolving dependencies using current context.
|
|
317
|
+
* Use this in component constructors when DependencyManagement is injected.
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* constructor(private dm: DependencyManagement) {
|
|
321
|
+
* this.myService = dm.get<MyService>('MyService');
|
|
322
|
+
* }
|
|
323
|
+
*/
|
|
324
|
+
get(className) {
|
|
325
|
+
return this.resolve(
|
|
326
|
+
className,
|
|
327
|
+
this.currentSelector,
|
|
328
|
+
this.currentRouterSelector
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Resolve a dependency from component, router, or root scope (backward compatibility)
|
|
333
|
+
*/
|
|
334
|
+
resolveFromScopes(EntityName, componentContainer, routerContainer) {
|
|
335
|
+
let componentSelector;
|
|
336
|
+
let routerSelector;
|
|
337
|
+
if (componentContainer) {
|
|
338
|
+
for (const [selector, _scopeMap] of this.componentScopes.entries()) {
|
|
339
|
+
componentSelector = selector;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (routerContainer) {
|
|
344
|
+
for (const [selector, _scopeMap] of this.routerScopes.entries()) {
|
|
345
|
+
routerSelector = selector;
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return this.resolve(EntityName, componentSelector, routerSelector);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Re-register all providers (helper for reset operations)
|
|
353
|
+
*/
|
|
354
|
+
reregisterAll() {
|
|
355
|
+
for (const [className, token] of this.rootScope.entries()) {
|
|
356
|
+
const Provider = this.rootClasses.get(className);
|
|
357
|
+
if (Provider) {
|
|
358
|
+
this.container.register(
|
|
359
|
+
token,
|
|
360
|
+
{ useClass: Provider },
|
|
361
|
+
{ lifecycle: import_tsyringe.Lifecycle.Singleton }
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
for (const [selector, routerScope] of this.routerScopes.entries()) {
|
|
366
|
+
const routerClassMap = this.routerClasses.get(selector);
|
|
367
|
+
if (routerClassMap) {
|
|
368
|
+
for (const [className, token] of routerScope.entries()) {
|
|
369
|
+
const Provider = routerClassMap.get(className);
|
|
370
|
+
if (Provider) {
|
|
371
|
+
this.container.register(
|
|
372
|
+
token,
|
|
373
|
+
{ useClass: Provider },
|
|
374
|
+
{ lifecycle: import_tsyringe.Lifecycle.Singleton }
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
for (const [selector, componentScope] of this.componentScopes.entries()) {
|
|
381
|
+
const componentClassMap = this.componentClasses.get(selector);
|
|
382
|
+
if (componentClassMap) {
|
|
383
|
+
for (const [className, token] of componentScope.entries()) {
|
|
384
|
+
const Provider = componentClassMap.get(className);
|
|
385
|
+
if (Provider) {
|
|
386
|
+
this.container.register(
|
|
387
|
+
token,
|
|
388
|
+
{ useClass: Provider },
|
|
389
|
+
{ lifecycle: import_tsyringe.Lifecycle.Singleton }
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Reset all instances in a specific scope
|
|
398
|
+
* Creates fresh container and re-registers all providers
|
|
399
|
+
* Note: Due to tsyringe limitations, this resets ALL scopes but is still useful for cleanup
|
|
400
|
+
*/
|
|
401
|
+
resetScope(_scope, _selector) {
|
|
402
|
+
this.container.reset();
|
|
403
|
+
this.container = import_tsyringe.container.createChildContainer();
|
|
404
|
+
this.reregisterAll();
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Reset a specific class across all scopes
|
|
408
|
+
* Creates fresh container and re-registers all providers
|
|
409
|
+
* Note: Due to tsyringe limitations, this resets ALL instances
|
|
410
|
+
*/
|
|
411
|
+
resetClass(_className) {
|
|
412
|
+
this.container.reset();
|
|
413
|
+
this.container = import_tsyringe.container.createChildContainer();
|
|
414
|
+
this.reregisterAll();
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Reset all instances in all scopes
|
|
418
|
+
* This clears all cached singletons but keeps registrations
|
|
419
|
+
*/
|
|
420
|
+
resetAll() {
|
|
421
|
+
this.container.clearInstances();
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/decorators/Component.ts
|
|
426
|
+
var import_react = __toESM(require("react"));
|
|
427
|
+
var import_mobx_react = require("mobx-react");
|
|
428
|
+
var import_tsyringe2 = require("tsyringe");
|
|
429
|
+
var componentRegistry = /* @__PURE__ */ new Map();
|
|
430
|
+
var componentReverseRegistry = /* @__PURE__ */ new Map();
|
|
431
|
+
function Component(params) {
|
|
432
|
+
const decorator = function(Entity) {
|
|
433
|
+
(0, import_tsyringe2.injectable)()(Entity);
|
|
434
|
+
class ComponentWrapper extends import_react.default.Component {
|
|
435
|
+
constructor(props) {
|
|
436
|
+
super(props);
|
|
437
|
+
this.entityInstance = null;
|
|
438
|
+
const initialState = {};
|
|
439
|
+
this.state = initialState;
|
|
440
|
+
this.dependencyManagement = DependencyManagement.getInstance();
|
|
441
|
+
this.dependencyManagement.setupComponentContainer(params.selector, [
|
|
442
|
+
...params.providers || [],
|
|
443
|
+
Entity
|
|
444
|
+
]);
|
|
445
|
+
const componentContainer = this.dependencyManagement.getComponentContainer(params.selector);
|
|
446
|
+
const routerSelector = this.dependencyManagement.getRouterForComponent(Entity.name);
|
|
447
|
+
const self = this;
|
|
448
|
+
const controller = {
|
|
449
|
+
props,
|
|
450
|
+
get state() {
|
|
451
|
+
return self.state;
|
|
452
|
+
},
|
|
453
|
+
setState: (state) => {
|
|
454
|
+
if (typeof state === "function") {
|
|
455
|
+
this.setState((prevState) => {
|
|
456
|
+
const newState = state(prevState);
|
|
457
|
+
return newState;
|
|
458
|
+
});
|
|
459
|
+
} else {
|
|
460
|
+
this.setState((prevState) => {
|
|
461
|
+
const newState = {
|
|
462
|
+
...prevState,
|
|
463
|
+
...state
|
|
464
|
+
};
|
|
465
|
+
return newState;
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
forceUpdate: this.forceUpdate.bind(this)
|
|
470
|
+
};
|
|
471
|
+
componentContainer?.register("Controller", { useValue: controller });
|
|
472
|
+
const paramTypes = Reflect.getMetadata(
|
|
473
|
+
"design:paramtypes",
|
|
474
|
+
Entity
|
|
475
|
+
);
|
|
476
|
+
const constructorArgs = [];
|
|
477
|
+
if (paramTypes && paramTypes.length > 0) {
|
|
478
|
+
for (const ParamType of paramTypes) {
|
|
479
|
+
let dependency = this.dependencyManagement.resolve(
|
|
480
|
+
ParamType.name,
|
|
481
|
+
params.selector,
|
|
482
|
+
routerSelector,
|
|
483
|
+
Entity.name
|
|
484
|
+
);
|
|
485
|
+
if (dependency === void 0 && ParamType.name === "Object") {
|
|
486
|
+
dependency = componentContainer?.resolve("Controller");
|
|
487
|
+
}
|
|
488
|
+
constructorArgs.push(dependency);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
this.entityInstance = // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
492
|
+
new Entity(...constructorArgs) ?? null;
|
|
493
|
+
if (this.entityInstance?.state !== void 0 && this.entityInstance?.state !== null) {
|
|
494
|
+
const entityState = Object.assign(
|
|
495
|
+
{},
|
|
496
|
+
this.entityInstance.state
|
|
497
|
+
);
|
|
498
|
+
Object.assign(this.state, entityState);
|
|
499
|
+
}
|
|
500
|
+
if (this.entityInstance) {
|
|
501
|
+
const prototype = Object.getPrototypeOf(
|
|
502
|
+
this.entityInstance
|
|
503
|
+
);
|
|
504
|
+
Object.getOwnPropertyNames(prototype).forEach((key) => {
|
|
505
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
|
|
506
|
+
if (key !== "constructor" && descriptor && typeof descriptor.value === "function") {
|
|
507
|
+
this.entityInstance[key] = descriptor.value.bind(this.entityInstance);
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
if ("state" in this.entityInstance) {
|
|
511
|
+
Object.defineProperty(this.entityInstance, "state", {
|
|
512
|
+
get: () => controller.state,
|
|
513
|
+
configurable: true,
|
|
514
|
+
enumerable: true
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
componentDidMount() {
|
|
520
|
+
if (this.entityInstance && typeof this.entityInstance.componentDidMount === "function") {
|
|
521
|
+
this.entityInstance.componentDidMount.call(this.entityInstance);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
componentDidUpdate(prevProps, prevState) {
|
|
525
|
+
if (this.entityInstance && typeof this.entityInstance.componentDidUpdate === "function") {
|
|
526
|
+
this.entityInstance.componentDidUpdate.call(
|
|
527
|
+
this.entityInstance,
|
|
528
|
+
prevProps,
|
|
529
|
+
prevState
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
componentWillUnmount() {
|
|
534
|
+
if (this.entityInstance && typeof this.entityInstance.componentWillUnmount === "function") {
|
|
535
|
+
this.entityInstance.componentWillUnmount.call(this.entityInstance);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
render() {
|
|
539
|
+
if (!this.entityInstance) {
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
return this.entityInstance.render.call(this.entityInstance);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const wrappedComponent = (0, import_mobx_react.observer)(ComponentWrapper);
|
|
546
|
+
const reactComponent = wrappedComponent;
|
|
547
|
+
componentRegistry.set(Entity.name, reactComponent);
|
|
548
|
+
componentReverseRegistry.set(reactComponent, Entity.name);
|
|
549
|
+
return Entity;
|
|
550
|
+
};
|
|
551
|
+
decorator.$provider = (Entity) => {
|
|
552
|
+
const component = componentRegistry.get(Entity.name);
|
|
553
|
+
if (!component) {
|
|
554
|
+
throw new Error(
|
|
555
|
+
`Component ${Entity.name} not found. Make sure to apply @Component decorator first.`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
return component;
|
|
559
|
+
};
|
|
560
|
+
return decorator;
|
|
561
|
+
}
|
|
562
|
+
function getComponentClassName(component) {
|
|
563
|
+
return componentReverseRegistry.get(component);
|
|
564
|
+
}
|
|
565
|
+
Component.$provider = (Entity) => {
|
|
566
|
+
const component = componentRegistry.get(Entity.name);
|
|
567
|
+
if (!component) {
|
|
568
|
+
throw new Error(
|
|
569
|
+
`Component ${Entity.name} not found. Make sure to apply @Component decorator first.`
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
return component;
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
// src/decorators/Injectable.ts
|
|
576
|
+
var import_tsyringe3 = require("tsyringe");
|
|
577
|
+
function Injectable(params) {
|
|
578
|
+
return function(Entity) {
|
|
579
|
+
(0, import_tsyringe3.injectable)()(Entity);
|
|
580
|
+
if (params?.providedIn === "root") {
|
|
581
|
+
const dependencyManagement = DependencyManagement.getInstance();
|
|
582
|
+
dependencyManagement.setupRootContainer(Entity);
|
|
583
|
+
}
|
|
584
|
+
return Entity;
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// src/decorators/Router.ts
|
|
589
|
+
var import_react2 = __toESM(require("react"));
|
|
590
|
+
var import_mobx_react2 = require("mobx-react");
|
|
591
|
+
var import_tsyringe4 = require("tsyringe");
|
|
592
|
+
var routerRegistry = /* @__PURE__ */ new Map();
|
|
593
|
+
var routerReverseRegistry = /* @__PURE__ */ new Map();
|
|
594
|
+
function getRouterClassName(router) {
|
|
595
|
+
return routerReverseRegistry.get(router);
|
|
596
|
+
}
|
|
597
|
+
function Router(params) {
|
|
598
|
+
const decorator = function(Entity) {
|
|
599
|
+
(0, import_tsyringe4.injectable)()(Entity);
|
|
600
|
+
const dependencyManagement = DependencyManagement.getInstance();
|
|
601
|
+
const componentClassNames = params.components.map((comp) => {
|
|
602
|
+
const componentClassName = getComponentClassName(
|
|
603
|
+
comp
|
|
604
|
+
);
|
|
605
|
+
if (componentClassName) {
|
|
606
|
+
return componentClassName;
|
|
607
|
+
}
|
|
608
|
+
const routerClassName = getRouterClassName(
|
|
609
|
+
comp
|
|
610
|
+
);
|
|
611
|
+
if (routerClassName) {
|
|
612
|
+
return routerClassName;
|
|
613
|
+
}
|
|
614
|
+
const classComp = comp;
|
|
615
|
+
return classComp.name || void 0;
|
|
616
|
+
}).filter((name) => name !== void 0);
|
|
617
|
+
dependencyManagement.setupRouterContainer(
|
|
618
|
+
componentClassNames,
|
|
619
|
+
[...params.providers || [], Entity],
|
|
620
|
+
params.selector
|
|
621
|
+
);
|
|
622
|
+
class RouterWrapper extends import_react2.default.Component {
|
|
623
|
+
constructor(props) {
|
|
624
|
+
super(props);
|
|
625
|
+
this.entityInstance = null;
|
|
626
|
+
const initialState = {};
|
|
627
|
+
this.state = initialState;
|
|
628
|
+
this.dependencyManagement = DependencyManagement.getInstance();
|
|
629
|
+
const routerContainerInstance = this.dependencyManagement.getRouterContainer(params.selector);
|
|
630
|
+
const wrapperInstance = this;
|
|
631
|
+
const controller = {
|
|
632
|
+
props,
|
|
633
|
+
get state() {
|
|
634
|
+
return wrapperInstance.state;
|
|
635
|
+
},
|
|
636
|
+
setState: (state) => {
|
|
637
|
+
if (typeof state === "function") {
|
|
638
|
+
this.setState((prevState) => {
|
|
639
|
+
const newState = state(prevState);
|
|
640
|
+
if (this.entityInstance?.state) {
|
|
641
|
+
Object.assign(this.entityInstance.state, newState);
|
|
642
|
+
}
|
|
643
|
+
return newState;
|
|
644
|
+
});
|
|
645
|
+
} else {
|
|
646
|
+
this.setState((prevState) => {
|
|
647
|
+
const newState = {
|
|
648
|
+
...prevState,
|
|
649
|
+
...state
|
|
650
|
+
};
|
|
651
|
+
if (this.entityInstance?.state) {
|
|
652
|
+
Object.assign(this.entityInstance.state, newState);
|
|
653
|
+
}
|
|
654
|
+
return newState;
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
forceUpdate: this.forceUpdate.bind(this)
|
|
659
|
+
};
|
|
660
|
+
routerContainerInstance?.register("Controller", { useValue: controller });
|
|
661
|
+
const paramTypes = Reflect.getMetadata(
|
|
662
|
+
"design:paramtypes",
|
|
663
|
+
Entity
|
|
664
|
+
);
|
|
665
|
+
const constructorArgs = [];
|
|
666
|
+
if (paramTypes && paramTypes.length > 0) {
|
|
667
|
+
for (const ParamType of paramTypes) {
|
|
668
|
+
let dependency = this.dependencyManagement.resolve(
|
|
669
|
+
ParamType.name,
|
|
670
|
+
void 0,
|
|
671
|
+
// No component selector - this is a router
|
|
672
|
+
params.selector,
|
|
673
|
+
// Own router scope
|
|
674
|
+
Entity.name
|
|
675
|
+
// Pass class name to find parent router if needed
|
|
676
|
+
);
|
|
677
|
+
if (dependency === void 0 && ParamType.name === "Object") {
|
|
678
|
+
dependency = routerContainerInstance?.resolve("Controller");
|
|
679
|
+
}
|
|
680
|
+
constructorArgs.push(dependency);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
this.entityInstance = // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
684
|
+
new Entity(...constructorArgs) ?? null;
|
|
685
|
+
if (this.entityInstance?.state !== void 0 && this.entityInstance?.state !== null) {
|
|
686
|
+
const entityState = Object.assign(
|
|
687
|
+
{},
|
|
688
|
+
this.entityInstance.state
|
|
689
|
+
);
|
|
690
|
+
Object.assign(this.state, entityState);
|
|
691
|
+
}
|
|
692
|
+
if (this.entityInstance) {
|
|
693
|
+
const prototype = Object.getPrototypeOf(
|
|
694
|
+
this.entityInstance
|
|
695
|
+
);
|
|
696
|
+
Object.getOwnPropertyNames(prototype).forEach((key) => {
|
|
697
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
|
|
698
|
+
if (key !== "constructor" && descriptor && typeof descriptor.value === "function") {
|
|
699
|
+
this.entityInstance[key] = descriptor.value.bind(this.entityInstance);
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
if ("state" in this.entityInstance) {
|
|
703
|
+
Object.defineProperty(this.entityInstance, "state", {
|
|
704
|
+
get: () => controller.state,
|
|
705
|
+
configurable: true,
|
|
706
|
+
enumerable: true
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
componentDidMount() {
|
|
712
|
+
if (this.entityInstance && typeof this.entityInstance.componentDidMount === "function") {
|
|
713
|
+
this.entityInstance.componentDidMount.call(this.entityInstance);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
componentDidUpdate(prevProps, prevState) {
|
|
717
|
+
if (this.entityInstance && typeof this.entityInstance.componentDidUpdate === "function") {
|
|
718
|
+
this.entityInstance.componentDidUpdate.call(
|
|
719
|
+
this.entityInstance,
|
|
720
|
+
prevProps,
|
|
721
|
+
prevState
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
componentWillUnmount() {
|
|
726
|
+
if (this.entityInstance && typeof this.entityInstance.componentWillUnmount === "function") {
|
|
727
|
+
this.entityInstance.componentWillUnmount.call(this.entityInstance);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
render() {
|
|
731
|
+
if (!this.entityInstance) {
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
734
|
+
return this.entityInstance.render.call(this.entityInstance);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
const wrappedComponent = (0, import_mobx_react2.observer)(RouterWrapper);
|
|
738
|
+
const reactComponent = wrappedComponent;
|
|
739
|
+
routerRegistry.set(Entity.name, reactComponent);
|
|
740
|
+
routerReverseRegistry.set(reactComponent, Entity.name);
|
|
741
|
+
return Entity;
|
|
742
|
+
};
|
|
743
|
+
return decorator;
|
|
744
|
+
}
|
|
745
|
+
Router.$provider = (Entity) => {
|
|
746
|
+
const component = routerRegistry.get(Entity.name);
|
|
747
|
+
if (!component) {
|
|
748
|
+
throw new Error(
|
|
749
|
+
`Router ${Entity.name} not found. Make sure to apply @Router decorator first.`
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
return component;
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
// src/index.ts
|
|
756
|
+
function resetScope(_scope, _selector) {
|
|
757
|
+
DependencyManagement.getInstance().resetScope(_scope, _selector);
|
|
758
|
+
}
|
|
759
|
+
function resetClass(_className) {
|
|
760
|
+
DependencyManagement.getInstance().resetClass(_className);
|
|
761
|
+
}
|
|
762
|
+
function resetAll() {
|
|
763
|
+
DependencyManagement.getInstance().resetAll();
|
|
764
|
+
}
|
|
765
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
766
|
+
0 && (module.exports = {
|
|
767
|
+
Component,
|
|
768
|
+
Injectable,
|
|
769
|
+
Router,
|
|
770
|
+
resetAll,
|
|
771
|
+
resetClass,
|
|
772
|
+
resetScope
|
|
773
|
+
});
|
|
774
|
+
//# sourceMappingURL=index.js.map
|