@adaas/a-concept 0.2.7 → 0.2.9

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.
Files changed (49) hide show
  1. package/dist/browser/A-Context.types-BtR_HJ0j.d.mts +3828 -0
  2. package/dist/browser/chunk-5ABP3TCO.mjs +57 -0
  3. package/dist/browser/chunk-5ABP3TCO.mjs.map +1 -0
  4. package/dist/browser/env.constants-CgDhS6pf.d.mts +39 -0
  5. package/dist/browser/env.d.mts +48 -0
  6. package/dist/browser/env.mjs +27 -0
  7. package/dist/browser/env.mjs.map +1 -0
  8. package/dist/browser/index.d.mts +990 -0
  9. package/dist/browser/index.mjs +5531 -0
  10. package/dist/browser/index.mjs.map +1 -0
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.mjs +2 -2
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/node/A-Context.types-BtR_HJ0j.d.mts +3828 -0
  16. package/dist/node/A-Context.types-BtR_HJ0j.d.ts +3828 -0
  17. package/dist/node/chunk-HIVDZ2X6.mjs +63 -0
  18. package/dist/node/chunk-HIVDZ2X6.mjs.map +1 -0
  19. package/dist/node/chunk-LKQAYXTD.mjs +161 -0
  20. package/dist/node/chunk-LKQAYXTD.mjs.map +1 -0
  21. package/dist/node/env.constants-CgDhS6pf.d.mts +39 -0
  22. package/dist/node/env.constants-CgDhS6pf.d.ts +39 -0
  23. package/dist/node/env.d.mts +75 -0
  24. package/dist/node/env.d.ts +75 -0
  25. package/dist/node/env.js +151 -0
  26. package/dist/node/env.js.map +1 -0
  27. package/dist/node/env.mjs +3 -0
  28. package/dist/node/env.mjs.map +1 -0
  29. package/dist/node/index.d.mts +990 -0
  30. package/dist/node/index.d.ts +990 -0
  31. package/dist/node/index.js +5639 -0
  32. package/dist/node/index.js.map +1 -0
  33. package/dist/node/index.mjs +5428 -0
  34. package/dist/node/index.mjs.map +1 -0
  35. package/jest.config.ts +1 -0
  36. package/package.json +16 -10
  37. package/src/constants/env.constants.ts +5 -0
  38. package/src/env/env-browser.ts +24 -0
  39. package/src/env/env-node.ts +58 -0
  40. package/src/env/env.base.ts +56 -0
  41. package/src/env/global.browser.d.ts +8 -0
  42. package/src/env/index.browser.ts +1 -0
  43. package/src/env/index.node.ts +1 -0
  44. package/src/global/A-Context/A-Context.class.ts +6 -26
  45. package/src/global/A-Error/A_Error.class.ts +2 -2
  46. package/src/global/A-Scope/A-Scope.class.ts +55 -1
  47. package/tests/A-Scope.test.ts +105 -0
  48. package/tsconfig.json +3 -1
  49. package/tsup.config.ts +91 -28
package/jest.config.ts CHANGED
@@ -10,6 +10,7 @@ const config: Config.InitialOptions = {
10
10
  },
11
11
  moduleNameMapper: {
12
12
  "@adaas/a-concept/constants/(.*)": ["<rootDir>/src/constants/$1"],
13
+ "@adaas/a-concept/env": ["<rootDir>/src/env/index.node.ts"],
13
14
  "@adaas/a-concept/global/(.*)": ["<rootDir>/src/global/$1"],
14
15
  "@adaas/a-concept/types/(.*)": ["<rootDir>/src/types/$1"],
15
16
  "@adaas/a-concept/helpers/(.*)": ["<rootDir>/src/helpers/$1"],
package/package.json CHANGED
@@ -1,11 +1,23 @@
1
1
  {
2
2
  "name": "@adaas/a-concept",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
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
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.mjs",
8
- "types": "./dist/index.d.ts",
6
+ "main": "./dist/node/index.cjs",
7
+ "module": "./dist/node/index.mjs",
8
+ "types": "./dist/node/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "browser": "./dist/browser/index.mjs",
12
+ "import": "./dist/node/index.mjs",
13
+ "require": "./dist/node/index.cjs"
14
+ },
15
+ "./env": {
16
+ "browser": "./dist/browser/env.mjs",
17
+ "import": "./dist/node/env.mjs",
18
+ "require": "./dist/node/env.cjs"
19
+ }
20
+ },
9
21
  "author": {
10
22
  "name": "ADAAS YAZILIM LİMİTED ŞİRKETİ",
11
23
  "email": "contact-us@adaas.org"
@@ -24,12 +36,6 @@
24
36
  "url": "https://github.com/ADAAS-org/adaas-a-concept/issues"
25
37
  },
