From 3a4992633ee62d5edfbb484d9c6bcb3cf158489d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 31 Jul 2023 14:34:36 +0200 Subject: Migrate server to ESM Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports) --- server/controllers/plugins.ts | 175 ------------------------------------------ 1 file changed, 175 deletions(-) delete mode 100644 server/controllers/plugins.ts (limited to 'server/controllers/plugins.ts') diff --git a/server/controllers/plugins.ts b/server/controllers/plugins.ts deleted file mode 100644 index f0491b16a..000000000 --- a/server/controllers/plugins.ts +++ /dev/null @@ -1,175 +0,0 @@ -import express from 'express' -import { join } from 'path' -import { logger } from '@server/helpers/logger' -import { CONFIG } from '@server/initializers/config' -import { buildRateLimiter } from '@server/middlewares' -import { optionalAuthenticate } from '@server/middlewares/auth' -import { getCompleteLocale, is18nLocale } from '../../shared/core-utils/i18n' -import { HttpStatusCode } from '../../shared/models/http/http-error-codes' -import { PluginType } from '../../shared/models/plugins/plugin.type' -import { isProdInstance } from '../helpers/core-utils' -import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants' -import { PluginManager, RegisteredPlugin } from '../lib/plugins/plugin-manager' -import { getExternalAuthValidator, getPluginValidator, pluginStaticDirectoryValidator } from '../middlewares/validators/plugins' -import { serveThemeCSSValidator } from '../middlewares/validators/themes' - -const sendFileOptions = { - maxAge: '30 days', - immutable: isProdInstance() -} - -const pluginsRouter = express.Router() - -const pluginsRateLimiter = buildRateLimiter({ - windowMs: CONFIG.RATES_LIMIT.PLUGINS.WINDOW_MS, - max: CONFIG.RATES_LIMIT.PLUGINS.MAX -}) - -pluginsRouter.get('/plugins/global.css', - pluginsRateLimiter, - servePluginGlobalCSS -) - -pluginsRouter.get('/plugins/translations/:locale.json', - pluginsRateLimiter, - getPluginTranslations -) - -pluginsRouter.get('/plugins/:pluginName/:pluginVersion/auth/:authName', - pluginsRateLimiter, - getPluginValidator(PluginType.PLUGIN), - getExternalAuthValidator, - handleAuthInPlugin -) - -pluginsRouter.get('/plugins/:pluginName/:pluginVersion/static/:staticEndpoint(*)', - pluginsRateLimiter, - getPluginValidator(PluginType.PLUGIN), - pluginStaticDirectoryValidator, - servePluginStaticDirectory -) - -pluginsRouter.get('/plugins/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)', - pluginsRateLimiter, - getPluginValidator(PluginType.PLUGIN), - pluginStaticDirectoryValidator, - servePluginClientScripts -) - -pluginsRouter.use('/plugins/:pluginName/router', - pluginsRateLimiter, - getPluginValidator(PluginType.PLUGIN, false), - optionalAuthenticate, - servePluginCustomRoutes -) - -pluginsRouter.use('/plugins/:pluginName/:pluginVersion/router', - pluginsRateLimiter, - getPluginValidator(PluginType.PLUGIN), - optionalAuthenticate, - servePluginCustomRoutes -) - -pluginsRouter.get('/themes/:pluginName/:pluginVersion/static/:staticEndpoint(*)', - pluginsRateLimiter, - getPluginValidator(PluginType.THEME), - pluginStaticDirectoryValidator, - servePluginStaticDirectory -) - -pluginsRouter.get('/themes/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)', - pluginsRateLimiter, - getPluginValidator(PluginType.THEME), - pluginStaticDirectoryValidator, - servePluginClientScripts -) - -pluginsRouter.get('/themes/:themeName/:themeVersion/css/:staticEndpoint(*)', - pluginsRateLimiter, - serveThemeCSSValidator, - serveThemeCSSDirectory -) - -// --------------------------------------------------------------------------- - -export { - pluginsRouter -} - -// --------------------------------------------------------------------------- - -function servePluginGlobalCSS (req: express.Request, res: express.Response) { - // Only cache requests that have a ?hash=... query param - const globalCSSOptions = req.query.hash - ? sendFileOptions - : {} - - return res.sendFile(PLUGIN_GLOBAL_CSS_PATH, globalCSSOptions) -} - -function getPluginTranslations (req: express.Request, res: express.Response) { - const locale = req.params.locale - - if (is18nLocale(locale)) { - const completeLocale = getCompleteLocale(locale) - const json = PluginManager.Instance.getTranslations(completeLocale) - - return res.json(json) - } - - return res.status(HttpStatusCode.NOT_FOUND_404).end() -} - -function servePluginStaticDirectory (req: express.Request, res: express.Response) { - const plugin: RegisteredPlugin = res.locals.registeredPlugin - const staticEndpoint = req.params.staticEndpoint - - const [ directory, ...file ] = staticEndpoint.split('/') - - const staticPath = plugin.staticDirs[directory] - if (!staticPath) return res.status(HttpStatusCode.NOT_FOUND_404).end() - - const filepath = file.join('/') - return res.sendFile(join(plugin.path, staticPath, filepath), sendFileOptions) -} - -function servePluginCustomRoutes (req: express.Request, res: express.Response, next: express.NextFunction) { - const plugin: RegisteredPlugin = res.locals.registeredPlugin - const router = PluginManager.Instance.getRouter(plugin.npmName) - - if (!router) return res.status(HttpStatusCode.NOT_FOUND_404).end() - - return router(req, res, next) -} - -function servePluginClientScripts (req: express.Request, res: express.Response) { - const plugin: RegisteredPlugin = res.locals.registeredPlugin - const staticEndpoint = req.params.staticEndpoint - - const file = plugin.clientScripts[staticEndpoint] - if (!file) return res.status(HttpStatusCode.NOT_FOUND_404).end() - - return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions) -} - -function serveThemeCSSDirectory (req: express.Request, res: express.Response) { - const plugin: RegisteredPlugin = res.locals.registeredPlugin - const staticEndpoint = req.params.staticEndpoint - - if (plugin.css.includes(staticEndpoint) === false) { - return res.status(HttpStatusCode.NOT_FOUND_404).end() - } - - return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions) -} - -function handleAuthInPlugin (req: express.Request, res: express.Response) { - const authOptions = res.locals.externalAuth - - try { - logger.debug('Forwarding auth plugin request in %s of plugin %s.', authOptions.authName, res.locals.registeredPlugin.npmName) - authOptions.onAuthRequest(req, res) - } catch (err) { - logger.error('Forward request error in auth %s of plugin %s.', authOptions.authName, res.locals.registeredPlugin.npmName, { err }) - } -} -- cgit v1.2.3