From 01a66390421bc0ddbd31cab0877a5605c8623333 Mon Sep 17 00:00:00 2001 From: Alexander Roidl <34438048+alexanderroidl@users.noreply.github.com> Date: Sat, 26 Jul 2025 09:35:12 +0200 Subject: [PATCH] refactor: replace runtime imports with static imports --- index.js | 14 ++++++------- lib/api/routes/notificationAdapterRouter.js | 14 +++++-------- lib/api/routes/providerRouter.js | 12 ++++------- lib/notification/adapter/index.js | 12 +++++++++++ lib/notification/notify.js | 16 ++------------ lib/provider/index.js | 21 +++++++++++++++++++ .../queryStringMutator.test.js | 10 +++------ 7 files changed, 53 insertions(+), 46 deletions(-) create mode 100644 lib/notification/adapter/index.js create mode 100644 lib/provider/index.js diff --git a/index.js b/index.js index c08652f8..227e7984 100755 --- a/index.js +++ b/index.js @@ -9,24 +9,22 @@ import './lib/api/api.js'; import { track } from './lib/services/tracking/Tracker.js'; import { handleDemoUser } from './lib/services/storage/userStorage.js'; import { cleanupDemoAtMidnight } from './lib/services/demoCleanup.js'; +import providers from './lib/provider/index.js'; + //if db folder does not exist, ensure to create it before loading anything else if (!fs.existsSync('./db')) { fs.mkdirSync('./db'); } -const path = './lib/provider'; -const provider = fs.readdirSync(path).filter((file) => file.endsWith('.js')); + //assuming interval is always in minutes const INTERVAL = config.interval * 60 * 1000; + /* eslint-disable no-console */ console.log(`Started Fredy successfully. Ui can be accessed via http://localhost:${config.port}`); if (config.demoMode) { console.info('Running in demo mode'); cleanupDemoAtMidnight(); } -/* eslint-enable no-console */ -const fetchedProvider = await Promise.all( - provider.filter((provider) => provider.endsWith('.js')).map(async (pro) => import(`${path}/${pro}`)), -); handleDemoUser(); @@ -42,9 +40,9 @@ setInterval( .filter((job) => job.enabled) .forEach((job) => { job.provider - .filter((p) => fetchedProvider.find((fp) => fp.metaInformation.id === p.id) != null) + .filter((p) => providers.find((fp) => fp.metaInformation.id === p.id) != null) .forEach(async (prov) => { - const pro = fetchedProvider.find((fp) => fp.metaInformation.id === prov.id); + const pro = providers.find((fp) => fp.metaInformation.id === prov.id); pro.init(prov, job.blacklist); await new FredyRuntime(pro.config, job.notificationAdapter, prov.id, job.id, similarityCache).execute(); setLastJobExecution(job.id); diff --git a/lib/api/routes/notificationAdapterRouter.js b/lib/api/routes/notificationAdapterRouter.js index 483fa141..41f16b4c 100644 --- a/lib/api/routes/notificationAdapterRouter.js +++ b/lib/api/routes/notificationAdapterRouter.js @@ -1,16 +1,12 @@ -import fs from 'fs'; import restana from 'restana'; +import notificationAdapters from '../../notification/adapter/index.js'; + const service = restana(); const notificationAdapterRouter = service.newRouter(); -const notificationAdapterList = fs.readdirSync('./lib//notification/adapter').filter((file) => file.endsWith('.js')); -const notificationAdapter = await Promise.all( - notificationAdapterList.map(async (pro) => { - return await import(`../../notification/adapter/${pro}`); - }) -); + notificationAdapterRouter.post('/try', async (req, res) => { const { id, fields } = req.body; - const adapter = notificationAdapter.find((adapter) => adapter.config.id === id); + const adapter = notificationAdapters.find((adapter) => adapter.config.id === id); if (adapter == null) { res.send(404); } @@ -45,7 +41,7 @@ notificationAdapterRouter.post('/try', async (req, res) => { } }); notificationAdapterRouter.get('/', async (req, res) => { - res.body = notificationAdapter.map((adapter) => adapter.config); + res.body = notificationAdapters.map((adapter) => adapter.config); res.send(); }); export { notificationAdapterRouter }; diff --git a/lib/api/routes/providerRouter.js b/lib/api/routes/providerRouter.js index 2718baae..6e8042af 100644 --- a/lib/api/routes/providerRouter.js +++ b/lib/api/routes/providerRouter.js @@ -1,15 +1,11 @@ -import fs from 'fs'; import restana from 'restana'; +import providers from '../../provider/index.js'; + const service = restana(); const providerRouter = service.newRouter(); -const providerList = fs.readdirSync('./lib/provider').filter((file) => file.endsWith('.js')); -const provider = await Promise.all( - providerList.map(async (pro) => { - return await import(`../../provider/${pro}`); - }) -); + providerRouter.get('/', async (req, res) => { - res.body = provider.map((p) => p.metaInformation); + res.body = providers.map((p) => p.metaInformation); res.send(); }); export { providerRouter }; diff --git a/lib/notification/adapter/index.js b/lib/notification/adapter/index.js new file mode 100644 index 00000000..c26d83a2 --- /dev/null +++ b/lib/notification/adapter/index.js @@ -0,0 +1,12 @@ +import * as apprise from './apprise.js'; +import * as console from './console.js'; +import * as mailJet from './mailJet.js'; +import * as mattermost from './mattermost.js'; +import * as ntfy from './ntfy.js'; +import * as pushover from './pushover.js'; +import * as sendGrid from './sendGrid.js'; +import * as slack from './slack.js'; +import * as sqlite from './sqlite.js'; +import * as telegram from './telegram.js'; + +export default [apprise, console, mailJet, mattermost, ntfy, pushover, sendGrid, slack, sqlite, telegram]; diff --git a/lib/notification/notify.js b/lib/notification/notify.js index 5fcfec12..3886f355 100755 --- a/lib/notification/notify.js +++ b/lib/notification/notify.js @@ -1,19 +1,7 @@ -import fs from 'fs'; -const path = './adapter'; +import notificationAdapters from './adapter/index.js'; -/** Read every integration existing in ./adapter **/ -const adapter = await Promise.all( - fs - .readdirSync('./lib/notification/adapter') - .filter((file) => file.endsWith('.js')) - .map(async (integPath) => await import(`${path}/${integPath}`)), -); - -if (adapter.length === 0) { - throw new Error('Please specify at least one notification provider'); -} const findAdapter = (notificationAdapter) => { - return adapter.find((a) => a.config.id === notificationAdapter.id); + return notificationAdapters.find((a) => a.config.id === notificationAdapter.id); }; export const send = (serviceName, newListings, notificationConfig, jobKey) => { //this is not being used in tests, therefore adapter are always set diff --git a/lib/provider/index.js b/lib/provider/index.js new file mode 100644 index 00000000..6ddc880a --- /dev/null +++ b/lib/provider/index.js @@ -0,0 +1,21 @@ +import * as einsAImmobilien from './einsAImmobilien.js'; +import * as immobilienDe from './immobilienDe.js'; +import * as immonet from './immonet.js'; +import * as immoscout from './immoscout.js'; +import * as immoswp from './immoswp.js'; +import * as immowelt from './immowelt.js'; +import * as kleinanzeigen from './kleinanzeigen.js'; +import * as neubauKompass from './neubauKompass.js'; +import * as wgGesucht from './wgGesucht.js'; + +export default [ + einsAImmobilien, + immobilienDe, + immonet, + immoscout, + immoswp, + immowelt, + kleinanzeigen, + neubauKompass, + wgGesucht, +]; diff --git a/test/queryStringMutator/queryStringMutator.test.js b/test/queryStringMutator/queryStringMutator.test.js index 0fce449a..5c08eb97 100644 --- a/test/queryStringMutator/queryStringMutator.test.js +++ b/test/queryStringMutator/queryStringMutator.test.js @@ -1,26 +1,22 @@ -import fs from 'fs'; import { expect } from 'chai'; import { readFile } from 'fs/promises'; import mutator from '../../lib/services/queryStringMutator.js'; import queryString from 'query-string'; +import providers from '../../lib/provider/index.js'; const data = await readFile(new URL('./testData.json', import.meta.url)); const testData = JSON.parse(data); -let _provider = await Promise.all( - fs.readdirSync('./lib/provider/').map(async (integPath) => await import(`../../lib/provider/${integPath}`)), -); - /** - * Test test might look a bit weird at first, but listen stranger... + * The test might look a bit weird at first, but listen stranger... * It's not wise to compare 2 urls, as this means all url params must be in the expected order. This is however not * guaranteed, as params (and their order) are totally variable. */ describe('queryStringMutator', () => { it('should fix all urls', () => { for (let test of testData) { - const provider = _provider.find((p) => p.metaInformation.id === test.id); + const provider = providers.find((p) => p.metaInformation.id === test.id); if (provider == null) { throw new Error(`Cannot find provider for given id: ${test.id}`); }