UNPKG

9.11 kBPlain TextView Raw
1/**
2 * takes a SlsIsomorphic Component and parses it into an Iso-Config
3 *
4 * @param component a SlsIsomorphic React-Component
5 */
6import {ConfigTypes} from "./lib/config";
7import React from 'react';
8import * as deepmerge from 'deepmerge';
9
10const isClientApp = (component) => {
11
12 return component.props &&
13 component.props.id !== undefined &&
14 component.props.path !== undefined &&
15 component.props.method !== undefined ? true : false;
16};
17
18const isMiddleware = (component) => {
19
20 return component.props &&
21 component.props.callback !== undefined ? true : false;
22};
23
24const isRedirect = (component) => {
25
26 return component.props &&
27 component.props.from !== undefined &&
28 component.props.to !== undefined &&
29 component.props.status !== undefined ? true : false;
30};
31
32const isRoute = (component) => {
33
34 return component.props &&
35 component.props.path !== undefined &&
36 (component.props.render !== undefined || component.props.component !== undefined) &&
37 component.props.name !== undefined ? true : false;
38};
39
40export const parseCustomComponent = (component, compileMode) => {
41
42 try {
43
44 //console.log("parseCustomComponent: " , component);
45
46
47 const params = Object.assign({
48 infrastructureMode: compileMode ? "compile" : undefined,
49 }, component.props);
50
51 var custom = undefined;
52 const parsed = `const f=${component.type}; f(${JSON.stringify(params)})`;
53
54 const result = eval(parsed);
55
56 //console.log("isCustomComponent: ", component)
57 //console.log("parsed: ", parsed);
58 //console.log("result: ", result);
59
60 return result.infrastructureType !== undefined ? result : undefined;
61
62 } catch (error) {
63 //console.error(error);
64 return undefined;
65 }
66
67
68}
69
70export const getChildrenArray = (component) => {
71
72 if (component == undefined) {
73 return [];
74 }
75
76 if (Array.isArray(component) && component.length > 0) {
77 //console.log("component is array: ", component)
78 return [...component] ;
79 }
80
81 if (component.props == undefined || component.props.children == undefined) {
82 return [];
83 }
84
85 return Array.isArray(component.props.children) ? component.props.children : [component.props.children];
86};
87
88const applyMiddleware = (mwComponent) => {
89 return mwComponent.props.callback;
90};
91
92
93const parseMiddlewares = (component) => {
94 return getChildrenArray(component)
95 .filter(child => isMiddleware(child))
96 .map(child => applyMiddleware(child));
97}
98
99const applyClientApp = (caComponent) => {
100
101 //console.log("applyClientApp: " , caComponent);
102
103 return Object.assign(
104 Object.assign({}, caComponent.props),
105 {
106 middlewareCallbacks: (caComponent.props.middlewareCallbacks !== undefined ?
107 caComponent.props.middlewareCallbacks : []).concat(parseMiddlewares(caComponent)),
108
109 redirects: (caComponent.props.redirects !== undefined ?
110 caComponent.props.redirects : []).concat(parseRedirects(caComponent)),
111
112 routes: (caComponent.props.routes !== undefined ?
113 caComponent.props.routes : []).concat(parseRoutes(caComponent, caComponent.props.method)),
114 }
115 );
116
117};
118
119
120export const applyCustomComponents = (component: any, addToTopLevelConfig, addDataLayer, compileMode) => {
121 //getChildrenArray(caComponent).forEach( c => {
122 const customComponent = parseCustomComponent(component, compileMode);
123
124 if (customComponent !== undefined && compileMode) {
125 //console.log("CustomComponent: ", customComponent);
126
127 if (customComponent.infrastructureType === "dataLayer") {
128 addDataLayer(customComponent);
129 }
130
131 // now add to the configuration
132 addToTopLevelConfig(customComponent);
133
134 // we expect a single one child!!
135 if (Array.isArray(customComponent.children)) {
136 throw new Error("custom Components must have a single one child!");
137 }
138
139
140 //console.log("component: " , component);
141 //return component.props.children
142
143 var customProps = {}
144 customProps[customComponent.infrastructureType] = Object.assign(
145 {},
146 customComponent /*component.props*/,
147 {infrastructureMode: "component"}
148 )
149
150 const child = component.props.children;
151
152 // add the custom props to the child that is forwarded
153 return child !== undefined ? React.cloneElement(child,
154 Object.assign({}, child, customProps)) : () => {}
155
156
157
158 } else if (customComponent !== undefined) {
159 //console.log("applyCustomComponents | customComponent ")
160
161 if (React.isValidElement(component)) {
162 //console.log("custom component is a react-component, " , component)
163 if (Array.isArray(customComponent.children)) {
164 throw new Error("custom Components must have a single one child!");
165 }
166
167 const child = component["props"]["children"];
168
169 var customProps = {}
170 customProps[customComponent.infrastructureType] = React.cloneElement(component,
171 Object.assign({}, component.props, {infrastructureMode: "component"}))
172
173 //console.log("customProps: " , customProps);
174
175 const result = React.cloneElement(component,
176 Object.assign({}, child !== undefined ? child.props : {}, customProps));
177
178 if (customComponent.infrastructureType === "dataLayer") {
179 addDataLayer(result);
180 }
181
182 return result;
183 //return React.cloneElement(component, Object.assign({}, component.props, {infrastructureMode: "component"}))
184
185 }
186
187 return component.props.children;
188 }
189
190 // when the component is NOT a custom one, we return it
191 return component;
192
193 //});
194}
195
196const parseRedirects = (component) => {
197 return getChildrenArray(component)
198 .filter(child => isRedirect(child))
199 .map(child => applyRedirect(child));
200};
201
202const applyRedirect = (redirectComponent) => {
203 //console.log("redirect: ", redirectComponent.props);
204 return redirectComponent.props
205};
206
207const parseRoutes = (component, method) => {
208 /*return getChildrenArray(component)
209 .filter(child => isRoute(child))
210 .map(child => applyRoute(child, component.props.method));
211
212 */
213
214 return getChildrenArray(component)
215 .map(child => {
216 //console.log("child: ", child)
217
218 if (isRoute(child)) {
219 return applyRoute(child, method);
220 } else if (!isMiddleware(child) && !isRedirect(child)) {
221
222 //console.log("investigate child: ", child)
223
224 return parseRoutes(child, method)
225 } else return [];
226 })
227 .flat();
228};
229
230const applyRoute = (routeComponent, method) => {
231 //console.log("route: ", routeComponent.props);
232 return Object.assign(
233 Object.assign({}, routeComponent.props),
234 {
235 method: method,
236 exact: true,
237 middlewareCallbacks: (routeComponent.props.middlewareCallbacks !== undefined ?
238 routeComponent.props.middlewareCallbacks : []).concat(parseMiddlewares(routeComponent)),
239 }
240 );
241};
242
243
244export function loadIsoConfigFromComponent(component: any, compileMode: boolean = true) {
245
246 //console.log("child: ", component.props.children.props);
247
248 var arrConfigs = [];
249 const addToTopLevelConfig = (c) => {
250 //console.log("addToTopLevelConfig: ", c);
251
252 const allowed = ['slsConfig', 'ssrConfig'];
253
254 arrConfigs.push(Object.keys(c)
255 .filter(key => allowed.includes(key))
256 .reduce((obj, key) => {
257 obj[key] = c[key];
258 return obj;
259 }, {})
260 );
261 }
262
263 var arrDataLayers = [];
264 const addDataLayer = (dlComponent) => {
265 arrDataLayers.push(dlComponent);
266 }
267
268 const clientApps= getChildrenArray(component)
269 .map(child => applyCustomComponents(child, addToTopLevelConfig, addDataLayer, compileMode))
270 .filter(child => isClientApp(child))
271 .map(child => applyClientApp(child));
272
273 //console.log("arrConfigs: " , arrConfigs)
274
275 const result = deepmerge.all([{
276 type: ConfigTypes.ISOMORPHIC,
277 isoConfig: {
278 middlewares: parseMiddlewares(component),
279
280 clientApps: clientApps,
281
282 dataLayers: arrDataLayers
283 },
284
285 ssrConfig: {
286 stackName: component.props.stackName,
287 buildPath: component.props.buildPath,
288 assetsPath: component.props.assetsPath,
289 region: component.props.region
290 },
291
292 slsConfig: {}
293 }, ...arrConfigs
294 ]);
295
296 //console.log("loaded IsoConfig: " , result);
297 return result;
298
299}