From 23e254eee903d686e23eb0bff9e11beff42e3be5 Mon Sep 17 00:00:00 2001 From: Sergio Zharinov <zharinov@users.noreply.github.com> Date: Sun, 16 Feb 2020 08:57:12 +0400 Subject: [PATCH] refactor: Extract module loading code out to utils (#5444) --- lib/datasource/index.ts | 30 ++------------------------- lib/manager/index.ts | 35 +++---------------------------- lib/util/modules.ts | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 60 deletions(-) create mode 100644 lib/util/modules.ts diff --git a/lib/datasource/index.ts b/lib/datasource/index.ts index aa4f88c693..a8773e176a 100644 --- a/lib/datasource/index.ts +++ b/lib/datasource/index.ts @@ -1,4 +1,3 @@ -import fs from 'fs'; import { logger } from '../logger'; import { addMetaData } from './metadata'; import * as versioning from '../versioning'; @@ -12,36 +11,11 @@ import { DigestConfig, } from './common'; import { VERSION_SCHEME_SEMVER } from '../constants/version-schemes'; +import { loadModules } from '../util/modules'; export * from './common'; -const datasources: Record<string, Datasource> = {}; - -function isValidDatasourceModule( - datasourceName: string, - module: unknown -): module is Datasource { - return !!module; -} - -function loadDatasources(): void { - const datasourceDirs = fs - .readdirSync(__dirname, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name) - .filter(name => !name.startsWith('__')) - .sort(); - for (const datasourceName of datasourceDirs) { - const module = require(`./${datasourceName}`); // eslint-disable-line - if (isValidDatasourceModule(datasourceName, module)) { - datasources[datasourceName] = module; - } /* istanbul ignore next */ else { - throw new Error(`Datasource module "${datasourceName}" is invalid.`); - } - } -} - -loadDatasources(); +const datasources = loadModules<Datasource>(__dirname); const cacheNamespace = 'datasource-releases'; diff --git a/lib/manager/index.ts b/lib/manager/index.ts index 9a691c0a57..c76274c740 100644 --- a/lib/manager/index.ts +++ b/lib/manager/index.ts @@ -1,6 +1,3 @@ -import fs from 'fs'; -import { logger } from '../logger'; - import { ExtractConfig, ManagerApi, @@ -24,37 +21,11 @@ import { LANGUAGE_RUBY, LANGUAGE_RUST, } from '../constants/languages'; +import { loadModules } from '../util/modules'; -const managerList = []; -const managers: Record<string, ManagerApi> = {}; - -function isValidManagerModule(module: unknown): module is ManagerApi { - // TODO: check interface and fail-fast? - return !!module; -} - -function loadManagers(): void { - const managerDirs = fs - .readdirSync(__dirname, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name) - .sort(); - for (const manager of managerDirs) { - let module = null; - try { - module = require(`./${manager}`); // eslint-disable-line - } catch (err) /* istanbul ignore next */ { - logger.fatal({ err }, `Can not load manager "${manager}".`); - process.exit(1); - } +const managers = loadModules<ManagerApi>(__dirname); - if (isValidManagerModule(module)) { - managers[manager] = module; - managerList.push(manager); - } - } -} -loadManagers(); +const managerList = Object.keys(managers); const languageList = [ LANGUAGE_DART, diff --git a/lib/util/modules.ts b/lib/util/modules.ts new file mode 100644 index 0000000000..f61deada35 --- /dev/null +++ b/lib/util/modules.ts @@ -0,0 +1,46 @@ +import fs from 'fs'; +import { join, normalizeTrim } from 'upath'; + +function relatePath(here: string, there: string): string { + const thereParts = normalizeTrim(there).split(/[\\/]/); + const hereParts = normalizeTrim(here).split(/[\\/]/); + + let idx = 0; + while ( + typeof thereParts[idx] === 'string' && + typeof hereParts[idx] === 'string' && + thereParts[idx] === hereParts[idx] + ) { + idx += 1; + } + + const result = []; + for (let x = 0; x < hereParts.length - idx; x += 1) result.push('..'); + for (let y = idx; y < thereParts.length; y += 1) result.push(thereParts[idx]); + return result.join('/'); +} + +export function loadModules<T>( + dirname: string, + validate?: (x: unknown) => x is T +): Record<string, T> { + const result: Record<string, T> = {}; + + const moduleNames: string[] = fs + .readdirSync(dirname, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name) + .filter(name => !name.startsWith('__')) + .sort(); + + for (const moduleName of moduleNames) { + const modulePath = join(relatePath(__dirname, dirname), moduleName); + const module = require(modulePath); // eslint-disable-line + // istanbul ignore if + if (!module || (validate && !validate(module))) + throw new Error(`Invalid module: ${modulePath}`); + result[moduleName] = module as T; + } + + return result; +} -- GitLab