@acdf/build
Version:
Build dependency for Adobe Campaign Developer Framework projects
142 lines (115 loc) • 4.6 kB
JavaScript
const fs = require("fs");
const { src, dest } = require("gulp");
const gutil = require("gulp-util");
const merge = require("merge-stream");
const modifyFile = require("gulp-modify-file");
const xml = require("xml2js");
const common = require("./common");
const handlebars = require("handlebars");
const path = require("path");
const log = require("gulplog");
const BUILD_INFO = {
ts: new Date().toISOString(),
version: common.PACKAGE_JSON.version,
};
/**
* Traverses the staging directory, registering all files as partials
*
* @param {string} filepath
*/
function registerPartials(filepath) {
if (fs.lstatSync(filepath).isDirectory()) {
// If directory, then skip and process children
fs.readdirSync(filepath).forEach((child) => registerPartials(path.resolve(filepath, child)));
} else {
// If file, then register partial
const partialPath = path.relative(common.paths.dist.absolute.STAGING_DIR, filepath);
log.debug(`Registering partial ${partialPath}`);
handlebars.registerPartial(partialPath, fs.readFileSync(filepath, "utf8"));
}
}
/**
* Reads the package content as string and returns an XML object.
*
* @param {string} filepath the package filepath
* @param {string} content the package content
* @returns xml an XML object representing the package content
*/
function packageXmlAsObject(filepath, content) {
if (!content) {
throw new gutil.PluginError("acdf-build", `Could not parse empty package ${filepath}`);
}
let campaignPackage;
xml.parseString(content, (err, result) => {
if (err) {
throw new gutil.PluginError("acdf-build", `Could not parse package ${filepath}`);
}
campaignPackage = result;
});
return campaignPackage;
}
/**
* Compiles the package files per installation, per environment using the properties exported
* in the environment files.
*
* @returns the gulp stream
*/
function compileTemplates() {
registerPartials(common.paths.dist.absolute.STAGING_DIR);
const envs = common.getEnvs();
// For each environment
const streams = envs.reduce((streams, env) => {
// For each installation
const stream = env.installations.map(installation => {
const release = common.getRelease(installation.name);
return src(release.packageGlobs)
// Compile package templates
.pipe(modifyFile((content, path, file) => {
log.info(`Generating packages file for package: ${file.basename}, installation: ${installation.name}, environment: '${env.name}'`);
return handlebars.compile(content)({
...common.CONFIG,
...installation.properties,
build: BUILD_INFO,
package: {
number: file.basename.slice(0, 3),
},
});
}))
.pipe(
modifyFile((content, filepath) => {
if (path.basename(filepath).includes(".raw")) {
return content
} else {
// Generate CDATA in package XML
return new xml.Builder({ cdata: true }).buildObject(packageXmlAsObject(filepath, content));
}
})
)
// Remove the XML header
.pipe(modifyFile((content) => content.replace(/^<\?xml.*\?>/, "")))
// Send to environment-specific dist folder
.pipe(dest(path.resolve(common.paths.dist.absolute.PACKAGE_DIR, `packages.${installation.name}-${env.name}`)))
});
streams.push(stream);
return streams;
}, []);
return merge(streams)
}
module.exports = {
/**
* Copies the compiled scripts, packages and XML fragments into the staging directory to
* be used as templates and partials.
*
* @returns stream
*/
stagePartialsAndTemplates: () => {
return merge(
src("src/**/*.xml").pipe(dest(common.paths.dist.absolute.STAGING_DIR)),
src(common.GLOB_COMPILED_SCRIPTS)
.pipe(modifyFile((content) => `<![CDATA[${content}]]>`))
.pipe(dest(common.paths.dist.absolute.STAGING_DIR))
);
},
compileTemplates: compileTemplates,
createArtifact: () => common.createArtifact(common.paths.dist.absolute.PACKAGE_DIR)
};