diff --git a/package.json b/package.json index e1ef898..89f00e6 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@fastify/swagger": "^8.14.0", "@fastify/swagger-ui": "^3.0.0", "@fastify/view": "^9.0.0", - "@txtdot/plugins": "^1.0.0", + "@txtdot/plugins": "^1.1.1", "@txtdot/sdk": "^1.1.1", "axios": "^1.6.8", "dompurify": "^3.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 639a851..0c17d72 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^9.0.0 version: 9.0.0 '@txtdot/plugins': - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.1.1 + version: 1.1.1 '@txtdot/sdk': specifier: ^1.1.1 version: 1.1.1 @@ -310,8 +310,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@txtdot/plugins@1.0.0': - resolution: {integrity: sha512-RJLVNHFBxiEUo8my6eSgkfrSpxPDIUYdGsI0hfw8lyI5aZ30/OjhFfzfK0Jsf1b7xxw5acZn1My0yrF9RpdHBA==} + '@txtdot/plugins@1.1.1': + resolution: {integrity: sha512-rCRCzi18xdFK/JpdB+dQF1PaN+w6tNhVJum5YJu05PY0vsz5Rgx9ct7HmPi8W01Ek+iwec8GUeP1IKkUDHF6BQ==} '@txtdot/sdk@1.1.1': resolution: {integrity: sha512-H1YYXdDX3sjZdBfb+osDlDVBVlW8lNeyAIl0j7DhwbOmW3bNCFI9pdMiWGDIyotH6UqOncFP0u+jBugW/5N4Wg==} @@ -1666,7 +1666,7 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@txtdot/plugins@1.0.0': + '@txtdot/plugins@1.1.1': dependencies: '@mozilla/readability': 0.5.0 '@txtdot/sdk': 1.1.1 diff --git a/src/app.ts b/src/app.ts index d59f501..513b07d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -13,22 +13,19 @@ import proxyRoute from './routes/browser/proxy'; import parseRoute from './routes/api/parse'; import rawHtml from './routes/api/raw-html'; -import packageJSON from './package'; import errorHandler from './errors/handler'; -import getConfig from './config/main'; import redirectRoute from './routes/browser/redirect'; -import dynConfig from './config/dynamic.config'; import configurationRoute from './routes/browser/configuration'; +import config from './config'; + class App { async init() { - const config = getConfig(); - const fastify = Fastify({ logger: true, - trustProxy: config.reverse_proxy, - connectionTimeout: config.timeout, + trustProxy: config.env.reverse_proxy, + connectionTimeout: config.env.timeout, }); fastify.setErrorHandler(errorHandler); @@ -44,14 +41,14 @@ class App { }, }); - if (config.swagger) { - dynConfig.addRoute('/doc'); + if (config.env.swagger) { + config.dyn.addRoute('/doc'); await fastify.register(fastifySwagger, { swagger: { info: { title: 'TXTDot API', - description: packageJSON.description, - version: packageJSON.version, + description: config.package.description, + version: config.package.version, }, }, }); @@ -59,20 +56,20 @@ class App { } fastify.addHook('onRoute', (route) => { - dynConfig.addRoute(route.url); + config.dyn.addRoute(route.url); }); fastify.register(indexRoute); fastify.register(getRoute); fastify.register(configurationRoute); - config.third_party.searx_url && fastify.register(redirectRoute); - config.proxy.enabled && fastify.register(proxyRoute); + config.env.third_party.searx_url && fastify.register(redirectRoute); + config.env.proxy.enabled && fastify.register(proxyRoute); fastify.register(parseRoute); fastify.register(rawHtml); - fastify.listen({ host: config.host, port: config.port }, (err) => { + fastify.listen({ host: config.env.host, port: config.env.port }, (err) => { err && console.log(err); }); } diff --git a/src/config/dynamic.config.ts b/src/config/dynConfig.ts similarity index 58% rename from src/config/dynamic.config.ts rename to src/config/dynConfig.ts index ccddc1d..d18345d 100644 --- a/src/config/dynamic.config.ts +++ b/src/config/dynConfig.ts @@ -1,4 +1,4 @@ -class DynConfigService { +class DynConfig { public routes: Set = new Set(); constructor() {} addRoute(route: string) { @@ -6,5 +6,5 @@ class DynConfigService { } } -const config = new DynConfigService(); -export default config; +const dyn_config = new DynConfig(); +export default dyn_config; diff --git a/src/config/config.service.ts b/src/config/envConfig.ts similarity index 89% rename from src/config/config.service.ts rename to src/config/envConfig.ts index 7061435..578cd75 100644 --- a/src/config/config.service.ts +++ b/src/config/envConfig.ts @@ -1,6 +1,6 @@ -import { config } from 'dotenv'; +import { config as dconfig } from 'dotenv'; -export class ConfigService { +class EnvConfig { public readonly host: string; public readonly port: number; public readonly timeout: number; @@ -10,7 +10,7 @@ export class ConfigService { public readonly third_party: ThirdPartyConfig; constructor() { - config(); + dconfig(); this.host = process.env.HOST || '0.0.0.0'; this.port = Number(process.env.PORT) || 8080; @@ -37,6 +37,8 @@ export class ConfigService { return value === 'true' || value === '1'; } } +const env_config = new EnvConfig(); +export default env_config; interface ProxyConfig { enabled: boolean; diff --git a/src/config/index.ts b/src/config/index.ts new file mode 100644 index 0000000..c13eac0 --- /dev/null +++ b/src/config/index.ts @@ -0,0 +1,13 @@ +import dyn_config from './dynConfig'; +import env_config from './envConfig'; +import package_config from './packageConfig'; +import plugin_config from './pluginConfig'; + +const config = { + dyn: dyn_config, + env: env_config, + plugin: plugin_config, + package: package_config, +}; + +export default config; diff --git a/src/config/main.ts b/src/config/main.ts deleted file mode 100644 index ea4e219..0000000 --- a/src/config/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ConfigService } from './config.service'; - -let configSvc: ConfigService | undefined; - -export default function getConfig(): ConfigService { - if (configSvc) { - return configSvc; - } - - configSvc = new ConfigService(); - return configSvc; -} diff --git a/src/config/packageConfig.ts b/src/config/packageConfig.ts new file mode 100644 index 0000000..4eef3d3 --- /dev/null +++ b/src/config/packageConfig.ts @@ -0,0 +1,3 @@ +import * as package_config from '../../package.json'; + +export default package_config; diff --git a/src/config/pluginConfig.ts b/src/config/pluginConfig.ts new file mode 100644 index 0000000..0d51d9f --- /dev/null +++ b/src/config/pluginConfig.ts @@ -0,0 +1,12 @@ +import { IAppConfig } from '../types/appConfig'; +import { engineList } from '@txtdot/plugins'; + +/** + * Configuration of plugins + * Here you can add your own plugins + */ +const plugin_config: IAppConfig = { + engines: [...engineList], +}; + +export default plugin_config; diff --git a/src/handlers/distributor.ts b/src/distributor.ts similarity index 86% rename from src/handlers/distributor.ts rename to src/distributor.ts index d406a68..f20088a 100644 --- a/src/handlers/distributor.ts +++ b/src/distributor.ts @@ -1,15 +1,15 @@ -import axios, { oaxios } from '../types/axios'; +import axios, { oaxios } from './types/axios'; import micromatch from 'micromatch'; import DOMPurify from 'dompurify'; import { Readable } from 'stream'; -import { NotHtmlMimetypeError } from '../errors/main'; -import { decodeStream, parseEncodingName } from '../utils/http'; -import replaceHref from '../utils/replace-href'; +import { NotHtmlMimetypeError } from './errors/main'; +import { decodeStream, parseEncodingName } from './utils/http'; +import replaceHref from './utils/replace-href'; import { parseHTML } from 'linkedom'; -import getConfig from '../config/main'; import { Engine } from '@txtdot/sdk'; import { HandlerInput, IHandlerOutput } from '@txtdot/sdk/dist/types/handler'; +import config from './config'; interface IEngineId { [key: string]: number; @@ -35,7 +35,7 @@ export class Distributor { ): Promise { const urlObj = new URL(remoteUrl); - const webder_url = getConfig().third_party.webder_url; + const webder_url = config.env.third_party.webder_url; const response = webder_url ? await oaxios.get( diff --git a/src/errors/handler.ts b/src/errors/handler.ts index b513695..8b373d5 100644 --- a/src/errors/handler.ts +++ b/src/errors/handler.ts @@ -5,7 +5,7 @@ import { getFastifyError } from './validation'; import { TxtDotError } from '@txtdot/sdk/dist/types/errors'; import { IGetSchema } from '../types/requests/browser'; -import getConfig from '../config/main'; +import config from '../config'; export default function errorHandler( error: Error, @@ -58,7 +58,7 @@ function htmlErrorHandler(error: Error, reply: FastifyReply, url: string) { code: error.code, description: error.description, proxyBtn: - error instanceof NotHtmlMimetypeError && getConfig().proxy.enabled, + error instanceof NotHtmlMimetypeError && config.env.proxy.enabled, }); } diff --git a/src/errors/main.ts b/src/errors/main.ts index ec76370..ebd80a7 100644 --- a/src/errors/main.ts +++ b/src/errors/main.ts @@ -1,4 +1,4 @@ -import getConfig from '../config/main'; +import config from '../config'; import { TxtDotError } from '@txtdot/sdk/dist/types/errors'; export class LocalResourceError extends TxtDotError { @@ -23,7 +23,7 @@ export class NotHtmlMimetypeError extends TxtDotError { 421, 'NotHtmlMimetypeError', 'Received non-HTML content, ' + - (getConfig().proxy.enabled + (config.env.proxy.enabled ? 'use proxy instead of parser.' : 'proxying is disabled by the instance admin.') ); diff --git a/src/handlers/main.ts b/src/handlers/main.ts deleted file mode 100644 index 0f52ab8..0000000 --- a/src/handlers/main.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Distributor } from './distributor'; -import { engines } from '@txtdot/plugins'; - -const distributor = new Distributor(); - -distributor.engine(engines.StackOverflow); -distributor.engine(engines.SearX); -distributor.engine(engines.Readability); - -export const engineList = distributor.list; -export default distributor; diff --git a/src/package.ts b/src/package.ts deleted file mode 100644 index 01ff519..0000000 --- a/src/package.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as config from '../package.json'; - -export default config; diff --git a/src/plugin_manager.ts b/src/plugin_manager.ts new file mode 100644 index 0000000..7eee703 --- /dev/null +++ b/src/plugin_manager.ts @@ -0,0 +1,11 @@ +import { Distributor } from './distributor'; +import plugin_config from './config/pluginConfig'; + +const distributor = new Distributor(); + +for (const engine of plugin_config.engines) { + distributor.engine(engine); +} + +export const engineList = distributor.list; +export { distributor }; diff --git a/src/routes/api/parse.ts b/src/routes/api/parse.ts index 51f4edd..721b99d 100644 --- a/src/routes/api/parse.ts +++ b/src/routes/api/parse.ts @@ -6,7 +6,7 @@ import { parseSchema, } from '../../types/requests/api'; -import distributor from '../../handlers/main'; +import { distributor } from '../../plugin_manager'; import { generateRequestUrl } from '../../utils/generate'; export default async function parseRoute(fastify: FastifyInstance) { diff --git a/src/routes/api/raw-html.ts b/src/routes/api/raw-html.ts index 51c66bd..e372bd0 100644 --- a/src/routes/api/raw-html.ts +++ b/src/routes/api/raw-html.ts @@ -2,7 +2,7 @@ import { FastifyInstance } from 'fastify'; import { IParseSchema, rawHtmlSchema } from '../../types/requests/api'; -import distributor from '../../handlers/main'; +import { distributor } from '../../plugin_manager'; import { generateRequestUrl } from '../../utils/generate'; export default async function rawHtml(fastify: FastifyInstance) { diff --git a/src/routes/browser/configuration.ts b/src/routes/browser/configuration.ts index d5ce938..e832d53 100644 --- a/src/routes/browser/configuration.ts +++ b/src/routes/browser/configuration.ts @@ -1,19 +1,15 @@ import { FastifyInstance } from 'fastify'; -import packageJSON from '../../package'; -import distributor from '../../handlers/main'; +import { distributor } from '../../plugin_manager'; import { indexSchema } from '../../types/requests/browser'; -import getConfig from '../../config/main'; -import dynConfig from '../../config/dynamic.config'; +import config from '../../config'; export default async function configurationRoute(fastify: FastifyInstance) { fastify.get('/configuration', { schema: indexSchema }, async (_, reply) => { return reply.view('/templates/configuration.ejs', { - packageJSON, engines: distributor.fallback, - dynConfig, - config: getConfig(), + config, }); }); } diff --git a/src/routes/browser/get.ts b/src/routes/browser/get.ts index e5492dd..c7db850 100644 --- a/src/routes/browser/get.ts +++ b/src/routes/browser/get.ts @@ -1,10 +1,9 @@ import { FastifyInstance } from 'fastify'; import { GetSchema, IGetSchema } from '../../types/requests/browser'; -import distributor from '../../handlers/main'; +import { distributor } from '../../plugin_manager'; import { generateRequestUrl } from '../../utils/generate'; - -import getConfig from '../../config/main'; +import config from '../../config'; export default async function getRoute(fastify: FastifyInstance) { fastify.get( @@ -32,7 +31,7 @@ export default async function getRoute(fastify: FastifyInstance) { return reply.view('/templates/get.ejs', { parsed, remoteUrl, - config: getConfig(), + config, }); } } diff --git a/src/routes/browser/index.ts b/src/routes/browser/index.ts index d7ceb2a..a84f3d5 100644 --- a/src/routes/browser/index.ts +++ b/src/routes/browser/index.ts @@ -1,17 +1,14 @@ import { FastifyInstance } from 'fastify'; -import packageJSON from '../../package'; -import { engineList } from '../../handlers/main'; +import { engineList } from '../../plugin_manager'; import { indexSchema } from '../../types/requests/browser'; - -import getConfig from '../../config/main'; +import config from '../../config'; export default async function indexRoute(fastify: FastifyInstance) { fastify.get('/', { schema: indexSchema }, async (_, reply) => { return reply.view('/templates/index.ejs', { - packageJSON, engineList, - config: getConfig(), + config, }); }); } diff --git a/src/routes/browser/proxy.ts b/src/routes/browser/proxy.ts index 9ec78c1..68a2b02 100644 --- a/src/routes/browser/proxy.ts +++ b/src/routes/browser/proxy.ts @@ -2,8 +2,8 @@ import { FastifyInstance } from 'fastify'; import { IProxySchema, ProxySchema } from '../../types/requests/browser'; import axios from '../../types/axios'; import sharp from 'sharp'; -import getConfig from '../../config/main'; import { UnsupportedMimetypeError } from '../../errors/main'; +import config from '../../config'; export default async function proxyRoute(fastify: FastifyInstance) { fastify.get( @@ -21,7 +21,7 @@ export default async function proxyRoute(fastify: FastifyInstance) { } ); - if (getConfig().proxy.img_compress) + if (config.env.proxy.img_compress) fastify.get( '/proxy/img', { schema: ProxySchema }, diff --git a/src/types/appConfig.ts b/src/types/appConfig.ts new file mode 100644 index 0000000..49bccd6 --- /dev/null +++ b/src/types/appConfig.ts @@ -0,0 +1,5 @@ +import { Engine } from '@txtdot/sdk'; + +export interface IAppConfig { + engines: Engine[]; +} diff --git a/src/types/requests/api.ts b/src/types/requests/api.ts index 07e353a..91e49c2 100644 --- a/src/types/requests/api.ts +++ b/src/types/requests/api.ts @@ -1,6 +1,6 @@ import { FastifySchema, FastifyRequest } from 'fastify'; import { IApiError, errorResponseSchema } from '../../errors/api'; -import { engineList } from '../../handlers/main'; +import { engineList } from '../../plugin_manager'; import { FromSchema } from 'json-schema-to-ts'; import { handlerSchema } from '@txtdot/sdk/dist/types/handler'; diff --git a/src/types/requests/browser.ts b/src/types/requests/browser.ts index 350848f..587e60e 100644 --- a/src/types/requests/browser.ts +++ b/src/types/requests/browser.ts @@ -1,5 +1,5 @@ import { FastifySchema } from 'fastify'; -import { engineList } from '../../handlers/main'; +import { engineList } from '../../plugin_manager'; import { FromSchema } from 'json-schema-to-ts'; export interface IGetSchema { diff --git a/src/utils/replace-href.ts b/src/utils/replace-href.ts index f32ce17..4c38e66 100644 --- a/src/utils/replace-href.ts +++ b/src/utils/replace-href.ts @@ -1,5 +1,5 @@ +import config from '../config'; import { generateParserUrl, generateProxyUrl } from './generate'; -import getConfig from '../config/main'; export default function replaceHref( dom: Window, @@ -21,9 +21,7 @@ export default function replaceHref( modifyLinks(doc.querySelectorAll('a[href]'), 'href', parserUrl); modifyLinks(doc.querySelectorAll('frame,iframe'), 'src', parserUrl); - const config = getConfig(); - - if (config.proxy.enabled) { + if (config.env.proxy.enabled) { modifyLinks( doc.querySelectorAll('video,audio,embed,track,source'), 'src', @@ -33,7 +31,7 @@ export default function replaceHref( modifyLinks( doc.querySelectorAll('img,image'), 'src', - config.proxy.img_compress ? imgProxyUrl : proxyUrl + config.env.proxy.img_compress ? imgProxyUrl : proxyUrl ); modifyLinks(doc.getElementsByTagName('object'), 'data', proxyUrl); diff --git a/templates/components/form-main.ejs b/templates/components/form-main.ejs index 5b22f68..cc40e82 100644 --- a/templates/components/form-main.ejs +++ b/templates/components/form-main.ejs @@ -1,4 +1,4 @@ -<% search = config.third_party.searx_url %> +<% search = config.env.third_party.searx_url %> <% @@ -19,7 +19,7 @@ if (search) {
- + <% } diff --git a/templates/components/menu.ejs b/templates/components/menu.ejs index be3ba60..44b24f3 100644 --- a/templates/components/menu.ejs +++ b/templates/components/menu.ejs @@ -2,12 +2,12 @@ Home Original page <% - if (config.third_party.searx_url) { + if (config.env.third_party.searx_url) { %> <% } diff --git a/templates/components/search-styles.ejs b/templates/components/search-styles.ejs index a362cf8..f0404b8 100644 --- a/templates/components/search-styles.ejs +++ b/templates/components/search-styles.ejs @@ -1,5 +1,5 @@ <% - if (config.third_party.searx_url) { + if (config.env.third_party.searx_url) { %> <% } diff --git a/templates/configuration.ejs b/templates/configuration.ejs index 98a546c..db0f7e4 100644 --- a/templates/configuration.ejs +++ b/templates/configuration.ejs @@ -17,7 +17,7 @@ - + txt. configuration @@ -29,11 +29,11 @@ -

<%= packageJSON.description %>

+

<%= config.package.description %>

Configuration

-
  version: <%= packageJSON.version %><%= to_pretty(config) %>
+
  version: <%= config.package.version %><%= to_pretty(config.env) %>

Available engines

    <% @@ -44,7 +44,7 @@

Available routes

<% - for (const route of dynConfig.routes) { + for (const route of config.dyn.routes) { %><%= route %><% } %> diff --git a/templates/index.ejs b/templates/index.ejs index fc9c06e..70dd048 100644 --- a/templates/index.ejs +++ b/templates/index.ejs @@ -4,7 +4,7 @@ - + txt. main page @@ -16,11 +16,11 @@

txt.

-

<%= packageJSON.description %>

+

<%= config.package.description %>

<%- include('./components/form-main.ejs') %>