26
38
  "sideEffects": false,
27
- "exports": {
28
- ".": {
29
- "import": "./dist/index.mjs",
30
- "require": "./dist/index.cjs"
31
- }
32
- },
33
39
  "nodemonConfig": {
34
40
  "ignore": [
35
41
  "**/*.test.ts",
@@ -24,6 +24,10 @@ export const A_CONSTANTS__DEFAULT_ENV_VARIABLES = {
24
24
  * Environment of the application e.g. development, production, staging
25
25
  */
26
26
  A_CONCEPT_ENVIRONMENT: 'A_CONCEPT_ENVIRONMENT',
27
+ /**
28
+ * Runtime environment of the application e.g. browser, node
29
+ */
30
+ A_CONCEPT_RUNTIME_ENVIRONMENT: 'A_CONCEPT_RUNTIME_ENVIRONMENT',
27
31
  /**
28
32
  * Root folder of the application
29
33
  * [!] Automatically set by A-Concept when the application starts
@@ -44,6 +48,7 @@ export const A_CONSTANTS__DEFAULT_ENV_VARIABLES_ARRAY = [
44
48
  A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAME,
45
49
  A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_SCOPE,
46
50
  A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ENVIRONMENT,
51
+ A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_RUNTIME_ENVIRONMENT,
47
52
  A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_FOLDER,
48
53
 
49
54
  A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_ERROR_DEFAULT_DESCRIPTION,
@@ -0,0 +1,24 @@
1
+ import { A_TYPES__ContextEnvironment } from "../global/A-Context/A-Context.types";
2
+ import { A_CONCEPT_BASE_ENV } from "./env.base";
3
+
4
+
5
+ export class ENV extends A_CONCEPT_BASE_ENV {
6
+ static get A_CONCEPT_ENVIRONMENT() {
7
+ return window.__A_CONCEPT_ENVIRONMENT_ENV__?.A_CONCEPT_ENVIRONMENT || super.A_CONCEPT_ENVIRONMENT;
8
+ }
9
+ static get A_CONCEPT_RUNTIME_ENVIRONMENT(): A_TYPES__ContextEnvironment {
10
+ return 'browser';
11
+ }
12
+ static get A_CONCEPT_NAME() {
13
+ return window.__A_CONCEPT_ENVIRONMENT_ENV__?.A_CONCEPT_NAME || super.A_CONCEPT_NAME;
14
+ }
15
+ static get A_CONCEPT_ROOT_FOLDER() {
16
+ return window.__A_CONCEPT_ENVIRONMENT_ENV__?.A_CONCEPT_ROOT_FOLDER || super.A_CONCEPT_ROOT_FOLDER;
17
+ }
18
+ static get A_CONCEPT_ROOT_SCOPE() {
19
+ return window.__A_CONCEPT_ENVIRONMENT_ENV__?.A_CONCEPT_ROOT_SCOPE || super.A_CONCEPT_ROOT_SCOPE;
20
+ }
21
+ static get A_ERROR_DEFAULT_DESCRIPTION() {
22
+ return window.__A_CONCEPT_ENVIRONMENT_ENV__?.A_ERROR_DEFAULT_DESCRIPTION || super.A_ERROR_DEFAULT_DESCRIPTION;
23
+ }
24
+ };
@@ -0,0 +1,58 @@
1
+ import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from "../constants/env.constants";
2
+ import { A_TYPES__ContextEnvironment } from "../global/A-Context/A-Context.types";
3
+ import { A_CONCEPT_BASE_ENV } from "./env.base";
4
+
5
+ export class ENV extends A_CONCEPT_BASE_ENV {
6
+ // ----------------------------------------------------------
7
+ // A-Concept Core Environment Variables
8
+ // ----------------------------------------------------------
9
+ // These environment variables are used by A-Concept core to configure the application
10
+ // ----------------------------------------------------------
11
+ /**
12
+ * Name of the application
13
+ *
14
+ * DEFAULT value is 'a-concept'
15
+ *
16
+ * [!] Provided name will be used for all aseids in the application by default
17
+ */
18
+ static get A_CONCEPT_NAME() {
19
+ return process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAME] || super.A_CONCEPT_NAME
20
+ }
21
+ /**
22
+ * Root scope of the application
23
+ *
24
+ * DEFAULT value is 'root'
25
+ *
26
+ * [!] Provided name will be used for all aseids in the application by default
27
+ */
28
+ static get A_CONCEPT_ROOT_SCOPE() {
29
+ return process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_SCOPE] || super.A_CONCEPT_ROOT_SCOPE;
30
+ }
31
+ /**
32
+ * Environment of the application e.g. development, production, staging
33
+ */
34
+ static get A_CONCEPT_ENVIRONMENT() {
35
+ return process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ENVIRONMENT] || super.A_CONCEPT_ENVIRONMENT;
36
+ }
37
+ /**
38
+ * Runtime environment of the application e.g. browser, node
39
+ */
40
+ static get A_CONCEPT_RUNTIME_ENVIRONMENT():A_TYPES__ContextEnvironment {
41
+ return 'server';
42
+ }
43
+
44
+ /**
45
+ * Root folder of the application
46
+ * [!] Automatically set by A-Concept when the application starts
47
+ */
48
+ static get A_CONCEPT_ROOT_FOLDER() {
49
+ return process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_FOLDER] || super.A_CONCEPT_ROOT_FOLDER;
50
+ }
51
+
52
+ /**
53
+ * Allows to define a default error description for errors thrown without a description
54
+ */
55
+ static get A_ERROR_DEFAULT_DESCRIPTION() {
56
+ return process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_ERROR_DEFAULT_DESCRIPTION] || super.A_ERROR_DEFAULT_DESCRIPTION;
57
+ }
58
+ }
@@ -0,0 +1,56 @@
1
+ import { A_TYPES__ContextEnvironment } from "../global/A-Context/A-Context.types";
2
+
3
+ export class A_CONCEPT_BASE_ENV {
4
+ // ----------------------------------------------------------
5
+ // A-Concept Core Environment Variables
6
+ // ----------------------------------------------------------
7
+ // These environment variables are used by A-Concept core to configure the application
8
+ // ----------------------------------------------------------
9
+ /**
10
+ * Name of the application
11
+ *
12
+ * DEFAULT value is 'a-concept'
13
+ *
14
+ * [!] Provided name will be used for all aseids in the application by default
15
+ */
16
+ static get A_CONCEPT_NAME() {
17
+ return "a-concept";
18
+ }
19
+ /**
20
+ * Root scope of the application
21
+ *
22
+ * DEFAULT value is 'root'
23
+ *
24
+ * [!] Provided name will be used for all aseids in the application by default
25
+ */
26
+ static get A_CONCEPT_ROOT_SCOPE() {
27
+ return "root";
28
+ }
29
+ /**
30
+ * Environment of the application e.g. development, production, staging
31
+ */
32
+ static get A_CONCEPT_ENVIRONMENT() {
33
+ return "production";
34
+ }
35
+ /**
36
+ * Runtime environment of the application e.g. browser, node
37
+ */
38
+ static get A_CONCEPT_RUNTIME_ENVIRONMENT():A_TYPES__ContextEnvironment {
39
+ return "unknown";
40
+ }
41
+
42
+ /**
43
+ * Root folder of the application
44
+ * [!] Automatically set by A-Concept when the application starts
45
+ */
46
+ static get A_CONCEPT_ROOT_FOLDER() {
47
+ return "/app";
48
+ }
49
+
50
+ /**
51
+ * Allows to define a default error description for errors thrown without a description
52
+ */
53
+ static get A_ERROR_DEFAULT_DESCRIPTION() {
54
+ return "If you see this error please let us know.";
55
+ }
56
+ }
@@ -0,0 +1,8 @@
1
+ import type { RuntimeEnv } from "./env.base";
2
+
3
+ declare global {
4
+ interface Window {
5
+ __A_CONCEPT_ENVIRONMENT_ENV__?: Partial<RuntimeEnv> & {
6
+ };
7
+ }
8
+ }
@@ -0,0 +1 @@
1
+ export { ENV } from "./env-browser";
@@ -0,0 +1 @@
1
+ export { ENV } from "./env-node";
@@ -22,7 +22,6 @@ import { A_ContainerMeta } from "../A-Container/A-Container.meta";
22
22
  import { A_Entity } from "../A-Entity/A-Entity.class";
