UNPKG

@ewwmy/cv-builder

Version:

💻 A CLI utility to generate a well-formatted CV in PDF format 📕 based on JSON CV data and a Handlebars template

213 lines (212 loc) • 11.7 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; 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.ApplicationService = void 0; const node_path_1 = require("node:path"); const fs_extra_1 = __importDefault(require("fs-extra")); const inversify_1 = require("inversify"); const dependency_types_1 = require("../types/dependency.types"); const app_config_service_1 = require("../config/app-config.service"); const arguments_service_1 = require("../arguments/arguments.service"); const json_transformer_service_1 = require("../json-transformer/json-transformer.service"); const file_service_1 = require("../files/file.service"); const chokidar_1 = __importDefault(require("chokidar")); let ApplicationService = class ApplicationService { constructor(logger, config, templateEngine, output, args, jsonTransformer, fileService) { this.logger = logger; this.config = config; this.templateEngine = templateEngine; this.output = output; this.args = args; this.jsonTransformer = jsonTransformer; this.fileService = fileService; } // check app dir healthCheck() { return __awaiter(this, void 0, void 0, function* () { // restore everything if app dir doesn't exist if (!(yield fs_extra_1.default.pathExists(this.config.get('APP_DIR')))) { yield this.restoreDefault(); } }); } // restore default settings and examples restoreDefault() { return __awaiter(this, arguments, void 0, function* (force = false) { yield fs_extra_1.default.ensureDir(this.config.get('APP_DIR')); yield fs_extra_1.default.ensureDir(this.config.get('DEFAULT_OUTPUT_DIR')); // restore config if (!(yield fs_extra_1.default.pathExists(this.config.get('CONFIG_FILE_PATH'))) || force) { yield fs_extra_1.default.ensureDir(this.config.get('CONFIG_DIR')); yield this.fileService.saveJsonSettings(this.config.get('CONFIG_FILE_PATH'), this.config.getUserConfig()); } // restore cv example if (!(yield fs_extra_1.default.pathExists(this.config.get('DEFAULT_CV_FILE_PATH'))) || force) { yield fs_extra_1.default.copy(this.config.get('EXAMPLE_CV_FILE_PATH'), this.config.get('DEFAULT_CV_FILE_PATH')); } // restore icons if (!(yield fs_extra_1.default.pathExists(this.config.get('DEFAULT_ICONS_DIR'))) || force) { yield fs_extra_1.default.copy(this.config.get('EXAMPLE_ICONS_DIR'), this.config.get('DEFAULT_ICONS_DIR')); } // restore user photo examples if (!(yield fs_extra_1.default.pathExists(this.config.get('DEFAULT_IMAGES_DIR'))) || force) { yield fs_extra_1.default.copy(this.config.get('EXAMPLE_IMAGES_DIR'), this.config.get('DEFAULT_IMAGES_DIR')); } // restore template examples if (!(yield fs_extra_1.default.pathExists(this.config.get('DEFAULT_TEMPLATES_DIR'))) || force) { yield fs_extra_1.default.copy(this.config.get('EXAMPLE_TEMPLATES_DIR'), this.config.get('DEFAULT_TEMPLATES_DIR')); } }); } // getting the json file data getSourceData(filename) { return __awaiter(this, void 0, void 0, function* () { var _a; let data = null; try { data = JSON.parse((_a = (yield this.fileService.readFileData(filename))) !== null && _a !== void 0 ? _a : '{}'); } catch (error) { let errorInfo = 'Cannot parse JSON in CV data file'; if (error instanceof Error) { errorInfo += ': ' + error.message; } this.logger.error(errorInfo); } return data; }); } run() { return __awaiter(this, void 0, void 0, function* () { try { // check the app directory yield this.healthCheck(); // load user config yield this.config.loadFromFile(); // load command line options const options = yield this.args.getCommandLineOptions(); // generate all wrapper const generateAll = () => __awaiter(this, void 0, void 0, function* () { // registering handlebars helpers this.templateEngine.registerHelpers(); // restore default data if the option `restore` is set if (options.restore) { yield this.restoreDefault(options.force); this.logger.info('Restored' + (options.force ? ' (force)' : '')); process.exit(0); } // load cv json file data const cvData = yield this.getSourceData(options.input); if (!cvData) return; // process icons and images + remove hidden data const processedCvData = yield this.jsonTransformer.processImages(yield this.jsonTransformer.processIcons(this.jsonTransformer.processHiddenData(cvData), options.iconsBaseDir), options.imagesBaseDir); // walk through selected templates for (const template of options.templates) { // look for the template and read it if found const templateData = yield this.fileService.readFileData((0, node_path_1.join)(options.templatesDir, `${template}.hbs`)); if (!templateData) continue; // walk through selected locales for (const locale of options.locales) { // register handlebars date helper depending on the locale this.templateEngine.registerDateHelper(locale); // register handlebars year helper depending on the locale this.templateEngine.registerYearHelper(locale); // determine language from the processing locale const lang = String(locale).split('-')[0]; // setting up the output pdf file path const outputPath = (0, node_path_1.join)(options.output, `${template}_${locale}.pdf`); // language-mapped json data const localizedCvData = this.jsonTransformer.processLocalizedData(processedCvData, lang); // compile html const html = this.templateEngine.compile(templateData, localizedCvData); // save pdf yield this.output.saveToFile(outputPath, html, this.args.marginsToPuppeteer(options.margins)); // unregistering handlebars date helper this.templateEngine.unregisterDateHelper(); // unregistering handlebars year helper this.templateEngine.unregisterYearHelper(); } } }); // generate all pdfs according to the options yield generateAll(); // check if the watch mode is enabled if (options.watch) { this.logger.info('Watching for changes...'); // register file watcher const watcher = chokidar_1.default.watch([options.input, options.templatesDir], { ignoreInitial: true, persistent: true, }); // handle files changes watcher.on('change', (filePath) => __awaiter(this, void 0, void 0, function* () { this.logger.info(`File changed: "${filePath}". Regenerating...`); try { // regenerate on files change yield generateAll(); } catch (error) { let errorInfo = 'Error while regenerating'; if (error instanceof Error) { errorInfo += ': ' + error.message; } this.logger.error(errorInfo); } })); } } catch (error) { if (error instanceof Error) { this.logger.error(error.message); } else { this.logger.error(error); } } }); } }; exports.ApplicationService = ApplicationService; exports.ApplicationService = ApplicationService = __decorate([ (0, inversify_1.injectable)(), __param(0, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.Logger)), __param(1, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.Config)), __param(2, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.Template)), __param(3, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.Output)), __param(4, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.Arguments)), __param(5, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.JsonTransformer)), __param(6, (0, inversify_1.inject)(dependency_types_1.DependencyTypes.File)), __metadata("design:paramtypes", [Object, app_config_service_1.AppConfigService, Object, Object, arguments_service_1.ArgumentsService, json_transformer_service_1.JsonTransformerService, file_service_1.FileService]) ], ApplicationService);