@aimee-blue/ab-service-kit
Version:
Aimee Blue Service Template
1 lines • 13.6 kB
Source Map (JSON)
{"version":3,"sources":["../../src/setup/watchServerCode.ts"],"names":["process","env","NODE_ENV","Error","watchMultiple","patterns","logger","Observable","subscriber","watcher","chokidar","watch","ignorePermissionErrors","onChange","file","log","next","onError","err","error","onClose","complete","on","close","catch","teardownOldServer","moduleInfo","mod","filePath","path","relative","filename","mainModule","require","main","allChildModules","startFrom","pipe","stream","set","Set","uniqueModules","arr","items","filter","item","has","forEach","add","bind","data","children","pair","includes","findModule","fullPathToJs","compareTo","normalize","Object","entries","cache","entry","map","isTruthy","module","result","resolvedPath","allParentModules","parent","requireSetupModule","moduleId","default","serviceSetupInWatchMode","setupFilePath","setup","initialConfig","WATCH_PATTERNS","watchPatterns","subscription","join","cwd","then","exists","resolved","fileInfo","mods","length","id","__dirname","find","teardown","Promise","resolve","self","subscribe","mode","unsubscribe"],"mappings":"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","sourcesContent":["import chokidar from 'chokidar';\nimport path, { dirname, resolve, join } from 'path';\nimport { Observable, of, from, defer, concat, timer, never, empty } from 'rxjs';\nimport {\n mergeMap,\n map,\n expand,\n filter,\n find,\n concatMap,\n toArray,\n mapTo,\n catchError,\n switchMapTo,\n} from 'rxjs/operators';\nimport {\n IServiceConfig,\n isTruthy,\n isUnitTest,\n isIntegrationTest,\n defaultBasicLogger,\n} from '../shared';\nimport { pathExists } from 'fs-extra';\nimport { TeardownHandler } from '../shared/teardown';\nimport { clearModule } from '../shared/clearModule';\n\nif (process.env.NODE_ENV === 'production') {\n throw new Error('This file should not be imported in production');\n}\n\nconst watchMultiple = (patterns: string[]) => {\n if (isUnitTest() || isIntegrationTest()) {\n return never();\n }\n\n const logger = defaultBasicLogger();\n\n return new Observable<string>((subscriber) => {\n const watcher = chokidar.watch(patterns, {\n ignorePermissionErrors: true,\n });\n\n const onChange = (file: string) => {\n logger.log('Change detected for', file);\n subscriber.next(file);\n };\n\n const onError = (err: Error) => {\n subscriber.error(err);\n };\n\n const onClose = () => {\n subscriber.complete();\n };\n\n watcher.on('change', onChange).on('error', onError).on('close', onClose);\n\n return () => {\n watcher.close().catch((err) => {\n logger.log('Couldnt close file watcher', err);\n });\n };\n });\n};\n\nlet teardownOldServer: TeardownHandler = async () => {\n const logger = defaultBasicLogger();\n\n logger.log('Dummy teardown was called ... odd');\n return;\n};\n\nconst moduleInfo = (mod: NodeModule) => ({\n filePath: path.relative('./', mod.filename),\n mod,\n});\n\nfunction mainModule() {\n if (!require.main) {\n throw new Error('No require.main defined');\n }\n return require.main;\n}\n\nfunction allChildModules(startFrom: NodeModule = mainModule()) {\n return of(moduleInfo(startFrom)).pipe((stream) => {\n const set = new Set();\n\n // sometimes modules circularly reference each other :(\n const uniqueModules = (arr: NodeModule[]) => {\n const items = arr.filter((item) => !set.has(item));\n items.forEach(set.add.bind(set));\n return items;\n };\n\n return stream.pipe(\n expand((data) =>\n from(uniqueModules(data.mod.children)).pipe(\n map(moduleInfo),\n filter((pair) => !pair.filePath.includes('node_modules'))\n )\n )\n );\n });\n}\n\nfunction findModule(\n fullPathToJs: string,\n startFrom: NodeModule = mainModule()\n) {\n const compareTo = resolve(path.normalize(fullPathToJs));\n\n return concat(\n allChildModules(startFrom),\n from(\n Object.entries(require.cache as { [key: string]: NodeModule | undefined })\n .filter((entry) => !entry[0].includes('node_modules'))\n .map((entry) => entry[1])\n .filter(isTruthy)\n .map((module) => moduleInfo(module))\n )\n ).pipe(\n //\n find((result) => {\n const resolvedPath = resolve(path.normalize(result.filePath));\n return resolvedPath === compareTo;\n })\n );\n}\n\nfunction allParentModules(module: NodeModule) {\n return defer(() => {\n return of(module.parent).pipe(\n filter(isTruthy),\n expand((next) => (next.parent ? of(next.parent) : empty())),\n map((mod) => moduleInfo(mod))\n );\n });\n}\n\ntype ServiceSetupFunc = (config: IServiceConfig) => Promise<TeardownHandler>;\n\nfunction requireSetupModule(moduleId: string): IServiceConfig {\n // eslint-disable-next-line\n const result = require(moduleId) as\n | IServiceConfig\n | {\n default: IServiceConfig;\n };\n if (typeof result !== 'object') {\n throw new Error('Resolved to a non-object');\n }\n\n if ('default' in result) {\n return result.default;\n }\n\n return result;\n}\n\nexport async function serviceSetupInWatchMode(\n setupFilePath: string,\n setup: ServiceSetupFunc\n): Promise<TeardownHandler> {\n const initialConfig = requireSetupModule(setupFilePath);\n\n const logger = defaultBasicLogger();\n\n teardownOldServer = await setup(initialConfig);\n\n // please note that changes to this pattern will probably need changes to `watchServerCode` function\n // to detect .ts file locations correctly\n const WATCH_PATTERNS = initialConfig.watchPatterns || [\n 'lib/**/*.js',\n '.env',\n '.env.local',\n ];\n\n const subscription = defer(() => {\n logger.log(`🔍 Watching for file changes in ${WATCH_PATTERNS.join(', ')}`);\n return watchMultiple(WATCH_PATTERNS);\n })\n .pipe(\n mergeMap((filePath) =>\n from(\n pathExists(join(process.cwd(), filePath))\n .catch(() => false)\n .then((exists) => ({\n exists,\n filePath,\n resolved: join(process.cwd(), filePath),\n }))\n )\n ),\n filter((pair) => {\n if (!pair.exists) {\n logger.log(\n `Cannot resolve changes to ${pair.filePath} (tried ${pair.resolved}), ignoring`\n );\n }\n\n return pair.exists;\n }),\n\n mergeMap((fileInfo) =>\n findModule(fileInfo.resolved).pipe(\n filter(isTruthy),\n concatMap((mod) => concat(of(mod), allParentModules(mod.mod))),\n toArray()\n )\n ),\n\n filter((mods) => mods.length > 0),\n\n concatMap((mods) =>\n from(teardownOldServer('watch-mode')).pipe(mapTo(mods))\n ),\n\n concatMap((mods) => {\n for (const mod of mods) {\n if (mod.mod.id === '.') {\n // we do not reload the main module\n continue;\n }\n if (dirname(mod.mod.id) === __dirname) {\n continue;\n }\n\n clearModule(mod.mod.id);\n }\n\n if (!mods.find((item) => item.filePath === setupFilePath)) {\n clearModule(setupFilePath);\n }\n\n return defer(() =>\n from(\n setup(requireSetupModule(setupFilePath)).then((teardown) => {\n teardownOldServer = teardown;\n return Promise.resolve();\n })\n )\n );\n }),\n\n catchError((err, self) => {\n logger.log(\n '💥 Watching error, will wait for 2sec before restart ... ',\n err\n );\n return timer(2000).pipe(switchMapTo(self));\n })\n )\n .subscribe(\n () => {\n return;\n },\n (err) => logger.log('💥 Watching error', err),\n () => logger.log('Watching stopped')\n );\n\n return async (mode) => {\n subscription.unsubscribe();\n\n await teardownOldServer(mode);\n };\n}\n"],"file":"watchServerCode.js"}