23
23
  import { A_EntityMeta } from "../A-Entity/A-Entity.meta";
24
24
  import { A_TYPES__A_StageStep } from "../A-Stage/A-Stage.types";
25
- import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from "@adaas/a-concept/constants/env.constants";
26
25
  import { A_TYPES__EntityMetaKey } from "../A-Entity/A-Entity.constants";
27
26
  import { A_TYPES__ContainerMetaKey } from "../A-Container/A-Container.constants";
28
27
  import { A_TYPES__ComponentMetaKey } from "../A-Component/A-Component.constants";
@@ -40,6 +39,7 @@ import { A_CommonHelper } from "@adaas/a-concept/helpers/A_Common.helper";
40
39
  import { A_TYPES__Fragment_Constructor } from "../A-Fragment/A-Fragment.types";
41
40
  import { A_Dependency } from "../A-Dependency/A-Dependency.class";
42
41
  import { A_TYPES__Ctor } from "@adaas/a-concept/types/A_Common.types";
42
+ import { ENV } from "@adaas/a-concept/env";
43
43
 
44
44
 
45
45
 
@@ -53,7 +53,7 @@ export class A_Context {
53
53
  * [!] If environment variable is not set, it will default to 'a-concept'
54
54
  */
55
55
  static get concept() {
56
- return process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_NAME] || 'a-concept';
56
+ return ENV.A_CONCEPT_NAME || 'a-concept';
57
57
  }
