├── .gitignore ├── .gitattributes ├── docs ├── .nojekyll └── assets │ ├── navigation.js │ └── highlight.css ├── jest.config.js ├── bin ├── esm │ ├── interfaces │ │ ├── IView.js │ │ ├── IFacade.js │ │ ├── IModel.js │ │ ├── IProxy.js │ │ ├── ICommand.js │ │ ├── IMediator.js │ │ ├── INotifier.js │ │ ├── IObserver.js │ │ ├── IController.js │ │ └── INotification.js │ ├── index.js │ ├── patterns │ │ ├── command │ │ │ ├── SimpleCommand.js │ │ │ └── MacroCommand.js │ │ ├── observer │ │ │ ├── Notifier.js │ │ │ ├── Observer.js │ │ │ └── Notification.js │ │ ├── proxy │ │ │ └── Proxy.js │ │ └── mediator │ │ │ └── Mediator.js │ └── core │ │ └── Model.js ├── cjs │ ├── interfaces │ │ ├── IView.js │ │ ├── IFacade.js │ │ ├── IModel.js │ │ ├── IProxy.js │ │ ├── ICommand.js │ │ ├── IMediator.js │ │ ├── INotifier.js │ │ ├── IObserver.js │ │ ├── IController.js │ │ └── INotification.js │ ├── patterns │ │ ├── command │ │ │ ├── SimpleCommand.js │ │ │ └── MacroCommand.js │ │ ├── observer │ │ │ ├── Notifier.js │ │ │ ├── Observer.js │ │ │ └── Notification.js │ │ ├── proxy │ │ │ └── Proxy.js │ │ └── mediator │ │ │ └── Mediator.js │ ├── index.js │ └── core │ │ └── Model.js └── types │ ├── interfaces │ ├── ICommand.d.ts │ ├── INotifier.d.ts │ ├── IProxy.d.ts │ ├── IModel.d.ts │ ├── INotification.d.ts │ ├── IController.d.ts │ ├── IObserver.d.ts │ ├── IMediator.d.ts │ ├── IView.d.ts │ └── IFacade.d.ts │ ├── patterns │ ├── command │ │ ├── SimpleCommand.d.ts │ │ └── MacroCommand.d.ts │ ├── observer │ │ ├── Notifier.d.ts │ │ ├── Observer.d.ts │ │ └── Notification.d.ts │ ├── proxy │ │ └── Proxy.d.ts │ └── mediator │ │ └── Mediator.d.ts │ ├── index.d.ts │ └── core │ ├── Model.d.ts │ └── Controller.d.ts ├── tsconfig.json ├── VERSION ├── test ├── patterns │ ├── facade │ │ ├── FacadeTestVO.ts │ │ └── FacadeTestCommand.ts │ ├── command │ │ ├── SimpleCommandTestVO.ts │ │ ├── MacroCommandTestVO.ts │ │ ├── SimpleCommandTestCommand.ts │ │ ├── MacroCommandTestSub1Command.ts │ │ ├── MacroCommandTestCommand.ts │ │ ├── MacroCommandTestSub2Command.ts │ │ ├── SimpleCommand.spec.ts │ │ └── MacroCommand.spec.ts │ ├── observer │ │ ├── Notifier.spec.ts │ │ ├── Notification.spec.ts │ │ └── Observer.spec.ts │ ├── mediator │ │ └── Mediator.spec.ts │ └── proxy │ │ └── Proxy.spec.ts └── core │ ├── ControllerTestVO.ts │ ├── ViewTestMediator.ts │ ├── ModelTestProxy.ts │ ├── ViewTestMediator4.ts │ ├── ViewTestMediator6.ts │ ├── ControllerTestCommand.ts │ ├── ControllerTestCommand2.ts │ ├── ViewTestMediator5.ts │ ├── ViewTestNote.ts │ ├── ViewTestMediator3.ts │ ├── ViewTestMediator2.ts │ └── Model.spec.ts ├── src ├── interfaces │ ├── ICommand.ts │ ├── INotifier.ts │ ├── IProxy.ts │ ├── IModel.ts │ ├── INotification.ts │ ├── IController.ts │ ├── IObserver.ts │ ├── IMediator.ts │ ├── IView.ts │ └── IFacade.ts ├── index.ts ├── patterns │ ├── command │ │ ├── SimpleCommand.ts │ │ └── MacroCommand.ts │ ├── observer │ │ ├── Notifier.ts │ │ ├── Observer.ts │ │ └── Notification.ts │ ├── proxy │ │ └── Proxy.ts │ └── mediator │ │ └── Mediator.ts └── core │ └── Model.ts ├── .github └── workflows │ └── node.js.yml ├── .eslintrc.js ├── LICENSE ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | bin/** linguist-vendored 2 | *.js linguist-vendored -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest", 3 | testEnvironment: "node", 4 | testMatch: ["**/__tests__/**/*.ts?(x)", "**/?(*.)+(spec|test).ts?(x)"], 5 | maxWorkers: 11, 6 | }; 7 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IView.js: -------------------------------------------------------------------------------- 1 | // 2 | // IView.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IFacade.js: -------------------------------------------------------------------------------- 1 | // 2 | // IFacade.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IModel.js: -------------------------------------------------------------------------------- 1 | // 2 | // IModel.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IProxy.js: -------------------------------------------------------------------------------- 1 | // 2 | // IProxy.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/ICommand.js: -------------------------------------------------------------------------------- 1 | // 2 | // ICommand.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IMediator.js: -------------------------------------------------------------------------------- 1 | // 2 | // IMediator.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/INotifier.js: -------------------------------------------------------------------------------- 1 | // 2 | // INotifier.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IObserver.js: -------------------------------------------------------------------------------- 1 | // 2 | // IObserver.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/IController.js: -------------------------------------------------------------------------------- 1 | // 2 | // IController.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/esm/interfaces/INotification.js: -------------------------------------------------------------------------------- 1 | // 2 | // INotification.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export {}; 9 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IView.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IView.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IFacade.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IFacade.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IModel.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IModel.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IProxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IProxy.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/ICommand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // ICommand.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IMediator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IMediator.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/INotifier.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // INotifier.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IObserver.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IObserver.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/IController.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // IController.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /bin/cjs/interfaces/INotification.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // INotification.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | -------------------------------------------------------------------------------- /docs/assets/navigation.js: -------------------------------------------------------------------------------- 1 | window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE4WSQUsDMRBG/8ucF4sFRfZaEHrQCoKX0kNMpjSYzZQk2Ir0v8sqq0lmNl7z8V6W7Nt+QsJzgh5W5FMg5zBAB0eVDtCDdipGjIu/7eqQBgcdvFlvoL9e3l26X8O90sogp3/OW+SD0oFWNAzKG87na9OCxqpEwvdPS5Mmg05Ax+MW90jJ7q1WyZLneL7+b5Heflpa9OY1YniX6Glp0U+Bzh8c/T5ucc92ODqc/W3F3PK8WDxxfDxtUWt2sfUJw15pjIu1eO3y5rYU8OJLh1x9pamzzxVS+hXOq80Fcrm1oky34Hm+FSz3mzvmGxZVc88ph1wpeMm5Qq65UlQ557yQdAWXLeYs73FEd18SpZQwQQUAAA==" -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "moduleResolution": "node", 5 | "strict": true, 6 | "declaration": true, 7 | "declarationDir": "bin/types", 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["src/**/*"], 12 | "exclude": ["docs", "node_modules", "bin", "test"], 13 | "typedocOptions": { 14 | "entryPoints": ["src/index.ts"], 15 | "out": "docs" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | PureMVC Standard Framework for TypeScript 2 | -------------------------------------------------------------------------- 3 | Release Date: 11/03/24 4 | Platform: TypeScript 5 | Version: 2 6 | Revision: 0 7 | Minor: 0 8 | Authors: Saad Shams 9 | -------------------------------------------------------------------------- 10 | 2.0.0 - Brand new implementation of ported code, equivalent to AS3 Standard Version 2.0.4. 11 | -------------------------------------------------------------------------------- /bin/types/interfaces/ICommand.d.ts: -------------------------------------------------------------------------------- 1 | import { INotifier } from "./INotifier"; 2 | import { INotification } from "./INotification"; 3 | /** 4 | * The interface definition for a PureMVC Command. 5 | * 6 | * @see {@link INotification} 7 | * 8 | * @interface ICommand 9 | * @extends {INotifier} 10 | */ 11 | export interface ICommand extends INotifier { 12 | /** 13 | * Execute the `ICommand`'s logic to handle a given `INotification`. 14 | * 15 | * @param {INotification} notification - The notification carrying the data and type necessary for executing the command. 16 | * @returns {void} 17 | */ 18 | execute(notification: INotification): void; 19 | } 20 | -------------------------------------------------------------------------------- /test/patterns/facade/FacadeTestVO.ts: -------------------------------------------------------------------------------- 1 | // 2 | // FacadeTestVO.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | /** 10 | * A utility class used by FacadeTest. 11 | * 12 | * @class FacadeTestVO 13 | */ 14 | export class FacadeTestVO { 15 | 16 | public input: number; 17 | public result: number = 0; 18 | 19 | 20 | /** 21 | * @constructor 22 | * @param {number} input the number to be fed to the FacadeTestCommand 23 | */ 24 | public constructor(input: number) { 25 | this.input = input; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /test/core/ControllerTestVO.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ControllerTestVO.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | /** 10 | * A utility class used by ControllerTest. 11 | * 12 | * @see ControllerTest 13 | * @see ControllerTestCommand 14 | * 15 | * @class ControllerTestVO 16 | */ 17 | export class ControllerTestVO { 18 | 19 | public input: number = 0; 20 | public result: number = 0; 21 | 22 | /** 23 | * Constructor 24 | * 25 | * @param {number} input 26 | */ 27 | public constructor(input: number) { 28 | this.input = input; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /test/patterns/command/SimpleCommandTestVO.ts: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleCommandTestVO.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | /** 10 | * A utility class used by SimpleCommandTest. 11 | * 12 | * @see SimpleCommandTest 13 | * @see SimpleCommandTestCommand 14 | * 15 | * @class SimpleCommandTestVO 16 | */ 17 | export class SimpleCommandTestVO { 18 | 19 | public input: number; 20 | public result: number | undefined; 21 | 22 | /** 23 | * Constructor. 24 | * 25 | * @param {number} input the number to be fed to the SimpleCommandTestCommand 26 | */ 27 | public constructor(input: number) { 28 | this.input = input; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bin/esm/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // index.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | export { Controller } from "./core/Controller"; 9 | export { Model } from "./core/Model"; 10 | export { View } from "./core/View"; 11 | export { MacroCommand } from "./patterns/command/MacroCommand"; 12 | export { SimpleCommand } from "./patterns/command/SimpleCommand"; 13 | export { Facade } from "./patterns/facade/Facade"; 14 | export { Mediator } from "./patterns/mediator/Mediator"; 15 | export { Notification } from "./patterns/observer/Notification"; 16 | export { Notifier } from "./patterns/observer/Notifier"; 17 | export { Observer } from "./patterns/observer/Observer"; 18 | export { Proxy } from "./patterns/proxy/Proxy"; 19 | -------------------------------------------------------------------------------- /src/interfaces/ICommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ICommand.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotifier} from "./INotifier"; 10 | import {INotification} from "./INotification"; 11 | 12 | /** 13 | * The interface definition for a PureMVC Command. 14 | * 15 | * @see {@link INotification} 16 | * 17 | * @interface ICommand 18 | * @extends {INotifier} 19 | */ 20 | export interface ICommand extends INotifier { 21 | /** 22 | * Execute the `ICommand`'s logic to handle a given `INotification`. 23 | * 24 | * @param {INotification} notification - The notification carrying the data and type necessary for executing the command. 25 | * @returns {void} 26 | */ 27 | execute(notification: INotification): void; 28 | } 29 | -------------------------------------------------------------------------------- /test/patterns/command/MacroCommandTestVO.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommandTestVO.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | /** 10 | * A utility class used by MacroCommandTest. 11 | * 12 | * @see MacroCommandTest 13 | * @see MacroCommandTestCommand 14 | * @see MacroCommandTestSub1Command 15 | * @see MacroCommandTestSub2Command 16 | * 17 | * @class MacroCommandTestVO 18 | */ 19 | export class MacroCommandTestVO { 20 | 21 | public input: number; 22 | public result1: number | undefined; 23 | public result2: number | undefined; 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param {number} input the number to be fed to the MacroCommandTestCommand 29 | */ 30 | constructor(input: number) { 31 | this.input = input; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /test/core/ViewTestMediator.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestMediator.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Mediator} from "../../src"; 10 | 11 | /** 12 | * A Mediator class used by ViewTest. 13 | * 14 | * @class ViewTestMediator 15 | * @extends Mediator 16 | */ 17 | export class ViewTestMediator extends Mediator { 18 | 19 | public static NAME = "ViewTestMediator"; 20 | 21 | /** 22 | * @param {any} view 23 | */ 24 | public constructor(view: any) { 25 | super(ViewTestMediator.NAME, view); 26 | } 27 | 28 | public override listNotificationInterests(): string[] { 29 | // be sure that the mediator has some Observers created 30 | // in order to test removeMediator 31 | return ["ABC", "DEF", "GHI"]; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /test/core/ModelTestProxy.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ModelTestProxy.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Proxy} from "../../src"; 10 | 11 | /** 12 | * @class ModelTestProxy 13 | * @extends Proxy 14 | */ 15 | export class ModelTestProxy extends Proxy { 16 | 17 | public static NAME: string = "ModelTestProxy"; 18 | public static ON_REGISTER_CALLED: string = "OnRegisterCalled"; 19 | public static ON_REMOVE_CALLED: string = "OnRemoveCalled"; 20 | 21 | public constructor() { 22 | super(ModelTestProxy.NAME, ""); 23 | } 24 | 25 | public override onRegister(): void { 26 | this.data = ModelTestProxy.ON_REGISTER_CALLED; 27 | } 28 | 29 | public override onRemove(): void { 30 | this.data = ModelTestProxy.ON_REMOVE_CALLED; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /test/core/ViewTestMediator4.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestMediator4.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Mediator} from "../../src"; 10 | 11 | /** 12 | * @class ViewTestMediator4 13 | * @extends Mediator 14 | */ 15 | export class ViewTestMediator4 extends Mediator { 16 | 17 | public static NAME: string = "ViewTestMediator4"; 18 | 19 | /** 20 | * Constructor 21 | * @param {Object} view 22 | */ 23 | public constructor(view: any) { 24 | super(ViewTestMediator4.NAME, view); 25 | } 26 | 27 | /** 28 | * @override 29 | */ 30 | public onRegister() { 31 | this.viewComponent.onRegisterCalled = true; 32 | } 33 | 34 | /** 35 | * @override 36 | */ 37 | public onRemove() { 38 | this.viewComponent.onRemoveCalled = true; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /test/patterns/observer/Notifier.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Notifier.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Facade, Notifier} from "../../../src"; 10 | import {FacadeTestVO} from "../facade/FacadeTestVO"; 11 | import {FacadeTestCommand} from "../facade/FacadeTestCommand"; 12 | 13 | /** 14 | * Test the PureMVC Notifier class. 15 | * 16 | * @see Facade 17 | */ 18 | describe("NotifierTest", () => { 19 | 20 | test("test", () => { 21 | const facade = Facade.getInstance(() => new Facade()); 22 | 23 | const vo = new FacadeTestVO(5); 24 | facade.registerCommand("testCommand", () => new FacadeTestCommand()); 25 | 26 | const notifier = new Notifier(); 27 | notifier.sendNotification("testCommand", vo); 28 | 29 | // test assertions 30 | expect(vo.result).toBe(10); 31 | }); 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [20.x, 21.x, 22.x] 19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | cache: 'npm' 28 | - run: npm ci 29 | - run: npm run build --if-present 30 | - run: npm test 31 | -------------------------------------------------------------------------------- /test/core/ViewTestMediator6.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestMediator6.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Mediator, INotification} from "../../src"; 10 | import {ViewTestNote} from "./ViewTestNote"; 11 | 12 | /** 13 | * @class ViewTestMediator6 14 | * @extends Mediator 15 | */ 16 | export class ViewTestMediator6 extends Mediator { 17 | 18 | public static NAME: string = "ViewTestMediator6"; 19 | 20 | public constructor(name: string, view: any) { 21 | super(name, view); 22 | } 23 | 24 | public override listNotificationInterests(): string[] { 25 | return [ViewTestNote.NOTE6]; 26 | } 27 | 28 | public handleNotification(notification: INotification) { 29 | this.facade.removeMediator(this.name); 30 | } 31 | 32 | public override onRemove() { 33 | this.viewComponent.counter++; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /test/core/ControllerTestCommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ControllerTestCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {SimpleCommand, INotification} from "../../src"; 10 | import {ControllerTestVO} from "./ControllerTestVO"; 11 | 12 | /** 13 | * A SimpleCommand subclass used by ControllerTest. 14 | * 15 | * @see ControllerTest 16 | * @see ControllerTestVO 17 | * 18 | * @class ControllerTestCommand 19 | * @extends SimpleCommand 20 | */ 21 | export class ControllerTestCommand extends SimpleCommand { 22 | 23 | /** 24 | * Fabricate a result by multiplying the input by 2 25 | * 26 | * @param notification the note carrying the ControllerTestVO 27 | */ 28 | public override execute(notification: INotification) { 29 | const vo = notification.body as ControllerTestVO; 30 | 31 | // Fabricate a result 32 | vo.result = 2 * vo.input; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /test/patterns/facade/FacadeTestCommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // FacadeTestCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {SimpleCommand, INotification} from "../../../src"; 10 | import {FacadeTestVO} from "./FacadeTestVO"; 11 | 12 | /** 13 | * A SimpleCommand subclass used by FacadeTest. 14 | * 15 | * @see FacadeTest 16 | * @see FacadeTestVO 17 | * 18 | * @class FacadeTestCommand 19 | * @extends SimpleCommand 20 | */ 21 | export class FacadeTestCommand extends SimpleCommand { 22 | 23 | /** 24 | * Fabricate a result by multiplying the input by 2 25 | * 26 | * @param {Notification} notification the Notification carrying the FacadeTestVO 27 | */ 28 | public override execute(notification: INotification): void { 29 | const vo: FacadeTestVO = notification.body as FacadeTestVO; 30 | 31 | // Fabricate a result 32 | vo.result = vo.input * 2; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /test/patterns/command/SimpleCommandTestCommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleCommandTestCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {SimpleCommand, INotification} from "../../../src"; 10 | import {SimpleCommandTestVO} from "./SimpleCommandTestVO"; 11 | 12 | /** 13 | * A SimpleCommand subclass used by SimpleCommandTest. 14 | * 15 | * @class SimpleCommandTestCommand 16 | * @extends SimpleCommand 17 | */ 18 | export class SimpleCommandTestCommand extends SimpleCommand { 19 | 20 | /** 21 | * Fabricate a result by multiplying the input by 2 22 | * 23 | * @param {Notification} notification event the `INotification` carrying the `SimpleCommandTestVO` 24 | */ 25 | execute(notification: INotification): void { 26 | const vo: SimpleCommandTestVO = notification.body as SimpleCommandTestVO; 27 | 28 | // Fabricate a result 29 | vo.result = vo.input * 2; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /test/core/ControllerTestCommand2.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ControllerTestCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {SimpleCommand, INotification} from "../../src"; 10 | import {ControllerTestVO} from "./ControllerTestVO"; 11 | 12 | /** 13 | * A SimpleCommand subclass used by ControllerTest. 14 | * 15 | * @see ControllerTest 16 | * @see ControllerTestVO 17 | * 18 | * @class ControllerTestCommand2 19 | * @extends SimpleCommand 20 | */ 21 | export class ControllerTestCommand2 extends SimpleCommand { 22 | 23 | /** 24 | * Fabricate a result by multiplying the input by 2 and adding to the existing result 25 | * 26 | * @param {Notification} notification 27 | */ 28 | public override execute(notification: INotification): void { 29 | const vo = notification.body as ControllerTestVO; 30 | 31 | // Fabricate a result 32 | vo.result = vo.result + (2 * vo.input); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /test/core/ViewTestMediator5.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestMediator5.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Mediator, INotification} from "../../src"; 10 | import {ViewTestNote} from "./ViewTestNote"; 11 | 12 | /** 13 | * @class ViewTestMediator5 14 | * @extends Mediator 15 | */ 16 | export class ViewTestMediator5 extends Mediator { 17 | 18 | public static NAME: string = "ViewTestMediator5"; 19 | 20 | /** 21 | * 22 | * @param {Object} view 23 | */ 24 | public constructor(view: any) { 25 | super(ViewTestMediator5.NAME, view); 26 | } 27 | 28 | /** 29 | * @override 30 | * @returns {[string]} 31 | */ 32 | public override listNotificationInterests(): string[] { 33 | return [ViewTestNote.NOTE5]; 34 | } 35 | 36 | /** 37 | * @override 38 | * @param {Notification} notification 39 | */ 40 | public override handleNotification(notification: INotification): void { 41 | this.viewComponent.counter++; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /test/patterns/command/MacroCommandTestSub1Command.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommandTestSub1Command.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {SimpleCommand, INotification} from "../../../src"; 10 | import {MacroCommandTestVO} from "./MacroCommandTestVO"; 11 | 12 | /** 13 | * A SimpleCommand subclass used by MacroCommandTestCommand. 14 | * 15 | * @see MacroCommandTest 16 | * @see MacroCommandTestCommand 17 | * @see MacroCommandTestVO 18 | * 19 | * @class MacroCommandTestSub1Command 20 | * @extends SimpleCommand 21 | */ 22 | export class MacroCommandTestSub1Command extends SimpleCommand { 23 | 24 | /** 25 | * Fabricate a result by multiplying the input by 2 26 | * 27 | * @param {Notification} notification event the `IEvent` carrying the `MacroCommandTestVO` 28 | */ 29 | public override execute(notification: INotification) { 30 | const vo = notification.body as MacroCommandTestVO; 31 | 32 | // Fabricate a result 33 | vo.result1 = 2 * vo.input; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /test/patterns/command/MacroCommandTestCommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommandTestCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {MacroCommand} from "../../../src"; 10 | import {MacroCommandTestSub1Command} from "./MacroCommandTestSub1Command"; 11 | import {MacroCommandTestSub2Command} from "./MacroCommandTestSub2Command"; 12 | 13 | /** 14 | * A MacroCommand subclass used by MacroCommandTest. 15 | * 16 | * @see MacroCommandTest 17 | * @see MacroCommandTestSub1Command 18 | * @see MacroCommandTestSub2Command 19 | * @see MacroCommandTestVO 20 | * 21 | * @class MacroCommandTestCommand 22 | * @extends MacroCommand 23 | */ 24 | export class MacroCommandTestCommand extends MacroCommand { 25 | 26 | /** 27 | * Initialize the MacroCommandTestCommand by adding 28 | * its 2 SubCommands. 29 | */ 30 | public override initializeMacroCommand() { 31 | this.addSubCommand(() => new MacroCommandTestSub1Command()); 32 | this.addSubCommand(() => new MacroCommandTestSub2Command()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /test/core/ViewTestNote.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestNote.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Notification} from "../../src"; 10 | 11 | export class ViewTestNote extends Notification { 12 | 13 | public static NAME: string = "ViewTestNote"; 14 | 15 | public static NOTE1: string = "Notification1"; 16 | public static NOTE2: string = "Notification2"; 17 | public static NOTE3: string = "Notification3"; 18 | public static NOTE4: string = "Notification4"; 19 | public static NOTE5: string = "Notification5"; 20 | public static NOTE6: string = "Notification6"; 21 | 22 | /** 23 | * 24 | * @param {string} name 25 | * @param {Object} body 26 | */ 27 | public constructor(name: string, body: any) { 28 | super(name, body); 29 | } 30 | 31 | /** 32 | * 33 | * @param {Object} body 34 | * @returns {ViewTestNote} 35 | */ 36 | public static create(body: any): Notification { 37 | return new ViewTestNote(ViewTestNote.NAME, body); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /test/core/ViewTestMediator3.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestMediator3.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Mediator, INotification} from "../../src"; 10 | import {ViewTestNote} from "./ViewTestNote"; 11 | 12 | /** 13 | * @class ViewTestMediator3 14 | * @extends Mediator 15 | */ 16 | export class ViewTestMediator3 extends Mediator { 17 | 18 | public static NAME: string = "ViewTestMediator3"; 19 | 20 | /** 21 | * @constructor 22 | * @param {object} view 23 | */ 24 | public constructor(view: any) { 25 | super(ViewTestMediator3.NAME, view); 26 | } 27 | 28 | public listNotificationInterests(): string[] { 29 | // be sure that the mediator has some Observers created 30 | // in order to test removeMediator 31 | return [ViewTestNote.NOTE3]; 32 | } 33 | 34 | /** 35 | * @override 36 | * @param notification 37 | */ 38 | handleNotification(notification: INotification) { 39 | this.viewComponent.lastNotification = notification.name; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /test/patterns/command/MacroCommandTestSub2Command.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommandTestSub2Command.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {SimpleCommand, INotification} from "../../../src"; 10 | import {MacroCommandTestVO} from "./MacroCommandTestVO"; 11 | 12 | /** 13 | * A SimpleCommand subclass used by MacroCommandTestCommand. 14 | * 15 | * @see MacroCommandTest 16 | * @see MacroCommandTestCommand 17 | * @see MacroCommandTestVO 18 | * 19 | * @class MacroCommandTestSub2Command 20 | * @extends SimpleCommand 21 | */ 22 | export class MacroCommandTestSub2Command extends SimpleCommand { 23 | 24 | /** 25 | * Fabricate a result by multiplying the input by itself 26 | * 27 | * @param {Notification} notification event the `IEvent` carrying the `MacroCommandTestVO` 28 | */ 29 | public override execute(notification: INotification) { 30 | const vo: MacroCommandTestVO = notification.body as MacroCommandTestVO; 31 | 32 | // Fabricate a result 33 | vo.result2 = vo.input * vo.input; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /test/core/ViewTestMediator2.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTestMediator2.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotification, Mediator} from "../../src"; 10 | import {ViewTestNote} from "./ViewTestNote"; 11 | 12 | /** 13 | * @class ViewTestMediator2 14 | * @extends Mediator 15 | */ 16 | export class ViewTestMediator2 extends Mediator { 17 | 18 | public static NAME: string = "ViewTestMediator2"; 19 | 20 | /** 21 | * Constructor 22 | * 23 | * @constructor 24 | * @param view 25 | */ 26 | public constructor(view: any) { 27 | super(ViewTestMediator2.NAME, view); 28 | } 29 | 30 | /** 31 | * @override 32 | * @returns {[string]} 33 | */ 34 | public override listNotificationInterests(): string[] { 35 | return [ViewTestNote.NOTE1, ViewTestNote.NOTE2]; 36 | } 37 | 38 | /** 39 | * @override 40 | * @param notification 41 | */ 42 | public override handleNotification(notification: INotification) { 43 | this.viewComponent.lastNotification = notification.name; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /bin/types/patterns/command/SimpleCommand.d.ts: -------------------------------------------------------------------------------- 1 | import { ICommand } from "../../interfaces/ICommand"; 2 | import { INotification } from "../../interfaces/INotification"; 3 | import { Notifier } from "../observer/Notifier"; 4 | /** 5 | * A base `Command` implementation. 6 | * 7 | * Your subclass should override the `execute` 8 | * method where your business logic will handle the `Notification`. 9 | * 10 | * @see {@link Controller} 11 | * @see {@link Notification} 12 | * @see {@link MacroCommand} 13 | * 14 | * @class SimpleCommand 15 | * @extends Notifier 16 | */ 17 | export declare class SimpleCommand extends Notifier implements ICommand { 18 | /** 19 | * Fulfill the use-case initiated by the given `Notification`. 20 | * 21 | * In the Command Pattern, an application use-case typically 22 | * begins with some user action, which results in a `Notification` being broadcast, which 23 | * is handled by business logic in the `execute` method of an 24 | * `Command`. 25 | * 26 | * @param {INotification} notification - The notification containing the data or command details to be processed. 27 | * @returns {void} 28 | */ 29 | execute(notification: INotification): void; 30 | } 31 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/recommended" 10 | ], 11 | "overrides": [ 12 | { 13 | "env": { 14 | "node": true 15 | }, 16 | "files": [ 17 | ".eslintrc.{js,cjs}" 18 | ], 19 | "parserOptions": { 20 | "sourceType": "script" 21 | } 22 | } 23 | ], 24 | "parser": "@typescript-eslint/parser", 25 | "parserOptions": { 26 | "ecmaVersion": "latest" 27 | }, 28 | "plugins": [ 29 | "@typescript-eslint" 30 | ], 31 | "rules": { 32 | "@typescript-eslint/no-explicit-any": "off", 33 | "indent": [ 34 | "error", 35 | 4 36 | ], 37 | "linebreak-style": [ 38 | "error", 39 | "unix" 40 | ], 41 | "quotes": [ 42 | "error", 43 | "double" 44 | ], 45 | "semi": [ 46 | "error", 47 | "always" 48 | ] 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /bin/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export type { IController } from "./interfaces/IController"; 2 | export type { IModel } from "./interfaces/IModel"; 3 | export type { IView } from "./interfaces/IView"; 4 | export type { ICommand } from "./interfaces/ICommand"; 5 | export type { IFacade } from "./interfaces/IFacade"; 6 | export type { IMediator } from "./interfaces/IMediator"; 7 | export type { INotification } from "./interfaces/INotification"; 8 | export type { INotifier } from "./interfaces/INotifier"; 9 | export type { IObserver } from "./interfaces/IObserver"; 10 | export type { IProxy } from "./interfaces/IProxy"; 11 | export { Controller } from "./core/Controller"; 12 | export { Model } from "./core/Model"; 13 | export { View } from "./core/View"; 14 | export { MacroCommand } from "./patterns/command/MacroCommand"; 15 | export { SimpleCommand } from "./patterns/command/SimpleCommand"; 16 | export { Facade } from "./patterns/facade/Facade"; 17 | export { Mediator } from "./patterns/mediator/Mediator"; 18 | export { Notification } from "./patterns/observer/Notification"; 19 | export { Notifier } from "./patterns/observer/Notifier"; 20 | export { Observer } from "./patterns/observer/Observer"; 21 | export { Proxy } from "./patterns/proxy/Proxy"; 22 | -------------------------------------------------------------------------------- /bin/esm/patterns/command/SimpleCommand.js: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleCommand.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | import { Notifier } from "../observer/Notifier"; 9 | /** 10 | * A base `Command` implementation. 11 | * 12 | * Your subclass should override the `execute` 13 | * method where your business logic will handle the `Notification`. 14 | * 15 | * @see {@link Controller} 16 | * @see {@link Notification} 17 | * @see {@link MacroCommand} 18 | * 19 | * @class SimpleCommand 20 | * @extends Notifier 21 | */ 22 | export class SimpleCommand extends Notifier { 23 | /** 24 | * Fulfill the use-case initiated by the given `Notification`. 25 | * 26 | * In the Command Pattern, an application use-case typically 27 | * begins with some user action, which results in a `Notification` being broadcast, which 28 | * is handled by business logic in the `execute` method of an 29 | * `Command`. 30 | * 31 | * @param {INotification} notification - The notification containing the data or command details to be processed. 32 | * @returns {void} 33 | */ 34 | execute(notification) { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/patterns/mediator/Mediator.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Mediator.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IMediator, Mediator} from "../../../src"; 10 | 11 | /** 12 | * Test the PureMVC Mediator class. 13 | * 14 | * @see IMediator 15 | * @see Mediator 16 | */ 17 | describe("MediatorTest", () => { 18 | 19 | /** 20 | * Tests getting the name using Mediator class accessor method. 21 | */ 22 | test("testNameAccessor", () => { 23 | // Create a new Mediator and use accessors to set the mediator name 24 | const mediator: IMediator = new Mediator(); 25 | 26 | // test assertions 27 | expect(mediator.name).toBe(Mediator.NAME); 28 | }); 29 | 30 | /** 31 | * Tests getting the name using Mediator class accessor method. 32 | */ 33 | test("testViewAccessor", () => { 34 | // Create a view object 35 | const view: object = {}; 36 | 37 | // Create a new Proxy and use accessors to set the proxy name 38 | const mediator: IMediator = new Mediator(Mediator.NAME, view); 39 | 40 | // test assertions 41 | expect(mediator.viewComponent).toBe(view); 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // 2 | // index.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | export type {IController} from "./interfaces/IController"; 10 | export type {IModel} from "./interfaces/IModel"; 11 | export type {IView} from "./interfaces/IView"; 12 | export type {ICommand} from "./interfaces/ICommand"; 13 | export type {IFacade} from "./interfaces/IFacade"; 14 | export type {IMediator} from "./interfaces/IMediator"; 15 | export type {INotification} from "./interfaces/INotification"; 16 | export type {INotifier} from "./interfaces/INotifier"; 17 | export type {IObserver} from "./interfaces/IObserver"; 18 | export type {IProxy} from "./interfaces/IProxy"; 19 | 20 | export {Controller} from "./core/Controller"; 21 | export {Model} from "./core/Model"; 22 | export {View} from "./core/View"; 23 | export {MacroCommand} from "./patterns/command/MacroCommand"; 24 | export {SimpleCommand} from "./patterns/command/SimpleCommand"; 25 | export {Facade} from "./patterns/facade/Facade"; 26 | export {Mediator} from "./patterns/mediator/Mediator"; 27 | export {Notification} from "./patterns/observer/Notification"; 28 | export {Notifier} from "./patterns/observer/Notifier"; 29 | export {Observer} from "./patterns/observer/Observer"; 30 | export {Proxy} from "./patterns/proxy/Proxy"; 31 | -------------------------------------------------------------------------------- /bin/cjs/patterns/command/SimpleCommand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // SimpleCommand.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.SimpleCommand = void 0; 11 | const Notifier_1 = require("../observer/Notifier"); 12 | /** 13 | * A base `Command` implementation. 14 | * 15 | * Your subclass should override the `execute` 16 | * method where your business logic will handle the `Notification`. 17 | * 18 | * @see {@link Controller} 19 | * @see {@link Notification} 20 | * @see {@link MacroCommand} 21 | * 22 | * @class SimpleCommand 23 | * @extends Notifier 24 | */ 25 | class SimpleCommand extends Notifier_1.Notifier { 26 | /** 27 | * Fulfill the use-case initiated by the given `Notification`. 28 | * 29 | * In the Command Pattern, an application use-case typically 30 | * begins with some user action, which results in a `Notification` being broadcast, which 31 | * is handled by business logic in the `execute` method of an 32 | * `Command`. 33 | * 34 | * @param {INotification} notification - The notification containing the data or command details to be processed. 35 | * @returns {void} 36 | */ 37 | execute(notification) { 38 | } 39 | } 40 | exports.SimpleCommand = SimpleCommand; 41 | -------------------------------------------------------------------------------- /bin/types/interfaces/INotifier.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * `INotifier` The interface definition for a PureMVC `Notifier`. 3 | * 4 | * `MacroCommand`, `Command`, `Mediator` and `Proxy` 5 | * all have a need to send `Notifications`. 6 | * 7 | * The `INotifier` interface provides a common method called 8 | * `sendNotification` that relieves implementation code of 9 | * the necessity to actually construct `Notifications`. 10 | * 11 | * The `Notifier` class, which all the above-mentioned classes 12 | * extend, also provides an initialized reference to the `Facade` 13 | * Singleton, which is required for the convenience method 14 | * for sending `Notifications`, but also eases implementation as these 15 | * classes have frequent `Facade` interactions and usually require 16 | * access to the facade anyway. 17 | * 18 | * @interface INotifier 19 | */ 20 | export interface INotifier { 21 | /** 22 | * Send a `INotification`. 23 | * 24 | * Convenience method to prevent having to construct new 25 | * notification instances in our implementation code. 26 | * 27 | * @param {string} notificationName - The name of the notification to send. 28 | * @param {any} [body] - Optional data associated with the notification. 29 | * @param {string} [type] - Optional type of the notification. 30 | * @returns {void} 31 | */ 32 | sendNotification(notificationName: string, body?: any, type?: string): void; 33 | } 34 | -------------------------------------------------------------------------------- /src/patterns/command/SimpleCommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleCommand.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {ICommand} from "../../interfaces/ICommand"; 10 | import {INotification} from "../../interfaces/INotification"; 11 | import {Notifier} from "../observer/Notifier"; 12 | 13 | /** 14 | * A base `Command` implementation. 15 | * 16 | * Your subclass should override the `execute` 17 | * method where your business logic will handle the `Notification`. 18 | * 19 | * @see {@link Controller} 20 | * @see {@link Notification} 21 | * @see {@link MacroCommand} 22 | * 23 | * @class SimpleCommand 24 | * @extends Notifier 25 | */ 26 | export class SimpleCommand extends Notifier implements ICommand { 27 | 28 | /** 29 | * Fulfill the use-case initiated by the given `Notification`. 30 | * 31 | * In the Command Pattern, an application use-case typically 32 | * begins with some user action, which results in a `Notification` being broadcast, which 33 | * is handled by business logic in the `execute` method of an 34 | * `Command`. 35 | * 36 | * @param {INotification} notification - The notification containing the data or command details to be processed. 37 | * @returns {void} 38 | */ 39 | public execute(notification: INotification): void { 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /bin/types/interfaces/IProxy.d.ts: -------------------------------------------------------------------------------- 1 | import { INotifier } from "./INotifier"; 2 | /** 3 | * `IProxy` The interface definition for a PureMVC `Proxy`. 4 | * 5 | * In PureMVC, `IProxy` implementors assume these responsibilities: 6 | * 7 | * - Implement a common method which returns the name of the Proxy. 8 | * 9 | * - Provide methods for setting and getting the data object. 10 | * 11 | * Additionally, `IProxy`ies typically: 12 | * 13 | * - Maintain references to one or more pieces of model data. 14 | * 15 | * - Provide methods for manipulating that data. 16 | * 17 | * - Generate `INotifications` when their model data changes. 18 | * 19 | * - Expose their name as a public static const called `NAME`, if they are not instantiated multiple times. 20 | * 21 | * - Encapsulate interaction with local or remote services used to fetch and persist model data. 22 | * 23 | * @interface IProxy 24 | * @extends INotifier 25 | */ 26 | export interface IProxy extends INotifier { 27 | /** 28 | * The name of the proxy. 29 | * 30 | * @type {string} 31 | */ 32 | readonly name: string; 33 | /** 34 | * The data associated with the proxy. 35 | * 36 | * @type {any} 37 | */ 38 | data?: any; 39 | /** 40 | * Called by the Model when the Proxy is registered 41 | * 42 | * @returns {void} 43 | */ 44 | onRegister(): void; 45 | /** 46 | * Called by the Model when the Proxy is removed 47 | * 48 | * @returns {void} 49 | */ 50 | onRemove(): void; 51 | } 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, Saad Shams 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /src/interfaces/INotifier.ts: -------------------------------------------------------------------------------- 1 | // 2 | // INotifier.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | /** 10 | * `INotifier` The interface definition for a PureMVC `Notifier`. 11 | * 12 | * `MacroCommand`, `Command`, `Mediator` and `Proxy` 13 | * all have a need to send `Notifications`. 14 | * 15 | * The `INotifier` interface provides a common method called 16 | * `sendNotification` that relieves implementation code of 17 | * the necessity to actually construct `Notifications`. 18 | * 19 | * The `Notifier` class, which all the above-mentioned classes 20 | * extend, also provides an initialized reference to the `Facade` 21 | * Singleton, which is required for the convenience method 22 | * for sending `Notifications`, but also eases implementation as these 23 | * classes have frequent `Facade` interactions and usually require 24 | * access to the facade anyway. 25 | * 26 | * @interface INotifier 27 | */ 28 | export interface INotifier { 29 | 30 | /** 31 | * Send a `INotification`. 32 | * 33 | * Convenience method to prevent having to construct new 34 | * notification instances in our implementation code. 35 | * 36 | * @param {string} notificationName - The name of the notification to send. 37 | * @param {any} [body] - Optional data associated with the notification. 38 | * @param {string} [type] - Optional type of the notification. 39 | * @returns {void} 40 | */ 41 | sendNotification(notificationName: string, body?: any, type?: string): void; 42 | } 43 | -------------------------------------------------------------------------------- /bin/types/interfaces/IModel.d.ts: -------------------------------------------------------------------------------- 1 | import { IProxy } from "./IProxy"; 2 | /** 3 | * `IModel` The interface definition for a PureMVC `Model`. 4 | * 5 | * In PureMVC, `IModel` implementors provide 6 | * access to `IProxy` objects by named lookup. 7 | * 8 | * An `IModel` assumes these responsibilities: 9 | * 10 | * - Maintain a cache of `IProxy` instances 11 | * 12 | * - Provide methods for registering, retrieving, and removing `IProxy` instances 13 | * 14 | * @interface IModel 15 | */ 16 | export interface IModel { 17 | /** 18 | * Register an `IProxy` instance with the `Model`. 19 | * 20 | * @param {IProxy} proxy - an object reference to be held by the `Model`. 21 | * @returns {void} 22 | */ 23 | registerProxy(proxy: IProxy): void; 24 | /** 25 | * Retrieve an `IProxy` instance from the `Model`. 26 | * 27 | * @param {string} proxyName - The name of the proxy to retrieve. 28 | * @returns {IProxy | null} The `IProxy` if registered, otherwise null. 29 | */ 30 | retrieveProxy(proxyName: string): IProxy | null; 31 | /** 32 | * Check if a `Proxy` is registered 33 | * 34 | * @param {string} proxyName - The name of the proxy to check. 35 | * @returns {boolean} True if the `IProxy` is registered, otherwise false. 36 | */ 37 | hasProxy(proxyName: string): boolean; 38 | /** 39 | * Remove an `IProxy` instance from the `Model`. 40 | * 41 | * @param {string} proxyName - The name of the proxy to remove. 42 | * @returns {IProxy | null} The removed `IProxy` if found, otherwise null. 43 | */ 44 | removeProxy(proxyName: string): IProxy | null; 45 | } 46 | -------------------------------------------------------------------------------- /test/patterns/command/SimpleCommand.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Notification} from "../../../src"; 10 | import {SimpleCommandTestVO} from "./SimpleCommandTestVO"; 11 | import {SimpleCommandTestCommand} from "./SimpleCommandTestCommand"; 12 | 13 | /** 14 | * Test the PureMVC SimpleCommand class. 15 | * 16 | * @see SimpleCommandTestVO 17 | * @see SimpleCommandTestCommand 18 | */ 19 | describe("SimpleCommandTest", () => { 20 | 21 | /** 22 | * Tests the `execute` method of a `SimpleCommand`. 23 | * 24 | * This test creates a new `Notification`, adding a 25 | * `SimpleCommandTestVO` as the body. 26 | * It then creates a `SimpleCommandTestCommand` and invokes 27 | * its `execute` method, passing in the note. 28 | * 29 | * Success is determined by evaluating a property on the 30 | * object that was passed on the Notification body, which will 31 | * be modified by the SimpleCommand. 32 | */ 33 | test("testSimpleCommandExecute", () => { 34 | // Create the VO 35 | const vo = new SimpleCommandTestVO(5); 36 | 37 | // Create the Notification (note) 38 | const notification = new Notification("SimpleCommandTestNote", vo); 39 | 40 | // Create the SimpleCommand 41 | const command = new SimpleCommandTestCommand(); 42 | 43 | // Execute the SimpleCommand 44 | command.execute(notification); 45 | 46 | // test assertions 47 | expect(vo.result).toBe(10); 48 | 49 | }); 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /src/interfaces/IProxy.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IProxy.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotifier} from "./INotifier"; 10 | 11 | /** 12 | * `IProxy` The interface definition for a PureMVC `Proxy`. 13 | * 14 | * In PureMVC, `IProxy` implementors assume these responsibilities: 15 | * 16 | * - Implement a common method which returns the name of the Proxy. 17 | * 18 | * - Provide methods for setting and getting the data object. 19 | * 20 | * Additionally, `IProxy`ies typically: 21 | * 22 | * - Maintain references to one or more pieces of model data. 23 | * 24 | * - Provide methods for manipulating that data. 25 | * 26 | * - Generate `INotifications` when their model data changes. 27 | * 28 | * - Expose their name as a public static const called `NAME`, if they are not instantiated multiple times. 29 | * 30 | * - Encapsulate interaction with local or remote services used to fetch and persist model data. 31 | * 32 | * @interface IProxy 33 | * @extends INotifier 34 | */ 35 | export interface IProxy extends INotifier { 36 | 37 | /** 38 | * The name of the proxy. 39 | * 40 | * @type {string} 41 | */ 42 | readonly name: string; 43 | 44 | /** 45 | * The data associated with the proxy. 46 | * 47 | * @type {any} 48 | */ 49 | data?: any; 50 | 51 | /** 52 | * Called by the Model when the Proxy is registered 53 | * 54 | * @returns {void} 55 | */ 56 | onRegister(): void; 57 | 58 | /** 59 | * Called by the Model when the Proxy is removed 60 | * 61 | * @returns {void} 62 | */ 63 | onRemove(): void; 64 | 65 | } 66 | -------------------------------------------------------------------------------- /bin/types/patterns/observer/Notifier.d.ts: -------------------------------------------------------------------------------- 1 | import { INotifier } from "../../interfaces/INotifier"; 2 | import { IFacade } from "../../interfaces/IFacade"; 3 | /** 4 | * A Base `Notifier` implementation. 5 | * 6 | * `MacroCommand, Command, Mediator` and `Proxy` 7 | * all have a need to send `Notifications`. 8 | * 9 | * The `Notifier` interface provides a common method called 10 | * `sendNotification` that relieves implementation code of 11 | * the necessity to actually construct `Notifications`. 12 | * 13 | * The `Notifier` class, which all the above-mentioned classes 14 | * extend, provides an initialized reference to the `Facade` 15 | * Singleton, which is required for the convenience method 16 | * for sending `Notifications`, but also eases implementation as these 17 | * classes have frequent `Facade` interactions and usually require 18 | * access to the facade anyway. 19 | * 20 | * @see {@link Proxy} 21 | * @see {@link Facade} 22 | * @see {@link Mediator} 23 | * @see {@link MacroCommand} 24 | * @see {@link SimpleCommand} 25 | * 26 | * @class Notifier 27 | */ 28 | export declare class Notifier implements INotifier { 29 | /** 30 | * Create and send an `Notification`. 31 | * 32 | * Keeps us from having to construct new Notification 33 | * instances in our implementation code. 34 | * 35 | * @param {string} notificationName - The name of the notification to be sent. 36 | * @param {any} [body] - Optional data to be included with the notification. 37 | * @param {string} [type] - Optional type of the notification. 38 | * @returns {void} 39 | */ 40 | sendNotification(notificationName: string, body?: any, type?: string): void; 41 | /** 42 | * Return the Singleton Facade instance 43 | * 44 | * @returns {IFacade} The facade instance. 45 | */ 46 | protected facade: IFacade; 47 | } 48 | -------------------------------------------------------------------------------- /src/interfaces/IModel.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IModel.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IProxy} from "./IProxy"; 10 | 11 | /** 12 | * `IModel` The interface definition for a PureMVC `Model`. 13 | * 14 | * In PureMVC, `IModel` implementors provide 15 | * access to `IProxy` objects by named lookup. 16 | * 17 | * An `IModel` assumes these responsibilities: 18 | * 19 | * - Maintain a cache of `IProxy` instances 20 | * 21 | * - Provide methods for registering, retrieving, and removing `IProxy` instances 22 | * 23 | * @interface IModel 24 | */ 25 | export interface IModel { 26 | 27 | /** 28 | * Register an `IProxy` instance with the `Model`. 29 | * 30 | * @param {IProxy} proxy - an object reference to be held by the `Model`. 31 | * @returns {void} 32 | */ 33 | registerProxy(proxy: IProxy): void; 34 | 35 | /** 36 | * Retrieve an `IProxy` instance from the `Model`. 37 | * 38 | * @param {string} proxyName - The name of the proxy to retrieve. 39 | * @returns {IProxy | null} The `IProxy` if registered, otherwise null. 40 | */ 41 | retrieveProxy(proxyName: string): IProxy | null; 42 | 43 | /** 44 | * Check if a `Proxy` is registered 45 | * 46 | * @param {string} proxyName - The name of the proxy to check. 47 | * @returns {boolean} True if the `IProxy` is registered, otherwise false. 48 | */ 49 | hasProxy(proxyName: string): boolean; 50 | 51 | /** 52 | * Remove an `IProxy` instance from the `Model`. 53 | * 54 | * @param {string} proxyName - The name of the proxy to remove. 55 | * @returns {IProxy | null} The removed `IProxy` if found, otherwise null. 56 | */ 57 | removeProxy(proxyName: string): IProxy | null; 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@puremvc/puremvc-typescript-multicore-framework", 3 | "version": "2.0.0", 4 | "description": "PureMVC MultiCore Framework for TypeScript", 5 | "main": "bin/cjs/index.js", 6 | "module": "bin/esm/index.js", 7 | "types": "bin/types/index.d.ts", 8 | "exports": { 9 | ".": { 10 | "require": "./bin/cjs/index.cjs", 11 | "import": "./bin/esm/index.js" 12 | } 13 | }, 14 | "scripts": { 15 | "build": "npm run clean && npm run build:lib", 16 | "build:lib": "npm run build:cjs && npm run build:esm", 17 | "build:esm": "tsc --module esnext --outDir bin/esm", 18 | "build:cjs": "tsc --module commonjs --outDir bin/cjs", 19 | "build:doc": "typedoc", 20 | "clean": "rm -rf bin", 21 | "test": "jest", 22 | "npm:publish:dry-run": "npm publish --dry-run", 23 | "npm:publish": "npm publish --access public" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/PureMVC/puremvc-typescript-multicore-framework.git" 28 | }, 29 | "homepage": "https://puremvc.org", 30 | "bugs": { 31 | "url": "https://github.com/PureMVC/puremvc-typescript-multicore-framework/issues" 32 | }, 33 | "keywords": [ 34 | "puremvc", 35 | "typescript", 36 | "mvc" 37 | ], 38 | "files": [ 39 | "bin/**/*.*", 40 | "LICENSE", 41 | "VERSION", 42 | "package.json" 43 | ], 44 | "author": "Saad Shams ", 45 | "license": "BSD-3-Clause", 46 | "directories": { 47 | "doc": "docs", 48 | "test": "test", 49 | "bin": "bin" 50 | }, 51 | "devDependencies": { 52 | "@types/jest": "^29.5.10", 53 | "@typescript-eslint/eslint-plugin": "^6.13.2", 54 | "@typescript-eslint/parser": "^6.13.2", 55 | "eslint": "^8.55.0", 56 | "jest": "^29.7.0", 57 | "ts-jest": "^29.1.1", 58 | "typedoc": "^0.26.11", 59 | "typescript": "^5.6.3" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /docs/assets/highlight.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --light-hl-0: #795E26; 3 | --dark-hl-0: #DCDCAA; 4 | --light-hl-1: #000000; 5 | --dark-hl-1: #D4D4D4; 6 | --light-hl-2: #A31515; 7 | --dark-hl-2: #CE9178; 8 | --light-hl-3: #008000; 9 | --dark-hl-3: #6A9955; 10 | --light-hl-4: #0000FF; 11 | --dark-hl-4: #569CD6; 12 | --light-hl-5: #001080; 13 | --dark-hl-5: #9CDCFE; 14 | --light-code-background: #FFFFFF; 15 | --dark-code-background: #1E1E1E; 16 | } 17 | 18 | @media (prefers-color-scheme: light) { :root { 19 | --hl-0: var(--light-hl-0); 20 | --hl-1: var(--light-hl-1); 21 | --hl-2: var(--light-hl-2); 22 | --hl-3: var(--light-hl-3); 23 | --hl-4: var(--light-hl-4); 24 | --hl-5: var(--light-hl-5); 25 | --code-background: var(--light-code-background); 26 | } } 27 | 28 | @media (prefers-color-scheme: dark) { :root { 29 | --hl-0: var(--dark-hl-0); 30 | --hl-1: var(--dark-hl-1); 31 | --hl-2: var(--dark-hl-2); 32 | --hl-3: var(--dark-hl-3); 33 | --hl-4: var(--dark-hl-4); 34 | --hl-5: var(--dark-hl-5); 35 | --code-background: var(--dark-code-background); 36 | } } 37 | 38 | :root[data-theme='light'] { 39 | --hl-0: var(--light-hl-0); 40 | --hl-1: var(--light-hl-1); 41 | --hl-2: var(--light-hl-2); 42 | --hl-3: var(--light-hl-3); 43 | --hl-4: var(--light-hl-4); 44 | --hl-5: var(--light-hl-5); 45 | --code-background: var(--light-code-background); 46 | } 47 | 48 | :root[data-theme='dark'] { 49 | --hl-0: var(--dark-hl-0); 50 | --hl-1: var(--dark-hl-1); 51 | --hl-2: var(--dark-hl-2); 52 | --hl-3: var(--dark-hl-3); 53 | --hl-4: var(--dark-hl-4); 54 | --hl-5: var(--dark-hl-5); 55 | --code-background: var(--dark-code-background); 56 | } 57 | 58 | .hl-0 { color: var(--hl-0); } 59 | .hl-1 { color: var(--hl-1); } 60 | .hl-2 { color: var(--hl-2); } 61 | .hl-3 { color: var(--hl-3); } 62 | .hl-4 { color: var(--hl-4); } 63 | .hl-5 { color: var(--hl-5); } 64 | pre, code { background: var(--code-background); } 65 | -------------------------------------------------------------------------------- /bin/esm/patterns/observer/Notifier.js: -------------------------------------------------------------------------------- 1 | // 2 | // Notifier.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | import { Facade } from "../facade/Facade"; 9 | /** 10 | * A Base `Notifier` implementation. 11 | * 12 | * `MacroCommand, Command, Mediator` and `Proxy` 13 | * all have a need to send `Notifications`. 14 | * 15 | * The `Notifier` interface provides a common method called 16 | * `sendNotification` that relieves implementation code of 17 | * the necessity to actually construct `Notifications`. 18 | * 19 | * The `Notifier` class, which all the above-mentioned classes 20 | * extend, provides an initialized reference to the `Facade` 21 | * Singleton, which is required for the convenience method 22 | * for sending `Notifications`, but also eases implementation as these 23 | * classes have frequent `Facade` interactions and usually require 24 | * access to the facade anyway. 25 | * 26 | * @see {@link Proxy} 27 | * @see {@link Facade} 28 | * @see {@link Mediator} 29 | * @see {@link MacroCommand} 30 | * @see {@link SimpleCommand} 31 | * 32 | * @class Notifier 33 | */ 34 | export class Notifier { 35 | constructor() { 36 | /** 37 | * Return the Singleton Facade instance 38 | * 39 | * @returns {IFacade} The facade instance. 40 | */ 41 | this.facade = Facade.getInstance(() => new Facade()); 42 | } 43 | /** 44 | * Create and send an `Notification`. 45 | * 46 | * Keeps us from having to construct new Notification 47 | * instances in our implementation code. 48 | * 49 | * @param {string} notificationName - The name of the notification to be sent. 50 | * @param {any} [body] - Optional data to be included with the notification. 51 | * @param {string} [type] - Optional type of the notification. 52 | * @returns {void} 53 | */ 54 | sendNotification(notificationName, body, type) { 55 | this.facade.sendNotification(notificationName, body, type); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/patterns/proxy/Proxy.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Proxy.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IProxy, Proxy} from "../../../src"; 10 | 11 | /** 12 | * Test the PureMVC Proxy class. 13 | * 14 | * @see IProxy 15 | * @see Proxy 16 | */ 17 | describe("ProxyTest", () => { 18 | 19 | /** 20 | * Tests getting the name using Proxy class accessor method. Setting can only be done in constructor. 21 | */ 22 | test("testNameAccessor", () => { 23 | // Create a new Proxy and use accessors to set the proxy name 24 | const proxy: IProxy = new Proxy("TestProxy"); 25 | 26 | // test assertions 27 | expect(proxy.name).toBe("TestProxy"); 28 | 29 | const proxy2 = new Proxy(); 30 | 31 | // test assertions 32 | expect(proxy2.name).toBe(Proxy.NAME); 33 | }); 34 | 35 | /** 36 | * Tests setting and getting the data using Proxy class accessor methods. 37 | */ 38 | test("testDataAccessors", () => { 39 | // Create a new Proxy and use accessors to set the data 40 | const proxy = new Proxy("colors"); 41 | proxy.data = ["red", "green", "blue"]; 42 | const data = proxy.data; 43 | 44 | // test assertions 45 | expect(data.length).toBe(3); 46 | expect(data[0]).toBe("red"); 47 | expect(data[1]).toBe("green"); 48 | expect(data[2]).toBe("blue"); 49 | }); 50 | 51 | /** 52 | * Tests setting the name and body using the Notification class Constructor. 53 | */ 54 | test("testConstructor", () => { 55 | // Create a new Proxy using the Constructor to set the name and data 56 | const proxy = new Proxy("colors", ["red", "green", "blue"]); 57 | const data = proxy.data; 58 | 59 | // test assertions 60 | expect(data.length).toBe(3); 61 | expect(data[0]).toBe("red"); 62 | expect(data[1]).toBe("green"); 63 | expect(data[2]).toBe("blue"); 64 | }); 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /bin/types/interfaces/INotification.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * `INotification` The interface definition for a PureMVC `Notification`. 3 | * 4 | * PureMVC does not rely upon underlying event models such 5 | * as the one provided with Flash, and ActionScript 3 does 6 | * not have an inherent event model. 7 | * 8 | * The `Observer` Pattern as implemented within PureMVC exists 9 | * to support event-driven communication between the 10 | * application and the actors of the MVC triad. 11 | * 12 | * `Notifications` are not meant to be a replacement for Events 13 | * in Flex/Flash/AIR. Generally, `IMediator` implementors 14 | * place event listeners on their view components, which they 15 | * then handle in the usual way. This may lead to the broadcast of `Notifications` to 16 | * trigger `ICommands` or to communicate with other `IMediators`. `IProxy` and `ICommand` 17 | * instances communicate with each other and `IMediators` 18 | * by broadcasting `INotifications`. 19 | * 20 | * A key difference between Flash Events and PureMVC 21 | * `Notifications` is that Events follow the 22 | * 'Chain of Responsibility' pattern, 'bubbling' up the display hierarchy 23 | * until some parent component handles the Event, while 24 | * PureMVC `Notifications` follow a 'Publish/Subscribe' 25 | * pattern. PureMVC classes need not be related to each other in a 26 | * parent/child relationship in order to communicate with one another 27 | * using `Notifications`. 28 | * 29 | * @interface INotification 30 | */ 31 | export interface INotification { 32 | /** 33 | * The name of the notification. 34 | * 35 | * @type {string} 36 | */ 37 | readonly name: string; 38 | /** 39 | * The body of the notification. 40 | * 41 | * @type {any} 42 | */ 43 | body?: any; 44 | /** 45 | * The type of the notification. 46 | * 47 | * @type {string} 48 | */ 49 | type?: string; 50 | /** 51 | * Get the string representation of the `INotification` instance 52 | * 53 | * @returns {string} A string representation of the notification. 54 | */ 55 | toString(): string; 56 | } 57 | -------------------------------------------------------------------------------- /src/patterns/observer/Notifier.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Notifier.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotifier} from "../../interfaces/INotifier"; 10 | import {IFacade} from "../../interfaces/IFacade"; 11 | import {Facade} from "../facade/Facade"; 12 | 13 | /** 14 | * A Base `Notifier` implementation. 15 | * 16 | * `MacroCommand, Command, Mediator` and `Proxy` 17 | * all have a need to send `Notifications`. 18 | * 19 | * The `Notifier` interface provides a common method called 20 | * `sendNotification` that relieves implementation code of 21 | * the necessity to actually construct `Notifications`. 22 | * 23 | * The `Notifier` class, which all the above-mentioned classes 24 | * extend, provides an initialized reference to the `Facade` 25 | * Singleton, which is required for the convenience method 26 | * for sending `Notifications`, but also eases implementation as these 27 | * classes have frequent `Facade` interactions and usually require 28 | * access to the facade anyway. 29 | * 30 | * @see {@link Proxy} 31 | * @see {@link Facade} 32 | * @see {@link Mediator} 33 | * @see {@link MacroCommand} 34 | * @see {@link SimpleCommand} 35 | * 36 | * @class Notifier 37 | */ 38 | export class Notifier implements INotifier { 39 | 40 | /** 41 | * Create and send an `Notification`. 42 | * 43 | * Keeps us from having to construct new Notification 44 | * instances in our implementation code. 45 | * 46 | * @param {string} notificationName - The name of the notification to be sent. 47 | * @param {any} [body] - Optional data to be included with the notification. 48 | * @param {string} [type] - Optional type of the notification. 49 | * @returns {void} 50 | */ 51 | public sendNotification(notificationName: string, body?: any, type?: string): void { 52 | this.facade.sendNotification(notificationName, body, type); 53 | } 54 | 55 | /** 56 | * Return the Singleton Facade instance 57 | * 58 | * @returns {IFacade} The facade instance. 59 | */ 60 | protected facade: IFacade = Facade.getInstance(() => new Facade()); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /bin/cjs/patterns/observer/Notifier.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // Notifier.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Notifier = void 0; 11 | const Facade_1 = require("../facade/Facade"); 12 | /** 13 | * A Base `Notifier` implementation. 14 | * 15 | * `MacroCommand, Command, Mediator` and `Proxy` 16 | * all have a need to send `Notifications`. 17 | * 18 | * The `Notifier` interface provides a common method called 19 | * `sendNotification` that relieves implementation code of 20 | * the necessity to actually construct `Notifications`. 21 | * 22 | * The `Notifier` class, which all the above-mentioned classes 23 | * extend, provides an initialized reference to the `Facade` 24 | * Singleton, which is required for the convenience method 25 | * for sending `Notifications`, but also eases implementation as these 26 | * classes have frequent `Facade` interactions and usually require 27 | * access to the facade anyway. 28 | * 29 | * @see {@link Proxy} 30 | * @see {@link Facade} 31 | * @see {@link Mediator} 32 | * @see {@link MacroCommand} 33 | * @see {@link SimpleCommand} 34 | * 35 | * @class Notifier 36 | */ 37 | class Notifier { 38 | constructor() { 39 | /** 40 | * Return the Singleton Facade instance 41 | * 42 | * @returns {IFacade} The facade instance. 43 | */ 44 | this.facade = Facade_1.Facade.getInstance(() => new Facade_1.Facade()); 45 | } 46 | /** 47 | * Create and send an `Notification`. 48 | * 49 | * Keeps us from having to construct new Notification 50 | * instances in our implementation code. 51 | * 52 | * @param {string} notificationName - The name of the notification to be sent. 53 | * @param {any} [body] - Optional data to be included with the notification. 54 | * @param {string} [type] - Optional type of the notification. 55 | * @returns {void} 56 | */ 57 | sendNotification(notificationName, body, type) { 58 | this.facade.sendNotification(notificationName, body, type); 59 | } 60 | } 61 | exports.Notifier = Notifier; 62 | -------------------------------------------------------------------------------- /bin/types/interfaces/IController.d.ts: -------------------------------------------------------------------------------- 1 | import { ICommand } from "./ICommand"; 2 | import { INotification } from "./INotification"; 3 | /** 4 | * `IController` The interface definition for a PureMVC `Controller`. 5 | * 6 | * In PureMVC, an `IController` implementor 7 | * follows the 'Command and Controller' strategy, and 8 | * assumes these responsibilities: 9 | * 10 | * - Remembering which `ICommands` are intended to handle which `INotifications`. 11 | * 12 | * - Registering itself as an `IObserver` with the View for each `INotification` that it has an `ICommand` mapping for. 13 | * 14 | * - Creating a new instance of the proper `ICommand` to handle a given `INotification` when notified by the `View`. 15 | * 16 | * - Calling the `ICommand`'s execute method, passing in the `INotification`. 17 | * 18 | * @interface IController 19 | */ 20 | export interface IController { 21 | /** 22 | * Register a particular `ICommand` class as the handler 23 | * for a particular INotification. 24 | * 25 | * @param {string} notificationName - the name of the `INotification` 26 | * @param {() => ICommand} factory - A factory that returns `ICommand` 27 | * @returns {void} 28 | */ 29 | registerCommand(notificationName: string, factory: () => ICommand): void; 30 | /** 31 | * Execute the `ICommand` previously registered as the 32 | * handler for `INotifications` with the given notification name. 33 | * 34 | * @param {INotification} notification - the `INotification` to execute the associated `ICommand` for 35 | * @returns {void} 36 | */ 37 | executeCommand(notification: INotification): void; 38 | /** 39 | * Check if a `Command` is registered for a given `Notification` 40 | * 41 | * @param {string} notificationName - The name of the notification to check. 42 | * @returns {boolean} `true` if a command is registered for the notification name, `false` otherwise. 43 | */ 44 | hasCommand(notificationName: string): boolean; 45 | /** 46 | * Remove a previously registered `ICommand` to `INotification` mapping. 47 | * 48 | * @param {string} notificationName - the name of the INotification to remove the ICommand mapping for 49 | * @returns {void} 50 | */ 51 | removeCommand(notificationName: string): void; 52 | } 53 | -------------------------------------------------------------------------------- /src/interfaces/INotification.ts: -------------------------------------------------------------------------------- 1 | // 2 | // INotification.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | /** 10 | * `INotification` The interface definition for a PureMVC `Notification`. 11 | * 12 | * PureMVC does not rely upon underlying event models such 13 | * as the one provided with Flash, and ActionScript 3 does 14 | * not have an inherent event model. 15 | * 16 | * The `Observer` Pattern as implemented within PureMVC exists 17 | * to support event-driven communication between the 18 | * application and the actors of the MVC triad. 19 | * 20 | * `Notifications` are not meant to be a replacement for Events 21 | * in Flex/Flash/AIR. Generally, `IMediator` implementors 22 | * place event listeners on their view components, which they 23 | * then handle in the usual way. This may lead to the broadcast of `Notifications` to 24 | * trigger `ICommands` or to communicate with other `IMediators`. `IProxy` and `ICommand` 25 | * instances communicate with each other and `IMediators` 26 | * by broadcasting `INotifications`. 27 | * 28 | * A key difference between Flash Events and PureMVC 29 | * `Notifications` is that Events follow the 30 | * 'Chain of Responsibility' pattern, 'bubbling' up the display hierarchy 31 | * until some parent component handles the Event, while 32 | * PureMVC `Notifications` follow a 'Publish/Subscribe' 33 | * pattern. PureMVC classes need not be related to each other in a 34 | * parent/child relationship in order to communicate with one another 35 | * using `Notifications`. 36 | * 37 | * @interface INotification 38 | */ 39 | export interface INotification { 40 | 41 | /** 42 | * The name of the notification. 43 | * 44 | * @type {string} 45 | */ 46 | readonly name: string; 47 | 48 | /** 49 | * The body of the notification. 50 | * 51 | * @type {any} 52 | */ 53 | body?: any; 54 | 55 | /** 56 | * The type of the notification. 57 | * 58 | * @type {string} 59 | */ 60 | type?: string; 61 | 62 | /** 63 | * Get the string representation of the `INotification` instance 64 | * 65 | * @returns {string} A string representation of the notification. 66 | */ 67 | toString(): string; 68 | } 69 | -------------------------------------------------------------------------------- /test/patterns/observer/Notification.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Notification.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotification, Notification} from "../../../src"; 10 | 11 | /** 12 | * Test the PureMVC Notification class. 13 | * 14 | * @see Notification1 15 | */ 16 | describe("NotificationTest", () => { 17 | 18 | /** 19 | * Tests setting and getting the name using Notification class accessor methods. 20 | */ 21 | test("testNameAccessors", () => { 22 | // Create a new Notification and use accessors to set the note name 23 | const notification: INotification = new Notification("TestNote"); 24 | 25 | // test assertions 26 | expect(notification.name).toBe("TestNote"); 27 | }); 28 | 29 | /** 30 | * Tests setting and getting the body using Notification class accessor methods. 31 | */ 32 | test("testBodyAccessors", () => { 33 | // Create a new Notification and use accessors to set the body 34 | const notification: INotification = new Notification("TestNote"); 35 | notification.body = 5; 36 | 37 | // test assertions 38 | expect(notification.body).toBe(5); 39 | }); 40 | 41 | /** 42 | * Tests setting the name and body using the Notification class Constructor. 43 | */ 44 | test("testConstructor", () => { 45 | // Create a new Notification using the Constructor to set the note name and body 46 | const notification: INotification = new Notification("TestNote", 5, "TestNoteType"); 47 | 48 | // test assertions 49 | expect(notification.name).toBe("TestNote"); 50 | expect(notification.body).toBe(5); 51 | expect(notification.type).toBe("TestNoteType"); 52 | }); 53 | 54 | /** 55 | * Tests the toString method of the notification 56 | */ 57 | test("testToString", () => { 58 | // Create a new Notification and use accessors to set the note name 59 | const notification: INotification = new Notification("TestNote", [1, 3, 5], "TestType"); 60 | const ts = "Notification Name: TestNote\nBody: 1,3,5\nType: TestType"; 61 | 62 | // test assertions 63 | expect(notification.toString()).toBe(ts); 64 | }); 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /bin/types/patterns/proxy/Proxy.d.ts: -------------------------------------------------------------------------------- 1 | import { IProxy } from "../../interfaces/IProxy"; 2 | import { Notifier } from "../observer/Notifier"; 3 | /** 4 | * A base `Proxy` implementation. 5 | * 6 | * In PureMVC, `Proxy` classes are used to manage parts of the 7 | * application's data model. 8 | * 9 | * A `Proxy` might simply manage a reference to a local data object, 10 | * in which case interacting with it might involve setting and 11 | * getting of its data in synchronous fashion. 12 | * 13 | * `Proxy` classes are also used to encapsulate the application's 14 | * interaction with remote services to save or retrieve data, in which case, 15 | * we adopt an asynchronous idiom; setting data (or calling a method) on the 16 | * `Proxy` and listening for a `Notification` to be sent 17 | * when the `Proxy` has retrieved the data from the service. 18 | * 19 | * @see {@link Model} 20 | * 21 | * @class Proxy 22 | * @extends Notifier 23 | */ 24 | export declare class Proxy extends Notifier implements IProxy { 25 | /** 26 | * The default name for the Proxy. 27 | * 28 | * @type {string} 29 | */ 30 | static NAME: string; 31 | /** the proxy name 32 | * @type {string} _name */ 33 | protected readonly _name: string; 34 | /** the data object 35 | * @type {any} _data */ 36 | protected _data?: any; 37 | /** 38 | * Constructor 39 | * 40 | * @param {string} [name] - The name of the proxy. Defaults to `Proxy.NAME` if not provided. 41 | * @param {any} [data] - The data associated with the proxy. Can be `null`. 42 | */ 43 | constructor(name?: string, data?: any); 44 | /** 45 | * Called by the Model when the Proxy is registered 46 | * 47 | * @returns {void} 48 | */ 49 | onRegister(): void; 50 | /** 51 | * Called by the Model when the Proxy is removed 52 | * 53 | * @returns {void} 54 | */ 55 | onRemove(): void; 56 | /** 57 | * Get the proxy name 58 | * 59 | * @returns {string} The name of the proxy. 60 | */ 61 | get name(): string; 62 | /** 63 | * Get the data object 64 | * 65 | * @returns {any} The current data or `undefined` if no data is set. 66 | */ 67 | get data(): any; 68 | /** 69 | * Set the data object 70 | * 71 | * @param {any} value - The data to set. Can be `null`. 72 | */ 73 | set data(value: any); 74 | } 75 | -------------------------------------------------------------------------------- /test/patterns/command/MacroCommand.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommand.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {Notification} from "../../../src"; 10 | import {MacroCommandTestVO} from "./MacroCommandTestVO"; 11 | import {MacroCommandTestCommand} from "./MacroCommandTestCommand"; 12 | 13 | /** 14 | * Test the PureMVC SimpleCommand class. 15 | * 16 | * @see MacroCommandTestVO 17 | * @see MacroCommandTestCommand 18 | */ 19 | describe("MacroCommandTest", () => { 20 | 21 | /** 22 | * Tests operation of a `MacroCommand`. 23 | * 24 | * This test creates a new `Notification`, adding a 25 | * `MacroCommandTestVO` as the body. 26 | * It then creates a `MacroCommandTestCommand` and invokes 27 | * its `execute` method, passing in the 28 | * `Notification`. 29 | * 30 | * The `MacroCommandTestCommand` has defined an 31 | * `initializeMacroCommand` method, which is 32 | * called automatically by its constructor. In this method 33 | * the `MacroCommandTestCommand` adds 2 SubCommands 34 | * to itself, `MacroCommandTestSub1Command` and 35 | * `MacroCommandTestSub2Command`. 36 | * 37 | * The `MacroCommandTestVO` has 2 result properties, 38 | * one is set by `MacroCommandTestSub1Command` by 39 | * multiplying the input property by 2, and the other is set 40 | * by `MacroCommandTestSub2Command` by multiplying 41 | * the input property by itself. 42 | * 43 | * Success is determined by evaluating the 2 result properties 44 | * on the `MacroCommandTestVO` that was passed to 45 | * the `MacroCommandTestCommand` on the Notification 46 | * body. 47 | */ 48 | test("testMacroCommandExecute", () => { 49 | // Create the VO 50 | const vo: MacroCommandTestVO = new MacroCommandTestVO(5); 51 | 52 | // Create the Notification 53 | const notification = new Notification("MacroCommandTest", vo); 54 | 55 | // Create the SimpleCommand 56 | const command: MacroCommandTestCommand = new MacroCommandTestCommand(); 57 | 58 | // Execute the SimpleCommand 59 | command.execute(notification); 60 | 61 | // test assertions 62 | expect(vo.result1).toBe(10); 63 | expect(vo.result2).toBe(25); 64 | }); 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /bin/cjs/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // index.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Proxy = exports.Observer = exports.Notifier = exports.Notification = exports.Mediator = exports.Facade = exports.SimpleCommand = exports.MacroCommand = exports.View = exports.Model = exports.Controller = void 0; 11 | var Controller_1 = require("./core/Controller"); 12 | Object.defineProperty(exports, "Controller", { enumerable: true, get: function () { return Controller_1.Controller; } }); 13 | var Model_1 = require("./core/Model"); 14 | Object.defineProperty(exports, "Model", { enumerable: true, get: function () { return Model_1.Model; } }); 15 | var View_1 = require("./core/View"); 16 | Object.defineProperty(exports, "View", { enumerable: true, get: function () { return View_1.View; } }); 17 | var MacroCommand_1 = require("./patterns/command/MacroCommand"); 18 | Object.defineProperty(exports, "MacroCommand", { enumerable: true, get: function () { return MacroCommand_1.MacroCommand; } }); 19 | var SimpleCommand_1 = require("./patterns/command/SimpleCommand"); 20 | Object.defineProperty(exports, "SimpleCommand", { enumerable: true, get: function () { return SimpleCommand_1.SimpleCommand; } }); 21 | var Facade_1 = require("./patterns/facade/Facade"); 22 | Object.defineProperty(exports, "Facade", { enumerable: true, get: function () { return Facade_1.Facade; } }); 23 | var Mediator_1 = require("./patterns/mediator/Mediator"); 24 | Object.defineProperty(exports, "Mediator", { enumerable: true, get: function () { return Mediator_1.Mediator; } }); 25 | var Notification_1 = require("./patterns/observer/Notification"); 26 | Object.defineProperty(exports, "Notification", { enumerable: true, get: function () { return Notification_1.Notification; } }); 27 | var Notifier_1 = require("./patterns/observer/Notifier"); 28 | Object.defineProperty(exports, "Notifier", { enumerable: true, get: function () { return Notifier_1.Notifier; } }); 29 | var Observer_1 = require("./patterns/observer/Observer"); 30 | Object.defineProperty(exports, "Observer", { enumerable: true, get: function () { return Observer_1.Observer; } }); 31 | var Proxy_1 = require("./patterns/proxy/Proxy"); 32 | Object.defineProperty(exports, "Proxy", { enumerable: true, get: function () { return Proxy_1.Proxy; } }); 33 | -------------------------------------------------------------------------------- /bin/esm/patterns/proxy/Proxy.js: -------------------------------------------------------------------------------- 1 | // 2 | // Proxy.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | import { Notifier } from "../observer/Notifier"; 9 | /** 10 | * A base `Proxy` implementation. 11 | * 12 | * In PureMVC, `Proxy` classes are used to manage parts of the 13 | * application's data model. 14 | * 15 | * A `Proxy` might simply manage a reference to a local data object, 16 | * in which case interacting with it might involve setting and 17 | * getting of its data in synchronous fashion. 18 | * 19 | * `Proxy` classes are also used to encapsulate the application's 20 | * interaction with remote services to save or retrieve data, in which case, 21 | * we adopt an asynchronous idiom; setting data (or calling a method) on the 22 | * `Proxy` and listening for a `Notification` to be sent 23 | * when the `Proxy` has retrieved the data from the service. 24 | * 25 | * @see {@link Model} 26 | * 27 | * @class Proxy 28 | * @extends Notifier 29 | */ 30 | export class Proxy extends Notifier { 31 | /** 32 | * Constructor 33 | * 34 | * @param {string} [name] - The name of the proxy. Defaults to `Proxy.NAME` if not provided. 35 | * @param {any} [data] - The data associated with the proxy. Can be `null`. 36 | */ 37 | constructor(name, data) { 38 | super(); 39 | this._name = name || Proxy.NAME; 40 | this._data = data; 41 | } 42 | /** 43 | * Called by the Model when the Proxy is registered 44 | * 45 | * @returns {void} 46 | */ 47 | onRegister() { 48 | } 49 | /** 50 | * Called by the Model when the Proxy is removed 51 | * 52 | * @returns {void} 53 | */ 54 | onRemove() { 55 | } 56 | /** 57 | * Get the proxy name 58 | * 59 | * @returns {string} The name of the proxy. 60 | */ 61 | get name() { 62 | return this._name; 63 | } 64 | /** 65 | * Get the data object 66 | * 67 | * @returns {any} The current data or `undefined` if no data is set. 68 | */ 69 | get data() { 70 | return this._data; 71 | } 72 | /** 73 | * Set the data object 74 | * 75 | * @param {any} value - The data to set. Can be `null`. 76 | */ 77 | set data(value) { 78 | this._data = value; 79 | } 80 | } 81 | /** 82 | * The default name for the Proxy. 83 | * 84 | * @type {string} 85 | */ 86 | Proxy.NAME = "Proxy"; 87 | -------------------------------------------------------------------------------- /src/interfaces/IController.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IController.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {ICommand} from "./ICommand"; 10 | import {INotification} from "./INotification"; 11 | 12 | /** 13 | * `IController` The interface definition for a PureMVC `Controller`. 14 | * 15 | * In PureMVC, an `IController` implementor 16 | * follows the 'Command and Controller' strategy, and 17 | * assumes these responsibilities: 18 | * 19 | * - Remembering which `ICommands` are intended to handle which `INotifications`. 20 | * 21 | * - Registering itself as an `IObserver` with the View for each `INotification` that it has an `ICommand` mapping for. 22 | * 23 | * - Creating a new instance of the proper `ICommand` to handle a given `INotification` when notified by the `View`. 24 | * 25 | * - Calling the `ICommand`'s execute method, passing in the `INotification`. 26 | * 27 | * @interface IController 28 | */ 29 | export interface IController { 30 | /** 31 | * Register a particular `ICommand` class as the handler 32 | * for a particular INotification. 33 | * 34 | * @param {string} notificationName - the name of the `INotification` 35 | * @param {() => ICommand} factory - A factory that returns `ICommand` 36 | * @returns {void} 37 | */ 38 | registerCommand(notificationName: string, factory: () => ICommand): void; 39 | 40 | /** 41 | * Execute the `ICommand` previously registered as the 42 | * handler for `INotifications` with the given notification name. 43 | * 44 | * @param {INotification} notification - the `INotification` to execute the associated `ICommand` for 45 | * @returns {void} 46 | */ 47 | executeCommand(notification: INotification): void; 48 | 49 | /** 50 | * Check if a `Command` is registered for a given `Notification` 51 | * 52 | * @param {string} notificationName - The name of the notification to check. 53 | * @returns {boolean} `true` if a command is registered for the notification name, `false` otherwise. 54 | */ 55 | hasCommand(notificationName: string): boolean; 56 | 57 | /** 58 | * Remove a previously registered `ICommand` to `INotification` mapping. 59 | * 60 | * @param {string} notificationName - the name of the INotification to remove the ICommand mapping for 61 | * @returns {void} 62 | */ 63 | removeCommand(notificationName: string): void; 64 | } 65 | -------------------------------------------------------------------------------- /bin/types/interfaces/IObserver.d.ts: -------------------------------------------------------------------------------- 1 | import { INotification } from "./INotification"; 2 | /** 3 | * `IObserver` The interface definition for a PureMVC `Observer`. 4 | * 5 | * In PureMVC, `IObserver` implementors assume these responsibilities: 6 | * 7 | * - Encapsulate the notification (callback) method of the interested object. 8 | * 9 | * - Encapsulate the notification context (self) of the interested object. 10 | * 11 | * - Provide methods for setting the interested object notification method and context. 12 | * 13 | * - Provide a method for notifying the interested object. 14 | * 15 | * PureMVC does not rely upon underlying event 16 | * models such as the one provided with Flash, 17 | * and ActionScript 3 does not have an inherent 18 | * event model. 19 | * 20 | * The `Observer` Pattern as implemented within 21 | * PureMVC exists to support event driven communication 22 | * between the application and the actors of the 23 | * MVC triad. 24 | * 25 | * An `Observer` is an object that encapsulates information 26 | * about an interested object with a notification method that 27 | * should be called when an `INotification` is broadcast. 28 | * The Observer then acts as a proxy for notifying the interested object. 29 | * 30 | * Observers can receive Notifications by having their 31 | * `notifyObserver` method invoked, passing 32 | * in an object implementing the `INotification` interface, such 33 | * as a subclass of `Notification`. 34 | * 35 | * @interface IObserver 36 | */ 37 | export interface IObserver { 38 | /** 39 | * The method to be called when a notification is received. 40 | * 41 | * @type {((notification: INotification) => void) | null} 42 | */ 43 | notifyMethod?: ((notification: INotification) => void) | null; 44 | /** 45 | * The context in which the notification method should be called. 46 | * 47 | * @type {any | null} 48 | */ 49 | notifyContext?: any | null; 50 | /** 51 | * Notify the interested object. 52 | * 53 | * @param {INotification} notification - the `INotification` to pass to the interested object's notification method 54 | * @returns {void} 55 | */ 56 | notifyObserver(notification: INotification): void; 57 | /** 58 | * Compare the given object to the notification context object. 59 | * 60 | * @param {any} object - The object to compare with the `notifyContext`. 61 | * @returns {boolean} `true` if the object is the same as the `notifyContext`, otherwise `false`. 62 | */ 63 | compareNotifyContext(object: any): boolean; 64 | } 65 | -------------------------------------------------------------------------------- /bin/types/patterns/mediator/Mediator.d.ts: -------------------------------------------------------------------------------- 1 | import { IMediator } from "../../interfaces/IMediator"; 2 | import { INotification } from "../../interfaces/INotification"; 3 | import { Notifier } from "../observer/Notifier"; 4 | /** 5 | * A base `Mediator` implementation. 6 | * 7 | * @see {@link View} 8 | * 9 | * @class Mediator 10 | * @extends Notifier 11 | */ 12 | export declare class Mediator extends Notifier implements IMediator { 13 | /** The default name for the mediator. 14 | * @type {string} */ 15 | static NAME: string; 16 | /** the mediator name 17 | @type {string} */ 18 | protected readonly _name: string; 19 | /** The view component 20 | * @type {any} */ 21 | protected _viewComponent?: any; 22 | /** 23 | * Constructor. 24 | * 25 | * @param {string} [name] - Optional name for the mediator. Defaults to `Mediator.NAME`. 26 | * @param {any} [viewComponent] - Optional view component associated with the mediator. 27 | */ 28 | constructor(name?: string, viewComponent?: any); 29 | /** 30 | * Called by the View when the Mediator is registered 31 | * 32 | * @returns {void} 33 | */ 34 | onRegister(): void; 35 | /** 36 | * Called by the View when the Mediator is removed 37 | * 38 | * @returns {void} 39 | */ 40 | onRemove(): void; 41 | /** 42 | * List the `Notification` names this 43 | * `Mediator` is interested in being notified of. 44 | * 45 | * @returns {string[]} An array of notification names. 46 | */ 47 | listNotificationInterests(): string[]; 48 | /** 49 | * Handle `Notification`s. 50 | * 51 | * Typically, this will be handled in a switch statement, 52 | * with one 'case' entry per `Notification` 53 | * the `Mediator` is interested in. 54 | * 55 | * @param {INotification} notification - The notification to handle. 56 | * @returns {void} 57 | */ 58 | handleNotification(notification: INotification): void; 59 | /** 60 | * the mediator name 61 | * 62 | * @returns {string} The name of the mediator. 63 | */ 64 | get name(): string; 65 | /** 66 | * Get the `Mediator`'s view component. 67 | * 68 | * Additionally, an implicit getter will usually 69 | * be defined in the subclass that casts the view 70 | * object to a type, like this: 71 | * 72 | * @returns {any} The view component. 73 | */ 74 | get viewComponent(): any; 75 | /** 76 | * Set the `Mediator`'s view component. 77 | * 78 | * @param {any} value - The new view component. 79 | */ 80 | set viewComponent(value: any); 81 | } 82 | -------------------------------------------------------------------------------- /bin/cjs/patterns/proxy/Proxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // Proxy.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Proxy = void 0; 11 | const Notifier_1 = require("../observer/Notifier"); 12 | /** 13 | * A base `Proxy` implementation. 14 | * 15 | * In PureMVC, `Proxy` classes are used to manage parts of the 16 | * application's data model. 17 | * 18 | * A `Proxy` might simply manage a reference to a local data object, 19 | * in which case interacting with it might involve setting and 20 | * getting of its data in synchronous fashion. 21 | * 22 | * `Proxy` classes are also used to encapsulate the application's 23 | * interaction with remote services to save or retrieve data, in which case, 24 | * we adopt an asynchronous idiom; setting data (or calling a method) on the 25 | * `Proxy` and listening for a `Notification` to be sent 26 | * when the `Proxy` has retrieved the data from the service. 27 | * 28 | * @see {@link Model} 29 | * 30 | * @class Proxy 31 | * @extends Notifier 32 | */ 33 | class Proxy extends Notifier_1.Notifier { 34 | /** 35 | * Constructor 36 | * 37 | * @param {string} [name] - The name of the proxy. Defaults to `Proxy.NAME` if not provided. 38 | * @param {any} [data] - The data associated with the proxy. Can be `null`. 39 | */ 40 | constructor(name, data) { 41 | super(); 42 | this._name = name || Proxy.NAME; 43 | this._data = data; 44 | } 45 | /** 46 | * Called by the Model when the Proxy is registered 47 | * 48 | * @returns {void} 49 | */ 50 | onRegister() { 51 | } 52 | /** 53 | * Called by the Model when the Proxy is removed 54 | * 55 | * @returns {void} 56 | */ 57 | onRemove() { 58 | } 59 | /** 60 | * Get the proxy name 61 | * 62 | * @returns {string} The name of the proxy. 63 | */ 64 | get name() { 65 | return this._name; 66 | } 67 | /** 68 | * Get the data object 69 | * 70 | * @returns {any} The current data or `undefined` if no data is set. 71 | */ 72 | get data() { 73 | return this._data; 74 | } 75 | /** 76 | * Set the data object 77 | * 78 | * @param {any} value - The data to set. Can be `null`. 79 | */ 80 | set data(value) { 81 | this._data = value; 82 | } 83 | } 84 | exports.Proxy = Proxy; 85 | /** 86 | * The default name for the Proxy. 87 | * 88 | * @type {string} 89 | */ 90 | Proxy.NAME = "Proxy"; 91 | -------------------------------------------------------------------------------- /bin/types/interfaces/IMediator.d.ts: -------------------------------------------------------------------------------- 1 | import { INotifier } from "./INotifier"; 2 | import { INotification } from "./INotification"; 3 | /** 4 | * `IMediator` The interface definition for a PureMVC `Mediator`. 5 | * 6 | * In PureMVC, `IMediator` implementors assume these responsibilities: 7 | * 8 | * - Implement a common method which returns a list of all `INotifications` the `IMediator` has interest in. 9 | * 10 | * - Implement a notification callback method. 11 | * 12 | * - Implement methods that are called when the `IMediator` is registered or removed from the View. 13 | * 14 | * Additionally, `IMediators` typically: 15 | * 16 | * - Act as an intermediary between one or more view components such as text boxes or list controls, maintaining references and coordinating their behavior. 17 | * 18 | * - In Flash-based apps, this is often the place where event listeners are added to view components, and their handlers implemented. 19 | * 20 | * - Respond to and generate `INotifications`, interacting with of the rest of the PureMVC app. 21 | * 22 | * When an `IMediator` is registered with the `IView`, 23 | * the `IView` will call the `IMediator`'s 24 | * `listNotificationInterests` method. The `IMediator` will 25 | * return an Array of `INotification` names which 26 | * it wishes to be notified about. 27 | * 28 | * The `IView` will then create an `Observer` object 29 | * encapsulating that `IMediator`'s (`handleNotification`) method 30 | * and register it as an `Observer` for each `INotification` name returned by 31 | * `listNotificationInterests`. 32 | * 33 | * @interface IMediator 34 | * @extends {INotifier} 35 | */ 36 | export interface IMediator extends INotifier { 37 | /** 38 | * The name of the mediator. 39 | * 40 | * @type {string} 41 | */ 42 | readonly name: string; 43 | /** 44 | * The view component associated with the mediator. 45 | * 46 | * @type {any} 47 | */ 48 | viewComponent: any; 49 | /** 50 | * Called by the View when the `Mediator` is registered 51 | * 52 | * @returns {void} 53 | */ 54 | onRegister(): void; 55 | /** 56 | * Called by the View when the `Mediator` is removed 57 | * 58 | * @returns {void} 59 | */ 60 | onRemove(): void; 61 | /** 62 | * List `INotification` interests. 63 | * 64 | * @returns {string[]} an Array of the `INotification` names this `IMediator` has an interest in. 65 | */ 66 | listNotificationInterests(): string[]; 67 | /** 68 | * Handle an `INotification`. 69 | * 70 | * @param {INotification} notification - the `INotification` to be handled 71 | * @returns {void} 72 | */ 73 | handleNotification(notification: INotification): void; 74 | } 75 | -------------------------------------------------------------------------------- /bin/esm/patterns/mediator/Mediator.js: -------------------------------------------------------------------------------- 1 | // 2 | // Mediator.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | import { Notifier } from "../observer/Notifier"; 9 | /** 10 | * A base `Mediator` implementation. 11 | * 12 | * @see {@link View} 13 | * 14 | * @class Mediator 15 | * @extends Notifier 16 | */ 17 | export class Mediator extends Notifier { 18 | /** 19 | * Constructor. 20 | * 21 | * @param {string} [name] - Optional name for the mediator. Defaults to `Mediator.NAME`. 22 | * @param {any} [viewComponent] - Optional view component associated with the mediator. 23 | */ 24 | constructor(name, viewComponent) { 25 | super(); 26 | this._name = name || Mediator.NAME; 27 | this._viewComponent = viewComponent; 28 | } 29 | /** 30 | * Called by the View when the Mediator is registered 31 | * 32 | * @returns {void} 33 | */ 34 | onRegister() { 35 | } 36 | /** 37 | * Called by the View when the Mediator is removed 38 | * 39 | * @returns {void} 40 | */ 41 | onRemove() { 42 | } 43 | /** 44 | * List the `Notification` names this 45 | * `Mediator` is interested in being notified of. 46 | * 47 | * @returns {string[]} An array of notification names. 48 | */ 49 | listNotificationInterests() { 50 | return []; 51 | } 52 | /** 53 | * Handle `Notification`s. 54 | * 55 | * Typically, this will be handled in a switch statement, 56 | * with one 'case' entry per `Notification` 57 | * the `Mediator` is interested in. 58 | * 59 | * @param {INotification} notification - The notification to handle. 60 | * @returns {void} 61 | */ 62 | handleNotification(notification) { 63 | } 64 | /** 65 | * the mediator name 66 | * 67 | * @returns {string} The name of the mediator. 68 | */ 69 | get name() { 70 | return this._name; 71 | } 72 | /** 73 | * Get the `Mediator`'s view component. 74 | * 75 | * Additionally, an implicit getter will usually 76 | * be defined in the subclass that casts the view 77 | * object to a type, like this: 78 | * 79 | * @returns {any} The view component. 80 | */ 81 | get viewComponent() { 82 | return this._viewComponent; 83 | } 84 | /** 85 | * Set the `Mediator`'s view component. 86 | * 87 | * @param {any} value - The new view component. 88 | */ 89 | set viewComponent(value) { 90 | this._viewComponent = value; 91 | } 92 | } 93 | /** The default name for the mediator. 94 | * @type {string} */ 95 | Mediator.NAME = "Mediator"; 96 | -------------------------------------------------------------------------------- /src/interfaces/IObserver.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IObserver.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotification} from "./INotification"; 10 | 11 | /** 12 | * `IObserver` The interface definition for a PureMVC `Observer`. 13 | * 14 | * In PureMVC, `IObserver` implementors assume these responsibilities: 15 | * 16 | * - Encapsulate the notification (callback) method of the interested object. 17 | * 18 | * - Encapsulate the notification context (self) of the interested object. 19 | * 20 | * - Provide methods for setting the interested object notification method and context. 21 | * 22 | * - Provide a method for notifying the interested object. 23 | * 24 | * PureMVC does not rely upon underlying event 25 | * models such as the one provided with Flash, 26 | * and ActionScript 3 does not have an inherent 27 | * event model. 28 | * 29 | * The `Observer` Pattern as implemented within 30 | * PureMVC exists to support event driven communication 31 | * between the application and the actors of the 32 | * MVC triad. 33 | * 34 | * An `Observer` is an object that encapsulates information 35 | * about an interested object with a notification method that 36 | * should be called when an `INotification` is broadcast. 37 | * The Observer then acts as a proxy for notifying the interested object. 38 | * 39 | * Observers can receive Notifications by having their 40 | * `notifyObserver` method invoked, passing 41 | * in an object implementing the `INotification` interface, such 42 | * as a subclass of `Notification`. 43 | * 44 | * @interface IObserver 45 | */ 46 | export interface IObserver { 47 | 48 | /** 49 | * The method to be called when a notification is received. 50 | * 51 | * @type {((notification: INotification) => void) | null} 52 | */ 53 | notifyMethod?: ((notification: INotification) => void) | null; 54 | 55 | /** 56 | * The context in which the notification method should be called. 57 | * 58 | * @type {any | null} 59 | */ 60 | notifyContext?: any | null; 61 | 62 | /** 63 | * Notify the interested object. 64 | * 65 | * @param {INotification} notification - the `INotification` to pass to the interested object's notification method 66 | * @returns {void} 67 | */ 68 | notifyObserver(notification: INotification): void; 69 | 70 | /** 71 | * Compare the given object to the notification context object. 72 | * 73 | * @param {any} object - The object to compare with the `notifyContext`. 74 | * @returns {boolean} `true` if the object is the same as the `notifyContext`, otherwise `false`. 75 | */ 76 | compareNotifyContext(object: any): boolean; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/interfaces/IMediator.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IMediator.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotifier} from "./INotifier"; 10 | import {INotification} from "./INotification"; 11 | 12 | /** 13 | * `IMediator` The interface definition for a PureMVC `Mediator`. 14 | * 15 | * In PureMVC, `IMediator` implementors assume these responsibilities: 16 | * 17 | * - Implement a common method which returns a list of all `INotifications` the `IMediator` has interest in. 18 | * 19 | * - Implement a notification callback method. 20 | * 21 | * - Implement methods that are called when the `IMediator` is registered or removed from the View. 22 | * 23 | * Additionally, `IMediators` typically: 24 | * 25 | * - Act as an intermediary between one or more view components such as text boxes or list controls, maintaining references and coordinating their behavior. 26 | * 27 | * - In Flash-based apps, this is often the place where event listeners are added to view components, and their handlers implemented. 28 | * 29 | * - Respond to and generate `INotifications`, interacting with of the rest of the PureMVC app. 30 | * 31 | * When an `IMediator` is registered with the `IView`, 32 | * the `IView` will call the `IMediator`'s 33 | * `listNotificationInterests` method. The `IMediator` will 34 | * return an Array of `INotification` names which 35 | * it wishes to be notified about. 36 | * 37 | * The `IView` will then create an `Observer` object 38 | * encapsulating that `IMediator`'s (`handleNotification`) method 39 | * and register it as an `Observer` for each `INotification` name returned by 40 | * `listNotificationInterests`. 41 | * 42 | * @interface IMediator 43 | * @extends {INotifier} 44 | */ 45 | export interface IMediator extends INotifier { 46 | 47 | /** 48 | * The name of the mediator. 49 | * 50 | * @type {string} 51 | */ 52 | readonly name: string; 53 | 54 | /** 55 | * The view component associated with the mediator. 56 | * 57 | * @type {any} 58 | */ 59 | viewComponent: any; 60 | 61 | /** 62 | * Called by the View when the `Mediator` is registered 63 | * 64 | * @returns {void} 65 | */ 66 | onRegister(): void; 67 | 68 | /** 69 | * Called by the View when the `Mediator` is removed 70 | * 71 | * @returns {void} 72 | */ 73 | onRemove(): void; 74 | 75 | /** 76 | * List `INotification` interests. 77 | * 78 | * @returns {string[]} an Array of the `INotification` names this `IMediator` has an interest in. 79 | */ 80 | listNotificationInterests(): string[]; 81 | 82 | /** 83 | * Handle an `INotification`. 84 | * 85 | * @param {INotification} notification - the `INotification` to be handled 86 | * @returns {void} 87 | */ 88 | handleNotification(notification: INotification): void; 89 | 90 | } 91 | -------------------------------------------------------------------------------- /bin/cjs/patterns/mediator/Mediator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // Mediator.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Mediator = void 0; 11 | const Notifier_1 = require("../observer/Notifier"); 12 | /** 13 | * A base `Mediator` implementation. 14 | * 15 | * @see {@link View} 16 | * 17 | * @class Mediator 18 | * @extends Notifier 19 | */ 20 | class Mediator extends Notifier_1.Notifier { 21 | /** 22 | * Constructor. 23 | * 24 | * @param {string} [name] - Optional name for the mediator. Defaults to `Mediator.NAME`. 25 | * @param {any} [viewComponent] - Optional view component associated with the mediator. 26 | */ 27 | constructor(name, viewComponent) { 28 | super(); 29 | this._name = name || Mediator.NAME; 30 | this._viewComponent = viewComponent; 31 | } 32 | /** 33 | * Called by the View when the Mediator is registered 34 | * 35 | * @returns {void} 36 | */ 37 | onRegister() { 38 | } 39 | /** 40 | * Called by the View when the Mediator is removed 41 | * 42 | * @returns {void} 43 | */ 44 | onRemove() { 45 | } 46 | /** 47 | * List the `Notification` names this 48 | * `Mediator` is interested in being notified of. 49 | * 50 | * @returns {string[]} An array of notification names. 51 | */ 52 | listNotificationInterests() { 53 | return []; 54 | } 55 | /** 56 | * Handle `Notification`s. 57 | * 58 | * Typically, this will be handled in a switch statement, 59 | * with one 'case' entry per `Notification` 60 | * the `Mediator` is interested in. 61 | * 62 | * @param {INotification} notification - The notification to handle. 63 | * @returns {void} 64 | */ 65 | handleNotification(notification) { 66 | } 67 | /** 68 | * the mediator name 69 | * 70 | * @returns {string} The name of the mediator. 71 | */ 72 | get name() { 73 | return this._name; 74 | } 75 | /** 76 | * Get the `Mediator`'s view component. 77 | * 78 | * Additionally, an implicit getter will usually 79 | * be defined in the subclass that casts the view 80 | * object to a type, like this: 81 | * 82 | * @returns {any} The view component. 83 | */ 84 | get viewComponent() { 85 | return this._viewComponent; 86 | } 87 | /** 88 | * Set the `Mediator`'s view component. 89 | * 90 | * @param {any} value - The new view component. 91 | */ 92 | set viewComponent(value) { 93 | this._viewComponent = value; 94 | } 95 | } 96 | exports.Mediator = Mediator; 97 | /** The default name for the mediator. 98 | * @type {string} */ 99 | Mediator.NAME = "Mediator"; 100 | -------------------------------------------------------------------------------- /src/patterns/proxy/Proxy.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Proxy.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IProxy} from "../../interfaces/IProxy"; 10 | import {Notifier} from "../observer/Notifier"; 11 | 12 | /** 13 | * A base `Proxy` implementation. 14 | * 15 | * In PureMVC, `Proxy` classes are used to manage parts of the 16 | * application's data model. 17 | * 18 | * A `Proxy` might simply manage a reference to a local data object, 19 | * in which case interacting with it might involve setting and 20 | * getting of its data in synchronous fashion. 21 | * 22 | * `Proxy` classes are also used to encapsulate the application's 23 | * interaction with remote services to save or retrieve data, in which case, 24 | * we adopt an asynchronous idiom; setting data (or calling a method) on the 25 | * `Proxy` and listening for a `Notification` to be sent 26 | * when the `Proxy` has retrieved the data from the service. 27 | * 28 | * @see {@link Model} 29 | * 30 | * @class Proxy 31 | * @extends Notifier 32 | */ 33 | export class Proxy extends Notifier implements IProxy { 34 | 35 | /** 36 | * The default name for the Proxy. 37 | * 38 | * @type {string} 39 | */ 40 | public static NAME: string = "Proxy"; 41 | 42 | /** the proxy name 43 | * @type {string} _name */ 44 | protected readonly _name: string; 45 | 46 | /** the data object 47 | * @type {any} _data */ 48 | protected _data?: any; 49 | 50 | /** 51 | * Constructor 52 | * 53 | * @param {string} [name] - The name of the proxy. Defaults to `Proxy.NAME` if not provided. 54 | * @param {any} [data] - The data associated with the proxy. Can be `null`. 55 | */ 56 | public constructor(name?: string, data?: any) { 57 | super(); 58 | this._name = name || Proxy.NAME; 59 | this._data = data; 60 | } 61 | 62 | /** 63 | * Called by the Model when the Proxy is registered 64 | * 65 | * @returns {void} 66 | */ 67 | public onRegister(): void { 68 | 69 | } 70 | 71 | /** 72 | * Called by the Model when the Proxy is removed 73 | * 74 | * @returns {void} 75 | */ 76 | public onRemove(): void { 77 | 78 | } 79 | 80 | /** 81 | * Get the proxy name 82 | * 83 | * @returns {string} The name of the proxy. 84 | */ 85 | public get name(): string { 86 | return this._name; 87 | } 88 | 89 | /** 90 | * Get the data object 91 | * 92 | * @returns {any} The current data or `undefined` if no data is set. 93 | */ 94 | public get data(): any { 95 | return this._data; 96 | } 97 | 98 | /** 99 | * Set the data object 100 | * 101 | * @param {any} value - The data to set. Can be `null`. 102 | */ 103 | public set data(value: any) { 104 | this._data = value; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /bin/types/patterns/observer/Observer.d.ts: -------------------------------------------------------------------------------- 1 | import { IObserver } from "../../interfaces/IObserver"; 2 | import { INotification } from "../../interfaces/INotification"; 3 | /** 4 | * A base `Observer` implementation. 5 | * 6 | * An `Observer` is an object that encapsulates information 7 | * about an interested object with a method that should 8 | * be called when a particular `Notification` is broadcast. 9 | * 10 | * In PureMVC, the `Observer` class assumes these responsibilities: 11 | * 12 | * - Encapsulate the notification (callback) method of the interested object. 13 | * - Encapsulate the notification context (this) of the interested object. 14 | * - Provide methods for setting the notification method and context. 15 | * - Provide a method for notifying the interested object. 16 | * 17 | * @class Observer 18 | */ 19 | export declare class Observer implements IObserver { 20 | private _notifyMethod?; 21 | private _notifyContext?; 22 | /** 23 | * Constructor. 24 | * 25 | * The notification method on the interested object should take 26 | * one parameter of type `Notification` 27 | * 28 | * @param {((notification: INotification) => void) | null} notify - The method to be called when a notification is received. Can be `null`. 29 | * @param {any | null} context - The context in which to call the `notifyMethod`. Can be `null`. 30 | */ 31 | constructor(notify?: ((notification: INotification) => void) | null, context?: any | null); 32 | /** 33 | * Get the notification method. 34 | * 35 | * @returns {((notification: INotification) => void) | null} The current method or `null` if no method is set. 36 | */ 37 | get notifyMethod(): ((notification: INotification) => void) | null | undefined; 38 | /** 39 | * Set the notification method. 40 | * 41 | * The notification method should take one parameter of type `Notification`. 42 | * 43 | * @param {((notification: INotification) => void) | null} value - The method to set for handling notifications. Can be `null`. 44 | */ 45 | set notifyMethod(value: ((notification: INotification) => void) | null); 46 | /** 47 | * Get the notifyContext 48 | * 49 | * @returns {any | null} The current context or `null` if no context is set. 50 | */ 51 | get notifyContext(): any | null; 52 | /** 53 | * Set the notification context. 54 | * 55 | * @param {any | null} value - The context to set. Can be `null`. 56 | */ 57 | set notifyContext(value: any | null); 58 | /** 59 | * Notify the interested object. 60 | * 61 | * @param {INotification} notification - The notification to send to the observer. 62 | * @returns {void} 63 | */ 64 | notifyObserver(notification: INotification): void; 65 | /** 66 | * Compare an object to the notification context. 67 | * 68 | * @param {any} object - The object to compare with the observer's context. 69 | * @returns {boolean} `true` if the context is the same, otherwise `false`. 70 | */ 71 | compareNotifyContext(object: any): boolean; 72 | } 73 | -------------------------------------------------------------------------------- /bin/types/patterns/command/MacroCommand.d.ts: -------------------------------------------------------------------------------- 1 | import { ICommand } from "../../interfaces/ICommand"; 2 | import { INotification } from "../../interfaces/INotification"; 3 | import { SimpleCommand } from "./SimpleCommand"; 4 | /** 5 | * A base `Command` implementation that executes other `Command`s. 6 | * 7 | * A `MacroCommand` maintains a list of 8 | * `Command` Class references called `SubCommands`. 9 | * 10 | * When `execute` is called, the `MacroCommand` 11 | * instantiates and calls `execute` on each of its `SubCommands` turn. 12 | * Each `SubCommand` will be passed a reference to the original 13 | * `Notification` that was passed to the `MacroCommand`'s 14 | * `execute` method. 15 | * 16 | * Unlike `SimpleCommand`, your subclass 17 | * should not override `execute`, but instead, should 18 | * override the `initializeMacroCommand` method, 19 | * calling `addSubCommand` once for each `SubCommand` 20 | * to be executed. 21 | * 22 | * @see {@link Controller} 23 | * @see {@link Notification} 24 | * @see {@link SimpleCommand} 25 | * 26 | * @class MacroCommand 27 | * @extends Notifier 28 | */ 29 | export declare class MacroCommand extends SimpleCommand { 30 | /** An array of functions, each of which returns an instance of ICommand. 31 | * @type {(() => ICommand)[]} */ 32 | private subCommands; 33 | /** 34 | * Constructor. 35 | * 36 | * You should not need to define a constructor, 37 | * instead, override the `initializeMacroCommand` 38 | * method. 39 | * 40 | * If your subclass does define a constructor, be 41 | * sure to call `super()`. 42 | * 43 | */ 44 | constructor(); 45 | /** 46 | * Initialize the `MacroCommand`. 47 | * 48 | * In your subclass, override this method to 49 | * initialize the `MacroCommand`'s `SubCommand` 50 | * list with `Command` class references like 51 | * this: 52 | * 53 | * ```ts 54 | * // Initialize MyMacroCommand 55 | * initializeMacroCommand() { 56 | * this.addSubCommand(() => new app.FirstCommand()); 57 | * this.addSubCommand(() => new app.SecondCommand()); 58 | * this.addSubCommand(() => new app.ThirdCommand()); 59 | * } 60 | * ``` 61 | * 62 | * Note that `SubCommand`s may be any `Command` implementor, 63 | * `MacroCommand`s or `SimpleCommands` are both acceptable. 64 | */ 65 | initializeMacroCommand(): void; 66 | /** 67 | * Add a `SubCommand`. 68 | * 69 | * The `SubCommands` will be called in First In/First Out (FIFO) 70 | * order. 71 | * 72 | * @param {() => ICommand} factory - A factory function that creates an instance of ICommand. This function will be used to generate the sub-command. 73 | * @returns {void} 74 | */ 75 | protected addSubCommand(factory: () => ICommand): void; 76 | /** 77 | * Execute this `MacroCommand`'s `SubCommands`. 78 | * 79 | * The `SubCommands` will be called in First In/First Out (FIFO) 80 | * order. 81 | * 82 | * @param {INotification} notification - The notification containing the data or command details to be processed. 83 | * @returns {void} 84 | */ 85 | execute(notification: INotification): void; 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## [PureMVC](http://puremvc.org/) TypeScript Standard Framework [![Node.js CI](https://github.com/PureMVC/puremvc-typescript-standard-framework/actions/workflows/node.js.yml/badge.svg)](https://github.com/PureMVC/puremvc-typescript-standard-framework/actions/workflows/node.js.yml) 2 | 3 | PureMVC is a lightweight framework for creating applications based upon the classic [Model-View-Controller](http://en.wikipedia.org/wiki/Model-view-controller) design meta-pattern. It does not support [modular programming](http://en.wikipedia.org/wiki/Modular_programming) since it uses [Singleton](http://en.wikipedia.org/wiki/Singleton_pattern)s as Core actors rather than the [Multiton](http://en.wikipedia.org/wiki/Multiton)s used in the [MultiCore](https://github.com/PureMVC/puremvc-typescript-multicore-framework/wiki/) Version. 4 | 5 | * [API Docs](https://puremvc.org/pages/docs/TypeScript/standard/) 6 | * [Legacy Implementation](https://github.com/PureMVC/puremvc-typescript-standard-framework/tree/1.0.1) 7 | 8 | ## Platforms / Technologies 9 | * [TypeScript](https://en.wikipedia.org/wiki/TypeScript) 10 | * [JavaScript](https://en.wikipedia.org/wiki/JavaScript) 11 | * [ECMAScript](https://en.wikipedia.org/wiki/ECMAScript) 12 | * [CommonJS](https://en.wikipedia.org/wiki/CommonJS) 13 | * [Node.js](https://en.wikipedia.org/wiki/Node.js) 14 | * [React](https://en.wikipedia.org/wiki/React_(JavaScript_library)) 15 | * [React Native](https://en.wikipedia.org/wiki/React_Native) 16 | 17 | ## Status 18 | Production - [Version 2.0.0](https://github.com/PureMVC/puremvc-typescript-standard-framework/blob/master/VERSION) 19 | 20 | ## License 21 | * PureMVC Standard Framework for TypeScript - Copyright © 2024 [Saad Shams](https://www.linkedin.com/in/muizz) 22 | * PureMVC - Copyright © 2024 [Futurescale, Inc.](http://futurescale.com/) 23 | * All rights reserved. 24 | 25 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 26 | 27 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 28 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 29 | * Neither the name of Futurescale, Inc., PureMVC.org, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | -------------------------------------------------------------------------------- /bin/esm/patterns/observer/Observer.js: -------------------------------------------------------------------------------- 1 | // 2 | // Observer.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | /** 9 | * A base `Observer` implementation. 10 | * 11 | * An `Observer` is an object that encapsulates information 12 | * about an interested object with a method that should 13 | * be called when a particular `Notification` is broadcast. 14 | * 15 | * In PureMVC, the `Observer` class assumes these responsibilities: 16 | * 17 | * - Encapsulate the notification (callback) method of the interested object. 18 | * - Encapsulate the notification context (this) of the interested object. 19 | * - Provide methods for setting the notification method and context. 20 | * - Provide a method for notifying the interested object. 21 | * 22 | * @class Observer 23 | */ 24 | export class Observer { 25 | /** 26 | * Constructor. 27 | * 28 | * The notification method on the interested object should take 29 | * one parameter of type `Notification` 30 | * 31 | * @param {((notification: INotification) => void) | null} notify - The method to be called when a notification is received. Can be `null`. 32 | * @param {any | null} context - The context in which to call the `notifyMethod`. Can be `null`. 33 | */ 34 | constructor(notify, context) { 35 | this._notifyMethod = notify; 36 | this._notifyContext = context; 37 | } 38 | /** 39 | * Get the notification method. 40 | * 41 | * @returns {((notification: INotification) => void) | null} The current method or `null` if no method is set. 42 | */ 43 | get notifyMethod() { 44 | return this._notifyMethod; 45 | } 46 | /** 47 | * Set the notification method. 48 | * 49 | * The notification method should take one parameter of type `Notification`. 50 | * 51 | * @param {((notification: INotification) => void) | null} value - The method to set for handling notifications. Can be `null`. 52 | */ 53 | set notifyMethod(value) { 54 | this._notifyMethod = value; 55 | } 56 | /** 57 | * Get the notifyContext 58 | * 59 | * @returns {any | null} The current context or `null` if no context is set. 60 | */ 61 | get notifyContext() { 62 | return this._notifyContext; 63 | } 64 | /** 65 | * Set the notification context. 66 | * 67 | * @param {any | null} value - The context to set. Can be `null`. 68 | */ 69 | set notifyContext(value) { 70 | this._notifyContext = value; 71 | } 72 | /** 73 | * Notify the interested object. 74 | * 75 | * @param {INotification} notification - The notification to send to the observer. 76 | * @returns {void} 77 | */ 78 | notifyObserver(notification) { 79 | var _a; 80 | (_a = this.notifyMethod) === null || _a === void 0 ? void 0 : _a.call(this.notifyContext, notification); 81 | } 82 | /** 83 | * Compare an object to the notification context. 84 | * 85 | * @param {any} object - The object to compare with the observer's context. 86 | * @returns {boolean} `true` if the context is the same, otherwise `false`. 87 | */ 88 | compareNotifyContext(object) { 89 | return object == this.notifyContext; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/patterns/observer/Observer.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Observer.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotification, Notification, Observer} from "../../../src"; 10 | 11 | /** 12 | * Tests PureMVC Observer class. 13 | * 14 | * Since the Observer encapsulates the interested object's 15 | * callback information, there are no getters, only setters. 16 | * It is, in effect write-only memory. 17 | * 18 | * Therefore, the only way to test it is to set the 19 | * notification method and context and call the notifyObserver 20 | * method. 21 | */ 22 | describe("ObserverTest", () => { 23 | 24 | let observerTestVar: number = -1; 25 | 26 | const observerTestMethod = (notification: INotification): void => { 27 | observerTestVar = notification.body; 28 | }; 29 | 30 | /** 31 | * Tests observer class when initialized by accessor methods. 32 | */ 33 | test("testObserverAccessors", () => { 34 | // Create observer with null args, then 35 | // use accessors to set notification method and context 36 | const observer = new Observer(null, null); 37 | observer.notifyContext = this; 38 | observer.notifyMethod = observerTestMethod; 39 | 40 | // create a test event, setting a payload value and notify 41 | // the observer with it. since the observer is this class 42 | // and the notification method is observerTestMethod, 43 | // successful notification will result in our local 44 | // observerTestVar being set to the value we pass in 45 | // on the note body. 46 | const notification: INotification = new Notification("ObserverTestNote", 10); 47 | observer.notifyObserver(notification); 48 | 49 | // test assertions 50 | expect(observerTestVar).toBe(10); 51 | }); 52 | 53 | /** 54 | * Tests observer class when initialized by constructor. 55 | */ 56 | test("testObserverConstructor", () => { 57 | // Create observer with null args, then 58 | // use accessors to set notification method and context 59 | const observer = new Observer(observerTestMethod, this); 60 | 61 | // create a test note, setting a body value and notify 62 | // the observer with it. since the observer is this class 63 | // and the notification method is observerTestMethod, 64 | // successful notification will result in our local 65 | // observerTestVar being set to the value we pass in 66 | // on the note body. 67 | const notification: INotification = new Notification("ObserverTestNote", 5); 68 | observer.notifyObserver(notification); 69 | 70 | // test assertions 71 | expect(observerTestVar).toBe(5); 72 | }); 73 | 74 | /** 75 | * Tests the compareNotifyContext method of the Observer class 76 | */ 77 | test("testCompareNotifyContext", () => { 78 | // Create observer passing in notification method and context 79 | const observer = new Observer(observerTestMethod, this); 80 | const negTestObject: object = {}; 81 | 82 | // test assertions 83 | expect(observer.compareNotifyContext(negTestObject)).toBe(false); 84 | expect(observer.compareNotifyContext(this)).toBe(true); 85 | }); 86 | 87 | }); 88 | -------------------------------------------------------------------------------- /bin/types/patterns/observer/Notification.d.ts: -------------------------------------------------------------------------------- 1 | import { INotification } from "../../interfaces/INotification"; 2 | /** 3 | * A base `Notification` implementation. 4 | * 5 | * PureMVC does not rely upon underlying event models such 6 | * as the one provided with Flash, and ActionScript 3 does 7 | * not have an inherent event model. 8 | * 9 | * The Observer Pattern as implemented within PureMVC exists 10 | * to support event-driven communication between the 11 | * application and the actors of the MVC triad. 12 | * 13 | * Notifications are not meant to be a replacement for Events 14 | * in Flex/Flash/Apollo. Generally, `Mediator` implementors 15 | * place event listeners on their view components, which they 16 | * then handle in the usual way. This may lead to the broadcast of `Notification`s to 17 | * trigger `Command`s or to communicate with other `Mediators`. `Proxy` and `Command` 18 | * instances communicate with each other and `Mediator`s 19 | * by broadcasting `Notification`s. 20 | * 21 | * A key difference between Flash `Event`s and PureMVC 22 | * `Notification`s is that `Event`s follow the 23 | * 'Chain of Responsibility' pattern, 'bubbling' up the display hierarchy 24 | * until some parent component handles the `Event`, while 25 | * PureMVC `Notification`s follow a 'Publish/Subscribe' 26 | * pattern. PureMVC classes need not be related to each other in a 27 | * parent/child relationship in order to communicate with one another 28 | * using `Notification`s. 29 | * 30 | * @class Notification 31 | */ 32 | export declare class Notification implements INotification { 33 | /** the name of the notification instance 34 | * @type {string} */ 35 | private readonly _name; 36 | /** the body of the notification instance 37 | * @type {any} */ 38 | private _body?; 39 | /** 40 | * @type {string | undefined } */ 41 | private _type?; 42 | /** 43 | * Constructor. 44 | * 45 | * @param {string} name - The name of the notification. 46 | * @param {any} [body] - Optional data to be included with the notification. 47 | * @param {string} [type] - Optional type of the notification. 48 | */ 49 | constructor(name: string, body?: any, type?: string); 50 | /** 51 | * Get the name of the `Notification` instance. 52 | * 53 | * @returns {string} The name of the notification. 54 | */ 55 | get name(): string; 56 | /** 57 | * Get the body of the `Notification` instance. 58 | * 59 | * @returns {any} The body of the notification. 60 | */ 61 | get body(): any; 62 | /** 63 | * Set the body of the `Notification` instance. 64 | * 65 | * @param {any} value - The new body to be set for the notification. 66 | */ 67 | set body(value: any); 68 | /** 69 | * Get the type of the `Notification` instance. 70 | * 71 | * @returns {string | undefined} The type of the notification, or `undefined` if not set. 72 | */ 73 | get type(): string | undefined; 74 | /** 75 | * Set the type of the `Notification` instance. 76 | * 77 | * @param {string | undefined} value - The new type to be set for the notification. 78 | */ 79 | set type(value: string | undefined); 80 | /** 81 | * Get the string representation of the `Notification` instance. 82 | * 83 | * @returns {string} A string representation of the notification. 84 | */ 85 | toString(): string; 86 | } 87 | -------------------------------------------------------------------------------- /src/patterns/mediator/Mediator.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Mediator.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IMediator} from "../../interfaces/IMediator"; 10 | import {INotification} from "../../interfaces/INotification"; 11 | import {Notifier} from "../observer/Notifier"; 12 | 13 | /** 14 | * A base `Mediator` implementation. 15 | * 16 | * @see {@link View} 17 | * 18 | * @class Mediator 19 | * @extends Notifier 20 | */ 21 | export class Mediator extends Notifier implements IMediator { 22 | 23 | /** The default name for the mediator. 24 | * @type {string} */ 25 | public static NAME: string = "Mediator"; 26 | 27 | /** the mediator name 28 | @type {string} */ 29 | protected readonly _name: string; 30 | 31 | /** The view component 32 | * @type {any} */ 33 | protected _viewComponent?: any; 34 | 35 | /** 36 | * Constructor. 37 | * 38 | * @param {string} [name] - Optional name for the mediator. Defaults to `Mediator.NAME`. 39 | * @param {any} [viewComponent] - Optional view component associated with the mediator. 40 | */ 41 | public constructor(name?: string, viewComponent?: any) { 42 | super(); 43 | this._name = name || Mediator.NAME; 44 | this._viewComponent = viewComponent; 45 | } 46 | 47 | /** 48 | * Called by the View when the Mediator is registered 49 | * 50 | * @returns {void} 51 | */ 52 | public onRegister(): void { 53 | 54 | } 55 | 56 | /** 57 | * Called by the View when the Mediator is removed 58 | * 59 | * @returns {void} 60 | */ 61 | public onRemove(): void { 62 | 63 | } 64 | 65 | /** 66 | * List the `Notification` names this 67 | * `Mediator` is interested in being notified of. 68 | * 69 | * @returns {string[]} An array of notification names. 70 | */ 71 | public listNotificationInterests(): string[] { 72 | return []; 73 | } 74 | 75 | /** 76 | * Handle `Notification`s. 77 | * 78 | * Typically, this will be handled in a switch statement, 79 | * with one 'case' entry per `Notification` 80 | * the `Mediator` is interested in. 81 | * 82 | * @param {INotification} notification - The notification to handle. 83 | * @returns {void} 84 | */ 85 | public handleNotification(notification: INotification): void { 86 | 87 | } 88 | 89 | /** 90 | * the mediator name 91 | * 92 | * @returns {string} The name of the mediator. 93 | */ 94 | public get name(): string { 95 | return this._name; 96 | } 97 | 98 | /** 99 | * Get the `Mediator`'s view component. 100 | * 101 | * Additionally, an implicit getter will usually 102 | * be defined in the subclass that casts the view 103 | * object to a type, like this: 104 | * 105 | * @returns {any} The view component. 106 | */ 107 | public get viewComponent(): any { 108 | return this._viewComponent; 109 | } 110 | 111 | /** 112 | * Set the `Mediator`'s view component. 113 | * 114 | * @param {any} value - The new view component. 115 | */ 116 | public set viewComponent(value: any) { 117 | this._viewComponent = value; 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /bin/cjs/patterns/observer/Observer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // Observer.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Observer = void 0; 11 | /** 12 | * A base `Observer` implementation. 13 | * 14 | * An `Observer` is an object that encapsulates information 15 | * about an interested object with a method that should 16 | * be called when a particular `Notification` is broadcast. 17 | * 18 | * In PureMVC, the `Observer` class assumes these responsibilities: 19 | * 20 | * - Encapsulate the notification (callback) method of the interested object. 21 | * - Encapsulate the notification context (this) of the interested object. 22 | * - Provide methods for setting the notification method and context. 23 | * - Provide a method for notifying the interested object. 24 | * 25 | * @class Observer 26 | */ 27 | class Observer { 28 | /** 29 | * Constructor. 30 | * 31 | * The notification method on the interested object should take 32 | * one parameter of type `Notification` 33 | * 34 | * @param {((notification: INotification) => void) | null} notify - The method to be called when a notification is received. Can be `null`. 35 | * @param {any | null} context - The context in which to call the `notifyMethod`. Can be `null`. 36 | */ 37 | constructor(notify, context) { 38 | this._notifyMethod = notify; 39 | this._notifyContext = context; 40 | } 41 | /** 42 | * Get the notification method. 43 | * 44 | * @returns {((notification: INotification) => void) | null} The current method or `null` if no method is set. 45 | */ 46 | get notifyMethod() { 47 | return this._notifyMethod; 48 | } 49 | /** 50 | * Set the notification method. 51 | * 52 | * The notification method should take one parameter of type `Notification`. 53 | * 54 | * @param {((notification: INotification) => void) | null} value - The method to set for handling notifications. Can be `null`. 55 | */ 56 | set notifyMethod(value) { 57 | this._notifyMethod = value; 58 | } 59 | /** 60 | * Get the notifyContext 61 | * 62 | * @returns {any | null} The current context or `null` if no context is set. 63 | */ 64 | get notifyContext() { 65 | return this._notifyContext; 66 | } 67 | /** 68 | * Set the notification context. 69 | * 70 | * @param {any | null} value - The context to set. Can be `null`. 71 | */ 72 | set notifyContext(value) { 73 | this._notifyContext = value; 74 | } 75 | /** 76 | * Notify the interested object. 77 | * 78 | * @param {INotification} notification - The notification to send to the observer. 79 | * @returns {void} 80 | */ 81 | notifyObserver(notification) { 82 | var _a; 83 | (_a = this.notifyMethod) === null || _a === void 0 ? void 0 : _a.call(this.notifyContext, notification); 84 | } 85 | /** 86 | * Compare an object to the notification context. 87 | * 88 | * @param {any} object - The object to compare with the observer's context. 89 | * @returns {boolean} `true` if the context is the same, otherwise `false`. 90 | */ 91 | compareNotifyContext(object) { 92 | return object == this.notifyContext; 93 | } 94 | } 95 | exports.Observer = Observer; 96 | -------------------------------------------------------------------------------- /bin/types/core/Model.d.ts: -------------------------------------------------------------------------------- 1 | import { IModel } from "../interfaces/IModel"; 2 | import { IProxy } from "../interfaces/IProxy"; 3 | /** 4 | * A Singleton `Model` implementation. 5 | * 6 | * In PureMVC, the `Model` class provides 7 | * access to model objects (Proxies) by named lookup. 8 | * 9 | * The `Model` assumes these responsibilities: 10 | * 11 | * - Maintain a cache of `Proxy` instances. 12 | * - Provide methods for registering, retrieving, and removing 13 | * `Proxy` instances. 14 | * 15 | * Your application must register `Proxy` instances 16 | * with the `Model`. Typically, you use an 17 | * `Command` to create and register `Proxy` 18 | * instances once the `Facade` has initialized the Core 19 | * actors. 20 | * 21 | * @see {@link Proxy} 22 | * 23 | * @class Model 24 | */ 25 | export declare class Model implements IModel { 26 | /** Message Constants 27 | * @type {string} */ 28 | protected static SINGLETON_MSG: string; 29 | /** 30 | * Singleton instance 31 | * 32 | * @type {IModel} 33 | * @protected 34 | */ 35 | protected static instance: IModel; 36 | /** Mapping of proxyNames to IProxy instances 37 | * @type {{ [key: string]: IProxy }} */ 38 | protected proxyMap: { 39 | [key: string]: IProxy; 40 | }; 41 | /** 42 | * Constructor. 43 | * 44 | * This `Model` implementation is a Singleton, 45 | * so you should not call the constructor 46 | * directly, but instead call the static Singleton 47 | * Factory method `Model.getInstance()` 48 | * 49 | * @throws {Error} Error if instance for this Singleton instance has already been constructed 50 | */ 51 | constructor(); 52 | /** 53 | * Initialize the `Model` instance. 54 | * 55 | * Called automatically by the constructor, this 56 | * is your opportunity to initialize the Singleton 57 | * instance in your subclass without overriding the 58 | * constructor. 59 | * 60 | * @returns {void} 61 | */ 62 | protected initializeModel(): void; 63 | /** 64 | * `Model` Singleton Factory method. 65 | * 66 | * @param {() => IModel} factory - A factory function that creates a new instance of the model if one does not already exist. 67 | * @returns {IModel} The Singleton instance. 68 | */ 69 | static getInstance(factory: () => IModel): IModel; 70 | /** 71 | * Register a `Proxy` with the `Model`. 72 | * 73 | * @param {IProxy} proxy - The proxy instance to be registered. 74 | * @returns {void} 75 | */ 76 | registerProxy(proxy: IProxy): void; 77 | /** 78 | * Retrieve a `Proxy` from the `Model`. 79 | * 80 | * @param {string} proxyName - The name of the proxy to retrieve. 81 | * @returns {IProxy | null} The proxy instance associated with the given name, or `null` if no such proxy exists. 82 | */ 83 | retrieveProxy(proxyName: string): IProxy | null; 84 | /** 85 | * Check if a Proxy is registered 86 | * 87 | * @param {string} proxyName - The name of the proxy to check. 88 | * @returns {boolean} `true` if a proxy with the specified name is registered; otherwise, `false`. 89 | */ 90 | hasProxy(proxyName: string): boolean; 91 | /** 92 | * Remove a `Proxy` from the `Model`. 93 | * 94 | * @param {string} proxyName - The name of the proxy to be removed. 95 | * @returns {IProxy | null} The removed proxy instance, or `null` if no proxy with the given name was found. 96 | */ 97 | removeProxy(proxyName: string): IProxy | null; 98 | } 99 | -------------------------------------------------------------------------------- /bin/esm/patterns/command/MacroCommand.js: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommand.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | import { SimpleCommand } from "./SimpleCommand"; 9 | /** 10 | * A base `Command` implementation that executes other `Command`s. 11 | * 12 | * A `MacroCommand` maintains a list of 13 | * `Command` Class references called `SubCommands`. 14 | * 15 | * When `execute` is called, the `MacroCommand` 16 | * instantiates and calls `execute` on each of its `SubCommands` turn. 17 | * Each `SubCommand` will be passed a reference to the original 18 | * `Notification` that was passed to the `MacroCommand`'s 19 | * `execute` method. 20 | * 21 | * Unlike `SimpleCommand`, your subclass 22 | * should not override `execute`, but instead, should 23 | * override the `initializeMacroCommand` method, 24 | * calling `addSubCommand` once for each `SubCommand` 25 | * to be executed. 26 | * 27 | * @see {@link Controller} 28 | * @see {@link Notification} 29 | * @see {@link SimpleCommand} 30 | * 31 | * @class MacroCommand 32 | * @extends Notifier 33 | */ 34 | export class MacroCommand extends SimpleCommand { 35 | /** 36 | * Constructor. 37 | * 38 | * You should not need to define a constructor, 39 | * instead, override the `initializeMacroCommand` 40 | * method. 41 | * 42 | * If your subclass does define a constructor, be 43 | * sure to call `super()`. 44 | * 45 | */ 46 | constructor() { 47 | super(); 48 | this.subCommands = []; 49 | this.initializeMacroCommand(); 50 | } 51 | /** 52 | * Initialize the `MacroCommand`. 53 | * 54 | * In your subclass, override this method to 55 | * initialize the `MacroCommand`'s `SubCommand` 56 | * list with `Command` class references like 57 | * this: 58 | * 59 | * ```ts 60 | * // Initialize MyMacroCommand 61 | * initializeMacroCommand() { 62 | * this.addSubCommand(() => new app.FirstCommand()); 63 | * this.addSubCommand(() => new app.SecondCommand()); 64 | * this.addSubCommand(() => new app.ThirdCommand()); 65 | * } 66 | * ``` 67 | * 68 | * Note that `SubCommand`s may be any `Command` implementor, 69 | * `MacroCommand`s or `SimpleCommands` are both acceptable. 70 | */ 71 | initializeMacroCommand() { 72 | } 73 | /** 74 | * Add a `SubCommand`. 75 | * 76 | * The `SubCommands` will be called in First In/First Out (FIFO) 77 | * order. 78 | * 79 | * @param {() => ICommand} factory - A factory function that creates an instance of ICommand. This function will be used to generate the sub-command. 80 | * @returns {void} 81 | */ 82 | addSubCommand(factory) { 83 | this.subCommands.push(factory); 84 | } 85 | /** 86 | * Execute this `MacroCommand`'s `SubCommands`. 87 | * 88 | * The `SubCommands` will be called in First In/First Out (FIFO) 89 | * order. 90 | * 91 | * @param {INotification} notification - The notification containing the data or command details to be processed. 92 | * @returns {void} 93 | */ 94 | execute(notification) { 95 | while (this.subCommands.length > 0) { 96 | const factory = this.subCommands.shift(); 97 | const command = factory === null || factory === void 0 ? void 0 : factory(); 98 | if (command) { 99 | command.execute(notification); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /bin/esm/patterns/observer/Notification.js: -------------------------------------------------------------------------------- 1 | // 2 | // Notification.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | /** 9 | * A base `Notification` implementation. 10 | * 11 | * PureMVC does not rely upon underlying event models such 12 | * as the one provided with Flash, and ActionScript 3 does 13 | * not have an inherent event model. 14 | * 15 | * The Observer Pattern as implemented within PureMVC exists 16 | * to support event-driven communication between the 17 | * application and the actors of the MVC triad. 18 | * 19 | * Notifications are not meant to be a replacement for Events 20 | * in Flex/Flash/Apollo. Generally, `Mediator` implementors 21 | * place event listeners on their view components, which they 22 | * then handle in the usual way. This may lead to the broadcast of `Notification`s to 23 | * trigger `Command`s or to communicate with other `Mediators`. `Proxy` and `Command` 24 | * instances communicate with each other and `Mediator`s 25 | * by broadcasting `Notification`s. 26 | * 27 | * A key difference between Flash `Event`s and PureMVC 28 | * `Notification`s is that `Event`s follow the 29 | * 'Chain of Responsibility' pattern, 'bubbling' up the display hierarchy 30 | * until some parent component handles the `Event`, while 31 | * PureMVC `Notification`s follow a 'Publish/Subscribe' 32 | * pattern. PureMVC classes need not be related to each other in a 33 | * parent/child relationship in order to communicate with one another 34 | * using `Notification`s. 35 | * 36 | * @class Notification 37 | */ 38 | export class Notification { 39 | /** 40 | * Constructor. 41 | * 42 | * @param {string} name - The name of the notification. 43 | * @param {any} [body] - Optional data to be included with the notification. 44 | * @param {string} [type] - Optional type of the notification. 45 | */ 46 | constructor(name, body, type) { 47 | this._name = name; 48 | this._body = body; 49 | this._type = type; 50 | } 51 | /** 52 | * Get the name of the `Notification` instance. 53 | * 54 | * @returns {string} The name of the notification. 55 | */ 56 | get name() { 57 | return this._name; 58 | } 59 | /** 60 | * Get the body of the `Notification` instance. 61 | * 62 | * @returns {any} The body of the notification. 63 | */ 64 | get body() { 65 | return this._body; 66 | } 67 | /** 68 | * Set the body of the `Notification` instance. 69 | * 70 | * @param {any} value - The new body to be set for the notification. 71 | */ 72 | set body(value) { 73 | this._body = value; 74 | } 75 | /** 76 | * Get the type of the `Notification` instance. 77 | * 78 | * @returns {string | undefined} The type of the notification, or `undefined` if not set. 79 | */ 80 | get type() { 81 | return this._type; 82 | } 83 | /** 84 | * Set the type of the `Notification` instance. 85 | * 86 | * @param {string | undefined} value - The new type to be set for the notification. 87 | */ 88 | set type(value) { 89 | this._type = value; 90 | } 91 | /** 92 | * Get the string representation of the `Notification` instance. 93 | * 94 | * @returns {string} A string representation of the notification. 95 | */ 96 | toString() { 97 | var _a; 98 | let msg = `Notification Name: ${this.name}`; 99 | msg += `\nBody: ${this.body ? this.body : "null"}`; 100 | msg += `\nType: ${(_a = this.type) !== null && _a !== void 0 ? _a : "null"}`; 101 | return msg; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /bin/cjs/patterns/command/MacroCommand.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // MacroCommand.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.MacroCommand = void 0; 11 | const SimpleCommand_1 = require("./SimpleCommand"); 12 | /** 13 | * A base `Command` implementation that executes other `Command`s. 14 | * 15 | * A `MacroCommand` maintains a list of 16 | * `Command` Class references called `SubCommands`. 17 | * 18 | * When `execute` is called, the `MacroCommand` 19 | * instantiates and calls `execute` on each of its `SubCommands` turn. 20 | * Each `SubCommand` will be passed a reference to the original 21 | * `Notification` that was passed to the `MacroCommand`'s 22 | * `execute` method. 23 | * 24 | * Unlike `SimpleCommand`, your subclass 25 | * should not override `execute`, but instead, should 26 | * override the `initializeMacroCommand` method, 27 | * calling `addSubCommand` once for each `SubCommand` 28 | * to be executed. 29 | * 30 | * @see {@link Controller} 31 | * @see {@link Notification} 32 | * @see {@link SimpleCommand} 33 | * 34 | * @class MacroCommand 35 | * @extends Notifier 36 | */ 37 | class MacroCommand extends SimpleCommand_1.SimpleCommand { 38 | /** 39 | * Constructor. 40 | * 41 | * You should not need to define a constructor, 42 | * instead, override the `initializeMacroCommand` 43 | * method. 44 | * 45 | * If your subclass does define a constructor, be 46 | * sure to call `super()`. 47 | * 48 | */ 49 | constructor() { 50 | super(); 51 | this.subCommands = []; 52 | this.initializeMacroCommand(); 53 | } 54 | /** 55 | * Initialize the `MacroCommand`. 56 | * 57 | * In your subclass, override this method to 58 | * initialize the `MacroCommand`'s `SubCommand` 59 | * list with `Command` class references like 60 | * this: 61 | * 62 | * ```ts 63 | * // Initialize MyMacroCommand 64 | * initializeMacroCommand() { 65 | * this.addSubCommand(() => new app.FirstCommand()); 66 | * this.addSubCommand(() => new app.SecondCommand()); 67 | * this.addSubCommand(() => new app.ThirdCommand()); 68 | * } 69 | * ``` 70 | * 71 | * Note that `SubCommand`s may be any `Command` implementor, 72 | * `MacroCommand`s or `SimpleCommands` are both acceptable. 73 | */ 74 | initializeMacroCommand() { 75 | } 76 | /** 77 | * Add a `SubCommand`. 78 | * 79 | * The `SubCommands` will be called in First In/First Out (FIFO) 80 | * order. 81 | * 82 | * @param {() => ICommand} factory - A factory function that creates an instance of ICommand. This function will be used to generate the sub-command. 83 | * @returns {void} 84 | */ 85 | addSubCommand(factory) { 86 | this.subCommands.push(factory); 87 | } 88 | /** 89 | * Execute this `MacroCommand`'s `SubCommands`. 90 | * 91 | * The `SubCommands` will be called in First In/First Out (FIFO) 92 | * order. 93 | * 94 | * @param {INotification} notification - The notification containing the data or command details to be processed. 95 | * @returns {void} 96 | */ 97 | execute(notification) { 98 | while (this.subCommands.length > 0) { 99 | const factory = this.subCommands.shift(); 100 | const command = factory === null || factory === void 0 ? void 0 : factory(); 101 | if (command) { 102 | command.execute(notification); 103 | } 104 | } 105 | } 106 | } 107 | exports.MacroCommand = MacroCommand; 108 | -------------------------------------------------------------------------------- /bin/types/interfaces/IView.d.ts: -------------------------------------------------------------------------------- 1 | import { IMediator } from "./IMediator"; 2 | import { INotification } from "./INotification"; 3 | import { IObserver } from "./IObserver"; 4 | /** 5 | * `IView` The interface definition for a PureMVC `View`. 6 | * 7 | * In PureMVC, the View class assumes these responsibilities: 8 | * 9 | * - Maintain a cache of `IMediator` instances. 10 | * 11 | * - Provide methods for registering, retrieving, and removing `IMediators`. 12 | * 13 | * - Managing the observer lists for each `INotification` in the application. 14 | * 15 | * - Providing a method for attaching `IObservers` to an `INotification`'s observer list. 16 | * 17 | * - Providing a method for broadcasting an `INotification`. 18 | * 19 | * - Notifying the `IObservers` of a given `INotification` when it is broadcast. 20 | * 21 | * @interface IView 22 | */ 23 | export interface IView { 24 | /** 25 | * Register an `IObserver` to be notified 26 | * of `INotifications` with a given name. 27 | * 28 | * @param {string} notificationName - The name of the notification to register the observer for. 29 | * @param {IObserver} observer - The observer to be registered. 30 | * @returns {void} 31 | */ 32 | registerObserver(notificationName: string, observer: IObserver): void; 33 | /** 34 | * Notify the `IObservers` for a particular `INotification`. 35 | * 36 | * All previously attached `IObservers` for this `INotification`'s 37 | * list are notified and are passed a reference to the `INotification` in 38 | * the order in which they were registered. 39 | * 40 | * @param {INotification} notification - the `INotification` to notify `IObservers` of. 41 | * @returns {void} 42 | */ 43 | notifyObservers(notification: INotification): void; 44 | /** 45 | * Remove a group of observers from the observer list for a given Notification name. 46 | * 47 | * @param {string} notificationName - which observer list to remove from 48 | * @param {any} notifyContext - removed the observers with this object as their `notifyContext` 49 | * @returns {void} 50 | */ 51 | removeObserver(notificationName: string, notifyContext: any): void; 52 | /** 53 | * Register an `IMediator` instance with the View. 54 | * 55 | * Registers the `IMediator` so that it can be retrieved by name, 56 | * and further interrogates the `IMediator` for its 57 | * `INotification` interests. 58 | * 59 | * If the `IMediator` returns any `INotification` 60 | * names to be notified about, an `Observer` is created encapsulating 61 | * the `IMediator` instance's `handleNotification` method 62 | * and registering it as an `Observer` for all `INotifications` the 63 | * `IMediator` is interested in. 64 | * 65 | * @param {IMediator} mediator - The `IMediator` to be registered. 66 | * @returns {void} 67 | */ 68 | registerMediator(mediator: IMediator): void; 69 | /** 70 | * Retrieve an `IMediator` from the View. 71 | * 72 | * @param {string} mediatorName - the name of the `IMediator` instance to retrieve. 73 | * @returns {IMediator | null} The `IMediator` associated with the given name, or `null` if not found. 74 | */ 75 | retrieveMediator(mediatorName: string): IMediator | null; 76 | /** 77 | * Check if a `IMediator` is registered or not 78 | * 79 | * @param {string} mediatorName - The name of the `IMediator` to check. 80 | * @returns {boolean} `true` if the `IMediator` is registered, otherwise `false`. 81 | */ 82 | hasMediator(mediatorName: string): boolean; 83 | /** 84 | * Remove an `IMediator` from the View. 85 | * 86 | * @param {string} mediatorName - name of the `IMediator` instance to be removed. 87 | * @returns {IMediator | null} The removed `IMediator`, or `null` if not found. 88 | */ 89 | removeMediator(mediatorName: string): IMediator | null; 90 | } 91 | -------------------------------------------------------------------------------- /bin/cjs/patterns/observer/Notification.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // Notification.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Notification = void 0; 11 | /** 12 | * A base `Notification` implementation. 13 | * 14 | * PureMVC does not rely upon underlying event models such 15 | * as the one provided with Flash, and ActionScript 3 does 16 | * not have an inherent event model. 17 | * 18 | * The Observer Pattern as implemented within PureMVC exists 19 | * to support event-driven communication between the 20 | * application and the actors of the MVC triad. 21 | * 22 | * Notifications are not meant to be a replacement for Events 23 | * in Flex/Flash/Apollo. Generally, `Mediator` implementors 24 | * place event listeners on their view components, which they 25 | * then handle in the usual way. This may lead to the broadcast of `Notification`s to 26 | * trigger `Command`s or to communicate with other `Mediators`. `Proxy` and `Command` 27 | * instances communicate with each other and `Mediator`s 28 | * by broadcasting `Notification`s. 29 | * 30 | * A key difference between Flash `Event`s and PureMVC 31 | * `Notification`s is that `Event`s follow the 32 | * 'Chain of Responsibility' pattern, 'bubbling' up the display hierarchy 33 | * until some parent component handles the `Event`, while 34 | * PureMVC `Notification`s follow a 'Publish/Subscribe' 35 | * pattern. PureMVC classes need not be related to each other in a 36 | * parent/child relationship in order to communicate with one another 37 | * using `Notification`s. 38 | * 39 | * @class Notification 40 | */ 41 | class Notification { 42 | /** 43 | * Constructor. 44 | * 45 | * @param {string} name - The name of the notification. 46 | * @param {any} [body] - Optional data to be included with the notification. 47 | * @param {string} [type] - Optional type of the notification. 48 | */ 49 | constructor(name, body, type) { 50 | this._name = name; 51 | this._body = body; 52 | this._type = type; 53 | } 54 | /** 55 | * Get the name of the `Notification` instance. 56 | * 57 | * @returns {string} The name of the notification. 58 | */ 59 | get name() { 60 | return this._name; 61 | } 62 | /** 63 | * Get the body of the `Notification` instance. 64 | * 65 | * @returns {any} The body of the notification. 66 | */ 67 | get body() { 68 | return this._body; 69 | } 70 | /** 71 | * Set the body of the `Notification` instance. 72 | * 73 | * @param {any} value - The new body to be set for the notification. 74 | */ 75 | set body(value) { 76 | this._body = value; 77 | } 78 | /** 79 | * Get the type of the `Notification` instance. 80 | * 81 | * @returns {string | undefined} The type of the notification, or `undefined` if not set. 82 | */ 83 | get type() { 84 | return this._type; 85 | } 86 | /** 87 | * Set the type of the `Notification` instance. 88 | * 89 | * @param {string | undefined} value - The new type to be set for the notification. 90 | */ 91 | set type(value) { 92 | this._type = value; 93 | } 94 | /** 95 | * Get the string representation of the `Notification` instance. 96 | * 97 | * @returns {string} A string representation of the notification. 98 | */ 99 | toString() { 100 | var _a; 101 | let msg = `Notification Name: ${this.name}`; 102 | msg += `\nBody: ${this.body ? this.body : "null"}`; 103 | msg += `\nType: ${(_a = this.type) !== null && _a !== void 0 ? _a : "null"}`; 104 | return msg; 105 | } 106 | } 107 | exports.Notification = Notification; 108 | -------------------------------------------------------------------------------- /src/patterns/observer/Observer.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Observer.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IObserver} from "../../interfaces/IObserver"; 10 | import {INotification} from "../../interfaces/INotification"; 11 | 12 | /** 13 | * A base `Observer` implementation. 14 | * 15 | * An `Observer` is an object that encapsulates information 16 | * about an interested object with a method that should 17 | * be called when a particular `Notification` is broadcast. 18 | * 19 | * In PureMVC, the `Observer` class assumes these responsibilities: 20 | * 21 | * - Encapsulate the notification (callback) method of the interested object. 22 | * - Encapsulate the notification context (this) of the interested object. 23 | * - Provide methods for setting the notification method and context. 24 | * - Provide a method for notifying the interested object. 25 | * 26 | * @class Observer 27 | */ 28 | export class Observer implements IObserver { 29 | 30 | private _notifyMethod?: ((notification: INotification) => void) | null; 31 | 32 | private _notifyContext?: any | null; 33 | 34 | /** 35 | * Constructor. 36 | * 37 | * The notification method on the interested object should take 38 | * one parameter of type `Notification` 39 | * 40 | * @param {((notification: INotification) => void) | null} notify - The method to be called when a notification is received. Can be `null`. 41 | * @param {any | null} context - The context in which to call the `notifyMethod`. Can be `null`. 42 | */ 43 | constructor(notify?: ((notification: INotification) => void) | null, context?: any | null) { 44 | this._notifyMethod = notify; 45 | this._notifyContext = context; 46 | } 47 | 48 | /** 49 | * Get the notification method. 50 | * 51 | * @returns {((notification: INotification) => void) | null} The current method or `null` if no method is set. 52 | */ 53 | public get notifyMethod(): ((notification: INotification) => void) | null | undefined { 54 | return this._notifyMethod; 55 | } 56 | 57 | /** 58 | * Set the notification method. 59 | * 60 | * The notification method should take one parameter of type `Notification`. 61 | * 62 | * @param {((notification: INotification) => void) | null} value - The method to set for handling notifications. Can be `null`. 63 | */ 64 | public set notifyMethod(value: ((notification: INotification) => void) | null) { 65 | this._notifyMethod = value; 66 | } 67 | 68 | /** 69 | * Get the notifyContext 70 | * 71 | * @returns {any | null} The current context or `null` if no context is set. 72 | */ 73 | public get notifyContext(): any | null { 74 | return this._notifyContext; 75 | } 76 | 77 | /** 78 | * Set the notification context. 79 | * 80 | * @param {any | null} value - The context to set. Can be `null`. 81 | */ 82 | public set notifyContext(value: any | null) { 83 | this._notifyContext = value; 84 | } 85 | 86 | /** 87 | * Notify the interested object. 88 | * 89 | * @param {INotification} notification - The notification to send to the observer. 90 | * @returns {void} 91 | */ 92 | public notifyObserver(notification: INotification): void { 93 | this.notifyMethod?.call(this.notifyContext, notification); 94 | } 95 | 96 | /** 97 | * Compare an object to the notification context. 98 | * 99 | * @param {any} object - The object to compare with the observer's context. 100 | * @returns {boolean} `true` if the context is the same, otherwise `false`. 101 | */ 102 | public compareNotifyContext(object: any): boolean { 103 | return object == this.notifyContext; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /bin/esm/core/Model.js: -------------------------------------------------------------------------------- 1 | // 2 | // Model.ts 3 | // PureMVC TypeScript Multicore 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | /** 9 | * A Singleton `Model` implementation. 10 | * 11 | * In PureMVC, the `Model` class provides 12 | * access to model objects (Proxies) by named lookup. 13 | * 14 | * The `Model` assumes these responsibilities: 15 | * 16 | * - Maintain a cache of `Proxy` instances. 17 | * - Provide methods for registering, retrieving, and removing 18 | * `Proxy` instances. 19 | * 20 | * Your application must register `Proxy` instances 21 | * with the `Model`. Typically, you use an 22 | * `Command` to create and register `Proxy` 23 | * instances once the `Facade` has initialized the Core 24 | * actors. 25 | * 26 | * @see {@link Proxy} 27 | * 28 | * @class Model 29 | */ 30 | export class Model { 31 | /** 32 | * Constructor. 33 | * 34 | * This `Model` implementation is a Singleton, 35 | * so you should not call the constructor 36 | * directly, but instead call the static Singleton 37 | * Factory method `Model.getInstance()` 38 | * 39 | * @throws {Error} Error if instance for this Singleton instance has already been constructed 40 | */ 41 | constructor() { 42 | if (Model.instance != null) 43 | throw Error(Model.SINGLETON_MSG); 44 | Model.instance = this; 45 | this.proxyMap = {}; 46 | this.initializeModel(); 47 | } 48 | /** 49 | * Initialize the `Model` instance. 50 | * 51 | * Called automatically by the constructor, this 52 | * is your opportunity to initialize the Singleton 53 | * instance in your subclass without overriding the 54 | * constructor. 55 | * 56 | * @returns {void} 57 | */ 58 | initializeModel() { 59 | } 60 | /** 61 | * `Model` Singleton Factory method. 62 | * 63 | * @param {() => IModel} factory - A factory function that creates a new instance of the model if one does not already exist. 64 | * @returns {IModel} The Singleton instance. 65 | */ 66 | static getInstance(factory) { 67 | if (Model.instance == null) 68 | Model.instance = factory(); 69 | return Model.instance; 70 | } 71 | /** 72 | * Register a `Proxy` with the `Model`. 73 | * 74 | * @param {IProxy} proxy - The proxy instance to be registered. 75 | * @returns {void} 76 | */ 77 | registerProxy(proxy) { 78 | this.proxyMap[proxy.name] = proxy; 79 | proxy.onRegister(); 80 | } 81 | /** 82 | * Retrieve a `Proxy` from the `Model`. 83 | * 84 | * @param {string} proxyName - The name of the proxy to retrieve. 85 | * @returns {IProxy | null} The proxy instance associated with the given name, or `null` if no such proxy exists. 86 | */ 87 | retrieveProxy(proxyName) { 88 | return this.proxyMap[proxyName] || null; 89 | } 90 | /** 91 | * Check if a Proxy is registered 92 | * 93 | * @param {string} proxyName - The name of the proxy to check. 94 | * @returns {boolean} `true` if a proxy with the specified name is registered; otherwise, `false`. 95 | */ 96 | hasProxy(proxyName) { 97 | return this.proxyMap[proxyName] != null; 98 | } 99 | /** 100 | * Remove a `Proxy` from the `Model`. 101 | * 102 | * @param {string} proxyName - The name of the proxy to be removed. 103 | * @returns {IProxy | null} The removed proxy instance, or `null` if no proxy with the given name was found. 104 | */ 105 | removeProxy(proxyName) { 106 | const proxy = this.proxyMap[proxyName]; 107 | if (!proxy) 108 | return null; 109 | delete this.proxyMap[proxyName]; 110 | proxy.onRemove(); 111 | return proxy; 112 | } 113 | } 114 | /** Message Constants 115 | * @type {string} */ 116 | Model.SINGLETON_MSG = "Model Singleton already constructed!"; 117 | -------------------------------------------------------------------------------- /src/patterns/command/MacroCommand.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MacroCommand.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {ICommand} from "../../interfaces/ICommand"; 10 | import {INotification} from "../../interfaces/INotification"; 11 | import {SimpleCommand} from "./SimpleCommand"; 12 | 13 | /** 14 | * A base `Command` implementation that executes other `Command`s. 15 | * 16 | * A `MacroCommand` maintains a list of 17 | * `Command` Class references called `SubCommands`. 18 | * 19 | * When `execute` is called, the `MacroCommand` 20 | * instantiates and calls `execute` on each of its `SubCommands` turn. 21 | * Each `SubCommand` will be passed a reference to the original 22 | * `Notification` that was passed to the `MacroCommand`'s 23 | * `execute` method. 24 | * 25 | * Unlike `SimpleCommand`, your subclass 26 | * should not override `execute`, but instead, should 27 | * override the `initializeMacroCommand` method, 28 | * calling `addSubCommand` once for each `SubCommand` 29 | * to be executed. 30 | * 31 | * @see {@link Controller} 32 | * @see {@link Notification} 33 | * @see {@link SimpleCommand} 34 | * 35 | * @class MacroCommand 36 | * @extends Notifier 37 | */ 38 | export class MacroCommand extends SimpleCommand { 39 | 40 | /** An array of functions, each of which returns an instance of ICommand. 41 | * @type {(() => ICommand)[]} */ 42 | private subCommands: (() => ICommand)[]; 43 | 44 | /** 45 | * Constructor. 46 | * 47 | * You should not need to define a constructor, 48 | * instead, override the `initializeMacroCommand` 49 | * method. 50 | * 51 | * If your subclass does define a constructor, be 52 | * sure to call `super()`. 53 | * 54 | */ 55 | public constructor() { 56 | super(); 57 | this.subCommands = []; 58 | this.initializeMacroCommand(); 59 | } 60 | 61 | /** 62 | * Initialize the `MacroCommand`. 63 | * 64 | * In your subclass, override this method to 65 | * initialize the `MacroCommand`'s `SubCommand` 66 | * list with `Command` class references like 67 | * this: 68 | * 69 | * ```ts 70 | * // Initialize MyMacroCommand 71 | * initializeMacroCommand() { 72 | * this.addSubCommand(() => new app.FirstCommand()); 73 | * this.addSubCommand(() => new app.SecondCommand()); 74 | * this.addSubCommand(() => new app.ThirdCommand()); 75 | * } 76 | * ``` 77 | * 78 | * Note that `SubCommand`s may be any `Command` implementor, 79 | * `MacroCommand`s or `SimpleCommands` are both acceptable. 80 | */ 81 | public initializeMacroCommand(): void { 82 | 83 | } 84 | 85 | /** 86 | * Add a `SubCommand`. 87 | * 88 | * The `SubCommands` will be called in First In/First Out (FIFO) 89 | * order. 90 | * 91 | * @param {() => ICommand} factory - A factory function that creates an instance of ICommand. This function will be used to generate the sub-command. 92 | * @returns {void} 93 | */ 94 | protected addSubCommand(factory: () => ICommand): void { 95 | this.subCommands.push(factory); 96 | } 97 | 98 | /** 99 | * Execute this `MacroCommand`'s `SubCommands`. 100 | * 101 | * The `SubCommands` will be called in First In/First Out (FIFO) 102 | * order. 103 | * 104 | * @param {INotification} notification - The notification containing the data or command details to be processed. 105 | * @returns {void} 106 | */ 107 | public execute(notification: INotification): void { 108 | while (this.subCommands.length > 0) { 109 | const factory: (() => ICommand) | undefined = this.subCommands.shift(); 110 | const command: ICommand | undefined = factory?.(); 111 | if (command) { 112 | command.execute(notification); 113 | } 114 | } 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /bin/cjs/core/Model.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // 3 | // Model.ts 4 | // PureMVC TypeScript Multicore 5 | // 6 | // Copyright(c) 2024 Saad Shams 7 | // Your reuse is governed by the BSD-3-Clause License 8 | // 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.Model = void 0; 11 | /** 12 | * A Singleton `Model` implementation. 13 | * 14 | * In PureMVC, the `Model` class provides 15 | * access to model objects (Proxies) by named lookup. 16 | * 17 | * The `Model` assumes these responsibilities: 18 | * 19 | * - Maintain a cache of `Proxy` instances. 20 | * - Provide methods for registering, retrieving, and removing 21 | * `Proxy` instances. 22 | * 23 | * Your application must register `Proxy` instances 24 | * with the `Model`. Typically, you use an 25 | * `Command` to create and register `Proxy` 26 | * instances once the `Facade` has initialized the Core 27 | * actors. 28 | * 29 | * @see {@link Proxy} 30 | * 31 | * @class Model 32 | */ 33 | class Model { 34 | /** 35 | * Constructor. 36 | * 37 | * This `Model` implementation is a Singleton, 38 | * so you should not call the constructor 39 | * directly, but instead call the static Singleton 40 | * Factory method `Model.getInstance()` 41 | * 42 | * @throws {Error} Error if instance for this Singleton instance has already been constructed 43 | */ 44 | constructor() { 45 | if (Model.instance != null) 46 | throw Error(Model.SINGLETON_MSG); 47 | Model.instance = this; 48 | this.proxyMap = {}; 49 | this.initializeModel(); 50 | } 51 | /** 52 | * Initialize the `Model` instance. 53 | * 54 | * Called automatically by the constructor, this 55 | * is your opportunity to initialize the Singleton 56 | * instance in your subclass without overriding the 57 | * constructor. 58 | * 59 | * @returns {void} 60 | */ 61 | initializeModel() { 62 | } 63 | /** 64 | * `Model` Singleton Factory method. 65 | * 66 | * @param {() => IModel} factory - A factory function that creates a new instance of the model if one does not already exist. 67 | * @returns {IModel} The Singleton instance. 68 | */ 69 | static getInstance(factory) { 70 | if (Model.instance == null) 71 | Model.instance = factory(); 72 | return Model.instance; 73 | } 74 | /** 75 | * Register a `Proxy` with the `Model`. 76 | * 77 | * @param {IProxy} proxy - The proxy instance to be registered. 78 | * @returns {void} 79 | */ 80 | registerProxy(proxy) { 81 | this.proxyMap[proxy.name] = proxy; 82 | proxy.onRegister(); 83 | } 84 | /** 85 | * Retrieve a `Proxy` from the `Model`. 86 | * 87 | * @param {string} proxyName - The name of the proxy to retrieve. 88 | * @returns {IProxy | null} The proxy instance associated with the given name, or `null` if no such proxy exists. 89 | */ 90 | retrieveProxy(proxyName) { 91 | return this.proxyMap[proxyName] || null; 92 | } 93 | /** 94 | * Check if a Proxy is registered 95 | * 96 | * @param {string} proxyName - The name of the proxy to check. 97 | * @returns {boolean} `true` if a proxy with the specified name is registered; otherwise, `false`. 98 | */ 99 | hasProxy(proxyName) { 100 | return this.proxyMap[proxyName] != null; 101 | } 102 | /** 103 | * Remove a `Proxy` from the `Model`. 104 | * 105 | * @param {string} proxyName - The name of the proxy to be removed. 106 | * @returns {IProxy | null} The removed proxy instance, or `null` if no proxy with the given name was found. 107 | */ 108 | removeProxy(proxyName) { 109 | const proxy = this.proxyMap[proxyName]; 110 | if (!proxy) 111 | return null; 112 | delete this.proxyMap[proxyName]; 113 | proxy.onRemove(); 114 | return proxy; 115 | } 116 | } 117 | exports.Model = Model; 118 | /** Message Constants 119 | * @type {string} */ 120 | Model.SINGLETON_MSG = "Model Singleton already constructed!"; 121 | -------------------------------------------------------------------------------- /src/interfaces/IView.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IView.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IMediator} from "./IMediator"; 10 | import {INotification} from "./INotification"; 11 | import {IObserver} from "./IObserver"; 12 | 13 | /** 14 | * `IView` The interface definition for a PureMVC `View`. 15 | * 16 | * In PureMVC, the View class assumes these responsibilities: 17 | * 18 | * - Maintain a cache of `IMediator` instances. 19 | * 20 | * - Provide methods for registering, retrieving, and removing `IMediators`. 21 | * 22 | * - Managing the observer lists for each `INotification` in the application. 23 | * 24 | * - Providing a method for attaching `IObservers` to an `INotification`'s observer list. 25 | * 26 | * - Providing a method for broadcasting an `INotification`. 27 | * 28 | * - Notifying the `IObservers` of a given `INotification` when it is broadcast. 29 | * 30 | * @interface IView 31 | */ 32 | export interface IView { 33 | 34 | /** 35 | * Register an `IObserver` to be notified 36 | * of `INotifications` with a given name. 37 | * 38 | * @param {string} notificationName - The name of the notification to register the observer for. 39 | * @param {IObserver} observer - The observer to be registered. 40 | * @returns {void} 41 | */ 42 | registerObserver(notificationName: string, observer: IObserver): void; 43 | 44 | /** 45 | * Notify the `IObservers` for a particular `INotification`. 46 | * 47 | * All previously attached `IObservers` for this `INotification`'s 48 | * list are notified and are passed a reference to the `INotification` in 49 | * the order in which they were registered. 50 | * 51 | * @param {INotification} notification - the `INotification` to notify `IObservers` of. 52 | * @returns {void} 53 | */ 54 | notifyObservers(notification: INotification): void; 55 | 56 | /** 57 | * Remove a group of observers from the observer list for a given Notification name. 58 | * 59 | * @param {string} notificationName - which observer list to remove from 60 | * @param {any} notifyContext - removed the observers with this object as their `notifyContext` 61 | * @returns {void} 62 | */ 63 | removeObserver(notificationName: string, notifyContext: any): void; 64 | 65 | /** 66 | * Register an `IMediator` instance with the View. 67 | * 68 | * Registers the `IMediator` so that it can be retrieved by name, 69 | * and further interrogates the `IMediator` for its 70 | * `INotification` interests. 71 | * 72 | * If the `IMediator` returns any `INotification` 73 | * names to be notified about, an `Observer` is created encapsulating 74 | * the `IMediator` instance's `handleNotification` method 75 | * and registering it as an `Observer` for all `INotifications` the 76 | * `IMediator` is interested in. 77 | * 78 | * @param {IMediator} mediator - The `IMediator` to be registered. 79 | * @returns {void} 80 | */ 81 | registerMediator(mediator: IMediator): void; 82 | 83 | /** 84 | * Retrieve an `IMediator` from the View. 85 | * 86 | * @param {string} mediatorName - the name of the `IMediator` instance to retrieve. 87 | * @returns {IMediator | null} The `IMediator` associated with the given name, or `null` if not found. 88 | */ 89 | retrieveMediator(mediatorName: string): IMediator | null; 90 | 91 | /** 92 | * Check if a `IMediator` is registered or not 93 | * 94 | * @param {string} mediatorName - The name of the `IMediator` to check. 95 | * @returns {boolean} `true` if the `IMediator` is registered, otherwise `false`. 96 | */ 97 | hasMediator(mediatorName: string): boolean; 98 | 99 | /** 100 | * Remove an `IMediator` from the View. 101 | * 102 | * @param {string} mediatorName - name of the `IMediator` instance to be removed. 103 | * @returns {IMediator | null} The removed `IMediator`, or `null` if not found. 104 | */ 105 | removeMediator(mediatorName: string): IMediator | null; 106 | } 107 | -------------------------------------------------------------------------------- /src/patterns/observer/Notification.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Notification.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotification} from "../../interfaces/INotification"; 10 | 11 | /** 12 | * A base `Notification` implementation. 13 | * 14 | * PureMVC does not rely upon underlying event models such 15 | * as the one provided with Flash, and ActionScript 3 does 16 | * not have an inherent event model. 17 | * 18 | * The Observer Pattern as implemented within PureMVC exists 19 | * to support event-driven communication between the 20 | * application and the actors of the MVC triad. 21 | * 22 | * Notifications are not meant to be a replacement for Events 23 | * in Flex/Flash/Apollo. Generally, `Mediator` implementors 24 | * place event listeners on their view components, which they 25 | * then handle in the usual way. This may lead to the broadcast of `Notification`s to 26 | * trigger `Command`s or to communicate with other `Mediators`. `Proxy` and `Command` 27 | * instances communicate with each other and `Mediator`s 28 | * by broadcasting `Notification`s. 29 | * 30 | * A key difference between Flash `Event`s and PureMVC 31 | * `Notification`s is that `Event`s follow the 32 | * 'Chain of Responsibility' pattern, 'bubbling' up the display hierarchy 33 | * until some parent component handles the `Event`, while 34 | * PureMVC `Notification`s follow a 'Publish/Subscribe' 35 | * pattern. PureMVC classes need not be related to each other in a 36 | * parent/child relationship in order to communicate with one another 37 | * using `Notification`s. 38 | * 39 | * @class Notification 40 | */ 41 | export class Notification implements INotification { 42 | 43 | /** the name of the notification instance 44 | * @type {string} */ 45 | private readonly _name: string; 46 | 47 | /** the body of the notification instance 48 | * @type {any} */ 49 | private _body?: any; 50 | 51 | /** 52 | * @type {string | undefined } */ 53 | private _type?: string | undefined; 54 | 55 | /** 56 | * Constructor. 57 | * 58 | * @param {string} name - The name of the notification. 59 | * @param {any} [body] - Optional data to be included with the notification. 60 | * @param {string} [type] - Optional type of the notification. 61 | */ 62 | public constructor(name: string, body?: any, type?: string) { 63 | this._name = name; 64 | this._body = body; 65 | this._type = type; 66 | } 67 | 68 | /** 69 | * Get the name of the `Notification` instance. 70 | * 71 | * @returns {string} The name of the notification. 72 | */ 73 | public get name(): string { 74 | return this._name; 75 | } 76 | 77 | /** 78 | * Get the body of the `Notification` instance. 79 | * 80 | * @returns {any} The body of the notification. 81 | */ 82 | public get body(): any { 83 | return this._body; 84 | } 85 | 86 | /** 87 | * Set the body of the `Notification` instance. 88 | * 89 | * @param {any} value - The new body to be set for the notification. 90 | */ 91 | public set body(value: any) { 92 | this._body = value; 93 | } 94 | 95 | /** 96 | * Get the type of the `Notification` instance. 97 | * 98 | * @returns {string | undefined} The type of the notification, or `undefined` if not set. 99 | */ 100 | public get type(): string | undefined { 101 | return this._type; 102 | } 103 | 104 | /** 105 | * Set the type of the `Notification` instance. 106 | * 107 | * @param {string | undefined} value - The new type to be set for the notification. 108 | */ 109 | public set type(value: string | undefined) { 110 | this._type = value; 111 | } 112 | 113 | /** 114 | * Get the string representation of the `Notification` instance. 115 | * 116 | * @returns {string} A string representation of the notification. 117 | */ 118 | public toString(): string { 119 | let msg: string = `Notification Name: ${this.name}`; 120 | msg += `\nBody: ${this.body ? this.body : "null"}`; 121 | msg += `\nType: ${this.type ?? "null"}`; 122 | return msg; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /test/core/Model.spec.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Model.spec.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IModel, Model, IProxy, Proxy} from "../../src"; 10 | import {ModelTestProxy} from "./ModelTestProxy"; 11 | 12 | /** 13 | * Test the PureMVC Model class. 14 | */ 15 | describe("ModelTest", () => { 16 | 17 | /** 18 | * Tests the Model Singleton Factory Method 19 | */ 20 | test("testGetInstance", () => { 21 | // Test Factory Method 22 | const model: IModel = Model.getInstance(() => new Model()); 23 | 24 | // test assertions 25 | expect(model).toBeDefined(); 26 | }); 27 | 28 | /** 29 | * Tests the proxy registration and retrieval methods. 30 | * 31 | * 32 | * Tests `registerProxy` and `retrieveProxy` in the same test. 33 | * These methods cannot currently be tested separately 34 | * in any meaningful way other than to show that the 35 | * methods do not throw exception when called. 36 | */ 37 | test("testRegisterAndRetrieveProxy", () => { 38 | // register a proxy and retrieve it. 39 | const model: IModel = Model.getInstance(() => new Model()); 40 | model.registerProxy(new Proxy("colors", ["red", "green", "blue"])); 41 | const proxy: IProxy | null = model.retrieveProxy("colors"); 42 | expect(proxy).toBeDefined(); 43 | const data = proxy?.data as string[]; 44 | 45 | // test assertions 46 | expect(data).not.toBeNull(); 47 | expect(data).toBeInstanceOf(Array); 48 | expect(data.length).toBe(3); 49 | expect(data[0]).toBe("red"); 50 | expect(data[1]).toBe("green"); 51 | expect(data[2]).toBe("blue"); 52 | }); 53 | 54 | /** 55 | * Tests the proxy removal method. 56 | */ 57 | test("testRegisterAndRemoveProxy", () => { 58 | // register a proxy, remove it, then try to retrieve it 59 | const model: IModel = Model.getInstance(() => new Model()); 60 | const proxy: IProxy = new Proxy("sizes", ["7", "13", "21"]); 61 | model.registerProxy(proxy); 62 | 63 | // remove the proxy 64 | const removedProxy: IProxy | null = model.removeProxy("sizes"); 65 | 66 | // assert that we removed the appropriate proxy 67 | expect(removedProxy).not.toBeNull(); 68 | expect(removedProxy?.name).toBe("sizes"); 69 | 70 | // ensure that the proxy is no longer retrievable from the model 71 | const proxy1 = model.retrieveProxy("sizes"); 72 | 73 | // test assertions 74 | expect(proxy1).toBeNull(); 75 | }); 76 | 77 | /** 78 | * Tests the hasProxy Method 79 | */ 80 | test("testHasProxy", () => { 81 | // register a proxy 82 | const model: IModel = Model.getInstance(() => new Model()); 83 | const proxy: IProxy = new Proxy("aces", ["clubs", "spades", "hearts", "diamonds"]); 84 | model.registerProxy(proxy); 85 | 86 | // assert that the model.hasProxy method returns true 87 | // for that proxy name 88 | expect(model.hasProxy("aces")).toBeTruthy(); 89 | 90 | // remove the proxy 91 | model.removeProxy("aces"); 92 | 93 | // assert that the model.hasProxy method returns false 94 | // for that proxy name 95 | expect(model.hasProxy("aces")).toBeFalsy(); 96 | }); 97 | 98 | /** 99 | * Tests that the Model calls the onRegister and onRemove methods 100 | */ 101 | test("testOnRegisterAndOnRemove", () => { 102 | // Get a Singleton Model instance 103 | const model: IModel = Model.getInstance(() => new Model()); 104 | 105 | // Create and register the test proxy 106 | const proxy: IProxy = new ModelTestProxy(); 107 | model.registerProxy(proxy); 108 | 109 | // assert that onRegister was called, and the proxy responded by setting its data accordingly 110 | expect(proxy.data).toBe(ModelTestProxy.ON_REGISTER_CALLED); 111 | 112 | // Remove the component 113 | model.removeProxy(ModelTestProxy.NAME); 114 | 115 | // assert that onRemove was called, and the proxy responded by setting its data accordingly 116 | expect(proxy.data).toBe(ModelTestProxy.ON_REMOVE_CALLED); 117 | }); 118 | 119 | }); 120 | -------------------------------------------------------------------------------- /src/core/Model.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Model.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {IModel} from "../interfaces/IModel"; 10 | import {IProxy} from "../interfaces/IProxy"; 11 | 12 | /** 13 | * A Singleton `Model` implementation. 14 | * 15 | * In PureMVC, the `Model` class provides 16 | * access to model objects (Proxies) by named lookup. 17 | * 18 | * The `Model` assumes these responsibilities: 19 | * 20 | * - Maintain a cache of `Proxy` instances. 21 | * - Provide methods for registering, retrieving, and removing 22 | * `Proxy` instances. 23 | * 24 | * Your application must register `Proxy` instances 25 | * with the `Model`. Typically, you use an 26 | * `Command` to create and register `Proxy` 27 | * instances once the `Facade` has initialized the Core 28 | * actors. 29 | * 30 | * @see {@link Proxy} 31 | * 32 | * @class Model 33 | */ 34 | export class Model implements IModel { 35 | 36 | /** Message Constants 37 | * @type {string} */ 38 | protected static SINGLETON_MSG: string = "Model Singleton already constructed!"; 39 | 40 | /** 41 | * Singleton instance 42 | * 43 | * @type {IModel} 44 | * @protected 45 | */ 46 | protected static instance: IModel; 47 | 48 | /** Mapping of proxyNames to IProxy instances 49 | * @type {{ [key: string]: IProxy }} */ 50 | protected proxyMap: { [key: string]: IProxy }; 51 | 52 | /** 53 | * Constructor. 54 | * 55 | * This `Model` implementation is a Singleton, 56 | * so you should not call the constructor 57 | * directly, but instead call the static Singleton 58 | * Factory method `Model.getInstance()` 59 | * 60 | * @throws {Error} Error if instance for this Singleton instance has already been constructed 61 | */ 62 | public constructor() { 63 | if (Model.instance != null) throw Error(Model.SINGLETON_MSG); 64 | Model.instance = this; 65 | this.proxyMap = {}; 66 | this.initializeModel(); 67 | } 68 | 69 | /** 70 | * Initialize the `Model` instance. 71 | * 72 | * Called automatically by the constructor, this 73 | * is your opportunity to initialize the Singleton 74 | * instance in your subclass without overriding the 75 | * constructor. 76 | * 77 | * @returns {void} 78 | */ 79 | protected initializeModel(): void { 80 | } 81 | 82 | /** 83 | * `Model` Singleton Factory method. 84 | * 85 | * @param {() => IModel} factory - A factory function that creates a new instance of the model if one does not already exist. 86 | * @returns {IModel} The Singleton instance. 87 | */ 88 | public static getInstance(factory: () => IModel): IModel { 89 | if (Model.instance == null) 90 | Model.instance = factory(); 91 | return Model.instance; 92 | } 93 | 94 | /** 95 | * Register a `Proxy` with the `Model`. 96 | * 97 | * @param {IProxy} proxy - The proxy instance to be registered. 98 | * @returns {void} 99 | */ 100 | public registerProxy(proxy: IProxy): void { 101 | this.proxyMap[proxy.name] = proxy; 102 | proxy.onRegister(); 103 | } 104 | 105 | /** 106 | * Retrieve a `Proxy` from the `Model`. 107 | * 108 | * @param {string} proxyName - The name of the proxy to retrieve. 109 | * @returns {IProxy | null} The proxy instance associated with the given name, or `null` if no such proxy exists. 110 | */ 111 | public retrieveProxy(proxyName: string): IProxy | null { 112 | return this.proxyMap[proxyName] || null; 113 | } 114 | 115 | /** 116 | * Check if a Proxy is registered 117 | * 118 | * @param {string} proxyName - The name of the proxy to check. 119 | * @returns {boolean} `true` if a proxy with the specified name is registered; otherwise, `false`. 120 | */ 121 | public hasProxy(proxyName: string): boolean { 122 | return this.proxyMap[proxyName] != null; 123 | } 124 | 125 | /** 126 | * Remove a `Proxy` from the `Model`. 127 | * 128 | * @param {string} proxyName - The name of the proxy to be removed. 129 | * @returns {IProxy | null} The removed proxy instance, or `null` if no proxy with the given name was found. 130 | */ 131 | public removeProxy(proxyName: string): IProxy | null { 132 | const proxy: IProxy = this.proxyMap[proxyName]; 133 | if (!proxy) return null; 134 | 135 | delete this.proxyMap[proxyName]; 136 | proxy.onRemove(); 137 | return proxy; 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /bin/types/interfaces/IFacade.d.ts: -------------------------------------------------------------------------------- 1 | import { INotifier } from "./INotifier"; 2 | import { ICommand } from "./ICommand"; 3 | import { IMediator } from "./IMediator"; 4 | import { INotification } from "./INotification"; 5 | import { IProxy } from "./IProxy"; 6 | /** 7 | * `IFacade` The interface definition for a PureMVC `Facade`. 8 | * 9 | * The `Facade` Pattern suggests providing a single 10 | * class to act as a central point of communication 11 | * for a subsystem. 12 | * 13 | * In PureMVC, the `Facade` acts as an interface between 14 | * the core MVC actors (`Model`, `View`, `Controller`) and 15 | * the rest of your application. 16 | * 17 | * @interface IFacade 18 | * @extends {INotifier} 19 | */ 20 | export interface IFacade extends INotifier { 21 | /** 22 | * Register an `ICommand` with the `Controller` 23 | * 24 | * @param {string} notificationName - the name of the `INotification` to associate the `ICommand` with. 25 | * @param {() => ICommand} factory - A factory that creates an instance of the `ICommand` to be registered. 26 | * @returns {void} 27 | */ 28 | registerCommand(notificationName: string, factory: () => ICommand): void; 29 | /** 30 | * Check if a `ICommand` is registered for a given `Notification` 31 | * 32 | * @param {string} notificationName - The name of the notification to check. 33 | * @returns {boolean} `true` if a command is registered for the notification name, `false` otherwise. 34 | */ 35 | hasCommand(notificationName: string): boolean; 36 | /** 37 | * Remove a previously registered `ICommand` to `INotification` mapping from the `Controller`. 38 | * 39 | * @param {string} notificationName - the name of the `INotification` to remove the `ICommand` mapping for 40 | * @returns {void} 41 | */ 42 | removeCommand(notificationName: string): void; 43 | /** 44 | * Register an `IProxy` with the `Model` by name. 45 | * 46 | * @param {IProxy} proxy - the IProxy to be registered with the Model. 47 | * @returns {void} 48 | */ 49 | registerProxy(proxy: IProxy): void; 50 | /** 51 | * Retrieve a `IProxy` from the `Model` by name. 52 | * 53 | * @param {string} proxyName - the name of the `IProxy` instance to be retrieved. 54 | * @returns {IProxy | null} the `IProxy` previously registered by `proxyName` with the `Model`. 55 | */ 56 | retrieveProxy(proxyName: string): IProxy | null; 57 | /** 58 | * Check if a `Proxy` is registered 59 | * 60 | * @param {string} proxyName - The name of the proxy to check. 61 | * @returns {boolean} `true` if a proxy is registered with the name, `false` otherwise. 62 | */ 63 | hasProxy(proxyName: string): boolean; 64 | /** 65 | * Remove an `IProxy` instance from the `Model` by name. 66 | * 67 | * @param {string} proxyName - the `IProxy` to remove from the `Model`. 68 | * @returns {IProxy | null} The removed proxy instance if found, or `null` if no proxy was registered with the given name. 69 | */ 70 | removeProxy(proxyName: string): IProxy | null; 71 | /** 72 | * Register an `IMediator` instance with the `View`. 73 | * 74 | * @param {IMediator} mediator - a reference to the `IMediator` instance 75 | * @returns {void} 76 | */ 77 | registerMediator(mediator: IMediator): void; 78 | /** 79 | * Retrieve an `IMediator` instance from the `View`. 80 | * 81 | * @param {string} mediatorName - the name of the `IMediator` instance to retrieve 82 | * @returns {IMediator | null} The mediator instance if found, or `null` if no mediator is registered with the given name. 83 | */ 84 | retrieveMediator(mediatorName: string): IMediator | null; 85 | /** 86 | * Check if a `Mediator` is registered or not 87 | * 88 | * @param {string} mediatorName - The name of the mediator to check. 89 | * @returns {boolean} `true` if a mediator is registered with the name, `false` otherwise. 90 | */ 91 | hasMediator(mediatorName: string): boolean; 92 | /** 93 | * Remove a `IMediator` instance from the `View`. 94 | * 95 | * @param {string} mediatorName - The name of the mediator to remove. 96 | * @returns {IMediator | null} The removed mediator instance if found, or `null` if no mediator was registered with the given name. 97 | */ 98 | removeMediator(mediatorName: string): IMediator | null; 99 | /** 100 | * Notify Observers. 101 | * 102 | * This method is left public mostly for backward 103 | * compatibility, and to allow you to send custom 104 | * notification classes using the facade. 105 | * 106 | * Usually you should just call `sendNotification` 107 | * and pass the parameters, never having to 108 | * construct the notification yourself. 109 | * 110 | * @param {INotification} notification - the `INotification` to have the `View` notify `Observers` of. 111 | * @returns {void} 112 | */ 113 | notifyObservers(notification: INotification): void; 114 | } 115 | -------------------------------------------------------------------------------- /src/interfaces/IFacade.ts: -------------------------------------------------------------------------------- 1 | // 2 | // IFacade.ts 3 | // PureMVC TypeScript Standard 4 | // 5 | // Copyright(c) 2024 Saad Shams 6 | // Your reuse is governed by the BSD-3-Clause License 7 | // 8 | 9 | import {INotifier} from "./INotifier"; 10 | import {ICommand} from "./ICommand"; 11 | import {IMediator} from "./IMediator"; 12 | import {INotification} from "./INotification"; 13 | import {IProxy} from "./IProxy"; 14 | 15 | /** 16 | * `IFacade` The interface definition for a PureMVC `Facade`. 17 | * 18 | * The `Facade` Pattern suggests providing a single 19 | * class to act as a central point of communication 20 | * for a subsystem. 21 | * 22 | * In PureMVC, the `Facade` acts as an interface between 23 | * the core MVC actors (`Model`, `View`, `Controller`) and 24 | * the rest of your application. 25 | * 26 | * @interface IFacade 27 | * @extends {INotifier} 28 | */ 29 | export interface IFacade extends INotifier { 30 | 31 | /** 32 | * Register an `ICommand` with the `Controller` 33 | * 34 | * @param {string} notificationName - the name of the `INotification` to associate the `ICommand` with. 35 | * @param {() => ICommand} factory - A factory that creates an instance of the `ICommand` to be registered. 36 | * @returns {void} 37 | */ 38 | registerCommand(notificationName: string, factory: () => ICommand): void; 39 | 40 | /** 41 | * Check if a `ICommand` is registered for a given `Notification` 42 | * 43 | * @param {string} notificationName - The name of the notification to check. 44 | * @returns {boolean} `true` if a command is registered for the notification name, `false` otherwise. 45 | */ 46 | hasCommand(notificationName: string): boolean; 47 | 48 | /** 49 | * Remove a previously registered `ICommand` to `INotification` mapping from the `Controller`. 50 | * 51 | * @param {string} notificationName - the name of the `INotification` to remove the `ICommand` mapping for 52 | * @returns {void} 53 | */ 54 | removeCommand(notificationName: string): void; 55 | 56 | /** 57 | * Register an `IProxy` with the `Model` by name. 58 | * 59 | * @param {IProxy} proxy - the IProxy to be registered with the Model. 60 | * @returns {void} 61 | */ 62 | registerProxy(proxy: IProxy): void; 63 | 64 | /** 65 | * Retrieve a `IProxy` from the `Model` by name. 66 | * 67 | * @param {string} proxyName - the name of the `IProxy` instance to be retrieved. 68 | * @returns {IProxy | null} the `IProxy` previously registered by `proxyName` with the `Model`. 69 | */ 70 | retrieveProxy(proxyName: string): IProxy | null; 71 | 72 | /** 73 | * Check if a `Proxy` is registered 74 | * 75 | * @param {string} proxyName - The name of the proxy to check. 76 | * @returns {boolean} `true` if a proxy is registered with the name, `false` otherwise. 77 | */ 78 | hasProxy(proxyName: string): boolean; 79 | 80 | /** 81 | * Remove an `IProxy` instance from the `Model` by name. 82 | * 83 | * @param {string} proxyName - the `IProxy` to remove from the `Model`. 84 | * @returns {IProxy | null} The removed proxy instance if found, or `null` if no proxy was registered with the given name. 85 | */ 86 | removeProxy(proxyName: string): IProxy | null; 87 | 88 | /** 89 | * Register an `IMediator` instance with the `View`. 90 | * 91 | * @param {IMediator} mediator - a reference to the `IMediator` instance 92 | * @returns {void} 93 | */ 94 | registerMediator(mediator: IMediator): void; 95 | 96 | /** 97 | * Retrieve an `IMediator` instance from the `View`. 98 | * 99 | * @param {string} mediatorName - the name of the `IMediator` instance to retrieve 100 | * @returns {IMediator | null} The mediator instance if found, or `null` if no mediator is registered with the given name. 101 | */ 102 | retrieveMediator(mediatorName: string): IMediator | null; 103 | 104 | /** 105 | * Check if a `Mediator` is registered or not 106 | * 107 | * @param {string} mediatorName - The name of the mediator to check. 108 | * @returns {boolean} `true` if a mediator is registered with the name, `false` otherwise. 109 | */ 110 | hasMediator(mediatorName: string): boolean; 111 | 112 | /** 113 | * Remove a `IMediator` instance from the `View`. 114 | * 115 | * @param {string} mediatorName - The name of the mediator to remove. 116 | * @returns {IMediator | null} The removed mediator instance if found, or `null` if no mediator was registered with the given name. 117 | */ 118 | removeMediator(mediatorName: string): IMediator | null; 119 | 120 | /** 121 | * Notify Observers. 122 | * 123 | * This method is left public mostly for backward 124 | * compatibility, and to allow you to send custom 125 | * notification classes using the facade. 126 | * 127 | * Usually you should just call `sendNotification` 128 | * and pass the parameters, never having to 129 | * construct the notification yourself. 130 | * 131 | * @param {INotification} notification - the `INotification` to have the `View` notify `Observers` of. 132 | * @returns {void} 133 | */ 134 | notifyObservers(notification: INotification): void; 135 | 136 | } 137 | -------------------------------------------------------------------------------- /bin/types/core/Controller.d.ts: -------------------------------------------------------------------------------- 1 | import { IController } from "../interfaces/IController"; 2 | import { IView } from "../interfaces/IView"; 3 | import { ICommand } from "../interfaces/ICommand"; 4 | import { INotification } from "../interfaces/INotification"; 5 | /** 6 | * A Singleton `Controller` implementation. 7 | * 8 | * In PureMVC, the `Controller` class follows the 9 | * 'Command and Controller' strategy, and assumes these 10 | * responsibilities: 11 | * 12 | * 13 | * - Remembering which `Command`s 14 | * are intended to handle which `Notifications`. 15 | * - Registering itself as an `Observer` with 16 | * the `View` for each `Notification` 17 | * that it has a `Command` mapping for. 18 | * - Creating a new instance of the proper `Command` 19 | * to handle a given `Notification` when notified by the `View`. 20 | * - Calling the `Command`'s `execute` 21 | * method, passing in the `Notification`. 22 | * 23 | * 24 | * Your application must register `Commands` with the 25 | * Controller. 26 | * 27 | * The simplest way is to subclass `Facade`, 28 | * and use its `initializeController` method to add your 29 | * registrations. 30 | * 31 | * @see {@link View} 32 | * @see {@link Observer} 33 | * @see {@link Notification} 34 | * @see {@link SimpleCommand} 35 | * @see {@link MacroCommand} 36 | * 37 | * @class Controller 38 | */ 39 | export declare class Controller implements IController { 40 | /** Message Constants 41 | * @type {string} */ 42 | protected static SINGLETON_MSG: string; 43 | /** 44 | * Singleton instance 45 | * 46 | * @type {IController} 47 | * @protected 48 | */ 49 | protected static instance: IController; 50 | /** Local reference to View 51 | * @type {IView | undefined} */ 52 | protected view?: IView; 53 | /** Mapping of Notification names to Command factories 54 | * @type {{ [key: string]: () => ICommand }} */ 55 | protected commandMap: { 56 | [key: string]: () => ICommand; 57 | }; 58 | /** 59 | * Constructor. 60 | * 61 | * This `Controller` implementation is a Singleton, 62 | * so you should not call the constructor 63 | * directly, but instead call the static Singleton Factory method, 64 | * `Controller.getInstance()` 65 | * 66 | * @throws {Error} Error if instance for this Singleton has already been constructed 67 | */ 68 | constructor(); 69 | /** 70 | * Initialize the Singleton `Controller` instance. 71 | * 72 | * Called automatically by the constructor. 73 | * 74 | * Note that if you are using a subclass of `View` 75 | * in your application, you should also subclass `Controller` 76 | * and override the `initializeController` method in the 77 | * following way: 78 | * 79 | * ```ts 80 | * // ensure that the Controller is talking to my View implementation 81 | * initializeController() { 82 | * this.view = MyView.getInstance(() => new View()); 83 | * } 84 | * ``` 85 | * @returns {void} 86 | */ 87 | protected initializeController(): void; 88 | /** 89 | * `Controller` Singleton Factory method. 90 | * 91 | * @param {() => IController} factory - A factory function that creates a new instance of the controller if one does not already exist. 92 | * @returns {IController} the Singleton instance of `Controller`. 93 | */ 94 | static getInstance(factory: () => IController): IController; 95 | /** 96 | * Register a particular `Command` class as the handler 97 | * for a particular `Notification`. 98 | * 99 | * If an `Command` has already been registered to 100 | * handle `Notification`s with this name, it is no longer 101 | * used, the new `Command` is used instead. 102 | * 103 | * The Observer for the new Command is only created if this the 104 | * first time a Command has been registered for this Notification name. 105 | * 106 | * @param {string} notificationName - The name of the notification to associate with the command. 107 | * @param {() => ICommand} factory - A factory function that returns an instance of the command. 108 | * @returns {void} 109 | */ 110 | registerCommand(notificationName: string, factory: () => ICommand): void; 111 | /** 112 | * If a `Command` has previously been registered 113 | * to handle the given `Notification`, then it is executed. 114 | * 115 | * @param {INotification} notification - The notification containing the data or command details needed for execution. 116 | * @returns {void} 117 | */ 118 | executeCommand(notification: INotification): void; 119 | /** 120 | * Check if a Command is registered for a given Notification 121 | * 122 | * @param {string} notificationName - The name of the notification to check for a registered command. 123 | * @returns {boolean} `true` if a command is registered for the specified notification name; otherwise, `false`. 124 | */ 125 | hasCommand(notificationName: string): boolean; 126 | /** 127 | * Remove a previously registered `Command` to `Notification` mapping. 128 | * 129 | * @param {string} notificationName - The name of the notification for which the associated command should be removed. 130 | * @returns {void} 131 | */ 132 | removeCommand(notificationName: string): void; 133 | } 134 | --------------------------------------------------------------------------------