@communities-webruntime/services
Version:
If you would like to run Lightning Web Runtime without the CLI, we expose some of our programmatic APIs available in Node.js. If you're looking for the CLI documentation [you can find that here](https://www.npmjs.com/package/@communities-webruntime/cli).
232 lines • 7.99 kB
JavaScript
;
/**
* Copyright (c) 2019, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetadataService = void 0;
const crypto_1 = __importDefault(require("crypto"));
const fs_1 = require("fs");
const path_1 = require("path");
const uuid_parse_1 = require("uuid-parse");
const context_service_1 = require("../context/context-service");
const files_1 = require("../utils/files");
const tree_1 = require("../utils/tree");
const assert_1 = require("../utils/assert");
const metadata_validation_1 = require("./metadata-validation");
const process_branding_1 = require("./process-branding");
const { getContext } = context_service_1.ContextService;
/**
* Get all the context template routes
*/
function getRoutes() {
const { routes } = getContext();
if (typeof routes === 'object') {
return routes;
}
return files_1.readJsonFile(routes);
}
/**
* Get the context template theme
*/
function getTheme() {
const { theme } = getContext();
if (typeof theme === 'object') {
return theme;
}
return files_1.readJsonFile(theme);
}
/**
* Get all the context template labels
*/
function getLabels() {
const { labels } = getContext();
if (typeof labels === 'object') {
return labels;
}
return (labels && files_1.readJsonFile(labels)) || {};
}
/**
* Get all the context template locales
*/
function getLocales() {
const { locales } = getContext();
if (typeof locales === 'object') {
return locales;
}
return locales && fs_1.existsSync(locales) ? files_1.readJsonFile(locales) : [];
}
/**
* Get all the context template branding properties
*/
function getBrandingProperties() {
const { theme: themeConfig } = getContext();
let brandingProperties;
const theme = getTheme();
if (typeof themeConfig === 'object') {
brandingProperties = (theme && theme.branding) || [];
}
else {
const dir = path_1.dirname(themeConfig);
brandingProperties =
(theme && theme.branding && files_1.readJsonFile(`${dir}/${theme.branding}`)) || [];
}
return brandingProperties;
}
function getBrandingTokenMap() {
return process_branding_1.getBrandingTokenMap(getBrandingProperties());
}
/**
* Compute components and regions uuids for design mode.
*
* Ids are a hash of the concatenation of the view name
* and the cmp/region (deep) string representation.
*
* The resulting 128 bits hash is unparsed as a UUID.
*
* The view is mutated in place.
*
* @param {object} view the view to add uuids to
* @returns {object} the mutated view
*/
function updateViewWithUuids(view) {
// compute a uuid for a given region or component
function uuid(node) {
return uuid_parse_1.unparse(crypto_1.default
.createHash('md5')
.update(`${view.devName}:${JSON.stringify(node, (key, value) => {
// filter out uuid and region properties cause they would impact the hash
return ['uuid', 'region'].includes(key) ? undefined : value;
})}`)
.digest());
}
// update a region recursively
function updateRegionWithUuids(region) {
// First, generate region key
region.uuid = region.key ? region.key : uuid(region);
if (region.components) {
region.components.forEach((cmp) => {
cmp.region = region.slotName;
if (cmp.regions) {
// recursively generate keys for each inner component region
cmp.regions.forEach(updateRegionWithUuids);
}
// generate a key for the component itself
cmp.uuid = uuid(cmp);
});
}
}
// if the view has a corresponding component and this component has inner regions, generate
// keys for each region
if (view.component && view.component.regions) {
view.component.regions.forEach(updateRegionWithUuids);
}
return view;
}
function getView(devName) {
const { views, isDesignMode } = getContext();
const view = typeof views === 'object' ? views[devName] : files_1.readJsonFile(`${views}/${devName}.json`);
assert_1.assert(view, `Cannot find view '${devName}'`);
// Compute components and regions ids for design mode.
// Ids are a hash of the concatenation of the view name
// and the cmp/region (deep) string representation
if (isDesignMode) {
return updateViewWithUuids(view);
}
return view;
}
function getAllViews(routes = getRoutes(), theme = getTheme()) {
// using `[].concat(routes)` allows the caller to pass either a single route (the current route for example)
// or an array of routes
const routesArr = [].concat(routes || []);
// get all route views
const routeViewDevNames = routesArr.filter((route) => route.view).map((route) => route.view);
const routeViews = routeViewDevNames.map(getView);
// get all the theme layout views
const themeLayoutViewDevNames = routeViews
.filter((view) => view.themeLayoutType)
.map((view) => view.themeLayoutType)
.filter((themeLayoutType) => {
return theme.themeLayouts[themeLayoutType] && theme.themeLayouts[themeLayoutType].view;
})
.map((themeLayoutType) => theme.themeLayouts[themeLayoutType].view);
// filter out unique views
const allUniqueViewIds = [...new Set(routeViewDevNames.concat(themeLayoutViewDevNames))];
return allUniqueViewIds.map(getView);
}
/**
* Get all the HTML partials from the template's partials folder.
* Result is in format of `{[fileNameWithoutExtension] : stringContentOfFile }`
*/
function getPartials() {
const extension = '.html';
const { partials } = getContext();
if (typeof partials === 'object') {
return partials;
}
const fileMap = files_1.readFolder(partials, extension);
return Object.keys(fileMap).reduce((result, key) => {
result[key.slice(0, -extension.length)] = fileMap[key];
return result;
}, {});
}
/**
* Get all views which are routed
*/
function getViewToThemeLayoutMap() {
const viewToThemeLayoutMap = {};
const theme = getTheme();
getRoutes().forEach((route) => {
const view = getView(route.view);
const themeLayout = theme.themeLayouts[view.themeLayoutType];
viewToThemeLayoutMap[route.view] = themeLayout.view;
});
return viewToThemeLayoutMap;
}
function validate(schema = 'communities') {
return metadata_validation_1.validate({
routes: getRoutes(),
labels: getLabels(),
locales: getLocales(),
brandingProperties: getBrandingProperties(),
theme: getTheme(),
views: getAllViews(),
partials: getPartials(),
}, schema);
}
/**
* Returns the component with the given UUID among all the views.
*
* This is only available in design mode.
*
* @param uuid the UUID of the component to find
* @returns the component, or `undefined` if the component cannot be found
* @throws an error is not in design mode
*/
function getComponent(uuid) {
const { isDesignMode } = getContext();
assert_1.assert(isDesignMode, 'Can only get components by UUIDs in design mode');
return getAllViews().reduce((c, view) => {
return c || tree_1.findInTree(view, (cmp) => cmp && cmp.uuid === uuid);
}, undefined);
}
exports.MetadataService = {
getRoutes,
getTheme,
getBrandingProperties,
getBrandingTokenMap,
getComponent,
getLabels,
getLocales,
getView,
getViewToThemeLayoutMap,
getAllViews,
getPartials,
validate,
};
//# sourceMappingURL=metadata-service.js.map