58
58
  /**
59
59
  * Root scope of the application from environment variable A_CONCEPT_ROOT_SCOPE
@@ -66,18 +66,10 @@ export class A_Context {
66
66
  /**
67
67
  * Environment the application is running in.
68
68
  * Can be either 'server' or 'browser'.
69
- * [!] Determined by checking if 'window' object is available.
69
+ * [!] Determined by environment variable A_CONCEPT_RUNTIME_ENVIRONMENT that comes from the build tool or is set manually in the environment.
70
70
  */
71
71
  static get environment(): A_TYPES__ContextEnvironment {
72
- let testEnvironment: A_TYPES__ContextEnvironment = 'browser';
73
-
74
- try {
75
- testEnvironment = window.location ? 'browser' : 'server';
76
- } catch (error) {
77
- testEnvironment = 'server';
78
- }
79
-
80
- return testEnvironment;
72
+ return ENV.A_CONCEPT_RUNTIME_ENVIRONMENT
81
73
  }
82
74
 
83
75
  /**
@@ -129,13 +121,7 @@ export class A_Context {
129
121
  * [!] This class should not be instantiated directly. Use A_Context.getInstance() instead.
130
122
  */
131
123
  private constructor() {
132
- let name = 'root';
133
-
134
- if (A_Context.environment === 'server')
135
- name = process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_SCOPE] || 'root';
136
-
137
- if (A_Context.environment === 'browser')
138
- name = (window as any)[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_SCOPE] || 'root';
124
+ const name = String(ENV.A_CONCEPT_ROOT_SCOPE) || 'root';
139
125
 
