UNPKG

67.4 kBJavaScriptView Raw
1/**
2 * @license Framing v0.8.26
3 * Copyright 2016-2017 Ryan Campbell. https://github.com/framing
4 * License: Apache License, Version 2.0
5 */
6import { ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectorRef, Component, ComponentFactoryResolver, Directive, EventEmitter, Injectable, Injector, Input, NgModule, NgModuleFactory, Output, Type, ViewContainerRef } from '@angular/core';
7import { ActivatedRoute, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router, RouterModule } from '@angular/router';
8import { assign, camelCase, clone, defaults, differenceWith, each, filter, find, isArray, isEmpty, isEqual, isNil, keys, merge, reject, uniqWith } from 'lodash';
9import * as _ from 'lodash';
10import { BehaviorSubject } from 'rxjs/BehaviorSubject';
11import { ReplaySubject, Subject } from 'rxjs';
12import { ReplaySubject as ReplaySubject$1 } from 'rxjs/Rx';
13import { CommonModule } from '@angular/common';
14import { FormsModule } from '@angular/forms';
15import { BrowserModule } from '@angular/platform-browser';
16
17class Component$1 {
18 constructor(controller, injector) {
19 this.controller = controller;
20 this.changeDetectorRef = injector.get(ChangeDetectorRef);
21 this.subscriptions = [];
22 this.subscriptions.push(controller.model$.subscribe((model) => this.updateModel(model)), controller.view$.subscribe((view) => this.updateView(view)), controller.markForCheck$.subscribe(() => this.changeDetectorRef.markForCheck()));
23 this.controller.attach();
24 }
25 ngOnInit() {
26 }
27 ngOnDestroy() {
28 this.controller.detach();
29 this.subscriptions.forEach((s) => s.unsubscribe());
30 this.subscriptions = null;
31 this.changeDetectorRef = null;
32 this.controller = null;
33 this.model = null;
34 this.view = null;
35 }
36 updateModel(model) {
37 this.model = model;
38 this.changeDetectorRef.markForCheck();
39 }
40 updateView(view) {
41 this.view = view;
42 this.changeDetectorRef.markForCheck();
43 }
44}
45
46var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
47 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
48 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
49 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
50 return c > 3 && r && Object.defineProperty(target, key, r), r;
51};
52// import { Subject } from 'rxjs/Subject';
53let Controller = class Controller {
54 // import { Subject } from 'rxjs/Subject';
55 constructor() {
56 // ========================================
57 // private properties
58 // ========================================
59 this._refCount = 0;
60 }
61 // ========================================
62 // public methods
63 // ========================================
64 /**
65 * Model observable accessor.
66 */
67 get model$() { return this._model$; }
68 /**
69 * Model accessor.
70 */
71 get model() { return this._model; }
72 /**
73 * View observable accessor.
74 */
75 get view$() { return this._view$; }
76 /**
77 * View accessor.
78 */
79 get view() { return this._view; }
80 /**
81 * Mark for check observable accessor.
82 */
83 get markForCheck$() { return this._markForCheck$; }
84 /**
85 * Frame accessor.
86 */
87 get frame() { return this._frame; }
88 /**
89 * Model accessor.
90 */
91 get injector() { return this._injector; }
92 /**
93 * Called after controller is initialized with model, view & frame from framing.
94 */
95 onControllerInit() { }
96 /**
97 * Called when the controller's route starts resolving.
98 */
99 onResolveStart() { }
100 /**
101 * Called when the controller's route end resolving.
102 */
103 onResolveEnd() { }
104 /**
105 * Called when the controller's route resolve is cancelled.
106 */
107 onResolveCancel() { }
108 /**
109 * Called by framing after construction to link the model, view & frame for this controller.
110 */
111 initController(model, view, frame, framerName, injector) {
112 this._modelSubject = new BehaviorSubject(model);
113 this._viewSubject = new BehaviorSubject(view);
114 this._model$ = this._modelSubject.asObservable();
115 this._view$ = this._viewSubject.asObservable();
116 this._model = model;
117 this._view = view;
118 this._markForCheckSubject = new BehaviorSubject(true);
119 this._markForCheck$ = this._markForCheckSubject.asObservable();
120 this._frame = frame;
121 this._injector = injector;
122 this._framerName = framerName;
123 if (this._frame) {
124 this._frame.resolveStart$.subscribe(() => { this.onResolveStart(); });
125 this._frame.resolveEnd$.subscribe(() => { this.onResolveEnd(); });
126 this._frame.resolveCancel$.subscribe(() => { this.onResolveCancel(); });
127 }
128 this.onControllerInit();
129 console.log('initController');
130 console.log(this);
131 }
132 updateModel(model, replace = false) {
133 if (replace) {
134 this._model = clone(model);
135 }
136 else {
137 this._model = assign({}, this._model, model);
138 }
139 this._modelSubject.next(this._model);
140 }
141 updateView(view, replace = false) {
142 if (replace) {
143 this._view = clone(view);
144 }
145 else {
146 this._view = assign({}, this._view, view);
147 }
148 this._viewSubject.next(this._view);
149 }
150 markForCheck() {
151 this._markForCheckSubject.next(true);
152 }
153 attach() {
154 this._refCount++;
155 if (this._refCount === 1) {
156 setTimeout(() => {
157 this.onAttached();
158 });
159 }
160 }
161 detach() {
162 this._refCount--;
163 if (this._refCount === 0) {
164 setTimeout(() => {
165 this.onDetached();
166 });
167 }
168 }
169 onAttached() { }
170 onDetached() { }
171};
172Controller = __decorate$2([
173 Injectable()
174], Controller);
175
176/**
177 * Dev tool class used for framing integration with Redux DevTools
178 *
179 * @class FramingTools
180 */
181/**
182 * Dev tool class used for framing integration with Redux DevTools
183 *
184 * @class FramingTools
185 */ class FramingTools {
186 constructor() {
187 this.instantiatedControllers = {};
188 }
189 static get Instance() {
190 return this._instance || (this._instance = new this());
191 }
192 addController(framerName, controller) {
193 this.instantiatedControllers[framerName] = controller;
194 }
195 getAllControllers() {
196 return this.instantiatedControllers;
197 }
198 getControllerByKey(key) {
199 return this.instantiatedControllers[key] ? this.instantiatedControllers[key] : null;
200 }
201}
202
203let framingTools = FramingTools.Instance;
204let stateRoot = {};
205let onLoad = true;
206// let controllers: any[] = [];
207const devTools = _createReduxDevtoolsExtension();
208let isListening = false;
209/* tslint:disable */
210function Action(description = null, log = true) {
211 return function (target, propertyKey, descriptor) {
212 if (descriptor === undefined) {
213 descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
214 }
215 let originalMethod = descriptor.value;
216 descriptor.value = function () {
217 let args = [];
218 let controller = this;
219 // let controllerIndex: number;
220 // if (controllers.indexOf(controller) <= -1) {
221 // controllers.push(controller);
222 // controllerIndex = controllers.length - 1;
223 // } else {
224 // controllerIndex = controllers.indexOf(controller);
225 // }
226 for (let _i = 0; _i < arguments.length; _i++) {
227 args[_i] = arguments[_i];
228 }
229 try {
230 listenForChanges();
231 }
232 catch (e) {
233 console.log('Listen to Devtools failed: ');
234 console.log(e);
235 }
236 // Send the initial state if this is the first time connecting to the dev tools
237 if (onLoad && log && devTools) {
238 onLoad = !onLoad;
239 stateRoot[controller._framerName] = controller.model;
240 let state = {
241 framerName: controller._framerName,
242 value: stateRoot,
243 };
244 try {
245 devTools.send((description || propertyKey), state);
246 }
247 catch (e) {
248 console.log('Send to Devtools failed: ');
249 console.log(e);
250 }
251 }
252 originalMethod.apply(controller, args);
253 // Need to log after the method has been ran and state is updated
254 if (log && devTools) {
255 stateRoot[controller._framerName] = controller.model;
256 let state = {
257 framerName: controller._framerName,
258 // controllerIndex: controllerIndex,
259 value: stateRoot,
260 };
261 try {
262 devTools.send((description || propertyKey), state);
263 }
264 catch (e) {
265 console.log('Send to Devtools failed: ');
266 console.log(e);
267 }
268 }
269 controller.markForCheck();
270 };
271 return descriptor;
272 };
273}
274/**
275 * Listen for message events being broadcast from the redux devTools
276 * Changes state on the correct controller to match the state changes broadcast
277 */
278function listenForChanges() {
279 if (isListening || !devTools)
280 return;
281 isListening = true;
282 let connection = devTools.connect();
283 connection.subscribe((message) => {
284 if (!!message.state) {
285 let messageState = JSON.parse(message.state);
286 let messageController = framingTools.getControllerByKey(messageState.framerName);
287 if (messageController) {
288 for (let prop in messageController.model) {
289 messageController.model[prop] = messageState.value[messageState.framerName][prop];
290 }
291 messageController.markForCheck();
292 }
293 }
294 });
295}
296/**
297 * Returns correct instance of redux dev tools installed
298 *
299 * @export
300 * @returns
301 */
302function _createReduxDevtoolsExtension() {
303 const legacyExtensionKey = 'devToolsExtension';
304 const extensionKey = '__REDUX_DEVTOOLS_EXTENSION__';
305 if (typeof window === 'object' && typeof window[legacyExtensionKey] !== 'undefined') {
306 return window[legacyExtensionKey];
307 }
308 else if (typeof window === 'object' && typeof window[extensionKey] !== 'undefined') {
309 return window[extensionKey];
310 }
311 else {
312 return null;
313 }
314}
315
316var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
317 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
318 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
319 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
320 return c > 3 && r && Object.defineProperty(target, key, r), r;
321};
322var __metadata$1 = (undefined && undefined.__metadata) || function (k, v) {
323 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
324};
325let FramingDevToolsController = class FramingDevToolsController extends Controller {
326 constructor(router) {
327 super();
328 this.router = router;
329 this.replayNavigation = false;
330 }
331 onControllerInit() {
332 this.router.events.subscribe((event) => {
333 this.handleRouterEvents(event);
334 });
335 this.markForCheck$.subscribe((data) => {
336 if (this.model.snapshotUrl && this.model.snapshotUrl !== this.router.routerState.snapshot.url) {
337 this.replayNavigation = true;
338 this.router.navigate([this.model.snapshotUrl]);
339 }
340 }, (err) => console.error(err));
341 }
342 trackRouterState() {
343 this.model.snapshotUrl = this.router.routerState.snapshot.url;
344 }
345 handleRouterEvents(event) {
346 if (event instanceof NavigationEnd) {
347 if (!this.replayNavigation) {
348 this.trackRouterState();
349 }
350 this.replayNavigation = false;
351 }
352 }
353};
354__decorate$1([
355 Action(),
356 __metadata$1("design:type", Function),
357 __metadata$1("design:paramtypes", []),
358 __metadata$1("design:returntype", void 0)
359], FramingDevToolsController.prototype, "trackRouterState", null);
360FramingDevToolsController = __decorate$1([
361 Injectable(),
362 __metadata$1("design:paramtypes", [Router])
363], FramingDevToolsController);
364
365var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
366 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
367 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
368 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
369 return c > 3 && r && Object.defineProperty(target, key, r), r;
370};
371var __metadata = (undefined && undefined.__metadata) || function (k, v) {
372 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
373};
374let FramingDevToolsComponent = class FramingDevToolsComponent extends Component$1 {
375 constructor(controller, injector) {
376 super(controller, injector);
377 }
378};
379FramingDevToolsComponent = __decorate([
380 Component({}),
381 __metadata("design:paramtypes", [FramingDevToolsController, Injector])
382], FramingDevToolsComponent);
383
384class Frame {
385 constructor() {
386 // ========================================
387 // public properties
388 // ========================================
389 /**
390 * Subjects
391 */
392 this.routeUrlSubject = new ReplaySubject();
393 this.resolveStartSubject = new Subject();
394 this.resolveEndSubject = new Subject();
395 this.resolveCancelSubject = new Subject();
396 }
397 /**
398 * An observable of the route url of the route that this controllerr is attached to, if any.
399 */
400 get routeUrl$() { return this.routeUrlSubject; }
401 /**
402 * Emitted when the frame resolve method starts if this controller is attached to a route.
403 */
404 get resolveStart$() { return this.resolveStartSubject; }
405 /**
406 * Emitted when the frame resolve method ends if this controller is attached to a route.
407 */
408 get resolveEnd$() { return this.resolveEndSubject; }
409 /**
410 * Emitted when the frame resolve method is cancelled if this controller is attached to a route.
411 */
412 get resolveCancel$() { return this.resolveCancelSubject; }
413}
414
415/**
416 * @description This is a description
417 */
418class Framer {
419 // ========================================
420 // constructor
421 // ========================================
422 /**
423 * Contructor.
424 */
425 constructor(model, view, controller) {
426 this.framingDevTools = FramingTools.Instance;
427 /**
428 * True if framing() has been called.
429 */
430 this._framed = false;
431 this.construct(model, view, controller);
432 }
433 /**
434 * Model accessor.
435 */
436 get theModel() { return this._model; }
437 /**
438 * View accessor.
439 */
440 get theView() { return this._view; }
441 /**
442 * Controller accessor.
443 */
444 get theController() { return this._controller; }
445 /**
446 * When true, framing will create a frame for this framer.
447 */
448 get createFrame() { return true; }
449 /**
450 * When true, framing will use multi on all providers so multiple framers of the same type can be setup on the same module.
451 */
452 get multiFramer() { return false; }
453 /**
454 * When true, framing will setup the controller as a provider by its type.
455 */
456 get provideControllerByType() { return true; }
457 /**
458 * When true, framing will add the model to the route data.
459 */
460 get addModelToRouteData() { return false; }
461 /**
462 * When true, framing will add the view to the route data.
463 */
464 get addViewToRouteData() { return false; }
465 /**
466 * When true, framing will add the frame to the route data.
467 */
468 get addFrameToRouteData() { return false; }
469 /**
470 * The default model.
471 */
472 get defaultModel() { return undefined; }
473 /**
474 * The default view.
475 */
476 get defaultView() { return undefined; }
477 /**
478 * The default controller.
479 */
480 get defaultController() { return undefined; }
481 /**
482 * 'require': framing will attach the default route, creating it if it doesn't yet exist, if not route is attached to this framer (default behavior)
483 * 'auto': framing will attach the default route if available if not route is attached to this framer
484 * 'none': framing will not attach a route to this framer
485 */
486 get routeRule() { return 'require'; }
487 /**
488 * A unique framer id for this framer.
489 */
490 get framerId() { return this._framerId; }
491 /**
492 * A unique identifier string for this framer instance.
493 */
494 get framerIdent() { return `${this.framerName}Framer-${this._framerId}`; }
495 /**
496 * True if framing() has been called.
497 */
498 get framed() { return this._framed; }
499 /**
500 * The injector (available on and after framerOnResolveRoute or framerOnControllerInit, whichever comes first)
501 */
502 get injector() { return this._injector; }
503 /**
504 * The framer's route, if attached to a route, otherwise undefined
505 * Valid ONLY during the runFraming() and framing() functions
506 */
507 get route() { return this._route; }
508 // ========================================
509 // public static methods
510 // ========================================
511 /**
512 * Helper function to build the URL of an ActivatedRouteSnapshot
513 */
514 static buildUrlLink(route) {
515 if (!route) {
516 return '/';
517 }
518 let urls = [];
519 /* tslint:disable:no-param-reassign */
520 for (; route.parent; route = route.parent) {
521 /* tslint:enable:no-param-reassign */
522 urls = urls.concat(route.url.reverse());
523 }
524 urls = urls.reverse();
525 return '/' + urls.join('/');
526 }
527 // ========================================
528 // public methods
529 // ========================================
530 /**
531 * Model chaining function.
532 */
533 model(model) {
534 merge(this._model, model);
535 return this;
536 }
537 /**
538 * View chaining function.
539 */
540 view(view) {
541 merge(this._view, view);
542 return this;
543 }
544 /**
545 * Controller chaining function.
546 */
547 controller(controller) {
548 if (controller) {
549 this._controller = controller;
550 }
551 return this;
552 }
553 /**
554 * Framer on resolve route function called when framer's route is resolved.
555 * Injector is set before during this call.
556 * Not called if framer is not attached to a route.
557 * To be overwritten if needed.
558 */
559 framerOnResolveRoute() { }
560 /**
561 * Framer on controller init function is called when the controller is first injected.
562 * To be overwritten if needed.
563 */
564 framerOnControllerInit(controller) { }
565 /**
566 * Calls derived framing()
567 */
568 runFraming(framing, routeParam) {
569 if (this._framed) {
570 console.warn(`runFraming() called multiple times on framer '${this.framerIdent}'`);
571 return;
572 }
573 this._framed = true; // mark this framer to framed
574 if (this.routeRule === 'auto') {
575 // set the framer's attached route (if any)
576 this._route = routeParam;
577 }
578 else if (this.routeRule === 'require') {
579 // set the framer's attached route to the supplied route or create one if it doesn not exist
580 if (routeParam) {
581 this._route = routeParam;
582 }
583 else {
584 /* tslint:disable:no-param-reassign */
585 this._route = routeParam = framing.getOrAddRoute();
586 /* tslint:enable:no-param-reassign */
587 }
588 }
589 this._framing = framing; // set _framing to framing ONLY for the duration of the controller() function
590 try {
591 this.frame(framing);
592 }
593 catch (e) {
594 console.error(`Exception when framing ${this.framerIdent} :`, e);
595 this._model = undefined;
596 this._view = undefined;
597 this._controller = undefined;
598 }
599 this._framing = undefined;
600 if (this.routeRule === 'auto') {
601 this._route = routeParam;
602 }
603 const self = this;
604 if (this._controller) {
605 // FUTURE
606 // this.provideTypeByName(framing, this.framerName + 'Controller', this._controller);
607 let controllerInstance;
608 framing
609 .provide({
610 provide: this.framerIdent + '-ControllerInternal',
611 useClass: this._controller,
612 })
613 .provide({
614 provide: this.framerIdent + '-Controller',
615 useFactory: (injector) => {
616 if (controllerInstance) {
617 this.framingDevTools.addController(this.framerName, controllerInstance);
618 return controllerInstance;
619 }
620 self._injector = injector;
621 controllerInstance = injector.get(this.framerIdent + '-ControllerInternal');
622 controllerInstance.initController(this._model, this._view, this._frame, this.framerName, injector);
623 this.framerOnControllerInit(controllerInstance);
624 this.framingDevTools.addController(this.framerName, controllerInstance);
625 return controllerInstance;
626 },
627 deps: [Injector],
628 });
629 if (this.provideControllerByType) {
630 framing
631 .provide({
632 provide: this._controller,
633 useExisting: this.framerIdent + '-Controller',
634 multi: this.multiFramer && this._controller === this.defaultController,
635 });
636 /* tslint:disable:no-console */
637 console.info(`Providing controller for framer ${this.framerIdent} by type`);
638 /* tslint:enable:no-console */
639 if (this.defaultController && this._controller !== this.defaultController) {
640 framing.provide({
641 provide: this.defaultController,
642 useExisting: this.framerIdent + '-Controller',
643 multi: this.multiFramer,
644 });
645 /* tslint:disable:no-console */
646 console.info(`Providing controller overload for framer ${this.framerIdent} by default controller type`);
647 /* tslint:enable:no-console */
648 }
649 }
650 }
651 // FUTURE: frame, model & view provided by name
652 // this.provideValueByName(framing, this.framerName + 'Frame', this._frame);
653 // this.provideValueByName(framing, this.framerName + 'Model', this._model);
654 // this.provideValueByName(framing, this.framerName + 'View', this._view);
655 // FUTURE: model & view provided by type
656 // this.provideInstanceByType(framing, this._model);
657 // this.provideInstanceByType(framing, this._view);
658 if (this.route) {
659 if (this.addFrameToRouteData) {
660 this.addRouteData(framing, this.framerName + 'Frame', this._frame);
661 }
662 if (this.addModelToRouteData) {
663 this.addRouteData(framing, this.framerName + 'Model', this._model);
664 }
665 if (this.addViewToRouteData) {
666 this.addRouteData(framing, this.framerName + 'View', this._view);
667 }
668 if (this._frame) {
669 class FrameResolver {
670 constructor(router, route, injector) {
671 this.router = router;
672 this.route = route;
673 self._injector = injector;
674 }
675 resolve(routeSnapshot, routeStateSnapshot) {
676 self._frame.resolveStartSubject.next();
677 const routeUrl = Framer.buildUrlLink(routeSnapshot);
678 const sub = this.router.events.subscribe((event) => {
679 if (event instanceof NavigationStart) {
680 console.error('Unexpected NavigationStart');
681 }
682 else if (event instanceof NavigationEnd) {
683 /* tslint:disable:no-console */
684 console.info(`Route url for framer ${self.framerIdent} changed to ${routeUrl}`);
685 /* tslint:enable:no-console */
686 self._frame.routeSnapshot = self.findActivateRouteSnapshot(this.route);
687 self._frame.routeUrl = routeUrl;
688 self._frame.routeUrlSubject.next(routeUrl);
689 self.framerOnResolveRoute();
690 self._frame.resolveEndSubject.next();
691 }
692 else if (event instanceof NavigationError) {
693 self._frame.resolveCancelSubject.next();
694 }
695 else if (event instanceof NavigationCancel) {
696 self._frame.resolveCancelSubject.next();
697 }
698 sub.unsubscribe();
699 });
700 return self._frame;
701 }
702 }
703 framing
704 .resolve(this.framerIdent, FrameResolver, this.route)
705 .provide({
706 provide: FrameResolver,
707 useFactory: (r, a, i) => new FrameResolver(r, a, i),
708 deps: [Router, ActivatedRoute, Injector]
709 });
710 }
711 }
712 this._route = undefined; // clear the route so we're not holding any references to its properties
713 }
714 /**
715 * Protected construct function for derived construction help.
716 */
717 construct(model, view, controller) {
718 this._framerId = Framer._nextId++;
719 if (this.createFrame) {
720 this._frame = new Frame();
721 }
722 const defaultModel = this.defaultModel;
723 this._model = defaultModel ? merge(defaultModel, model) : model;
724 const defaultView = this.defaultView;
725 this._view = defaultView ? merge(defaultView, view) : view;
726 this._controller = controller || this.defaultController;
727 }
728 /**
729 * Protected construct function for derived construction help.
730 */
731 findActivateRouteSnapshot(route) {
732 if (!route) {
733 console.error('Failed to find activated route snapshot');
734 return undefined;
735 }
736 if (route.snapshot && route.snapshot.data && route.snapshot.data.hasOwnProperty(this.framerIdent)) {
737 return route.snapshot;
738 }
739 return this.findActivateRouteSnapshot(route.firstChild);
740 }
741 /**
742 * FUTURE
743 */
744 // private provideTypeByName(framing: FramingNgModule, name: string, type: any): void {
745 // if (type) {
746 // framing.provide({ provide: name, useClass: type });
747 // /* tslint:disable:no-console */
748 // console.info(`Providing ${name} for framer ${this.framerIdent} by name`);
749 // /* tslint:enable:no-console */
750 // }
751 // }
752 /**
753 * FUTURE
754 */
755 // private provideInstanceByType(framing: FramingNgModule, instance: any): void {
756 // if (instance &&
757 // (instance as any).__proto__ &&
758 // (instance as any).__proto__.constructor &&
759 // (instance as any).__proto__.constructor.name !== 'Object') {
760 // framing.provide({ provide: (instance as any).__proto__.constructor, useValue: instance });
761 // /* tslint:disable:no-console */
762 // console.info(`Providing ${(instance as any).__proto__.constructor.name} for framer ${this.framerIdent} by type`);
763 // /* tslint:enable:no-console */
764 // }
765 // }
766 /**
767 * FUTURE
768 */
769 // private provideValueByName(framing: FramingNgModule, name: string, value: any): void {
770 // if (value) {
771 // framing.provide({ provide: name, useValue: value });
772 // /* tslint:disable:no-console */
773 // console.info(`Providing ${name} for framer ${this.framerIdent} by name`);
774 // /* tslint:enable:no-console */
775 // }
776 // }
777 addRouteData(framing, name, value) {
778 if (value) {
779 const routeConfig = framing.getOrAddRoute(this.route);
780 if (routeConfig.data && routeConfig.data[name]) {
781 console.warn(`Failed to add ${name} route data for framer ${this.framerIdent}. Data item already exists.`);
782 }
783 else {
784 framing.datum(name, value, this.route);
785 /* tslint:disable:no-console */
786 console.info(`Adding ${name} route data for framer ${this.framerIdent}`);
787 /* tslint:enable:no-console */
788 }
789 }
790 }
791}
792Framer._nextId = 1;
793
794class FramingDevToolsFeature extends Framer {
795 get defaultModel() {
796 return {};
797 }
798 get defaultView() {
799 return {};
800 }
801 frame(framing) { }
802 framerOnResolveRoute() {
803 let framingDevToolsController;
804 framingDevToolsController = this.injector.get(FramingDevToolsController);
805 }
806 // ========================================
807 // internal framing methods (don't touch!)
808 // ========================================
809 get framerName() { return 'FramingDevTools'; }
810 get defaultController() { return FramingDevToolsController; }
811}
812
813var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
814 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
815 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
816 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
817 return c > 3 && r && Object.defineProperty(target, key, r), r;
818};
819var __metadata$2 = (undefined && undefined.__metadata) || function (k, v) {
820 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
821};
822let FramingComponentOutletDirective = class FramingComponentOutletDirective {
823 constructor(_view) {
824 this._view = _view;
825 this.onComponent = new EventEmitter();
826 }
827 isActivated() { return !!this._componentRef; }
828 ngOnChanges(changes) {
829 let activate = false;
830 if (changes.ngModuleFactory) {
831 if (this._moduleRef) {
832 this._moduleRef.destroy();
833 }
834 if (this.ngModuleFactory) {
835 const injector = this.injector || this._view.parentInjector;
836 this._moduleRef = this.ngModuleFactory.create(injector);
837 }
838 else {
839 this._moduleRef = undefined;
840 }
841 activate = true;
842 }
843 if (changes.framingComponentOutlet.currentValue !== changes.framingComponentOutlet.previousValue) {
844 activate = true;
845 }
846 if (activate) {
847 this.activate(this.framingComponentOutlet);
848 }
849 }
850 ngOnDestroy() {
851 this.deactivate();
852 if (this._moduleRef) {
853 this._moduleRef.destroy();
854 }
855 }
856 activate(component) {
857 this.deactivate();
858 if (!component) {
859 return;
860 }
861 try {
862 const injector = this.injector || this._view.parentInjector;
863 const factory = injector.get(ComponentFactoryResolver).resolveComponentFactory(component);
864 this._componentRef = this._view.createComponent(factory, this._view.length, injector, this.content);
865 this.onComponent.emit(this._componentRef);
866 try {
867 this._componentRef.changeDetectorRef.detectChanges();
868 }
869 catch (e) {
870 console.error(`detectChanges failed on activated component in FramingComponentOutlet`, { e, component });
871 return;
872 }
873 }
874 catch (e) {
875 console.error(`Failed to activate component in FramingComponentOutlet`, { e, component });
876 return;
877 }
878 }
879 deactivate() {
880 if (this._componentRef) {
881 this._view.remove(this._view.indexOf(this._componentRef.hostView));
882 this._componentRef.destroy();
883 }
884 this._view.clear();
885 this._componentRef = undefined;
886 }
887};
888__decorate$3([
889 Input(),
890 __metadata$2("design:type", Type)
891], FramingComponentOutletDirective.prototype, "framingComponentOutlet", void 0);
892__decorate$3([
893 Input(),
894 __metadata$2("design:type", Injector)
895], FramingComponentOutletDirective.prototype, "injector", void 0);
896__decorate$3([
897 Input(),
898 __metadata$2("design:type", Array)
899], FramingComponentOutletDirective.prototype, "content", void 0);
900__decorate$3([
901 Input(),
902 __metadata$2("design:type", NgModuleFactory)
903], FramingComponentOutletDirective.prototype, "ngModuleFactory", void 0);
904__decorate$3([
905 Output(),
906 __metadata$2("design:type", EventEmitter)
907], FramingComponentOutletDirective.prototype, "onComponent", void 0);
908FramingComponentOutletDirective = __decorate$3([
909 Directive({
910 selector: '[framingComponentOutlet]',
911 }),
912 __metadata$2("design:paramtypes", [ViewContainerRef])
913], FramingComponentOutletDirective);
914
915var __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
916 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
917 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
918 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
919 return c > 3 && r && Object.defineProperty(target, key, r), r;
920};
921let FramingComponentOutletModule = FramingComponentOutletModule_1 = class FramingComponentOutletModule {
922 static withEntryComponents(...components) {
923 return {
924 ngModule: FramingComponentOutletModule_1,
925 providers: [
926 { provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true },
927 ],
928 };
929 }
930};
931FramingComponentOutletModule = FramingComponentOutletModule_1 = __decorate$4([
932 NgModule({
933 declarations: [FramingComponentOutletDirective],
934 exports: [FramingComponentOutletDirective],
935 })
936], FramingComponentOutletModule);
937var FramingComponentOutletModule_1;
938
939var __decorate$6 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
940 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
941 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
942 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
943 return c > 3 && r && Object.defineProperty(target, key, r), r;
944};
945var __metadata$4 = (undefined && undefined.__metadata) || function (k, v) {
946 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
947};
948let FramingContainerOutletService = class FramingContainerOutletService {
949 constructor(router) {
950 this.router = router;
951 this.contentsSubject = new ReplaySubject$1();
952 this.contents = [];
953 this.routeContents = [];
954 this.subscriptions = [];
955 this.subscriptions.push(this.router.events.subscribe((event) => {
956 if (event instanceof NavigationEnd) {
957 this.onNavigationEnd();
958 }
959 }));
960 }
961 get contents$() { return this.contentsSubject.asObservable(); }
962 hasContent(container) {
963 return !!this.contents.filter((c) => isEqual(c.container, container)).length;
964 }
965 activate(content) {
966 this.contents.push(content);
967 this.contentsSubject.next(clone(this.contents));
968 return () => { this.deactivate(content); };
969 }
970 deactivate(content) {
971 this.contents = this.contents.filter((e) => e !== content);
972 this.contentsSubject.next(clone(this.contents));
973 }
974 onNavigationEnd() {
975 let newRouteContents = [];
976 this.resolveRouteContents(this.router.routerState.snapshot.root, newRouteContents);
977 newRouteContents = uniqWith(newRouteContents, isEqual);
978 const newContents = differenceWith(newRouteContents, this.routeContents, isEqual);
979 const removedContents = differenceWith(this.routeContents, newRouteContents, isEqual);
980 newContents.forEach((c) => this.activate(c));
981 removedContents.forEach((c) => this.deactivate(c));
982 this.routeContents = newRouteContents;
983 }
984 resolveRouteContents(snapshot, routeContents) {
985 if (snapshot.data && snapshot.data.containers) {
986 const containers = snapshot.data.containers;
987 for (const container of containers) {
988 routeContents.push(container);
989 }
990 }
991 for (let child of snapshot.children) {
992 this.resolveRouteContents(child, routeContents);
993 }
994 }
995};
996FramingContainerOutletService = __decorate$6([
997 Injectable(),
998 __metadata$4("design:paramtypes", [Router])
999], FramingContainerOutletService);
1000
1001var __decorate$5 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1002 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1003 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1004 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1005 return c > 3 && r && Object.defineProperty(target, key, r), r;
1006};
1007var __metadata$3 = (undefined && undefined.__metadata) || function (k, v) {
1008 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1009};
1010let FramingContainerOutletDirective = class FramingContainerOutletDirective {
1011 constructor(_view, _containerService, _router) {
1012 this._view = _view;
1013 this._containerService = _containerService;
1014 this._router = _router;
1015 this.onComponents = new EventEmitter();
1016 this._activated = [];
1017 this._subscriptions = [];
1018 }
1019 containerName() { return this.framingContainerOutlet; }
1020 isActivated() { return this._activated.length > 0; }
1021 ngOnInit() {
1022 if (!this.framingContainerOutlet) {
1023 console.warn('FramingContainerOutlet without a container name');
1024 }
1025 else {
1026 if (this.framingContainerOutlet[0] === '\'') {
1027 console.warn(`FramingContainerOutlet name "${this.framingContainerOutlet}" starts with a qoute`);
1028 }
1029 this._subscriptions.push(this._containerService.contents$.subscribe((contents) => this.onContent(contents)));
1030 }
1031 this._subscriptions.push(this._router.events.subscribe((event) => {
1032 if (event instanceof NavigationEnd) {
1033 if (!this.optionalContainer && !this.isActivated()) {
1034 console.warn(`No content for required FramingContainerOutlet '${this.framingContainerOutlet}' found`);
1035 }
1036 }
1037 }));
1038 }
1039 ngOnDestroy() {
1040 this._activated.forEach((a) => this.deactivate(a));
1041 this._subscriptions.forEach((s) => s.unsubscribe());
1042 }
1043 onContent(allContents) {
1044 const contents = allContents.filter((c) => isEqual(c.container, this.framingContainerOutlet));
1045 // remove all content that is no longer active
1046 this._activated.forEach((a) => {
1047 if (contents.findIndex((content) => content === a.content) === -1) {
1048 this.deactivate(a);
1049 }
1050 });
1051 this._activated = this._activated.filter((a) => !!a.ref);
1052 // now setup the new activated components
1053 let i = 0;
1054 for (let content of contents) {
1055 if (this._activated.length > i) {
1056 if (this._activated[i].content !== content) {
1057 // look for this content
1058 const activatedIndex = this._activated.findIndex((a) => a.content === content);
1059 if (activatedIndex === -1) {
1060 // activate this content at i
1061 this._activated.splice(i, 0, { content, ref: this.activate(content) });
1062 }
1063 else if (activatedIndex > i) {
1064 // move content from activatedIndex to i
1065 const _activated = this._activated.splice(activatedIndex, 1);
1066 this._activated.splice(i, 0, ..._activated);
1067 const view = this._view.detach(activatedIndex);
1068 this._view.insert(view, i);
1069 }
1070 else {
1071 console.error('Logic error in FramingContainerOutlet!');
1072 }
1073 }
1074 }
1075 else {
1076 // activate this content
1077 const ref = this.activate(content);
1078 if (ref) {
1079 this._activated.push({ content, ref });
1080 }
1081 }
1082 i++;
1083 }
1084 this.onComponents.emit(this._activated.map((a) => a.ref));
1085 }
1086 activate(content, i) {
1087 try {
1088 const injector = (!this.useViewInjector && content.injector) ? content.injector : this._view.parentInjector;
1089 const factory = injector.get(ComponentFactoryResolver).resolveComponentFactory(content.component);
1090 let ref = this._view.createComponent(factory, i, injector, this.content);
1091 try {
1092 ref.changeDetectorRef.detectChanges();
1093 }
1094 catch (e) {
1095 console.error(`detectChanges failed on activated component in FramingContainerOutlet '${this.framingContainerOutlet}'`, { e, component: content.component });
1096 }
1097 return ref;
1098 }
1099 catch (e) {
1100 console.error(`Failed to activate component in FramingContainerOutlet '${this.framingContainerOutlet}'`, { e, component: content.component });
1101 return undefined;
1102 }
1103 }
1104 deactivate(activated) {
1105 activated.ref.destroy();
1106 activated.ref = null;
1107 }
1108};
1109__decorate$5([
1110 Input(),
1111 __metadata$3("design:type", String)
1112], FramingContainerOutletDirective.prototype, "framingContainerOutlet", void 0);
1113__decorate$5([
1114 Input(),
1115 __metadata$3("design:type", Boolean)
1116], FramingContainerOutletDirective.prototype, "optionalContainer", void 0);
1117__decorate$5([
1118 Input(),
1119 __metadata$3("design:type", Boolean)
1120], FramingContainerOutletDirective.prototype, "useViewInjector", void 0);
1121__decorate$5([
1122 Input(),
1123 __metadata$3("design:type", Array)
1124], FramingContainerOutletDirective.prototype, "content", void 0);
1125__decorate$5([
1126 Output(),
1127 __metadata$3("design:type", EventEmitter)
1128], FramingContainerOutletDirective.prototype, "onComponents", void 0);
1129FramingContainerOutletDirective = __decorate$5([
1130 Directive({
1131 selector: '[framingContainerOutlet]',
1132 }),
1133 __metadata$3("design:paramtypes", [ViewContainerRef,
1134 FramingContainerOutletService,
1135 Router])
1136], FramingContainerOutletDirective);
1137
1138var __decorate$7 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1139 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1140 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1141 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1142 return c > 3 && r && Object.defineProperty(target, key, r), r;
1143};
1144let FramingContainerOutletModule = FramingContainerOutletModule_1 = class FramingContainerOutletModule {
1145 static withEntryComponents(...components) {
1146 return {
1147 ngModule: FramingContainerOutletModule_1,
1148 providers: [
1149 { provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true },
1150 ],
1151 };
1152 }
1153 static forRoot() {
1154 return {
1155 ngModule: FramingContainerOutletModule_1,
1156 providers: [FramingContainerOutletService],
1157 };
1158 }
1159};
1160FramingContainerOutletModule = FramingContainerOutletModule_1 = __decorate$7([
1161 NgModule({
1162 declarations: [FramingContainerOutletDirective],
1163 exports: [FramingContainerOutletDirective],
1164 })
1165], FramingContainerOutletModule);
1166var FramingContainerOutletModule_1;
1167
1168var __decorate$8 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1169 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1170 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1171 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1172 return c > 3 && r && Object.defineProperty(target, key, r), r;
1173};
1174var __metadata$5 = (undefined && undefined.__metadata) || function (k, v) {
1175 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1176};
1177let FramingContainerOutletResolver = class FramingContainerOutletResolver {
1178 constructor(containers, injector) {
1179 this.containers = containers;
1180 this.injector = injector;
1181 }
1182 /**
1183 * Resolve hook.
1184 */
1185 resolve(route, state) {
1186 // set the injector in each container
1187 for (let container of this.containers) {
1188 container.injector = this.injector;
1189 }
1190 return this.containers;
1191 }
1192};
1193FramingContainerOutletResolver = __decorate$8([
1194 Injectable(),
1195 __metadata$5("design:paramtypes", [Array, Injector])
1196], FramingContainerOutletResolver);
1197
1198var __decorate$9 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1199 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1200 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1201 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1202 return c > 3 && r && Object.defineProperty(target, key, r), r;
1203};
1204/**
1205 * @experimental
1206 */
1207let FramingEmptyParentComponent = class FramingEmptyParentComponent {
1208};
1209FramingEmptyParentComponent = __decorate$9([
1210 Component({
1211 selector: 'empty-parent-component',
1212 template: '<router-outlet></router-outlet>',
1213 })
1214], FramingEmptyParentComponent);
1215
1216var __decorate$11 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1217 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1218 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1219 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1220 return c > 3 && r && Object.defineProperty(target, key, r), r;
1221};
1222let FramingRootComponent = class FramingRootComponent {
1223};
1224FramingRootComponent = __decorate$11([
1225 Component({
1226 selector: 'app-root',
1227 template: '<router-outlet></router-outlet>',
1228 })
1229], FramingRootComponent);
1230
1231var __decorate$10 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1232 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1233 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1234 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1235 return c > 3 && r && Object.defineProperty(target, key, r), r;
1236};
1237let FramingComponentsModule = class FramingComponentsModule {
1238};
1239FramingComponentsModule = __decorate$10([
1240 NgModule({
1241 imports: [
1242 RouterModule,
1243 ],
1244 declarations: [
1245 FramingEmptyParentComponent,
1246 FramingRootComponent,
1247 ],
1248 exports: [
1249 FramingEmptyParentComponent,
1250 FramingRootComponent,
1251 ],
1252 })
1253], FramingComponentsModule);
1254
1255class FramerHelper {
1256 // ========================================
1257 // constructor
1258 // ========================================
1259 constructor() {
1260 this.framerHelperId = FramerHelper._nextId++;
1261 }
1262 /**
1263 * A unique identifier string for this framer helper instance.
1264 */
1265 get framerHelperIdent() {
1266 return camelCase(`framerHelper-${this.__proto__.constructor.name}-${this.framerHelperId}`);
1267 }
1268}
1269FramerHelper._nextId = 1;
1270
1271/**
1272 *
1273 */
1274class FramingNgModule {
1275 constructor() {
1276 // ========================================
1277 // private properties
1278 // ========================================
1279 this._ngModule = {
1280 imports: [],
1281 declarations: [],
1282 exports: [],
1283 providers: [],
1284 bootstrap: [],
1285 entryComponents: [],
1286 };
1287 this._root = false;
1288 this._routes = [];
1289 }
1290 static get defaultPathMatch() { return 'prefix'; }
1291 // ========================================
1292 // public methods
1293 // ========================================
1294 ngModule(ngModule) {
1295 if (ngModule) {
1296 defaults(this._ngModule, ngModule);
1297 each(filter(keys(ngModule), (key) => { return isArray(ngModule[key]); }), (key) => {
1298 this._ngModule[key] = uniqWith(this._ngModule[key].concat(reject(ngModule[key], isNil)), isEqual);
1299 });
1300 }
1301 return this;
1302 }
1303 bootstrap(bootstrap) {
1304 const flattened = [].concat.apply([], bootstrap);
1305 this._ngModule.bootstrap = uniqWith(this._ngModule.bootstrap.concat(reject(flattened, isNil)), isEqual);
1306 return this;
1307 }
1308 child(child, parent) {
1309 let parentRoute = this.getOrAddRouteOverload(parent);
1310 if (!parentRoute.children) {
1311 parentRoute.children = [];
1312 }
1313 if (!parentRoute.component) {
1314 parentRoute.component = FramingEmptyParentComponent;
1315 }
1316 this.getOrAddRoute(child, parentRoute.children);
1317 return this;
1318 }
1319 children(children, parent) {
1320 each(children, (child) => {
1321 this.child(child, parent);
1322 });
1323 return this;
1324 }
1325 component(component, route) {
1326 if (component) {
1327 let routeConfig = this.getOrAddRouteOverload(route);
1328 routeConfig.component = component;
1329 }
1330 return this;
1331 }
1332 componentAndDeclare(component, route) {
1333 return this.componentAndDeclaration(component, route);
1334 }
1335 componentAndDeclaration(component, route) {
1336 this.component(component, route);
1337 if (component) {
1338 this.declare(component);
1339 }
1340 return this;
1341 }
1342 container(container, components, route) {
1343 let containers = {};
1344 containers[container] = components;
1345 this.containers(containers, route);
1346 return this;
1347 }
1348 containers(containers, route) {
1349 for (let key in containers) {
1350 if (containers.hasOwnProperty(key)) {
1351 if (isNil(containers[key])) {
1352 delete containers[key];
1353 }
1354 }
1355 }
1356 const routeConfig = this.getOrAddRoute(route);
1357 if (!routeConfig.resolve) {
1358 routeConfig.resolve = {};
1359 }
1360 if (!routeConfig.resolve.containers) {
1361 routeConfig.resolve.containers = [];
1362 }
1363 for (let key in containers) {
1364 if (containers.hasOwnProperty(key)) {
1365 const components = containers[key];
1366 if (isArray(components)) {
1367 for (const component of components) {
1368 routeConfig.resolve.containers.push({ container: key, component });
1369 }
1370 }
1371 else {
1372 routeConfig.resolve.containers.push({ container: key, component: components });
1373 }
1374 }
1375 }
1376 return this;
1377 }
1378 datum(key, datum, route) {
1379 let data = {};
1380 data[key] = datum;
1381 this.data(data, route);
1382 return this;
1383 }
1384 data(data, route) {
1385 let routeConfig = this.getOrAddRouteOverload(route);
1386 if (!routeConfig.data) {
1387 routeConfig.data = {};
1388 }
1389 merge(routeConfig.data, data);
1390 return this;
1391 }
1392 resolve(key, resolve, route) {
1393 let resolves = {};
1394 resolves[key] = resolve;
1395 this.resolves(resolves, route);
1396 return this;
1397 }
1398 resolves(resolves, route) {
1399 let routeConfig = this.getOrAddRouteOverload(route);
1400 if (!routeConfig.resolve) {
1401 routeConfig.resolve = {};
1402 }
1403 merge(routeConfig.resolve, resolves);
1404 return this;
1405 }
1406 declare(declaration) {
1407 return this.declaration(declaration);
1408 }
1409 declaration(declaration) {
1410 return this.declarations(isArray(declaration) ? declaration : [declaration]);
1411 }
1412 declarations(declarations) {
1413 const flattened = [].concat.apply([], declarations);
1414 this._ngModule.declarations = uniqWith(this._ngModule.declarations.concat(reject(flattened, isNil)), isEqual);
1415 return this;
1416 }
1417 declareAndExport(declaration) {
1418 return this.declarationAndExport(declaration);
1419 }
1420 declarationAndExport(declaration) {
1421 return this.declarationsAndExports(isArray(declaration) ? declaration : [declaration]);
1422 }
1423 declarationsAndExports(declarations) {
1424 this.declarations(declarations);
1425 this.exports(declarations);
1426 return this;
1427 }
1428 declareAndEntryComponent(declaration) {
1429 return this.declarationAndEntryComponent(declaration);
1430 }
1431 declarationAndEntryComponent(declaration) {
1432 return this.declarationsAndEntryComponents(isArray(declaration) ? declaration : [declaration]);
1433 }
1434 declarationsAndEntryComponents(declarations) {
1435 this.declarations(declarations);
1436 this.entryComponents(declarations);
1437 return this;
1438 }
1439 entryComponent(entryComponent) {
1440 return this.entryComponents(isArray(entryComponent) ? entryComponent : [entryComponent]);
1441 }
1442 entryComponents(entryComponents) {
1443 const flattened = [].concat.apply([], entryComponents);
1444 this._ngModule.entryComponents = uniqWith(this._ngModule.entryComponents.concat(reject(flattened, isNil)), isEqual);
1445 return this;
1446 }
1447 export(e) {
1448 return this.exports(isArray(e) ? e : [e]);
1449 }
1450 exports(exports) {
1451 const flattened = [].concat.apply([], exports);
1452 this._ngModule.exports = uniqWith(this._ngModule.exports.concat(reject(flattened, isNil)), isEqual);
1453 return this;
1454 }
1455 import(i) {
1456 return this.imports(isArray(i) ? i : [i]);
1457 }
1458 imports(imports) {
1459 const flattened = [].concat.apply([], imports);
1460 this._ngModule.imports = uniqWith(this._ngModule.imports.concat(reject(flattened, isNil)), isEqual);
1461 return this;
1462 }
1463 importAndExport(m) {
1464 return this.importsAndExports(isArray(m) ? m : [m]);
1465 }
1466 importsAndExports(modules) {
1467 this.imports(modules);
1468 this.exports(modules);
1469 return this;
1470 }
1471 provide(provider) {
1472 return this.provider(provider);
1473 }
1474 provider(provider) {
1475 return this.providers(isArray(provider) ? provider : [provider]);
1476 }
1477 providers(providers) {
1478 const flattened = [].concat.apply([], providers);
1479 this._ngModule.providers = uniqWith(this._ngModule.providers.concat(reject(flattened, isNil)), isEqual);
1480 return this;
1481 }
1482 /**
1483 * Adds component to bootstrap
1484 * Defaults route to path '', pathMatch: 'full'
1485 */
1486 root(rootComponent, config) {
1487 this._root = true;
1488 this._rootComponentConfig = config || {};
1489 defaults(this._rootComponentConfig, { hybrid: false });
1490 this._rootComponent = rootComponent || FramingRootComponent;
1491 return this;
1492 }
1493 /**
1494 * Creates Routes array with single route
1495 * Adds RouterModule.forRoot(routes) or RouterModule.forChild(routes) to imports
1496 * Adds all resolve services as providers
1497 */
1498 route(route, config) {
1499 this.getOrAddRoute(route);
1500 if (this._routeConfig) {
1501 if (config) {
1502 merge(this._routeConfig, config);
1503 }
1504 }
1505 else {
1506 this._routeConfig = config || {};
1507 defaults(this._routeConfig, { forRoot: false });
1508 }
1509 return this;
1510 }
1511 routes(routes, config) {
1512 each(routes, (route) => {
1513 this.route(route, config);
1514 });
1515 return this;
1516 }
1517 frameRoute(route, ...framers) {
1518 this.buildFramers(framers, this.getOrAddRouteOverload(route));
1519 return this;
1520 }
1521 /**
1522 * Returns the route if it exists.
1523 */
1524 getRoute(route = {}, array) {
1525 /* tslint:disable:no-param-reassign */
1526 if (!array) {
1527 array = this._routes;
1528 }
1529 /* tslint:enable:no-param-reassign */
1530 defaults(route, { path: '', pathMatch: FramingNgModule.defaultPathMatch });
1531 return find(array, (m) => { return m.path === route.path && m.pathMatch === route.pathMatch; });
1532 }
1533 /**
1534 * Returns the route. Creates it if it does not exist.
1535 */
1536 getOrAddRoute(route = {}, array) {
1537 /* tslint:disable:no-param-reassign */
1538 if (!array) {
1539 array = this._routes;
1540 }
1541 /* tslint:enable:no-param-reassign */
1542 defaults(route, { path: '', pathMatch: FramingNgModule.defaultPathMatch });
1543 let r = find(array, (m) => { return m.path === route.path && m.pathMatch === route.pathMatch; });
1544 if (r) {
1545 merge(r, route);
1546 return r;
1547 }
1548 else {
1549 array.push(route);
1550 return route;
1551 }
1552 }
1553 /**
1554 * Run framers.
1555 */
1556 frame(...framers) {
1557 this.buildFramers(framers);
1558 return this;
1559 }
1560 use(...framers) {
1561 return this.frame(...framers);
1562 }
1563 /**
1564 * Builds @NgModule() config in the following order:
1565 * - Route framers
1566 * - Root
1567 * - Route
1568 */
1569 build() {
1570 this.buildRouteFramers(this._routes);
1571 this.buildRoot();
1572 this.buildContainers(this._routes);
1573 this.buildRoute();
1574 this.inspectModule();
1575 return this._ngModule;
1576 }
1577 // ========================================
1578 // private methods
1579 // ========================================
1580 inspectModule() {
1581 this._routes.forEach((r) => this.inspectRoute(r));
1582 }
1583 inspectRoute(route) {
1584 if (route.component === undefined && route.redirectTo === undefined && isEmpty(route.children) && route.loadChildren === undefined) {
1585 console.error(`Looks like you have a badly configured route in a framed module.
1586 One of the following must be provided: component, redirectTo, children or loadChildren`, { route, self: this });
1587 }
1588 if (route.children) {
1589 route.children.forEach((c) => this.inspectRoute(c));
1590 }
1591 }
1592 buildRoot() {
1593 let m = this._ngModule;
1594 if (this._root) {
1595 m.imports = uniqWith(m.imports.concat([
1596 BrowserModule.withServerTransition({
1597 appId: 'app',
1598 }),
1599 FormsModule,
1600 ]), isEqual);
1601 m.bootstrap = uniqWith(m.bootstrap.concat([this._rootComponent]), isEqual);
1602 }
1603 else {
1604 m.imports = uniqWith(m.imports.concat([
1605 CommonModule,
1606 ]), isEqual);
1607 }
1608 m.imports = uniqWith(m.imports.concat([FramingComponentsModule]), isEqual);
1609 }
1610 buildFramers(framers, route) {
1611 for (let framer of framers) {
1612 this.buildFramer(framer, route);
1613 }
1614 }
1615 buildFramer(framer, route) {
1616 if (!framer.framed) {
1617 framer.runFraming(this, route || this.getRoute());
1618 }
1619 }
1620 /**
1621 * Builds framers that were manually added to route data.
1622 */
1623 buildRouteFramers(routes) {
1624 for (let route of routes) {
1625 if (route.data) {
1626 for (let key in route.data) {
1627 if (route.data.hasOwnProperty(key)) {
1628 let prop = route.data[key];
1629 if (prop && prop._frame !== undefined) {
1630 // this is a framer attached to route data
1631 this.buildFramer(prop, route);
1632 }
1633 }
1634 }
1635 }
1636 if (route.children) {
1637 this.buildRouteFramers(route.children);
1638 }
1639 }
1640 }
1641 buildContainers(routes) {
1642 for (let route of routes) {
1643 if (route.resolve && route.resolve.containers) {
1644 const containers = route.resolve.containers;
1645 for (const container of containers) {
1646 const containerId = FramingNgModule._nextId++;
1647 container.id = '' + containerId;
1648 }
1649 const resolveId = FramingNgModule._nextId++;
1650 this.provide({
1651 provide: 'containerResolver' + resolveId,
1652 useFactory: (i) => new FramingContainerOutletResolver(containers, i),
1653 deps: [Injector],
1654 });
1655 route.resolve.containers = 'containerResolver' + resolveId;
1656 }
1657 if (route.children) {
1658 this.buildContainers(route.children);
1659 }
1660 }
1661 }
1662 buildRoute() {
1663 if (this._routes.length > 0) {
1664 // re-order routes so that full routes are first
1665 let fullRoutes = [];
1666 let prefixRoutes = [];
1667 this._routes.forEach((route) => {
1668 if (route.pathMatch && route.pathMatch === 'full') {
1669 fullRoutes.push(route);
1670 }
1671 else if (!route.pathMatch || route.pathMatch === 'prefix') {
1672 prefixRoutes.push(route);
1673 }
1674 else {
1675 console.warn('Unknown pathMatch on route', route);
1676 }
1677 this._routes = [];
1678 this._routes = this._routes.concat(fullRoutes);
1679 this._routes = this._routes.concat(prefixRoutes);
1680 });
1681 const routing = this._root || (this._routeConfig && this._routeConfig.forRoot) ?
1682 RouterModule.forRoot(this._routes, this._routeConfig ? this._routeConfig.extraRootRouterOptions : undefined) :
1683 RouterModule.forChild(this._routes);
1684 this.imports([routing]);
1685 if (this._routeConfig && this._routeConfig.forRoot && !this._root) {
1686 this.exports([RouterModule]); // export RouterModule from AppRoutingModule
1687 }
1688 }
1689 }
1690 getOrAddRouteOverload(route) {
1691 if (isArray(route)) {
1692 if (route.length) {
1693 let result;
1694 /* tslint:disable:prefer-for-of */
1695 result = this.getOrAddRoute(route[0]);
1696 for (let i = 1; i < route.length; i++) {
1697 if (!result.children) {
1698 result.children = [];
1699 }
1700 result = this.getOrAddRoute(route[i], result.children);
1701 }
1702 /* tslint:enable:prefer-for-of */
1703 return result;
1704 }
1705 else {
1706 return this.getOrAddRoute();
1707 }
1708 }
1709 else {
1710 return this.getOrAddRoute(route);
1711 }
1712 }
1713}
1714FramingNgModule._nextId = 1;
1715
1716/* tslint:disable:variable-name */
1717const Framing = (ngModuleBuilder) => {
1718 /* tslint:enable:variable-name */
1719 let framing = ngModuleBuilder(new FramingNgModule());
1720 if (!framing) {
1721 console.error('Framing must return a FramingNgModule');
1722 return {};
1723 }
1724 return framing.build();
1725};
1726
1727/**
1728 * A framer with no route, model, view, controller or frame.
1729 * To be used for leveraging the frame() function only.
1730 */
1731class SimpleFramer extends Framer {
1732 get framerName() { return 'Simple'; }
1733 get createFrame() { return false; }
1734 get routeRule() { return 'none'; }
1735}
1736
1737export { FramingDevToolsComponent, FramingDevToolsController, FramingDevToolsFeature, Action, _createReduxDevtoolsExtension, FramingComponentOutletDirective, FramingComponentOutletModule, FramingContainerOutletDirective, FramingContainerOutletModule, FramingContainerOutletResolver, FramingContainerOutletService, FramingEmptyParentComponent, FramingComponentsModule, FramingRootComponent, Component$1 as Component, Controller, FramingTools, Frame, FramerHelper, Framer, FramingNgModule, Framing, SimpleFramer };
1738//# sourceMappingURL=ng-core.js.map