@robotlegsjs/macrobot
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -19,2 +19,12 @@ # RobotlegsJS Macrobot Changelog: | ||
### [v0.2.1](https://github.com/RobotlegsJS/RobotlegsJS-Macrobot/releases/tag/0.2.1) - 2018-09-16 | ||
- Update @robotlegsjs/core to version 0.2.1 (see #67). | ||
- Update `karma` setup to generate code coverage report only for `src` folder (see #65). | ||
- Map payloads into the context of macro commands (see #49 and #68). | ||
- Update dev dependencies to latest version. | ||
### [v0.2.0](https://github.com/RobotlegsJS/RobotlegsJS-Macrobot/releases/tag/0.2.0) - 2018-08-02 | ||
@@ -21,0 +31,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { ContainerModule, IClass, ICommand, IInjector, IContext } from "@robotlegsjs/core"; | ||
import { CommandPayload, ContainerModule, IClass, ICommand, IInjector, IContext } from "@robotlegsjs/core"; | ||
import { IMacro } from "../api/IMacro"; | ||
@@ -10,2 +10,3 @@ import { ISubCommandMapping } from "../api/ISubCommandMapping"; | ||
protected _injector: IInjector; | ||
protected _macroPayload: CommandPayload; | ||
protected _mappings: SubCommandMappingList; | ||
@@ -17,3 +18,6 @@ protected _payloadsModule: ContainerModule; | ||
abstract prepare(): void; | ||
protected captureMacroPayload(executeArguments: IArguments): void; | ||
protected executeCommand(mapping: ISubCommandMapping): void; | ||
protected mapMacroPayload(payload: CommandPayload): void; | ||
protected unmapMacroPayload(payload: CommandPayload): void; | ||
protected mapPayloads(payloads: Array<ISubCommandPayload<any>>): void; | ||
@@ -20,0 +24,0 @@ protected unmapPayloads(payloads: Array<ISubCommandPayload<any>>): void; |
@@ -19,4 +19,4 @@ "use strict"; | ||
_this._injector = injector.createChild(); | ||
_this._macroPayload = new core_1.CommandPayload(); | ||
_this._mappings = new SubCommandMappingList_1.SubCommandMappingList(); | ||
_this.prepare(); | ||
return _this; | ||
@@ -32,2 +32,8 @@ } | ||
}; | ||
AbstractMacro.prototype.captureMacroPayload = function (executeArguments) { | ||
var i = 0; | ||
for (i = 0; i < executeArguments.length; i++) { | ||
this._macroPayload.addPayload(executeArguments[i], executeArguments[i].constructor); | ||
} | ||
}; | ||
AbstractMacro.prototype.executeCommand = function (mapping) { | ||
@@ -38,2 +44,3 @@ var command; | ||
var hasPayloads = payloads.length > 0; | ||
this.mapMacroPayload(this._macroPayload); | ||
if (hasPayloads) { | ||
@@ -53,2 +60,3 @@ this.mapPayloads(payloads); | ||
} | ||
this.unmapMacroPayload(this._macroPayload); | ||
if (command) { | ||
@@ -68,2 +76,14 @@ var isAsync = command.constructor.prototype.registerCompleteCallback !== undefined; | ||
}; | ||
AbstractMacro.prototype.mapMacroPayload = function (payload) { | ||
var i = payload.length; | ||
while (i--) { | ||
this._injector.bind(payload.classes[i]).toConstantValue(payload.values[i]); | ||
} | ||
}; | ||
AbstractMacro.prototype.unmapMacroPayload = function (payload) { | ||
var i = payload.length; | ||
while (i--) { | ||
this._injector.unbind(payload.classes[i]); | ||
} | ||
}; | ||
AbstractMacro.prototype.mapPayloads = function (payloads) { | ||
@@ -70,0 +90,0 @@ this._payloadsModule = new core_1.ContainerModule(function (bind, unbind) { |
@@ -8,4 +8,4 @@ import { IContext } from "@robotlegsjs/core"; | ||
registerCompleteCallback(listener: Function): void; | ||
abstract execute(): void; | ||
abstract execute(...args: any[]): void; | ||
protected dispatchComplete(success: boolean): void; | ||
} |
@@ -8,3 +8,3 @@ import { IMacro } from "../api/IMacro"; | ||
private _commands; | ||
execute(): void; | ||
execute(payload?: any, ...payloads: any[]): void; | ||
private readonly hasCommands; | ||
@@ -11,0 +11,0 @@ protected commandCompleteHandler(success: boolean): void; |
@@ -10,2 +10,3 @@ "use strict"; | ||
var tslib_1 = require("tslib"); | ||
var core_1 = require("@robotlegsjs/core"); | ||
var AbstractMacro_1 = require("./AbstractMacro"); | ||
@@ -21,3 +22,9 @@ var ParallelMacro = /** @class */ (function (_super) { | ||
} | ||
ParallelMacro.prototype.execute = function () { | ||
ParallelMacro.prototype.execute = function (payload) { | ||
var payloads = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
payloads[_i - 1] = arguments[_i]; | ||
} | ||
this.captureMacroPayload(arguments); | ||
this.prepare(); | ||
this._commands = this._mappings.getList(); | ||
@@ -58,2 +65,5 @@ if (this.hasCommands) { | ||
}; | ||
ParallelMacro = tslib_1.__decorate([ | ||
core_1.injectable() | ||
], ParallelMacro); | ||
return ParallelMacro; | ||
@@ -60,0 +70,0 @@ }(AbstractMacro_1.AbstractMacro)); |
@@ -12,3 +12,3 @@ import { IMacro } from "../api/IMacro"; | ||
atomic: boolean; | ||
execute(): void; | ||
execute(payload?: any, ...payloads: any[]): void; | ||
protected executeNext(): void; | ||
@@ -15,0 +15,0 @@ private readonly hasCommands; |
@@ -10,2 +10,3 @@ "use strict"; | ||
var tslib_1 = require("tslib"); | ||
var core_1 = require("@robotlegsjs/core"); | ||
var AbstractMacro_1 = require("./AbstractMacro"); | ||
@@ -29,3 +30,9 @@ var SequenceMacro = /** @class */ (function (_super) { | ||
}); | ||
SequenceMacro.prototype.execute = function () { | ||
SequenceMacro.prototype.execute = function (payload) { | ||
var payloads = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
payloads[_i - 1] = arguments[_i]; | ||
} | ||
this.captureMacroPayload(arguments); | ||
this.prepare(); | ||
this._atomic = this.atomic; | ||
@@ -72,2 +79,5 @@ this._success = true; | ||
}; | ||
SequenceMacro = tslib_1.__decorate([ | ||
core_1.injectable() | ||
], SequenceMacro); | ||
return SequenceMacro; | ||
@@ -74,0 +84,0 @@ }(AbstractMacro_1.AbstractMacro)); |
{ | ||
"name": "@robotlegsjs/macrobot", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "TypeScript port of Robotlegs Utilities Macrobot", | ||
@@ -72,11 +72,12 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@robotlegsjs/core": "^0.2.0", | ||
"@robotlegsjs/core": "^0.2.1", | ||
"tslib": "^1.9.3" | ||
}, | ||
"devDependencies": { | ||
"@types/bluebird": "^3.5.23", | ||
"@robotlegsjs/signalcommandmap": "^0.2.0", | ||
"@types/bluebird": "^3.5.24", | ||
"@types/chai": "^4.1.4", | ||
"@types/mocha": "^5.2.5", | ||
"@types/sinon": "^5.0.1", | ||
"bluebird": "^3.5.1", | ||
"@types/sinon": "^5.0.2", | ||
"bluebird": "^3.5.2", | ||
"browserify-versionify": "^1.0.6", | ||
@@ -86,11 +87,11 @@ "chai": "^4.1.2", | ||
"es6-symbol": "^3.1.1", | ||
"glslify": "^6.2.1", | ||
"glslify": "^6.3.1", | ||
"imports-loader": "^0.8.0", | ||
"istanbul": "^0.4.5", | ||
"istanbul-instrumenter-loader": "^3.0.1", | ||
"karma": "^2.0.5", | ||
"karma": "^3.0.0", | ||
"karma-chai": "^0.1.0", | ||
"karma-chai-sinon": "^0.1.5", | ||
"karma-chrome-launcher": "^2.2.0", | ||
"karma-coverage-istanbul-reporter": "^2.0.1", | ||
"karma-coverage-istanbul-reporter": "^2.0.4", | ||
"karma-es6-shim": "^1.0.0", | ||
@@ -104,23 +105,22 @@ "karma-mocha": "^1.3.0", | ||
"karma-sourcemap-writer": "^0.1.2", | ||
"karma-webpack": "^3.0.0", | ||
"karma-webpack": "^3.0.5", | ||
"mocha": "^5.2.0", | ||
"nyc": "^12.0.2", | ||
"prettier": "^1.14.0", | ||
"nyc": "^13.0.1", | ||
"prettier": "^1.14.2", | ||
"publish-please": "^3.2.0", | ||
"reflect-metadata": "^0.1.12", | ||
"remap-istanbul": "^0.11.1", | ||
"remap-istanbul": "^0.12.0", | ||
"rimraf": "^2.6.2", | ||
"sinon": "^6.1.4", | ||
"sinon": "^5.1.1", | ||
"sinon-chai": "^3.2.0", | ||
"source-map-support": "^0.5.6", | ||
"ts-loader": "^4.4.2", | ||
"ts-node": "^7.0.0", | ||
"source-map-support": "^0.5.9", | ||
"ts-loader": "^5.1.1", | ||
"ts-node": "^7.0.1", | ||
"tslint": "^5.11.0", | ||
"tslint-config-prettier": "^1.14.0", | ||
"typescript": "^3.0.1", | ||
"webpack": "^4.16.4", | ||
"tslint-config-prettier": "^1.15.0", | ||
"typescript": "^3.0.3", | ||
"webpack": "^4.19.0", | ||
"webpack-cli": "^3.1.0", | ||
"webpack-dev-server": "^3.1.5" | ||
}, | ||
"peerDependencies": {} | ||
"webpack-dev-server": "^3.1.8" | ||
} | ||
} |
200
README.md
@@ -1,3 +0,2 @@ | ||
RobotlegsJS Macrobot | ||
=== | ||
# RobotlegsJS Macrobot | ||
@@ -17,4 +16,3 @@ [![GitHub license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobotlegsJS/RobotlegsJS-Macrobot/blob/master/LICENSE) | ||
Introduction | ||
--- | ||
## Introduction | ||
@@ -29,4 +27,3 @@ While using [RobotlegsJS](https://github.com/RobotlegsJS/RobotlegsJS) and encapsulating your business logic inside commands, you may find yourself in a situation where you wish to batch commands, instead of relying on events to trigger every step. | ||
Installation | ||
--- | ||
## Installation | ||
@@ -36,3 +33,3 @@ You can get the latest release and the type definitions using [NPM](https://www.npmjs.com/): | ||
```bash | ||
npm install @robotlegsjs/macrobot | ||
npm install @robotlegsjs/macrobot --save-prod | ||
``` | ||
@@ -46,4 +43,3 @@ | ||
Usage | ||
--- | ||
## Usage | ||
@@ -237,3 +233,4 @@ To create a macro command, extend one of the two classes Macrobot provides: `SequenceMacro` or `ParallelMacro`. | ||
export class DelayCommand extends AsyncCommand { | ||
@inject(Number) protected _delay: number; | ||
@inject(Number) | ||
protected _delay: number; | ||
@@ -290,5 +287,7 @@ public execute(): void { | ||
class DelayAsyncCommand extends AsyncCommand { | ||
@inject(Number) protected _delay: number; | ||
@inject(Number) | ||
protected _delay: number; | ||
@inject(Boolean) protected _succeed: boolean; | ||
@inject(Boolean) | ||
protected _succeed: boolean; | ||
@@ -310,10 +309,179 @@ public execute(): void { | ||
Contributing | ||
--- | ||
## Macro Command Triggers | ||
Macro commands can be triggered by **Events** or **Signals**. In both cases, it is common to have to send payloads to the macro command or sub-commands | ||
through the **Event** or **Signal** trigger. | ||
The macro command can capture the **CommandPayload** provided by the **CommandExecutor** and map it into the context of the sub-commands. | ||
### Events | ||
The **Event** class from `@robotlegsjs/core` package can send parameters through the optional `data` property. In more complex cases, you can create your | ||
own **CustomEvent** class that extends the **Event** class, adding as many payloads as you wish. | ||
When dispatching an event, the **IEventCommandMap** will map the triggered **Event** into the context of the macro command, | ||
allowing you to access it from inside the macro, from inside guards and hooks or even from inside the context of each sub-command. | ||
Here's an example of a macro command that will load all the assets for your application based on the options of each user. | ||
In this case, the user can disable the sound system through user options. When loading the assets, you don't need to load the sound files when the **muted** option is enabled. | ||
```typescript | ||
import { inject, IEventCommandMap, IEventDispatcher } from "@robotlegsjs/core"; | ||
import { LoadAssetsMacro } from "./commands/LoadAssetsMacro"; | ||
import { AssetsEvent } from "./events/AssetsEvent"; | ||
export class LoadAssets { | ||
@inject(IEventCommandMap) | ||
protected _eventCommandMap: IEventCommandMap; | ||
@inject(IEventDispatcher) | ||
protected _eventDispatcher: IEventDispatcher; | ||
public loadAssets(): void { | ||
this._eventCommandMap.map(AssetsEvent.LOAD_ASSETS, AssetsEvent).toCommand(LoadAssetsMacro); | ||
let assetsEvent: AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_ASSETS); | ||
assetsEvent.muted = false; | ||
this._eventDispatcher.dispatchEvent(assetsEvent); | ||
} | ||
} | ||
``` | ||
Since the `AssetsEvent` will be mapped into the context of the macro command, you can use it on a `Guard` that can allow the execution of the `LoadSoundsCommand` | ||
only when the sound system is not muted: | ||
```typescript | ||
import { inject, injectable } from "@robotlegsjs/core"; | ||
import { ParallelMacro } from "@robotlegsjs/macrobot"; | ||
import { LoadDataCommand } from "./commands/LoadDataCommand"; | ||
import { LoadSpriteSheetsCommand } from "./commands/LoadSpriteSheetsCommand"; | ||
import { LoadSoundsCommand } from "./commands/LoadSoundsCommand"; | ||
@injectable() | ||
export class LoadAssetsMacro extends ParallelMacro { | ||
public prepare(): void { | ||
// load data for all users | ||
this.add(LoadDataCommand); | ||
// load sprite sheets for all users | ||
this.add(LoadSpriteSheetsCommand); | ||
// load sounds only for users who enabled sound system | ||
this.add(LoadSoundsCommand).withGuards(NotMuted); | ||
} | ||
} | ||
@injectable() | ||
class NotMuted implements IGuard { | ||
@inject(AssetsEvent) | ||
protected _assetsEvent: AssetsEvent; | ||
public approve():boolean { | ||
return !_assetsEvent.muted; | ||
} | ||
} | ||
``` | ||
### Signals | ||
The **Signal** class from `@robotlegsjs/signals` package can be extended to send parameters through the `dispatch` trigger. | ||
When dispatching an signal, the **ISignalCommandMap** from `@robotlegsjs/signalcommandmap` package will map the payloads into the context of the macro command, | ||
allowing you to access them from inside the macro, from inside guards and hooks or even from inside the context of each sub-command. | ||
Here's an example of a macro command that will load all the assets for your application based on the options of each user. | ||
In this case, the user can disable the sound system through user options. When loading the assets, you don't need to load the sound files when the **muted** option is enabled. | ||
The `AssetsSignal` extends the `Signal` class adding an `Boolean` as payload: | ||
```typescript | ||
import { injectable } from "@robotlegsjs/core"; | ||
import { Signal } from "@robotlegsjs/signals"; | ||
@injectable() | ||
export class AssetsSignal extends Signal { | ||
constructor() { | ||
super(Boolean); | ||
} | ||
} | ||
``` | ||
Then you can map the `AssetsSignal` to the `LoadAssetsMacro` command using the `ISignalCommandMap` extension: | ||
```typescript | ||
import { inject, IInjector } from "@robotlegsjs/core"; | ||
import { ISignalCommandMap } from "@robotlegsjs/signalcommandmap"; | ||
import { LoadAssetsMacro } from "./commands/LoadAssetsMacro"; | ||
import { AssetsSignal } from "./signals/AssetsSignal"; | ||
export class LoadAssets { | ||
@inject(IInjector) | ||
protected _injector: IInjector; | ||
@inject(ISignalCommandMap) | ||
protected _signalCommandMap: ISignalCommandMap; | ||
public loadAssets(): void { | ||
this._signalCommandMap.map(AssetsSignal).toCommand(LoadAssetsMacro); | ||
let assetsSignal: AssetsSignal = this._injector.get(AssetsSignal); | ||
// dispatch the signal telling the macro command that the muted option is disabled | ||
assetsSignal.dispatch(false); | ||
} | ||
} | ||
``` | ||
Since the payload of the `AssetsSignal` will be mapped into the context of the macro command, you can use it on a `Guard` that can allow the execution of the `LoadSoundsCommand` | ||
only when the sound system is not muted: | ||
```typescript | ||
import { inject, injectable } from "@robotlegsjs/core"; | ||
import { ParallelMacro } from "@robotlegsjs/macrobot"; | ||
import { LoadDataCommand } from "./commands/LoadDataCommand"; | ||
import { LoadSpriteSheetsCommand } from "./commands/LoadSpriteSheetsCommand"; | ||
import { LoadSoundsCommand } from "./commands/LoadSoundsCommand"; | ||
@injectable() | ||
export class LoadAssetsMacro extends ParallelMacro { | ||
public prepare(): void { | ||
// load data for all users | ||
this.add(LoadDataCommand); | ||
// load sprite sheets for all users | ||
this.add(LoadSpriteSheetsCommand); | ||
// load sounds only for users who enabled sound system | ||
this.add(LoadSoundsCommand).withGuards(NotMuted); | ||
} | ||
} | ||
@injectable() | ||
class NotMuted implements IGuard { | ||
@inject(Boolean) | ||
protected _muted: Boolean; | ||
public approve():boolean { | ||
return !this._muted; | ||
} | ||
} | ||
``` | ||
## Contributing | ||
If you want to contribute to the project refer to the [contributing document](CONTRIBUTING.md) for guidelines. | ||
License | ||
--- | ||
## License | ||
[MIT](LICENSE) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
98760
761
481
46
Updated@robotlegsjs/core@^0.2.1