140
126
  this._root = new A_Scope({ name });
141
127
  }
@@ -1063,13 +1049,7 @@ export class A_Context {
1063
1049
 
1064
1050
  instance._registry = new WeakMap();
1065
1051
 
1066
- let name = 'root';
1067
-
1068
- if (A_Context.environment === 'server')
1069
- name = process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_SCOPE] || 'root';
1070
-
1071
- if (A_Context.environment === 'browser')
1072
- name = (window as any)[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_CONCEPT_ROOT_SCOPE] || 'root';
1052
+ const name = String(ENV.A_CONCEPT_ROOT_SCOPE) || 'root';
1073
1053
 
1074
1054
  instance._root = new A_Scope({ name });
1075
1055
  }
@@ -10,7 +10,7 @@ import { A_FormatterHelper } from '@adaas/a-concept/helpers/A_Formatter.helper';
10
10
  import { A_Context } from '../A-Context/A-Context.class';
11
11
  import { A_TypeGuards } from '@adaas/a-concept/helpers/A_TypeGuards.helper';
12
12
  import { ASEID } from '../ASEID/ASEID.class';
13
- import { A_CONSTANTS__DEFAULT_ENV_VARIABLES } from '@adaas/a-concept/constants/env.constants';
13
+ import { ENV } from '@adaas/a-concept/env';
14
14
 
15
15
 
16
16
  export class A_Error<
@@ -286,7 +286,7 @@ export class A_Error<
286
286
  * [!] Note: This description is intended to provide more context about the error and can be used for debugging or logging purposes
287
287
  */
288
288
  get description(): string {
289
- return this._description || process.env[A_CONSTANTS__DEFAULT_ENV_VARIABLES.A_ERROR_DEFAULT_DESCRIPTION] || A_CONSTANTS__ERROR_DESCRIPTION;
289
+ return this._description || String(ENV.A_ERROR_DEFAULT_DESCRIPTION) || A_CONSTANTS__ERROR_DESCRIPTION;
290
290
  }
