UNPKG

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
"use strict"; 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;