@adaas/a-concept 0.1.44 → 0.1.45
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/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +51 -152
- package/dist/index.d.ts +51 -152
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/global/A-Context/A-Context.class.ts +0 -1
- package/src/global/A-Feature/A-Feature-Extend.decorator.ts +23 -4
- package/src/global/A-Fragment/A-Fragment.class.ts +4 -203
- package/src/global/A-Meta/A-Meta.class.ts +45 -2
- package/src/global/A-Scope/A-Scope.class.ts +48 -3
- package/tests/A-Container.test.ts +34 -1
- package/tests/A-Fragment.test.ts +0 -305
- package/tests/A-Scope.test.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaas/a-concept",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.45",
|
|
4
4
|
"description": "A-Concept is a framework to build new Applications within or outside the ADAAS ecosystem. This framework is designed to be modular structure regardless environment and program goal.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -35,7 +35,6 @@ import { A_TYPES__Component_Constructor } from "../A-Component/A-Component.types
|
|
|
35
35
|
import { A_FormatterHelper } from "@adaas/a-concept/helpers/A_Formatter.helper";
|
|
36
36
|
import { A_Fragment } from "../A-Fragment/A-Fragment.class";
|
|
37
37
|
import { A_TYPES__InjectableTargets } from "../A-Inject/A-Inject.types";
|
|
38
|
-
import { A_TYPES__ConceptAbstraction } from "../A-Concept/A-Concept.types";
|
|
39
38
|
import { A_TYPES__ConceptAbstractions } from "../A-Concept/A-Concept.constants";
|
|
40
39
|
import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
|
|
41
40
|
|
|
@@ -5,6 +5,9 @@ import { A_TypeGuards } from "@adaas/a-concept/helpers/A_TypeGuards.helper";
|
|
|
5
5
|
import { A_TYPES__ComponentMetaKey } from "../A-Component/A-Component.constants";
|
|
6
6
|
import { A_FeatureError } from "./A-Feature.error";
|
|
7
7
|
import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
|
|
8
|
+
import { A_TYPES__EntityMetaKey } from "../A-Entity/A-Entity.constants";
|
|
9
|
+
import { A_TYPES__ContainerMetaKey } from "../A-Container/A-Container.constants";
|
|
10
|
+
import { A_Container } from "../A-Container/A-Container.class";
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
|
|
@@ -81,8 +84,21 @@ export function A_Feature_Extend(
|
|
|
81
84
|
let include: Array<A_TYPES__FeatureExtendDecoratorScopeItem> = [];
|
|
82
85
|
let exclude: Array<A_TYPES__FeatureExtendDecoratorScopeItem> = [];
|
|
83
86
|
let throwOnError: boolean = true;
|
|
87
|
+
let metaKey;
|
|
84
88
|
|
|
85
89
|
|
|
90
|
+
switch (true) {
|
|
91
|
+
case A_TypeGuards.isEntityInstance(target):
|
|
92
|
+
metaKey = A_TYPES__EntityMetaKey.EXTENSIONS;
|
|
93
|
+
break;
|
|
94
|
+
case A_TypeGuards.isContainerInstance(target):
|
|
95
|
+
metaKey = A_TYPES__ContainerMetaKey.EXTENSIONS
|
|
96
|
+
break;
|
|
97
|
+
case A_TypeGuards.isComponentInstance(target):
|
|
98
|
+
metaKey = A_TYPES__ComponentMetaKey.EXTENSIONS
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
|
|
86
102
|
|
|
87
103
|
switch (true) {
|
|
88
104
|
case A_TypeGuards.isRegExp(param1):
|
|
@@ -130,17 +146,20 @@ export function A_Feature_Extend(
|
|
|
130
146
|
}
|
|
131
147
|
|
|
132
148
|
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
133
152
|
const existedDefinitions = A_Context
|
|
134
153
|
.meta(target)
|
|
135
|
-
.get(
|
|
154
|
+
.get(metaKey);
|
|
136
155
|
|
|
137
156
|
|
|
138
157
|
// Get the existed metadata or create a new one
|
|
139
158
|
const meta = A_Context
|
|
140
159
|
.meta(target)
|
|
141
160
|
|
|
142
|
-
const existedMeta = meta.get(
|
|
143
|
-
? new A_Meta().from(meta.get(
|
|
161
|
+
const existedMeta = meta.get(metaKey)
|
|
162
|
+
? new A_Meta().from(meta.get(metaKey)!)
|
|
144
163
|
: new A_Meta();
|
|
145
164
|
|
|
146
165
|
if (existedDefinitions
|
|
@@ -187,7 +206,7 @@ export function A_Feature_Extend(
|
|
|
187
206
|
// Update the metadata of the container with the new Feature definition
|
|
188
207
|
A_Context
|
|
189
208
|
.meta(target)
|
|
190
|
-
.set(
|
|
209
|
+
.set(metaKey, existedMeta);
|
|
191
210
|
};
|
|
192
211
|
}
|
|
193
212
|
|
|
@@ -24,7 +24,7 @@ import { A_TYPES__Fragment_Init, A_TYPES__Fragment_Serialized } from "./A-Fragme
|
|
|
24
24
|
* constructor() {
|
|
25
25
|
* super({ name: 'UserFragment' });
|
|
26
26
|
* }
|
|
27
|
-
* }
|
|
27
|
+
* }
|
|
28
28
|
*
|
|
29
29
|
* // Custom serialization
|
|
30
30
|
* class SessionFragment extends A_Fragment<
|
|
@@ -41,8 +41,7 @@ import { A_TYPES__Fragment_Init, A_TYPES__Fragment_Serialized } from "./A-Fragme
|
|
|
41
41
|
* ```
|
|
42
42
|
*/
|
|
43
43
|
export class A_Fragment<
|
|
44
|
-
|
|
45
|
-
_SerializedType extends A_TYPES__Fragment_Serialized = A_TYPES__Fragment_Serialized & _MetaItems
|
|
44
|
+
_SerializedType extends A_TYPES__Fragment_Serialized = A_TYPES__Fragment_Serialized
|
|
46
45
|
> {
|
|
47
46
|
/**
|
|
48
47
|
* The unique identifier/name for this fragment instance.
|
|
@@ -50,14 +49,6 @@ export class A_Fragment<
|
|
|
50
49
|
*/
|
|
51
50
|
protected _name: string;
|
|
52
51
|
|
|
53
|
-
/**
|
|
54
|
-
* Internal meta storage using A_Meta for type-safe key-value operations.
|
|
55
|
-
* This stores all the fragment's runtime data that can be accessed and modified
|
|
56
|
-
* throughout the execution pipeline.
|
|
57
|
-
*/
|
|
58
|
-
protected _meta: A_Meta<_MetaItems> = new A_Meta<_MetaItems>();
|
|
59
|
-
|
|
60
|
-
|
|
61
52
|
/**
|
|
62
53
|
* Creates a new A_Fragment instance.
|
|
63
54
|
*
|
|
@@ -69,7 +60,7 @@ export class A_Fragment<
|
|
|
69
60
|
* Key Benefits:
|
|
70
61
|
* - Centralized state management for related operations
|
|
71
62
|
* - Type-safe meta operations with full IntelliSense support
|
|
72
|
-
* - Serialization support for data persistence
|
|
63
|
+
* - Serialization support for data persistence
|
|
73
64
|
* - Singleton pattern ensures consistent state within scope
|
|
74
65
|
*
|
|
75
66
|
* @param params - Initialization parameters
|
|
@@ -96,191 +87,6 @@ export class A_Fragment<
|
|
|
96
87
|
return this._name;
|
|
97
88
|
}
|
|
98
89
|
|
|
99
|
-
/**
|
|
100
|
-
* Gets direct access to the underlying Meta object for advanced meta operations.
|
|
101
|
-
*
|
|
102
|
-
* Use this when you need to perform bulk operations or access Meta-specific methods.
|
|
103
|
-
* For simple get/set operations, prefer using the direct methods on the fragment.
|
|
104
|
-
*
|
|
105
|
-
* @returns The Meta instance containing the fragment's meta
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```typescript
|
|
109
|
-
* const fragment = new A_Fragment<{ users: string[], count: number }>();
|
|
110
|
-
*
|
|
111
|
-
* // Advanced operations using meta
|
|
112
|
-
* fragment.meta.setMultiple({
|
|
113
|
-
* users: ['alice', 'bob'],
|
|
114
|
-
* count: 2
|
|
115
|
-
* });
|
|
116
|
-
*
|
|
117
|
-
* // Get all keys
|
|
118
|
-
* const keys = fragment.meta.keys();
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
get meta(): A_Meta<_MetaItems> {
|
|
122
|
-
return this._meta;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Checks if a specific meta key exists in the fragment.
|
|
127
|
-
*
|
|
128
|
-
* @param param - The key to check for existence
|
|
129
|
-
* @returns True if the key exists, false otherwise
|
|
130
|
-
*
|
|
131
|
-
* @example
|
|
132
|
-
* ```typescript
|
|
133
|
-
* if (fragment.has('userId')) {
|
|
134
|
-
* console.log('User ID is set');
|
|
135
|
-
* }
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
has(param: keyof _MetaItems): boolean {
|
|
139
|
-
return this._meta.has(param);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Retrieves a value from the fragment's meta.
|
|
144
|
-
*
|
|
145
|
-
* @param param - The key to retrieve
|
|
146
|
-
* @returns The value associated with the key, or undefined if not found
|
|
147
|
-
*
|
|
148
|
-
* @example
|
|
149
|
-
* ```typescript
|
|
150
|
-
* const userId = fragment.get('userId');
|
|
151
|
-
* if (userId) {
|
|
152
|
-
* console.log(`Current user: ${userId}`);
|
|
153
|
-
* }
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
get(param: keyof _MetaItems): _MetaItems[typeof param] | undefined {
|
|
157
|
-
return this._meta.get(param);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Stores a value in the fragment's meta.
|
|
162
|
-
*
|
|
163
|
-
* @param param - The key to store the value under
|
|
164
|
-
* @param value - The value to store
|
|
165
|
-
*
|
|
166
|
-
* @example
|
|
167
|
-
* ```typescript
|
|
168
|
-
* fragment.set('userId', '12345');
|
|
169
|
-
* fragment.set('role', 'admin');
|
|
170
|
-
* ```
|
|
171
|
-
*/
|
|
172
|
-
set(param: keyof _MetaItems, value: _MetaItems[typeof param]): void {
|
|
173
|
-
this._meta.set(param, value);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Removes a specific key from the fragment's meta.
|
|
178
|
-
*
|
|
179
|
-
* @param param - The key to remove
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* ```typescript
|
|
183
|
-
* fragment.drop('temporaryData');
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
|
-
drop(param: keyof _MetaItems): void {
|
|
187
|
-
this._meta.delete(param);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Clears all data from the fragment's meta.
|
|
192
|
-
*
|
|
193
|
-
* Use with caution as this will remove all stored data in the fragment.
|
|
194
|
-
*
|
|
195
|
-
* @example
|
|
196
|
-
* ```typescript
|
|
197
|
-
* fragment.clear(); // All meta data is now gone
|
|
198
|
-
* ```
|
|
199
|
-
*/
|
|
200
|
-
clear(): void {
|
|
201
|
-
this._meta.clear();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Gets the number of items stored in the fragment's meta.
|
|
206
|
-
*
|
|
207
|
-
* @returns The count of stored meta items
|
|
208
|
-
*
|
|
209
|
-
* @example
|
|
210
|
-
* ```typescript
|
|
211
|
-
* console.log(`Fragment contains ${fragment.size()} items`);
|
|
212
|
-
* ```
|
|
213
|
-
*/
|
|
214
|
-
size(): number {
|
|
215
|
-
return this._meta.size();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Gets all keys currently stored in the fragment's meta.
|
|
220
|
-
*
|
|
221
|
-
* @returns Array of all meta keys
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* const keys = fragment.keys();
|
|
226
|
-
* console.log('Stored keys:', keys);
|
|
227
|
-
* ```
|
|
228
|
-
*/
|
|
229
|
-
keys(): (keyof _MetaItems)[] {
|
|
230
|
-
return this._meta.toArray().map(([key]) => key);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Sets multiple values at once in the fragment's meta.
|
|
235
|
-
*
|
|
236
|
-
* @param data - Object containing key-value pairs to set
|
|
237
|
-
*
|
|
238
|
-
* @example
|
|
239
|
-
* ```typescript
|
|
240
|
-
* fragment.setMultiple({
|
|
241
|
-
* userId: '12345',
|
|
242
|
-
* role: 'admin',
|
|
243
|
-
* lastLogin: new Date()
|
|
244
|
-
* });
|
|
245
|
-
* ```
|
|
246
|
-
*/
|
|
247
|
-
setMultiple(data: A_TYPES__DeepPartial<_MetaItems>): void {
|
|
248
|
-
Object.entries(data).forEach(([key, value]) => {
|
|
249
|
-
if (value !== undefined) {
|
|
250
|
-
this._meta.set(key as keyof _MetaItems, value);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Creates a shallow copy of the fragment with the same meta data.
|
|
257
|
-
*
|
|
258
|
-
* @param newName - Optional new name for the cloned fragment
|
|
259
|
-
* @returns A new fragment instance with copied meta
|
|
260
|
-
*
|
|
261
|
-
* @example
|
|
262
|
-
* ```typescript
|
|
263
|
-
* const original = new A_Fragment<{ data: string }>({ name: 'original' });
|
|
264
|
-
* original.set('data', 'test');
|
|
265
|
-
*
|
|
266
|
-
* const clone = original.clone('cloned');
|
|
267
|
-
* console.log(clone.get('data')); // 'test'
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
clone(newName?: string): A_Fragment<_MetaItems, _SerializedType> {
|
|
271
|
-
const cloned = new (this.constructor as any)({
|
|
272
|
-
name: newName || `${this._name}_copy`
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
// Copy all meta data
|
|
276
|
-
this._meta.toArray().forEach(([key, value]) => {
|
|
277
|
-
cloned.set(key, value);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
return cloned;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
90
|
/**
|
|
285
91
|
* Serializes the fragment to a JSON-compatible object.
|
|
286
92
|
*
|
|
@@ -305,13 +111,8 @@ export class A_Fragment<
|
|
|
305
111
|
toJSON(): _SerializedType {
|
|
306
112
|
const result = {
|
|
307
113
|
name: this.name,
|
|
308
|
-
|
|
309
|
-
...this.meta.toArray().reduce((acc, [key, value]) => {
|
|
310
|
-
acc[key] = value;
|
|
311
|
-
return acc;
|
|
312
|
-
}, {} as _MetaItems)
|
|
313
114
|
};
|
|
314
115
|
|
|
315
|
-
return result as
|
|
116
|
+
return result as _SerializedType;
|
|
316
117
|
}
|
|
317
118
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* [!] Meta can be different depending on the type of input data
|
|
5
5
|
*/
|
|
6
6
|
export class A_Meta<
|
|
7
|
-
_StorageItems extends Record<string, any> = any
|
|
8
|
-
|
|
7
|
+
_StorageItems extends Record<string, any> = any,
|
|
8
|
+
_SerializedType extends Record<string, any> = Record<string, any>
|
|
9
9
|
> implements Iterable<[keyof _StorageItems, _StorageItems[keyof _StorageItems]]> {
|
|
10
10
|
|
|
11
11
|
protected meta: Map<keyof _StorageItems, _StorageItems[keyof _StorageItems]> = new Map();
|
|
@@ -192,4 +192,47 @@ export class A_Meta<
|
|
|
192
192
|
toArray(): Array<[keyof _StorageItems, _StorageItems[keyof _StorageItems]]> {
|
|
193
193
|
return Array.from(this.meta.entries());
|
|
194
194
|
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
protected recursiveToJSON(value: any): any {
|
|
198
|
+
switch (true) {
|
|
199
|
+
case value instanceof A_Meta:
|
|
200
|
+
return value.toJSON();
|
|
201
|
+
|
|
202
|
+
case value instanceof Map:
|
|
203
|
+
const obj: Record<string, any> = {};
|
|
204
|
+
for (const [k, v] of value.entries()) {
|
|
205
|
+
obj[String(k)] = this.recursiveToJSON(v);
|
|
206
|
+
}
|
|
207
|
+
return obj;
|
|
208
|
+
|
|
209
|
+
case Array.isArray(value):
|
|
210
|
+
return value.map((item) => this.recursiveToJSON(item));
|
|
211
|
+
|
|
212
|
+
case !!value && typeof value === 'object':
|
|
213
|
+
const res: Record<string, any> = {};
|
|
214
|
+
for (const [k, v] of Object.entries(value)) {
|
|
215
|
+
res[k] = this.recursiveToJSON(v);
|
|
216
|
+
}
|
|
217
|
+
return res;
|
|
218
|
+
|
|
219
|
+
default:
|
|
220
|
+
return value;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Serializes the meta to a JSON object
|
|
226
|
+
* Uses internal storage to convert to JSON
|
|
227
|
+
*
|
|
228
|
+
* @returns
|
|
229
|
+
*/
|
|
230
|
+
toJSON(): _SerializedType {
|
|
231
|
+
const json: Record<string, any> = {};
|
|
232
|
+
|
|
233
|
+
for (const [key, value] of this.meta.entries()) {
|
|
234
|
+
json[String(key)] = this.recursiveToJSON(value);
|
|
235
|
+
}
|
|
236
|
+
return json as _SerializedType;
|
|
237
|
+
}
|
|
195
238
|
}
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
A_TYPES__A_InjectDecorator_EntityInjectionInstructions,
|
|
11
11
|
A_TYPES__A_InjectDecorator_EntityInjectionQuery,
|
|
12
12
|
A_TYPES__InjectableConstructors,
|
|
13
|
-
A_TYPES__InjectableTargets,
|
|
14
13
|
} from "@adaas/a-concept/global/A-Inject/A-Inject.types";
|
|
15
14
|
import { A_Fragment } from "../A-Fragment/A-Fragment.class";
|
|
16
15
|
import { A_Context } from "../A-Context/A-Context.class";
|
|
@@ -27,11 +26,13 @@ import { A_TYPES__Component_Constructor } from '../A-Component/A-Component.types
|
|
|
27
26
|
import { A_TYPES__Fragment_Constructor } from '../A-Fragment/A-Fragment.types';
|
|
28
27
|
import { A_TYPES__Error_Constructor } from '../A-Error/A_Error.types';
|
|
29
28
|
import { A_TYPES__ComponentMetaKey } from '../A-Component/A-Component.constants';
|
|
29
|
+
import { A_Meta } from '../A-Meta/A-Meta.class';
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
export class A_Scope<
|
|
35
|
+
_MetaItems extends Record<string, any> = any,
|
|
35
36
|
_ComponentType extends A_TYPES__Component_Constructor[] = A_TYPES__Component_Constructor[],
|
|
36
37
|
_ErrorType extends A_TYPES__Error_Constructor[] = A_TYPES__Error_Constructor[],
|
|
37
38
|
_EntityType extends A_TYPES__Entity_Constructor[] = A_TYPES__Entity_Constructor[],
|
|
@@ -46,6 +47,12 @@ export class A_Scope<
|
|
|
46
47
|
* Parent scope reference, used for inheritance of components, fragments, entities and commands
|
|
47
48
|
*/
|
|
48
49
|
protected _parent?: A_Scope;
|
|
50
|
+
/**
|
|
51
|
+
* Internal meta storage using A_Meta for type-safe key-value operations.
|
|
52
|
+
* This stores all the scope's runtime data that can be accessed and modified
|
|
53
|
+
* throughout the execution pipeline or within running containers.
|
|
54
|
+
*/
|
|
55
|
+
protected _meta: A_Meta<_MetaItems> = new A_Meta<_MetaItems>();
|
|
49
56
|
|
|
50
57
|
// ===========================================================================
|
|
51
58
|
// --------------------ALLowed Constructors--------------------------------
|
|
@@ -100,7 +107,10 @@ export class A_Scope<
|
|
|
100
107
|
* Returns the name of the scope
|
|
101
108
|
*/
|
|
102
109
|
get name() { return this._name }
|
|
103
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Returns the meta object of the scope
|
|
112
|
+
*/
|
|
113
|
+
get meta() { return this._meta }
|
|
104
114
|
/**
|
|
105
115
|
* Returns a list of Constructors for A-Components that are available in the scope
|
|
106
116
|
*/
|
|
@@ -300,6 +310,41 @@ export class A_Scope<
|
|
|
300
310
|
}
|
|
301
311
|
|
|
302
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Retrieves a value from the scope's meta.
|
|
315
|
+
*
|
|
316
|
+
* @param param - The key to retrieve
|
|
317
|
+
* @returns The value associated with the key, or undefined if not found
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```typescript
|
|
321
|
+
* const userId = scope.get('userId');
|
|
322
|
+
* if (userId) {
|
|
323
|
+
* console.log(`Current user: ${userId}`);
|
|
324
|
+
* }
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
get(param: keyof _MetaItems): _MetaItems[typeof param] | undefined {
|
|
328
|
+
return this._meta.get(param);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Stores a value in the scope's meta.
|
|
333
|
+
*
|
|
334
|
+
* @param param - The key to store the value under
|
|
335
|
+
* @param value - The value to store
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* scope.set('userId', '12345');
|
|
340
|
+
* scope.set('role', 'admin');
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
set(param: keyof _MetaItems, value: _MetaItems[typeof param]): void {
|
|
344
|
+
this._meta.set(param, value);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
|
|
303
348
|
/**
|
|
304
349
|
* Returns the issuer of the scope, useful for debugging and tracking purposes
|
|
305
350
|
*
|
|
@@ -312,7 +357,7 @@ export class A_Scope<
|
|
|
312
357
|
* @returns
|
|
313
358
|
*/
|
|
314
359
|
issuer<T extends A_TYPES__ScopeLinkedComponents>(): T | undefined {
|
|
315
|
-
|
|
360
|
+
return A_Context.issuer(this) as T;
|
|
316
361
|
}
|
|
317
362
|
|
|
318
363
|
|
|
@@ -1,15 +1,48 @@
|
|
|
1
1
|
import { A_Container } from '@adaas/a-concept/global/A-Container/A-Container.class';
|
|
2
2
|
import { A_Scope } from '@adaas/a-concept/global/A-Scope/A-Scope.class';
|
|
3
|
+
import { A_Concept, A_Feature } from '../src';
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
describe('A-Container tests', () => {
|
|
6
7
|
|
|
7
|
-
it('Should
|
|
8
|
+
it('Should allow to create a concept', async () => {
|
|
8
9
|
const container = new A_Container();
|
|
9
10
|
expect(container).toBeInstanceOf(A_Container);
|
|
10
11
|
expect(container.scope).toBeDefined();
|
|
11
12
|
expect(container.scope).toBeInstanceOf(A_Scope);
|
|
12
13
|
});
|
|
14
|
+
it('Should allow to define and extend features on container level', async () => {
|
|
15
|
+
const results: string[] = [];
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class customContainer extends A_Container {
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@A_Concept.Start()
|
|
22
|
+
async start() {
|
|
23
|
+
results.push('started');
|
|
24
|
+
|
|
25
|
+
await this.call('testFeature');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@A_Feature.Extend({
|
|
29
|
+
name: 'testFeature',
|
|
30
|
+
})
|
|
31
|
+
async extendFeature() {
|
|
32
|
+
results.push('extended');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
const myContainer = new customContainer();
|
|
38
|
+
const concept = new A_Concept({
|
|
39
|
+
containers: [myContainer]
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await concept.start();
|
|
43
|
+
|
|
44
|
+
expect(results).toEqual(['started', 'extended']);
|
|
45
|
+
});
|
|
13
46
|
|
|
14
47
|
|
|
15
48
|
});
|