291
291
  /**
292
292
  * Returns the original error if any
@@ -1814,6 +1814,13 @@ export class A_Scope<
1814
1814
  this._components.delete(param1.constructor as _ComponentType[number]);
1815
1815
  A_Context.deregister(param1);
1816
1816
 
1817
+ const ctor = param1.constructor as _ComponentType[number];
1818
+
1819
+ const hasComponent = this._components.has(ctor);
1820
+ if (!hasComponent) {
1821
+ this.allowedComponents.delete(ctor);
1822
+ }
1823
+
1817
1824
  break;
1818
1825
  }
1819
1826
  // 3) In case when it's a A-Entity instance
@@ -1821,14 +1828,28 @@ export class A_Scope<
1821
1828
 
1822
1829
  this._entities.delete(param1.aseid.toString());
1823
1830
  A_Context.deregister(param1);
1831
+
1832
+ const ctor = param1.constructor as _EntityType[number];
1833
+
1834
+ const hasEntity = Array.from(this._entities.values()).some(entity => entity instanceof ctor);
1835
+ if (!hasEntity) {
1836
+ this.allowedEntities.delete(ctor);
1837
+ }
1838
+
1824
1839
  break;
1825
1840
  }
1826
1841
  // 4) In case when it's a A-Fragment instance
1827
1842
  case A_TypeGuards.isFragmentInstance(param1): {
1828
-
1829
1843
  this._fragments.delete(param1.constructor as A_TYPES__Fragment_Constructor<_FragmentType[number]>);
1830
1844
  A_Context.deregister(param1);
1831
1845
 
1846
+ const ctor = param1.constructor as A_TYPES__Fragment_Constructor<_FragmentType[number]>;
1847
+
1848
+ const hasFragment = Array.from(this._fragments.values()).some(fragment => fragment instanceof ctor);
1849
+ if (!hasFragment) {
1850
+ this.allowedFragments.delete(ctor);
1851
+ }
1852
+
1832
1853
  break;
1833
1854
  }
1834
1855
  // 5) In case when it's a A-Error instance
@@ -1836,6 +1857,14 @@ export class A_Scope<
1836
1857
 
1837
1858
  this._errors.delete(param1.code);
1838
1859
  A_Context.deregister(param1);
1860
+
1861
+ const ctor = param1.constructor as _ErrorType[number];
1862
+
1863
+ const hasError = Array.from(this._errors.values()).some(error => error instanceof ctor);
1864
+ if (!hasError) {
1865
+ this.allowedErrors.delete(ctor);
1866
+ }
1867
+
1839
1868
  break;
1840
1869
  }
1841
1870
 
@@ -1850,16 +1879,40 @@ export class A_Scope<
1850
1879
  // 8) In case when it's a A-Fragment constructor
1851
1880
  case A_TypeGuards.isFragmentConstructor(param1): {
1852
1881
  this.allowedFragments.delete(param1 as A_TYPES__Fragment_Constructor<_FragmentType[number]>);
1882
+ // and then deregister all instances of this fragment
1883
+ Array.from(this._fragments.entries()).forEach(([ctor, instance]) => {
1884
+ if (A_CommonHelper.isInheritedFrom(ctor, param1)) {
1885
+ this._fragments.delete(ctor);
1886
+ A_Context.deregister(instance);
1887
+ }
1888
+ });
1889
+
1853
1890
  break;
1854
1891
  }
1855
1892
  // 9) In case when it's a A-Entity constructor
1856
1893
  case A_TypeGuards.isEntityConstructor(param1): {
1857
1894
  this.allowedEntities.delete(param1 as _EntityType[number]);
1895
+ // and then deregister all instances of this entity
1896
+ Array.from(this._entities.entries()).forEach(([aseid, instance]) => {
1897
+ if (A_CommonHelper.isInheritedFrom(instance.constructor, param1)) {
1898
+ this._entities.delete(aseid);
1899
+ A_Context.deregister(instance);
1900
+ }
1901
+ });
1902
+
1858
1903
  break;
1859
1904
  }
1860
1905
  // 10) In case when it's a A-Error constructor
1861
1906
  case A_TypeGuards.isErrorConstructor(param1): {
1862
1907
  this.allowedErrors.delete(param1 as _ErrorType[number]);
1908
+ // and then deregister all instances of this error
1909
+ Array.from(this._errors.entries()).forEach(([code, instance]) => {
1910
+ if (A_CommonHelper.isInheritedFrom(instance.constructor, param1)) {
1911
+ this._errors.delete(code);
1912
+ A_Context.deregister(instance);
1913
+ }
1914
+ });
1915
+
1863
1916
  break;
1864
1917
  }
1865
1918
 
@@ -1875,6 +1928,7 @@ export class A_Scope<
1875
1928
  `Cannot deregister ${componentName} from the scope ${this.name}`
1876
1929
  );
1877
1930
  }
1931
+
1878
1932
  }
1879
1933
 
1880
1934
  /**
@@ -705,4 +705,109 @@ describe('A-Scope tests', () => {
705
705
  expect(resolvedA).toBeInstanceOf(MyEntity_B);
706
706
  expect(resolvedA?.name).toBe('Entity1');
707
707
  });
708
+
709
+ it('Should deregister entities properly', async () => {
710
+
711
+ class MyEntity extends A_Entity { }
712
+
713
+ class MyFragment extends A_Fragment { }
714
+
715
+ class MyComponent extends A_Component { }
716
+
717
+ const scope = new A_Scope({ name: 'TestScope' });
718
+
719
+
720
+
721
+ const entity = new MyEntity();
722
+ const fragment = new MyFragment();
723
+
724
+ scope.register(entity);
725
+ scope.register(fragment);
726
+ scope.register(MyComponent);
727
+
728
+ expect(scope.has(MyEntity)).toBe(true);
729
+ expect(scope.has(MyFragment)).toBe(true);
730
+ expect(scope.has(MyComponent)).toBe(true);
731
+
732
+ scope.deregister(entity);
733
+ scope.deregister(fragment);
734
+ scope.deregister(MyComponent);
735
+
736
+ expect(scope.has(MyEntity)).toBe(false);
737
+ expect(scope.has(MyFragment)).toBe(false);
738
+ expect(scope.has(MyComponent)).toBe(false);
739
+ });
740
+
741
+ it('Should deregister all entities by class', async () => {
742
+
743
+ class BaseEntity extends A_Entity { }
744
+
745
+ class MyEntityA extends A_Entity { }
746
+ class MyEntityB extends BaseEntity { }
747
+
748
+
749
+ const scope = new A_Scope({ name: 'TestScope' });
750
+
751
+
752
+
753
+ const entityA1 = new MyEntityA();
754
+ const entityA2 = new MyEntityA();
755
+ const entityB1 = new MyEntityB();
756
+
757
+ scope.register(entityA1);
758
+ scope.register(entityA2);
759
+ scope.register(entityB1);
760
+
761
+ expect(scope.resolveAll(MyEntityA).length).toBe(2);
762
+ expect(scope.resolveAll(BaseEntity).length).toBe(1);
763
+
764
+ scope.deregister(MyEntityA);
765
+
766
+ expect(scope.resolveAll(MyEntityA).length).toBe(0);
767
+ expect(scope.resolveAll(BaseEntity).length).toBe(1);
768
+
769
+ const entityB2 = new MyEntityB();
770
+ scope.register(entityB2);
771
+
772
+ expect(scope.resolveAll(BaseEntity).length).toBe(2);
773
+
774
+ scope.deregister(BaseEntity);
775
+
776
+ expect(scope.resolveAll(BaseEntity).length).toBe(0);
777
+ });
778
+ it('Should register/deregister fragments with the same names', async () => {
779
+
780
+ class MyFragment extends A_Fragment {
781
+
782
+ array: string[] = [];
783
+
784
+ constructor(name: string) {
785
+ super({ name });
786
+ }
787
+ }
788
+
789
+ const scope = new A_Scope({ name: 'TestScope' });
790
+
791
+ const fragmentA1 = new MyFragment('fragmentA');
792
+
793
+ scope.register(fragmentA1);
794
+
795
+ expect(scope.has(MyFragment)).toBe(true);
796
+ expect(scope.resolve(MyFragment)).toBe(fragmentA1);
797
+
798
+ scope.deregister(fragmentA1);
799
+
800
+ fragmentA1.array.push('newData');
801
+
802
+
803
+ expect(scope.has(MyFragment)).toBe(false);
804
+
805
+ const fragmentA2 = new MyFragment('fragmentA');
806
+
807
+ scope.register(fragmentA2);
808
+
809
+ expect(scope.has(MyFragment)).toBe(true);
810
+ expect(scope.resolve(MyFragment)).toBe(fragmentA2);
811
+ expect(fragmentA2.array.length).toBe(0);
812
+ });
708
813
  });
package/tsconfig.json CHANGED
@@ -31,6 +31,7 @@
31
31
  ],
32
32
  "paths": {
33
33
  "@adaas/a-concept/constants/*": ["src/constants/*"],
34
+ "@adaas/a-concept/env": ["src/env/index.node.ts"],
34
35
  "@adaas/a-concept/global/*": ["src/global/*"],
35
36
  "@adaas/a-concept/types/*": ["src/types/*"],
36
37
  "@adaas/a-concept/helpers/*": ["src/helpers/*"],
@@ -50,7 +51,8 @@
50
51
  "src/**/*",
