UNPKG

trifid-core

Version:
207 lines (175 loc) 5.9 kB
// @ts-check import './tracing.js' import EventEmitter from 'node:events' import pino from 'pino' import fastify from 'fastify' import fastifyCompress from '@fastify/compress' import fastifyCors from '@fastify/cors' import fastifyCookie from '@fastify/cookie' import fastifyAccepts from '@fastify/accepts' import fastifyFormBody from '@fastify/formbody' import handler from './lib/config/handler.js' import { defaultHost, defaultLogLevel, defaultLogFormat, defaultPort, } from './lib/config/default.js' import pluginsAssembler from './lib/plugins/assembler.js' import applyPlugins from './lib/plugins/apply.js' import templateEngine from './lib/templateEngine.js' import { errorsHandler, notFoundHandler } from './lib/handlers/index.js' // Export some useful functions to work with SPARQL export { supportedTypes as sparqlSupportedTypes, serializeFormattedStream as sparqlSerializeFormattedStream, serializeQuadStream as sparqlSerializeQuadStream, getRewriteConfiguration as sparqlGetRewriteConfiguration, } from './lib/sparql.js' // Export some functions that can be used for testing export { assertRejection, getListenerURL, } from './lib/test.js' /** * Create a new Trifid instance. * * @param {import('./types/index.js').TrifidConfigWithExtends?} config Trifid configuration. * @param {Record<string, { * order?: number, * module: import('./types/index.js').TrifidPlugin, * paths?: string | string[]; * methods?: string | string[]; * hosts?: string | string[]; * config?: Record<string, any>; * }>?} additionalPlugins Add additional plugins. * @returns {Promise<{ * start: () => Promise<import('fastify').FastifyInstance>; * server: import('fastify').FastifyInstance; * config: import('./types/index.js').TrifidConfig * }>} Trifid instance. */ const trifid = async (config, additionalPlugins = {}) => { const trifidEvents = new EventEmitter() const fullConfig = await handler(config) const serverOptions = fullConfig?.server?.options || {} // Template configuration const template = fullConfig?.template || {} // Dynamic server configuration const portFromConfig = fullConfig?.server?.listener?.port const port = (portFromConfig === 0 || portFromConfig === '0') ? 0 : (portFromConfig || defaultPort) const host = fullConfig?.server?.listener?.host || defaultHost const portNumber = typeof port === 'string' ? parseInt(port, 10) : port // Logger configuration const logLevel = fullConfig?.server?.logLevel || defaultLogLevel const logFormat = fullConfig?.server?.logFormat || defaultLogFormat const loggerConfig = { name: 'trifid-core', level: logLevel, } if (logFormat === 'pretty') { loggerConfig.transport = { target: 'pino-pretty', } } // Custom logger instance const logger = pino(loggerConfig) const server = await fastify({ logger: false, trustProxy: true, ...serverOptions, }) // Register fastifyCompress and add custom compressible mime-types (in addition to mime-db) await server.register(fastifyCompress, { customTypes: /(turtle|n-triples|n-quads|trig|json)(;.+)?$/ }) // Add support for `application/sparql-query` content type server.addContentTypeParser('application/sparql-query', (_request, payload, done) => { const data = [] payload.on('data', (chunk) => data.push(chunk)) payload.on('end', () => { try { const parsed = data.join('') done(null, parsed) } catch (err) { done(err, undefined) } }) }) // This can be used to pass data from multiple plugins /** @type {Map<string, any>} */ const trifidLocals = new Map() server.decorate('locals', trifidLocals) /** * Handler to add a session to the request. * * @param {import('fastify').FastifyRequest & { session: Map<string, any> }} request Request. * @param {import('fastify').FastifyReply} _reply Reply. * @param {import('fastify').DoneFuncWithErrOrRes} done Done. */ const addSessionHandler = (request, _reply, done) => { request.session = new Map() done() } server.addHook('onRequest', addSessionHandler) // Add required plugins server.register(fastifyCors, { credentials: true, origin: true, }) // Add support for cookies server.register(fastifyCookie) // Add support for Accept header parser server.register(fastifyAccepts) // Add support for `application/x-www-form-urlencoded` content type server.register(fastifyFormBody) // Template engine configuration const templateEngineInstance = await templateEngine(template, trifidLocals) const { render } = templateEngineInstance // Add error and not found handlers (requires template engine to be ready) server.setErrorHandler(errorsHandler) server.setNotFoundHandler(await notFoundHandler({ render })) const plugins = await pluginsAssembler( fullConfig, additionalPlugins, ) await applyPlugins( server, fullConfig.globals, plugins, logger, templateEngineInstance, `http://${host}:${portNumber}/`, trifidEvents, ) const start = async () => { // Forward server events to the Trifid plugins server.addHook('onListen', () => { trifidEvents.emit('listen') }) server.addHook('onClose', () => { trifidEvents.emit('close') }) server.addHook('onReady', () => { trifidEvents.emit('ready') }) // Start server await server.listen({ port: portNumber, host, }) // Log server address const fastifyAddresses = server.addresses().map((address) => { if (typeof address === 'string') { return address } return `http://${address.address}:${address.port}` }) logger.info(`Server listening on ${fastifyAddresses.join(', ')}`) return server } return { start, server, config: fullConfig, } } export default trifid