@adaas/a-concept 0.3.2 → 0.3.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/a-concept",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
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": {
@@ -65,7 +65,7 @@ export function A_Abstraction_Extend(
65
65
  }
66
66
 
67
67
  let metaKey;
68
- const meta: A_ContainerMeta | A_ComponentMeta = A_Context.meta(target);
68
+ const meta: A_Meta = A_Context.meta(target);
69
69
 
70
70
  switch (true) {
71
71
  case A_TypeGuards.isContainerConstructor(target) || A_TypeGuards.isContainerInstance(target):
@@ -13,7 +13,7 @@ import { A_TYPES__FeatureDefineDecoratorMeta } from "@adaas/a-concept/a-feature"
13
13
 
14
14
 
15
15
 
16
- export class A_ContainerMeta extends A_Meta<A_TYPES__ContainerMeta> {
16
+ export class A_ContainerMeta<T extends A_TYPES__ContainerMeta = A_TYPES__ContainerMeta> extends A_Meta<T> {
17
17
 
18
18
 
19
19
 
@@ -8,6 +8,7 @@ import {
8
8
  } from "@adaas/a-concept/a-scope";
9
9
  import {
10
10
  A_Meta,
11
+ A_TYPES__Meta_Constructor,
11
12
  A_TYPES__MetaLinkedComponentConstructors,
12
13
  A_TYPES__MetaLinkedComponents
13
14
  } from "@adaas/a-concept/a-meta";
@@ -364,11 +365,11 @@ export class A_Context {
364
365
  */
365
366
  entity: A_TYPES__Entity_Constructor,
366
367
  ): T
367
- static meta<T extends A_EntityMeta>(
368
+ static meta<T extends A_EntityMeta, E extends A_Entity>(
368
369
  /**
369
370
  * Get meta for the specific entity instance.
370
371
  */
371
- entity: A_Entity,
372
+ entity: E,
372
373
  ): T
373
374
  static meta<T extends A_ComponentMeta>(
374
375
  /**
@@ -376,7 +377,7 @@ export class A_Context {
376
377
  */
377
378
  component: A_TYPES__Component_Constructor,
378
379
  ): T
379
- static meta<T extends A_ComponentMeta, S extends A_Component>(
380
+ static meta<T extends A_ComponentMeta<any>, S extends A_Component>(
380
381
  /**
381
382
  * Get meta for the specific component instance.
382
383
  */
@@ -442,7 +443,7 @@ export class A_Context {
442
443
  ) throw new A_ContextError(A_ContextError.InvalidMetaParameterError, `Invalid parameter provided to get meta. Component of type ${componentName} is not allowed for meta storage. Only A_Container, A_Component and A_Entity are allowed.`);
443
444
 
444
445
  let property: A_TYPES__MetaLinkedComponentConstructors;
445
- let metaType: typeof A_Meta<T> | typeof A_ContainerMeta | typeof A_ComponentMeta | typeof A_EntityMeta
446
+ let metaType: A_TYPES__Meta_Constructor<A_Meta<any>>
446
447
 
447
448
  switch (true) {
448
449
  // 1) If param1 is instance of A_Container
@@ -545,7 +546,7 @@ export class A_Context {
545
546
  if (!inheritedMeta)
546
547
  inheritedMeta = new metaType();
547
548
 
548
- instance._metaStorage.set(property, new metaType().from(inheritedMeta as any));
549
+ instance._metaStorage.set(property, inheritedMeta.clone());
549
550
  }
550
551
 
551
552
  // Return the meta for the property
@@ -5,14 +5,15 @@ import {
5
5
  A_TYPES__IEntity,
6
6
  } from "./A-Entity.types";
7
7
  import { A_Scope } from "@adaas/a-concept/a-scope";
8
- import { A_FormatterHelper} from "@adaas/a-concept/helpers/A_Formatter.helper";
9
- import { A_IdentityHelper} from "@adaas/a-concept/helpers/A_Identity.helper";
8
+ import { A_FormatterHelper } from "@adaas/a-concept/helpers/A_Formatter.helper";
9
+ import { A_IdentityHelper } from "@adaas/a-concept/helpers/A_Identity.helper";
10
10
  import {
11
11
  ASEID,
12
12
  A_TYPES__ASEID_Constructor
13
13
  } from "@adaas/a-concept/aseid";
14
14
  import { A_EntityError } from "./A-Entity.error";
15
15
  import { A_Feature } from "@adaas/a-concept/a-feature";
16
+ import { A_TYPES__EntityFeatures } from "./A-Entity.constants";
16
17
 
17
18
 
18
19
  /**
@@ -289,24 +290,24 @@ export class A_Entity<
289
290
  /**
290
291
  * The default method that can be called and extended to load entity data.
291
292
  */
292
- async load(
293
+ load(
293
294
  scope?: A_Scope,
294
- ) {
295
- return this.call('load', scope);
295
+ ): Promise<void> | void {
296
+ return this.call(A_TYPES__EntityFeatures.LOAD, scope);
296
297
  }
297
298
 
298
299
  /**
299
300
  * The default method that can be called and extended to destroy entity data.
300
301
  */
301
- async destroy(scope?: A_Scope) {
302
- return this.call('destroy', scope);
302
+ destroy(scope?: A_Scope): Promise<void> | void {
303
+ return this.call(A_TYPES__EntityFeatures.DESTROY, scope);
303
304
  }
304
305
 
305
306
  /**
306
307
  * The default method that can be called and extended to save entity data.
307
308
  */
308
- async save(scope?: A_Scope) {
309
- return this.call('save', scope);
309
+ save(scope?: A_Scope): Promise<void> | void {
310
+ return this.call(A_TYPES__EntityFeatures.SAVE, scope);
310
311
  }
311
312
 
312
313
 
@@ -5,8 +5,8 @@ export enum A_TYPES__EntityMetaKey {
5
5
  INJECTIONS = 'a-component-injections',
6
6
  }
7
7
 
8
- export enum A_TYPES__EntityFeatures {
9
- SAVE = 'save',
10
- DESTROY = 'destroy',
11
- LOAD = 'load'
12
- }
8
+ export const A_TYPES__EntityFeatures = {
9
+ SAVE: '_A_Entity__Save',
10
+ DESTROY: '_A_Entity__Destroy',
11
+ LOAD: '_A_Entity__Load'
12
+ } as const;
@@ -5,7 +5,7 @@ import { A_TYPES__FeatureDefineDecoratorMeta } from "@adaas/a-concept/a-feature"
5
5
  import { A_TYPES__A_InjectDecorator_Meta } from "@adaas/a-concept/a-inject";
6
6
 
7
7
 
8
- export class A_EntityMeta extends A_Meta<A_TYPES__EntityMeta> {
8
+ export class A_EntityMeta<T extends A_TYPES__EntityMeta = A_TYPES__EntityMeta> extends A_Meta<T> {
9
9
 
10
10
  /**
11
11
  * Returns all features defined in the Container
@@ -1,7 +1,7 @@
1
1
  import { A_Meta } from "@adaas/a-concept/a-meta";
2
2
  import { A_Entity } from "./A-Entity.class";
3
3
  import { ASEID } from "@adaas/a-concept/aseid";
4
- import { A_TYPES__EntityMetaKey } from "./A-Entity.constants";
4
+ import { A_TYPES__EntityFeatures, A_TYPES__EntityMetaKey } from "./A-Entity.constants";
5
5
  import { A_TYPES__FeatureDefineDecoratorMeta, A_TYPES__FeatureExtendDecoratorMeta } from "@adaas/a-concept/a-feature";
6
6
  import { A_TYPES__A_InjectDecorator_Meta } from "@adaas/a-concept/a-inject";
7
7
  import { A_TYPES__Ctor } from "@adaas/a-concept/types";
@@ -88,3 +88,4 @@ export type A_TYPES__EntityMeta = {
88
88
 
89
89
 
90
90
 
91
+ export type A_TYPES__EntityFeatureNames = typeof A_TYPES__EntityFeatures[keyof typeof A_TYPES__EntityFeatures];
@@ -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,7 +179,7 @@ export class A_Scope<
179
179
  get parent(): A_Scope | undefined {
180
180
  return this._parent;
181
181
  }
182
-
182
+
183
183
  /**
184
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
185
  * It refers to the visibility and accessibility of :
@@ -839,8 +839,61 @@ export class A_Scope<
839
839
  */
840
840
  name: string
841
841
  ): A_TYPES__Fragment_Constructor<T>
842
- resolveConstructor<T extends A_TYPES__A_DependencyInjectable>(name: string): A_TYPES__Entity_Constructor<T> | A_TYPES__Component_Constructor<T> | A_TYPES__Fragment_Constructor<T> | undefined
843
- resolveConstructor<T extends A_TYPES__A_DependencyInjectable>(name: string): A_TYPES__Entity_Constructor<T> | A_TYPES__Component_Constructor<T> | A_TYPES__Fragment_Constructor<T> | undefined {
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
+
844
897
  // 1) Check components
845
898
  const component = Array.from(this.allowedComponents).find(
846
899
  c => c.name === name
@@ -1812,7 +1865,12 @@ export class A_Scope<
1812
1865
  */
1813
1866
  entity: A_Entity
1814
1867
  ): void
1815
-
1868
+ deregister<T extends A_TYPES__A_DependencyInjectable>(
1869
+ /**
1870
+ * Provide an entity instance to register it in the scope
1871
+ */
1872
+ component: T
1873
+ ): void
1816
1874
  deregister(
1817
1875
  param1: unknown
1818
1876
  ): void {
@@ -132,7 +132,7 @@ describe('A-Meta tests', () => {
132
132
  expect(metaE.get(A_TYPES__ComponentMetaKey.EXTENSIONS)?.get('.*\\.testFeature$')?.map(e => e.handler)).toContain('test3');
133
133
  expect(metaE.get(A_TYPES__ComponentMetaKey.EXTENSIONS)?.get('.*\\.testFeature$')?.map(e => e.handler)).not.toContain('test2');
134
134
  })
135
- it('Should allow to inherit meta properly', async () => {
135
+ it('Should allow to define a custom meta', async () => {
136
136
 
137
137
  class InjectableComponent extends A_Component { }
138
138
 
@@ -170,6 +170,49 @@ describe('A-Meta tests', () => {
170
170
  expect(meta).toBeInstanceOf(CustomComponentMeta);
171
171
  expect(meta).toHaveProperty('customField');
172
172
 
173
+ expect(meta.get(A_TYPES__ComponentMetaKey.EXTENSIONS)?.size()).toBe(1);
174
+ expect(meta.get(A_TYPES__ComponentMetaKey.EXTENSIONS)?.has('.*\\.testFeature$')).toBe(true);
175
+ })
176
+ it('Should propagate a custom me', async () => {
177
+
178
+ class InjectableComponent extends A_Component { }
179
+
180
+ class CustomComponentMeta extends A_ComponentMeta<{ customField: string } & A_TYPES__ComponentMeta> {
181
+
182
+ get customField(): string | undefined {
183
+ return this.get('customField');
184
+ }
185
+ }
186
+
187
+ @A_Meta.Define(CustomComponentMeta)
188
+ class CustomComponent extends A_Component {
189
+
190
+ static Test() {
191
+
192
+ }
193
+
194
+ constructor(
195
+ @A_Inject(InjectableComponent) public injectableComponent: InjectableComponent
196
+ ) {
197
+ super();
198
+ }
199
+
200
+ @A_Feature.Extend({
201
+ name: 'testFeature'
202
+ })
203
+ async feature() {
204
+
205
+ }
206
+ }
207
+
208
+ class SubCustomComponent extends CustomComponent {}
209
+
210
+
211
+ const meta = A_Context.meta<CustomComponentMeta>(SubCustomComponent);
212
+
213
+ expect(meta).toBeInstanceOf(CustomComponentMeta);
214
+ expect(meta).toHaveProperty('customField');
215
+
173
216
  expect(meta.get(A_TYPES__ComponentMetaKey.EXTENSIONS)?.size()).toBe(1);
174
217
  expect(meta.get(A_TYPES__ComponentMetaKey.EXTENSIONS)?.has('.*\\.testFeature$')).toBe(true);
175
218
  })
@@ -106,7 +106,24 @@ describe('A-Scope tests', () => {
106
106
  const resolved = childScope.resolve(A_Component);
107
107
  expect(resolved).toBe(component);
108
108
  });
109
+ it('should resolve component constructor registered in scope', async () => {
110
+ class testComponent extends A_Component { }
109
111
 
112
+ const parentScope = new A_Scope({ name: 'ParentScope', components: [testComponent] });
113
+
114
+ const resolved = parentScope.resolveConstructor(testComponent);
115
+ expect(resolved).toBe(testComponent);
116
+ });
117
+ it('should resolve inherited component constructor in scope', async () => {
118
+ class testComponent extends A_Component { }
119
+ class inheritedComponent extends testComponent { }
120
+
121
+ const parentScope = new A_Scope({ name: 'ParentScope', components: [inheritedComponent] });
122
+
123
+ const resolved = parentScope.resolveConstructor(testComponent);
124
+
125
+ expect(resolved).toBe(inheritedComponent);
126
+ });
110
127
  it('Should resolve only one entity if no query is provided', async () => {
111
128
  class MyEntity extends A_Entity<{ bar: string }> {
112
129
  public bar!: string;