templates-mo
Version:
Templates is a scaffolding framework that makes code generation simple, dynamic, and reusable. Generate files, parts of your app, or whole project structures—without the repetitive copy-pasting
176 lines (175 loc) • 6.88 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Template = void 0;
const fileSystemTree_1 = require("../fileSystemTree");
const constants_1 = require("../utilities/constants");
const cosmiconfig_1 = require("cosmiconfig");
const template_utils_1 = require("./template-utils");
const File_1 = __importDefault(require("./File"));
const errors_1 = require("../errors");
const logger_1 = __importDefault(require("../utilities/logger"));
const path_1 = __importDefault(require("path"));
const settingsConfig = (0, cosmiconfig_1.cosmiconfig)(constants_1.TEMPLATE_SETTINGS_FILE, {
cache: !constants_1.IS_TESTING,
searchPlaces: [
`${constants_1.TEMPLATE_SETTINGS_FILE}.js`,
`${constants_1.TEMPLATE_SETTINGS_FILE}.json`,
...(0, cosmiconfig_1.getDefaultSearchPlaces)(constants_1.TEMPLATE_SETTINGS_FILE),
],
});
class Template {
/**
* Get a template
*/
static get(templateName) {
return __awaiter(this, void 0, void 0, function* () {
const location = yield Template.fetchTemplateLocation(templateName);
const settingsFile = yield Template.fetchSettingsFile(location);
const template = new Template(templateName, location, settingsFile, {}, []);
yield template.fetchPackage('default');
return template;
});
}
static fetchSettingsFile(location) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
try {
const cosmiResult = yield settingsConfig.search(location);
// we should validate this
return (_a = cosmiResult === null || cosmiResult === void 0 ? void 0 : cosmiResult.config) !== null && _a !== void 0 ? _a : null;
}
catch (e) {
console.log(e);
return null;
}
});
}
static fetchTemplateLocation(templateName) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
if (!templateName || typeof templateName !== 'string') {
throw new errors_1.RequiresTemplateError();
}
const location = (_b = (_a = (0, template_utils_1.findTemplate)(templateName)) !== null && _a !== void 0 ? _a : (0, template_utils_1.findTemplate)(`tps-${templateName}`)) !== null && _b !== void 0 ? _b : null;
if (!location) {
logger_1.default.tps.error('Template not found! \n%O', {
searchedPaths: (0, template_utils_1.getTemplateLocations)(),
});
throw new errors_1.TemplateNotFoundError(templateName);
}
return location;
});
}
constructor(
/**
* Name of template
*/
name,
/**
* The Directory were the template code lives
*/
location,
/**
* Settings file of the template
*/
settingsFile,
/**
* Template's packages. By default all packages arent loaded into memory and only
* packages that are requests are loaded
*/
packages = {},
/**
* Packages used
*/
packagesUsed = [],
/**
* Compiled Files
*/
compiledFiles = [],
/**
* Def files
*/
defs = {}) {
this.name = name;
this.location = location;
this.settingsFile = settingsFile;
this.packages = packages;
this.packagesUsed = packagesUsed;
this.compiledFiles = compiledFiles;
this.defs = defs;
/**
* Extra Relative directories to create in instances
*
* TODO: This is not the best way to do this but at the moment
*/
this.extraDirectories = [];
// do nothing
}
/**
* Fetch packages contents so they can be included in rendered instance.
*/
fetchPackages(newPackages) {
return __awaiter(this, void 0, void 0, function* () {
const isString = typeof newPackages === 'string';
if (!Array.isArray(newPackages) && !isString) {
throw new TypeError('Argument must be a string or an array of stings');
}
const packages = isString ? [newPackages] : newPackages;
yield Promise.all(packages.map((p) => this.fetchPackage(p)));
});
}
/**
* Fetch a package contents so they can be included in rendered instance.
*
* @param newPackage - package from the template you would like to use
*/
fetchPackage(newPackageName) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.location) {
throw new errors_1.RequiresTemplateError();
}
if (!(typeof newPackageName === 'string')) {
throw new TypeError('Argument must be a string');
}
if (newPackageName in this.packages) {
throw new errors_1.PackageAlreadyCompiledError(newPackageName);
}
this.packages[newPackageName] = new fileSystemTree_1.DirNode(newPackageName, this.location);
logger_1.default.tps.info('Loading package %s', newPackageName);
// TODO: implement some sort of compiled files
// this._compileFilesFromPackage(newPackageName);
logger_1.default.tps.success('Added package %s', newPackageName);
});
}
/**
* packages that will be used in the render process
*/
usedPackages() {
return this.packagesUsed.map((pkgName) => this.packages[pkgName]);
}
createFile(file, content, options = {}) {
// TODO: should remove
this.createDirectory(path_1.default.dirname(file));
this.compiledFiles.push(File_1.default.from(file, content, options));
}
/**
* Create a directory in the template. When instances are created these directories
* will be created in the instance
*/
createDirectory(dir) {
this.extraDirectories.push(dir);
}
}
exports.Template = Template;