@salesforce/templates
Version:
Salesforce JS library for templates
209 lines • 8.62 kB
JavaScript
"use strict";
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseGenerator = exports.getDefaultApiVersion = exports.setCustomTemplatesRootPathOrGitRepo = void 0;
const tslib_1 = require("tslib");
const fs = require("fs");
const promises_1 = require("node:fs/promises");
const path = require("path");
const ejs_1 = require("ejs");
const i18n_1 = require("../i18n");
const gitRepoUtils_1 = require("../service/gitRepoUtils");
const constants_1 = require("../utils/constants");
function outputFile(file, data) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const dir = path.dirname(file);
yield (0, promises_1.mkdir)(dir, { recursive: true });
return (0, promises_1.writeFile)(file, data);
});
}
function setCustomTemplatesRootPathOrGitRepo(pathOrRepoUri_1) {
return tslib_1.__awaiter(this, arguments, void 0, function* (pathOrRepoUri, forceLoadingRemoteRepo = false) {
if (pathOrRepoUri === undefined) {
return;
}
try {
// if pathOrRepoUri is valid url, load the repo
const url = new URL(pathOrRepoUri);
if (url) {
return yield (0, gitRepoUtils_1.loadCustomTemplatesGitRepo)(url, forceLoadingRemoteRepo);
}
}
catch (error) {
const err = error;
if (err.code !== 'ERR_INVALID_URL') {
throw error;
}
const localTemplatesPath = pathOrRepoUri;
if (fs.existsSync(localTemplatesPath)) {
return localTemplatesPath;
}
else {
throw new Error(i18n_1.nls.localize('localCustomTemplateDoNotExist', localTemplatesPath));
}
}
});
}
exports.setCustomTemplatesRootPathOrGitRepo = setCustomTemplatesRootPathOrGitRepo;
/**
* Look up package version of @salesforce/templates package to supply a default API version
*/
function getDefaultApiVersion() {
return constants_1.DEFAULT_API_VERSION;
}
exports.getDefaultApiVersion = getDefaultApiVersion;
class NotYeoman {
constructor() {
this.changes = {
created: [],
conflicted: [],
identical: [],
forced: [],
};
this._sourceRoot = this.sourceRoot(path.join(__dirname, '..', 'templates'));
this._destinationRoot = this.destinationRoot(process.cwd());
}
destinationPath(...dest) {
let filepath = path.join(...dest);
if (!path.isAbsolute(filepath)) {
filepath = path.join(this.destinationRoot(), filepath);
}
return filepath;
}
destinationRoot(rootPath) {
if (typeof rootPath === 'string') {
this._destinationRoot = path.resolve(rootPath);
if (!fs.existsSync(this._destinationRoot)) {
fs.mkdirSync(this._destinationRoot, { recursive: true });
}
}
return this._destinationRoot || process.cwd();
}
sourceRoot(rootPath) {
if (rootPath) {
this._sourceRoot = path.resolve(rootPath);
}
return this._sourceRoot;
}
templatePath(...dest) {
let filepath = path.join(...dest);
if (!path.isAbsolute(filepath)) {
filepath = path.join(this.sourceRoot(), filepath);
}
return filepath;
}
render(source, destination, data) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const rendered = yield new Promise((resolve, reject) => {
(0, ejs_1.renderFile)(source, data !== null && data !== void 0 ? data : {}, (err, str) => {
if (err) {
reject(err);
}
return resolve(str);
});
});
if (rendered) {
const relativePath = path.relative(process.cwd(), destination);
const existing = yield (0, promises_1.readFile)(destination, 'utf8').catch(() => null);
if (existing) {
if (rendered.trim() === existing.trim()) {
this.register('identical', relativePath);
return;
}
else {
this.register('conflicted', relativePath);
this.register('forced', relativePath);
}
}
else {
this.register('created', relativePath);
}
yield outputFile(destination, rendered);
}
});
}
register(verb, file) {
this.changes[verb].push(file);
}
}
class BaseGenerator extends NotYeoman {
/**
* The constructor for the SfGenerator.
*
* @param options SfGenerator specific options.
*/
constructor(options) {
var _a, _b;
super();
this.options = options;
this.apiversion = (_a = options.apiversion) !== null && _a !== void 0 ? _a : getDefaultApiVersion();
this.outputdir = (_b = options.outputdir) !== null && _b !== void 0 ? _b : process.cwd();
this.validateOptions();
}
/**
* Set source root to built-in templates or custom templates root if available.
* @param partialPath the relative path from the templates folder to templates root folder.
*/
sourceRootWithPartialPath(partialPath) {
/**
* CAUTION:
* PLEASE make sure the relative path from this function to /templates does NOT change!
* The core VSCode extension bundles /templates separately, so the change of the relative path will make bundling fail!
* Reach out to mingxuanzhang@salesforce.com if unsure.
*/
this.builtInTemplatesRootPath = path.join(__dirname, '..', 'templates', partialPath);
// set generator source directory to custom templates root if available
if (!this.customTemplatesRootPath) {
this.sourceRoot(path.join(this.builtInTemplatesRootPath));
}
else {
if (fs.existsSync(path.join(this.customTemplatesRootPath, partialPath))) {
this.sourceRoot(path.join(this.customTemplatesRootPath, partialPath));
}
}
}
templatePath(...paths) {
// The template paths are relative to the generator's source root
// If we have set a custom template root, the source root should have already been set.
// Otherwise we'll fallback to the built-in templates
const customPath = super.templatePath(...paths);
if (fs.existsSync(customPath)) {
return customPath;
}
else {
// files that are builtin and not in the custom template folder
return super.templatePath(path.join(this.builtInTemplatesRootPath, ...paths));
}
}
run(opts) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
const cwd = (_a = opts === null || opts === void 0 ? void 0 : opts.cwd) !== null && _a !== void 0 ? _a : process.cwd();
this.customTemplatesRootPath = yield setCustomTemplatesRootPathOrGitRepo(opts === null || opts === void 0 ? void 0 : opts.customTemplatesRootPathOrGitRepo);
yield this.generate();
const created = [...this.changes.created, ...this.changes.forced];
const outputDir = path.resolve(cwd, this.outputdir);
const rawOutput = i18n_1.nls.localize('RawOutput', [
outputDir,
[
...((_b = this.changes.created) !== null && _b !== void 0 ? _b : []).map((file) => ` create ${file}`),
...((_c = this.changes.identical) !== null && _c !== void 0 ? _c : []).map((file) => ` identical ${file}`),
...((_d = this.changes.conflicted) !== null && _d !== void 0 ? _d : []).map((file) => ` conflict ${file}`),
...((_e = this.changes.forced) !== null && _e !== void 0 ? _e : []).map((file) => ` force ${file}`),
].join('\n') + '\n',
]);
return {
outputDir,
created,
rawOutput,
};
});
}
}
exports.BaseGenerator = BaseGenerator;
//# sourceMappingURL=baseGenerator.js.map