@adaas/a-concept 0.3.1 → 0.3.3
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/dist/browser/index.d.mts +65 -6
- package/dist/browser/index.mjs +2 -2
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/index.cjs +100 -10
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.mts +65 -6
- package/dist/node/index.d.ts +65 -6
- package/dist/node/index.mjs +100 -11
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/env/env.base.ts +1 -1
- package/src/lib/A-Context/A-Context.class.ts +20 -17
- package/src/lib/A-Dependency/A-Dependency-Query.decorator.ts +90 -0
- package/src/lib/A-Dependency/A-Dependency.class.ts +11 -0
- package/src/lib/A-Dependency/A-Dependency.types.ts +12 -1
- package/src/lib/A-Dependency/index.ts +1 -0
- package/src/lib/A-Meta/A-Meta.class.ts +22 -26
- package/src/lib/A-Scope/A-Scope.class.ts +61 -6
- package/src/lib/A-Scope/A-Scope.types.ts +1 -1
- package/tests/A-Dependency.test.ts +67 -0
- package/tests/A-Entity.test.ts +101 -0
- package/tests/A-Meta.test.ts +44 -1
- package/tests/A-Scope.test.ts +17 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "A-Concept is a framework of the new generation that is tailored to use AI, enabling developers to create AI-powered applications with ease. It provides a structured approach to building, managing, and deploying AI-driven solutions.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": {
|
package/src/env/env.base.ts
CHANGED
|
@@ -31,7 +31,7 @@ export class A_CONCEPT_BASE_ENV {
|
|
|
31
31
|
* Environment of the application e.g. development, production, staging
|
|
32
32
|
*/
|
|
33
33
|
static get A_CONCEPT_ENVIRONMENT() {
|
|
34
|
-
return "
|
|
34
|
+
return "development";
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Runtime environment of the application e.g. browser, node
|
|
@@ -36,9 +36,9 @@ import {
|
|
|
36
36
|
} from "@adaas/a-concept/a-entity";
|
|
37
37
|
import { A_TYPES__A_StageStep } from "@adaas/a-concept/a-stage";
|
|
38
38
|
import { A_TYPES__ContextEnvironment } from "./A-Context.types";
|
|
39
|
-
import { A_TypeGuards} from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
40
|
-
import { A_FormatterHelper} from "@adaas/a-concept/helpers/A_Formatter.helper";
|
|
41
|
-
import { A_CommonHelper} from "@adaas/a-concept/helpers/A_Common.helper";
|
|
39
|
+
import { A_TypeGuards } from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
40
|
+
import { A_FormatterHelper } from "@adaas/a-concept/helpers/A_Formatter.helper";
|
|
41
|
+
import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
|
|
42
42
|
import { A_ContextError } from "./A-Context.error";
|
|
43
43
|
import {
|
|
44
44
|
A_Fragment,
|
|
@@ -364,11 +364,11 @@ export class A_Context {
|
|
|
364
364
|
*/
|
|
365
365
|
entity: A_TYPES__Entity_Constructor,
|
|
366
366
|
): T
|
|
367
|
-
static meta<T extends A_EntityMeta>(
|
|
367
|
+
static meta<T extends A_EntityMeta, E extends A_Entity>(
|
|
368
368
|
/**
|
|
369
369
|
* Get meta for the specific entity instance.
|
|
370
370
|
*/
|
|
371
|
-
entity:
|
|
371
|
+
entity: E,
|
|
372
372
|
): T
|
|
373
373
|
static meta<T extends A_ComponentMeta>(
|
|
374
374
|
/**
|
|
@@ -545,7 +545,7 @@ export class A_Context {
|
|
|
545
545
|
if (!inheritedMeta)
|
|
546
546
|
inheritedMeta = new metaType();
|
|
547
547
|
|
|
548
|
-
instance._metaStorage.set(property,
|
|
548
|
+
instance._metaStorage.set(property, inheritedMeta.clone());
|
|
549
549
|
}
|
|
550
550
|
|
|
551
551
|
// Return the meta for the property
|
|
@@ -684,17 +684,7 @@ export class A_Context {
|
|
|
684
684
|
throw new A_ContextError(A_ContextError.InvalidScopeParameterError, `Invalid parameter provided to get scope. Component of type ${name} is not allowed for scope allocation.`);
|
|
685
685
|
|
|
686
686
|
switch (true) {
|
|
687
|
-
case this.isAllowedForScopeAllocation(param1):
|
|
688
|
-
|
|
689
|
-
// Check if the parameter has a scope allocated
|
|
690
|
-
if (!instance._registry.has(param1))
|
|
691
|
-
throw new A_ContextError(
|
|
692
|
-
A_ContextError.ScopeNotFoundError,
|
|
693
|
-
`Invalid parameter provided to get scope. Component of type ${name} does not have a scope allocated. Make sure to allocate a scope using A_Context.allocate() method before trying to get the scope.`
|
|
694
|
-
);
|
|
695
687
|
|
|
696
|
-
// If the parameter is allowed for scope allocation, return the scope
|
|
697
|
-
return instance._registry.get(param1)!;
|
|
698
688
|
|
|
699
689
|
case this.isAllowedToBeRegistered(param1):
|
|
700
690
|
|
|
@@ -707,6 +697,18 @@ export class A_Context {
|
|
|
707
697
|
|
|
708
698
|
// If the parameter is allowed to be registered, return the scope from the storage
|
|
709
699
|
return instance._scopeStorage.get(param1)!;
|
|
700
|
+
|
|
701
|
+
case this.isAllowedForScopeAllocation(param1):
|
|
702
|
+
|
|
703
|
+
// Check if the parameter has a scope allocated
|
|
704
|
+
if (!instance._registry.has(param1))
|
|
705
|
+
throw new A_ContextError(
|
|
706
|
+
A_ContextError.ScopeNotFoundError,
|
|
707
|
+
`Invalid parameter provided to get scope. Component of type ${name} does not have a scope allocated. Make sure to allocate a scope using A_Context.allocate() method before trying to get the scope.`
|
|
708
|
+
);
|
|
709
|
+
|
|
710
|
+
// If the parameter is allowed for scope allocation, return the scope
|
|
711
|
+
return instance._registry.get(param1)!;
|
|
710
712
|
default:
|
|
711
713
|
throw new A_ContextError(A_ContextError.InvalidScopeParameterError, `Invalid parameter provided to get scope. Component of type ${name} is not allowed to be registered.`);
|
|
712
714
|
}
|
|
@@ -1076,7 +1078,8 @@ export class A_Context {
|
|
|
1076
1078
|
*/
|
|
1077
1079
|
static isAllowedForScopeAllocation(param: any): param is A_TYPES__ScopeLinkedComponents {
|
|
1078
1080
|
return A_TypeGuards.isContainerInstance(param)
|
|
1079
|
-
|| A_TypeGuards.isFeatureInstance(param)
|
|
1081
|
+
|| A_TypeGuards.isFeatureInstance(param)
|
|
1082
|
+
|| A_TypeGuards.isEntityInstance(param);
|
|
1080
1083
|
}
|
|
1081
1084
|
/**
|
|
1082
1085
|
* Type guard to check if the param is allowed to be registered in the context.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
|
|
2
|
+
import { A_Context } from "@adaas/a-concept/a-context";
|
|
3
|
+
import { A_Meta } from "@adaas/a-concept/a-meta";
|
|
4
|
+
import { A_TYPES__ComponentMetaKey } from "@adaas/a-concept/a-component";
|
|
5
|
+
import { A_TYPES__ContainerMetaKey } from "@adaas/a-concept/a-container";
|
|
6
|
+
import { A_TYPES__A_Dependency_EntityInjectionPagination, A_TYPES__A_Dependency_EntityInjectionQuery, A_TYPES__A_Dependency_EntityResolutionConfig, A_TYPES__A_Dependency_QueryDecoratorReturn } from "./A-Dependency.types";
|
|
7
|
+
import { A_DependencyError } from "./A-Dependency.error";
|
|
8
|
+
import type { A_Entity } from "@adaas/a-concept/a-entity";
|
|
9
|
+
import { A_TYPES__EntityMetaKey } from "@adaas/a-concept/a-entity";
|
|
10
|
+
import {
|
|
11
|
+
A_TYPES__A_InjectDecorator_Meta,
|
|
12
|
+
A_TYPES__InjectableTargets
|
|
13
|
+
} from "@adaas/a-concept/a-inject";
|
|
14
|
+
import { A_TypeGuards } from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
15
|
+
import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Query Decorator is only applicable for Entities since Scope instance may have multiple entities but only one component or container, so there is no need for such complex resolution strategies for them, but for entities it is a common case to have multiple instances and need to specify which one(s) to inject.
|
|
19
|
+
*
|
|
20
|
+
*
|
|
21
|
+
* @param query
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
export function A_Dependency_Query<T extends A_Entity = A_Entity>(
|
|
25
|
+
query: Partial<A_TYPES__A_Dependency_EntityInjectionQuery<T>>,
|
|
26
|
+
pagination?: Partial<A_TYPES__A_Dependency_EntityInjectionPagination>
|
|
27
|
+
): A_TYPES__A_Dependency_QueryDecoratorReturn {
|
|
28
|
+
|
|
29
|
+
return function (
|
|
30
|
+
target: A_TYPES__InjectableTargets,
|
|
31
|
+
methodName: string | symbol | undefined,
|
|
32
|
+
parameterIndex: number
|
|
33
|
+
) {
|
|
34
|
+
// for Error handling purposes
|
|
35
|
+
const componentName = A_CommonHelper.getComponentName(target)
|
|
36
|
+
|
|
37
|
+
if (!A_TypeGuards.isTargetAvailableForInjection(target)) {
|
|
38
|
+
throw new A_DependencyError(
|
|
39
|
+
A_DependencyError.InvalidDependencyTarget,
|
|
40
|
+
`A-All cannot be used on the target of type ${typeof target} (${componentName})`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// determine the method name or 'constructor' for constructor injections
|
|
45
|
+
const method = methodName ? String(methodName) : 'constructor';
|
|
46
|
+
let metaKey;
|
|
47
|
+
|
|
48
|
+
switch (true) {
|
|
49
|
+
case A_TypeGuards.isComponentConstructor(target) || A_TypeGuards.isComponentInstance(target):
|
|
50
|
+
metaKey = A_TYPES__ComponentMetaKey.INJECTIONS;
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case A_TypeGuards.isContainerInstance(target):
|
|
54
|
+
metaKey = A_TYPES__ContainerMetaKey.INJECTIONS;
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
case A_TypeGuards.isEntityInstance(target):
|
|
58
|
+
metaKey = A_TYPES__EntityMetaKey.INJECTIONS;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// get existing meta or create a new one
|
|
63
|
+
const existedMeta = A_Context.meta(target).get(metaKey) || new A_Meta();
|
|
64
|
+
// get existing injections for the method or create a new array
|
|
65
|
+
const paramsArray: A_TYPES__A_InjectDecorator_Meta = existedMeta.get(method) || [];
|
|
66
|
+
|
|
67
|
+
// set the parameter injection info
|
|
68
|
+
paramsArray[parameterIndex].resolutionStrategy = {
|
|
69
|
+
query: {
|
|
70
|
+
...paramsArray[parameterIndex].resolutionStrategy.query,
|
|
71
|
+
...query
|
|
72
|
+
},
|
|
73
|
+
pagination: {
|
|
74
|
+
...paramsArray[parameterIndex].resolutionStrategy.pagination,
|
|
75
|
+
...pagination
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// save back the updated injections array
|
|
80
|
+
existedMeta.set(method, paramsArray);
|
|
81
|
+
|
|
82
|
+
// save back the updated meta info
|
|
83
|
+
A_Context
|
|
84
|
+
.meta(target)
|
|
85
|
+
.set(
|
|
86
|
+
metaKey,
|
|
87
|
+
existedMeta
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "./A-Dependency.types";
|
|
15
15
|
import { A_TYPES__Ctor } from "@adaas/a-concept/types";
|
|
16
16
|
import { A_Dependency_All } from "./A-Dependency-All.decorator";
|
|
17
|
+
import { A_Dependency_Query } from "./A-Dependency-Query.decorator";
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
export class A_Dependency<
|
|
@@ -74,6 +75,16 @@ export class A_Dependency<
|
|
|
74
75
|
return A_Dependency_All;
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Allows to indicate that the dependency should be resolved by specific query parameters
|
|
80
|
+
* e.g. by ASEID, name, type, custom properties, etc.
|
|
81
|
+
*
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
84
|
+
static get Query(): typeof A_Dependency_Query {
|
|
85
|
+
return A_Dependency_Query;
|
|
86
|
+
}
|
|
87
|
+
|
|
77
88
|
protected _name: string;
|
|
78
89
|
protected _target?: A_TYPES__Ctor<T>;
|
|
79
90
|
protected _resolutionStrategy!: A_TYPES__A_DependencyResolutionStrategy;
|
|
@@ -4,7 +4,7 @@ import { A_TYPES__Ctor } from "@adaas/a-concept/types";
|
|
|
4
4
|
import { A_Caller } from "@adaas/a-concept/a-caller";
|
|
5
5
|
import { A_Component } from "@adaas/a-concept/a-component";
|
|
6
6
|
import { A_Container } from "@adaas/a-concept/a-container";
|
|
7
|
-
import { A_Entity } from "@adaas/a-concept/a-entity"
|
|
7
|
+
import { A_Entity, A_TYPES__Entity_Constructor } from "@adaas/a-concept/a-entity"
|
|
8
8
|
import { A_Error } from "@adaas/a-concept/a-error";
|
|
9
9
|
import { A_Feature } from "@adaas/a-concept/a-feature";
|
|
10
10
|
import { A_Fragment } from "@adaas/a-concept/a-fragment";
|
|
@@ -163,3 +163,14 @@ export type A_TYPES__A_Dependency_AllDecoratorReturn<T = any> = (
|
|
|
163
163
|
propertyKey: string | symbol | undefined,
|
|
164
164
|
parameterIndex: number
|
|
165
165
|
) => void
|
|
166
|
+
|
|
167
|
+
export type A_TYPES__A_Dependency_QueryTarget<T extends A_Entity = A_Entity> = T
|
|
168
|
+
| A_TYPES__Entity_Constructor<T>
|
|
169
|
+
/**
|
|
170
|
+
* A-Dependency Query decorator return type
|
|
171
|
+
*/
|
|
172
|
+
export type A_TYPES__A_Dependency_QueryDecoratorReturn<T = any> = (
|
|
173
|
+
target: T,
|
|
174
|
+
propertyKey: string | symbol | undefined,
|
|
175
|
+
parameterIndex: number
|
|
176
|
+
) => void
|
|
@@ -13,5 +13,6 @@ export { A_Dependency_Flat } from './A-Dependency-Flat.decorator';
|
|
|
13
13
|
export { A_Dependency_Load } from './A-Dependency-Load.decorator';
|
|
14
14
|
export { A_Dependency_Parent } from './A-Dependency-Parent.decorator';
|
|
15
15
|
export { A_Dependency_Require } from './A-Dependency-Require.decorator';
|
|
16
|
+
export { A_Dependency_Query } from './A-Dependency-Query.decorator';
|
|
16
17
|
|
|
17
18
|
|
|
@@ -56,8 +56,17 @@ export class A_Meta<
|
|
|
56
56
|
|
|
57
57
|
return this;
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Allows to create a copy of the meta object with the same values, this is needed to ensure that when we inherit meta from the parent component, we create a copy of it, not a reference to the same object. This allows us to modify the meta of the child component without affecting the meta of the parent component.
|
|
61
|
+
*
|
|
62
|
+
* @returns
|
|
63
|
+
*/
|
|
64
|
+
clone(): A_Meta<_StorageItems> {
|
|
65
|
+
const ctor = this.constructor as new () => this;
|
|
66
|
+
const copy = new ctor();
|
|
67
|
+
copy.meta = new Map(this.meta);
|
|
68
|
+
return copy;
|
|
69
|
+
}
|
|
61
70
|
/**
|
|
62
71
|
* Method to set values in the map
|
|
63
72
|
*
|
|
@@ -83,9 +92,6 @@ export class A_Meta<
|
|
|
83
92
|
this.meta.set(key, value);
|
|
84
93
|
|
|
85
94
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
95
|
/**
|
|
90
96
|
* Method to get values from the map
|
|
91
97
|
*
|
|
@@ -95,8 +101,6 @@ export class A_Meta<
|
|
|
95
101
|
get<K extends keyof _StorageItems>(key: K): _StorageItems[K] | undefined {
|
|
96
102
|
return this.meta.get(key) as _StorageItems[K];
|
|
97
103
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
104
|
/**
|
|
101
105
|
* Method to delete values from the map
|
|
102
106
|
*
|
|
@@ -106,8 +110,6 @@ export class A_Meta<
|
|
|
106
110
|
delete(key: keyof _StorageItems): boolean {
|
|
107
111
|
return this.meta.delete(key);
|
|
108
112
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
113
|
/**
|
|
112
114
|
* Method to get the size of the map
|
|
113
115
|
*
|
|
@@ -116,8 +118,6 @@ export class A_Meta<
|
|
|
116
118
|
size(): number {
|
|
117
119
|
return this.meta.size;
|
|
118
120
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
121
|
/**
|
|
122
122
|
* This method is needed to convert the key to a regular expression and cover cases like:
|
|
123
123
|
*
|
|
@@ -135,8 +135,6 @@ export class A_Meta<
|
|
|
135
135
|
? key
|
|
136
136
|
: new RegExp(key);
|
|
137
137
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
138
|
/**
|
|
141
139
|
* Method to find values in the map by name.
|
|
142
140
|
*
|
|
@@ -154,8 +152,6 @@ export class A_Meta<
|
|
|
154
152
|
}
|
|
155
153
|
return results;
|
|
156
154
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
155
|
/**
|
|
160
156
|
* Method to find values in the map by regular expression
|
|
161
157
|
*
|
|
@@ -173,8 +169,6 @@ export class A_Meta<
|
|
|
173
169
|
}
|
|
174
170
|
return results;
|
|
175
171
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
172
|
/**
|
|
179
173
|
* Method to check if the map has a specific key
|
|
180
174
|
*
|
|
@@ -184,8 +178,6 @@ export class A_Meta<
|
|
|
184
178
|
has(key: keyof _StorageItems): boolean {
|
|
185
179
|
return this.meta.has(key);
|
|
186
180
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
181
|
/**
|
|
190
182
|
* Method to get the size of the map
|
|
191
183
|
*
|
|
@@ -194,21 +186,26 @@ export class A_Meta<
|
|
|
194
186
|
entries(): IterableIterator<[keyof _StorageItems, _StorageItems[keyof _StorageItems]]> {
|
|
195
187
|
return this.meta.entries();
|
|
196
188
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
189
|
/**
|
|
200
190
|
* Method to clear the map
|
|
201
191
|
*/
|
|
202
192
|
clear(): void {
|
|
203
193
|
this.meta.clear();
|
|
204
194
|
}
|
|
205
|
-
|
|
206
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Method to convert the meta to an array of key-value pairs
|
|
197
|
+
*
|
|
198
|
+
* @returns
|
|
199
|
+
*/
|
|
207
200
|
toArray(): Array<[keyof _StorageItems, _StorageItems[keyof _StorageItems]]> {
|
|
208
201
|
return Array.from(this.meta.entries());
|
|
209
202
|
}
|
|
210
|
-
|
|
211
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Helper method to recursively convert the meta object to a JSON-compatible format. It handles nested A_Meta instances, Maps, Arrays, and plain objects.
|
|
205
|
+
*
|
|
206
|
+
* @param value
|
|
207
|
+
* @returns
|
|
208
|
+
*/
|
|
212
209
|
protected recursiveToJSON(value: any): any {
|
|
213
210
|
switch (true) {
|
|
214
211
|
case value instanceof A_Meta:
|
|
@@ -235,7 +232,6 @@ export class A_Meta<
|
|
|
235
232
|
return value;
|
|
236
233
|
}
|
|
237
234
|
}
|
|
238
|
-
|
|
239
235
|
/**
|
|
240
236
|
* Serializes the meta to a JSON object
|
|
241
237
|
* Uses internal storage to convert to JSON
|
|
@@ -19,9 +19,9 @@ import {
|
|
|
19
19
|
A_Entity,
|
|
20
20
|
A_TYPES__Entity_Constructor
|
|
21
21
|
} from "@adaas/a-concept/a-entity";
|
|
22
|
-
import { A_TypeGuards} from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
23
|
-
import { A_FormatterHelper} from "@adaas/a-concept/helpers/A_Formatter.helper";
|
|
24
|
-
import { A_CommonHelper} from "@adaas/a-concept/helpers/A_Common.helper";
|
|
22
|
+
import { A_TypeGuards } from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
23
|
+
import { A_FormatterHelper } from "@adaas/a-concept/helpers/A_Formatter.helper";
|
|
24
|
+
import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
|
|
25
25
|
import {
|
|
26
26
|
A_Error,
|
|
27
27
|
A_TYPES__Error_Constructor
|
|
@@ -179,8 +179,10 @@ export class A_Scope<
|
|
|
179
179
|
get parent(): A_Scope | undefined {
|
|
180
180
|
return this._parent;
|
|
181
181
|
}
|
|
182
|
+
|
|
182
183
|
/**
|
|
183
|
-
* A_Scope
|
|
184
|
+
* A_Scope is a unique A-Concept Structure that allows to operate with A-Concept Primitives and Models in a specific context and with specific rules.
|
|
185
|
+
* It refers to the visibility and accessibility of :
|
|
184
186
|
* - variables,
|
|
185
187
|
* - Components,
|
|
186
188
|
* - Context Fragments
|
|
@@ -837,8 +839,61 @@ export class A_Scope<
|
|
|
837
839
|
*/
|
|
838
840
|
name: string
|
|
839
841
|
): A_TYPES__Fragment_Constructor<T>
|
|
840
|
-
resolveConstructor<T extends
|
|
841
|
-
|
|
842
|
+
resolveConstructor<T extends A_Component>(
|
|
843
|
+
/**
|
|
844
|
+
* Provide the component constructor or its name to retrieve its constructor
|
|
845
|
+
*/
|
|
846
|
+
component: A_TYPES__Ctor<T>
|
|
847
|
+
): A_TYPES__Component_Constructor<T> | undefined
|
|
848
|
+
resolveConstructor<T extends A_Entity>(
|
|
849
|
+
/**
|
|
850
|
+
* Provide the entity constructor or its name to retrieve its constructor
|
|
851
|
+
*/
|
|
852
|
+
entity: A_TYPES__Ctor<T>
|
|
853
|
+
): A_TYPES__Entity_Constructor<T> | undefined
|
|
854
|
+
resolveConstructor<T extends A_Fragment>(
|
|
855
|
+
/**
|
|
856
|
+
* Provide the fragment constructor or its name to retrieve its constructor
|
|
857
|
+
*/
|
|
858
|
+
fragment: A_TYPES__Ctor<T>
|
|
859
|
+
): A_TYPES__Fragment_Constructor<T> | undefined
|
|
860
|
+
resolveConstructor<T extends A_Error>(
|
|
861
|
+
/**
|
|
862
|
+
* Provide the error constructor or its name to retrieve its constructor
|
|
863
|
+
*/
|
|
864
|
+
error: A_TYPES__Ctor<T>
|
|
865
|
+
): A_TYPES__Error_Constructor<T> | undefined
|
|
866
|
+
resolveConstructor<T extends A_TYPES__A_DependencyInjectable>(
|
|
867
|
+
name: string | A_TYPES__Ctor<T>
|
|
868
|
+
): A_TYPES__Entity_Constructor<T> | A_TYPES__Component_Constructor<T> | A_TYPES__Fragment_Constructor<T> | undefined
|
|
869
|
+
resolveConstructor<T extends A_TYPES__A_DependencyInjectable>(
|
|
870
|
+
name: string | A_TYPES__Ctor<T>
|
|
871
|
+
): A_TYPES__Entity_Constructor<T> | A_TYPES__Component_Constructor<T> | A_TYPES__Fragment_Constructor<T> | undefined {
|
|
872
|
+
// If it's a constructor, find any extension from the allowed constructors and return it
|
|
873
|
+
switch (true) {
|
|
874
|
+
case A_TypeGuards.isComponentConstructor(name):
|
|
875
|
+
return Array.from(this.allowedComponents)
|
|
876
|
+
.find((c) => A_CommonHelper.isInheritedFrom(c, name)) as A_TYPES__Component_Constructor<T> | undefined;
|
|
877
|
+
|
|
878
|
+
case A_TypeGuards.isEntityConstructor(name):
|
|
879
|
+
return Array.from(this.allowedEntities)
|
|
880
|
+
.find((e) => A_CommonHelper.isInheritedFrom(e, name)) as A_TYPES__Entity_Constructor<T> | undefined;
|
|
881
|
+
|
|
882
|
+
case A_TypeGuards.isFragmentConstructor(name):
|
|
883
|
+
return Array.from(this.allowedFragments)
|
|
884
|
+
.find((f) => A_CommonHelper.isInheritedFrom(f, name)) as A_TYPES__Fragment_Constructor<T> | undefined;
|
|
885
|
+
|
|
886
|
+
case A_TypeGuards.isErrorConstructor(name):
|
|
887
|
+
return Array.from(this.allowedErrors)
|
|
888
|
+
.find((e) => A_CommonHelper.isInheritedFrom(e, name)) as A_TYPES__Error_Constructor<T> | undefined;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
if(!A_TypeGuards.isString(name))
|
|
892
|
+
throw new A_ScopeError(
|
|
893
|
+
A_ScopeError.ResolutionError,
|
|
894
|
+
`Invalid constructor name provided: ${name}`
|
|
895
|
+
);
|
|
896
|
+
|
|
842
897
|
// 1) Check components
|
|
843
898
|
const component = Array.from(this.allowedComponents).find(
|
|
844
899
|
c => c.name === name
|
|
@@ -89,7 +89,7 @@ export type A_TYPES__ScopeLinkedConstructors = A_TYPES__Container_Constructor |
|
|
|
89
89
|
/**
|
|
90
90
|
* A list of components that can have a scope associated with them
|
|
91
91
|
*/
|
|
92
|
-
export type A_TYPES__ScopeLinkedComponents = A_Container | A_Feature
|
|
92
|
+
export type A_TYPES__ScopeLinkedComponents = A_Container | A_Feature | A_Entity
|
|
93
93
|
/**
|
|
94
94
|
* A list of components that are dependent on a scope and do not have their own scope
|
|
95
95
|
*/
|
|
@@ -455,4 +455,71 @@ describe('A-Dependency tests', () => {
|
|
|
455
455
|
|
|
456
456
|
});
|
|
457
457
|
|
|
458
|
+
it('Should be possible to use query decorator for A_Entities in scope', async () => {
|
|
459
|
+
|
|
460
|
+
class MyEntity_A extends A_Entity<{ name: string, group: string }> {
|
|
461
|
+
name!: string;
|
|
462
|
+
group!: string;
|
|
463
|
+
|
|
464
|
+
fromNew(newEntity: { name: string; group: string }): void {
|
|
465
|
+
super.fromNew(newEntity);
|
|
466
|
+
this.name = newEntity.name;
|
|
467
|
+
this.group = newEntity.group;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
class MyComponent extends A_Component {
|
|
472
|
+
@A_Feature.Extend()
|
|
473
|
+
async simpleQuery(
|
|
474
|
+
@A_Dependency.Query<MyEntity_A>({ name: 'Entity 1' })
|
|
475
|
+
@A_Inject(MyEntity_A) entity: MyEntity_A,
|
|
476
|
+
) {
|
|
477
|
+
expect(entity.name).toBe('Entity 1');
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
@A_Feature.Extend()
|
|
481
|
+
async andQuery(
|
|
482
|
+
@A_Dependency.Query<MyEntity_A>({ name: 'Entity 1', group: 'Group 1' })
|
|
483
|
+
@A_Inject(MyEntity_A) entity: MyEntity_A,
|
|
484
|
+
) {
|
|
485
|
+
expect(entity.name).toBe('Entity 1');
|
|
486
|
+
expect(entity.group).toBe('Group 1');
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
@A_Feature.Extend()
|
|
490
|
+
async paginationQuery(
|
|
491
|
+
@A_Dependency.Query<MyEntity_A>({ name: 'Entity 1' }, { count: 2 })
|
|
492
|
+
@A_Inject(MyEntity_A) entities: MyEntity_A[],
|
|
493
|
+
) {
|
|
494
|
+
|
|
495
|
+
expect(entities.length).toBe(2);
|
|
496
|
+
expect(entities[0].name).toBe('Entity 1');
|
|
497
|
+
expect(entities[0].group).toBe('Group 1');
|
|
498
|
+
expect(entities[1].name).toBe('Entity 1');
|
|
499
|
+
expect(entities[1].group).toBe('Group 2');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const scope = new A_Scope({
|
|
504
|
+
name: 'Test Scope',
|
|
505
|
+
components: [MyComponent],
|
|
506
|
+
entities: [
|
|
507
|
+
new MyEntity_A({ name: 'Entity 1', group: 'Group 1' }),
|
|
508
|
+
new MyEntity_A({ name: 'Entity 2', group: 'Group 1' }),
|
|
509
|
+
new MyEntity_A({ name: 'Entity 1', group: 'Group 2' }),
|
|
510
|
+
new MyEntity_A({ name: 'Entity 2', group: 'Group 2' }),
|
|
511
|
+
new MyEntity_A({ name: 'Entity 3', group: 'Group 2' }),
|
|
512
|
+
new MyEntity_A({ name: 'Entity 1', group: 'Group 3' }),
|
|
513
|
+
new MyEntity_A({ name: 'Entity 2', group: 'Group 3' }),
|
|
514
|
+
]
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
const componentInstance = scope.resolve(MyComponent);
|
|
518
|
+
|
|
519
|
+
await componentInstance?.call('simpleQuery');
|
|
520
|
+
await componentInstance?.call('andQuery');
|
|
521
|
+
await componentInstance?.call('paginationQuery');
|
|
522
|
+
|
|
523
|
+
});
|
|
524
|
+
|
|
458
525
|
});
|
package/tests/A-Entity.test.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "@adaas/a-concept/a-entity";
|
|
7
7
|
import { A_Feature } from "@adaas/a-concept/a-feature";
|
|
8
8
|
import { ASEID } from '@adaas/a-concept/aseid';
|
|
9
|
+
import { A_Scope } from "@adaas/a-concept/a-scope";
|
|
9
10
|
|
|
10
11
|
jest.retryTimes(0);
|
|
11
12
|
|
|
@@ -21,6 +22,106 @@ describe('A-Entity tests', () => {
|
|
|
21
22
|
expect(entity.aseid.concept).toBe('a-concept');
|
|
22
23
|
|
|
23
24
|
});
|
|
25
|
+
it('Should handle proper types declaration', async () => {
|
|
26
|
+
type MyInitType = {
|
|
27
|
+
name: string;
|
|
28
|
+
customId: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type mySerializedType = {
|
|
32
|
+
name: string;
|
|
33
|
+
serializedFlag: boolean;
|
|
34
|
+
customId: number;
|
|
35
|
+
} & A_TYPES__Entity_Serialized;
|
|
36
|
+
|
|
37
|
+
class MyEntity extends A_Entity<MyInitType, mySerializedType> {
|
|
38
|
+
public name!: string;
|
|
39
|
+
public customId!: number;
|
|
40
|
+
|
|
41
|
+
fromNew(newEntity: MyInitType): void {
|
|
42
|
+
super.fromNew(newEntity);
|
|
43
|
+
this.name = newEntity.name;
|
|
44
|
+
this.customId = newEntity.customId;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fromJSON(serialized: mySerializedType): void {
|
|
48
|
+
this.aseid = new ASEID(serialized.aseid);
|
|
49
|
+
this.name = serialized.name;
|
|
50
|
+
this.customId = serialized.customId;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
toJSON(): mySerializedType {
|
|
56
|
+
return {
|
|
57
|
+
...super.toJSON(),
|
|
58
|
+
name: this.name,
|
|
59
|
+
customId: this.customId,
|
|
60
|
+
serializedFlag: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
const entityInstance = new MyEntity({
|
|
67
|
+
name: 'Test Entity',
|
|
68
|
+
customId: 42,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
expect(entityInstance.name).toBe('Test Entity');
|
|
72
|
+
expect(entityInstance.customId).toBe(42);
|
|
73
|
+
|
|
74
|
+
const serialized = entityInstance.toJSON();
|
|
75
|
+
expect(serialized.name).toBe('Test Entity');
|
|
76
|
+
expect(serialized.customId).toBe(42);
|
|
77
|
+
expect(serialized.serializedFlag).toBe(true);
|
|
78
|
+
|
|
79
|
+
const deserializedEntity = new MyEntity(serialized);
|
|
80
|
+
expect(deserializedEntity.name).toBe('Test Entity');
|
|
81
|
+
expect(deserializedEntity.customId).toBe(42);
|
|
82
|
+
expect(deserializedEntity.aseid.toString()).toBe(entityInstance.aseid.toString());
|
|
83
|
+
});
|
|
84
|
+
it('Should be possible to allocate a scope for entity', async () => {
|
|
85
|
+
|
|
86
|
+
let resultScope: A_Scope | undefined = undefined;
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class MyEntity extends A_Entity {
|
|
90
|
+
|
|
91
|
+
scope!: A_Scope;
|
|
92
|
+
|
|
93
|
+
fromNew(newEntity: any): void {
|
|
94
|
+
super.fromNew(newEntity);
|
|
95
|
+
|
|
96
|
+
resultScope = new A_Scope({ name: 'entity-scope' });
|
|
97
|
+
|
|
98
|
+
this.scope = A_Context.allocate(this, resultScope);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fromUndefined(): void {
|
|
102
|
+
super.fromUndefined();
|
|
103
|
+
|
|
104
|
+
resultScope = new A_Scope({ name: 'entity-scope' });
|
|
105
|
+
|
|
106
|
+
this.scope = A_Context.allocate(this, resultScope);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
const entityInstance = new MyEntity();
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
const ParentScope = new A_Scope({
|
|
116
|
+
name: 'parent-scope',
|
|
117
|
+
entities: [entityInstance]
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expect(resultScope).toBeInstanceOf(A_Scope);
|
|
121
|
+
expect(entityInstance.scope).toBe(resultScope);
|
|
122
|
+
expect(resultScope!.issuer()).toBe(entityInstance);
|
|
123
|
+
expect(A_Context.scope(entityInstance)).toBe(ParentScope);
|
|
124
|
+
});
|
|
24
125
|
it('Should Allow to create an entity with overridden ASEID Scope or Concept', async () => {
|
|
25
126
|
class MyEntity extends A_Entity {
|
|
26
127
|
static get entity(): string {
|