@eui/tools 6.12.29 → 6.12.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,628 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const _ = require('lodash');
5
+
6
+ const tools = require('../../tools');
7
+ const configUtils = require('../../../csdr/config/config-utils');
8
+ const initUtils = require('../../../csdr/init/init-utils');
9
+
10
+ const subs = require('./routes-replacement-subs');
11
+
12
+ const { debug } = tools.getArgs();
13
+
14
+ /**
15
+ *
16
+ * ROUTES REPLACEMENT
17
+ *
18
+ */
19
+
20
+ /**
21
+ * Process routes either for playground local environment OR by envTarget at build time,
22
+ * injects the routesContent generated inside the project/src/app/app.routes.ts file from a base route file and
23
+ * based on definitions in mywp-host-ui/assets/routes folder definitions as data input
24
+ *
25
+ * used by projects pre-build phase
26
+ *
27
+ * PUBLIC
28
+ *
29
+ * @param {project} project The CSDR project object fetched from csdr global projects config
30
+ * @param {string} envTarget The build-time environment target provided to target specific routes for specific environment deployments
31
+ * @param {boolean} build if the script is launched from a release pipeline OR from local CSDR playground environment (false in that case)
32
+ * @returns {Promise} returns a Promise as it involves async I/O processes
33
+ */
34
+ module.exports.buildRoutes = (project, envTarget, build) => {
35
+ tools.logTitle('Starting routes replacement');
36
+
37
+ const envTargetFinal = subs.getEnvTarget(envTarget, build);
38
+
39
+ return Promise.resolve()
40
+ .then(() => {
41
+ // injecting routes json definitions into project assets
42
+ injectRoutesConfig(project);
43
+
44
+ // getting all routes defs to be processed
45
+ const rawRoutesDefs = getRawRoutesDefs(project, envTargetFinal);
46
+
47
+ // getting project routes remapped
48
+ const routes = getProjectRoutes(project, rawRoutesDefs);
49
+
50
+ // generate Angular routes replacement
51
+ generateAngularRoutes(project, routes);
52
+
53
+ // generate feature libs files for lazy loaded playground routes
54
+ generateLazyFeatureLibs(project, routes);
55
+
56
+ // generate remotes-metadata files in Angular host
57
+ generateRemotesMetadata(project, routes);
58
+
59
+ // generate links for sidebar menu entries
60
+ generateLinks(project, routes, envTargetFinal);
61
+ })
62
+
63
+ .then(() => {
64
+ tools.logSuccess();
65
+ })
66
+
67
+ .catch((e) => {
68
+ throw e;
69
+ });
70
+ };
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+ const injectRoutesConfig = (project) => {
79
+
80
+ const npmPkg = project.externalRoutesSources.routesConfigNpmPkg;
81
+
82
+ // check if package is locally cloned
83
+ const localPackage = configUtils.packages.getPackages().filter((p) => {
84
+ return p.npmPkg === npmPkg;
85
+ })[0];
86
+
87
+ let pkgAssetsPath;
88
+
89
+ // if local package is found
90
+ if (localPackage) {
91
+ pkgAssetsPath = path.join(process.cwd(), 'packages', localPackage.name, 'assets');
92
+
93
+ // if not sources are taken from the npm package def in node_modules
94
+ } else {
95
+ const npmPkgScope = npmPkg.substr(0, npmPkg.indexOf('/'));
96
+ const npmPkgName = npmPkg.substr(npmPkg.indexOf('/') + 1);
97
+ pkgAssetsPath = path.join(process.cwd(), 'node_modules', npmPkgScope, npmPkgName, 'assets');
98
+ }
99
+
100
+ if (!tools.isDirExists(pkgAssetsPath)) {
101
+ tools.logWarning(`Linked config pkg : ${npmPkg} cannot be found in node_modules`);
102
+ return;
103
+ }
104
+
105
+ const routesConfigPath = path.join(pkgAssetsPath, project.externalRoutesSources.routesConfigAssetsPath);
106
+
107
+ tools.logInfo(`${routesConfigPath} - injecting in ${project.paths.assetsPath}`);
108
+ tools.copydir(routesConfigPath, project.paths.assetsPath);
109
+ };
110
+
111
+
112
+
113
+
114
+
115
+ const getRawRoutesDefs = (project, envTargetFinal) => {
116
+ // getting generated from input params
117
+ const euiVersion = configUtils.projects.getProjectEuiVersion(project);
118
+ const euiVersionNumber = euiVersion.split('.')[0];
119
+
120
+ tools.logInfo(`Processing for envTarget : ${envTargetFinal}`);
121
+
122
+ // getting the input file definitions of routes for replacements
123
+ // from tokenized template in config -- allowing to control playground vs normal env (when using the MWP HOST for release)
124
+ // format :
125
+ // playground : "routesFilenameTemplate": "route-defs-base-v@eui.version@-playground.json"
126
+ // host : "routesFilenameTemplate": "route-defs.@env.target@.json"
127
+
128
+ let routeDefsInputFilename;
129
+
130
+ if (!project.externalRoutesSources.routesFilenameTemplate) {
131
+ throw 'ROUTES_CONFIG_V2_TEMPLATE_NOT_FOUND';
132
+ }
133
+
134
+ routeDefsInputFilename = project.externalRoutesSources.routesFilenameTemplate.replace('@eui.version@', euiVersionNumber);
135
+ routeDefsInputFilename = routeDefsInputFilename.replace('@env.target@', envTargetFinal);
136
+
137
+ tools.logInfo(`Starting replacement of routes based on generated template : ${routeDefsInputFilename}`);
138
+
139
+ // Getting input routeDefs entry
140
+
141
+ const routeDefsInputPath = path.join(project.paths.assetsPath, routeDefsInputFilename);
142
+
143
+ if (!tools.isFileExists(routeDefsInputPath)) {
144
+ tools.logError(`${routeDefsInputPath} File NOT FOUND`);
145
+ throw 'ROUTE_DEFS_INPUT_FILE_NOT_FOUND';
146
+ }
147
+
148
+ const routeDefsInputJSON = require(path.join(routeDefsInputPath));
149
+
150
+ // Merging content with "local" route file defs if existing
151
+
152
+ let routes = [];
153
+
154
+ if (envTargetFinal.indexOf('local') > -1) {
155
+ const localRouteDefsInputFilename = `route-defs.${envTargetFinal}.json`;
156
+ const localRouteDefsInputPath = path.join(project.paths.assetsPath, localRouteDefsInputFilename);
157
+
158
+ if (tools.isFileExists(localRouteDefsInputPath)) {
159
+ tools.logInfo(`Merging local configuration found : ${localRouteDefsInputFilename}`);
160
+ const localRouteDefsInputJSON = require(path.join(localRouteDefsInputPath));
161
+
162
+ routeDefsInputJSON.forEach((route) => {
163
+ const matchedRoute = localRouteDefsInputJSON.filter(newRoute => newRoute.path === route.path)[0];
164
+ if (matchedRoute) {
165
+ tools.logInfo(`-- replacing ${route.path} route entry with overriden local config`);
166
+ tools.logInfo(`-----> ${JSON.stringify(matchedRoute)}`);
167
+ routes.push(matchedRoute);
168
+ } else {
169
+ routes.push(route);
170
+ }
171
+ });
172
+ }
173
+ } else {
174
+ routes = routeDefsInputJSON;
175
+ }
176
+
177
+ return routes;
178
+ }
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+ const getProjectRoutes = (project, routesDefs) => {
187
+ let projectRoutes = [];
188
+
189
+ const euiVersion = configUtils.projects.getProjectEuiVersion(project);
190
+
191
+ const routeDefsBaseFilename = 'route-defs-base.json';
192
+ const routeDefsBaseJSON = require(path.join(project.paths.assetsPath, routeDefsBaseFilename));
193
+
194
+ routesDefs.forEach((route) => {
195
+ tools.logInfo(`Processing route : `);
196
+ console.log(route);
197
+
198
+ // checking if current route being processed exists in the the base routes defs
199
+ const defRoute = routeDefsBaseJSON.filter((r) => r.path === route.path)[0];
200
+
201
+ if (!defRoute) {
202
+ tools.logError('route not found for: ');
203
+ console.log(route);
204
+ throw 'ROUTE_NOT_FOUND';
205
+
206
+ } else {
207
+ let loadChildrenGenerated;
208
+ let lazyLibDef = null;
209
+
210
+ // in case of a lazy route, the route is generated from a import/export feature lib module TS file
211
+ // those files are also generated based on the route "lazyDefs" data definition
212
+
213
+ if (route.lazy) {
214
+ const scopeName = defRoute.lazyLoadDef.npmPkg.split('/')[0].substr(1);
215
+ const pkgName = defRoute.lazyLoadDef.npmPkg.split('/')[1];
216
+ const lazyFeatureLibName = `${scopeName}-${pkgName}-${defRoute.lazyLoadDef.moduleName}.lib.module`;
217
+
218
+ if (euiVersion === '10.x') {
219
+ loadChildrenGenerated = `loadChildren: "./features/${lazyFeatureLibName}#Module"`;
220
+ } else {
221
+ loadChildrenGenerated = `loadChildren: () => import("./features/${lazyFeatureLibName}").then(m => m.Module)`;
222
+ }
223
+
224
+ lazyLibDef = {
225
+ filename: `${lazyFeatureLibName}.ts`,
226
+ npmPkg: defRoute.lazyLoadDef.npmPkg,
227
+ moduleName: defRoute.lazyLoadDef.moduleName,
228
+ };
229
+
230
+ // if the route is a remote, the elementLoader is then used as a default feature module loaded
231
+ } else {
232
+ if (euiVersion === '10.x') {
233
+ loadChildrenGenerated = 'loadChildren: "./features/element-loader.module#ElementLoaderModule"';
234
+ } else {
235
+ loadChildrenGenerated = 'loadChildren: () => import("./features/element-loader.module").then(m => m.ElementLoaderModule)';
236
+ }
237
+ }
238
+
239
+ // we define the route item definition, that will be injected in the project app.routes source
240
+ const newAppRoute = {
241
+ lazyLibDef: lazyLibDef,
242
+ angularRouteDef: {
243
+ path: defRoute.path,
244
+ loadChildren: loadChildrenGenerated,
245
+ data: {},
246
+ },
247
+ remote: false,
248
+ remoteDef: null,
249
+ };
250
+
251
+ // in the case the route is auth guarded, we attach the defition of the auth parameters
252
+ if (defRoute.authMetadata) {
253
+ newAppRoute.angularRouteDef.data.id = defRoute.authMetadata.id;
254
+ newAppRoute.angularRouteDef.data.ids = defRoute.authMetadata.ids;
255
+ newAppRoute.angularRouteDef.canActivate = defRoute.authMetadata.canActivate;
256
+ }
257
+
258
+ // in case of a remote, the "remoteDefs" data entry are processed
259
+ // in case no remote corresponds to a remote path defined in the definitions, we throw an error and we stop the
260
+ // script to avoid bad route data / or partial routes data generated
261
+ if (route.remote) {
262
+ let remoteDef;
263
+
264
+ try {
265
+ remoteDef = defRoute.remoteDefs.filter((r) => {
266
+ return r.euiVersion === route.euiVersion;
267
+ })[0];
268
+
269
+ } catch {
270
+ tools.logError('Remote route not found for: ');
271
+ console.log(route);
272
+ throw 'REMOTE_ROUTE_DEF_NOT_FOUND';
273
+ }
274
+
275
+ if (remoteDef) {
276
+ newAppRoute.angularRouteDef.data.moduleId = remoteDef.moduleId;
277
+ newAppRoute.angularRouteDef.data.elementTag = remoteDef.elementTag;
278
+ newAppRoute.angularRouteDef.data.iframe = remoteDef.iframe;
279
+ newAppRoute.remote = true;
280
+ newAppRoute.remoteDef = remoteDef;
281
+
282
+ } else {
283
+ tools.logError('Remote route not found for: ');
284
+ console.log(route);
285
+ throw 'REMOTE_ROUTE_DEF_NOT_FOUND';
286
+ }
287
+ }
288
+
289
+ projectRoutes.push(newAppRoute);
290
+ }
291
+ });
292
+
293
+ return projectRoutes;
294
+ }
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+ const generateAngularRoutes = (project, routes) => {
304
+ tools.logInfo('Processing routes replacement');
305
+
306
+ const replaceRoute = (route) => {
307
+ let routeContent = '{\n';
308
+
309
+ routeContent += ` path: '${route.path}',\n`;
310
+ if (Object.keys(route.data).length > 0) {
311
+ routeContent += ' data: {\n';
312
+
313
+ if (route.data.id) {
314
+ routeContent += ` id: '${route.data.id}',\n`;
315
+ }
316
+ if (route.data.ids) {
317
+ routeContent += ` ids: ${route.data.ids},\n`;
318
+ }
319
+ if (route.data.featureName) {
320
+ routeContent += ` featureName: '${route.data.featureName}',\n`;
321
+ }
322
+ if (route.data.moduleId) {
323
+ routeContent += ` moduleId: '${route.data.moduleId}',\n`;
324
+ }
325
+ if (route.data.elementTag) {
326
+ routeContent += ` elementTag: '${route.data.elementTag}',\n`;
327
+ }
328
+ if (route.data.iframe) {
329
+ routeContent += ` iframe: ${route.data.iframe},\n`;
330
+ }
331
+ routeContent += ' },\n';
332
+ }
333
+ if (route.canActivate) {
334
+ routeContent += ` canActivate: ${route.canActivate},\n`;
335
+ }
336
+ if (route.loadChildren) {
337
+ routeContent += ` ${route.loadChildren},\n`;
338
+ }
339
+ routeContent += '},\n\n';
340
+
341
+ return routeContent;
342
+ };
343
+
344
+
345
+ const euiVersion = configUtils.projects.getProjectEuiVersion(project);
346
+
347
+ // getting routes file to replace (from /src/app host side)
348
+ const routesFile = subs.getRoutesFile(project, euiVersion);
349
+ if (!routesFile) {
350
+ throw 'ROUTES_FILE_NOT_FOUND';
351
+ }
352
+ let routesFileContent = tools.getFileContent(routesFile);
353
+
354
+ // replacing the placeholder content of the source routes file with the routes generated
355
+ let placeHolderContent = '';
356
+
357
+ routes.forEach((route) => {
358
+ placeHolderContent += replaceRoute(route.angularRouteDef);
359
+ });
360
+
361
+ const placeHolderToken = '// routes-placeholder';
362
+ routesFileContent = tools.replaceAll(routesFileContent, placeHolderToken, placeHolderContent);
363
+
364
+ if (debug) {
365
+ tools.logInfo('Routes file content replaced : ');
366
+ console.log(routesFileContent);
367
+ }
368
+
369
+ // writing final routes content into project sources
370
+ tools.writeFileContent(routesFile, routesFileContent);
371
+ }
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+ const generateLazyFeatureLibs = (project, routes) => {
381
+ tools.logInfo('Processing creation of features lib modules entries');
382
+
383
+ const appFeatureLibs = routes.filter(r => r.lazyLibDef !== null);
384
+
385
+ appFeatureLibs.forEach((r) => {
386
+ const featureLibPath = path.join(process.cwd(), project.folder, 'src', 'app', 'features', r.lazyLibDef.filename);
387
+
388
+ const featureLibDef = `
389
+ import { NgModule } from '@angular/core';
390
+ import { ${r.lazyLibDef.moduleName} as LibModule } from '${r.lazyLibDef.npmPkg}';
391
+
392
+ @NgModule({
393
+ imports: [LibModule],
394
+ exports: [LibModule],
395
+ })
396
+ export class Module {
397
+ }
398
+ `;
399
+
400
+ tools.logInfo(`Creating lazy feature lib module : ${r.lazyLibDef.filename}`);
401
+
402
+ tools.writeFileContent(featureLibPath, featureLibDef);
403
+ });
404
+ }
405
+
406
+
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+ const generateLinks = (project, routes, envTargetFinal) => {
415
+ tools.logInfo('Processing links generation');
416
+
417
+ const routeDefsBaseLinksFileName = 'route-defs-base-links.json';
418
+ const routeDefsBaseLinksJSON = require(path.join(project.paths.assetsPath, routeDefsBaseLinksFileName));
419
+ const routeDefsBaseFilename = 'route-defs-base.json';
420
+ const routeDefsBaseJSON = require(path.join(project.paths.assetsPath, routeDefsBaseFilename));
421
+
422
+ const getRouteMenuDef = (link) => {
423
+ let routeDef = null;
424
+
425
+ if (link.url) {
426
+ routeDefsBaseJSON.forEach((r) => {
427
+ if (r.menuLinkDefs && r.menuLinkDefs.length > 0) {
428
+ r.menuLinkDefs.forEach((md) => {
429
+ if (md.url === link.url) {
430
+ routeDef = md;
431
+ routeDef.path = r.path;
432
+ if (link.id) {
433
+ routeDef.id = link.id;
434
+ }
435
+ if (link.optional) {
436
+ routeDef.optional = link.optional;
437
+ }
438
+ if (link.workspace) {
439
+ routeDef.workspace = link.workspace;
440
+ }
441
+ if (link.dashboardWidgetDisabled) {
442
+ routeDef.dashboardWidgetDisabled = link.dashboardWidgetDisabled;
443
+ }
444
+ if (link.alwaysDisplayed) {
445
+ routeDef.alwaysDisplayed = link.alwaysDisplayed;
446
+ }
447
+
448
+ return;
449
+ }
450
+ });
451
+ }
452
+ });
453
+ }
454
+
455
+ return routeDef;
456
+ };
457
+
458
+ // inner method for checking based on the "allowedEnvs" option provided on the links definition if the link has to be added
459
+ // to the links list
460
+
461
+ const isLinkAllowed = (link) => {
462
+ // allow all link for playground - local env
463
+ if (envTargetFinal.indexOf('local') > -1) {
464
+ return true;
465
+ }
466
+
467
+ // checking if current envTarget generated is allowed
468
+ if (link.allowedEnvs) {
469
+ if (link.allowedEnvs.includes(envTargetFinal)) {
470
+ return true;
471
+ } else {
472
+ return false;
473
+ }
474
+ } else {
475
+ return true;
476
+ }
477
+ };
478
+
479
+ // processing each link and matching route from routes base data definitions
480
+
481
+ const linksGenerated = [];
482
+
483
+ routeDefsBaseLinksJSON.forEach((link) => {
484
+ let newLink = null;
485
+
486
+ if (link.parentId) {
487
+ if (isLinkAllowed(link)) {
488
+ newLink = { ...link };
489
+ newLink.children = [];
490
+
491
+ link.children.forEach((subLink) => {
492
+ if (isLinkAllowed(subLink)) {
493
+ const defRoute = getRouteMenuDef(subLink);
494
+
495
+ if (defRoute) {
496
+ if (project.externalRoutesSources.routesFilenameTemplate.indexOf('playground') > 0) {
497
+ const routePathInInputRoutes = routes.filter(r => r.angularRouteDef.path === defRoute.path)[0];
498
+
499
+ if (!routePathInInputRoutes) {
500
+ defRoute.disabled = true;
501
+
502
+ } else {
503
+ tools.logInfo(`[${defRoute.url}] --> route found in input routes - enabled`);
504
+ }
505
+ }
506
+ newLink.children.push(defRoute);
507
+ }
508
+ }
509
+ });
510
+ }
511
+ } else {
512
+ if (isLinkAllowed(link)) {
513
+ const defRoute = getRouteMenuDef(link);
514
+
515
+ if (defRoute) {
516
+ if (project.externalRoutesSources.routesFilenameTemplate.indexOf('playground') > 0) {
517
+ const routePathInInputRoutes = routes.filter(r => r.angularRouteDef.path === defRoute.path)[0];
518
+
519
+ if (!routePathInInputRoutes) {
520
+ defRoute.disabled = true;
521
+ } else {
522
+ tools.logInfo(`[${defRoute.url}] --> route found in input routes - enabled`);
523
+ }
524
+ }
525
+ newLink = {...defRoute};
526
+ } else {
527
+ newLink = {...link};
528
+ }
529
+ }
530
+ }
531
+
532
+ if (newLink) {
533
+ linksGenerated.push(newLink);
534
+ }
535
+ });
536
+
537
+ // if (debug) {
538
+ // console.log('Links generated');
539
+ // console.log(linksGenerated);
540
+ // }
541
+
542
+ tools.logInfo(`Links generated : ${linksGenerated.length} found`);
543
+
544
+ tools.writeJsonFileSync(path.join(project.paths.assetsPath, 'route-defs-links.json'), linksGenerated);
545
+ }
546
+
547
+
548
+
549
+
550
+
551
+
552
+ const generateRemotesMetadata = (project, routes) => {
553
+ const finalRemotesDefs = routes.filter(r => r.remote).map(r => r.remoteDef.moduleId);
554
+
555
+ if (finalRemotesDefs.length > 0) {
556
+ const finalRemotesDefsFile = path.join(project.paths.assetsPath, 'remotes-metadata.json');
557
+
558
+ tools.logInfo(`Generating ${finalRemotesDefsFile}`);
559
+
560
+ tools.writeJsonFileSync(finalRemotesDefsFile, finalRemotesDefs);
561
+ }
562
+ }
563
+
564
+
565
+
566
+
567
+ module.exports.extractRemotesMetadata = (project) => {
568
+ tools.logTitle('Extracting remotes-metadata.json for known participant remotes');
569
+
570
+ const openidConfigFile = path.join(project.paths.assetsPath, 'openid-login-config.json');
571
+ const finalRemotesDefsFile = path.join(project.paths.assetsPath, 'remotes-metadata.json');
572
+
573
+ if (!tools.isFileExists(finalRemotesDefsFile)) {
574
+ tools.logInfo('...remotes-metadata.json not found / not previously generated ... skipping');
575
+ return;
576
+ }
577
+
578
+ return Promise.resolve()
579
+ .then(() => {
580
+ return initUtils.remotes.cloneRemotesConfig();
581
+ })
582
+
583
+ .then(() => {
584
+ let remoteMetadataJSON = tools.getJsonFileContent(finalRemotesDefsFile);
585
+ const openidConfigJSON = tools.getJsonFileContent(openidConfigFile);
586
+
587
+ remoteMetadataJSON.forEach((r) => {
588
+ tools.logInfo(`Fetching remote info for : ${r}`);
589
+
590
+ let remote;
591
+ if (configUtils.remotes.isVirtualRemote(r)) {
592
+ remote = configUtils.remotes.getRemote(r);
593
+ } else {
594
+ remote = configUtils.packages.getPackage(r, true, true);
595
+ }
596
+
597
+ if (remote && remote.build && remote.build.hasParticipants) {
598
+ let participantsList;
599
+ if (remote.euiVersion === '15.x') {
600
+ participantsList = openidConfigJSON.modules[remote.build.configModuleName].participants_v15
601
+ } else {
602
+ participantsList = openidConfigJSON.modules[remote.build.configModuleName].participants
603
+ }
604
+ if (participantsList) {
605
+ let participantRemotes = [];
606
+ Object.keys(participantsList).forEach((p) => {
607
+ participantRemotes.push(participantsList[p].moduleId);
608
+ });
609
+ tools.logInfo('Found participant remotes : ');
610
+ console.log(participantRemotes);
611
+
612
+ remoteMetadataJSON = [...remoteMetadataJSON, ...participantRemotes];
613
+ }
614
+ }
615
+ })
616
+
617
+ remoteMetadataJSON = tools.removeArrayDuplicates(remoteMetadataJSON);
618
+
619
+ tools.logInfo('Final remotes metadata list found :');
620
+ console.log(remoteMetadataJSON);
621
+
622
+ return tools.writeJsonFileSync(finalRemotesDefsFile, remoteMetadataJSON);
623
+ })
624
+
625
+ .catch((e) => {
626
+ throw e;
627
+ });
628
+ }