├── .jshintrc ├── gulpfile.js ├── jsconfig.json ├── .npmignore ├── .gitignore ├── dist ├── amd │ ├── utils.d.ts │ ├── decorators │ │ ├── handle.d.ts │ │ ├── waitFor.d.ts │ │ ├── waitFor.js │ │ └── handle.js │ ├── symbols.d.ts │ ├── metadata.d.ts │ ├── router.d.ts │ ├── index.d.ts │ ├── flux-dispatcher.d.ts │ ├── index.js │ ├── lifecycle-manager.d.ts │ ├── utils.js │ ├── metadata.js │ ├── router.js │ ├── symbols.js │ ├── instance-dispatcher.d.ts │ ├── instance-dispatcher.js │ ├── flux-dispatcher.js │ └── lifecycle-manager.js ├── es6 │ ├── utils.d.ts │ ├── decorators │ │ ├── handle.d.ts │ │ ├── waitFor.d.ts │ │ ├── waitFor.js │ │ └── handle.js │ ├── symbols.d.ts │ ├── symbols.js │ ├── metadata.d.ts │ ├── router.d.ts │ ├── index.d.ts │ ├── index.js │ ├── metadata.js │ ├── utils.js │ ├── flux-dispatcher.d.ts │ ├── router.js │ ├── lifecycle-manager.d.ts │ ├── instance-dispatcher.d.ts │ ├── flux-dispatcher.js │ ├── instance-dispatcher.js │ └── lifecycle-manager.js ├── commonjs │ ├── utils.d.ts │ ├── decorators │ │ ├── handle.d.ts │ │ ├── waitFor.d.ts │ │ ├── waitFor.js │ │ └── handle.js │ ├── symbols.d.ts │ ├── metadata.d.ts │ ├── router.d.ts │ ├── index.d.ts │ ├── flux-dispatcher.d.ts │ ├── index.js │ ├── lifecycle-manager.d.ts │ ├── utils.js │ ├── metadata.js │ ├── router.js │ ├── symbols.js │ ├── instance-dispatcher.d.ts │ ├── instance-dispatcher.js │ ├── flux-dispatcher.js │ └── lifecycle-manager.js └── system │ ├── utils.d.ts │ ├── decorators │ ├── handle.d.ts │ ├── waitFor.d.ts │ ├── waitFor.js │ └── handle.js │ ├── symbols.d.ts │ ├── metadata.d.ts │ ├── router.d.ts │ ├── index.d.ts │ ├── flux-dispatcher.d.ts │ ├── lifecycle-manager.d.ts │ ├── index.js │ ├── utils.js │ ├── metadata.js │ ├── symbols.js │ ├── router.js │ ├── instance-dispatcher.d.ts │ ├── instance-dispatcher.js │ ├── flux-dispatcher.js │ └── lifecycle-manager.js ├── test ├── instance-dispatcher.spec.js ├── metadata.spec.js ├── utils.spec.js └── lifecycle-manager.spec.js ├── src ├── symbols.js ├── decorators │ ├── waitFor.js │ └── handle.js ├── index.js ├── metadata.js ├── utils.js ├── router.js ├── flux-dispatcher.js ├── instance-dispatcher.js └── lifecycle-manager.js ├── bower.json ├── .travis.yml ├── doc ├── api.json └── CHANGELOG.md ├── LICENSE ├── karma.conf.js ├── package.json ├── config.js └── README.md /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esnext": true 3 | } 4 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | require('require-dir')('build/tasks'); 2 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "system" 5 | } 6 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | jspm_packages 3 | bower_components 4 | .idea 5 | .DS_STORE 6 | test 7 | npm-debug.log 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | jspm_packages 3 | bower_components 4 | .idea 5 | .DS_STORE 6 | *.swp 7 | npm-debug.log 8 | aurelia-flux 9 | *.iml -------------------------------------------------------------------------------- /dist/amd/utils.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Utils { 3 | static patternsToRegex(patterns: any): any; 4 | } 5 | } -------------------------------------------------------------------------------- /dist/es6/utils.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Utils { 3 | static patternsToRegex(patterns: any): any; 4 | } 5 | } -------------------------------------------------------------------------------- /dist/commonjs/utils.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Utils { 3 | static patternsToRegex(patterns: any): any; 4 | } 5 | } -------------------------------------------------------------------------------- /dist/system/utils.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Utils { 3 | static patternsToRegex(patterns: any): any; 4 | } 5 | } -------------------------------------------------------------------------------- /dist/amd/decorators/handle.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function handle(...patterns: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/amd/decorators/waitFor.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function waitFor(...types: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/es6/decorators/handle.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function handle(...patterns: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/es6/decorators/waitFor.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function waitFor(...types: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/system/decorators/handle.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function handle(...patterns: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/system/decorators/waitFor.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function waitFor(...types: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/commonjs/decorators/handle.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function handle(...patterns: any[]): any; 4 | } -------------------------------------------------------------------------------- /dist/commonjs/decorators/waitFor.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from '../metadata'; 3 | export function waitFor(...types: any[]): any; 4 | } -------------------------------------------------------------------------------- /test/instance-dispatcher.spec.js: -------------------------------------------------------------------------------- 1 | import {Utils} from 'src/utils'; 2 | 3 | describe('Utils', () => { 4 | describe('patternsArrayToRegex', () => { 5 | 6 | 7 | }); 8 | }); -------------------------------------------------------------------------------- /dist/amd/symbols.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Symbols { 3 | static instanceDispatcher: any; 4 | static metadata: any; 5 | static deactivators: any; 6 | } 7 | } -------------------------------------------------------------------------------- /dist/es6/symbols.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Symbols { 3 | static instanceDispatcher: any; 4 | static metadata: any; 5 | static deactivators: any; 6 | } 7 | } -------------------------------------------------------------------------------- /dist/system/symbols.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Symbols { 3 | static instanceDispatcher: any; 4 | static metadata: any; 5 | static deactivators: any; 6 | } 7 | } -------------------------------------------------------------------------------- /dist/commonjs/symbols.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | export class Symbols { 3 | static instanceDispatcher: any; 4 | static metadata: any; 5 | static deactivators: any; 6 | } 7 | } -------------------------------------------------------------------------------- /dist/es6/symbols.js: -------------------------------------------------------------------------------- 1 | export class Symbols { 2 | static instanceDispatcher = Symbol('fluxDispatcher'); 3 | static metadata = Symbol('fluxMetadata'); 4 | static deactivators = Symbol('fluxDeactivators'); 5 | } 6 | -------------------------------------------------------------------------------- /src/symbols.js: -------------------------------------------------------------------------------- 1 | export class Symbols { 2 | static instanceDispatcher = Symbol('fluxDispatcher'); 3 | static metadata = Symbol('fluxMetadata'); 4 | static deactivators = Symbol('fluxDeactivators'); 5 | } 6 | -------------------------------------------------------------------------------- /dist/amd/metadata.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Symbols } from 'aurelia-flux/symbols'; 3 | export class Metadata { 4 | static getOrCreateMetadata(target: any): any; 5 | static exists(target: any): any; 6 | constructor(); 7 | } 8 | } -------------------------------------------------------------------------------- /dist/es6/metadata.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Symbols } from 'aurelia-flux/symbols'; 3 | export class Metadata { 4 | static getOrCreateMetadata(target: any): any; 5 | static exists(target: any): any; 6 | constructor(); 7 | } 8 | } -------------------------------------------------------------------------------- /dist/system/metadata.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Symbols } from 'aurelia-flux/symbols'; 3 | export class Metadata { 4 | static getOrCreateMetadata(target: any): any; 5 | static exists(target: any): any; 6 | constructor(); 7 | } 8 | } -------------------------------------------------------------------------------- /dist/commonjs/metadata.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Symbols } from 'aurelia-flux/symbols'; 3 | export class Metadata { 4 | static getOrCreateMetadata(target: any): any; 5 | static exists(target: any): any; 6 | constructor(); 7 | } 8 | } -------------------------------------------------------------------------------- /dist/amd/router.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Router, RouterConfiguration } from 'aurelia-router'; 3 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 4 | export class RouterManager { 5 | static AddFluxPipelineStep(aurelia: any): any; 6 | } 7 | class FluxLifeCycleStep { 8 | run(context: any, next: any): any; 9 | } 10 | } -------------------------------------------------------------------------------- /dist/es6/router.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Router, RouterConfiguration } from 'aurelia-router'; 3 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 4 | export class RouterManager { 5 | static AddFluxPipelineStep(aurelia: any): any; 6 | } 7 | class FluxLifeCycleStep { 8 | run(context: any, next: any): any; 9 | } 10 | } -------------------------------------------------------------------------------- /dist/commonjs/router.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Router, RouterConfiguration } from 'aurelia-router'; 3 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 4 | export class RouterManager { 5 | static AddFluxPipelineStep(aurelia: any): any; 6 | } 7 | class FluxLifeCycleStep { 8 | run(context: any, next: any): any; 9 | } 10 | } -------------------------------------------------------------------------------- /dist/system/router.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Router, RouterConfiguration } from 'aurelia-router'; 3 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 4 | export class RouterManager { 5 | static AddFluxPipelineStep(aurelia: any): any; 6 | } 7 | class FluxLifeCycleStep { 8 | run(context: any, next: any): any; 9 | } 10 | } -------------------------------------------------------------------------------- /src/decorators/waitFor.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from '../metadata'; 2 | 3 | export function waitFor(...types) { 4 | return function (target, method) { 5 | var metadata = Metadata.getOrCreateMetadata(target); 6 | 7 | if(metadata.awaiters.has(method) === false) { 8 | metadata.awaiters.set(method, []); 9 | } 10 | 11 | metadata.awaiters.set(method, metadata.awaiters.get(method).concat(types)); 12 | }; 13 | } -------------------------------------------------------------------------------- /dist/es6/decorators/waitFor.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from '../metadata'; 2 | 3 | export function waitFor(...types) { 4 | return function (target, method) { 5 | var metadata = Metadata.getOrCreateMetadata(target); 6 | 7 | if(metadata.awaiters.has(method) === false) { 8 | metadata.awaiters.set(method, []); 9 | } 10 | 11 | metadata.awaiters.set(method, metadata.awaiters.get(method).concat(types)); 12 | }; 13 | } -------------------------------------------------------------------------------- /src/decorators/handle.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from '../metadata'; 2 | export function handle(...patterns) { 3 | 4 | return function(target, method) { 5 | 6 | var metadata = Metadata.getOrCreateMetadata(target); 7 | 8 | if(metadata.handlers.has(method) === false) { 9 | metadata.handlers.set(method, []); 10 | } 11 | 12 | metadata.handlers.set(method, metadata.handlers.get(method).concat(patterns)); 13 | }; 14 | } -------------------------------------------------------------------------------- /dist/es6/decorators/handle.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from '../metadata'; 2 | export function handle(...patterns) { 3 | 4 | return function(target, method) { 5 | 6 | var metadata = Metadata.getOrCreateMetadata(target); 7 | 8 | if(metadata.handlers.has(method) === false) { 9 | metadata.handlers.set(method, []); 10 | } 11 | 12 | metadata.handlers.set(method, metadata.handlers.get(method).concat(patterns)); 13 | }; 14 | } -------------------------------------------------------------------------------- /dist/amd/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { LifecycleManager } from 'aurelia-flux/lifecycle-manager'; 3 | import { RouterManager } from 'aurelia-flux/router'; 4 | export { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 5 | 6 | /* 7 | * Decorators 8 | */ 9 | export { handle } from 'aurelia-flux/decorators/handle'; 10 | export { waitFor } from 'aurelia-flux/decorators/waitFor'; 11 | export function configure(aurelia: any, configCallback: any): any; 12 | } -------------------------------------------------------------------------------- /dist/es6/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { LifecycleManager } from 'aurelia-flux/lifecycle-manager'; 3 | import { RouterManager } from 'aurelia-flux/router'; 4 | export { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 5 | 6 | /* 7 | * Decorators 8 | */ 9 | export { handle } from 'aurelia-flux/decorators/handle'; 10 | export { waitFor } from 'aurelia-flux/decorators/waitFor'; 11 | export function configure(aurelia: any, configCallback: any): any; 12 | } -------------------------------------------------------------------------------- /dist/commonjs/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { LifecycleManager } from 'aurelia-flux/lifecycle-manager'; 3 | import { RouterManager } from 'aurelia-flux/router'; 4 | export { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 5 | 6 | /* 7 | * Decorators 8 | */ 9 | export { handle } from 'aurelia-flux/decorators/handle'; 10 | export { waitFor } from 'aurelia-flux/decorators/waitFor'; 11 | export function configure(aurelia: any, configCallback: any): any; 12 | } -------------------------------------------------------------------------------- /dist/system/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { LifecycleManager } from 'aurelia-flux/lifecycle-manager'; 3 | import { RouterManager } from 'aurelia-flux/router'; 4 | export { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 5 | 6 | /* 7 | * Decorators 8 | */ 9 | export { handle } from 'aurelia-flux/decorators/handle'; 10 | export { waitFor } from 'aurelia-flux/decorators/waitFor'; 11 | export function configure(aurelia: any, configCallback: any): any; 12 | } -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-flux", 3 | "version": "0.1.6", 4 | "description": "A Flux dispatcher plugin for Aurelia.", 5 | "keywords": [ 6 | "aurelia", 7 | "flux", 8 | "plugin" 9 | ], 10 | "homepage": "https://github.com/tfrydrychewicz/aurelia-flux", 11 | "license": "MIT", 12 | "authors": [ 13 | "Tomasz Frydrychewicz " 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/tfrydrychewicz/aurelia-flux" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export {Dispatcher} from './instance-dispatcher'; 2 | 3 | /* 4 | * Decorators 5 | */ 6 | export {handle} from './decorators/handle'; 7 | export {waitFor} from './decorators/waitFor'; 8 | 9 | import {LifecycleManager} from './lifecycle-manager'; 10 | import {RouterManager} from './router'; 11 | 12 | export function configure(aurelia, configCallback) { 13 | LifecycleManager.interceptClassActivator(); 14 | LifecycleManager.interceptHtmlBehaviorResource(); 15 | RouterManager.AddFluxPipelineStep(aurelia); 16 | } 17 | -------------------------------------------------------------------------------- /dist/es6/index.js: -------------------------------------------------------------------------------- 1 | export {Dispatcher} from './instance-dispatcher'; 2 | 3 | /* 4 | * Decorators 5 | */ 6 | export {handle} from './decorators/handle'; 7 | export {waitFor} from './decorators/waitFor'; 8 | 9 | import {LifecycleManager} from './lifecycle-manager'; 10 | import {RouterManager} from './router'; 11 | 12 | export function configure(aurelia, configCallback) { 13 | LifecycleManager.interceptClassActivator(); 14 | LifecycleManager.interceptHtmlBehaviorResource(); 15 | RouterManager.AddFluxPipelineStep(aurelia); 16 | } 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | before_install: 5 | - "export DISPLAY=:99.0" 6 | - "sh -e /etc/init.d/xvfb start" 7 | before_script: 8 | - ./node_modules/.bin/jspm config registries.github.auth $GH_TOKEN 9 | - ./node_modules/.bin/jspm install 10 | notifications: 11 | webhooks: 12 | urls: 13 | - https://webhooks.gitter.im/e/002974bac8937a25ae85 14 | on_success: always # options: [always|never|change] default: always 15 | on_failure: always # options: [always|never|change] default: always 16 | on_start: false # default: false 17 | -------------------------------------------------------------------------------- /src/metadata.js: -------------------------------------------------------------------------------- 1 | import {Symbols} from './symbols'; 2 | 3 | export class Metadata { 4 | 5 | static getOrCreateMetadata(target) { 6 | if(target[Symbols.metadata] === undefined) { 7 | target[Symbols.metadata] = new Metadata(); 8 | } 9 | 10 | return target[Symbols.metadata]; 11 | } 12 | 13 | static exists(target) { 14 | return target[Symbols.metadata] !== undefined && target[Symbols.metadata] instanceof Metadata; 15 | } 16 | 17 | constructor() { 18 | this.handlers = new Map(); 19 | this.awaiters = new Map(); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | function globStringToRegexString(str) { 2 | return preg_quote(str).replace(/\\\*/g, '.*').replace(/\\\?/g, '.'); 3 | } 4 | function preg_quote(str, delimiter) { 5 | return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); 6 | } 7 | 8 | export class Utils { 9 | static patternsToRegex(patterns) { 10 | if(Array.isArray(patterns) === false) { 11 | patterns = Array.of(patterns); 12 | } 13 | 14 | return new RegExp('^' + patterns.map(globStringToRegexString).join('|') + '$'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dist/es6/metadata.js: -------------------------------------------------------------------------------- 1 | import {Symbols} from './symbols'; 2 | 3 | export class Metadata { 4 | 5 | static getOrCreateMetadata(target) { 6 | if(target[Symbols.metadata] === undefined) { 7 | target[Symbols.metadata] = new Metadata(); 8 | } 9 | 10 | return target[Symbols.metadata]; 11 | } 12 | 13 | static exists(target) { 14 | return target[Symbols.metadata] !== undefined && target[Symbols.metadata] instanceof Metadata; 15 | } 16 | 17 | constructor() { 18 | this.handlers = new Map(); 19 | this.awaiters = new Map(); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /dist/es6/utils.js: -------------------------------------------------------------------------------- 1 | function globStringToRegexString(str) { 2 | return preg_quote(str).replace(/\\\*/g, '.*').replace(/\\\?/g, '.'); 3 | } 4 | function preg_quote(str, delimiter) { 5 | return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); 6 | } 7 | 8 | export class Utils { 9 | static patternsToRegex(patterns) { 10 | if(Array.isArray(patterns) === false) { 11 | patterns = Array.of(patterns); 12 | } 13 | 14 | return new RegExp('^' + patterns.map(globStringToRegexString).join('|') + '$'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dist/amd/flux-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import Promise from 'bluebird'; 3 | import { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 4 | export class FluxDispatcher { 5 | static instance: any; 6 | constructor(); 7 | getOrCreateTypeDispatchers(type: Object): Set; 8 | getOrCreateTypePromises(type: Object): any; 9 | registerInstanceDispatcher(dispatcher: Dispatcher): any; 10 | unregisterInstanceDispatcher(dispatcher: Dispatcher): any; 11 | dispatch(action: String, payload: any): any; 12 | $dispatch(action: String, payload: any, fromQueue: boolean): any; 13 | waitFor(types: String | String[], handler: (() => any)): any; 14 | } 15 | } -------------------------------------------------------------------------------- /dist/es6/flux-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import Promise from 'bluebird'; 3 | import { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 4 | export class FluxDispatcher { 5 | static instance: any; 6 | constructor(); 7 | getOrCreateTypeDispatchers(type: Object): Set; 8 | getOrCreateTypePromises(type: Object): any; 9 | registerInstanceDispatcher(dispatcher: Dispatcher): any; 10 | unregisterInstanceDispatcher(dispatcher: Dispatcher): any; 11 | dispatch(action: String, payload: any): any; 12 | $dispatch(action: String, payload: any, fromQueue: boolean): any; 13 | waitFor(types: String | String[], handler: (() => any)): any; 14 | } 15 | } -------------------------------------------------------------------------------- /dist/commonjs/decorators/waitFor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.waitFor = waitFor; 5 | 6 | var _metadata = require('../metadata'); 7 | 8 | function waitFor() { 9 | for (var _len = arguments.length, types = Array(_len), _key = 0; _key < _len; _key++) { 10 | types[_key] = arguments[_key]; 11 | } 12 | 13 | return function (target, method) { 14 | var metadata = _metadata.Metadata.getOrCreateMetadata(target); 15 | 16 | if (metadata.awaiters.has(method) === false) { 17 | metadata.awaiters.set(method, []); 18 | } 19 | 20 | metadata.awaiters.set(method, metadata.awaiters.get(method).concat(types)); 21 | }; 22 | } -------------------------------------------------------------------------------- /dist/commonjs/flux-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import Promise from 'bluebird'; 3 | import { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 4 | export class FluxDispatcher { 5 | static instance: any; 6 | constructor(); 7 | getOrCreateTypeDispatchers(type: Object): Set; 8 | getOrCreateTypePromises(type: Object): any; 9 | registerInstanceDispatcher(dispatcher: Dispatcher): any; 10 | unregisterInstanceDispatcher(dispatcher: Dispatcher): any; 11 | dispatch(action: String, payload: any): any; 12 | $dispatch(action: String, payload: any, fromQueue: boolean): any; 13 | waitFor(types: String | String[], handler: (() => any)): any; 14 | } 15 | } -------------------------------------------------------------------------------- /dist/system/flux-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import Promise from 'bluebird'; 3 | import { Dispatcher } from 'aurelia-flux/instance-dispatcher'; 4 | export class FluxDispatcher { 5 | static instance: any; 6 | constructor(); 7 | getOrCreateTypeDispatchers(type: Object): Set; 8 | getOrCreateTypePromises(type: Object): any; 9 | registerInstanceDispatcher(dispatcher: Dispatcher): any; 10 | unregisterInstanceDispatcher(dispatcher: Dispatcher): any; 11 | dispatch(action: String, payload: any): any; 12 | $dispatch(action: String, payload: any, fromQueue: boolean): any; 13 | waitFor(types: String | String[], handler: (() => any)): any; 14 | } 15 | } -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import {Router, RouterConfiguration} from 'aurelia-router'; 2 | import {FluxDispatcher} from './flux-dispatcher' 3 | 4 | export class RouterManager { 5 | static AddFluxPipelineStep(aurelia) { 6 | let router = aurelia.container.get(Router); 7 | let configuration = new RouterConfiguration(); 8 | 9 | configuration.addPipelineStep("modelbind", FluxLifeCycleStep); 10 | router.configure(configuration); 11 | } 12 | } 13 | 14 | class FluxLifeCycleStep { 15 | run(context, next) { 16 | 17 | if(context && context.plan && context.plan.default) { 18 | FluxDispatcher.instance.strategy = context.plan.default.strategy; 19 | } 20 | 21 | return next(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dist/commonjs/decorators/handle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.handle = handle; 5 | 6 | var _metadata = require('../metadata'); 7 | 8 | function handle() { 9 | for (var _len = arguments.length, patterns = Array(_len), _key = 0; _key < _len; _key++) { 10 | patterns[_key] = arguments[_key]; 11 | } 12 | 13 | return function (target, method) { 14 | 15 | var metadata = _metadata.Metadata.getOrCreateMetadata(target); 16 | 17 | if (metadata.handlers.has(method) === false) { 18 | metadata.handlers.set(method, []); 19 | } 20 | 21 | metadata.handlers.set(method, metadata.handlers.get(method).concat(patterns)); 22 | }; 23 | } -------------------------------------------------------------------------------- /dist/es6/router.js: -------------------------------------------------------------------------------- 1 | import {Router, RouterConfiguration} from 'aurelia-router'; 2 | import {FluxDispatcher} from './flux-dispatcher' 3 | 4 | export class RouterManager { 5 | static AddFluxPipelineStep(aurelia) { 6 | let router = aurelia.container.get(Router); 7 | let configuration = new RouterConfiguration(); 8 | 9 | configuration.addPipelineStep("modelbind", FluxLifeCycleStep); 10 | router.configure(configuration); 11 | } 12 | } 13 | 14 | class FluxLifeCycleStep { 15 | run(context, next) { 16 | 17 | if(context && context.plan && context.plan.default) { 18 | FluxDispatcher.instance.strategy = context.plan.default.strategy; 19 | } 20 | 21 | return next(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dist/amd/decorators/waitFor.js: -------------------------------------------------------------------------------- 1 | define(['exports', '../metadata'], function (exports, _metadata) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | exports.waitFor = waitFor; 6 | 7 | function waitFor() { 8 | for (var _len = arguments.length, types = Array(_len), _key = 0; _key < _len; _key++) { 9 | types[_key] = arguments[_key]; 10 | } 11 | 12 | return function (target, method) { 13 | var metadata = _metadata.Metadata.getOrCreateMetadata(target); 14 | 15 | if (metadata.awaiters.has(method) === false) { 16 | metadata.awaiters.set(method, []); 17 | } 18 | 19 | metadata.awaiters.set(method, metadata.awaiters.get(method).concat(types)); 20 | }; 21 | } 22 | }); -------------------------------------------------------------------------------- /dist/amd/decorators/handle.js: -------------------------------------------------------------------------------- 1 | define(['exports', '../metadata'], function (exports, _metadata) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | exports.handle = handle; 6 | 7 | function handle() { 8 | for (var _len = arguments.length, patterns = Array(_len), _key = 0; _key < _len; _key++) { 9 | patterns[_key] = arguments[_key]; 10 | } 11 | 12 | return function (target, method) { 13 | 14 | var metadata = _metadata.Metadata.getOrCreateMetadata(target); 15 | 16 | if (metadata.handlers.has(method) === false) { 17 | metadata.handlers.set(method, []); 18 | } 19 | 20 | metadata.handlers.set(method, metadata.handlers.get(method).concat(patterns)); 21 | }; 22 | } 23 | }); -------------------------------------------------------------------------------- /dist/amd/index.js: -------------------------------------------------------------------------------- 1 | define(['exports', './lifecycle-manager', './router', './instance-dispatcher', './decorators/handle', './decorators/waitFor'], function (exports, _lifecycleManager, _router, _instanceDispatcher, _decoratorsHandle, _decoratorsWaitFor) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | exports.configure = configure; 6 | exports.Dispatcher = _instanceDispatcher.Dispatcher; 7 | exports.handle = _decoratorsHandle.handle; 8 | exports.waitFor = _decoratorsWaitFor.waitFor; 9 | 10 | function configure(aurelia, configCallback) { 11 | _lifecycleManager.LifecycleManager.interceptClassActivator(); 12 | _lifecycleManager.LifecycleManager.interceptHtmlBehaviorResource(); 13 | _router.RouterManager.AddFluxPipelineStep(aurelia); 14 | } 15 | }); -------------------------------------------------------------------------------- /dist/commonjs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.configure = configure; 5 | 6 | var _lifecycleManager = require('./lifecycle-manager'); 7 | 8 | var _router = require('./router'); 9 | 10 | var _instanceDispatcher = require('./instance-dispatcher'); 11 | 12 | exports.Dispatcher = _instanceDispatcher.Dispatcher; 13 | 14 | var _decoratorsHandle = require('./decorators/handle'); 15 | 16 | exports.handle = _decoratorsHandle.handle; 17 | 18 | var _decoratorsWaitFor = require('./decorators/waitFor'); 19 | 20 | exports.waitFor = _decoratorsWaitFor.waitFor; 21 | 22 | function configure(aurelia, configCallback) { 23 | _lifecycleManager.LifecycleManager.interceptClassActivator(); 24 | _lifecycleManager.LifecycleManager.interceptHtmlBehaviorResource(); 25 | _router.RouterManager.AddFluxPipelineStep(aurelia); 26 | } -------------------------------------------------------------------------------- /dist/amd/lifecycle-manager.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { ClassActivator } from 'aurelia-dependency-injection'; 3 | import { HtmlBehaviorResource } from 'aurelia-templating'; 4 | import { Dispatcher, DispatcherProxy } from 'aurelia-flux/instance-dispatcher'; 5 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 6 | import { Metadata } from 'aurelia-flux/metadata'; 7 | import { Symbols } from 'aurelia-flux/symbols'; 8 | import Promise from 'bluebird'; 9 | import { activationStrategy } from 'aurelia-router'; 10 | export class LifecycleManager { 11 | static interceptInstanceDeactivators(instance: any): any; 12 | static interceptInstanceDeactivate(instance: any): any; 13 | static interceptInstanceDetached(instance: any): any; 14 | static interceptHtmlBehaviorResource(): any; 15 | static interceptClassActivator(): any; 16 | } 17 | } -------------------------------------------------------------------------------- /dist/es6/lifecycle-manager.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { ClassActivator } from 'aurelia-dependency-injection'; 3 | import { HtmlBehaviorResource } from 'aurelia-templating'; 4 | import { Dispatcher, DispatcherProxy } from 'aurelia-flux/instance-dispatcher'; 5 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 6 | import { Metadata } from 'aurelia-flux/metadata'; 7 | import { Symbols } from 'aurelia-flux/symbols'; 8 | import Promise from 'bluebird'; 9 | import { activationStrategy } from 'aurelia-router'; 10 | export class LifecycleManager { 11 | static interceptInstanceDeactivators(instance: any): any; 12 | static interceptInstanceDeactivate(instance: any): any; 13 | static interceptInstanceDetached(instance: any): any; 14 | static interceptHtmlBehaviorResource(): any; 15 | static interceptClassActivator(): any; 16 | } 17 | } -------------------------------------------------------------------------------- /dist/commonjs/lifecycle-manager.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { ClassActivator } from 'aurelia-dependency-injection'; 3 | import { HtmlBehaviorResource } from 'aurelia-templating'; 4 | import { Dispatcher, DispatcherProxy } from 'aurelia-flux/instance-dispatcher'; 5 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 6 | import { Metadata } from 'aurelia-flux/metadata'; 7 | import { Symbols } from 'aurelia-flux/symbols'; 8 | import Promise from 'bluebird'; 9 | import { activationStrategy } from 'aurelia-router'; 10 | export class LifecycleManager { 11 | static interceptInstanceDeactivators(instance: any): any; 12 | static interceptInstanceDeactivate(instance: any): any; 13 | static interceptInstanceDetached(instance: any): any; 14 | static interceptHtmlBehaviorResource(): any; 15 | static interceptClassActivator(): any; 16 | } 17 | } -------------------------------------------------------------------------------- /dist/system/lifecycle-manager.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { ClassActivator } from 'aurelia-dependency-injection'; 3 | import { HtmlBehaviorResource } from 'aurelia-templating'; 4 | import { Dispatcher, DispatcherProxy } from 'aurelia-flux/instance-dispatcher'; 5 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 6 | import { Metadata } from 'aurelia-flux/metadata'; 7 | import { Symbols } from 'aurelia-flux/symbols'; 8 | import Promise from 'bluebird'; 9 | import { activationStrategy } from 'aurelia-router'; 10 | export class LifecycleManager { 11 | static interceptInstanceDeactivators(instance: any): any; 12 | static interceptInstanceDeactivate(instance: any): any; 13 | static interceptInstanceDetached(instance: any): any; 14 | static interceptHtmlBehaviorResource(): any; 15 | static interceptClassActivator(): any; 16 | } 17 | } -------------------------------------------------------------------------------- /dist/system/decorators/waitFor.js: -------------------------------------------------------------------------------- 1 | System.register(['../metadata'], function (_export) { 2 | 'use strict'; 3 | 4 | var Metadata; 5 | 6 | _export('waitFor', waitFor); 7 | 8 | function waitFor() { 9 | for (var _len = arguments.length, types = Array(_len), _key = 0; _key < _len; _key++) { 10 | types[_key] = arguments[_key]; 11 | } 12 | 13 | return function (target, method) { 14 | var metadata = Metadata.getOrCreateMetadata(target); 15 | 16 | if (metadata.awaiters.has(method) === false) { 17 | metadata.awaiters.set(method, []); 18 | } 19 | 20 | metadata.awaiters.set(method, metadata.awaiters.get(method).concat(types)); 21 | }; 22 | } 23 | 24 | return { 25 | setters: [function (_metadata) { 26 | Metadata = _metadata.Metadata; 27 | }], 28 | execute: function () {} 29 | }; 30 | }); -------------------------------------------------------------------------------- /dist/system/decorators/handle.js: -------------------------------------------------------------------------------- 1 | System.register(['../metadata'], function (_export) { 2 | 'use strict'; 3 | 4 | var Metadata; 5 | 6 | _export('handle', handle); 7 | 8 | function handle() { 9 | for (var _len = arguments.length, patterns = Array(_len), _key = 0; _key < _len; _key++) { 10 | patterns[_key] = arguments[_key]; 11 | } 12 | 13 | return function (target, method) { 14 | 15 | var metadata = Metadata.getOrCreateMetadata(target); 16 | 17 | if (metadata.handlers.has(method) === false) { 18 | metadata.handlers.set(method, []); 19 | } 20 | 21 | metadata.handlers.set(method, metadata.handlers.get(method).concat(patterns)); 22 | }; 23 | } 24 | 25 | return { 26 | setters: [function (_metadata) { 27 | Metadata = _metadata.Metadata; 28 | }], 29 | execute: function () {} 30 | }; 31 | }); -------------------------------------------------------------------------------- /dist/commonjs/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6 | 7 | function globStringToRegexString(str) { 8 | return preg_quote(str).replace(/\\\*/g, '.*').replace(/\\\?/g, '.'); 9 | } 10 | function preg_quote(str, delimiter) { 11 | return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); 12 | } 13 | 14 | var Utils = (function () { 15 | function Utils() { 16 | _classCallCheck(this, Utils); 17 | } 18 | 19 | Utils.patternsToRegex = function patternsToRegex(patterns) { 20 | if (Array.isArray(patterns) === false) { 21 | patterns = Array.of(patterns); 22 | } 23 | 24 | return new RegExp('^' + patterns.map(globStringToRegexString).join('|') + '$'); 25 | }; 26 | 27 | return Utils; 28 | })(); 29 | 30 | exports.Utils = Utils; -------------------------------------------------------------------------------- /test/metadata.spec.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from 'src/metadata'; 2 | import {Symbols} from 'src/symbols'; 3 | 4 | describe('Metadata', () => { 5 | describe('getOrCreateMetadata', () => { 6 | 7 | it('adds metadata', () => { 8 | 9 | let obj = {}; 10 | 11 | expect(obj[Symbols.metadata]).toBeUndefined(); 12 | let metadata = Metadata.getOrCreateMetadata(obj); 13 | expect(obj[Symbols.metadata]).toBeDefined(); 14 | expect(metadata instanceof Metadata).toBeTruthy(); 15 | }); 16 | 17 | it('adds metadata only once', () => { 18 | let obj = {}; 19 | 20 | let metadata1 = Metadata.getOrCreateMetadata(obj); 21 | let metadata2 = Metadata.getOrCreateMetadata(obj); 22 | 23 | expect(metadata1).toBe(metadata2); 24 | }); 25 | 26 | }); 27 | 28 | describe('exists', () => { 29 | it('return adequate value', () => { 30 | let obj = {}; 31 | 32 | expect(Metadata.exists(obj)).toBeFalsy(); 33 | Metadata.getOrCreateMetadata(obj); 34 | expect(Metadata.exists(obj)).toBeTruthy(); 35 | }); 36 | }); 37 | }); -------------------------------------------------------------------------------- /dist/commonjs/metadata.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6 | 7 | var _symbols = require('./symbols'); 8 | 9 | var Metadata = (function () { 10 | Metadata.getOrCreateMetadata = function getOrCreateMetadata(target) { 11 | if (target[_symbols.Symbols.metadata] === undefined) { 12 | target[_symbols.Symbols.metadata] = new Metadata(); 13 | } 14 | 15 | return target[_symbols.Symbols.metadata]; 16 | }; 17 | 18 | Metadata.exists = function exists(target) { 19 | return target[_symbols.Symbols.metadata] !== undefined && target[_symbols.Symbols.metadata] instanceof Metadata; 20 | }; 21 | 22 | function Metadata() { 23 | _classCallCheck(this, Metadata); 24 | 25 | this.handlers = new Map(); 26 | this.awaiters = new Map(); 27 | } 28 | 29 | return Metadata; 30 | })(); 31 | 32 | exports.Metadata = Metadata; -------------------------------------------------------------------------------- /doc/api.json: -------------------------------------------------------------------------------- 1 | {"classes":[],"methods":[{"file":"aurelia-flux\\src\\instance-dispatcher.js","line":23,"description":"Registers new handler function for given action patterns","name":"handle","params":[{"name":"patterns","description":"","type":"String|String[]"},{"name":"callback","description":"","type":"(action:String, ...payload : any[]) => any"}],"return":{"description":"- unregistering function","type":"() => void"},"class":""},{"file":"aurelia-flux\\src\\instance-dispatcher.js","line":40,"description":"Registers a method that will be invoked when all\ngiven types finish dispatching","name":"waitFor","params":[{"name":"types","description":"","type":"String|String[]"},{"name":"handler","description":"","type":"(() => any)"}],"return":{"description":"void"},"class":""},{"file":"aurelia-flux\\src\\instance-dispatcher.js","line":53,"description":"Dispatches an action alond with all passed\nparameters (paylod)","name":"dispatch","params":[{"name":"action","description":"","type":"String"},{"name":"...payload","description":"","type":"Any[]"}],"return":{"description":"void"},"class":""}],"properties":[],"events":[]} -------------------------------------------------------------------------------- /dist/amd/utils.js: -------------------------------------------------------------------------------- 1 | define(['exports'], function (exports) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | function globStringToRegexString(str) { 9 | return preg_quote(str).replace(/\\\*/g, '.*').replace(/\\\?/g, '.'); 10 | } 11 | function preg_quote(str, delimiter) { 12 | return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); 13 | } 14 | 15 | var Utils = (function () { 16 | function Utils() { 17 | _classCallCheck(this, Utils); 18 | } 19 | 20 | Utils.patternsToRegex = function patternsToRegex(patterns) { 21 | if (Array.isArray(patterns) === false) { 22 | patterns = Array.of(patterns); 23 | } 24 | 25 | return new RegExp('^' + patterns.map(globStringToRegexString).join('|') + '$'); 26 | }; 27 | 28 | return Utils; 29 | })(); 30 | 31 | exports.Utils = Utils; 32 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tomasz Frydrychewicz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist/system/index.js: -------------------------------------------------------------------------------- 1 | System.register(['./lifecycle-manager', './router', './instance-dispatcher', './decorators/handle', './decorators/waitFor'], function (_export) { 2 | 'use strict'; 3 | 4 | var LifecycleManager, RouterManager; 5 | 6 | _export('configure', configure); 7 | 8 | function configure(aurelia, configCallback) { 9 | LifecycleManager.interceptClassActivator(); 10 | LifecycleManager.interceptHtmlBehaviorResource(); 11 | RouterManager.AddFluxPipelineStep(aurelia); 12 | } 13 | 14 | return { 15 | setters: [function (_lifecycleManager) { 16 | LifecycleManager = _lifecycleManager.LifecycleManager; 17 | }, function (_router) { 18 | RouterManager = _router.RouterManager; 19 | }, function (_instanceDispatcher) { 20 | _export('Dispatcher', _instanceDispatcher.Dispatcher); 21 | }, function (_decoratorsHandle) { 22 | _export('handle', _decoratorsHandle.handle); 23 | }, function (_decoratorsWaitFor) { 24 | _export('waitFor', _decoratorsWaitFor.waitFor); 25 | }], 26 | execute: function () {} 27 | }; 28 | }); -------------------------------------------------------------------------------- /dist/amd/metadata.js: -------------------------------------------------------------------------------- 1 | define(['exports', './symbols'], function (exports, _symbols) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | var Metadata = (function () { 9 | Metadata.getOrCreateMetadata = function getOrCreateMetadata(target) { 10 | if (target[_symbols.Symbols.metadata] === undefined) { 11 | target[_symbols.Symbols.metadata] = new Metadata(); 12 | } 13 | 14 | return target[_symbols.Symbols.metadata]; 15 | }; 16 | 17 | Metadata.exists = function exists(target) { 18 | return target[_symbols.Symbols.metadata] !== undefined && target[_symbols.Symbols.metadata] instanceof Metadata; 19 | }; 20 | 21 | function Metadata() { 22 | _classCallCheck(this, Metadata); 23 | 24 | this.handlers = new Map(); 25 | this.awaiters = new Map(); 26 | } 27 | 28 | return Metadata; 29 | })(); 30 | 31 | exports.Metadata = Metadata; 32 | }); -------------------------------------------------------------------------------- /dist/system/utils.js: -------------------------------------------------------------------------------- 1 | System.register([], function (_export) { 2 | 'use strict'; 3 | 4 | var Utils; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | function globStringToRegexString(str) { 9 | return preg_quote(str).replace(/\\\*/g, '.*').replace(/\\\?/g, '.'); 10 | } 11 | function preg_quote(str, delimiter) { 12 | return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); 13 | } 14 | 15 | return { 16 | setters: [], 17 | execute: function () { 18 | Utils = (function () { 19 | function Utils() { 20 | _classCallCheck(this, Utils); 21 | } 22 | 23 | Utils.patternsToRegex = function patternsToRegex(patterns) { 24 | if (Array.isArray(patterns) === false) { 25 | patterns = Array.of(patterns); 26 | } 27 | 28 | return new RegExp('^' + patterns.map(globStringToRegexString).join('|') + '$'); 29 | }; 30 | 31 | return Utils; 32 | })(); 33 | 34 | _export('Utils', Utils); 35 | } 36 | }; 37 | }); -------------------------------------------------------------------------------- /test/utils.spec.js: -------------------------------------------------------------------------------- 1 | import {Utils} from 'src/utils'; 2 | 3 | describe('Utils', () => { 4 | describe('patternsArrayToRegex', () => { 5 | 6 | it('handles *', () => { 7 | expect(Utils.patternsToRegex("*")).toEqual(/^.*$/); 8 | expect(Utils.patternsToRegex("foo*")).toEqual(/^foo.*$/); 9 | expect(Utils.patternsToRegex("foo*bar")).toEqual(/^foo.*bar$/); 10 | }); 11 | 12 | it('handles ?', () => { 13 | expect(Utils.patternsToRegex("?")).toEqual(/^.$/); 14 | expect(Utils.patternsToRegex("foo?")).toEqual(/^foo.$/); 15 | expect(Utils.patternsToRegex("foo?bar")).toEqual(/^foo.bar$/); 16 | expect(Utils.patternsToRegex("foo??bar")).toEqual(/^foo..bar$/); 17 | }); 18 | 19 | it('escapes regex characters', () => { 20 | expect(Utils.patternsToRegex("foo()")).toEqual(/^foo\(\)$/); 21 | expect(Utils.patternsToRegex("foo[]")).toEqual(/^foo\[\]$/); 22 | expect(Utils.patternsToRegex("foo.")).toEqual(/^foo\.$/); 23 | expect(Utils.patternsToRegex("^(:foo)$")).toEqual(/^\^\(\:foo\)\$$/); 24 | }); 25 | 26 | it('handles patterns array', () => { 27 | expect(Utils.patternsToRegex(["foo", "bar"])).toEqual(/^foo|bar$/); 28 | expect(Utils.patternsToRegex(["foo*", "bar?"])).toEqual(/^foo.*|bar.$/); 29 | }); 30 | }); 31 | }); -------------------------------------------------------------------------------- /dist/commonjs/router.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6 | 7 | var _aureliaRouter = require('aurelia-router'); 8 | 9 | var _fluxDispatcher = require('./flux-dispatcher'); 10 | 11 | var RouterManager = (function () { 12 | function RouterManager() { 13 | _classCallCheck(this, RouterManager); 14 | } 15 | 16 | RouterManager.AddFluxPipelineStep = function AddFluxPipelineStep(aurelia) { 17 | var router = aurelia.container.get(_aureliaRouter.Router); 18 | var configuration = new _aureliaRouter.RouterConfiguration(); 19 | 20 | configuration.addPipelineStep("modelbind", FluxLifeCycleStep); 21 | router.configure(configuration); 22 | }; 23 | 24 | return RouterManager; 25 | })(); 26 | 27 | exports.RouterManager = RouterManager; 28 | 29 | var FluxLifeCycleStep = (function () { 30 | function FluxLifeCycleStep() { 31 | _classCallCheck(this, FluxLifeCycleStep); 32 | } 33 | 34 | FluxLifeCycleStep.prototype.run = function run(context, next) { 35 | 36 | if (context && context.plan && context.plan['default']) { 37 | _fluxDispatcher.FluxDispatcher.instance.strategy = context.plan['default'].strategy; 38 | } 39 | 40 | return next(); 41 | }; 42 | 43 | return FluxLifeCycleStep; 44 | })(); -------------------------------------------------------------------------------- /dist/commonjs/symbols.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 6 | 7 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8 | 9 | var Symbols = (function () { 10 | function Symbols() { 11 | _classCallCheck(this, Symbols); 12 | } 13 | 14 | _createClass(Symbols, null, [{ 15 | key: 'instanceDispatcher', 16 | value: Symbol('fluxDispatcher'), 17 | enumerable: true 18 | }, { 19 | key: 'metadata', 20 | value: Symbol('fluxMetadata'), 21 | enumerable: true 22 | }, { 23 | key: 'deactivators', 24 | value: Symbol('fluxDeactivators'), 25 | enumerable: true 26 | }]); 27 | 28 | return Symbols; 29 | })(); 30 | 31 | exports.Symbols = Symbols; -------------------------------------------------------------------------------- /dist/system/metadata.js: -------------------------------------------------------------------------------- 1 | System.register(['./symbols'], function (_export) { 2 | 'use strict'; 3 | 4 | var Symbols, Metadata; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | return { 9 | setters: [function (_symbols) { 10 | Symbols = _symbols.Symbols; 11 | }], 12 | execute: function () { 13 | Metadata = (function () { 14 | Metadata.getOrCreateMetadata = function getOrCreateMetadata(target) { 15 | if (target[Symbols.metadata] === undefined) { 16 | target[Symbols.metadata] = new Metadata(); 17 | } 18 | 19 | return target[Symbols.metadata]; 20 | }; 21 | 22 | Metadata.exists = function exists(target) { 23 | return target[Symbols.metadata] !== undefined && target[Symbols.metadata] instanceof Metadata; 24 | }; 25 | 26 | function Metadata() { 27 | _classCallCheck(this, Metadata); 28 | 29 | this.handlers = new Map(); 30 | this.awaiters = new Map(); 31 | } 32 | 33 | return Metadata; 34 | })(); 35 | 36 | _export('Metadata', Metadata); 37 | } 38 | }; 39 | }); -------------------------------------------------------------------------------- /dist/amd/router.js: -------------------------------------------------------------------------------- 1 | define(['exports', 'aurelia-router', './flux-dispatcher'], function (exports, _aureliaRouter, _fluxDispatcher) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | var RouterManager = (function () { 9 | function RouterManager() { 10 | _classCallCheck(this, RouterManager); 11 | } 12 | 13 | RouterManager.AddFluxPipelineStep = function AddFluxPipelineStep(aurelia) { 14 | var router = aurelia.container.get(_aureliaRouter.Router); 15 | var configuration = new _aureliaRouter.RouterConfiguration(); 16 | 17 | configuration.addPipelineStep("modelbind", FluxLifeCycleStep); 18 | router.configure(configuration); 19 | }; 20 | 21 | return RouterManager; 22 | })(); 23 | 24 | exports.RouterManager = RouterManager; 25 | 26 | var FluxLifeCycleStep = (function () { 27 | function FluxLifeCycleStep() { 28 | _classCallCheck(this, FluxLifeCycleStep); 29 | } 30 | 31 | FluxLifeCycleStep.prototype.run = function run(context, next) { 32 | 33 | if (context && context.plan && context.plan['default']) { 34 | _fluxDispatcher.FluxDispatcher.instance.strategy = context.plan['default'].strategy; 35 | } 36 | 37 | return next(); 38 | }; 39 | 40 | return FluxLifeCycleStep; 41 | })(); 42 | }); -------------------------------------------------------------------------------- /dist/amd/symbols.js: -------------------------------------------------------------------------------- 1 | define(['exports'], function (exports) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 7 | 8 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9 | 10 | var Symbols = (function () { 11 | function Symbols() { 12 | _classCallCheck(this, Symbols); 13 | } 14 | 15 | _createClass(Symbols, null, [{ 16 | key: 'instanceDispatcher', 17 | value: Symbol('fluxDispatcher'), 18 | enumerable: true 19 | }, { 20 | key: 'metadata', 21 | value: Symbol('fluxMetadata'), 22 | enumerable: true 23 | }, { 24 | key: 'deactivators', 25 | value: Symbol('fluxDeactivators'), 26 | enumerable: true 27 | }]); 28 | 29 | return Symbols; 30 | })(); 31 | 32 | exports.Symbols = Symbols; 33 | }); -------------------------------------------------------------------------------- /dist/system/symbols.js: -------------------------------------------------------------------------------- 1 | System.register([], function (_export) { 2 | 'use strict'; 3 | 4 | var Symbols; 5 | 6 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 7 | 8 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9 | 10 | return { 11 | setters: [], 12 | execute: function () { 13 | Symbols = (function () { 14 | function Symbols() { 15 | _classCallCheck(this, Symbols); 16 | } 17 | 18 | _createClass(Symbols, null, [{ 19 | key: 'instanceDispatcher', 20 | value: Symbol('fluxDispatcher'), 21 | enumerable: true 22 | }, { 23 | key: 'metadata', 24 | value: Symbol('fluxMetadata'), 25 | enumerable: true 26 | }, { 27 | key: 'deactivators', 28 | value: Symbol('fluxDeactivators'), 29 | enumerable: true 30 | }]); 31 | 32 | return Symbols; 33 | })(); 34 | 35 | _export('Symbols', Symbols); 36 | } 37 | }; 38 | }); -------------------------------------------------------------------------------- /doc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 0.1.7 (2015-09-13) 2 | 3 | * Upgraded Aurelia dependencies to early September release 4 | 5 | ### 0.1.6 (2015-08-04) 6 | 7 | #### Bug Fixes 8 | 9 | * **instance-dispatcher:** handle will now properly return release() function ([20936f9f](https://github.com/tfrydrychewicz/aurelia-flux/commit/20936f9f400b3e457a9a88c146e0741bc9091041), closes [#7](https://github.com/tfrydrychewicz/aurelia-flux/issues/7)) 10 | 11 | #### Features 12 | 13 | * **typescript-type-definitions:** Added babel-dts-generator generator ([e8edfc43](https://github.com/tfrydrychewicz/aurelia-flux/commit/e8edfc43fb7f4bc73ff47d4b7014994caed132d6), closes [#5](https://github.com/tfrydrychewicz/aurelia-flux/issues/5)) 14 | 15 | ### 0.1.5 (2015-07-31) 16 | 17 | #### Features 18 | 19 | * **activation-strategy:** Add support for invoke-lifecycle activation strategy ([e6f08d0d](https://github.com/tfrydrychewicz/aurelia-flux/commit/e6f08d0d3bea03db46ba0acf3b402f418c043e9c), closes [#6](https://github.com/tfrydrychewicz/aurelia-flux/issues/6)) 20 | 21 | ### 0.1.4 (2015-07-29) 22 | 23 | #### Features 24 | 25 | * **lifecycle-manager:** Added support for component detaching ([913f2160](https://github.com/tfrydrychewicz/aurelia-flux/commit/913f2160286e989d27947a1cc50be5d1ad84af95), closes [#2](https://github.com/tfrydrychewicz/aurelia-flux/issues/2)) 26 | 27 | ### 0.1.3 (2015-07-22) 28 | 29 | #### Bug Fixes 30 | 31 | * **waitFor:** @waitFor decorated handler will now properly handle dispatch ([bfc6ce95](https://github.com/tfrydrychewicz/aurelia-flux/commit/bfc6ce95e4b4938afa6b3644cc35aea29cc60ead)) 32 | 33 | ### 0.1.2 (2015-07-21) 34 | 35 | #### Bug Fixes 36 | 37 | * **instance-dispatcher:** waitFor now properly handles callback parameters ([8b0d9fca](https://github.com/tfrydrychewicz/aurelia-flux/commit/8b0d9fca2734ba93ebbe3b15ed600aa5b6340541)) 38 | -------------------------------------------------------------------------------- /dist/system/router.js: -------------------------------------------------------------------------------- 1 | System.register(['aurelia-router', './flux-dispatcher'], function (_export) { 2 | 'use strict'; 3 | 4 | var Router, RouterConfiguration, FluxDispatcher, RouterManager, FluxLifeCycleStep; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | return { 9 | setters: [function (_aureliaRouter) { 10 | Router = _aureliaRouter.Router; 11 | RouterConfiguration = _aureliaRouter.RouterConfiguration; 12 | }, function (_fluxDispatcher) { 13 | FluxDispatcher = _fluxDispatcher.FluxDispatcher; 14 | }], 15 | execute: function () { 16 | RouterManager = (function () { 17 | function RouterManager() { 18 | _classCallCheck(this, RouterManager); 19 | } 20 | 21 | RouterManager.AddFluxPipelineStep = function AddFluxPipelineStep(aurelia) { 22 | var router = aurelia.container.get(Router); 23 | var configuration = new RouterConfiguration(); 24 | 25 | configuration.addPipelineStep("modelbind", FluxLifeCycleStep); 26 | router.configure(configuration); 27 | }; 28 | 29 | return RouterManager; 30 | })(); 31 | 32 | _export('RouterManager', RouterManager); 33 | 34 | FluxLifeCycleStep = (function () { 35 | function FluxLifeCycleStep() { 36 | _classCallCheck(this, FluxLifeCycleStep); 37 | } 38 | 39 | FluxLifeCycleStep.prototype.run = function run(context, next) { 40 | 41 | if (context && context.plan && context.plan['default']) { 42 | FluxDispatcher.instance.strategy = context.plan['default'].strategy; 43 | } 44 | 45 | return next(); 46 | }; 47 | 48 | return FluxLifeCycleStep; 49 | })(); 50 | } 51 | }; 52 | }); -------------------------------------------------------------------------------- /dist/amd/instance-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from 'aurelia-flux/metadata'; 3 | import { Utils } from 'aurelia-flux/utils'; 4 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 5 | import Promise from 'bluebird'; 6 | import { Symbols } from 'aurelia-flux/symbols'; 7 | class Handler { 8 | constructor(regexp: any, handler: any); 9 | } 10 | export class Dispatcher { 11 | constructor(instance: Object); 12 | 13 | /** 14 | * Registers new handler function for given action patterns 15 | * 16 | * @method handle 17 | * @param {String|String[]} patterns 18 | * @param {(action:String, ...payload : any[]) => any} callback 19 | * @return {() => void} - unregistering function 20 | */ 21 | handle(patterns: String | String[], callback: ((action: String) => any)): (() => void); 22 | 23 | /** 24 | * Registers a method that will be invoked when all 25 | * given types finish dispatching 26 | * 27 | * @method waitFor 28 | * @param {String|String[]} types 29 | * @param {(() => any)} handler 30 | * @return void 31 | */ 32 | waitFor(types: String | String[], handler: (() => any)): void; 33 | 34 | /** 35 | * Dispatches an action alond with all passed 36 | * parameters (paylod) 37 | * 38 | * @method dispatch 39 | * @param {String} action 40 | * @param {any[]} ...payload 41 | * @return void 42 | */ 43 | dispatch(action: String, ...payload: any[]): void; 44 | dispatchOwn(action: String, payload: any[]): any; 45 | registerMetadata(): void; 46 | } 47 | export class DispatcherProxy { 48 | constructor(instancePromise: any); 49 | handle(patterns: any, handler: any): any; 50 | waitFor(types: any, handler: any): any; 51 | dispatch(action: any, ...payload: any[]): any; 52 | } 53 | } -------------------------------------------------------------------------------- /dist/es6/instance-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from 'aurelia-flux/metadata'; 3 | import { Utils } from 'aurelia-flux/utils'; 4 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 5 | import Promise from 'bluebird'; 6 | import { Symbols } from 'aurelia-flux/symbols'; 7 | class Handler { 8 | constructor(regexp: any, handler: any); 9 | } 10 | export class Dispatcher { 11 | constructor(instance: Object); 12 | 13 | /** 14 | * Registers new handler function for given action patterns 15 | * 16 | * @method handle 17 | * @param {String|String[]} patterns 18 | * @param {(action:String, ...payload : any[]) => any} callback 19 | * @return {() => void} - unregistering function 20 | */ 21 | handle(patterns: String | String[], callback: ((action: String) => any)): (() => void); 22 | 23 | /** 24 | * Registers a method that will be invoked when all 25 | * given types finish dispatching 26 | * 27 | * @method waitFor 28 | * @param {String|String[]} types 29 | * @param {(() => any)} handler 30 | * @return void 31 | */ 32 | waitFor(types: String | String[], handler: (() => any)): void; 33 | 34 | /** 35 | * Dispatches an action alond with all passed 36 | * parameters (paylod) 37 | * 38 | * @method dispatch 39 | * @param {String} action 40 | * @param {any[]} ...payload 41 | * @return void 42 | */ 43 | dispatch(action: String, ...payload: any[]): void; 44 | dispatchOwn(action: String, payload: any[]): any; 45 | registerMetadata(): void; 46 | } 47 | export class DispatcherProxy { 48 | constructor(instancePromise: any); 49 | handle(patterns: any, handler: any): any; 50 | waitFor(types: any, handler: any): any; 51 | dispatch(action: any, ...payload: any[]): any; 52 | } 53 | } -------------------------------------------------------------------------------- /dist/commonjs/instance-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from 'aurelia-flux/metadata'; 3 | import { Utils } from 'aurelia-flux/utils'; 4 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 5 | import Promise from 'bluebird'; 6 | import { Symbols } from 'aurelia-flux/symbols'; 7 | class Handler { 8 | constructor(regexp: any, handler: any); 9 | } 10 | export class Dispatcher { 11 | constructor(instance: Object); 12 | 13 | /** 14 | * Registers new handler function for given action patterns 15 | * 16 | * @method handle 17 | * @param {String|String[]} patterns 18 | * @param {(action:String, ...payload : any[]) => any} callback 19 | * @return {() => void} - unregistering function 20 | */ 21 | handle(patterns: String | String[], callback: ((action: String) => any)): (() => void); 22 | 23 | /** 24 | * Registers a method that will be invoked when all 25 | * given types finish dispatching 26 | * 27 | * @method waitFor 28 | * @param {String|String[]} types 29 | * @param {(() => any)} handler 30 | * @return void 31 | */ 32 | waitFor(types: String | String[], handler: (() => any)): void; 33 | 34 | /** 35 | * Dispatches an action alond with all passed 36 | * parameters (paylod) 37 | * 38 | * @method dispatch 39 | * @param {String} action 40 | * @param {any[]} ...payload 41 | * @return void 42 | */ 43 | dispatch(action: String, ...payload: any[]): void; 44 | dispatchOwn(action: String, payload: any[]): any; 45 | registerMetadata(): void; 46 | } 47 | export class DispatcherProxy { 48 | constructor(instancePromise: any); 49 | handle(patterns: any, handler: any): any; 50 | waitFor(types: any, handler: any): any; 51 | dispatch(action: any, ...payload: any[]): any; 52 | } 53 | } -------------------------------------------------------------------------------- /dist/system/instance-dispatcher.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aurelia-flux' { 2 | import { Metadata } from 'aurelia-flux/metadata'; 3 | import { Utils } from 'aurelia-flux/utils'; 4 | import { FluxDispatcher } from 'aurelia-flux/flux-dispatcher'; 5 | import Promise from 'bluebird'; 6 | import { Symbols } from 'aurelia-flux/symbols'; 7 | class Handler { 8 | constructor(regexp: any, handler: any); 9 | } 10 | export class Dispatcher { 11 | constructor(instance: Object); 12 | 13 | /** 14 | * Registers new handler function for given action patterns 15 | * 16 | * @method handle 17 | * @param {String|String[]} patterns 18 | * @param {(action:String, ...payload : any[]) => any} callback 19 | * @return {() => void} - unregistering function 20 | */ 21 | handle(patterns: String | String[], callback: ((action: String) => any)): (() => void); 22 | 23 | /** 24 | * Registers a method that will be invoked when all 25 | * given types finish dispatching 26 | * 27 | * @method waitFor 28 | * @param {String|String[]} types 29 | * @param {(() => any)} handler 30 | * @return void 31 | */ 32 | waitFor(types: String | String[], handler: (() => any)): void; 33 | 34 | /** 35 | * Dispatches an action alond with all passed 36 | * parameters (paylod) 37 | * 38 | * @method dispatch 39 | * @param {String} action 40 | * @param {any[]} ...payload 41 | * @return void 42 | */ 43 | dispatch(action: String, ...payload: any[]): void; 44 | dispatchOwn(action: String, payload: any[]): any; 45 | registerMetadata(): void; 46 | } 47 | export class DispatcherProxy { 48 | constructor(instancePromise: any); 49 | handle(patterns: any, handler: any): any; 50 | waitFor(types: any, handler: any): any; 51 | dispatch(action: any, ...payload: any[]): any; 52 | } 53 | } -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Dec 05 2014 16:49:29 GMT-0500 (EST) 3 | 4 | var babelOptions = { 5 | sourceMap: 'inline', 6 | modules: 'system', 7 | moduleIds: false, 8 | comments: false, 9 | loose: "all", 10 | optional: [ 11 | "es7.decorators", 12 | "es7.classProperties" 13 | ] 14 | }; 15 | 16 | module.exports = function(config) { 17 | config.set({ 18 | 19 | // base path that will be used to resolve all patterns (eg. files, exclude) 20 | basePath: '', 21 | 22 | 23 | // frameworks to use 24 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 25 | frameworks: ['phantomjs-shim', 'jspm', 'jasmine'], 26 | 27 | jspm: { 28 | // Edit this to your needs 29 | loadFiles: ['src/**/*.js', 'test/**/*.js'] 30 | }, 31 | 32 | 33 | // list of files / patterns to load in the browser 34 | files: [], 35 | 36 | 37 | // list of files to exclude 38 | exclude: [ 39 | ], 40 | 41 | 42 | // preprocess matching files before serving them to the browser 43 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 44 | preprocessors: { 45 | 'test/**/*.js': ['babel'], 46 | 'src/**/*.js': ['babel'] 47 | }, 48 | 'babelPreprocessor': { 49 | options: babelOptions 50 | }, 51 | 52 | // test results reporter to use 53 | // possible values: 'dots', 'progress' 54 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 55 | reporters: ['progress'], 56 | 57 | // web server port 58 | port: 9876, 59 | 60 | 61 | // enable / disable colors in the output (reporters and logs) 62 | colors: true, 63 | 64 | 65 | // level of logging 66 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 67 | logLevel: config.LOG_INFO, 68 | 69 | 70 | // enable / disable watching file and executing tests whenever any file changes 71 | autoWatch: true, 72 | 73 | 74 | // start these browsers 75 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 76 | browsers: ['Chrome'], 77 | 78 | 79 | // Continuous Integration mode 80 | // if true, Karma captures browsers, runs the tests and exits 81 | singleRun: false 82 | }); 83 | }; 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-flux", 3 | "version": "0.1.7", 4 | "description": "A Flux dispatcher plugin for Aurelia.", 5 | "keywords": [ 6 | "aurelia", 7 | "flux", 8 | "plugin" 9 | ], 10 | "homepage": "https://github.com/tfrydrychewicz/aurelia-flux", 11 | "bugs": { 12 | "url": "https://github.com/tfrydrychewicz/aurelia-flux/issues" 13 | }, 14 | "license": "MIT", 15 | "author": "Tomasz Frydrychewicz ", 16 | "main": "dist/commonjs/index.js", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/tfrydrychewicz/aurelia-flux" 20 | }, 21 | "scripts": { 22 | "test": "./node_modules/.bin/karma start --single-run --browsers Firefox" 23 | }, 24 | "jspm": { 25 | "main": "index", 26 | "format": "amd", 27 | "directories": { 28 | "lib": "dist/amd" 29 | }, 30 | "dependencies": { 31 | "aurelia-binding": "github:aurelia/binding@^0.9.1", 32 | "aurelia-dependency-injection": "github:aurelia/dependency-injection@^0.10.1", 33 | "aurelia-router": "github:aurelia/router@^0.12.0", 34 | "aurelia-templating": "github:aurelia/templating@^0.15.3", 35 | "bluebird": "npm:bluebird@^2.9.27", 36 | "core-js": "npm:core-js@^1.1.4" 37 | }, 38 | "devDependencies": { 39 | "babel": "npm:babel-core@^5.8.24", 40 | "babel-runtime": "npm:babel-runtime@^5.8.24", 41 | "core-js": "npm:core-js@^1.1.4" 42 | } 43 | }, 44 | "devDependencies": { 45 | "aurelia-tools": "^0.1.0", 46 | "babel-dts-generator": "^0.2.6", 47 | "conventional-changelog": "0.0.11", 48 | "del": "^1.1.0", 49 | "es5-shim": "^4.1.5", 50 | "es6-shim": "^0.28.1", 51 | "gulp": "^3.8.10", 52 | "gulp-babel": "^5.1.0", 53 | "gulp-bump": "^0.1.11", 54 | "gulp-jshint": "^1.9.0", 55 | "gulp-rename": "^1.2.2", 56 | "gulp-yuidoc": "^0.1.2", 57 | "jasmine-core": "^2.1.3", 58 | "jshint-stylish": "^1.0.0", 59 | "jspm": "beta", 60 | "karma": "^0.12.28", 61 | "karma-babel-preprocessor": "^5.2.1", 62 | "karma-chrome-launcher": "^0.1.7", 63 | "karma-firefox-launcher": "^0.1.6", 64 | "karma-jasmine": "^0.3.2", 65 | "karma-jspm": "^2.0.1-beta.1", 66 | "karma-phantomjs-launcher": "^0.2.1", 67 | "karma-phantomjs-shim": "^1.0.0", 68 | "object.assign": "^1.0.3", 69 | "phantomjs": "^1.9.17", 70 | "require-dir": "^0.1.0", 71 | "run-sequence": "^1.1.0", 72 | "vinyl-paths": "^1.0.0", 73 | "yargs": "^2.1.1" 74 | }, 75 | "aurelia": { 76 | "usedBy": [], 77 | "documentation": { 78 | "links": [ 79 | { 80 | "rel": "license", 81 | "mediaType": "text/plain", 82 | "title": "The MIT License (MIT)", 83 | "href": "LICENSE" 84 | }, 85 | { 86 | "rel": "describedby", 87 | "mediaType": "application/aurelia-doc+json", 88 | "title": "API", 89 | "href": "doc/api.json" 90 | }, 91 | { 92 | "rel": "version-history", 93 | "mediaType": "text/markdown", 94 | "title": "Change Log", 95 | "href": "doc/CHANGELOG.md" 96 | } 97 | ] 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | System.config({ 2 | defaultJSExtensions: true, 3 | transpiler: "babel", 4 | babelOptions: { 5 | "optional": [ 6 | "runtime", 7 | "es7.decorators", 8 | "es7.classProperties" 9 | ] 10 | }, 11 | paths: { 12 | "*": "*", 13 | "github:*": "jspm_packages/github/*", 14 | "npm:*": "jspm_packages/npm/*" 15 | }, 16 | 17 | map: { 18 | "aurelia-binding": "github:aurelia/binding@0.9.1", 19 | "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.10.1", 20 | "aurelia-router": "github:aurelia/router@0.12.0", 21 | "aurelia-templating": "github:aurelia/templating@0.15.3", 22 | "babel": "npm:babel-core@5.8.24", 23 | "babel-runtime": "npm:babel-runtime@5.8.24", 24 | "bluebird": "npm:bluebird@2.9.34", 25 | "core-js": "npm:core-js@1.1.4", 26 | "github:aurelia/binding@0.9.1": { 27 | "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.10.1", 28 | "aurelia-metadata": "github:aurelia/metadata@0.8.0", 29 | "aurelia-task-queue": "github:aurelia/task-queue@0.7.0", 30 | "core-js": "npm:core-js@0.9.18" 31 | }, 32 | "github:aurelia/dependency-injection@0.10.1": { 33 | "aurelia-logging": "github:aurelia/logging@0.7.0", 34 | "aurelia-metadata": "github:aurelia/metadata@0.8.0", 35 | "core-js": "npm:core-js@0.9.18" 36 | }, 37 | "github:aurelia/event-aggregator@0.8.0": { 38 | "aurelia-logging": "github:aurelia/logging@0.7.0" 39 | }, 40 | "github:aurelia/loader@0.9.0": { 41 | "aurelia-html-template-element": "github:aurelia/html-template-element@0.3.0", 42 | "aurelia-metadata": "github:aurelia/metadata@0.8.0", 43 | "aurelia-path": "github:aurelia/path@0.9.0", 44 | "core-js": "github:zloirock/core-js@0.8.4" 45 | }, 46 | "github:aurelia/metadata@0.8.0": { 47 | "core-js": "npm:core-js@0.9.18" 48 | }, 49 | "github:aurelia/route-recognizer@0.7.0": { 50 | "aurelia-path": "github:aurelia/path@0.9.0", 51 | "core-js": "npm:core-js@0.9.18" 52 | }, 53 | "github:aurelia/router@0.12.0": { 54 | "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.10.1", 55 | "aurelia-event-aggregator": "github:aurelia/event-aggregator@0.8.0", 56 | "aurelia-history": "github:aurelia/history@0.7.0", 57 | "aurelia-logging": "github:aurelia/logging@0.7.0", 58 | "aurelia-path": "github:aurelia/path@0.9.0", 59 | "aurelia-route-recognizer": "github:aurelia/route-recognizer@0.7.0", 60 | "core-js": "npm:core-js@0.9.18" 61 | }, 62 | "github:aurelia/templating@0.15.3": { 63 | "aurelia-binding": "github:aurelia/binding@0.9.1", 64 | "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.10.1", 65 | "aurelia-html-template-element": "github:aurelia/html-template-element@0.3.0", 66 | "aurelia-loader": "github:aurelia/loader@0.9.0", 67 | "aurelia-logging": "github:aurelia/logging@0.7.0", 68 | "aurelia-metadata": "github:aurelia/metadata@0.8.0", 69 | "aurelia-path": "github:aurelia/path@0.9.0", 70 | "aurelia-task-queue": "github:aurelia/task-queue@0.7.0", 71 | "core-js": "npm:core-js@0.9.18" 72 | }, 73 | "github:jspm/nodelibs-process@0.1.1": { 74 | "process": "npm:process@0.10.1" 75 | }, 76 | "npm:babel-runtime@5.8.24": { 77 | "process": "github:jspm/nodelibs-process@0.1.1" 78 | }, 79 | "npm:bluebird@2.9.34": { 80 | "process": "github:jspm/nodelibs-process@0.1.1" 81 | }, 82 | "npm:core-js@0.9.18": { 83 | "fs": "github:jspm/nodelibs-fs@0.1.2", 84 | "process": "github:jspm/nodelibs-process@0.1.1", 85 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 86 | }, 87 | "npm:core-js@1.1.4": { 88 | "fs": "github:jspm/nodelibs-fs@0.1.2", 89 | "process": "github:jspm/nodelibs-process@0.1.1", 90 | "systemjs-json": "github:systemjs/plugin-json@0.1.0" 91 | } 92 | } 93 | }); 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aurelia-flux 2 | [![Join the chat at https://gitter.im/aurelia/discuss](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/aurelia/discuss?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 3 | [![Circle CI](https://circleci.com/gh/tfrydrychewicz/aurelia-flux.svg?&style=shield&circle-token=072ff96bc8a1c1b3bc23cd72c0c39639e5531bdb)](https://circleci.com/gh/tfrydrychewicz/aurelia-flux) 4 | 5 | A Flux plugin for [Aurelia](http://www.aurelia.io/) that supports Promises. 6 | 7 | ``` javascript 8 | import {inject} from 'aurelia-framework'; 9 | import {Dispatcher, handle, waitFor} from 'aurelia-flux'; 10 | 11 | @inject(Dispatcher) 12 | class MessagesStore { 13 | messages = []; 14 | 15 | constructor(dispatcher) { 16 | this.dispatcher = dispatcher; 17 | } 18 | 19 | @handle('message.submit') 20 | collect(action, message) { 21 | return new Promise((resolve) => { 22 | setTimeout(() => { 23 | this.messages.push(message); 24 | this.dispatcher.dispatch('message.submitted', message); 25 | resolve(); 26 | }, 1000); 27 | }); 28 | } 29 | 30 | getMessages() { 31 | return this.messages; 32 | } 33 | } 34 | 35 | @inject(Dispatcher, MessagesStore) 36 | export class Welcome { 37 | 38 | message = "Hello Aurelia!"; 39 | 40 | constructor(dispatcher, store) { 41 | this.dispatcher = dispatcher; 42 | this.store = store; 43 | 44 | this.dispatcher.handle('message.submitted', (action, message) => { 45 | alert(message); 46 | }); 47 | } 48 | 49 | submit() { 50 | this.dispatcher.dispatch('message.submit', this.message); 51 | } 52 | 53 | @handle('message.*') 54 | @waitFor(MessagesStore) 55 | logMessage(action, message) { 56 | console.log(event, message); 57 | } 58 | } 59 | ``` 60 | ## Articles 61 | 62 | * [Creating Reactive, Loosely Coupled Apps with Aurelia and Flux - Episode 1](http://blog.durandal.io/2015/07/23/creating-reactive-loosely-coupled-apps-with-aurelia-and-flux-episode-1/) 63 | * [Creating Reactive, Loosely Coupled Apps with Aurelia and Flux - Episode 2](http://blog.durandal.io/2015/08/07/creating-reactive-loosely-coupled-apps-with-aurelia-and-flux-episode-2/) 64 | 65 | ## Dependencies 66 | 67 | * [aurelia-binding](https://github.com/aurelia/binding) 68 | * [aurelia-dependency-injection](https://github.com/aurelia/dependency-injection) 69 | * [aurelia-router](https://github.com/aurelia/router) 70 | * [aurelia-templating](https://github.com/aurelia/templating) 71 | * [bluebird](https://github.com/petkaantonov/bluebird) 72 | 73 | ## Used By 74 | 75 | This library isn't used by [Aurelia](http://www.aurelia.io/). It is an optional plugin. 76 | 77 | ## Platform Support 78 | 79 | This library can be used in the **browser** only. 80 | 81 | ## Building The Code 82 | 83 | To build the code, follow these steps. 84 | 85 | 1. Ensure that [NodeJS](http://nodejs.org/) is installed. This provides the platform on which the build tooling runs. 86 | 2. From the project folder, execute the following command: 87 | 88 | ```shell 89 | npm install 90 | ``` 91 | 3. Ensure that [Gulp](http://gulpjs.com/) is installed. If you need to install it, use the following command: 92 | 93 | ```shell 94 | npm install -g gulp 95 | ``` 96 | 4. To build the code, you can now run: 97 | 98 | ```shell 99 | gulp build 100 | ``` 101 | 5. You will find the compiled code in the `dist` folder, available in three module formats: AMD, CommonJS and ES6. 102 | 103 | 6. See `gulpfile.js` for other tasks related to generating the docs and linting. 104 | 105 | ## Running The Tests 106 | 107 | To run the unit tests, first ensure that you have followed the steps above in order to install all dependencies and successfully build the library. Once you have done that, proceed with these additional steps: 108 | 109 | 1. Ensure that the [Karma](http://karma-runner.github.io/) CLI is installed. If you need to install it, use the following command: 110 | 111 | ```shell 112 | npm install -g karma-cli 113 | ``` 114 | 2. Ensure that [jspm](http://jspm.io/) is installed. If you need to install it, use the following commnand: 115 | 116 | ```shell 117 | npm install -g jspm 118 | ``` 119 | 3. Install the client-side dependencies with jspm: 120 | 121 | ```shell 122 | jspm install 123 | ``` 124 | 125 | 4. You can now run the tests with this command: 126 | 127 | ```shell 128 | karma start 129 | ``` 130 | -------------------------------------------------------------------------------- /src/flux-dispatcher.js: -------------------------------------------------------------------------------- 1 | import Promise from 'bluebird'; 2 | import {Dispatcher} from './instance-dispatcher'; 3 | 4 | export class FluxDispatcher { 5 | static instance = new FluxDispatcher(); 6 | 7 | constructor() { 8 | this.instanceDispatchers = new Map(); 9 | this.isDispatching = false; 10 | this.queue = []; 11 | this.typesPromises = new Map(); 12 | } 13 | 14 | getOrCreateTypeDispatchers(type : Object) : Set { 15 | if(this.instanceDispatchers.has(type) === false) { 16 | this.instanceDispatchers.set(type, new Set()); 17 | } 18 | 19 | return this.instanceDispatchers.get(type); 20 | } 21 | 22 | getOrCreateTypePromises(type : Object) { 23 | if(this.typesPromises.has(type) === false) { 24 | this.typesPromises.set(type, Promise.defer()); 25 | } 26 | 27 | return this.typesPromises.get(type); 28 | } 29 | 30 | registerInstanceDispatcher(dispatcher : Dispatcher) { 31 | if(dispatcher === undefined || dispatcher.instance === undefined) { 32 | return; 33 | } 34 | 35 | var typeDispatchers = this.getOrCreateTypeDispatchers(Object.getPrototypeOf(dispatcher.instance)); 36 | 37 | typeDispatchers.add(dispatcher); 38 | } 39 | 40 | unregisterInstanceDispatcher(dispatcher : Dispatcher) { 41 | if(dispatcher === undefined || dispatcher.instance === undefined) { 42 | return; 43 | } 44 | 45 | let type = Object.getPrototypeOf(dispatcher.instance); 46 | 47 | if(this.instanceDispatchers.has(type) === false) { 48 | return; 49 | } 50 | 51 | this.instanceDispatchers.get(type).delete(dispatcher); 52 | 53 | if(this.instanceDispatchers.get(type).size === 0) { 54 | this.instanceDispatchers.delete(type); 55 | } 56 | } 57 | 58 | dispatch(action : String, payload : any) { 59 | this.$dispatch(action, payload, false); 60 | } 61 | 62 | $dispatch(action : String, payload : any, fromQueue : boolean) { 63 | 64 | if(this.isDispatching && fromQueue === false) { 65 | this.queue.push([action, payload]); 66 | return; 67 | } 68 | 69 | this.isDispatching = true; 70 | 71 | this.typesPromises = new Map(); 72 | 73 | this.instanceDispatchers.forEach((dispatchers, type) => { 74 | var typePromise = this.getOrCreateTypePromises(type); 75 | var promises = []; 76 | 77 | dispatchers.forEach((dispatcher) => { 78 | promises.push(dispatcher.dispatchOwn.apply(dispatcher, [action, payload])); 79 | }); 80 | 81 | Promise.settle(promises).then(() => { 82 | typePromise.resolve(); 83 | }); 84 | }); 85 | 86 | this.typesPromises.forEach((promise, type) => { 87 | if(this.instanceDispatchers.has(type) === false) { 88 | 89 | let name = (type !== undefined && type.constructor !== undefined && type.constructor.name !== undefined) ? type.constructor.name : type.toString(); 90 | console.warn(`You are waiting for a type '${name}' that didn't handle event '${action}'. ${name} promise has been resolved automatically.`); 91 | 92 | promise.resolve(); 93 | } 94 | }); 95 | 96 | var allTypesPromises = Array.from(this.typesPromises.values()).map((defer) => { return defer.promise; }); 97 | 98 | Promise.settle(allTypesPromises).then(() => { 99 | let next = this.queue.shift(); 100 | setTimeout(() => { 101 | if(next !== undefined) { 102 | this.$dispatch(next[0], next[1], true); 103 | } else { 104 | this.isDispatching = false; 105 | } 106 | }, 0); 107 | }); 108 | } 109 | 110 | waitFor(types : String|String[], handler: (() => any)) { 111 | if(Array.isArray(types) === false) { 112 | types = [types]; 113 | } 114 | 115 | let typesPromises = types.map((type) => { 116 | return this.getOrCreateTypePromises(type.prototype).promise; 117 | }); 118 | 119 | var def = Promise.defer(); 120 | 121 | Promise.settle(typesPromises).then(() => { 122 | Promise.resolve(handler()).then((ret) => { 123 | def.resolve(ret); 124 | }).catch((err) => { 125 | def.reject(err); 126 | }); 127 | }); 128 | 129 | return def.promise; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /dist/es6/flux-dispatcher.js: -------------------------------------------------------------------------------- 1 | import Promise from 'bluebird'; 2 | import {Dispatcher} from './instance-dispatcher'; 3 | 4 | export class FluxDispatcher { 5 | static instance = new FluxDispatcher(); 6 | 7 | constructor() { 8 | this.instanceDispatchers = new Map(); 9 | this.isDispatching = false; 10 | this.queue = []; 11 | this.typesPromises = new Map(); 12 | } 13 | 14 | getOrCreateTypeDispatchers(type : Object) : Set { 15 | if(this.instanceDispatchers.has(type) === false) { 16 | this.instanceDispatchers.set(type, new Set()); 17 | } 18 | 19 | return this.instanceDispatchers.get(type); 20 | } 21 | 22 | getOrCreateTypePromises(type : Object) { 23 | if(this.typesPromises.has(type) === false) { 24 | this.typesPromises.set(type, Promise.defer()); 25 | } 26 | 27 | return this.typesPromises.get(type); 28 | } 29 | 30 | registerInstanceDispatcher(dispatcher : Dispatcher) { 31 | if(dispatcher === undefined || dispatcher.instance === undefined) { 32 | return; 33 | } 34 | 35 | var typeDispatchers = this.getOrCreateTypeDispatchers(Object.getPrototypeOf(dispatcher.instance)); 36 | 37 | typeDispatchers.add(dispatcher); 38 | } 39 | 40 | unregisterInstanceDispatcher(dispatcher : Dispatcher) { 41 | if(dispatcher === undefined || dispatcher.instance === undefined) { 42 | return; 43 | } 44 | 45 | let type = Object.getPrototypeOf(dispatcher.instance); 46 | 47 | if(this.instanceDispatchers.has(type) === false) { 48 | return; 49 | } 50 | 51 | this.instanceDispatchers.get(type).delete(dispatcher); 52 | 53 | if(this.instanceDispatchers.get(type).size === 0) { 54 | this.instanceDispatchers.delete(type); 55 | } 56 | } 57 | 58 | dispatch(action : String, payload : any) { 59 | this.$dispatch(action, payload, false); 60 | } 61 | 62 | $dispatch(action : String, payload : any, fromQueue : boolean) { 63 | 64 | if(this.isDispatching && fromQueue === false) { 65 | this.queue.push([action, payload]); 66 | return; 67 | } 68 | 69 | this.isDispatching = true; 70 | 71 | this.typesPromises = new Map(); 72 | 73 | this.instanceDispatchers.forEach((dispatchers, type) => { 74 | var typePromise = this.getOrCreateTypePromises(type); 75 | var promises = []; 76 | 77 | dispatchers.forEach((dispatcher) => { 78 | promises.push(dispatcher.dispatchOwn.apply(dispatcher, [action, payload])); 79 | }); 80 | 81 | Promise.settle(promises).then(() => { 82 | typePromise.resolve(); 83 | }); 84 | }); 85 | 86 | this.typesPromises.forEach((promise, type) => { 87 | if(this.instanceDispatchers.has(type) === false) { 88 | 89 | let name = (type !== undefined && type.constructor !== undefined && type.constructor.name !== undefined) ? type.constructor.name : type.toString(); 90 | console.warn(`You are waiting for a type '${name}' that didn't handle event '${action}'. ${name} promise has been resolved automatically.`); 91 | 92 | promise.resolve(); 93 | } 94 | }); 95 | 96 | var allTypesPromises = Array.from(this.typesPromises.values()).map((defer) => { return defer.promise; }); 97 | 98 | Promise.settle(allTypesPromises).then(() => { 99 | let next = this.queue.shift(); 100 | setTimeout(() => { 101 | if(next !== undefined) { 102 | this.$dispatch(next[0], next[1], true); 103 | } else { 104 | this.isDispatching = false; 105 | } 106 | }, 0); 107 | }); 108 | } 109 | 110 | waitFor(types : String|String[], handler: (() => any)) { 111 | if(Array.isArray(types) === false) { 112 | types = [types]; 113 | } 114 | 115 | let typesPromises = types.map((type) => { 116 | return this.getOrCreateTypePromises(type.prototype).promise; 117 | }); 118 | 119 | var def = Promise.defer(); 120 | 121 | Promise.settle(typesPromises).then(() => { 122 | Promise.resolve(handler()).then((ret) => { 123 | def.resolve(ret); 124 | }).catch((err) => { 125 | def.reject(err); 126 | }); 127 | }); 128 | 129 | return def.promise; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/instance-dispatcher.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from './metadata'; 2 | import {Utils} from './utils'; 3 | import {FluxDispatcher} from './flux-dispatcher'; 4 | import Promise from 'bluebird'; 5 | import {Symbols} from './symbols'; 6 | 7 | class Handler { 8 | constructor(regexp, handler) { 9 | this.regexp = regexp; 10 | this.function = handler; 11 | } 12 | } 13 | 14 | export class Dispatcher { 15 | 16 | constructor(instance : Object) { 17 | this.instance = instance; 18 | this.handlers = new Set(); 19 | 20 | FluxDispatcher.instance.registerInstanceDispatcher(this); 21 | } 22 | 23 | /** 24 | * Registers new handler function for given action patterns 25 | * 26 | * @method handle 27 | * @param {String|String[]} patterns 28 | * @param {(action:String, ...payload : any[]) => any} callback 29 | * @return {() => void} - unregistering function 30 | */ 31 | handle(patterns : String|String[], callback : ((action : String, ...payload : any[]) => any)) : (() => void) { 32 | var handler = new Handler(Utils.patternsToRegex(patterns), callback) 33 | this.handlers.add(handler); 34 | 35 | return () => { 36 | this.handlers.delete(handler); 37 | }; 38 | } 39 | 40 | /** 41 | * Registers a method that will be invoked when all 42 | * given types finish dispatching 43 | * 44 | * @method waitFor 45 | * @param {String|String[]} types 46 | * @param {(() => any)} handler 47 | * @return void 48 | */ 49 | waitFor(types : String|String[], handler : (() => any)) : void { 50 | FluxDispatcher.instance.waitFor(types, handler); 51 | } 52 | 53 | /** 54 | * Dispatches an action alond with all passed 55 | * parameters (paylod) 56 | * 57 | * @method dispatch 58 | * @param {String} action 59 | * @param {any[]} ...payload 60 | * @return void 61 | */ 62 | dispatch(action : String, ...payload:any[]) : void { 63 | FluxDispatcher.instance.dispatch(action, payload); 64 | } 65 | 66 | dispatchOwn(action : String, payload:any[]) { 67 | 68 | var promises = []; 69 | 70 | this.handlers.forEach((handler) => { 71 | if(handler.regexp.test(action)) { 72 | promises.push(Promise.resolve(handler.function.apply(this.instance, [action].concat(payload)))); 73 | } 74 | }); 75 | 76 | return Promise.settle(promises); 77 | } 78 | 79 | registerMetadata() : void { 80 | var metadata = Metadata.getOrCreateMetadata(Object.getPrototypeOf(this.instance)); 81 | 82 | metadata.awaiters.forEach((types, methodName) => { 83 | if(this.instance[methodName] !== undefined && typeof this.instance[methodName] === 'function') { 84 | var methodImpl = this.instance[methodName]; 85 | this.instance[methodName] = (...args) => { 86 | return FluxDispatcher.instance.waitFor(types, () => { 87 | methodImpl.apply(this.instance, args); 88 | }); 89 | }; 90 | } 91 | }); 92 | 93 | metadata.handlers.forEach((patterns, methodName) => { 94 | if(this.instance[methodName] !== undefined && typeof this.instance[methodName] === 'function') { 95 | this.handlers.add(new Handler(Utils.patternsToRegex(patterns), this.instance[methodName])); 96 | } 97 | }); 98 | } 99 | } 100 | 101 | export class DispatcherProxy { 102 | 103 | constructor(instancePromise) { 104 | this.inititalize = Promise.resolve(instancePromise).then((instance) => { 105 | this.instance = instance; 106 | }); 107 | } 108 | 109 | 110 | handle(patterns, handler) { 111 | var def = Promise.defer(); 112 | 113 | this.inititalize.then(() => { 114 | def.resolve(this.instance[Symbols.instanceDispatcher].handle(patterns, handler)); 115 | }); 116 | 117 | return function() { 118 | def.promise.then((unregister) => unregister()); 119 | } 120 | } 121 | 122 | waitFor(types, handler) { 123 | this.inititalize.then(() => { 124 | this.instance[Symbols.instanceDispatcher].waitFor(types, handler); 125 | }); 126 | } 127 | 128 | dispatch(action, ...payload) { 129 | this.inititalize.then(() => { 130 | this.instance[Symbols.instanceDispatcher].dispatch 131 | .apply(this.instance[Symbols.instanceDispatcher],[action].concat(payload)); 132 | }); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /dist/es6/instance-dispatcher.js: -------------------------------------------------------------------------------- 1 | import {Metadata} from './metadata'; 2 | import {Utils} from './utils'; 3 | import {FluxDispatcher} from './flux-dispatcher'; 4 | import Promise from 'bluebird'; 5 | import {Symbols} from './symbols'; 6 | 7 | class Handler { 8 | constructor(regexp, handler) { 9 | this.regexp = regexp; 10 | this.function = handler; 11 | } 12 | } 13 | 14 | export class Dispatcher { 15 | 16 | constructor(instance : Object) { 17 | this.instance = instance; 18 | this.handlers = new Set(); 19 | 20 | FluxDispatcher.instance.registerInstanceDispatcher(this); 21 | } 22 | 23 | /** 24 | * Registers new handler function for given action patterns 25 | * 26 | * @method handle 27 | * @param {String|String[]} patterns 28 | * @param {(action:String, ...payload : any[]) => any} callback 29 | * @return {() => void} - unregistering function 30 | */ 31 | handle(patterns : String|String[], callback : ((action : String, ...payload : any[]) => any)) : (() => void) { 32 | var handler = new Handler(Utils.patternsToRegex(patterns), callback) 33 | this.handlers.add(handler); 34 | 35 | return () => { 36 | this.handlers.delete(handler); 37 | }; 38 | } 39 | 40 | /** 41 | * Registers a method that will be invoked when all 42 | * given types finish dispatching 43 | * 44 | * @method waitFor 45 | * @param {String|String[]} types 46 | * @param {(() => any)} handler 47 | * @return void 48 | */ 49 | waitFor(types : String|String[], handler : (() => any)) : void { 50 | FluxDispatcher.instance.waitFor(types, handler); 51 | } 52 | 53 | /** 54 | * Dispatches an action alond with all passed 55 | * parameters (paylod) 56 | * 57 | * @method dispatch 58 | * @param {String} action 59 | * @param {any[]} ...payload 60 | * @return void 61 | */ 62 | dispatch(action : String, ...payload:any[]) : void { 63 | FluxDispatcher.instance.dispatch(action, payload); 64 | } 65 | 66 | dispatchOwn(action : String, payload:any[]) { 67 | 68 | var promises = []; 69 | 70 | this.handlers.forEach((handler) => { 71 | if(handler.regexp.test(action)) { 72 | promises.push(Promise.resolve(handler.function.apply(this.instance, [action].concat(payload)))); 73 | } 74 | }); 75 | 76 | return Promise.settle(promises); 77 | } 78 | 79 | registerMetadata() : void { 80 | var metadata = Metadata.getOrCreateMetadata(Object.getPrototypeOf(this.instance)); 81 | 82 | metadata.awaiters.forEach((types, methodName) => { 83 | if(this.instance[methodName] !== undefined && typeof this.instance[methodName] === 'function') { 84 | var methodImpl = this.instance[methodName]; 85 | this.instance[methodName] = (...args) => { 86 | return FluxDispatcher.instance.waitFor(types, () => { 87 | methodImpl.apply(this.instance, args); 88 | }); 89 | }; 90 | } 91 | }); 92 | 93 | metadata.handlers.forEach((patterns, methodName) => { 94 | if(this.instance[methodName] !== undefined && typeof this.instance[methodName] === 'function') { 95 | this.handlers.add(new Handler(Utils.patternsToRegex(patterns), this.instance[methodName])); 96 | } 97 | }); 98 | } 99 | } 100 | 101 | export class DispatcherProxy { 102 | 103 | constructor(instancePromise) { 104 | this.inititalize = Promise.resolve(instancePromise).then((instance) => { 105 | this.instance = instance; 106 | }); 107 | } 108 | 109 | 110 | handle(patterns, handler) { 111 | var def = Promise.defer(); 112 | 113 | this.inititalize.then(() => { 114 | def.resolve(this.instance[Symbols.instanceDispatcher].handle(patterns, handler)); 115 | }); 116 | 117 | return function() { 118 | def.promise.then((unregister) => unregister()); 119 | } 120 | } 121 | 122 | waitFor(types, handler) { 123 | this.inititalize.then(() => { 124 | this.instance[Symbols.instanceDispatcher].waitFor(types, handler); 125 | }); 126 | } 127 | 128 | dispatch(action, ...payload) { 129 | this.inititalize.then(() => { 130 | this.instance[Symbols.instanceDispatcher].dispatch 131 | .apply(this.instance[Symbols.instanceDispatcher],[action].concat(payload)); 132 | }); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /dist/es6/lifecycle-manager.js: -------------------------------------------------------------------------------- 1 | import {ClassActivator} from 'aurelia-dependency-injection'; 2 | import {HtmlBehaviorResource} from 'aurelia-templating'; 3 | import {Dispatcher, DispatcherProxy} from './instance-dispatcher'; 4 | import {FluxDispatcher} from './flux-dispatcher'; 5 | import {Metadata} from './metadata'; 6 | import {Symbols} from './symbols'; 7 | import Promise from 'bluebird'; 8 | import {activationStrategy} from 'aurelia-router'; 9 | 10 | export class LifecycleManager { 11 | 12 | static interceptInstanceDeactivators(instance) { 13 | if(instance[Symbols.deactivators] === true) { 14 | return; 15 | } 16 | 17 | LifecycleManager.interceptInstanceDeactivate(instance); 18 | LifecycleManager.interceptInstanceDetached(instance); 19 | 20 | instance[Symbols.deactivators] = true; 21 | } 22 | 23 | static interceptInstanceDeactivate(instance) { 24 | 25 | function _unregister() { 26 | if(FluxDispatcher.instance.strategy !== activationStrategy.invokeLifecycle) { 27 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 28 | } 29 | } 30 | 31 | if(instance.deactivate !== undefined) { 32 | var deactivateImpl = instance.deactivate; 33 | instance.deactivate = function(...args) { 34 | _unregister(); 35 | deactivateImpl.apply(instance, args); 36 | }; 37 | } else { 38 | instance.deactivate = function() { 39 | _unregister(); 40 | }; 41 | } 42 | } 43 | 44 | static interceptInstanceDetached(instance) { 45 | if(instance.detached !== undefined) { 46 | var deactivateImpl = instance.detached; 47 | instance.detached = function(...args) { 48 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 49 | deactivateImpl.apply(instance, args); 50 | }; 51 | } else { 52 | instance.detached = function() { 53 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 54 | }; 55 | } 56 | } 57 | 58 | static interceptHtmlBehaviorResource() { 59 | if(HtmlBehaviorResource === undefined || typeof HtmlBehaviorResource.prototype.analyze !== 'function') { 60 | throw new Error('Unsupported version of HtmlBehaviorResource'); 61 | } 62 | 63 | var analyzeImpl = HtmlBehaviorResource.prototype.analyze; 64 | 65 | HtmlBehaviorResource.prototype.analyze = function(...args) { 66 | let target = args[1]; 67 | if( target 68 | && target.prototype 69 | && target.prototype[Symbols.metadata] 70 | && target.prototype[Symbols.metadata].handlers 71 | && target.prototype[Symbols.metadata].handlers.size) { 72 | if(target.prototype.detached === undefined) { 73 | target.prototype.detached = function() {}; 74 | } 75 | } 76 | return analyzeImpl.apply(this, args); 77 | }; 78 | } 79 | 80 | static interceptClassActivator() { 81 | if(ClassActivator.instance === undefined || ClassActivator.instance.invoke === undefined) { 82 | throw new Error('Unsupported version of ClassActivator'); 83 | } 84 | 85 | var invokeImpl = ClassActivator.instance.invoke; 86 | ClassActivator.instance.invoke = function(...invokeArgs) { 87 | var args = invokeArgs[1], 88 | instance; 89 | 90 | if(Array.isArray(args) === false) { 91 | throw new Error('Unsupported version of ClassActivator'); 92 | } 93 | 94 | var dispatcher = args.find((item) => { return item instanceof Dispatcher; }); 95 | 96 | if(dispatcher) { 97 | var instancePromise = Promise.defer(); 98 | args[args.indexOf(dispatcher)] = new DispatcherProxy(instancePromise.promise); 99 | instance = invokeImpl.apply(this, invokeArgs); 100 | instance[Symbols.instanceDispatcher] = new Dispatcher(instance); 101 | instancePromise.resolve(instance); 102 | } else { 103 | instance = invokeImpl.apply(this, invokeArgs); 104 | } 105 | 106 | if(Metadata.exists(Object.getPrototypeOf(instance))) { 107 | if(instance[Symbols.instanceDispatcher] === undefined) { 108 | instance[Symbols.instanceDispatcher] = new Dispatcher(instance); 109 | } 110 | instance[Symbols.instanceDispatcher].registerMetadata(); 111 | } 112 | 113 | if(instance[Symbols.instanceDispatcher] !== undefined) { 114 | LifecycleManager.interceptInstanceDeactivators(instance); 115 | } 116 | 117 | return instance; 118 | }; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/lifecycle-manager.js: -------------------------------------------------------------------------------- 1 | import {ClassActivator} from 'aurelia-dependency-injection'; 2 | import {HtmlBehaviorResource} from 'aurelia-templating'; 3 | import {Dispatcher, DispatcherProxy} from './instance-dispatcher'; 4 | import {FluxDispatcher} from './flux-dispatcher'; 5 | import {Metadata} from './metadata'; 6 | import {Symbols} from './symbols'; 7 | import Promise from 'bluebird'; 8 | import {activationStrategy} from 'aurelia-router'; 9 | 10 | export class LifecycleManager { 11 | 12 | static interceptInstanceDeactivators(instance) { 13 | if(instance[Symbols.deactivators] === true) { 14 | return; 15 | } 16 | 17 | LifecycleManager.interceptInstanceDeactivate(instance); 18 | LifecycleManager.interceptInstanceDetached(instance); 19 | 20 | instance[Symbols.deactivators] = true; 21 | } 22 | 23 | static interceptInstanceDeactivate(instance) { 24 | 25 | function _unregister() { 26 | if(FluxDispatcher.instance.strategy !== activationStrategy.invokeLifecycle) { 27 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 28 | } 29 | } 30 | 31 | if(instance.deactivate !== undefined) { 32 | var deactivateImpl = instance.deactivate; 33 | instance.deactivate = function(...args) { 34 | _unregister(); 35 | deactivateImpl.apply(instance, args); 36 | }; 37 | } else { 38 | instance.deactivate = function() { 39 | _unregister(); 40 | }; 41 | } 42 | } 43 | 44 | static interceptInstanceDetached(instance) { 45 | if(instance.detached !== undefined) { 46 | var deactivateImpl = instance.detached; 47 | instance.detached = function(...args) { 48 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 49 | deactivateImpl.apply(instance, args); 50 | }; 51 | } else { 52 | instance.detached = function() { 53 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 54 | }; 55 | } 56 | } 57 | 58 | static interceptHtmlBehaviorResource() { 59 | if(HtmlBehaviorResource === undefined || typeof HtmlBehaviorResource.prototype.analyze !== 'function') { 60 | throw new Error('Unsupported version of HtmlBehaviorResource'); 61 | } 62 | 63 | var analyzeImpl = HtmlBehaviorResource.prototype.analyze; 64 | 65 | HtmlBehaviorResource.prototype.analyze = function(...args) { 66 | let target = args[1]; 67 | if( target 68 | && target.prototype 69 | && target.prototype[Symbols.metadata] 70 | && target.prototype[Symbols.metadata].handlers 71 | && target.prototype[Symbols.metadata].handlers.size) { 72 | if(target.prototype.detached === undefined) { 73 | target.prototype.detached = function() {}; 74 | } 75 | } 76 | return analyzeImpl.apply(this, args); 77 | }; 78 | } 79 | 80 | static interceptClassActivator() { 81 | if(ClassActivator.instance === undefined || ClassActivator.instance.invoke === undefined) { 82 | throw new Error('Unsupported version of ClassActivator'); 83 | } 84 | 85 | var invokeImpl = ClassActivator.instance.invoke; 86 | ClassActivator.instance.invoke = function(...invokeArgs) { 87 | var args = invokeArgs[1], 88 | instance; 89 | 90 | if(Array.isArray(args) === false) { 91 | throw new Error('Unsupported version of ClassActivator'); 92 | } 93 | 94 | var dispatcher = args.find((item) => { return item instanceof Dispatcher; }); 95 | 96 | if(dispatcher) { 97 | var instancePromise = Promise.defer(); 98 | args[args.indexOf(dispatcher)] = new DispatcherProxy(instancePromise.promise); 99 | instance = invokeImpl.apply(this, invokeArgs); 100 | instance[Symbols.instanceDispatcher] = new Dispatcher(instance); 101 | instancePromise.resolve(instance); 102 | } else { 103 | instance = invokeImpl.apply(this, invokeArgs); 104 | } 105 | 106 | if(Metadata.exists(Object.getPrototypeOf(instance))) { 107 | if(instance[Symbols.instanceDispatcher] === undefined) { 108 | instance[Symbols.instanceDispatcher] = new Dispatcher(instance); 109 | } 110 | instance[Symbols.instanceDispatcher].registerMetadata(); 111 | } 112 | 113 | if(instance[Symbols.instanceDispatcher] !== undefined) { 114 | LifecycleManager.interceptInstanceDeactivators(instance); 115 | } 116 | 117 | return instance; 118 | }; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /dist/commonjs/instance-dispatcher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6 | 7 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8 | 9 | var _metadata = require('./metadata'); 10 | 11 | var _utils = require('./utils'); 12 | 13 | var _fluxDispatcher = require('./flux-dispatcher'); 14 | 15 | var _bluebird = require('bluebird'); 16 | 17 | var _bluebird2 = _interopRequireDefault(_bluebird); 18 | 19 | var _symbols = require('./symbols'); 20 | 21 | var Handler = function Handler(regexp, handler) { 22 | _classCallCheck(this, Handler); 23 | 24 | this.regexp = regexp; 25 | this['function'] = handler; 26 | }; 27 | 28 | var Dispatcher = (function () { 29 | function Dispatcher(instance) { 30 | _classCallCheck(this, Dispatcher); 31 | 32 | this.instance = instance; 33 | this.handlers = new Set(); 34 | 35 | _fluxDispatcher.FluxDispatcher.instance.registerInstanceDispatcher(this); 36 | } 37 | 38 | Dispatcher.prototype.handle = function handle(patterns, callback) { 39 | var _this = this; 40 | 41 | var handler = new Handler(_utils.Utils.patternsToRegex(patterns), callback); 42 | this.handlers.add(handler); 43 | 44 | return function () { 45 | _this.handlers['delete'](handler); 46 | }; 47 | }; 48 | 49 | Dispatcher.prototype.waitFor = function waitFor(types, handler) { 50 | _fluxDispatcher.FluxDispatcher.instance.waitFor(types, handler); 51 | }; 52 | 53 | Dispatcher.prototype.dispatch = function dispatch(action) { 54 | for (var _len = arguments.length, payload = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 55 | payload[_key - 1] = arguments[_key]; 56 | } 57 | 58 | _fluxDispatcher.FluxDispatcher.instance.dispatch(action, payload); 59 | }; 60 | 61 | Dispatcher.prototype.dispatchOwn = function dispatchOwn(action, payload) { 62 | var _this2 = this; 63 | 64 | var promises = []; 65 | 66 | this.handlers.forEach(function (handler) { 67 | if (handler.regexp.test(action)) { 68 | promises.push(_bluebird2['default'].resolve(handler['function'].apply(_this2.instance, [action].concat(payload)))); 69 | } 70 | }); 71 | 72 | return _bluebird2['default'].settle(promises); 73 | }; 74 | 75 | Dispatcher.prototype.registerMetadata = function registerMetadata() { 76 | var _this3 = this; 77 | 78 | var metadata = _metadata.Metadata.getOrCreateMetadata(Object.getPrototypeOf(this.instance)); 79 | 80 | metadata.awaiters.forEach(function (types, methodName) { 81 | if (_this3.instance[methodName] !== undefined && typeof _this3.instance[methodName] === 'function') { 82 | var methodImpl = _this3.instance[methodName]; 83 | _this3.instance[methodName] = function () { 84 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 85 | args[_key2] = arguments[_key2]; 86 | } 87 | 88 | return _fluxDispatcher.FluxDispatcher.instance.waitFor(types, function () { 89 | methodImpl.apply(_this3.instance, args); 90 | }); 91 | }; 92 | } 93 | }); 94 | 95 | metadata.handlers.forEach(function (patterns, methodName) { 96 | if (_this3.instance[methodName] !== undefined && typeof _this3.instance[methodName] === 'function') { 97 | _this3.handlers.add(new Handler(_utils.Utils.patternsToRegex(patterns), _this3.instance[methodName])); 98 | } 99 | }); 100 | }; 101 | 102 | return Dispatcher; 103 | })(); 104 | 105 | exports.Dispatcher = Dispatcher; 106 | 107 | var DispatcherProxy = (function () { 108 | function DispatcherProxy(instancePromise) { 109 | var _this4 = this; 110 | 111 | _classCallCheck(this, DispatcherProxy); 112 | 113 | this.inititalize = _bluebird2['default'].resolve(instancePromise).then(function (instance) { 114 | _this4.instance = instance; 115 | }); 116 | } 117 | 118 | DispatcherProxy.prototype.handle = function handle(patterns, handler) { 119 | var _this5 = this; 120 | 121 | var def = _bluebird2['default'].defer(); 122 | 123 | this.inititalize.then(function () { 124 | def.resolve(_this5.instance[_symbols.Symbols.instanceDispatcher].handle(patterns, handler)); 125 | }); 126 | 127 | return function () { 128 | def.promise.then(function (unregister) { 129 | return unregister(); 130 | }); 131 | }; 132 | }; 133 | 134 | DispatcherProxy.prototype.waitFor = function waitFor(types, handler) { 135 | var _this6 = this; 136 | 137 | this.inititalize.then(function () { 138 | _this6.instance[_symbols.Symbols.instanceDispatcher].waitFor(types, handler); 139 | }); 140 | }; 141 | 142 | DispatcherProxy.prototype.dispatch = function dispatch(action) { 143 | var _this7 = this; 144 | 145 | for (var _len3 = arguments.length, payload = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { 146 | payload[_key3 - 1] = arguments[_key3]; 147 | } 148 | 149 | this.inititalize.then(function () { 150 | _this7.instance[_symbols.Symbols.instanceDispatcher].dispatch.apply(_this7.instance[_symbols.Symbols.instanceDispatcher], [action].concat(payload)); 151 | }); 152 | }; 153 | 154 | return DispatcherProxy; 155 | })(); 156 | 157 | exports.DispatcherProxy = DispatcherProxy; -------------------------------------------------------------------------------- /dist/amd/instance-dispatcher.js: -------------------------------------------------------------------------------- 1 | define(['exports', './metadata', './utils', './flux-dispatcher', 'bluebird', './symbols'], function (exports, _metadata, _utils, _fluxDispatcher, _bluebird, _symbols) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7 | 8 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9 | 10 | var _Promise = _interopRequireDefault(_bluebird); 11 | 12 | var Handler = function Handler(regexp, handler) { 13 | _classCallCheck(this, Handler); 14 | 15 | this.regexp = regexp; 16 | this['function'] = handler; 17 | }; 18 | 19 | var Dispatcher = (function () { 20 | function Dispatcher(instance) { 21 | _classCallCheck(this, Dispatcher); 22 | 23 | this.instance = instance; 24 | this.handlers = new Set(); 25 | 26 | _fluxDispatcher.FluxDispatcher.instance.registerInstanceDispatcher(this); 27 | } 28 | 29 | Dispatcher.prototype.handle = function handle(patterns, callback) { 30 | var _this = this; 31 | 32 | var handler = new Handler(_utils.Utils.patternsToRegex(patterns), callback); 33 | this.handlers.add(handler); 34 | 35 | return function () { 36 | _this.handlers['delete'](handler); 37 | }; 38 | }; 39 | 40 | Dispatcher.prototype.waitFor = function waitFor(types, handler) { 41 | _fluxDispatcher.FluxDispatcher.instance.waitFor(types, handler); 42 | }; 43 | 44 | Dispatcher.prototype.dispatch = function dispatch(action) { 45 | for (var _len = arguments.length, payload = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 46 | payload[_key - 1] = arguments[_key]; 47 | } 48 | 49 | _fluxDispatcher.FluxDispatcher.instance.dispatch(action, payload); 50 | }; 51 | 52 | Dispatcher.prototype.dispatchOwn = function dispatchOwn(action, payload) { 53 | var _this2 = this; 54 | 55 | var promises = []; 56 | 57 | this.handlers.forEach(function (handler) { 58 | if (handler.regexp.test(action)) { 59 | promises.push(_Promise['default'].resolve(handler['function'].apply(_this2.instance, [action].concat(payload)))); 60 | } 61 | }); 62 | 63 | return _Promise['default'].settle(promises); 64 | }; 65 | 66 | Dispatcher.prototype.registerMetadata = function registerMetadata() { 67 | var _this3 = this; 68 | 69 | var metadata = _metadata.Metadata.getOrCreateMetadata(Object.getPrototypeOf(this.instance)); 70 | 71 | metadata.awaiters.forEach(function (types, methodName) { 72 | if (_this3.instance[methodName] !== undefined && typeof _this3.instance[methodName] === 'function') { 73 | var methodImpl = _this3.instance[methodName]; 74 | _this3.instance[methodName] = function () { 75 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 76 | args[_key2] = arguments[_key2]; 77 | } 78 | 79 | return _fluxDispatcher.FluxDispatcher.instance.waitFor(types, function () { 80 | methodImpl.apply(_this3.instance, args); 81 | }); 82 | }; 83 | } 84 | }); 85 | 86 | metadata.handlers.forEach(function (patterns, methodName) { 87 | if (_this3.instance[methodName] !== undefined && typeof _this3.instance[methodName] === 'function') { 88 | _this3.handlers.add(new Handler(_utils.Utils.patternsToRegex(patterns), _this3.instance[methodName])); 89 | } 90 | }); 91 | }; 92 | 93 | return Dispatcher; 94 | })(); 95 | 96 | exports.Dispatcher = Dispatcher; 97 | 98 | var DispatcherProxy = (function () { 99 | function DispatcherProxy(instancePromise) { 100 | var _this4 = this; 101 | 102 | _classCallCheck(this, DispatcherProxy); 103 | 104 | this.inititalize = _Promise['default'].resolve(instancePromise).then(function (instance) { 105 | _this4.instance = instance; 106 | }); 107 | } 108 | 109 | DispatcherProxy.prototype.handle = function handle(patterns, handler) { 110 | var _this5 = this; 111 | 112 | var def = _Promise['default'].defer(); 113 | 114 | this.inititalize.then(function () { 115 | def.resolve(_this5.instance[_symbols.Symbols.instanceDispatcher].handle(patterns, handler)); 116 | }); 117 | 118 | return function () { 119 | def.promise.then(function (unregister) { 120 | return unregister(); 121 | }); 122 | }; 123 | }; 124 | 125 | DispatcherProxy.prototype.waitFor = function waitFor(types, handler) { 126 | var _this6 = this; 127 | 128 | this.inititalize.then(function () { 129 | _this6.instance[_symbols.Symbols.instanceDispatcher].waitFor(types, handler); 130 | }); 131 | }; 132 | 133 | DispatcherProxy.prototype.dispatch = function dispatch(action) { 134 | var _this7 = this; 135 | 136 | for (var _len3 = arguments.length, payload = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { 137 | payload[_key3 - 1] = arguments[_key3]; 138 | } 139 | 140 | this.inititalize.then(function () { 141 | _this7.instance[_symbols.Symbols.instanceDispatcher].dispatch.apply(_this7.instance[_symbols.Symbols.instanceDispatcher], [action].concat(payload)); 142 | }); 143 | }; 144 | 145 | return DispatcherProxy; 146 | })(); 147 | 148 | exports.DispatcherProxy = DispatcherProxy; 149 | }); -------------------------------------------------------------------------------- /dist/commonjs/flux-dispatcher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 6 | 7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8 | 9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 10 | 11 | var _bluebird = require('bluebird'); 12 | 13 | var _bluebird2 = _interopRequireDefault(_bluebird); 14 | 15 | var _instanceDispatcher = require('./instance-dispatcher'); 16 | 17 | var FluxDispatcher = (function () { 18 | _createClass(FluxDispatcher, null, [{ 19 | key: 'instance', 20 | value: new FluxDispatcher(), 21 | enumerable: true 22 | }]); 23 | 24 | function FluxDispatcher() { 25 | _classCallCheck(this, FluxDispatcher); 26 | 27 | this.instanceDispatchers = new Map(); 28 | this.isDispatching = false; 29 | this.queue = []; 30 | this.typesPromises = new Map(); 31 | } 32 | 33 | FluxDispatcher.prototype.getOrCreateTypeDispatchers = function getOrCreateTypeDispatchers(type) { 34 | if (this.instanceDispatchers.has(type) === false) { 35 | this.instanceDispatchers.set(type, new Set()); 36 | } 37 | 38 | return this.instanceDispatchers.get(type); 39 | }; 40 | 41 | FluxDispatcher.prototype.getOrCreateTypePromises = function getOrCreateTypePromises(type) { 42 | if (this.typesPromises.has(type) === false) { 43 | this.typesPromises.set(type, _bluebird2['default'].defer()); 44 | } 45 | 46 | return this.typesPromises.get(type); 47 | }; 48 | 49 | FluxDispatcher.prototype.registerInstanceDispatcher = function registerInstanceDispatcher(dispatcher) { 50 | if (dispatcher === undefined || dispatcher.instance === undefined) { 51 | return; 52 | } 53 | 54 | var typeDispatchers = this.getOrCreateTypeDispatchers(Object.getPrototypeOf(dispatcher.instance)); 55 | 56 | typeDispatchers.add(dispatcher); 57 | }; 58 | 59 | FluxDispatcher.prototype.unregisterInstanceDispatcher = function unregisterInstanceDispatcher(dispatcher) { 60 | if (dispatcher === undefined || dispatcher.instance === undefined) { 61 | return; 62 | } 63 | 64 | var type = Object.getPrototypeOf(dispatcher.instance); 65 | 66 | if (this.instanceDispatchers.has(type) === false) { 67 | return; 68 | } 69 | 70 | this.instanceDispatchers.get(type)['delete'](dispatcher); 71 | 72 | if (this.instanceDispatchers.get(type).size === 0) { 73 | this.instanceDispatchers['delete'](type); 74 | } 75 | }; 76 | 77 | FluxDispatcher.prototype.dispatch = function dispatch(action, payload) { 78 | this.$dispatch(action, payload, false); 79 | }; 80 | 81 | FluxDispatcher.prototype.$dispatch = function $dispatch(action, payload, fromQueue) { 82 | var _this = this; 83 | 84 | if (this.isDispatching && fromQueue === false) { 85 | this.queue.push([action, payload]); 86 | return; 87 | } 88 | 89 | this.isDispatching = true; 90 | 91 | this.typesPromises = new Map(); 92 | 93 | this.instanceDispatchers.forEach(function (dispatchers, type) { 94 | var typePromise = _this.getOrCreateTypePromises(type); 95 | var promises = []; 96 | 97 | dispatchers.forEach(function (dispatcher) { 98 | promises.push(dispatcher.dispatchOwn.apply(dispatcher, [action, payload])); 99 | }); 100 | 101 | _bluebird2['default'].settle(promises).then(function () { 102 | typePromise.resolve(); 103 | }); 104 | }); 105 | 106 | this.typesPromises.forEach(function (promise, type) { 107 | if (_this.instanceDispatchers.has(type) === false) { 108 | 109 | var _name = type !== undefined && type.constructor !== undefined && type.constructor.name !== undefined ? type.constructor.name : type.toString(); 110 | console.warn('You are waiting for a type \'' + _name + '\' that didn\'t handle event \'' + action + '\'. ' + _name + ' promise has been resolved automatically.'); 111 | 112 | promise.resolve(); 113 | } 114 | }); 115 | 116 | var allTypesPromises = Array.from(this.typesPromises.values()).map(function (defer) { 117 | return defer.promise; 118 | }); 119 | 120 | _bluebird2['default'].settle(allTypesPromises).then(function () { 121 | var next = _this.queue.shift(); 122 | setTimeout(function () { 123 | if (next !== undefined) { 124 | _this.$dispatch(next[0], next[1], true); 125 | } else { 126 | _this.isDispatching = false; 127 | } 128 | }, 0); 129 | }); 130 | }; 131 | 132 | FluxDispatcher.prototype.waitFor = function waitFor(types, handler) { 133 | var _this2 = this; 134 | 135 | if (Array.isArray(types) === false) { 136 | types = [types]; 137 | } 138 | 139 | var typesPromises = types.map(function (type) { 140 | return _this2.getOrCreateTypePromises(type.prototype).promise; 141 | }); 142 | 143 | var def = _bluebird2['default'].defer(); 144 | 145 | _bluebird2['default'].settle(typesPromises).then(function () { 146 | _bluebird2['default'].resolve(handler()).then(function (ret) { 147 | def.resolve(ret); 148 | })['catch'](function (err) { 149 | def.reject(err); 150 | }); 151 | }); 152 | 153 | return def.promise; 154 | }; 155 | 156 | return FluxDispatcher; 157 | })(); 158 | 159 | exports.FluxDispatcher = FluxDispatcher; -------------------------------------------------------------------------------- /dist/amd/flux-dispatcher.js: -------------------------------------------------------------------------------- 1 | define(['exports', 'bluebird', './instance-dispatcher'], function (exports, _bluebird, _instanceDispatcher) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 7 | 8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 9 | 10 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 11 | 12 | var _Promise = _interopRequireDefault(_bluebird); 13 | 14 | var FluxDispatcher = (function () { 15 | _createClass(FluxDispatcher, null, [{ 16 | key: 'instance', 17 | value: new FluxDispatcher(), 18 | enumerable: true 19 | }]); 20 | 21 | function FluxDispatcher() { 22 | _classCallCheck(this, FluxDispatcher); 23 | 24 | this.instanceDispatchers = new Map(); 25 | this.isDispatching = false; 26 | this.queue = []; 27 | this.typesPromises = new Map(); 28 | } 29 | 30 | FluxDispatcher.prototype.getOrCreateTypeDispatchers = function getOrCreateTypeDispatchers(type) { 31 | if (this.instanceDispatchers.has(type) === false) { 32 | this.instanceDispatchers.set(type, new Set()); 33 | } 34 | 35 | return this.instanceDispatchers.get(type); 36 | }; 37 | 38 | FluxDispatcher.prototype.getOrCreateTypePromises = function getOrCreateTypePromises(type) { 39 | if (this.typesPromises.has(type) === false) { 40 | this.typesPromises.set(type, _Promise['default'].defer()); 41 | } 42 | 43 | return this.typesPromises.get(type); 44 | }; 45 | 46 | FluxDispatcher.prototype.registerInstanceDispatcher = function registerInstanceDispatcher(dispatcher) { 47 | if (dispatcher === undefined || dispatcher.instance === undefined) { 48 | return; 49 | } 50 | 51 | var typeDispatchers = this.getOrCreateTypeDispatchers(Object.getPrototypeOf(dispatcher.instance)); 52 | 53 | typeDispatchers.add(dispatcher); 54 | }; 55 | 56 | FluxDispatcher.prototype.unregisterInstanceDispatcher = function unregisterInstanceDispatcher(dispatcher) { 57 | if (dispatcher === undefined || dispatcher.instance === undefined) { 58 | return; 59 | } 60 | 61 | var type = Object.getPrototypeOf(dispatcher.instance); 62 | 63 | if (this.instanceDispatchers.has(type) === false) { 64 | return; 65 | } 66 | 67 | this.instanceDispatchers.get(type)['delete'](dispatcher); 68 | 69 | if (this.instanceDispatchers.get(type).size === 0) { 70 | this.instanceDispatchers['delete'](type); 71 | } 72 | }; 73 | 74 | FluxDispatcher.prototype.dispatch = function dispatch(action, payload) { 75 | this.$dispatch(action, payload, false); 76 | }; 77 | 78 | FluxDispatcher.prototype.$dispatch = function $dispatch(action, payload, fromQueue) { 79 | var _this = this; 80 | 81 | if (this.isDispatching && fromQueue === false) { 82 | this.queue.push([action, payload]); 83 | return; 84 | } 85 | 86 | this.isDispatching = true; 87 | 88 | this.typesPromises = new Map(); 89 | 90 | this.instanceDispatchers.forEach(function (dispatchers, type) { 91 | var typePromise = _this.getOrCreateTypePromises(type); 92 | var promises = []; 93 | 94 | dispatchers.forEach(function (dispatcher) { 95 | promises.push(dispatcher.dispatchOwn.apply(dispatcher, [action, payload])); 96 | }); 97 | 98 | _Promise['default'].settle(promises).then(function () { 99 | typePromise.resolve(); 100 | }); 101 | }); 102 | 103 | this.typesPromises.forEach(function (promise, type) { 104 | if (_this.instanceDispatchers.has(type) === false) { 105 | 106 | var _name = type !== undefined && type.constructor !== undefined && type.constructor.name !== undefined ? type.constructor.name : type.toString(); 107 | console.warn('You are waiting for a type \'' + _name + '\' that didn\'t handle event \'' + action + '\'. ' + _name + ' promise has been resolved automatically.'); 108 | 109 | promise.resolve(); 110 | } 111 | }); 112 | 113 | var allTypesPromises = Array.from(this.typesPromises.values()).map(function (defer) { 114 | return defer.promise; 115 | }); 116 | 117 | _Promise['default'].settle(allTypesPromises).then(function () { 118 | var next = _this.queue.shift(); 119 | setTimeout(function () { 120 | if (next !== undefined) { 121 | _this.$dispatch(next[0], next[1], true); 122 | } else { 123 | _this.isDispatching = false; 124 | } 125 | }, 0); 126 | }); 127 | }; 128 | 129 | FluxDispatcher.prototype.waitFor = function waitFor(types, handler) { 130 | var _this2 = this; 131 | 132 | if (Array.isArray(types) === false) { 133 | types = [types]; 134 | } 135 | 136 | var typesPromises = types.map(function (type) { 137 | return _this2.getOrCreateTypePromises(type.prototype).promise; 138 | }); 139 | 140 | var def = _Promise['default'].defer(); 141 | 142 | _Promise['default'].settle(typesPromises).then(function () { 143 | _Promise['default'].resolve(handler()).then(function (ret) { 144 | def.resolve(ret); 145 | })['catch'](function (err) { 146 | def.reject(err); 147 | }); 148 | }); 149 | 150 | return def.promise; 151 | }; 152 | 153 | return FluxDispatcher; 154 | })(); 155 | 156 | exports.FluxDispatcher = FluxDispatcher; 157 | }); -------------------------------------------------------------------------------- /dist/commonjs/lifecycle-manager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.__esModule = true; 4 | 5 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6 | 7 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8 | 9 | var _aureliaDependencyInjection = require('aurelia-dependency-injection'); 10 | 11 | var _aureliaTemplating = require('aurelia-templating'); 12 | 13 | var _instanceDispatcher = require('./instance-dispatcher'); 14 | 15 | var _fluxDispatcher = require('./flux-dispatcher'); 16 | 17 | var _metadata = require('./metadata'); 18 | 19 | var _symbols = require('./symbols'); 20 | 21 | var _bluebird = require('bluebird'); 22 | 23 | var _bluebird2 = _interopRequireDefault(_bluebird); 24 | 25 | var _aureliaRouter = require('aurelia-router'); 26 | 27 | var LifecycleManager = (function () { 28 | function LifecycleManager() { 29 | _classCallCheck(this, LifecycleManager); 30 | } 31 | 32 | LifecycleManager.interceptInstanceDeactivators = function interceptInstanceDeactivators(instance) { 33 | if (instance[_symbols.Symbols.deactivators] === true) { 34 | return; 35 | } 36 | 37 | LifecycleManager.interceptInstanceDeactivate(instance); 38 | LifecycleManager.interceptInstanceDetached(instance); 39 | 40 | instance[_symbols.Symbols.deactivators] = true; 41 | }; 42 | 43 | LifecycleManager.interceptInstanceDeactivate = function interceptInstanceDeactivate(instance) { 44 | 45 | function _unregister() { 46 | if (_fluxDispatcher.FluxDispatcher.instance.strategy !== _aureliaRouter.activationStrategy.invokeLifecycle) { 47 | _fluxDispatcher.FluxDispatcher.instance.unregisterInstanceDispatcher(instance[_symbols.Symbols.instanceDispatcher]); 48 | } 49 | } 50 | 51 | if (instance.deactivate !== undefined) { 52 | var deactivateImpl = instance.deactivate; 53 | instance.deactivate = function () { 54 | _unregister(); 55 | 56 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 57 | args[_key] = arguments[_key]; 58 | } 59 | 60 | deactivateImpl.apply(instance, args); 61 | }; 62 | } else { 63 | instance.deactivate = function () { 64 | _unregister(); 65 | }; 66 | } 67 | }; 68 | 69 | LifecycleManager.interceptInstanceDetached = function interceptInstanceDetached(instance) { 70 | if (instance.detached !== undefined) { 71 | var deactivateImpl = instance.detached; 72 | instance.detached = function () { 73 | _fluxDispatcher.FluxDispatcher.instance.unregisterInstanceDispatcher(instance[_symbols.Symbols.instanceDispatcher]); 74 | 75 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 76 | args[_key2] = arguments[_key2]; 77 | } 78 | 79 | deactivateImpl.apply(instance, args); 80 | }; 81 | } else { 82 | instance.detached = function () { 83 | _fluxDispatcher.FluxDispatcher.instance.unregisterInstanceDispatcher(instance[_symbols.Symbols.instanceDispatcher]); 84 | }; 85 | } 86 | }; 87 | 88 | LifecycleManager.interceptHtmlBehaviorResource = function interceptHtmlBehaviorResource() { 89 | if (_aureliaTemplating.HtmlBehaviorResource === undefined || typeof _aureliaTemplating.HtmlBehaviorResource.prototype.analyze !== 'function') { 90 | throw new Error('Unsupported version of HtmlBehaviorResource'); 91 | } 92 | 93 | var analyzeImpl = _aureliaTemplating.HtmlBehaviorResource.prototype.analyze; 94 | 95 | _aureliaTemplating.HtmlBehaviorResource.prototype.analyze = function () { 96 | for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 97 | args[_key3] = arguments[_key3]; 98 | } 99 | 100 | var target = args[1]; 101 | if (target && target.prototype && target.prototype[_symbols.Symbols.metadata] && target.prototype[_symbols.Symbols.metadata].handlers && target.prototype[_symbols.Symbols.metadata].handlers.size) { 102 | if (target.prototype.detached === undefined) { 103 | target.prototype.detached = function () {}; 104 | } 105 | } 106 | return analyzeImpl.apply(this, args); 107 | }; 108 | }; 109 | 110 | LifecycleManager.interceptClassActivator = function interceptClassActivator() { 111 | if (_aureliaDependencyInjection.ClassActivator.instance === undefined || _aureliaDependencyInjection.ClassActivator.instance.invoke === undefined) { 112 | throw new Error('Unsupported version of ClassActivator'); 113 | } 114 | 115 | var invokeImpl = _aureliaDependencyInjection.ClassActivator.instance.invoke; 116 | _aureliaDependencyInjection.ClassActivator.instance.invoke = function () { 117 | for (var _len4 = arguments.length, invokeArgs = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { 118 | invokeArgs[_key4] = arguments[_key4]; 119 | } 120 | 121 | var args = invokeArgs[1], 122 | instance; 123 | 124 | if (Array.isArray(args) === false) { 125 | throw new Error('Unsupported version of ClassActivator'); 126 | } 127 | 128 | var dispatcher = args.find(function (item) { 129 | return item instanceof _instanceDispatcher.Dispatcher; 130 | }); 131 | 132 | if (dispatcher) { 133 | var instancePromise = _bluebird2['default'].defer(); 134 | args[args.indexOf(dispatcher)] = new _instanceDispatcher.DispatcherProxy(instancePromise.promise); 135 | instance = invokeImpl.apply(this, invokeArgs); 136 | instance[_symbols.Symbols.instanceDispatcher] = new _instanceDispatcher.Dispatcher(instance); 137 | instancePromise.resolve(instance); 138 | } else { 139 | instance = invokeImpl.apply(this, invokeArgs); 140 | } 141 | 142 | if (_metadata.Metadata.exists(Object.getPrototypeOf(instance))) { 143 | if (instance[_symbols.Symbols.instanceDispatcher] === undefined) { 144 | instance[_symbols.Symbols.instanceDispatcher] = new _instanceDispatcher.Dispatcher(instance); 145 | } 146 | instance[_symbols.Symbols.instanceDispatcher].registerMetadata(); 147 | } 148 | 149 | if (instance[_symbols.Symbols.instanceDispatcher] !== undefined) { 150 | LifecycleManager.interceptInstanceDeactivators(instance); 151 | } 152 | 153 | return instance; 154 | }; 155 | }; 156 | 157 | return LifecycleManager; 158 | })(); 159 | 160 | exports.LifecycleManager = LifecycleManager; -------------------------------------------------------------------------------- /dist/system/instance-dispatcher.js: -------------------------------------------------------------------------------- 1 | System.register(['./metadata', './utils', './flux-dispatcher', 'bluebird', './symbols'], function (_export) { 2 | 'use strict'; 3 | 4 | var Metadata, Utils, FluxDispatcher, Promise, Symbols, Handler, Dispatcher, DispatcherProxy; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | return { 9 | setters: [function (_metadata) { 10 | Metadata = _metadata.Metadata; 11 | }, function (_utils) { 12 | Utils = _utils.Utils; 13 | }, function (_fluxDispatcher) { 14 | FluxDispatcher = _fluxDispatcher.FluxDispatcher; 15 | }, function (_bluebird) { 16 | Promise = _bluebird['default']; 17 | }, function (_symbols) { 18 | Symbols = _symbols.Symbols; 19 | }], 20 | execute: function () { 21 | Handler = function Handler(regexp, handler) { 22 | _classCallCheck(this, Handler); 23 | 24 | this.regexp = regexp; 25 | this['function'] = handler; 26 | }; 27 | 28 | Dispatcher = (function () { 29 | function Dispatcher(instance) { 30 | _classCallCheck(this, Dispatcher); 31 | 32 | this.instance = instance; 33 | this.handlers = new Set(); 34 | 35 | FluxDispatcher.instance.registerInstanceDispatcher(this); 36 | } 37 | 38 | Dispatcher.prototype.handle = function handle(patterns, callback) { 39 | var _this = this; 40 | 41 | var handler = new Handler(Utils.patternsToRegex(patterns), callback); 42 | this.handlers.add(handler); 43 | 44 | return function () { 45 | _this.handlers['delete'](handler); 46 | }; 47 | }; 48 | 49 | Dispatcher.prototype.waitFor = function waitFor(types, handler) { 50 | FluxDispatcher.instance.waitFor(types, handler); 51 | }; 52 | 53 | Dispatcher.prototype.dispatch = function dispatch(action) { 54 | for (var _len = arguments.length, payload = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 55 | payload[_key - 1] = arguments[_key]; 56 | } 57 | 58 | FluxDispatcher.instance.dispatch(action, payload); 59 | }; 60 | 61 | Dispatcher.prototype.dispatchOwn = function dispatchOwn(action, payload) { 62 | var _this2 = this; 63 | 64 | var promises = []; 65 | 66 | this.handlers.forEach(function (handler) { 67 | if (handler.regexp.test(action)) { 68 | promises.push(Promise.resolve(handler['function'].apply(_this2.instance, [action].concat(payload)))); 69 | } 70 | }); 71 | 72 | return Promise.settle(promises); 73 | }; 74 | 75 | Dispatcher.prototype.registerMetadata = function registerMetadata() { 76 | var _this3 = this; 77 | 78 | var metadata = Metadata.getOrCreateMetadata(Object.getPrototypeOf(this.instance)); 79 | 80 | metadata.awaiters.forEach(function (types, methodName) { 81 | if (_this3.instance[methodName] !== undefined && typeof _this3.instance[methodName] === 'function') { 82 | var methodImpl = _this3.instance[methodName]; 83 | _this3.instance[methodName] = function () { 84 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 85 | args[_key2] = arguments[_key2]; 86 | } 87 | 88 | return FluxDispatcher.instance.waitFor(types, function () { 89 | methodImpl.apply(_this3.instance, args); 90 | }); 91 | }; 92 | } 93 | }); 94 | 95 | metadata.handlers.forEach(function (patterns, methodName) { 96 | if (_this3.instance[methodName] !== undefined && typeof _this3.instance[methodName] === 'function') { 97 | _this3.handlers.add(new Handler(Utils.patternsToRegex(patterns), _this3.instance[methodName])); 98 | } 99 | }); 100 | }; 101 | 102 | return Dispatcher; 103 | })(); 104 | 105 | _export('Dispatcher', Dispatcher); 106 | 107 | DispatcherProxy = (function () { 108 | function DispatcherProxy(instancePromise) { 109 | var _this4 = this; 110 | 111 | _classCallCheck(this, DispatcherProxy); 112 | 113 | this.inititalize = Promise.resolve(instancePromise).then(function (instance) { 114 | _this4.instance = instance; 115 | }); 116 | } 117 | 118 | DispatcherProxy.prototype.handle = function handle(patterns, handler) { 119 | var _this5 = this; 120 | 121 | var def = Promise.defer(); 122 | 123 | this.inititalize.then(function () { 124 | def.resolve(_this5.instance[Symbols.instanceDispatcher].handle(patterns, handler)); 125 | }); 126 | 127 | return function () { 128 | def.promise.then(function (unregister) { 129 | return unregister(); 130 | }); 131 | }; 132 | }; 133 | 134 | DispatcherProxy.prototype.waitFor = function waitFor(types, handler) { 135 | var _this6 = this; 136 | 137 | this.inititalize.then(function () { 138 | _this6.instance[Symbols.instanceDispatcher].waitFor(types, handler); 139 | }); 140 | }; 141 | 142 | DispatcherProxy.prototype.dispatch = function dispatch(action) { 143 | var _this7 = this; 144 | 145 | for (var _len3 = arguments.length, payload = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { 146 | payload[_key3 - 1] = arguments[_key3]; 147 | } 148 | 149 | this.inititalize.then(function () { 150 | _this7.instance[Symbols.instanceDispatcher].dispatch.apply(_this7.instance[Symbols.instanceDispatcher], [action].concat(payload)); 151 | }); 152 | }; 153 | 154 | return DispatcherProxy; 155 | })(); 156 | 157 | _export('DispatcherProxy', DispatcherProxy); 158 | } 159 | }; 160 | }); -------------------------------------------------------------------------------- /dist/amd/lifecycle-manager.js: -------------------------------------------------------------------------------- 1 | define(['exports', 'aurelia-dependency-injection', 'aurelia-templating', './instance-dispatcher', './flux-dispatcher', './metadata', './symbols', 'bluebird', 'aurelia-router'], function (exports, _aureliaDependencyInjection, _aureliaTemplating, _instanceDispatcher, _fluxDispatcher, _metadata, _symbols, _bluebird, _aureliaRouter) { 2 | 'use strict'; 3 | 4 | exports.__esModule = true; 5 | 6 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7 | 8 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9 | 10 | var _Promise = _interopRequireDefault(_bluebird); 11 | 12 | var LifecycleManager = (function () { 13 | function LifecycleManager() { 14 | _classCallCheck(this, LifecycleManager); 15 | } 16 | 17 | LifecycleManager.interceptInstanceDeactivators = function interceptInstanceDeactivators(instance) { 18 | if (instance[_symbols.Symbols.deactivators] === true) { 19 | return; 20 | } 21 | 22 | LifecycleManager.interceptInstanceDeactivate(instance); 23 | LifecycleManager.interceptInstanceDetached(instance); 24 | 25 | instance[_symbols.Symbols.deactivators] = true; 26 | }; 27 | 28 | LifecycleManager.interceptInstanceDeactivate = function interceptInstanceDeactivate(instance) { 29 | 30 | function _unregister() { 31 | if (_fluxDispatcher.FluxDispatcher.instance.strategy !== _aureliaRouter.activationStrategy.invokeLifecycle) { 32 | _fluxDispatcher.FluxDispatcher.instance.unregisterInstanceDispatcher(instance[_symbols.Symbols.instanceDispatcher]); 33 | } 34 | } 35 | 36 | if (instance.deactivate !== undefined) { 37 | var deactivateImpl = instance.deactivate; 38 | instance.deactivate = function () { 39 | _unregister(); 40 | 41 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 42 | args[_key] = arguments[_key]; 43 | } 44 | 45 | deactivateImpl.apply(instance, args); 46 | }; 47 | } else { 48 | instance.deactivate = function () { 49 | _unregister(); 50 | }; 51 | } 52 | }; 53 | 54 | LifecycleManager.interceptInstanceDetached = function interceptInstanceDetached(instance) { 55 | if (instance.detached !== undefined) { 56 | var deactivateImpl = instance.detached; 57 | instance.detached = function () { 58 | _fluxDispatcher.FluxDispatcher.instance.unregisterInstanceDispatcher(instance[_symbols.Symbols.instanceDispatcher]); 59 | 60 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 61 | args[_key2] = arguments[_key2]; 62 | } 63 | 64 | deactivateImpl.apply(instance, args); 65 | }; 66 | } else { 67 | instance.detached = function () { 68 | _fluxDispatcher.FluxDispatcher.instance.unregisterInstanceDispatcher(instance[_symbols.Symbols.instanceDispatcher]); 69 | }; 70 | } 71 | }; 72 | 73 | LifecycleManager.interceptHtmlBehaviorResource = function interceptHtmlBehaviorResource() { 74 | if (_aureliaTemplating.HtmlBehaviorResource === undefined || typeof _aureliaTemplating.HtmlBehaviorResource.prototype.analyze !== 'function') { 75 | throw new Error('Unsupported version of HtmlBehaviorResource'); 76 | } 77 | 78 | var analyzeImpl = _aureliaTemplating.HtmlBehaviorResource.prototype.analyze; 79 | 80 | _aureliaTemplating.HtmlBehaviorResource.prototype.analyze = function () { 81 | for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 82 | args[_key3] = arguments[_key3]; 83 | } 84 | 85 | var target = args[1]; 86 | if (target && target.prototype && target.prototype[_symbols.Symbols.metadata] && target.prototype[_symbols.Symbols.metadata].handlers && target.prototype[_symbols.Symbols.metadata].handlers.size) { 87 | if (target.prototype.detached === undefined) { 88 | target.prototype.detached = function () {}; 89 | } 90 | } 91 | return analyzeImpl.apply(this, args); 92 | }; 93 | }; 94 | 95 | LifecycleManager.interceptClassActivator = function interceptClassActivator() { 96 | if (_aureliaDependencyInjection.ClassActivator.instance === undefined || _aureliaDependencyInjection.ClassActivator.instance.invoke === undefined) { 97 | throw new Error('Unsupported version of ClassActivator'); 98 | } 99 | 100 | var invokeImpl = _aureliaDependencyInjection.ClassActivator.instance.invoke; 101 | _aureliaDependencyInjection.ClassActivator.instance.invoke = function () { 102 | for (var _len4 = arguments.length, invokeArgs = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { 103 | invokeArgs[_key4] = arguments[_key4]; 104 | } 105 | 106 | var args = invokeArgs[1], 107 | instance; 108 | 109 | if (Array.isArray(args) === false) { 110 | throw new Error('Unsupported version of ClassActivator'); 111 | } 112 | 113 | var dispatcher = args.find(function (item) { 114 | return item instanceof _instanceDispatcher.Dispatcher; 115 | }); 116 | 117 | if (dispatcher) { 118 | var instancePromise = _Promise['default'].defer(); 119 | args[args.indexOf(dispatcher)] = new _instanceDispatcher.DispatcherProxy(instancePromise.promise); 120 | instance = invokeImpl.apply(this, invokeArgs); 121 | instance[_symbols.Symbols.instanceDispatcher] = new _instanceDispatcher.Dispatcher(instance); 122 | instancePromise.resolve(instance); 123 | } else { 124 | instance = invokeImpl.apply(this, invokeArgs); 125 | } 126 | 127 | if (_metadata.Metadata.exists(Object.getPrototypeOf(instance))) { 128 | if (instance[_symbols.Symbols.instanceDispatcher] === undefined) { 129 | instance[_symbols.Symbols.instanceDispatcher] = new _instanceDispatcher.Dispatcher(instance); 130 | } 131 | instance[_symbols.Symbols.instanceDispatcher].registerMetadata(); 132 | } 133 | 134 | if (instance[_symbols.Symbols.instanceDispatcher] !== undefined) { 135 | LifecycleManager.interceptInstanceDeactivators(instance); 136 | } 137 | 138 | return instance; 139 | }; 140 | }; 141 | 142 | return LifecycleManager; 143 | })(); 144 | 145 | exports.LifecycleManager = LifecycleManager; 146 | }); -------------------------------------------------------------------------------- /dist/system/flux-dispatcher.js: -------------------------------------------------------------------------------- 1 | System.register(['bluebird', './instance-dispatcher'], function (_export) { 2 | 'use strict'; 3 | 4 | var Promise, Dispatcher, FluxDispatcher; 5 | 6 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 7 | 8 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9 | 10 | return { 11 | setters: [function (_bluebird) { 12 | Promise = _bluebird['default']; 13 | }, function (_instanceDispatcher) { 14 | Dispatcher = _instanceDispatcher.Dispatcher; 15 | }], 16 | execute: function () { 17 | FluxDispatcher = (function () { 18 | _createClass(FluxDispatcher, null, [{ 19 | key: 'instance', 20 | value: new FluxDispatcher(), 21 | enumerable: true 22 | }]); 23 | 24 | function FluxDispatcher() { 25 | _classCallCheck(this, FluxDispatcher); 26 | 27 | this.instanceDispatchers = new Map(); 28 | this.isDispatching = false; 29 | this.queue = []; 30 | this.typesPromises = new Map(); 31 | } 32 | 33 | FluxDispatcher.prototype.getOrCreateTypeDispatchers = function getOrCreateTypeDispatchers(type) { 34 | if (this.instanceDispatchers.has(type) === false) { 35 | this.instanceDispatchers.set(type, new Set()); 36 | } 37 | 38 | return this.instanceDispatchers.get(type); 39 | }; 40 | 41 | FluxDispatcher.prototype.getOrCreateTypePromises = function getOrCreateTypePromises(type) { 42 | if (this.typesPromises.has(type) === false) { 43 | this.typesPromises.set(type, Promise.defer()); 44 | } 45 | 46 | return this.typesPromises.get(type); 47 | }; 48 | 49 | FluxDispatcher.prototype.registerInstanceDispatcher = function registerInstanceDispatcher(dispatcher) { 50 | if (dispatcher === undefined || dispatcher.instance === undefined) { 51 | return; 52 | } 53 | 54 | var typeDispatchers = this.getOrCreateTypeDispatchers(Object.getPrototypeOf(dispatcher.instance)); 55 | 56 | typeDispatchers.add(dispatcher); 57 | }; 58 | 59 | FluxDispatcher.prototype.unregisterInstanceDispatcher = function unregisterInstanceDispatcher(dispatcher) { 60 | if (dispatcher === undefined || dispatcher.instance === undefined) { 61 | return; 62 | } 63 | 64 | var type = Object.getPrototypeOf(dispatcher.instance); 65 | 66 | if (this.instanceDispatchers.has(type) === false) { 67 | return; 68 | } 69 | 70 | this.instanceDispatchers.get(type)['delete'](dispatcher); 71 | 72 | if (this.instanceDispatchers.get(type).size === 0) { 73 | this.instanceDispatchers['delete'](type); 74 | } 75 | }; 76 | 77 | FluxDispatcher.prototype.dispatch = function dispatch(action, payload) { 78 | this.$dispatch(action, payload, false); 79 | }; 80 | 81 | FluxDispatcher.prototype.$dispatch = function $dispatch(action, payload, fromQueue) { 82 | var _this = this; 83 | 84 | if (this.isDispatching && fromQueue === false) { 85 | this.queue.push([action, payload]); 86 | return; 87 | } 88 | 89 | this.isDispatching = true; 90 | 91 | this.typesPromises = new Map(); 92 | 93 | this.instanceDispatchers.forEach(function (dispatchers, type) { 94 | var typePromise = _this.getOrCreateTypePromises(type); 95 | var promises = []; 96 | 97 | dispatchers.forEach(function (dispatcher) { 98 | promises.push(dispatcher.dispatchOwn.apply(dispatcher, [action, payload])); 99 | }); 100 | 101 | Promise.settle(promises).then(function () { 102 | typePromise.resolve(); 103 | }); 104 | }); 105 | 106 | this.typesPromises.forEach(function (promise, type) { 107 | if (_this.instanceDispatchers.has(type) === false) { 108 | 109 | var _name = type !== undefined && type.constructor !== undefined && type.constructor.name !== undefined ? type.constructor.name : type.toString(); 110 | console.warn('You are waiting for a type \'' + _name + '\' that didn\'t handle event \'' + action + '\'. ' + _name + ' promise has been resolved automatically.'); 111 | 112 | promise.resolve(); 113 | } 114 | }); 115 | 116 | var allTypesPromises = Array.from(this.typesPromises.values()).map(function (defer) { 117 | return defer.promise; 118 | }); 119 | 120 | Promise.settle(allTypesPromises).then(function () { 121 | var next = _this.queue.shift(); 122 | setTimeout(function () { 123 | if (next !== undefined) { 124 | _this.$dispatch(next[0], next[1], true); 125 | } else { 126 | _this.isDispatching = false; 127 | } 128 | }, 0); 129 | }); 130 | }; 131 | 132 | FluxDispatcher.prototype.waitFor = function waitFor(types, handler) { 133 | var _this2 = this; 134 | 135 | if (Array.isArray(types) === false) { 136 | types = [types]; 137 | } 138 | 139 | var typesPromises = types.map(function (type) { 140 | return _this2.getOrCreateTypePromises(type.prototype).promise; 141 | }); 142 | 143 | var def = Promise.defer(); 144 | 145 | Promise.settle(typesPromises).then(function () { 146 | Promise.resolve(handler()).then(function (ret) { 147 | def.resolve(ret); 148 | })['catch'](function (err) { 149 | def.reject(err); 150 | }); 151 | }); 152 | 153 | return def.promise; 154 | }; 155 | 156 | return FluxDispatcher; 157 | })(); 158 | 159 | _export('FluxDispatcher', FluxDispatcher); 160 | } 161 | }; 162 | }); -------------------------------------------------------------------------------- /dist/system/lifecycle-manager.js: -------------------------------------------------------------------------------- 1 | System.register(['aurelia-dependency-injection', 'aurelia-templating', './instance-dispatcher', './flux-dispatcher', './metadata', './symbols', 'bluebird', 'aurelia-router'], function (_export) { 2 | 'use strict'; 3 | 4 | var ClassActivator, HtmlBehaviorResource, Dispatcher, DispatcherProxy, FluxDispatcher, Metadata, Symbols, Promise, activationStrategy, LifecycleManager; 5 | 6 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7 | 8 | return { 9 | setters: [function (_aureliaDependencyInjection) { 10 | ClassActivator = _aureliaDependencyInjection.ClassActivator; 11 | }, function (_aureliaTemplating) { 12 | HtmlBehaviorResource = _aureliaTemplating.HtmlBehaviorResource; 13 | }, function (_instanceDispatcher) { 14 | Dispatcher = _instanceDispatcher.Dispatcher; 15 | DispatcherProxy = _instanceDispatcher.DispatcherProxy; 16 | }, function (_fluxDispatcher) { 17 | FluxDispatcher = _fluxDispatcher.FluxDispatcher; 18 | }, function (_metadata) { 19 | Metadata = _metadata.Metadata; 20 | }, function (_symbols) { 21 | Symbols = _symbols.Symbols; 22 | }, function (_bluebird) { 23 | Promise = _bluebird['default']; 24 | }, function (_aureliaRouter) { 25 | activationStrategy = _aureliaRouter.activationStrategy; 26 | }], 27 | execute: function () { 28 | LifecycleManager = (function () { 29 | function LifecycleManager() { 30 | _classCallCheck(this, LifecycleManager); 31 | } 32 | 33 | LifecycleManager.interceptInstanceDeactivators = function interceptInstanceDeactivators(instance) { 34 | if (instance[Symbols.deactivators] === true) { 35 | return; 36 | } 37 | 38 | LifecycleManager.interceptInstanceDeactivate(instance); 39 | LifecycleManager.interceptInstanceDetached(instance); 40 | 41 | instance[Symbols.deactivators] = true; 42 | }; 43 | 44 | LifecycleManager.interceptInstanceDeactivate = function interceptInstanceDeactivate(instance) { 45 | 46 | function _unregister() { 47 | if (FluxDispatcher.instance.strategy !== activationStrategy.invokeLifecycle) { 48 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 49 | } 50 | } 51 | 52 | if (instance.deactivate !== undefined) { 53 | var deactivateImpl = instance.deactivate; 54 | instance.deactivate = function () { 55 | _unregister(); 56 | 57 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 58 | args[_key] = arguments[_key]; 59 | } 60 | 61 | deactivateImpl.apply(instance, args); 62 | }; 63 | } else { 64 | instance.deactivate = function () { 65 | _unregister(); 66 | }; 67 | } 68 | }; 69 | 70 | LifecycleManager.interceptInstanceDetached = function interceptInstanceDetached(instance) { 71 | if (instance.detached !== undefined) { 72 | var deactivateImpl = instance.detached; 73 | instance.detached = function () { 74 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 75 | 76 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 77 | args[_key2] = arguments[_key2]; 78 | } 79 | 80 | deactivateImpl.apply(instance, args); 81 | }; 82 | } else { 83 | instance.detached = function () { 84 | FluxDispatcher.instance.unregisterInstanceDispatcher(instance[Symbols.instanceDispatcher]); 85 | }; 86 | } 87 | }; 88 | 89 | LifecycleManager.interceptHtmlBehaviorResource = function interceptHtmlBehaviorResource() { 90 | if (HtmlBehaviorResource === undefined || typeof HtmlBehaviorResource.prototype.analyze !== 'function') { 91 | throw new Error('Unsupported version of HtmlBehaviorResource'); 92 | } 93 | 94 | var analyzeImpl = HtmlBehaviorResource.prototype.analyze; 95 | 96 | HtmlBehaviorResource.prototype.analyze = function () { 97 | for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 98 | args[_key3] = arguments[_key3]; 99 | } 100 | 101 | var target = args[1]; 102 | if (target && target.prototype && target.prototype[Symbols.metadata] && target.prototype[Symbols.metadata].handlers && target.prototype[Symbols.metadata].handlers.size) { 103 | if (target.prototype.detached === undefined) { 104 | target.prototype.detached = function () {}; 105 | } 106 | } 107 | return analyzeImpl.apply(this, args); 108 | }; 109 | }; 110 | 111 | LifecycleManager.interceptClassActivator = function interceptClassActivator() { 112 | if (ClassActivator.instance === undefined || ClassActivator.instance.invoke === undefined) { 113 | throw new Error('Unsupported version of ClassActivator'); 114 | } 115 | 116 | var invokeImpl = ClassActivator.instance.invoke; 117 | ClassActivator.instance.invoke = function () { 118 | for (var _len4 = arguments.length, invokeArgs = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { 119 | invokeArgs[_key4] = arguments[_key4]; 120 | } 121 | 122 | var args = invokeArgs[1], 123 | instance; 124 | 125 | if (Array.isArray(args) === false) { 126 | throw new Error('Unsupported version of ClassActivator'); 127 | } 128 | 129 | var dispatcher = args.find(function (item) { 130 | return item instanceof Dispatcher; 131 | }); 132 | 133 | if (dispatcher) { 134 | var instancePromise = Promise.defer(); 135 | args[args.indexOf(dispatcher)] = new DispatcherProxy(instancePromise.promise); 136 | instance = invokeImpl.apply(this, invokeArgs); 137 | instance[Symbols.instanceDispatcher] = new Dispatcher(instance); 138 | instancePromise.resolve(instance); 139 | } else { 140 | instance = invokeImpl.apply(this, invokeArgs); 141 | } 142 | 143 | if (Metadata.exists(Object.getPrototypeOf(instance))) { 144 | if (instance[Symbols.instanceDispatcher] === undefined) { 145 | instance[Symbols.instanceDispatcher] = new Dispatcher(instance); 146 | } 147 | instance[Symbols.instanceDispatcher].registerMetadata(); 148 | } 149 | 150 | if (instance[Symbols.instanceDispatcher] !== undefined) { 151 | LifecycleManager.interceptInstanceDeactivators(instance); 152 | } 153 | 154 | return instance; 155 | }; 156 | }; 157 | 158 | return LifecycleManager; 159 | })(); 160 | 161 | _export('LifecycleManager', LifecycleManager); 162 | } 163 | }; 164 | }); -------------------------------------------------------------------------------- /test/lifecycle-manager.spec.js: -------------------------------------------------------------------------------- 1 | import {LifecycleManager} from '../src/lifecycle-manager'; 2 | import {ClassActivator} from 'aurelia-dependency-injection'; 3 | import {FluxDispatcher} from '../src/flux-dispatcher'; 4 | import {Symbols} from '../src/symbols'; 5 | import {HtmlBehaviorResource} from 'aurelia-templating'; 6 | import {Dispatcher, DispatcherProxy} from '../src/instance-dispatcher'; 7 | import {Metadata} from '../src/metadata'; 8 | 9 | describe('Lifecycle Manager', () => { 10 | describe('interceptInstanceDeactivate', () => { 11 | 12 | var instance; 13 | 14 | beforeEach(() => { 15 | instance = {}; 16 | }); 17 | 18 | describe('without instance.deactivate', () => { 19 | it('adds new deactivate method', () => { 20 | expect(instance.deactivate).toBeUndefined(); 21 | LifecycleManager.interceptInstanceDeactivate(instance); 22 | expect(instance.deactivate).toBeDefined(); 23 | }); 24 | 25 | describe('intercepted deactivate method', () => { 26 | it('runs FluxDispatcher', () => { 27 | spyOn(FluxDispatcher.instance, 'unregisterInstanceDispatcher'); 28 | LifecycleManager.interceptInstanceDeactivate(instance); 29 | instance.deactivate(); 30 | expect(FluxDispatcher.instance.unregisterInstanceDispatcher).toHaveBeenCalled(); 31 | }); 32 | }); 33 | }); 34 | 35 | describe('with instance.deactivate', () => { 36 | it('intercepts deactivate method', () => { 37 | var deactivate = function () { }; 38 | instance.deactivate = deactivate; 39 | LifecycleManager.interceptInstanceDeactivate(instance); 40 | expect(instance.deactivate).toBeDefined(); 41 | expect(instance.deactivate).not.toBe(deactivate); 42 | }); 43 | 44 | describe('intercepted deactivate method', () => { 45 | it('runs original deactivate method', () => { 46 | var deactivate = jasmine.createSpy('deactivate'); 47 | instance.deactivate = deactivate; 48 | LifecycleManager.interceptInstanceDeactivate(instance); 49 | instance.deactivate(); 50 | expect(deactivate).toHaveBeenCalled(); 51 | }); 52 | 53 | it('runs FluxDispatcher', () => { 54 | spyOn(FluxDispatcher.instance, 'unregisterInstanceDispatcher'); 55 | var deactivate = function () { }; 56 | instance.deactivate = deactivate; 57 | LifecycleManager.interceptInstanceDeactivate(instance); 58 | instance.deactivate(); 59 | expect(FluxDispatcher.instance.unregisterInstanceDispatcher).toHaveBeenCalled(); 60 | }); 61 | }); 62 | }); 63 | }); 64 | 65 | 66 | describe('interceptInstanceDetached', () => { 67 | 68 | var instance; 69 | 70 | beforeEach(() => { 71 | instance = {}; 72 | }); 73 | 74 | describe('without instance.detached', () => { 75 | it('adds new detached method', () => { 76 | expect(instance.detached).toBeUndefined(); 77 | LifecycleManager.interceptInstanceDetached(instance); 78 | expect(instance.detached).toBeDefined(); 79 | }); 80 | 81 | describe('intercepted detached method', () => { 82 | it('runs FluxDispatcher', () => { 83 | spyOn(FluxDispatcher.instance, 'unregisterInstanceDispatcher'); 84 | LifecycleManager.interceptInstanceDetached(instance); 85 | instance.detached(); 86 | expect(FluxDispatcher.instance.unregisterInstanceDispatcher).toHaveBeenCalled(); 87 | }); 88 | }); 89 | }); 90 | 91 | describe('with instance.detached', () => { 92 | it('intercepts detached method', () => { 93 | var detached = function () { }; 94 | instance.detached = detached; 95 | LifecycleManager.interceptInstanceDetached(instance); 96 | expect(instance.detached).toBeDefined(); 97 | expect(instance.detached).not.toBe(detached); 98 | }); 99 | 100 | describe('intercepted detached method', () => { 101 | it('runs original detached method', () => { 102 | var detached = jasmine.createSpy('detached'); 103 | instance.detached = detached; 104 | LifecycleManager.interceptInstanceDetached(instance); 105 | instance.detached(); 106 | expect(detached).toHaveBeenCalled(); 107 | }); 108 | 109 | it('runs FluxDispatcher', () => { 110 | spyOn(FluxDispatcher.instance, 'unregisterInstanceDispatcher'); 111 | var detached = function () { }; 112 | instance.detached = detached; 113 | LifecycleManager.interceptInstanceDetached(instance); 114 | instance.detached(); 115 | expect(FluxDispatcher.instance.unregisterInstanceDispatcher).toHaveBeenCalled(); 116 | }); 117 | }); 118 | }); 119 | }); 120 | 121 | 122 | describe('interceptInstanceDeactivators', () => { 123 | 124 | var instance; 125 | 126 | beforeEach(() => { 127 | instance = {}; 128 | }); 129 | 130 | it('sets Symbols.deactivators on an instance when invoked', () => { 131 | expect(instance[Symbols.deactivators]).toBeUndefined(); 132 | LifecycleManager.interceptInstanceDeactivators(instance); 133 | expect(instance[Symbols.deactivators]).toBeDefined(); 134 | }); 135 | 136 | it('runs LifecycleManager.interceptInstanceDeactivate', () => { 137 | spyOn(LifecycleManager, 'interceptInstanceDeactivate'); 138 | LifecycleManager.interceptInstanceDeactivators(instance); 139 | expect(LifecycleManager.interceptInstanceDeactivate).toHaveBeenCalledWith(instance); 140 | }); 141 | 142 | it('runs LifecycleManager.interceptInstanceDeactivate only once', () => { 143 | spyOn(LifecycleManager, 'interceptInstanceDeactivate'); 144 | LifecycleManager.interceptInstanceDeactivators(instance); 145 | LifecycleManager.interceptInstanceDeactivators(instance); 146 | expect(LifecycleManager.interceptInstanceDeactivate.calls.count()).toEqual(1); 147 | }); 148 | 149 | it('runs LifecycleManager.interceptInstanceDetached', () => { 150 | spyOn(LifecycleManager, 'interceptInstanceDetached'); 151 | LifecycleManager.interceptInstanceDeactivators(instance); 152 | expect(LifecycleManager.interceptInstanceDetached).toHaveBeenCalledWith(instance); 153 | }); 154 | 155 | it('runs LifecycleManager.interceptInstanceDetached only once', () => { 156 | spyOn(LifecycleManager, 'interceptInstanceDetached'); 157 | LifecycleManager.interceptInstanceDeactivators(instance); 158 | LifecycleManager.interceptInstanceDeactivators(instance); 159 | expect(LifecycleManager.interceptInstanceDetached.calls.count()).toEqual(1); 160 | }); 161 | }); 162 | 163 | 164 | describe('interceptHtmlBehaviorResource', () => { 165 | 166 | describe('intercepted analyze method', () => { 167 | 168 | it('runs original method', () => { 169 | var analyze = jasmine.createSpy('analyze'); 170 | HtmlBehaviorResource.prototype.analyze = analyze; 171 | LifecycleManager.interceptHtmlBehaviorResource(); 172 | expect(HtmlBehaviorResource.prototype.analyze).not.toBe(analyze); 173 | 174 | function target() { }; 175 | 176 | HtmlBehaviorResource.prototype.analyze(1, target, false); 177 | expect(analyze).toHaveBeenCalledWith(1, target, false); 178 | }); 179 | 180 | it('adds detached method to a target with flux metadata', () => { 181 | function target() { } 182 | 183 | target.prototype[Symbols.metadata] = { 184 | handlers: { 185 | size: 123 186 | } 187 | }; 188 | 189 | expect(target.prototype.detached).toBeUndefined(); 190 | HtmlBehaviorResource.prototype.analyze = function () { }; 191 | LifecycleManager.interceptHtmlBehaviorResource(); 192 | HtmlBehaviorResource.prototype.analyze(null, target); 193 | expect(target.prototype.detached).toBeDefined(); 194 | }); 195 | 196 | it('doesn\'t add detached method to a target without flux metadata', () => { 197 | function target() { } 198 | 199 | expect(target.prototype.detached).toBeUndefined(); 200 | HtmlBehaviorResource.prototype.analyze = function () { }; 201 | LifecycleManager.interceptHtmlBehaviorResource(); 202 | HtmlBehaviorResource.prototype.analyze(null, target); 203 | expect(target.prototype.detached).toBeUndefined(); 204 | }); 205 | 206 | }); 207 | }); 208 | 209 | describe('interceptClassActivator', () => { 210 | 211 | var invokeImpl, 212 | instance, 213 | origInstanceProto, 214 | instanceProto; 215 | 216 | beforeAll(() => { 217 | instanceProto = {}; 218 | }); 219 | 220 | beforeEach(() => { 221 | instance = Object.create(instanceProto); 222 | invokeImpl = jasmine.createSpy('invoke').and.returnValue(instance); 223 | ClassActivator.instance.invoke = invokeImpl; 224 | }); 225 | 226 | it('intercepts ClassActivator.instance.invoke', () => { 227 | LifecycleManager.interceptClassActivator(); 228 | expect(ClassActivator.instance.invoke).not.toBe(invokeImpl); 229 | }); 230 | 231 | describe('intercepted ClassActivator.instance.invoke', () => { 232 | 233 | it('throws an exception when second argument is not an array', () => { 234 | LifecycleManager.interceptClassActivator(); 235 | expect(() => ClassActivator.instance.invoke(null, "")).toThrowError('Unsupported version of ClassActivator'); 236 | }); 237 | 238 | // without dispatcher injected 239 | describe('without dispatcher injected', () => { 240 | it('runs original invoke method', () => { 241 | LifecycleManager.interceptClassActivator(); 242 | ClassActivator.instance.invoke(null, []); 243 | expect(invokeImpl).toHaveBeenCalled(); 244 | }); 245 | 246 | it('returns proper instance', () => { 247 | LifecycleManager.interceptClassActivator(); 248 | var result = ClassActivator.instance.invoke(null, []); 249 | expect(result).toBe(instance); 250 | }); 251 | }); 252 | /////////////////////////////// 253 | 254 | // with dispatcher injected 255 | describe('with dispatcher injected', () => { 256 | 257 | var dispatcher; 258 | 259 | beforeEach(() => { 260 | dispatcher = new Dispatcher(); 261 | }); 262 | 263 | it('runs original invoke method', () => { 264 | LifecycleManager.interceptClassActivator(); 265 | ClassActivator.instance.invoke(null, [dispatcher]); 266 | expect(invokeImpl).toHaveBeenCalled(); 267 | }); 268 | 269 | it('returns proper instance', () => { 270 | LifecycleManager.interceptClassActivator(); 271 | var result = ClassActivator.instance.invoke(null, [dispatcher]); 272 | expect(result).toBe(instance); 273 | }); 274 | 275 | it('replaces injected Dispatcher with DispatcherProxy', (done) => { 276 | LifecycleManager.interceptClassActivator(); 277 | var args = [dispatcher]; 278 | ClassActivator.instance.invoke(null, args); 279 | expect(args[0] instanceof DispatcherProxy).toBe(true); 280 | args[0].inititalize.then(() => { 281 | expect(args[0].instance).toBe(instance); 282 | done(); 283 | }, done.fail); 284 | }); 285 | 286 | it('sets instance[Symbols.instanceDispatcher] to be new Dispatcher', () => { 287 | LifecycleManager.interceptClassActivator(); 288 | expect(instance[Symbols.instanceDispatcher]).toBeUndefined(); 289 | ClassActivator.instance.invoke(null, [dispatcher]); 290 | expect(instance[Symbols.instanceDispatcher]).toBeDefined(); 291 | }); 292 | 293 | it('intercepts instance deactivators', () => { 294 | spyOn(LifecycleManager, 'interceptInstanceDeactivators'); 295 | LifecycleManager.interceptClassActivator(); 296 | ClassActivator.instance.invoke(null, [dispatcher]); 297 | expect(LifecycleManager.interceptInstanceDeactivators).toHaveBeenCalledWith(instance); 298 | }); 299 | }); 300 | /////////////////////////////// 301 | 302 | describe('for instance prototype with metadata', () => { 303 | 304 | beforeEach(() => { 305 | instanceProto[Symbols.metadata] = new Metadata(); 306 | }); 307 | 308 | it('runs instance Disptacher.registerMetadata', () => { 309 | spyOn(Dispatcher.prototype, 'registerMetadata'); 310 | LifecycleManager.interceptClassActivator(); 311 | ClassActivator.instance.invoke(null, []); 312 | expect(Dispatcher.prototype.registerMetadata).toHaveBeenCalled(); 313 | }); 314 | 315 | it('intercepts instance deactivators', () => { 316 | spyOn(LifecycleManager, 'interceptInstanceDeactivators'); 317 | LifecycleManager.interceptClassActivator(); 318 | ClassActivator.instance.invoke(null, []); 319 | expect(LifecycleManager.interceptInstanceDeactivators).toHaveBeenCalledWith(instance); 320 | }); 321 | }); 322 | 323 | }); 324 | }); 325 | }); 326 | --------------------------------------------------------------------------------