UNPKG

@tsed/cli

Version:
163 lines (162 loc) 6 kB
import { __decorate } from "tslib"; import "../utils/hbs/index.js"; import { basename, dirname, join, relative } from "node:path"; import { CliFs } from "@tsed/cli-core"; import { isString } from "@tsed/core"; import { constant, inject, Injectable } from "@tsed/di"; import { normalizePath } from "@tsed/normalize-path"; import Consolidate from "consolidate"; import fs from "fs-extra"; import { globby } from "globby"; import handlebars from "handlebars"; import { Observable } from "rxjs"; import { insertAfter } from "../utils/renderer/insertAfter.js"; import { insertImport } from "../utils/renderer/insertImport.js"; export class Renderer { constructor() { this.templateDir = constant("templateDir", ""); this.fs = inject(CliFs); this.cache = new Set(); } async loadPartials(cwd) { if (this.cache.has(cwd)) { return; } const files = await globby("**/_partials/*.hbs", { cwd }); files.forEach((filename) => { let template = this.fs.readFileSync(join(cwd, filename), "utf8"); const name = basename(filename).replace(".hbs", ""); handlebars.registerPartial(name, template); }); this.cache.add(cwd); } async render(path, data, options = {}) { const { output, templateDir, rootDir } = this.mapOptions(path, options); let content = ""; const file = normalizePath(join(templateDir, path)); options.baseDir && (await this.loadPartials(join(templateDir, options.baseDir))); if (path.endsWith(".hbs")) { content = await Consolidate.handlebars(file, data); } else { content = await this.fs.readFile(file, { encoding: "utf8" }); } return this.write(content, { output, rootDir }); } renderAll(paths, data, options = {}) { let count = 0; const mapOptions = (opts) => { if (isString(opts)) { return { ...options, path: opts }; } return { ...options, ...opts }; }; return new Observable((observer) => { observer.next(`[${count}/${paths.length}] Rendering files...`); const promises = paths .filter(Boolean) .map(mapOptions) .map(async ({ path, ...opts }) => { await this.render(path, data, opts); count++; observer.next(`[${count}/${paths.length}] Rendering files...`); }); Promise.all(promises) .then(() => { observer.next(`[${count}/${paths.length}] Rendering files...`); observer.complete(); }) .catch((err) => { observer.error(err); }); }); } async write(content, options) { const { output, rootDir = this.rootDir } = options; const outputFile = join(...[rootDir, output].filter(Boolean)); await this.fs.ensureDir(dirname(outputFile)); return this.fs.writeFile(outputFile, content, { encoding: "utf8" }); } templateExists(path, options = {}) { const { templateDir } = this.mapOptions(path, options); return fs.existsSync(join(templateDir, path)); } async scan(pattern, options = {}) { const result = await globby(pattern.map((s) => normalizePath(s)), { ...options, objectMode: true, cwd: this.rootDir }); return result.map((entry) => entry.path); } relativeFrom(path) { return relative(dirname(join(this.rootDir, path)), this.rootDir); } async update(path, actions) { path = join(this.rootDir, path); if (!this.fs.exists(path)) { return; } const content = actions.reduce((fileContent, action) => { switch (action.type) { case "import": return insertImport(fileContent, action.content); case "insert-after": return insertAfter(fileContent, action.content, action.pattern); default: break; } return fileContent; }, await this.fs.readFile(path, { encoding: "utf8" })); return this.fs.writeFile(path, content, { encoding: "utf8" }); } mapOptions(path, options) { const { templateDir = this.templateDir, rootDir = this.rootDir } = options; let { output = path } = options; if (options.baseDir) { output = normalizePath(join("/", relative(options.baseDir, path))); } if (options.basename) { output = normalizePath(join(dirname(output), options.basename)); } output = output.replace(/\.hbs$/, ""); if (options.replaces) { options.replaces.filter(Boolean).forEach((replace) => { output = output.replace(replace, ""); }); } return { output, templateDir, rootDir }; } } let RootRendererService = class RootRendererService extends Renderer { get rootDir() { return constant("project.rootDir", ""); } }; RootRendererService = __decorate([ Injectable() ], RootRendererService); export { RootRendererService }; let SrcRendererService = class SrcRendererService extends Renderer { get rootDir() { return join(...[constant("project.rootDir"), constant("project.srcDir")].filter(Boolean)); } }; SrcRendererService = __decorate([ Injectable() ], SrcRendererService); export { SrcRendererService }; let ScriptsRendererService = class ScriptsRendererService extends Renderer { get rootDir() { return join(...[constant("project.rootDir"), constant("project.scriptsDir")].filter(Boolean)); } }; ScriptsRendererService = __decorate([ Injectable() ], ScriptsRendererService); export { ScriptsRendererService };