UNPKG

@aimee-blue/ab-service-kit

Version:
181 lines (143 loc) 7.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.serviceSetupInWatchMode = serviceSetupInWatchMode; var _chokidar = _interopRequireDefault(require("chokidar")); var _path = _interopRequireWildcard(require("path")); var _rxjs = require("rxjs"); var _operators = require("rxjs/operators"); var _shared = require("../shared"); var _fsExtra = require("fs-extra"); var _clearModule = require("../shared/clearModule"); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } if (process.env.NODE_ENV === 'production') { throw new Error('This file should not be imported in production'); } const watchMultiple = patterns => { if ((0, _shared.isUnitTest)() || (0, _shared.isIntegrationTest)()) { return (0, _rxjs.never)(); } const logger = (0, _shared.defaultBasicLogger)(); return new _rxjs.Observable(subscriber => { const watcher = _chokidar.default.watch(patterns, { ignorePermissionErrors: true }); const onChange = file => { logger.log('Change detected for', file); subscriber.next(file); }; const onError = err => { subscriber.error(err); }; const onClose = () => { subscriber.complete(); }; watcher.on('change', onChange).on('error', onError).on('close', onClose); return () => { watcher.close().catch(err => { logger.log('Couldnt close file watcher', err); }); }; }); }; let teardownOldServer = async () => { const logger = (0, _shared.defaultBasicLogger)(); logger.log('Dummy teardown was called ... odd'); return; }; const moduleInfo = mod => ({ filePath: _path.default.relative('./', mod.filename), mod }); function mainModule() { if (!require.main) { throw new Error('No require.main defined'); } return require.main; } function allChildModules(startFrom = mainModule()) { return (0, _rxjs.of)(moduleInfo(startFrom)).pipe(stream => { const set = new Set(); // sometimes modules circularly reference each other :( const uniqueModules = arr => { const items = arr.filter(item => !set.has(item)); items.forEach(set.add.bind(set)); return items; }; return stream.pipe((0, _operators.expand)(data => (0, _rxjs.from)(uniqueModules(data.mod.children)).pipe((0, _operators.map)(moduleInfo), (0, _operators.filter)(pair => !pair.filePath.includes('node_modules'))))); }); } function findModule(fullPathToJs, startFrom = mainModule()) { const compareTo = (0, _path.resolve)(_path.default.normalize(fullPathToJs)); return (0, _rxjs.concat)(allChildModules(startFrom), (0, _rxjs.from)(Object.entries(require.cache).filter(entry => !entry[0].includes('node_modules')).map(entry => entry[1]).filter(_shared.isTruthy).map(module => moduleInfo(module)))).pipe( // (0, _operators.find)(result => { const resolvedPath = (0, _path.resolve)(_path.default.normalize(result.filePath)); return resolvedPath === compareTo; })); } function allParentModules(module) { return (0, _rxjs.defer)(() => { return (0, _rxjs.of)(module.parent).pipe((0, _operators.filter)(_shared.isTruthy), (0, _operators.expand)(next => next.parent ? (0, _rxjs.of)(next.parent) : (0, _rxjs.empty)()), (0, _operators.map)(mod => moduleInfo(mod))); }); } function requireSetupModule(moduleId) { // eslint-disable-next-line const result = require(moduleId); if (typeof result !== 'object') { throw new Error('Resolved to a non-object'); } if ('default' in result) { return result.default; } return result; } async function serviceSetupInWatchMode(setupFilePath, setup) { const initialConfig = requireSetupModule(setupFilePath); const logger = (0, _shared.defaultBasicLogger)(); teardownOldServer = await setup(initialConfig); // please note that changes to this pattern will probably need changes to `watchServerCode` function // to detect .ts file locations correctly const WATCH_PATTERNS = initialConfig.watchPatterns || ['lib/**/*.js', '.env', '.env.local']; const subscription = (0, _rxjs.defer)(() => { logger.log(`🔍 Watching for file changes in ${WATCH_PATTERNS.join(', ')}`); return watchMultiple(WATCH_PATTERNS); }).pipe((0, _operators.mergeMap)(filePath => (0, _rxjs.from)((0, _fsExtra.pathExists)((0, _path.join)(process.cwd(), filePath)).catch(() => false).then(exists => ({ exists, filePath, resolved: (0, _path.join)(process.cwd(), filePath) })))), (0, _operators.filter)(pair => { if (!pair.exists) { logger.log(`Cannot resolve changes to ${pair.filePath} (tried ${pair.resolved}), ignoring`); } return pair.exists; }), (0, _operators.mergeMap)(fileInfo => findModule(fileInfo.resolved).pipe((0, _operators.filter)(_shared.isTruthy), (0, _operators.concatMap)(mod => (0, _rxjs.concat)((0, _rxjs.of)(mod), allParentModules(mod.mod))), (0, _operators.toArray)())), (0, _operators.filter)(mods => mods.length > 0), (0, _operators.concatMap)(mods => (0, _rxjs.from)(teardownOldServer('watch-mode')).pipe((0, _operators.mapTo)(mods))), (0, _operators.concatMap)(mods => { for (const mod of mods) { if (mod.mod.id === '.') { // we do not reload the main module continue; } if ((0, _path.dirname)(mod.mod.id) === __dirname) { continue; } (0, _clearModule.clearModule)(mod.mod.id); } if (!mods.find(item => item.filePath === setupFilePath)) { (0, _clearModule.clearModule)(setupFilePath); } return (0, _rxjs.defer)(() => (0, _rxjs.from)(setup(requireSetupModule(setupFilePath)).then(teardown => { teardownOldServer = teardown; return Promise.resolve(); }))); }), (0, _operators.catchError)((err, self) => { logger.log('💥 Watching error, will wait for 2sec before restart ... ', err); return (0, _rxjs.timer)(2000).pipe((0, _operators.switchMapTo)(self)); })).subscribe(() => { return; }, err => logger.log('💥 Watching error', err), () => logger.log('Watching stopped')); return async mode => { subscription.unsubscribe(); await teardownOldServer(mode); }; } //# sourceMappingURL=watchServerCode.js.map