/
PageFactory.ts
135 lines (118 loc) · 3.52 KB
/
PageFactory.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { Constructor } from 'type-fest';
import { PageStateManager } from './state/PageStateManager';
import { OCAliasMap } from '../config/bind';
import { Controller } from '../controller/Controller';
import { GenericError } from '../error/GenericError';
import { Extension } from '../extension/Extension';
import { ObjectContainer } from '../oc/ObjectContainer';
import { RouteController } from '../router/AbstractRoute';
import { RouteOptions } from '../router/Router';
/**
* Factory for page.
*/
export class PageFactory {
/**
* The current application object container.
*/
_oc: ObjectContainer;
/**
* Factory used by page management classes.
*/
constructor(oc: ObjectContainer) {
this._oc = oc;
}
/**
* Create new instance of {@link Controller}.
*/
createController(
controller: RouteController,
options: RouteOptions
): Controller {
const { extensions = [] } = options;
let mergedExtensions = [...extensions];
if (
Array.isArray((controller as typeof Controller)?.$extensions) &&
(controller as typeof Controller).$extensions?.length
) {
// @ts-expect-error can't check static properties
mergedExtensions = mergedExtensions.concat(controller.$extensions);
}
const controllerInstance = this._oc.create(controller) as Controller;
for (const extension of mergedExtensions) {
const loadedExtension = this._oc.get(extension) as Extension;
// Optional extension handling
if (!loadedExtension) {
continue;
}
// Spread support handling
if (Array.isArray(loadedExtension)) {
for (const extensionInstance of loadedExtension) {
controllerInstance.addExtension(
extensionInstance.constructor,
extensionInstance
);
}
} else {
controllerInstance.addExtension(
extension as typeof Extension,
loadedExtension
);
}
}
return controllerInstance;
}
/**
* Retrieves the specified react component class.
*
* @param view The namespace
* referring to a react component class, or a react component class
* constructor.
* @return The react component class
* constructor.
*/
createView<
V extends keyof OCAliasMap | Constructor<any> | ((...args: any[]) => any)
>(view: V) {
if (typeof view === 'function') {
return view;
}
const classConstructor = this._oc.getConstructorOf(view);
if (classConstructor) {
return classConstructor;
} else {
throw new GenericError(
`ima.core.page.Factory:createView hasn't name of view "${view}".`
);
}
}
/**
* Returns decorated controller for ease setting seo params in controller.
*/
decorateController(controller: Controller) {
const metaManager = this._oc.get('$MetaManager');
const router = this._oc.get('$Router');
const dictionary = this._oc.get('$Dictionary');
const settings = this._oc.get('$Settings');
const decoratedController = this._oc.create('$ControllerDecorator', [
controller,
metaManager,
router,
dictionary,
settings,
]);
return decoratedController;
}
/**
* Returns decorated page state manager for extension.
*/
decoratePageStateManager(
pageStateManager: PageStateManager,
allowedStateKeys: string[]
) {
const decoratedPageStateManager = this._oc.create(
'$PageStateManagerDecorator',
[pageStateManager, allowedStateKeys]
);
return decoratedPageStateManager;
}
}