UNPKG

@whook/whook

Version:

Build strong and efficient REST web services.

179 lines 7.85 kB
import { autoService, location, name } from 'knifecycle'; import { noop } from '../libs/utils.js'; import { ROUTE_ASIDE_COMPONENTS_PROPERTY_MAP, DEFAULT_ROUTE_CONFIG, } from '../types/routes.js'; import { DEFAULT_COMMAND_CONFIG, } from '../types/commands.js'; import { DEFAULT_CRON_CONFIG, } from '../types/crons.js'; import { DEFAULT_TRANSFORMER_CONFIG, } from '../types/transformers.js'; import { DEFAULT_CONSUMER_CONFIG, } from '../types/consumers.js'; /* Architecture Note #2.9.2.1: Definitions loader The `DEFINITIONS` service provide a convenient way to gather your various definitions from the routes, crons or commands you created in the `src/(routes|cron|commands)` folder. */ export const DEFAULT_SECURITY_DEFINITIONS = { securitySchemes: {}, security: [], }; export default location(name('DEFINITIONS', autoService(initDefinitions)), import.meta.url); /** * Initialize the DEFINITIONS service. * @param {Object} services * The services DEFINITIONS depends on * @param {Object} [services.ROUTES_DEFINITIONS] * The API routes modules * @param {Object} [services.COMMANDS_DEFINITIONS] * The commands modules * @param {Object} [services.CRONS_DEFINITIONS] * The crons modules * @param {Object} [services.CONSUMERS_DEFINITIONS] * The consumers modules * @param {Object} [services.TRANSFORMERS_DEFINITIONS] * The transformers modules * @param {Object} [services.log=noop] * An optional logging service * @return {Promise<String>} * A promise of a containing the actual host. */ async function initDefinitions({ ROUTES_DEFINITIONS, COMMANDS_DEFINITIONS, CRONS_DEFINITIONS, CONSUMERS_DEFINITIONS, TRANSFORMERS_DEFINITIONS, SECURITY_DEFINITIONS = DEFAULT_SECURITY_DEFINITIONS, log = noop, }) { log('debug', `🈁 - Generating the DEFINITIONS`); const routesModules = Object.keys(ROUTES_DEFINITIONS).map((key) => ({ file: ROUTES_DEFINITIONS[key].url, module: ROUTES_DEFINITIONS[key].module, })); const commandsModules = Object.keys(COMMANDS_DEFINITIONS).map((key) => ({ file: COMMANDS_DEFINITIONS[key].url, module: COMMANDS_DEFINITIONS[key].module, })); const cronsModules = Object.keys(CRONS_DEFINITIONS).map((key) => ({ file: CRONS_DEFINITIONS[key].url, module: CRONS_DEFINITIONS[key].module, })); const consumersModules = Object.keys(CONSUMERS_DEFINITIONS).map((key) => ({ file: CONSUMERS_DEFINITIONS[key].url, module: CONSUMERS_DEFINITIONS[key].module, })); const transformersModules = Object.keys(TRANSFORMERS_DEFINITIONS).map((key) => ({ file: TRANSFORMERS_DEFINITIONS[key].url, module: TRANSFORMERS_DEFINITIONS[key].module, })); const DEFINITIONS = { paths: routesModules.reduce((paths, { file, module }) => { const definition = module.definition; if (!definition) { log('debug', `🈁 - Handler module at "${file}" exports no definition!`); return paths; } if (paths[definition.path]?.[definition.method]) { log('warning', `⚠️ - Overriding an existing definition ("${definition.method}" "${definition.path}").`); } return { ...paths, ...(definition ? { [definition.path]: { ...(paths[definition.path] || {}), [definition.method]: definition.operation, }, } : {}), }; }, {}), components: { schemas: combineComponents({ log }, 'Schema', routesModules .concat(commandsModules) .concat(cronsModules) .concat(transformersModules) .concat(consumersModules)), parameters: combineComponents({ log }, 'Parameter', routesModules), headers: combineComponents({ log }, 'Header', routesModules), requestBodies: combineComponents({ log }, 'RequestBody', routesModules), responses: combineComponents({ log }, 'Response', routesModules), callbacks: combineComponents({ log }, 'Callback', routesModules), securitySchemes: SECURITY_DEFINITIONS.securitySchemes, }, security: SECURITY_DEFINITIONS.security, configs: {}, }; for (const routeModule of routesModules) { if (!routeModule.module.definition) { continue; } const operationId = routeModule.module.definition.operation.operationId; if (DEFINITIONS.configs[operationId]) { log('error', `💥 - Cannot override an existing definition (${operationId}).`); } DEFINITIONS.configs[operationId] = { type: 'route', config: routeModule.module.definition.config || DEFAULT_ROUTE_CONFIG, path: routeModule.module.definition.path, method: routeModule.module.definition.method, operation: routeModule.module.definition.operation, }; } for (const cronModule of cronsModules) { const name = cronModule.module.definition.name; if (DEFINITIONS.configs[name]) { log('error', `💥 - Cannot override an existing definition (${name}).`); } DEFINITIONS.configs[name] = { type: 'cron', ...cronModule.module.definition, config: cronModule.module.definition.config || DEFAULT_CRON_CONFIG, schedules: cronModule.module.definition.schedules || [], }; } for (const consumerModule of consumersModules) { const name = consumerModule.module.definition.name; if (DEFINITIONS.configs[name]) { log('error', `💥 - Cannot override an existing definition (${name}).`); } DEFINITIONS.configs[name] = { type: 'consumer', ...consumerModule.module.definition, config: consumerModule.module.definition.config || DEFAULT_CONSUMER_CONFIG, }; } for (const transformerModule of transformersModules) { const name = transformerModule.module.definition.name; if (DEFINITIONS.configs[name]) { log('error', `💥 - Cannot override an existing definition (${name}).`); } DEFINITIONS.configs[name] = { type: 'transformer', ...transformerModule.module.definition, config: transformerModule.module.definition.config || DEFAULT_TRANSFORMER_CONFIG, }; } for (const commandModule of commandsModules) { const name = commandModule.module.definition.name; if (DEFINITIONS.configs[name]) { log('error', `💥 - Cannot override an existing definition (${name}).`); } DEFINITIONS.configs[name] = { type: 'command', ...commandModule.module.definition, config: commandModule.module.definition.config || DEFAULT_COMMAND_CONFIG, }; } return DEFINITIONS; } export function combineComponents({ log }, type, modules) { return modules.reduce((components, { module }) => ({ ...components, ...Object.keys(module) .filter((key) => key.endsWith(type)) .reduce((addedComponents, key) => { const component = module[key]; if (addedComponents[component.name]) { log('warning', `⚠️ - Overriding an existing aside component (type: "${type}", name: "${component.name}").`); } return { ...addedComponents, [component.name]: component[ROUTE_ASIDE_COMPONENTS_PROPERTY_MAP[type]], }; }, {}), }), {}); } //# sourceMappingURL=DEFINITIONS.js.map