@vived/core 1.6.0 → 2.0.1
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/cjs/AppObject/AppObjectComponent.js +8 -10
- package/dist/cjs/AppObject/AppObjectComponent.js.map +1 -1
- package/dist/cjs/AppObject/AppObjectEntityRepo.js +113 -11
- package/dist/cjs/AppObject/AppObjectEntityRepo.js.map +1 -1
- package/dist/cjs/AppObject/AppObjectPM.js +106 -6
- package/dist/cjs/AppObject/AppObjectPM.js.map +1 -1
- package/dist/cjs/AppObject/AppObjectRepo.js +4 -1
- package/dist/cjs/AppObject/AppObjectRepo.js.map +1 -1
- package/dist/cjs/AppObject/AppObjectSingletonEntity.js +40 -0
- package/dist/cjs/AppObject/AppObjectSingletonEntity.js.map +1 -0
- package/dist/cjs/AppObject/AppObjectSingletonEntityRepo.js +54 -0
- package/dist/cjs/AppObject/AppObjectSingletonEntityRepo.js.map +1 -0
- package/dist/cjs/AppObject/AppObjectSingletonPM.js +69 -0
- package/dist/cjs/AppObject/AppObjectSingletonPM.js.map +1 -0
- package/dist/cjs/AppObject/AppObjectSingletonUC.js +60 -0
- package/dist/cjs/AppObject/AppObjectSingletonUC.js.map +1 -0
- package/dist/cjs/AppObject/index.js +4 -0
- package/dist/cjs/AppObject/index.js.map +1 -1
- package/dist/cjs/Entities/ObserverList.js +6 -0
- package/dist/cjs/Entities/ObserverList.js.map +1 -1
- package/dist/cjs/ExampleFeature/Entities/ExampleRepo.js +10 -22
- package/dist/cjs/ExampleFeature/Entities/ExampleRepo.js.map +1 -1
- package/dist/cjs/ExampleFeature/Entities/ExampleSingletonEntity.js +1 -3
- package/dist/cjs/ExampleFeature/Entities/ExampleSingletonEntity.js.map +1 -1
- package/dist/cjs/ExampleFeature/Factory/ExampleFeatureFactory.js +1 -1
- package/dist/cjs/ExampleFeature/Factory/ExampleFeatureFactory.js.map +1 -1
- package/dist/cjs/ExampleFeature/PMs/ExamplePM.js +5 -13
- package/dist/cjs/ExampleFeature/PMs/ExamplePM.js.map +1 -1
- package/dist/cjs/ExampleFeature/PMs/ExampleSingletonPM.js +8 -12
- package/dist/cjs/ExampleFeature/PMs/ExampleSingletonPM.js.map +1 -1
- package/dist/cjs/ExampleFeature/UCs/EditExampleStringUC.js +0 -4
- package/dist/cjs/ExampleFeature/UCs/EditExampleStringUC.js.map +1 -1
- package/dist/cjs/ExampleFeature/UCs/ToggleExampleBooleanUC.js +2 -8
- package/dist/cjs/ExampleFeature/UCs/ToggleExampleBooleanUC.js.map +1 -1
- package/dist/esm/AppObject/AppObjectComponent.js +8 -10
- package/dist/esm/AppObject/AppObjectComponent.js.map +1 -1
- package/dist/esm/AppObject/AppObjectEntityRepo.js +113 -11
- package/dist/esm/AppObject/AppObjectEntityRepo.js.map +1 -1
- package/dist/esm/AppObject/AppObjectPM.js +107 -7
- package/dist/esm/AppObject/AppObjectPM.js.map +1 -1
- package/dist/esm/AppObject/AppObjectRepo.js +4 -1
- package/dist/esm/AppObject/AppObjectRepo.js.map +1 -1
- package/dist/esm/AppObject/AppObjectSingletonEntity.js +36 -0
- package/dist/esm/AppObject/AppObjectSingletonEntity.js.map +1 -0
- package/dist/esm/AppObject/AppObjectSingletonEntityRepo.js +50 -0
- package/dist/esm/AppObject/AppObjectSingletonEntityRepo.js.map +1 -0
- package/dist/esm/AppObject/AppObjectSingletonPM.js +65 -0
- package/dist/esm/AppObject/AppObjectSingletonPM.js.map +1 -0
- package/dist/esm/AppObject/AppObjectSingletonUC.js +56 -0
- package/dist/esm/AppObject/AppObjectSingletonUC.js.map +1 -0
- package/dist/esm/AppObject/index.js +4 -0
- package/dist/esm/AppObject/index.js.map +1 -1
- package/dist/esm/Entities/ObserverList.js +6 -0
- package/dist/esm/Entities/ObserverList.js.map +1 -1
- package/dist/esm/ExampleFeature/Entities/ExampleRepo.js +10 -22
- package/dist/esm/ExampleFeature/Entities/ExampleRepo.js.map +1 -1
- package/dist/esm/ExampleFeature/Entities/ExampleSingletonEntity.js +2 -4
- package/dist/esm/ExampleFeature/Entities/ExampleSingletonEntity.js.map +1 -1
- package/dist/esm/ExampleFeature/Factory/ExampleFeatureFactory.js +1 -1
- package/dist/esm/ExampleFeature/Factory/ExampleFeatureFactory.js.map +1 -1
- package/dist/esm/ExampleFeature/PMs/ExamplePM.js +5 -13
- package/dist/esm/ExampleFeature/PMs/ExamplePM.js.map +1 -1
- package/dist/esm/ExampleFeature/PMs/ExampleSingletonPM.js +9 -13
- package/dist/esm/ExampleFeature/PMs/ExampleSingletonPM.js.map +1 -1
- package/dist/esm/ExampleFeature/UCs/EditExampleStringUC.js +0 -4
- package/dist/esm/ExampleFeature/UCs/EditExampleStringUC.js.map +1 -1
- package/dist/esm/ExampleFeature/UCs/ToggleExampleBooleanUC.js +3 -9
- package/dist/esm/ExampleFeature/UCs/ToggleExampleBooleanUC.js.map +1 -1
- package/dist/types/AppObject/AppObjectComponent.d.ts +6 -4
- package/dist/types/AppObject/AppObjectComponent.d.ts.map +1 -1
- package/dist/types/AppObject/AppObjectEntityRepo.d.ts +80 -7
- package/dist/types/AppObject/AppObjectEntityRepo.d.ts.map +1 -1
- package/dist/types/AppObject/AppObjectPM.d.ts +82 -2
- package/dist/types/AppObject/AppObjectPM.d.ts.map +1 -1
- package/dist/types/AppObject/AppObjectRepo.d.ts +6 -0
- package/dist/types/AppObject/AppObjectRepo.d.ts.map +1 -1
- package/dist/types/AppObject/AppObjectSingletonEntity.d.ts +31 -0
- package/dist/types/AppObject/AppObjectSingletonEntity.d.ts.map +1 -0
- package/dist/types/AppObject/AppObjectSingletonEntityRepo.d.ts +46 -0
- package/dist/types/AppObject/AppObjectSingletonEntityRepo.d.ts.map +1 -0
- package/dist/types/AppObject/AppObjectSingletonPM.d.ts +60 -0
- package/dist/types/AppObject/AppObjectSingletonPM.d.ts.map +1 -0
- package/dist/types/AppObject/AppObjectSingletonUC.d.ts +51 -0
- package/dist/types/AppObject/AppObjectSingletonUC.d.ts.map +1 -0
- package/dist/types/AppObject/index.d.ts +4 -0
- package/dist/types/AppObject/index.d.ts.map +1 -1
- package/dist/types/Entities/ObserverList.d.ts +4 -0
- package/dist/types/Entities/ObserverList.d.ts.map +1 -1
- package/dist/types/ExampleFeature/Entities/ExampleRepo.d.ts +1 -5
- package/dist/types/ExampleFeature/Entities/ExampleRepo.d.ts.map +1 -1
- package/dist/types/ExampleFeature/Entities/ExampleSingletonEntity.d.ts +2 -2
- package/dist/types/ExampleFeature/Entities/ExampleSingletonEntity.d.ts.map +1 -1
- package/dist/types/ExampleFeature/PMs/ExampleSingletonPM.d.ts +4 -4
- package/dist/types/ExampleFeature/PMs/ExampleSingletonPM.d.ts.map +1 -1
- package/dist/types/ExampleFeature/UCs/ToggleExampleBooleanUC.d.ts +2 -2
- package/dist/types/ExampleFeature/UCs/ToggleExampleBooleanUC.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -75,10 +75,6 @@ class EditSlideTextUCImp extends EditExampleStringUC {
|
|
|
75
75
|
* @param text The new string value to set
|
|
76
76
|
*/
|
|
77
77
|
this.editExampleString = (text) => {
|
|
78
|
-
if (!this.exampleEntity) {
|
|
79
|
-
this.warn("Unable to find AppState");
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
78
|
// Update the entity property, which will trigger PM updates and UI refreshes
|
|
83
79
|
this.exampleEntity.aStringProperty = text;
|
|
84
80
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditExampleStringUC.js","sourceRoot":"","sources":["../../../../src/ExampleFeature/UCs/EditExampleStringUC.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AA+CH,kDAEC;AA/CD,+CAAwE;AACxE,6DAA0D;AAE1D;;;GAGG;AACH,MAAsB,mBAAoB,SAAQ,uBAAW;IAU3D;;;;OAIG;IACH,MAAM,CAAC,GAAG,CAAC,MAAiB;QAC1B,OAAO,MAAM,CAAC,YAAY,CAAsB,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CACZ,EAAU,EACV,UAAyB;QAEzB,OAAO,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,YAAY,CAAsB,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC;;AA9BH,kDA+BC;AA9BC,gDAAgD;AAChC,wBAAI,GAAG,yBAAyB,CAAC;AA+BnD;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,SAAoB;IACtD,OAAO,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,kBAAmB,SAAQ,mBAAmB;IAClD;;;OAGG;IACH,IAAY,aAAa;QACvB,OAAO,IAAI,CAAC,uBAAuB,CAAgB,6BAAa,CAAC,IAAI,CAAC,CAAC;IACzE,CAAC;
|
|
1
|
+
{"version":3,"file":"EditExampleStringUC.js","sourceRoot":"","sources":["../../../../src/ExampleFeature/UCs/EditExampleStringUC.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AA+CH,kDAEC;AA/CD,+CAAwE;AACxE,6DAA0D;AAE1D;;;GAGG;AACH,MAAsB,mBAAoB,SAAQ,uBAAW;IAU3D;;;;OAIG;IACH,MAAM,CAAC,GAAG,CAAC,MAAiB;QAC1B,OAAO,MAAM,CAAC,YAAY,CAAsB,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CACZ,EAAU,EACV,UAAyB;QAEzB,OAAO,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,YAAY,CAAsB,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC;;AA9BH,kDA+BC;AA9BC,gDAAgD;AAChC,wBAAI,GAAG,yBAAyB,CAAC;AA+BnD;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,SAAoB;IACtD,OAAO,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,kBAAmB,SAAQ,mBAAmB;IAClD;;;OAGG;IACH,IAAY,aAAa;QACvB,OAAO,IAAI,CAAC,uBAAuB,CAAgB,6BAAa,CAAC,IAAI,CAAC,CAAC;IACzE,CAAC;IAYD,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAX7C;;;WAGG;QACH,sBAAiB,GAAG,CAAC,IAAY,EAAE,EAAE;YAEnC,6EAA6E;YAC7E,IAAI,CAAC,aAAa,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5C,CAAC,CAAC;IAIF,CAAC;CACF","sourcesContent":["/**\r\n * EditExampleStringUC.ts\r\n * \r\n * This file demonstrates how to implement a Use Case (UC) component.\r\n * UCs handle business logic and operations that modify entities.\r\n * They encapsulate specific actions that can be performed in the application.\r\n * \r\n * Key concepts:\r\n * - UCs extend AppObjectUC and provide methods for specific operations\r\n * - They implement business logic for modifying entities\r\n * - They validate inputs and handle errors\r\n * - Each UC instance is associated with a specific AppObject\r\n * \r\n * Usage pattern:\r\n * 1. Get a UC instance using getById or get\r\n * 2. Call the UC's methods to perform operations\r\n * 3. The UC will update entities, which will trigger PM updates and UI refreshes\r\n */\r\n\r\nimport { AppObject, AppObjectRepo, AppObjectUC } from \"../../AppObject\";\r\nimport { ExampleEntity } from \"../Entities/ExampleEntity\";\r\n\r\n/**\r\n * EditExampleStringUC provides functionality to update the string property of an ExampleEntity.\r\n * Abstract class provides the interface and static helper methods.\r\n */\r\nexport abstract class EditExampleStringUC extends AppObjectUC {\r\n /** Unique type identifier for this component */\r\n static readonly type = \"EditExampleStringUCType\";\r\n\r\n /**\r\n * Updates the string property of the associated ExampleEntity\r\n * @param text The new string value to set\r\n */\r\n abstract editExampleString(text: string): void;\r\n\r\n /**\r\n * Retrieves an EditExampleStringUC component from an AppObject\r\n * @param appObj The AppObject to get the component from\r\n * @returns The EditExampleStringUC component or undefined if not found\r\n */\r\n static get(appObj: AppObject): EditExampleStringUC | undefined {\r\n return appObj.getComponent<EditExampleStringUC>(this.type);\r\n }\r\n\r\n /**\r\n * Retrieves an EditExampleStringUC by its parent AppObject's ID\r\n * @param id The ID of the parent AppObject\r\n * @param appObjects The AppObjectRepo to search in\r\n * @returns The EditExampleStringUC component or undefined if not found\r\n */\r\n static getById(\r\n id: string,\r\n appObjects: AppObjectRepo\r\n ): EditExampleStringUC | undefined {\r\n return appObjects.get(id)?.getComponent<EditExampleStringUC>(this.type);\r\n }\r\n}\r\n\r\n/**\r\n * Factory function to create a new EditExampleStringUC\r\n * @param appObject The AppObject to attach the UC to\r\n * @returns A new EditExampleStringUC instance\r\n */\r\nexport function makeEditSlideTextUC(appObject: AppObject): EditExampleStringUC {\r\n return new EditSlideTextUCImp(appObject);\r\n}\r\n\r\n/**\r\n * Concrete implementation of EditExampleStringUC\r\n * This private class handles the actual implementation details\r\n */\r\nclass EditSlideTextUCImp extends EditExampleStringUC {\r\n /**\r\n * Gets the ExampleEntity from the same AppObject\r\n * Uses getCachedLocalComponent for efficient repeated access\r\n */\r\n private get exampleEntity() {\r\n return this.getCachedLocalComponent<ExampleEntity>(ExampleEntity.type);\r\n }\r\n\r\n /**\r\n * Implements the editExampleString method to update the entity's string property\r\n * @param text The new string value to set\r\n */\r\n editExampleString = (text: string) => {\r\n\r\n // Update the entity property, which will trigger PM updates and UI refreshes\r\n this.exampleEntity.aStringProperty = text;\r\n };\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, EditExampleStringUC.type);\r\n }\r\n}\r\n"]}
|
|
@@ -27,7 +27,7 @@ const ExampleSingletonEntity_1 = require("../Entities/ExampleSingletonEntity");
|
|
|
27
27
|
* ToggleExampleBooleanUC provides functionality to toggle the boolean property
|
|
28
28
|
* of the SingletonEntityExample. As a singleton, only one instance exists in the application.
|
|
29
29
|
*/
|
|
30
|
-
class ToggleExampleBooleanUC extends AppObject_1.
|
|
30
|
+
class ToggleExampleBooleanUC extends AppObject_1.AppObjectSingletonUC {
|
|
31
31
|
}
|
|
32
32
|
exports.ToggleExampleBooleanUC = ToggleExampleBooleanUC;
|
|
33
33
|
/** Unique type identifier for this component */
|
|
@@ -64,16 +64,10 @@ class ToggleExampleBooleanUCImp extends ToggleExampleBooleanUC {
|
|
|
64
64
|
* Implements the toggleExampleBoolean method to invert the entity's boolean property
|
|
65
65
|
*/
|
|
66
66
|
this.toggleExampleBoolean = () => {
|
|
67
|
-
if (!this.singletonEntityExample) {
|
|
68
|
-
this.warn("Unable to find SingletonEntityExample");
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
67
|
// Toggle the boolean property by inverting its current value
|
|
72
68
|
this.singletonEntityExample.aBoolProperty =
|
|
73
|
-
!this.singletonEntityExample
|
|
69
|
+
!this.singletonEntityExample.aBoolProperty;
|
|
74
70
|
};
|
|
75
|
-
// Register this UC as a singleton so it can be accessed globally
|
|
76
|
-
this.appObjects.registerSingleton(this);
|
|
77
71
|
}
|
|
78
72
|
}
|
|
79
73
|
//# sourceMappingURL=ToggleExampleBooleanUC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToggleExampleBooleanUC.js","sourceRoot":"","sources":["../../../../src/ExampleFeature/UCs/ToggleExampleBooleanUC.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAuCH,gEAIC;AAzCD,+CAIyB;AACzB,iFAA8E;AAC9E,+EAA4E;AAE5E;;;GAGG;AACH,MAAsB,sBAAuB,SAAQ,
|
|
1
|
+
{"version":3,"file":"ToggleExampleBooleanUC.js","sourceRoot":"","sources":["../../../../src/ExampleFeature/UCs/ToggleExampleBooleanUC.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAuCH,gEAIC;AAzCD,+CAIyB;AACzB,iFAA8E;AAC9E,+EAA4E;AAE5E;;;GAGG;AACH,MAAsB,sBAAuB,SAAQ,gCAAoB;;AAAzE,wDAkBC;AAjBC,gDAAgD;AAChC,2BAAI,GAAG,4BAA4B,CAAC;AAOpD;;;;GAIG;AACI,0BAAG,GAAG,CACX,UAAyB,EACW,EAAE,CACtC,IAAA,6CAAqB,EAAC,sBAAsB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAGnE;;;;GAIG;AACH,SAAgB,0BAA0B,CACxC,SAAoB;IAEpB,OAAO,IAAI,yBAAyB,CAAC,SAAS,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,yBAA0B,SAAQ,sBAAsB;IAC5D;;;OAGG;IACH,IAAY,sBAAsB;QAChC,OAAO,IAAI,CAAC,kBAAkB,CAC5B,+CAAsB,CAAC,IAAI,CAC5B,CAAC;IACJ,CAAC;IAWD,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAVhD;;WAEG;QACH,yBAAoB,GAAG,GAAG,EAAE;YAC1B,6DAA6D;YAC7D,IAAI,CAAC,sBAAsB,CAAC,aAAa;gBACvC,CAAC,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAAC;QAC/C,CAAC,CAAC;IAIF,CAAC;CACF","sourcesContent":["/**\r\n * ToggleExampleBooleanUC.ts\r\n *\r\n * This file demonstrates how to implement a Singleton Use Case (UC) component.\r\n * Singleton UCs are special UCs that exist only once in the application and can be\r\n * accessed globally. They handle business logic and operations that modify singleton entities.\r\n *\r\n * Key concepts:\r\n * - Singleton UCs extend AppObjectUC like regular UCs\r\n * - They register themselves as singletons with appObjects.registerSingleton()\r\n * - They're accessed through a static get() method using getSingletonComponent()\r\n * - They typically operate on singleton entities\r\n *\r\n * Usage pattern:\r\n * 1. Access the singleton UC using the static get() method\r\n * 2. Call the UC's methods to perform operations\r\n * 3. The UC will update entities, which will trigger PM updates and UI refreshes\r\n */\r\n\r\nimport {\r\n AppObject,\r\n AppObjectRepo,\r\n AppObjectSingletonUC,\r\n} from \"../../AppObject\";\r\nimport { getSingletonComponent } from \"../../AppObject/getSingletonComponent\";\r\nimport { SingletonEntityExample } from \"../Entities/ExampleSingletonEntity\";\r\n\r\n/**\r\n * ToggleExampleBooleanUC provides functionality to toggle the boolean property\r\n * of the SingletonEntityExample. As a singleton, only one instance exists in the application.\r\n */\r\nexport abstract class ToggleExampleBooleanUC extends AppObjectSingletonUC {\r\n /** Unique type identifier for this component */\r\n static readonly type = \"ToggleExampleBooleanUCType\";\r\n\r\n /**\r\n * Toggles the boolean property of the SingletonEntityExample\r\n */\r\n abstract toggleExampleBoolean(): void;\r\n\r\n /**\r\n * Global accessor for the singleton UC\r\n * @param appObjects The AppObjectRepo to search in\r\n * @returns The singleton UC or undefined if not created yet\r\n */\r\n static get = (\r\n appObjects: AppObjectRepo\r\n ): ToggleExampleBooleanUC | undefined =>\r\n getSingletonComponent(ToggleExampleBooleanUC.type, appObjects);\r\n}\r\n\r\n/**\r\n * Factory function to create a new ToggleExampleBooleanUC\r\n * @param appObject The AppObject to attach the UC to\r\n * @returns A new ToggleExampleBooleanUC instance\r\n */\r\nexport function makeToggleExampleBooleanUC(\r\n appObject: AppObject\r\n): ToggleExampleBooleanUC {\r\n return new ToggleExampleBooleanUCImp(appObject);\r\n}\r\n\r\n/**\r\n * Concrete implementation of ToggleExampleBooleanUC\r\n * This private class handles the actual implementation details\r\n */\r\nclass ToggleExampleBooleanUCImp extends ToggleExampleBooleanUC {\r\n /**\r\n * Gets the SingletonEntityExample from the application\r\n * Uses getCachedSingleton for efficient repeated access\r\n */\r\n private get singletonEntityExample() {\r\n return this.getCachedSingleton<SingletonEntityExample>(\r\n SingletonEntityExample.type\r\n );\r\n }\r\n\r\n /**\r\n * Implements the toggleExampleBoolean method to invert the entity's boolean property\r\n */\r\n toggleExampleBoolean = () => {\r\n // Toggle the boolean property by inverting its current value\r\n this.singletonEntityExample.aBoolProperty =\r\n !this.singletonEntityExample.aBoolProperty;\r\n };\r\n\r\n constructor(appObject: AppObject) {\r\n super(appObject, ToggleExampleBooleanUC.type);\r\n }\r\n}\r\n"]}
|
|
@@ -42,17 +42,16 @@ export class AppObjectComponent {
|
|
|
42
42
|
* Results are cached for better performance in repeated calls
|
|
43
43
|
*
|
|
44
44
|
* @param type The component type identifier to look up
|
|
45
|
-
* @returns The singleton component cast to type T
|
|
45
|
+
* @returns The singleton component cast to type T
|
|
46
|
+
* @throws Error if the component is not found
|
|
46
47
|
*/
|
|
47
48
|
getCachedSingleton(type) {
|
|
48
49
|
if (!this.cachedComponents.has(type)) {
|
|
49
50
|
const component = this.appObjects.getSingleton(type);
|
|
50
51
|
if (!component) {
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
this.cachedComponents.set(type, component);
|
|
52
|
+
throw new Error("Unable to get cached singleton type " + type);
|
|
55
53
|
}
|
|
54
|
+
this.cachedComponents.set(type, component);
|
|
56
55
|
}
|
|
57
56
|
return this.cachedComponents.get(type);
|
|
58
57
|
}
|
|
@@ -61,17 +60,16 @@ export class AppObjectComponent {
|
|
|
61
60
|
* Results are cached for better performance in repeated calls
|
|
62
61
|
*
|
|
63
62
|
* @param type The component type identifier to look up
|
|
64
|
-
* @returns The component cast to type T
|
|
63
|
+
* @returns The component cast to type T
|
|
64
|
+
* @throws Error if the component is not found
|
|
65
65
|
*/
|
|
66
66
|
getCachedLocalComponent(type) {
|
|
67
67
|
if (!this.cachedComponents.has(type)) {
|
|
68
68
|
const component = this.appObject.getComponent(type);
|
|
69
69
|
if (!component) {
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
this.cachedComponents.set(type, component);
|
|
70
|
+
throw new Error("Unable to get local component of type " + type);
|
|
74
71
|
}
|
|
72
|
+
this.cachedComponents.set(type, component);
|
|
75
73
|
}
|
|
76
74
|
return this.cachedComponents.get(type);
|
|
77
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppObjectComponent.js","sourceRoot":"","sources":["../../../src/AppObject/AppObjectComponent.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAN,IAAY,sBAkBX;AAlBD,WAAY,sBAAsB;IAChC,2CAA2C;IAC3C,2CAAiB,CAAA;IAEjB,oDAAoD;IACpD,qDAA2B,CAAA;IAE3B,+DAA+D;IAC/D,yCAAe,CAAA;IAEf,8CAA8C;IAC9C,mDAAyB,CAAA;IAEzB,sEAAsE;IACtE,uCAAa,CAAA;IAEb,yEAAyE;IACzE,6CAAmB,CAAA;AACrB,CAAC,EAlBW,sBAAsB,KAAtB,sBAAsB,QAkBjC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,kBAAkB;
|
|
1
|
+
{"version":3,"file":"AppObjectComponent.js","sourceRoot":"","sources":["../../../src/AppObject/AppObjectComponent.ts"],"names":[],"mappings":"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","sourcesContent":["import { AppObject } from \"./AppObject\";\r\nimport { AppObjectRepo } from \"./AppObjectRepo\";\r\n\r\n/**\r\n * Enumeration of the different types of components in the architecture.\r\n * Each type serves a specific purpose in the application structure.\r\n */\r\nexport enum AppObjectComponentType {\r\n /** Stores and manages application state */\r\n ENTITY = \"Entity\",\r\n\r\n /** Transforms application state into view models */\r\n PM = \"Presentation Manager\",\r\n\r\n /** Implements business logic and coordinates between layers */\r\n UC = \"Use Case\",\r\n\r\n /** Handles user inputs and external events */\r\n CONTROLLER = \"Controller\",\r\n\r\n /** Renders UI elements and interacts with the DOM/rendering system */\r\n VIEW = \"View\",\r\n\r\n /** Default type for components that don't fit the standard categories */\r\n UNKNOWN = \"Unknown\",\r\n}\r\n\r\n/**\r\n * Base class for all components in the AppObject architecture.\r\n *\r\n * Components attach to AppObjects and provide specific functionality based on their type.\r\n * The architecture follows a clean separation of concerns, with each component type\r\n * having a well-defined responsibility in the application.\r\n *\r\n * Components can communicate with each other through various mechanisms:\r\n * - Direct access via parent AppObject\r\n * - Repository-level singleton access\r\n * - Observer patterns for reactive updates\r\n */\r\nexport class AppObjectComponent {\r\n /** The type category of this component */\r\n readonly componentType: AppObjectComponentType =\r\n AppObjectComponentType.UNKNOWN;\r\n\r\n /** Unique type identifier for this specific component */\r\n readonly type: string;\r\n\r\n /** The parent AppObject this component is attached to */\r\n readonly appObject: AppObject;\r\n\r\n /**\r\n * Convenience accessor for the repository containing all AppObjects\r\n * @returns The application's AppObjectRepo\r\n */\r\n get appObjects(): AppObjectRepo {\r\n return this.appObject.appObjectRepo;\r\n }\r\n\r\n /** Cache for components to avoid repeated lookups */\r\n private cachedComponents = new Map<string, AppObjectComponent>();\r\n\r\n /**\r\n * Retrieves a singleton component of the specified type from the repository\r\n * Results are cached for better performance in repeated calls\r\n *\r\n * @param type The component type identifier to look up\r\n * @returns The singleton component cast to type T\r\n * @throws Error if the component is not found\r\n */\r\n getCachedSingleton<T extends AppObjectComponent>(type: string): T {\r\n if (!this.cachedComponents.has(type)) {\r\n const component = this.appObjects.getSingleton(type);\r\n if (!component) {\r\n throw new Error(\"Unable to get cached singleton type \" + type);\r\n }\r\n this.cachedComponents.set(type, component);\r\n }\r\n\r\n return this.cachedComponents.get(type) as T;\r\n }\r\n\r\n /**\r\n * Retrieves a component from the same AppObject as this component\r\n * Results are cached for better performance in repeated calls\r\n *\r\n * @param type The component type identifier to look up\r\n * @returns The component cast to type T\r\n * @throws Error if the component is not found\r\n */\r\n getCachedLocalComponent<T extends AppObjectComponent>(type: string): T {\r\n if (!this.cachedComponents.has(type)) {\r\n const component = this.appObject.getComponent(type);\r\n\r\n if (!component) {\r\n throw new Error(\"Unable to get local component of type \" + type);\r\n }\r\n this.cachedComponents.set(type, component);\r\n }\r\n\r\n return this.cachedComponents.get(type) as T;\r\n }\r\n\r\n /**\r\n * Retrieves a singleton component from the repository with customizable logging\r\n * Unlike getCachedSingleton, results are not cached\r\n *\r\n * @param type The component type identifier to look up\r\n * @param logType The severity level for logging if component isn't found\r\n * @returns The singleton component cast to type T, or undefined if not found\r\n */\r\n getSingleton<T extends AppObjectComponent>(\r\n type: string,\r\n logType: \"LOG\" | \"WARN\" | \"ERROR\" = \"WARN\"\r\n ): T | undefined {\r\n const comp = this.appObjects.getSingleton<T>(type);\r\n\r\n if (!comp) {\r\n const msg = \"Unable to get singleton type \" + type;\r\n switch (logType) {\r\n case \"ERROR\":\r\n this.error(msg);\r\n break;\r\n case \"LOG\":\r\n this.log(msg);\r\n break;\r\n case \"WARN\":\r\n this.warn(msg);\r\n break;\r\n }\r\n }\r\n\r\n return comp;\r\n }\r\n\r\n /**\r\n * Cleans up resources used by this component\r\n * Removes itself from the parent AppObject if it's still attached\r\n */\r\n dispose() {\r\n if (this.appObject.getComponent(this.type) === this) {\r\n this.appObject.removeComponent(this.type);\r\n }\r\n }\r\n\r\n /**\r\n * Logs an informational message to the application's logging system\r\n * Messages are prefixed with the AppObject ID and component type for easier debugging\r\n *\r\n * @param message The message to log\r\n */\r\n log(message: string) {\r\n this.appObjects.submitLog(`${this.appObject.id}/${this.type}`, message);\r\n }\r\n\r\n /**\r\n * Logs a warning message to the application's logging system\r\n * Messages are prefixed with the AppObject ID and component type for easier debugging\r\n *\r\n * @param message The warning message to log\r\n */\r\n warn(message: string) {\r\n this.appObjects.submitWarning(`${this.appObject.id}/${this.type}`, message);\r\n }\r\n\r\n /**\r\n * Logs an error message to the application's logging system\r\n * Messages are prefixed with the AppObject ID and component type for easier debugging\r\n *\r\n * @param message The error message to log\r\n */\r\n error(message: string) {\r\n this.appObjects.submitError(`${this.appObject.id}/${this.type}`, message);\r\n }\r\n\r\n /**\r\n * Creates a new component and attaches it to the specified AppObject\r\n *\r\n * @param appObject The parent AppObject this component will be attached to\r\n * @param type The unique type identifier for this component\r\n */\r\n constructor(appObject: AppObject, type: string) {\r\n this.appObject = appObject;\r\n this.type = type;\r\n appObject.addComponent(this);\r\n }\r\n}\r\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ObserverList } from "../Entities";
|
|
2
|
+
import { generateUniqueID } from "../Utilities";
|
|
2
3
|
import { AppObjectEntity } from "./AppObjectEntity";
|
|
3
4
|
/**
|
|
4
5
|
* A repository for managing collections of AppObjectEntity instances.
|
|
@@ -7,20 +8,32 @@ import { AppObjectEntity } from "./AppObjectEntity";
|
|
|
7
8
|
* entities that are associated with specific AppObjects. It implements the observer
|
|
8
9
|
* pattern to notify listeners when entities are added or removed.
|
|
9
10
|
*
|
|
11
|
+
* Derived classes should override the `entityFactory` method to provide custom
|
|
12
|
+
* entity creation logic for the `create` method.
|
|
13
|
+
*
|
|
10
14
|
* @template T - The type of entities managed by this repository, must extend AppObjectEntity
|
|
11
15
|
* @extends AppObjectEntity
|
|
12
16
|
*
|
|
13
17
|
* @example
|
|
14
18
|
* ```typescript
|
|
15
|
-
* // Create a repository
|
|
16
|
-
*
|
|
19
|
+
* // Create a custom repository with entity factory
|
|
20
|
+
* class PlayerRepo extends AppObjectEntityRepo<PlayerEntity> {
|
|
21
|
+
* entityFactory(id: string): PlayerEntity {
|
|
22
|
+
* const appObject = makeAppObject(id, this.appObjects);
|
|
23
|
+
* return new PlayerEntity(appObject);
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* const playerRepo = new PlayerRepo(repoAppObject);
|
|
28
|
+
*
|
|
29
|
+
* // Create a new player with auto-generated ID
|
|
30
|
+
* const player = playerRepo.create();
|
|
17
31
|
*
|
|
18
|
-
* //
|
|
19
|
-
* const
|
|
20
|
-
* playerRepo.add(player);
|
|
32
|
+
* // Create a new player with specific ID
|
|
33
|
+
* const specificPlayer = playerRepo.create("player1");
|
|
21
34
|
*
|
|
22
|
-
* // Get a player by its
|
|
23
|
-
* const retrievedPlayer = playerRepo.
|
|
35
|
+
* // Get a player by its ID
|
|
36
|
+
* const retrievedPlayer = playerRepo.getById("player1");
|
|
24
37
|
* ```
|
|
25
38
|
*/
|
|
26
39
|
export class AppObjectEntityRepo extends AppObjectEntity {
|
|
@@ -61,23 +74,33 @@ export class AppObjectEntityRepo extends AppObjectEntity {
|
|
|
61
74
|
this.removeEntityRemovedObserver = (observer) => {
|
|
62
75
|
this.onEntityRemovedObservers.remove(observer);
|
|
63
76
|
};
|
|
77
|
+
/**
|
|
78
|
+
* Checks if an entity exists for the given ID.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} id - The ID of the AppObject
|
|
81
|
+
* @returns {boolean} True if an entity exists for the given ID, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
this.has = (id) => {
|
|
84
|
+
return this.entityLookup.has(id);
|
|
85
|
+
};
|
|
64
86
|
/**
|
|
65
87
|
* Checks if an entity exists for the given AppObject ID.
|
|
66
88
|
*
|
|
67
89
|
* @param {string} appObjectID - The ID of the AppObject
|
|
68
90
|
* @returns {boolean} True if an entity exists for the given AppObject ID, false otherwise
|
|
91
|
+
* @deprecated Use has instead
|
|
69
92
|
*/
|
|
70
93
|
this.hasForAppObject = (appObjectID) => {
|
|
71
|
-
return this.
|
|
94
|
+
return this.has(appObjectID);
|
|
72
95
|
};
|
|
73
96
|
/**
|
|
74
|
-
* Removes the entity associated with the specified
|
|
97
|
+
* Removes the entity associated with the specified ID.
|
|
75
98
|
*
|
|
76
99
|
* Notifies all registered observers after the entity is removed.
|
|
77
100
|
*
|
|
78
101
|
* @param {string} id - The ID of the AppObject whose entity should be removed
|
|
79
102
|
*/
|
|
80
|
-
this.
|
|
103
|
+
this.removeById = (id) => {
|
|
81
104
|
const existing = this.entityLookup.get(id);
|
|
82
105
|
if (!existing)
|
|
83
106
|
return;
|
|
@@ -86,14 +109,50 @@ export class AppObjectEntityRepo extends AppObjectEntity {
|
|
|
86
109
|
this.notifyOnChange();
|
|
87
110
|
this.onEntityRemovedObservers.notify(existing);
|
|
88
111
|
};
|
|
112
|
+
/**
|
|
113
|
+
* Removes the entity associated with the specified AppObject ID.
|
|
114
|
+
*
|
|
115
|
+
* Notifies all registered observers after the entity is removed.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} id - The ID of the AppObject whose entity should be removed
|
|
118
|
+
* @deprecated Use removeById instead
|
|
119
|
+
*/
|
|
120
|
+
this.removeForAppObject = (id) => {
|
|
121
|
+
this.removeById(id);
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Removes all entities from the repository.
|
|
125
|
+
*
|
|
126
|
+
* Unsubscribes from all entity change observers and notifies all registered
|
|
127
|
+
* removal observers for each entity before clearing the repository.
|
|
128
|
+
*/
|
|
129
|
+
this.deleteAll = () => {
|
|
130
|
+
const entities = Array.from(this.entityLookup.values());
|
|
131
|
+
entities.forEach((entity) => {
|
|
132
|
+
entity.removeChangeObserver(this.notifyOnChange);
|
|
133
|
+
this.onEntityRemovedObservers.notify(entity);
|
|
134
|
+
});
|
|
135
|
+
this.entityLookup.clear();
|
|
136
|
+
this.notifyOnChange();
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Gets the entity associated with the specified ID.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} id - The ID of the AppObject
|
|
142
|
+
* @returns {T | undefined} The entity if found, undefined otherwise
|
|
143
|
+
*/
|
|
144
|
+
this.getById = (id) => {
|
|
145
|
+
return this.entityLookup.get(id);
|
|
146
|
+
};
|
|
89
147
|
/**
|
|
90
148
|
* Gets the entity associated with the specified AppObject ID.
|
|
91
149
|
*
|
|
92
150
|
* @param {string} appObjectID - The ID of the AppObject
|
|
93
151
|
* @returns {T | undefined} The entity if found, undefined otherwise
|
|
152
|
+
* @deprecated Use getById instead
|
|
94
153
|
*/
|
|
95
154
|
this.getForAppObject = (appObjectID) => {
|
|
96
|
-
return this.
|
|
155
|
+
return this.getById(appObjectID);
|
|
97
156
|
};
|
|
98
157
|
/**
|
|
99
158
|
* Gets all entities in the repository.
|
|
@@ -103,6 +162,19 @@ export class AppObjectEntityRepo extends AppObjectEntity {
|
|
|
103
162
|
this.getAll = () => {
|
|
104
163
|
return Array.from(this.entityLookup.values());
|
|
105
164
|
};
|
|
165
|
+
/**
|
|
166
|
+
* Gets an entity by ID, or creates it if it doesn't exist.
|
|
167
|
+
*
|
|
168
|
+
* @param {string} id - The ID of the entity to get or create
|
|
169
|
+
* @returns {T} The existing or newly created entity
|
|
170
|
+
*/
|
|
171
|
+
this.getOrCreate = (id) => {
|
|
172
|
+
const existing = this.getById(id);
|
|
173
|
+
if (existing) {
|
|
174
|
+
return existing;
|
|
175
|
+
}
|
|
176
|
+
return this.create(id);
|
|
177
|
+
};
|
|
106
178
|
}
|
|
107
179
|
/**
|
|
108
180
|
* Adds an entity to the repository.
|
|
@@ -122,5 +194,35 @@ export class AppObjectEntityRepo extends AppObjectEntity {
|
|
|
122
194
|
this.notifyOnChange();
|
|
123
195
|
this.onEntityAddedObservers.notify(entity);
|
|
124
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Creates a new entity with the specified or auto-generated ID and adds it to the repository.
|
|
199
|
+
*
|
|
200
|
+
* This method uses the `entityFactory` method to create the entity instance.
|
|
201
|
+
* If no ID is provided, a unique ID is generated automatically.
|
|
202
|
+
*
|
|
203
|
+
* @param {string} [id] - Optional ID for the entity. If not provided, a unique ID is generated.
|
|
204
|
+
* @returns {T} The newly created entity
|
|
205
|
+
*/
|
|
206
|
+
create(id) {
|
|
207
|
+
const idToUse = id ?? generateUniqueID();
|
|
208
|
+
const ao = this.appObjects.getOrCreate(idToUse);
|
|
209
|
+
const entity = this.entityFactory(ao);
|
|
210
|
+
this.add(entity);
|
|
211
|
+
return entity;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Factory method for creating entity instances.
|
|
215
|
+
*
|
|
216
|
+
* This method must be overridden in derived classes to provide custom entity creation logic.
|
|
217
|
+
* It is called by the `create` method to instantiate new entities.
|
|
218
|
+
*
|
|
219
|
+
* @param {string} id - The ID to use for the new entity
|
|
220
|
+
* @returns {T} A new entity instance
|
|
221
|
+
* @throws {Error} If not overridden in derived class
|
|
222
|
+
*/
|
|
223
|
+
entityFactory(appObject) {
|
|
224
|
+
// Override this method in derived classes to provide entity creation logic
|
|
225
|
+
throw new Error("Entity factory not implemented.");
|
|
226
|
+
}
|
|
125
227
|
}
|
|
126
228
|
//# sourceMappingURL=AppObjectEntityRepo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppObjectEntityRepo.js","sourceRoot":"","sources":["../../../src/AppObject/AppObjectEntityRepo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,mBAEX,SAAQ,eAAe;IAFzB;;QAGU,iBAAY,GAAG,IAAI,GAAG,EAAa,CAAC;QAEpC,2BAAsB,GAAG,IAAI,YAAY,EAAK,CAAC;QACvD;;;;WAIG;QACH,2BAAsB,GAAG,CAAC,QAAkC,EAAE,EAAE;YAC9D,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF;;;;WAIG;QACH,8BAAyB,GAAG,CAAC,QAAkC,EAAQ,EAAE;YACvE,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC,CAAC;QAEM,6BAAwB,GAAG,IAAI,YAAY,EAAK,CAAC;QACzD;;;;WAIG;QACH,6BAAwB,GAAG,CAAC,QAAoC,EAAE,EAAE;YAClE,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF;;;;WAIG;QACH,gCAA2B,GAAG,CAC5B,QAAoC,EAC9B,EAAE;YACR,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC,CAAC;QAEF;;;;;WAKG;QACH,oBAAe,GAAG,CAAC,WAAmB,EAAW,EAAE;YACjD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC5C,CAAC,CAAC;QAsBF;;;;;;WAMG;QACH,uBAAkB,GAAG,CAAC,EAAU,EAAE,EAAE;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3C,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAEtB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC7B,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnD,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC,CAAC;QAEF;;;;;WAKG;QACH,oBAAe,GAAG,CAAC,WAAmB,EAAiB,EAAE;YACvD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF;;;;WAIG;QACH,WAAM,GAAG,GAAQ,EAAE;YACjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAChD,CAAC,CAAC;IACJ,CAAC;IAvDC;;;;;;;OAOG;IACH,GAAG,CAAC,MAAS;QACX,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC5D,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9C,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;CAqCF","sourcesContent":["import { ObserverList } from \"../Entities\";\r\nimport { AppObjectEntity } from \"./AppObjectEntity\";\r\n\r\n/**\r\n * A repository for managing collections of AppObjectEntity instances.\r\n *\r\n * This generic class provides a centralized way to store, retrieve, and manage\r\n * entities that are associated with specific AppObjects. It implements the observer\r\n * pattern to notify listeners when entities are added or removed.\r\n *\r\n * @template T - The type of entities managed by this repository, must extend AppObjectEntity\r\n * @extends AppObjectEntity\r\n *\r\n * @example\r\n * ```typescript\r\n * // Create a repository for player entities\r\n * const playerRepo = new AppObjectEntityRepo<PlayerEntity>();\r\n *\r\n * // Add a new player\r\n * const player = new PlayerEntity(appObject);\r\n * playerRepo.add(player);\r\n *\r\n * // Get a player by its AppObject ID\r\n * const retrievedPlayer = playerRepo.getForAppObject(\"player1\");\r\n * ```\r\n */\r\nexport class AppObjectEntityRepo<\r\n T extends AppObjectEntity,\r\n> extends AppObjectEntity {\r\n private entityLookup = new Map<string, T>();\r\n\r\n private onEntityAddedObservers = new ObserverList<T>();\r\n /**\r\n * Registers an observer to be notified when an entity is added to the repository.\r\n *\r\n * @param {(addedEntity: T) => void} observer - The callback function to invoke when an entity is added\r\n */\r\n addEntityAddedObserver = (observer: (addedEntity: T) => void) => {\r\n this.onEntityAddedObservers.add(observer);\r\n };\r\n\r\n /**\r\n * Removes an observer previously registered for entity addition notifications.\r\n *\r\n * @param {(addedEntity: T) => void} observer - The callback function to remove\r\n */\r\n removeEntityAddedObserver = (observer: (addedEntity: T) => void): void => {\r\n this.onEntityAddedObservers.remove(observer);\r\n };\r\n\r\n private onEntityRemovedObservers = new ObserverList<T>();\r\n /**\r\n * Registers an observer to be notified when an entity is removed from the repository.\r\n *\r\n * @param {(removedEntity: T) => void} observer - The callback function to invoke when an entity is removed\r\n */\r\n addEntityRemovedObserver = (observer: (removedEntity: T) => void) => {\r\n this.onEntityRemovedObservers.add(observer);\r\n };\r\n\r\n /**\r\n * Removes an observer previously registered for entity removal notifications.\r\n *\r\n * @param {(removedEntity: T) => void} observer - The callback function to remove\r\n */\r\n removeEntityRemovedObserver = (\r\n observer: (removedEntity: T) => void\r\n ): void => {\r\n this.onEntityRemovedObservers.remove(observer);\r\n };\r\n\r\n /**\r\n * Checks if an entity exists for the given AppObject ID.\r\n *\r\n * @param {string} appObjectID - The ID of the AppObject\r\n * @returns {boolean} True if an entity exists for the given AppObject ID, false otherwise\r\n */\r\n hasForAppObject = (appObjectID: string): boolean => {\r\n return this.entityLookup.has(appObjectID);\r\n };\r\n\r\n /**\r\n * Adds an entity to the repository.\r\n *\r\n * If an entity with the same AppObject ID already exists, it is replaced.\r\n * Notifies all registered observers after the entity is added.\r\n *\r\n * @param {T} entity - The entity to add\r\n */\r\n add(entity: T) {\r\n const existing = this.entityLookup.get(entity.appObject.id);\r\n if (existing) {\r\n existing.removeChangeObserver(this.notifyOnChange);\r\n }\r\n\r\n this.entityLookup.set(entity.appObject.id, entity);\r\n entity.addChangeObserver(this.notifyOnChange);\r\n this.notifyOnChange();\r\n this.onEntityAddedObservers.notify(entity);\r\n }\r\n\r\n /**\r\n * Removes the entity associated with the specified AppObject ID.\r\n *\r\n * Notifies all registered observers after the entity is removed.\r\n *\r\n * @param {string} id - The ID of the AppObject whose entity should be removed\r\n */\r\n removeForAppObject = (id: string) => {\r\n const existing = this.entityLookup.get(id);\r\n if (!existing) return;\r\n\r\n this.entityLookup.delete(id);\r\n existing.removeChangeObserver(this.notifyOnChange);\r\n this.notifyOnChange();\r\n this.onEntityRemovedObservers.notify(existing);\r\n };\r\n\r\n /**\r\n * Gets the entity associated with the specified AppObject ID.\r\n *\r\n * @param {string} appObjectID - The ID of the AppObject\r\n * @returns {T | undefined} The entity if found, undefined otherwise\r\n */\r\n getForAppObject = (appObjectID: string): T | undefined => {\r\n return this.entityLookup.get(appObjectID);\r\n };\r\n\r\n /**\r\n * Gets all entities in the repository.\r\n *\r\n * @returns {T[]} An array of all entities\r\n */\r\n getAll = (): T[] => {\r\n return Array.from(this.entityLookup.values());\r\n };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"AppObjectEntityRepo.js","sourceRoot":"","sources":["../../../src/AppObject/AppObjectEntityRepo.ts"],"names":[],"mappings":"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","sourcesContent":["import { ObserverList } from \"../Entities\";\r\nimport { generateUniqueID } from \"../Utilities\";\r\nimport { AppObject } from \"./AppObject\";\r\nimport { AppObjectEntity } from \"./AppObjectEntity\";\r\n\r\n/**\r\n * A repository for managing collections of AppObjectEntity instances.\r\n *\r\n * This generic class provides a centralized way to store, retrieve, and manage\r\n * entities that are associated with specific AppObjects. It implements the observer\r\n * pattern to notify listeners when entities are added or removed.\r\n *\r\n * Derived classes should override the `entityFactory` method to provide custom\r\n * entity creation logic for the `create` method.\r\n *\r\n * @template T - The type of entities managed by this repository, must extend AppObjectEntity\r\n * @extends AppObjectEntity\r\n *\r\n * @example\r\n * ```typescript\r\n * // Create a custom repository with entity factory\r\n * class PlayerRepo extends AppObjectEntityRepo<PlayerEntity> {\r\n * entityFactory(id: string): PlayerEntity {\r\n * const appObject = makeAppObject(id, this.appObjects);\r\n * return new PlayerEntity(appObject);\r\n * }\r\n * }\r\n *\r\n * const playerRepo = new PlayerRepo(repoAppObject);\r\n *\r\n * // Create a new player with auto-generated ID\r\n * const player = playerRepo.create();\r\n *\r\n * // Create a new player with specific ID\r\n * const specificPlayer = playerRepo.create(\"player1\");\r\n *\r\n * // Get a player by its ID\r\n * const retrievedPlayer = playerRepo.getById(\"player1\");\r\n * ```\r\n */\r\nexport class AppObjectEntityRepo<\r\n T extends AppObjectEntity,\r\n> extends AppObjectEntity {\r\n private entityLookup = new Map<string, T>();\r\n\r\n private onEntityAddedObservers = new ObserverList<T>();\r\n /**\r\n * Registers an observer to be notified when an entity is added to the repository.\r\n *\r\n * @param {(addedEntity: T) => void} observer - The callback function to invoke when an entity is added\r\n */\r\n addEntityAddedObserver = (observer: (addedEntity: T) => void) => {\r\n this.onEntityAddedObservers.add(observer);\r\n };\r\n\r\n /**\r\n * Removes an observer previously registered for entity addition notifications.\r\n *\r\n * @param {(addedEntity: T) => void} observer - The callback function to remove\r\n */\r\n removeEntityAddedObserver = (observer: (addedEntity: T) => void): void => {\r\n this.onEntityAddedObservers.remove(observer);\r\n };\r\n\r\n private onEntityRemovedObservers = new ObserverList<T>();\r\n /**\r\n * Registers an observer to be notified when an entity is removed from the repository.\r\n *\r\n * @param {(removedEntity: T) => void} observer - The callback function to invoke when an entity is removed\r\n */\r\n addEntityRemovedObserver = (observer: (removedEntity: T) => void) => {\r\n this.onEntityRemovedObservers.add(observer);\r\n };\r\n\r\n /**\r\n * Removes an observer previously registered for entity removal notifications.\r\n *\r\n * @param {(removedEntity: T) => void} observer - The callback function to remove\r\n */\r\n removeEntityRemovedObserver = (\r\n observer: (removedEntity: T) => void\r\n ): void => {\r\n this.onEntityRemovedObservers.remove(observer);\r\n };\r\n\r\n /**\r\n * Checks if an entity exists for the given ID.\r\n *\r\n * @param {string} id - The ID of the AppObject\r\n * @returns {boolean} True if an entity exists for the given ID, false otherwise\r\n */\r\n has = (id: string): boolean => {\r\n return this.entityLookup.has(id);\r\n };\r\n\r\n /**\r\n * Checks if an entity exists for the given AppObject ID.\r\n *\r\n * @param {string} appObjectID - The ID of the AppObject\r\n * @returns {boolean} True if an entity exists for the given AppObject ID, false otherwise\r\n * @deprecated Use has instead\r\n */\r\n hasForAppObject = (appObjectID: string): boolean => {\r\n return this.has(appObjectID);\r\n };\r\n\r\n /**\r\n * Adds an entity to the repository.\r\n *\r\n * If an entity with the same AppObject ID already exists, it is replaced.\r\n * Notifies all registered observers after the entity is added.\r\n *\r\n * @param {T} entity - The entity to add\r\n */\r\n add(entity: T) {\r\n const existing = this.entityLookup.get(entity.appObject.id);\r\n if (existing) {\r\n existing.removeChangeObserver(this.notifyOnChange);\r\n }\r\n\r\n this.entityLookup.set(entity.appObject.id, entity);\r\n entity.addChangeObserver(this.notifyOnChange);\r\n this.notifyOnChange();\r\n this.onEntityAddedObservers.notify(entity);\r\n }\r\n\r\n /**\r\n * Creates a new entity with the specified or auto-generated ID and adds it to the repository.\r\n *\r\n * This method uses the `entityFactory` method to create the entity instance.\r\n * If no ID is provided, a unique ID is generated automatically.\r\n *\r\n * @param {string} [id] - Optional ID for the entity. If not provided, a unique ID is generated.\r\n * @returns {T} The newly created entity\r\n */\r\n create(id?: string): T {\r\n const idToUse = id ?? generateUniqueID();\r\n const ao = this.appObjects.getOrCreate(idToUse);\r\n const entity = this.entityFactory(ao);\r\n this.add(entity);\r\n return entity;\r\n }\r\n\r\n /**\r\n * Factory method for creating entity instances.\r\n *\r\n * This method must be overridden in derived classes to provide custom entity creation logic.\r\n * It is called by the `create` method to instantiate new entities.\r\n *\r\n * @param {string} id - The ID to use for the new entity\r\n * @returns {T} A new entity instance\r\n * @throws {Error} If not overridden in derived class\r\n */\r\n entityFactory(appObject: AppObject): T {\r\n // Override this method in derived classes to provide entity creation logic\r\n throw new Error(\"Entity factory not implemented.\");\r\n }\r\n\r\n /**\r\n * Removes the entity associated with the specified ID.\r\n *\r\n * Notifies all registered observers after the entity is removed.\r\n *\r\n * @param {string} id - The ID of the AppObject whose entity should be removed\r\n */\r\n removeById = (id: string) => {\r\n const existing = this.entityLookup.get(id);\r\n if (!existing) return;\r\n\r\n this.entityLookup.delete(id);\r\n existing.removeChangeObserver(this.notifyOnChange);\r\n this.notifyOnChange();\r\n this.onEntityRemovedObservers.notify(existing);\r\n };\r\n\r\n /**\r\n * Removes the entity associated with the specified AppObject ID.\r\n *\r\n * Notifies all registered observers after the entity is removed.\r\n *\r\n * @param {string} id - The ID of the AppObject whose entity should be removed\r\n * @deprecated Use removeById instead\r\n */\r\n removeForAppObject = (id: string) => {\r\n this.removeById(id);\r\n };\r\n\r\n /**\r\n * Removes all entities from the repository.\r\n *\r\n * Unsubscribes from all entity change observers and notifies all registered\r\n * removal observers for each entity before clearing the repository.\r\n */\r\n deleteAll = () => {\r\n const entities = Array.from(this.entityLookup.values());\r\n\r\n entities.forEach((entity) => {\r\n entity.removeChangeObserver(this.notifyOnChange);\r\n this.onEntityRemovedObservers.notify(entity);\r\n });\r\n\r\n this.entityLookup.clear();\r\n this.notifyOnChange();\r\n };\r\n\r\n /**\r\n * Gets the entity associated with the specified ID.\r\n *\r\n * @param {string} id - The ID of the AppObject\r\n * @returns {T | undefined} The entity if found, undefined otherwise\r\n */\r\n getById = (id: string): T | undefined => {\r\n return this.entityLookup.get(id);\r\n };\r\n\r\n /**\r\n * Gets the entity associated with the specified AppObject ID.\r\n *\r\n * @param {string} appObjectID - The ID of the AppObject\r\n * @returns {T | undefined} The entity if found, undefined otherwise\r\n * @deprecated Use getById instead\r\n */\r\n getForAppObject = (appObjectID: string): T | undefined => {\r\n return this.getById(appObjectID);\r\n };\r\n\r\n /**\r\n * Gets all entities in the repository.\r\n *\r\n * @returns {T[]} An array of all entities\r\n */\r\n getAll = (): T[] => {\r\n return Array.from(this.entityLookup.values());\r\n };\r\n\r\n /**\r\n * Gets an entity by ID, or creates it if it doesn't exist.\r\n *\r\n * @param {string} id - The ID of the entity to get or create\r\n * @returns {T} The existing or newly created entity\r\n */\r\n getOrCreate = (id: string): T => {\r\n const existing = this.getById(id);\r\n if (existing) {\r\n return existing;\r\n }\r\n return this.create(id);\r\n };\r\n}\r\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ObserverList } from "../Entities";
|
|
2
|
-
import { AppObjectComponent, AppObjectComponentType } from "./AppObjectComponent";
|
|
2
|
+
import { AppObjectComponent, AppObjectComponentType, } from "./AppObjectComponent";
|
|
3
3
|
/**
|
|
4
4
|
* Presentation Manager (PM) component that transforms application state into view models
|
|
5
5
|
*
|
|
@@ -21,13 +21,21 @@ export class AppObjectPM extends AppObjectComponent {
|
|
|
21
21
|
/** Identifies this as a Presentation Manager component */
|
|
22
22
|
this.componentType = AppObjectComponentType.PM;
|
|
23
23
|
/** List of view update functions to notify when the view model changes */
|
|
24
|
-
this.
|
|
24
|
+
this.views = new ObserverList();
|
|
25
|
+
/**
|
|
26
|
+
* List of entities being observed by this PM.
|
|
27
|
+
* Used for automatic cleanup during disposal.
|
|
28
|
+
*/
|
|
29
|
+
this.observedEntities = [];
|
|
25
30
|
}
|
|
26
31
|
/**
|
|
27
32
|
* Gets the most recently generated view model
|
|
28
|
-
* @returns The last view model or
|
|
33
|
+
* @returns The last view model, or `defaultVM` if no view model has been generated yet,
|
|
34
|
+
* or undefined if neither exists
|
|
29
35
|
*/
|
|
30
36
|
get lastVM() {
|
|
37
|
+
if (!this._lastVM)
|
|
38
|
+
return this.defaultVM;
|
|
31
39
|
return this._lastVM;
|
|
32
40
|
}
|
|
33
41
|
/**
|
|
@@ -37,11 +45,92 @@ export class AppObjectPM extends AppObjectComponent {
|
|
|
37
45
|
* @param updateView Function to call with updated view models
|
|
38
46
|
*/
|
|
39
47
|
addView(updateView) {
|
|
40
|
-
this.
|
|
48
|
+
if (this.views.length === 0) {
|
|
49
|
+
// There are no views yet - generate the initial view model
|
|
50
|
+
this.formVM();
|
|
51
|
+
}
|
|
52
|
+
this.views.add(updateView);
|
|
41
53
|
// Immediately update the view with current view model if one exists
|
|
42
54
|
if (this._lastVM !== undefined) {
|
|
43
55
|
updateView(this._lastVM);
|
|
44
56
|
}
|
|
57
|
+
this.onViewAdded();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Called when an observed entity changes.
|
|
61
|
+
* If views are registered, this method calls `formVM()` to regenerate the view model.
|
|
62
|
+
*
|
|
63
|
+
* This method is automatically invoked when entities registered via `observeEntity()`
|
|
64
|
+
* notify their observers. It implements lazy evaluation - view models are only
|
|
65
|
+
* formed when there are views to receive them.
|
|
66
|
+
*/
|
|
67
|
+
onEntityChanged() {
|
|
68
|
+
if (this.views.length === 0) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.formVM();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Forms and updates the view model based on current entity state.
|
|
77
|
+
*
|
|
78
|
+
* Override this method in derived classes to:
|
|
79
|
+
* 1. Read data from observed entities
|
|
80
|
+
* 2. Transform the data into a view model
|
|
81
|
+
* 3. Call `doUpdateView(vm)` with the new view model
|
|
82
|
+
*
|
|
83
|
+
* This method is only called when at least one view has been registered,
|
|
84
|
+
* implementing lazy evaluation to avoid unnecessary computation.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* formVM(): void {
|
|
89
|
+
* const entity = this.getCachedLocalComponent<MyEntity>(MyEntity.type);
|
|
90
|
+
* if (entity) {
|
|
91
|
+
* this.doUpdateView({
|
|
92
|
+
* displayName: entity.name,
|
|
93
|
+
* isActive: entity.active
|
|
94
|
+
* });
|
|
95
|
+
* }
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
formVM() {
|
|
100
|
+
// To be implemented by derived classes
|
|
101
|
+
// Form up the VM and then call doUpdateView(vm: T)
|
|
102
|
+
// This will only be called if at least one view has been registered
|
|
103
|
+
}
|
|
104
|
+
onViewAdded() {
|
|
105
|
+
// Can be overridden by derived classes to react when the first view is added
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Registers an entity to be observed for changes.
|
|
109
|
+
*
|
|
110
|
+
* When the entity notifies of changes (via `notifyOnChange()`), this PM will
|
|
111
|
+
* automatically call `onEntityChanged()`, which in turn calls `formVM()` if
|
|
112
|
+
* views are registered.
|
|
113
|
+
*
|
|
114
|
+
* The entity observer is automatically cleaned up when this PM is disposed.
|
|
115
|
+
*
|
|
116
|
+
* @param entity The entity to observe for changes
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* constructor(appObj: AppObject) {
|
|
121
|
+
* super(appObj, MyPM.type);
|
|
122
|
+
* const entity = appObj.getComponent<MyEntity>(MyEntity.type);
|
|
123
|
+
* if (entity) {
|
|
124
|
+
* this.observeEntity(entity);
|
|
125
|
+
* }
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
observeEntity(entity) {
|
|
130
|
+
entity.addChangeObserver(() => {
|
|
131
|
+
this.onEntityChanged();
|
|
132
|
+
});
|
|
133
|
+
this.observedEntities.push(entity);
|
|
45
134
|
}
|
|
46
135
|
/**
|
|
47
136
|
* Unregisters a previously added view update function
|
|
@@ -49,7 +138,7 @@ export class AppObjectPM extends AppObjectComponent {
|
|
|
49
138
|
* @param updateView The view update function to remove
|
|
50
139
|
*/
|
|
51
140
|
removeView(updateView) {
|
|
52
|
-
this.
|
|
141
|
+
this.views.remove(updateView);
|
|
53
142
|
}
|
|
54
143
|
/**
|
|
55
144
|
* Updates the view model and notifies all registered views if the model has changed
|
|
@@ -66,13 +155,24 @@ export class AppObjectPM extends AppObjectComponent {
|
|
|
66
155
|
return;
|
|
67
156
|
}
|
|
68
157
|
this._lastVM = vm;
|
|
69
|
-
this.
|
|
158
|
+
this.views.notify(vm);
|
|
70
159
|
}
|
|
71
160
|
/**
|
|
72
161
|
* Cleans up resources and detaches this PM from its parent AppObject
|
|
162
|
+
*
|
|
163
|
+
* This method:
|
|
164
|
+
* 1. Removes change observers from all observed entities
|
|
165
|
+
* 2. Clears all view observers
|
|
166
|
+
* 3. Removes this component from its parent AppObject if still attached
|
|
167
|
+
* 4. Calls the parent class dispose method
|
|
73
168
|
*/
|
|
74
169
|
dispose() {
|
|
75
|
-
this.
|
|
170
|
+
this.observedEntities.forEach((entity) => {
|
|
171
|
+
entity.removeChangeObserver(() => {
|
|
172
|
+
this.onEntityChanged();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
this.views.clear();
|
|
76
176
|
if (this.appObject.getComponent(this.type) === this) {
|
|
77
177
|
this.appObject.removeComponent(this.type);
|
|
78
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppObjectPM.js","sourceRoot":"","sources":["../../../src/AppObject/AppObjectPM.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"AppObjectPM.js","sourceRoot":"","sources":["../../../src/AppObject/AppObjectPM.ts"],"names":[],"mappings":"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","sourcesContent":["import { ObserverList } from \"../Entities\";\r\nimport {\r\n AppObjectComponent,\r\n AppObjectComponentType,\r\n} from \"./AppObjectComponent\";\r\nimport { AppObjectEntity } from \"./AppObjectEntity\";\r\n\r\n/**\r\n * Presentation Manager (PM) component that transforms application state into view models\r\n *\r\n * AppObjectPM acts as a mediator between application state (entities) and views.\r\n * It transforms raw application data into a format that's optimized for presentation,\r\n * implementing the presentation model or MVVM pattern.\r\n *\r\n * A PM typically:\r\n * 1. Observes entity changes\r\n * 2. Transforms entity data into view models\r\n * 3. Notifies attached views when view models change\r\n * 4. Handles view model caching and optimization\r\n *\r\n * @typeparam T The view model type this PM produces\r\n */\r\nexport abstract class AppObjectPM<T> extends AppObjectComponent {\r\n /** Identifies this as a Presentation Manager component */\r\n readonly componentType = AppObjectComponentType.PM;\r\n\r\n /**\r\n * Compares two view models to determine if they're equivalent\r\n * Used to prevent unnecessary view updates when the view model hasn't changed\r\n *\r\n * @param a First view model to compare\r\n * @param b Second view model to compare\r\n * @returns True if the view models are considered equal, false otherwise\r\n */\r\n abstract vmsAreEqual(a: T, b: T): boolean;\r\n\r\n /** The most recently generated view model */\r\n private _lastVM?: T;\r\n\r\n /**\r\n * Optional default view model to return when no view model has been generated yet.\r\n * If set, this value will be returned by the `lastVM` getter before any view model\r\n * has been created via `doUpdateView`.\r\n *\r\n * This is useful for providing initial state to views without requiring immediate\r\n * view model generation.\r\n */\r\n public defaultVM?: T;\r\n\r\n /**\r\n * Gets the most recently generated view model\r\n * @returns The last view model, or `defaultVM` if no view model has been generated yet,\r\n * or undefined if neither exists\r\n */\r\n get lastVM(): T | undefined {\r\n if (!this._lastVM) return this.defaultVM;\r\n return this._lastVM;\r\n }\r\n\r\n /** List of view update functions to notify when the view model changes */\r\n private views = new ObserverList<T>();\r\n\r\n /**\r\n * List of entities being observed by this PM.\r\n * Used for automatic cleanup during disposal.\r\n */\r\n private observedEntities: AppObjectEntity[] = [];\r\n\r\n /**\r\n * Registers a view update function to be called when the view model changes\r\n * If a view model already exists, the provided function is called immediately with that model\r\n *\r\n * @param updateView Function to call with updated view models\r\n */\r\n addView(updateView: (vm: T) => void): void {\r\n if (this.views.length === 0) {\r\n // There are no views yet - generate the initial view model\r\n this.formVM();\r\n }\r\n\r\n this.views.add(updateView);\r\n \r\n // Immediately update the view with current view model if one exists\r\n if (this._lastVM !== undefined) {\r\n updateView(this._lastVM);\r\n }\r\n\r\n this.onViewAdded();\r\n }\r\n\r\n /**\r\n * Called when an observed entity changes.\r\n * If views are registered, this method calls `formVM()` to regenerate the view model.\r\n *\r\n * This method is automatically invoked when entities registered via `observeEntity()`\r\n * notify their observers. It implements lazy evaluation - view models are only\r\n * formed when there are views to receive them.\r\n */\r\n onEntityChanged(): void {\r\n if (this.views.length === 0) {\r\n return;\r\n } else {\r\n this.formVM();\r\n }\r\n }\r\n\r\n /**\r\n * Forms and updates the view model based on current entity state.\r\n *\r\n * Override this method in derived classes to:\r\n * 1. Read data from observed entities\r\n * 2. Transform the data into a view model\r\n * 3. Call `doUpdateView(vm)` with the new view model\r\n *\r\n * This method is only called when at least one view has been registered,\r\n * implementing lazy evaluation to avoid unnecessary computation.\r\n *\r\n * @example\r\n * ```typescript\r\n * formVM(): void {\r\n * const entity = this.getCachedLocalComponent<MyEntity>(MyEntity.type);\r\n * if (entity) {\r\n * this.doUpdateView({\r\n * displayName: entity.name,\r\n * isActive: entity.active\r\n * });\r\n * }\r\n * }\r\n * ```\r\n */\r\n formVM(): void {\r\n // To be implemented by derived classes\r\n // Form up the VM and then call doUpdateView(vm: T)\r\n // This will only be called if at least one view has been registered\r\n }\r\n\r\n onViewAdded(): void {\r\n // Can be overridden by derived classes to react when the first view is added\r\n }\r\n\r\n /**\r\n * Registers an entity to be observed for changes.\r\n *\r\n * When the entity notifies of changes (via `notifyOnChange()`), this PM will\r\n * automatically call `onEntityChanged()`, which in turn calls `formVM()` if\r\n * views are registered.\r\n *\r\n * The entity observer is automatically cleaned up when this PM is disposed.\r\n *\r\n * @param entity The entity to observe for changes\r\n *\r\n * @example\r\n * ```typescript\r\n * constructor(appObj: AppObject) {\r\n * super(appObj, MyPM.type);\r\n * const entity = appObj.getComponent<MyEntity>(MyEntity.type);\r\n * if (entity) {\r\n * this.observeEntity(entity);\r\n * }\r\n * }\r\n * ```\r\n */\r\n protected observeEntity(entity: AppObjectEntity): void {\r\n entity.addChangeObserver(() => {\r\n this.onEntityChanged();\r\n });\r\n\r\n this.observedEntities.push(entity);\r\n }\r\n\r\n /**\r\n * Unregisters a previously added view update function\r\n *\r\n * @param updateView The view update function to remove\r\n */\r\n removeView(updateView: (vm: T) => void): void {\r\n this.views.remove(updateView);\r\n }\r\n\r\n /**\r\n * Updates the view model and notifies all registered views if the model has changed\r\n * This method should be called by derived classes when the view model needs to be updated\r\n *\r\n * The method performs equality checking to prevent unnecessary updates when\r\n * the new view model is equivalent to the previous one\r\n *\r\n * @param vm The new view model\r\n */\r\n doUpdateView(vm: T) {\r\n // Skip update if the view model hasn't changed\r\n if (this._lastVM && this.vmsAreEqual(this._lastVM, vm)) {\r\n return;\r\n }\r\n\r\n this._lastVM = vm;\r\n this.views.notify(vm);\r\n }\r\n\r\n /**\r\n * Cleans up resources and detaches this PM from its parent AppObject\r\n *\r\n * This method:\r\n * 1. Removes change observers from all observed entities\r\n * 2. Clears all view observers\r\n * 3. Removes this component from its parent AppObject if still attached\r\n * 4. Calls the parent class dispose method\r\n */\r\n dispose() {\r\n this.observedEntities.forEach((entity) => {\r\n entity.removeChangeObserver(() => {\r\n this.onEntityChanged();\r\n });\r\n });\r\n\r\n this.views.clear();\r\n if (this.appObject.getComponent(this.type) === this) {\r\n this.appObject.removeComponent(this.type);\r\n }\r\n super.dispose();\r\n }\r\n}\r\n"]}
|
|
@@ -122,10 +122,13 @@ class AppObjectRepoImp extends AppObjectRepo {
|
|
|
122
122
|
}
|
|
123
123
|
registerSingleton(component) {
|
|
124
124
|
if (this.singletons.has(component.type)) {
|
|
125
|
-
this.submitWarning("AppObjectRepo", `Singleton for type ${component.type} already exists.
|
|
125
|
+
this.submitWarning("AppObjectRepo", `Singleton for type ${component.type} already exists. Replacing`);
|
|
126
126
|
}
|
|
127
127
|
this.singletons.set(component.type, component);
|
|
128
128
|
}
|
|
129
|
+
unregisterSingleton(type) {
|
|
130
|
+
this.singletons.delete(type);
|
|
131
|
+
}
|
|
129
132
|
hasSingleton(type) {
|
|
130
133
|
if (this.singletons.has(type)) {
|
|
131
134
|
return true;
|