51
52
  "tests/**/*",
52
53
  "examples/**/*",
53
- "src/index.ts"
54
+ "src/index.ts",
55
+ "src/env/global.browser.d.ts"
54
56
  ],
55
57
  "exclude": [
56
58
  "node_modules/**/*",
package/tsup.config.ts CHANGED
@@ -1,32 +1,95 @@
1
1
  import { defineConfig } from "tsup";
2
2
 
3
- export default defineConfig((options) => ({
4
- entry: ["src/index.ts"],
5
- format: ["esm", "cjs"],
6
- dts: true,
7
- clean: !options.watch,
8
- sourcemap: true,
9
- target: "es2020",
10
- minify: !options.watch,
11
- treeshake: "recommended",
12
- skipNodeModulesBundle: true,
13
- splitting: false,
14
- silent: false,
15
- platform: "neutral",
16
- // Add hash to filenames for cache busting in production builds
17
- outExtension({ format }) {
18
- return {
19
- js: format === "esm" ? `.mjs` : `.cjs`,
20
- };
21
- },
22
- // Extra optimization options (for 2025 esbuild)
23
- esbuildOptions(options) {
24
- options.keepNames = true; // Preserve class/function names for better debugging
25
- options.charset = "utf8";
3
+ export default defineConfig([
4
+ /**
5
+ * ============================
6
+ * Browser build
7
+ * ============================
8
+ *
9
+ * Produces:
10
+ * dist/browser/index.mjs
11
+ * dist/browser/env.mjs
12
+ *
13
+ * - No Node globals
14
+ * - No `process`
15
+ * - Used by bundlers (Vite, Webpack, Rollup)
16
+ */
17
+ {
18
+ entry: {
19
+ // Public library entry
20
+ index: "src/index.ts",
21
+
22
+ // Public env entry (browser implementation)
23
+ env: "src/env/index.browser.ts",
24
+ },
25
+
26
+ // Output directory for browser bundle
27
+ outDir: "dist/browser",
28
+
29
+ // Browser consumers expect ESM
30
+ format: ["esm"],
31
+
32
+ // Tells esbuild this is browser-safe code
33
+ platform: "browser",
34
+
35
+ // Reasonable baseline for modern browsers
36
+ target: "es2020",
37
+
38
+ // Smaller bundles
39
+ treeshake: true,
40
+
41
+ // Useful for debugging in bundlers
42
+ sourcemap: true,
43
+
44
+ // Emit .d.ts files
45
+ dts: true,
46
+
47
+ /**
48
+ * IMPORTANT:
49
+ * We do NOT define process.env here.
50
+ * Browser env must never reference process at all.
51
+ */
26
52
  },
27
53
 
28
- // Enable minification for output size (production only)
29
- minifyWhitespace: !options.watch,
30
- minifyIdentifiers: !options.watch,
31
- minifySyntax: !options.watch,
32
- }));
54
+ /**
55
+ * ============================
56
+ * Node build
57
+ * ============================
58
+ *
59
+ * Produces:
60
+ * dist/node/index.mjs
61
+ * dist/node/index.cjs
62
+ * dist/node/env.mjs
63
+ * dist/node/env.cjs
64
+ *
65
+ * - Can use process.env
66
+ * - Used by Node (ESM + CJS)
67
+ */
68
+ {
69
+ entry: {
70
+ // Same public API as browser
71
+ index: "src/index.ts",
72
+
73
+ // Node-specific env implementation
74
+ env: "src/env/index.node.ts",
75
+ },
76
+
77
+ // Output directory for node bundle
78
+ outDir: "dist/node",
79
+
80
+ // Support both module systems
81
+ format: ["esm", "cjs"],
82
+
83
+ // Enables Node globals and resolution
84
+ platform: "node",
85
+
86
+ // Node 16+ safe baseline
87
+ target: "es2020",
88
+
89
+ treeshake: true,
90
+ sourcemap: true,
91
+
92
+ // Emit .d.ts files (shared shape)
93
+ dts: true,
94
+ },
95
+ ]);