// site-common.js // Copyright (C) 2022 DTP Technologies, LLC // License: Apache-2.0 'use strict'; const path = require('path'); const pug = require('pug'); const striptags = require('striptags'); const { SiteLog } = require(path.join(__dirname, 'site-log')); const { SiteAsync } = require(path.join(__dirname, 'site-async')); const EventEmitter2 = require('eventemitter2'); class SiteCommon extends EventEmitter2 { constructor (dtp, component, options) { // ensure valid options options = Object.assign({ }, options); // provide DTP's default EventEmitter2 configuration options.emitter = Object.assign({ wildcard: false, delimiter: '.', newListener: false, removeListener: false, maxListeners: 64, verboseMemoryLeak: process.env.NODE_ENV === 'local', ignoreErrors: false, }, options); // construct the EventEmitter2 instance via super() super(options.emitter); // store options *after* super() because you can't alter `this` prior this.options = options; this.dtp = dtp; this.component = component; this.log = new SiteLog(dtp, component); this.appTemplateRoot = path.join(this.dtp.config.root, 'app', 'templates'); this.jobQueues = { }; } async start ( ) {/* I will need this, do not delete. */} async stop ( ) { let slugs = Object.keys(this.jobQueues); await SiteAsync.each(slugs, async (slug) => { const queue = this.jobQueues[slug]; try { this.log.info('closing job queue'); await queue.close(); delete this.jobQueues[slug]; } catch (error) { this.log.error('failed to close job queue', { name: slug, error }); } }, 1); } getEventName (name) { return `dtp.${this.component.slug}.${name}`; } async emitDtpEvent (name, params) { await this.emitAsync(this.getEventName(name), params); } async getJobQueue (name) { if (this.jobQueues[name]) { return this.jobQueues[name]; } const { jobQueue: jobQueueService } = this.dtp.services; const config = this.dtp.config.jobQueues[name]; this.log.info('connecting to job queue', { name, config }); const queue = jobQueueService.getJobQueue(name, config); this.jobQueues[name] = queue; return queue; } regenerateSession (req) { return new Promise((resolve, reject) => { req.session.regenerate((err) => { if (err) { return reject(err); } resolve(); }); }); } saveSession (req) { return new Promise((resolve, reject) => { req.session.save((err) => { if (err) { return reject(err); } resolve(); }); }); } isSystemRoute (pathname) { return pathname.startsWith('/auth') || pathname.startsWith('/image') || pathname.startsWith('/manifest') ; } isValidString (text) { return text && (typeof text === 'string') && (text.length > 0); } loadAppTemplate (type, name) { return pug.compileFile(path.join(this.appTemplateRoot, type, name)); } loadViewTemplate (filename) { const scriptFile = path.join(this.dtp.config.root, 'app', 'views', filename); return pug.compileFile(scriptFile); } compileViewTemplate (filename, options) { const scriptFile = path.join(this.dtp.config.root, 'app', 'views', filename); const pathObj = path.parse(scriptFile); options = Object.assign({ filename: scriptFile, basedir: path.join(this.dtp.config.root, 'app', 'views'), doctype: 'html', name: pathObj.name, }, options); return pug.compileFileClient(scriptFile, options); } parseTagList (tagList, options) { options = Object.assign({ lowercase: true, filter: [ ], }, options); return tagList .split(',') .map((metric) => { metric = striptags(metric.trim()); return options.lowercase ? metric.toLowerCase() : metric; }) .filter((metric) => { return (typeof metric === 'string') && (metric.length > 0) && !options.filter.includes(metric.toLowerCase()) ; }); } } module.exports.SiteCommon = SiteCommon;