UNPKG

europa-build

Version:

Tool for generating and maintaining Europa plugins and presets

145 lines 7.26 kB
"use strict"; /* * Copyright (C) 2022 neocotic * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MustacheTemplateGenerator = void 0; const promises_1 = require("fs/promises"); const mkdirp = require("mkdirp"); const Mustache = require("mustache"); const os_1 = require("os"); const path_1 = require("path"); const PackageInfo_1 = require("../PackageInfo"); const _logger = Symbol(); const _partials = Symbol(); const _provider = Symbol(); /** * A {@link TemplateGenerator} implementation that uses Mustache to render templates. */ class MustacheTemplateGenerator { /** * Creates an instance of {@link MustacheTemplateGenerator} using the `options` provided. * * @param options - The options to be used. */ constructor(options) { this[_logger] = options.parentLogger.child({ name: 'MustacheTemplateGenerator' }); this[_provider] = options.provider; } async generate(context, directory) { const targetDirectory = (0, path_1.join)(directory, context.name); this[_logger].info(`Generating ${this[_provider].getType()} package '${context.name}' in directory: ${targetDirectory}`); await MustacheTemplateGenerator.verifyDirectoryEmptyOrNotExists(targetDirectory); await mkdirp(targetDirectory); for (const templateDirectory of this[_provider].getDirectories()) { await this.generateDirectory(context, targetDirectory, templateDirectory); } this[_logger].info(`Generated ${this[_provider].getType()} package: ${targetDirectory}@${context.version}`); } static formatOutput(output, fileExtension) { if (fileExtension === '.json') { return JSON.stringify(JSON.parse(output), undefined, ' ') + os_1.EOL; } return output; } async generateDirectory(context, targetDirectory, directory) { const templatePath = await this.getTemplatePath(directory); const entries = await (0, promises_1.readdir)(templatePath, { withFileTypes: true }); for (const entry of entries) { await this.generateEntry(context, targetDirectory, directory, '', entry); } } async generateEntry(context, targetDirectory, directory, subDirectoryPath, entry) { const templatePath = await this.getTemplatePath(directory, subDirectoryPath, entry.name); if (entry.isDirectory()) { const targetPath = MustacheTemplateGenerator.getTargetPath(targetDirectory, subDirectoryPath, entry.name); this[_logger].info(`Generating ${this[_provider].getType()} package sub-directory: ${targetPath}`); await mkdirp(targetPath); const subEntries = await (0, promises_1.readdir)(templatePath, { withFileTypes: true }); for (const subEntry of subEntries) { await this.generateEntry(context, targetDirectory, directory, (0, path_1.join)(subDirectoryPath, entry.name), subEntry); } } else if (entry.isFile()) { const targetPath = MustacheTemplateGenerator.getTargetPathExcludingExtension(targetDirectory, subDirectoryPath, entry.name); this[_logger].info(`Generating ${this[_provider].getType()} package template file: ${targetPath}`); const template = await (0, promises_1.readFile)(templatePath, 'utf8'); // eslint-disable-next-line import/namespace const templateOutput = Mustache.render(template, context, await this.getPartials()); const output = MustacheTemplateGenerator.formatOutput(templateOutput, (0, path_1.extname)(targetPath)); await (0, promises_1.writeFile)(targetPath, output, 'utf8'); } else { throw new Error(`Unexpected template entry: ${templatePath}`); } } async getPartials() { const cachedPartials = this[_partials]; if (cachedPartials) { return cachedPartials; } const partialDirectoryPath = await this.getTemplatePath('.partial'); this[_logger].debug(`Loading ${this[_provider].getType()} package template partials from directory: ${partialDirectoryPath}`); const partials = {}; const entries = await (0, promises_1.readdir)(partialDirectoryPath, { withFileTypes: true }); for (const entry of entries) { const partialName = (0, path_1.basename)(entry.name, (0, path_1.extname)(entry.name)); const partialPath = (0, path_1.join)(partialDirectoryPath, entry.name); if (!entry.isFile()) { throw new Error(`Unexpected partial entry: ${partialPath}`); } partials[partialName] = await (0, promises_1.readFile)(partialPath, 'utf8'); } this[_partials] = partials; return partials; } async getTemplatePath(directory, ...paths) { const packageInfo = await PackageInfo_1.PackageInfo.getSingleton(); const providerType = this[_provider].getType(); return (0, path_1.resolve)(packageInfo.directoryPath, 'templates', providerType, directory, ...paths); } static getTargetPath(targetDirectory, ...paths) { return (0, path_1.resolve)(targetDirectory, ...paths); } static getTargetPathExcludingExtension(targetDirectory, ...paths) { const targetPath = MustacheTemplateGenerator.getTargetPath(targetDirectory, ...paths); const targetDirectoryPath = (0, path_1.dirname)(targetPath); const targetFileName = (0, path_1.basename)(targetPath, (0, path_1.extname)(targetPath)); return (0, path_1.join)(targetDirectoryPath, targetFileName); } static async verifyDirectoryEmptyOrNotExists(directoryPath) { let stats; try { stats = await (0, promises_1.stat)(directoryPath); } catch (e) { if (e.code === 'ENOENT') { return; } throw e; } if (!stats.isDirectory()) { throw new Error(`Invalid directory: ${directoryPath}`); } } } exports.MustacheTemplateGenerator = MustacheTemplateGenerator; //# sourceMappingURL=MustacheTemplateGenerator.js.map