UNPKG

ring-websites-toolbelt

Version:

Ring Publishing Platform tool to work with Ring Websites

280 lines (217 loc) 9.68 kB
const chokidar = require('chokidar'); const path = require('path'); class Watchers { constructor(options) { options = options || {}; this._paths = options.paths; this._providers = options.providers; this._dbCodes = options.dbCodes; this._directories = options.directories; this._files = options.files; this._ocdnData = options.ocdnData; this._watchers = {}; this._jobs = []; } startSavingConfig() { let watcherName = "savingConfig"; if (this._watchers[watcherName]) { throw Error(`Watcher ${watcherName} is already running`); } const toWatch = [ path.join(this._paths.build, this._files.CONFIG_JSON), path.join(this._paths.build, this._files.PARTIALS_JSON), path.join(this._paths.build, this._directories.SCHEMES) ]; this._watchers[watcherName] = chokidar.watch(toWatch, { persistent: true, ignoreInitial: true, usePolling: true, awaitWriteFinish: { stabilityThreshold: 1000, pollInterval: 100 }, }).on('all', (event, p) => { console.info(`Watcher | ${watcherName} reloaded ${p}`); let configPath = path.join(this._paths.build, this._files.CONFIG_JSON); let partialsPath = path.join(this._paths.build, this._files.PARTIALS_JSON); let schemesPath = path.join(this._paths.build, this._directories.SCHEMES); let configJson = this._providers.files.getConfigJson(configPath, partialsPath, schemesPath, this._ocdnData.Location + Watchers.DIRECTORIES.STATIC); this._providers.api.insertThemeConfig(configJson); console.info(`Watcher | ${watcherName} updated config.json`); }); console.info(`Watcher | ${watcherName} is running`); } startBuildingTheme() { let watcherName = "buildingTheme"; if (this._watchers[watcherName]) { throw Error(`Watcher ${watcherName} is already running`); } let changeDetected = 0; this._watchers[watcherName] = chokidar.watch([this._paths.theme, this._paths.modules], { persistent: true, ignoreInitial: true, ignored: [ `${this._paths.theme}/node_modules`, `${this._paths.theme}/.git`, `**/${this._paths.modules}/**/node_modules`, `**/${this._paths.modules}/**/.git` ] }).on('all', (event, path) => { changeDetected = 1; }); let job = setInterval(async () => { if (changeDetected) { changeDetected = 0; await this._providers.builder.build(); console.info(`Watcher | ${watcherName} build theme`); } }, Watchers.WATCHER_INTERVAL); this._jobs.push(job); console.info(`Watcher | ${watcherName} is running`); } startGetLogs(verboseLogging) { let watcherName = "getLogs"; let lastLogDate = 0; if (this._watchers[watcherName]) { throw Error(`Watcher ${watcherName} is already running`); } let job = setInterval(async () => { let data = await this._providers.api.getLogs(); if (data && data.length) { for (let i = 0; i < data.length; i++) { if (lastLogDate < data[i].add_time) { for (let j = 0; j < data[i].logs.length; j++) { try { const log = JSON.parse(data[i].logs[j]); const logType = Object.keys(log)[0]; let logMessage = log[logType]; const isWarnError = ['warn', 'error'].includes(logType); const isSpecialLog = logMessage.includes('__USER_LOG:') || logMessage.includes('__FINAL:'); logMessage = logMessage.replace('__USER_LOG:', '').replace('__FINAL:', ''); if (verboseLogging || isWarnError || isSpecialLog) { console[logType](logMessage); } } catch (e) { console.error(e.message); console.warn("Can't parse log, please contact CSP team"); } } lastLogDate = data[i].add_time; } } } }, Watchers.WATCHER_INTERVAL); this._jobs.push(job); console.info(`Watcher | ${watcherName} is running`); } _watchFiles(watcherName, dirs, addAction, delAction) { if (this._watchers[watcherName]) { throw Error(`Watcher ${watcherName} is already running`); } let changedFiles = new Set(); let deletedFiles = new Set(); this._watchers[watcherName] = chokidar.watch(dirs, { persistent: true, ignoreInitial: true }).on('all', (event, path) => { if (event === 'add' || event === 'change') { deletedFiles.delete(path); changedFiles.add(path); console.info(`Watcher | ${watcherName} event: ${event} (${path})`); } else if (event === 'unlink') { changedFiles.delete(path); deletedFiles.add(path); console.info(`Watcher | ${watcherName} event: ${event} (${path})`); } }); let job = setInterval(async () => { let filesToDelete = [...deletedFiles]; deletedFiles = new Set(); let filesToSave = [...changedFiles]; changedFiles = new Set(); if (filesToDelete.length) { await delAction(filesToDelete); console.info(`Watcher | ${watcherName} delete files: ${JSON.stringify(filesToDelete)}`); } if (filesToSave.length) { await addAction(filesToSave); console.info(`Watcher | ${watcherName} save files: ${JSON.stringify(filesToSave)}`); } }, Watchers.WATCHER_INTERVAL); this._jobs.push(job); console.info(`Watcher | ${watcherName} is running`); } startSavingTheme() { let codes = Object.keys(this._dbCodes); for (let i = 0; i < codes.length; i++) { let dbCode = this._dbCodes[codes[i]]; let dir = path.join(this._paths.build, this._directories[codes[i]]); let addAction = async (files) => { let objFiles = files.map((el) => { return { 'basePath': dir, 'relativePath': path.relative(dir, el) }; }); await this._providers.api.insertFiles(objFiles, dbCode); }; let delAction = async (files) => { let objFiles = files.map((el) => { return { 'basePath': dir, 'relativePath': path.relative(dir, el) }; }); await this._providers.api.deleteFiles(objFiles, dbCode); }; this._watchFiles(`savingTheme_${codes[i]}`, dir, addAction, delAction); } } startSavingStatic() { let dir = path.join(this._paths.build, this._directories.STATIC); let addAction = async (files) => { // const tmpFile = path.join(this._paths.temp, `tmp_${Date.now()}.zip`); // let filesToZip = files.map( (el) => { // return { // source: el, // target: path.relative(this._paths.build, el) // } // }); // await this._providers.files.compressFiles(filesToZip, tmpFile); // await this._providers.s3.uploadCompressedFile(tmpFile, this._ocdnData.Key); // await this._providers.files.removeCompressedFile(tmpFile); let promises = files.map((el) => { return this._providers.s3.uploadFile(el, path.join(this._ocdnData.Key, path.relative(this._paths.build, el))); }); return await Promise.all(promises); }; let delAction = async (files) => { // const filesToDelete = files.map( (el) => { // return { // Key: path.join(this._ocdnData.Key, path.relative(this._paths.build, el)) // } // }); // await this._providers.s3.deleteFiles(filesToDelete); let promises = files.map((el) => { return this._providers.s3.deleteFile(path.join(this._ocdnData.Key, path.relative(this._paths.build, el))); }); return await Promise.all(promises); }; this._watchFiles('savingStatic', dir, addAction, delAction); } stopAll() { let watcherNames = Object.keys(this._watchers); for (let i = 0; i < watcherNames.length; i++) { this._watchers[watcherNames[i]].close(); } this._watchers = {}; for (let i = 0; i < this._jobs.length; i++) { clearInterval(this._jobs[i]); } this._jobs = []; } } Watchers.WATCHER_INTERVAL = 1000; Watchers.DIRECTORIES = {}; Watchers.DIRECTORIES.STATIC = '/static/'; module.exports = Watchers;