UNPKG

n8n

Version:

n8n Workflow Automation Tool

136 lines 5.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HTTP_METHODS = void 0; exports.resolveRouteArgs = resolveRouteArgs; exports.resolveSuccessStatus = resolveSuccessStatus; exports.apiKeyScopesSatisfy = apiKeyScopesSatisfy; exports.scopesInRequirement = scopesInRequirement; exports.scopeRequirementFromString = scopeRequirementFromString; exports.scopeRequirementToString = scopeRequirementToString; exports.toOpenApiPathTemplate = toOpenApiPathTemplate; exports.resolvePublicApiRoutes = resolvePublicApiRoutes; const decorators_1 = require("@n8n/decorators"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); exports.HTTP_METHODS = [ 'get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace', ]; function isDtoArg(arg, type) { return arg.type === type; } function resolveRouteArgs(controllerClass, handlerName, args) { const argTypes = Reflect.getMetadata('design:paramtypes', controllerClass.prototype, handlerName); const resolved = []; let sawDecoratedArg = false; const paramCount = Math.max(args.length, argTypes?.length ?? 0); for (let index = 0; index < paramCount; index++) { const arg = args[index]; if (!arg) { if (sawDecoratedArg) { throw new n8n_workflow_1.UnexpectedError(`Public API route ${controllerClass.name}.${handlerName} has an undecorated parameter ` + `at index ${index}, after an already-decorated one. Every parameter after the first ` + '@Param/@Body/@Query must also be decorated, or a later argument would silently bind ' + 'to the wrong parameter.'); } continue; } sawDecoratedArg = true; if (arg.type === 'param') { resolved.push(arg); continue; } const paramType = argTypes?.[index]; if (!paramType || !('safeParse' in paramType)) { throw new n8n_workflow_1.UnexpectedError(`Public API route ${controllerClass.name}.${handlerName} is missing a Zod DTO for @${arg.type}`); } resolved.push({ type: arg.type, dto: paramType }); } return resolved; } function resolveSuccessStatus(controllerName, handlerName, successStatus) { if (successStatus === undefined) { throw new n8n_workflow_1.UnexpectedError(`Public API route ${controllerName}.${handlerName} does not declare a success status. Add ` + '`@ApiResponse(200, SomeDto)` if it returns a body, or `@ApiResponse(204)` if it does not.'); } return successStatus; } function apiKeyScopesSatisfy(granted, requirement) { if (!granted) return false; if (typeof requirement === 'string') { return granted.includes(requirement); } if ('anyOf' in requirement) { return requirement.anyOf.some((scope) => granted.includes(scope)); } return requirement.allOf.every((scope) => granted.includes(scope)); } function scopesInRequirement(requirement) { if (typeof requirement === 'string') return [requirement]; return 'anyOf' in requirement ? requirement.anyOf : requirement.allOf; } function scopeRequirementFromString(serialized) { const scopes = serialized .split(',') .map((scope) => scope.trim()) .filter(Boolean); return scopes.length === 1 ? scopes[0] : { anyOf: scopes }; } function scopeRequirementToString(requirement) { if (typeof requirement === 'string') { return requirement; } if ('anyOf' in requirement) { return requirement.anyOf.join(','); } return requirement.allOf.join(','); } function toOpenApiPathTemplate(path) { return path.replace(/:([A-Za-z0-9_]+)/g, '{$1}'); } function resolvePublicApiRoutes() { const metadata = di_1.Container.get(decorators_1.ControllerRegistryMetadata); const resolved = []; for (const controllerClass of metadata.controllerClasses) { const controllerMetadata = metadata.getControllerMetadata(controllerClass); if (!controllerMetadata.isPublicApi) { continue; } const prefix = controllerMetadata.basePath.replace(/\/+/g, '/').replace(/\/$/, ''); for (const [handlerName, route] of controllerMetadata.routes) { const args = resolveRouteArgs(controllerClass, handlerName, route.args); const requestBodyDto = args.find((arg) => isDtoArg(arg, 'body'))?.dto; const requestQueryDto = args.find((arg) => isDtoArg(arg, 'query'))?.dto; const joined = `${prefix}${route.path}`.replace(/\/+/g, '/'); const path = joined.length > 1 ? joined.replace(/\/$/, '') : joined || '/'; resolved.push({ controllerClass, controllerName: controllerClass.name, handlerName, method: route.method, path, args, requestBodyDto, requestQueryDto, responseDto: route.responseDto, successStatus: resolveSuccessStatus(controllerClass.name, handlerName, route.successStatus), apiKeyScope: route.apiKeyScope, summary: route.summary, description: route.description, tags: route.tags, errorResponses: route.errorResponses, deprecated: route.deprecated, }); } } return resolved; } //# sourceMappingURL=public-api-route-resolver.js.map