@tangelo/tangelo-configuration-toolkit
Version:
Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.
178 lines (151 loc) • 7.59 kB
JavaScript
const fs = require('fs-extra');
const globby = require('globby');
const path = require('path');
const SaxonJS = require('saxon-js');
const spConfigPath = 'build/oxygen/stylesheetPaths.json';
const sefFilePath = 'build/oxygen/createProjectFile.sef.json';
const cmscustomPath = 'config/cmscustom/';
const siteStylesheetsPath = 'config/txp/site-stylesheets/';
const masterFiles = new Set;
const transformationScenarios = [];
let spConfig, sefFile;
const convertToValidFilename = string => string.replace(/[/|\\:*?"<>]/g, ' ');
const createProjectFile = (config, newXprFile) => {
_info('Initializing xpr file(s):');
const xprFiles = [...globby.sync(`*.xpr`)];
// Add newXprFile at the start of xprFiles if it does not already exists:
if (newXprFile && xprFiles.indexOf(newXprFile)===-1) xprFiles.unshift(newXprFile);
// Copy xpr file from TDI if it does not exists yet;
if (xprFiles[0] && !newXprFile) _write(`Found: ${xprFiles.join(', ')}`);
else {
if (!newXprFile) {
// Set xpr filename to customer name (assumes correct upsert scripts structure)
const customers = new Set;
_repoconfig.forEach(p => customers.add(p.customer_name));
xprFiles.push(convertToValidFilename([...customers].join(' - ')) + '.xpr');
}
// Copy new xpr file
fs.copySync(path.join(_paths.repo, 'tangelo-default-implementation/src/[customer].xpr'), path.join(_paths.repo, xprFiles[0]));
_write(`Created: '${xprFiles[0]}'`);
}
// Search for transformationScenarios/masterfiles based on TDI submodule oxygenProjectFile config
_info('\nSearching for transformationScenarios/masterfiles');
config.oxygenProjectFile.forEach(
pf => {
// Collect transformation scenarios and add them to the transformationScenarios array; add individual stylesheets to the masterFiles set.
if (pf.transformation) getTransformations(pf.transformation);
// Add files to the masterfiles set.
else if (pf.masterfile) getMasterfiles(pf.masterfile);
}
);
// update all .xpr files with collected transformation scenarios and masterfiles.
transformXprFile(xprFiles);
};
const getTransformations = config => {
_repoconfig.forEach(rc => {
// get pathname of customer/project
const [customerPath, projectPath] = config.location === 'database' ? rc.path_dbconfig : rc.path_cmscustom;
// set pathname of customer/project in location glob-expression
const location = path.join(
_paths.repo,
config.files.replace(/\[customer\]/, customerPath).replace(/\[project\]/, projectPath)
);
globby
.sync(`${location}`)
.forEach(f => {
// extract baseStrings from file
const fileString = fs.readFileSync(f).toString();
const baseStrings = fileString.match(RegExp(config.extracts.base, 'gm'));
if (fileString.replace(/\s|^prompt\s.*$/gm, '') !== '') {
if (baseStrings) {
baseStrings.forEach(s => {
// extract type, name, files info from baseString
const type = config.extracts.type ? s.match(RegExp(config.extracts.type))[1] : config.values.type;
const name = config.extracts.name ? s.match(RegExp(config.extracts.name))[1] : config.values.name;
const files = s.match(RegExp(config.extracts.files))[1];
// Add transformation scenario to the transformationScenario array
transformationScenarios.push({
name: `${type}: ${name} (${rc.customer_name}, ${rc.project_name})`, // note that in createProjectFile.xsl a regex is added that matches scenarios based on this name. This to preserve manually added scenarios.
transformationScenario: files,
location: config.location === 'txp' ? siteStylesheetsPath : cmscustomPath
});
// Add each non-tdi stylesheet in transformation scenario to the masterFiles set
files.split(',').forEach(f => {
const filePath = `${config.location === 'txp' ? siteStylesheetsPath : cmscustomPath}${f}`;
if (!f.startsWith('tdi')) masterFiles.add(filePath);
});
});
} else {
_write(`No transformation scenarios found in ${f} for '${config.extracts.base}'`);
}
}
});
});
};
const getMasterfiles = config => {
globby
.sync(`${path.join(_paths.repo, config.files)}`)
.forEach(cf => {
// Check if masterfile should be extracted from file
const fileString = fs.readFileSync(cf).toString();
if (fileString.replace(/\s|^prompt\s.*$/gm, '')!=='') {
if (config.extracts) {
// extract baseStrings from file
const baseStrings = fileString.match(RegExp(config.extracts.base, 'gm'));
if (baseStrings) {
baseStrings.forEach(s => {
// extract (comma-separated) list of masterfiles
const filesString = s.match(RegExp(config.extracts.files))[1];
if (!filesString) _error(`No masterfiles found in '${s}' for '${config.extracts.files}'`);
// Add each non-tdi masterfile to the masterFiles set
filesString.split(',').forEach(f => {
if (!f.startsWith('tdi')){
const filePath = `${config.location === 'txp' ? siteStylesheetsPath : cmscustomPath}${f}`;
masterFiles.add(filePath);
}
});
});
} else {
_write(`No masterfiles found in ${cf} for '${config.extracts.base}'`);
}
} else { // Add synced file to masterfiles; strip path from c:/... hence it starts with config/cmscustom or config/txp/site-stylesheets
const filePath = config.location === 'txp' ? `${siteStylesheetsPath}${cf.split(siteStylesheetsPath)[1]}` : `${cmscustomPath}${cf.split(cmscustomPath)[1]}`;
masterFiles.add(filePath);
}
}
});
};
const transformXprFile = xprFiles => {
_info('\nUpdating xpr file(s):');
// create with: xslt3 -t -xsl:createProjectFile.xsl -export:createProjectFile.sef.json v -nogo'
xprFiles
.forEach(xprFile => {
// Transform xpr; add masterfiles and transformationScenarios as parameters of the stylesheet
_write(`${xprFile}\n`);
SaxonJS.transform({
stylesheetText: JSON.stringify(sefFile),
stylesheetBaseURI: 'createProjectFile.sef.json',
sourceFileName: path.join(_paths.repo, xprFile),
destination: 'serialized',
stylesheetParams: {
'masterfiles': [...masterFiles],
'Q{}transformationScenarios': transformationScenarios
}
}, 'async')
.then(output => {
// Write result of transformation to xpr file
fs.writeFileSync(path.join(_paths.repo, xprFile), output.principalResult);
})
.catch(e => _warn(`Failed to update: ${xprFile}\n ${e}`));
});
};
module.exports = function oxygen (arg) {
// Set projects transformation scenarios and masterfiles in oXygen project file
// - Will try to preserve manually added entries in the transformation scenarios and masterfiles
// - Will remove non existing masterfiles or masterfiles that start with a '_'
spConfig = _modulesTdi.require(spConfigPath);
sefFile = _modulesTdi.require(sefFilePath);
if (!spConfig || !sefFile) _error(`Cannot find required files in TDI submodule. Try updating TDI submodule.`);
const newXprFile = (typeof arg === 'string') ? convertToValidFilename(arg) + '.xpr' : null;
createProjectFile(spConfig, newXprFile);
};