UNPKG

@nexica/nestjs-trpc

Version:
241 lines 13 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TRPCFactory = void 0; const common_1 = require("@nestjs/common"); const nestjs_discovery_1 = require("@golevelup/nestjs-discovery"); const constants_1 = require("../constants"); const error_handler_1 = require("../utils/error-handler"); let TRPCFactory = class TRPCFactory { constructor() { Object.defineProperty(this, "discovery", { enumerable: true, configurable: true, writable: true, value: void 0 }); } createAppRouter() { return __awaiter(this, arguments, void 0, function* (options = {}, routerFactory, procedureBuilder) { var _a; if (!this.discovery) { error_handler_1.ErrorHandler.logWarning('TRPCFactory', 'DiscoveryService is not available - unable to discover routers automatically. Returning empty router.'); return routerFactory({}); } try { const routerProviders = yield this.discovery.providersWithMetaAtKey(constants_1.TRPC_ROUTER_METADATA); if (!routerProviders.length) { error_handler_1.ErrorHandler.logWarning('TRPCFactory', 'No router providers found, returning empty router'); return routerFactory({}); } const routers = {}; for (const provider of routerProviders) { try { const discoveredClass = provider.discoveredClass; const instance = discoveredClass === null || discoveredClass === void 0 ? void 0 : discoveredClass.instance; const metatype = discoveredClass === null || discoveredClass === void 0 ? void 0 : discoveredClass.injectType; const metadata = provider.meta; if (!instance || !metatype) { error_handler_1.ErrorHandler.logWarning('TRPCFactory', 'Skipping router - missing instance or metatype'); continue; } const typedInstance = instance; const routerMiddlewareMetadata = Reflect.getMetadata(constants_1.TRPC_ROUTER_MIDDLEWARE_METADATA, metatype); let routerProcedureBuilder = procedureBuilder; if ((_a = routerMiddlewareMetadata === null || routerMiddlewareMetadata === void 0 ? void 0 : routerMiddlewareMetadata.middlewares) === null || _a === void 0 ? void 0 : _a.length) { for (const middleware of routerMiddlewareMetadata.middlewares) { if (typeof middleware === 'string') { const middlewareMethod = typedInstance[middleware]; if (typeof middlewareMethod === 'function') { const middlewareFn = middlewareMethod; routerProcedureBuilder = routerProcedureBuilder.use((opts) => __awaiter(this, void 0, void 0, function* () { yield middlewareFn.call(typedInstance, opts); return opts.next(); })); } } else if (typeof middleware === 'function') { routerProcedureBuilder = routerProcedureBuilder.use(middleware); } } } const procedures = {}; const methods = this.getMethodsWithProcedureMetadata(metatype, instance); for (const methodName of methods) { const procedureResult = this.createProcedureFromMethod(metatype, methodName, typedInstance, routerProcedureBuilder); if (procedureResult) { procedures[procedureResult.path] = procedureResult.procedure; } } if (Object.keys(procedures).length > 0) { const routerName = (metadata === null || metadata === void 0 ? void 0 : metadata.path) || (typeof metatype === 'function' ? metatype.name : 'UnnamedRouter'); routers[routerName] = routerFactory(procedures); } } catch (error) { error_handler_1.ErrorHandler.logError('TRPCFactory', 'Error processing router', error); } } return routerFactory(routers); } catch (error) { error_handler_1.ErrorHandler.logError('TRPCFactory', 'Error creating app router', error); return routerFactory({}); } }); } getMethodsWithProcedureMetadata(target, instance) { const methods = []; const prototype = Object.getPrototypeOf(instance); const methodNames = Object.getOwnPropertyNames(prototype).filter((prop) => prop !== 'constructor' && typeof prototype[prop] === 'function'); for (const method of methodNames) { const metadata = Reflect.getMetadata(constants_1.TRPC_PROCEDURE_METADATA, target, method); if (metadata) { methods.push(method); } } return methods; } createProcedureFromMethod(target, methodName, instance, procedureBuilder) { const procedureMetadata = this.getProcedureMetadata(target, methodName); if (!procedureMetadata) { return null; } const procedure = this.applyMiddleware(target, methodName, instance, procedureBuilder); const configuredProcedure = this.configureInputOutput(procedure, procedureMetadata); const handler = this.createProcedureHandler(target, methodName, instance); const finalProcedure = this.createFinalProcedure(configuredProcedure, handler, procedureMetadata); return { procedure: finalProcedure, path: methodName, }; } getProcedureMetadata(target, methodName) { return Reflect.getMetadata(constants_1.TRPC_PROCEDURE_METADATA, target, methodName) || null; } applyMiddleware(target, methodName, instance, procedureBuilder) { var _a; const middlewareMetadata = Reflect.getMetadata(constants_1.TRPC_MIDDLEWARE_METADATA, target, methodName); let procedure = procedureBuilder; if ((_a = middlewareMetadata === null || middlewareMetadata === void 0 ? void 0 : middlewareMetadata.middlewares) === null || _a === void 0 ? void 0 : _a.length) { for (const middleware of middlewareMetadata.middlewares) { if (typeof middleware === 'string') { const middlewareMethod = instance[middleware]; if (typeof middlewareMethod === 'function') { const middlewareFn = middlewareMethod; procedure = procedure.use((opts) => __awaiter(this, void 0, void 0, function* () { yield middlewareFn.call(instance, opts); return opts.next(); })); } } else if (typeof middleware === 'function') { procedure = procedure.use(middleware); } } } return procedure; } configureInputOutput(procedure, procedureMetadata) { let configuredProcedure = procedure; if (procedureMetadata.input) { if (procedureMetadata.inputName) { const inputWithName = procedureMetadata.input.describe(procedureMetadata.inputName); configuredProcedure = configuredProcedure.input(inputWithName); } else { configuredProcedure = configuredProcedure.input(procedureMetadata.input); } } if (procedureMetadata.output && procedureMetadata.type !== 'subscription') { if (procedureMetadata.outputName) { const outputWithName = procedureMetadata.output.describe(procedureMetadata.outputName); configuredProcedure = configuredProcedure.output(outputWithName); } else { configuredProcedure = configuredProcedure.output(procedureMetadata.output); } } return configuredProcedure; } createProcedureHandler(target, methodName, instance) { const parameterMetadata = this.getParameterMetadata(target, methodName); return (opts) => __awaiter(this, void 0, void 0, function* () { const { input, ctx } = opts; const args = this.buildMethodArguments(input, ctx, parameterMetadata); const method = instance[methodName]; return yield method.apply(instance, args); }); } getParameterMetadata(target, methodName) { const inputParamIndexes = Reflect.getMetadata(constants_1.TRPC_INPUT_PARAM_METADATA, target, methodName) || []; const contextParamIndexes = Reflect.getMetadata(constants_1.TRPC_CONTEXT_PARAM_METADATA, target, methodName) || []; return { inputParamIndexes, contextParamIndexes }; } buildMethodArguments(input, ctx, parameterMetadata) { const { inputParamIndexes, contextParamIndexes } = parameterMetadata; const inputData = input || {}; const contextData = ctx || input; if (inputParamIndexes.length === 0 && contextParamIndexes.length === 0) { return [inputData]; } const methodArgs = []; for (const paramIndex of inputParamIndexes) { methodArgs[paramIndex] = inputData; } for (const paramIndex of contextParamIndexes) { methodArgs[paramIndex] = contextData; } return methodArgs; } createFinalProcedure(procedure, handler, procedureMetadata) { const { type } = procedureMetadata; let finalProcedure; switch (type) { case 'query': finalProcedure = procedure.query(handler); break; case 'mutation': finalProcedure = procedure.mutation(handler); break; case 'subscription': finalProcedure = procedure.subscription(handler); break; default: throw error_handler_1.ErrorHandler.createError('TRPCFactory', `Unknown procedure type: ${String(type)}`); } if (procedureMetadata.output || procedureMetadata.outputName) { ; finalProcedure._def.output = procedureMetadata.output; finalProcedure._def.outputName = procedureMetadata.outputName; } return finalProcedure; } }; exports.TRPCFactory = TRPCFactory; __decorate([ (0, common_1.Inject)(nestjs_discovery_1.DiscoveryService), (0, common_1.Optional)(), __metadata("design:type", nestjs_discovery_1.DiscoveryService) ], TRPCFactory.prototype, "discovery", void 0); exports.TRPCFactory = TRPCFactory = __decorate([ (0, common_1.Injectable)() ], TRPCFactory); //# sourceMappingURL=trpc.factory.js.map