UNPKG

uzen

Version:

General-purpose GraphQL subscription server library

91 lines (90 loc) 3.97 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.startServer = startServer; const uWebSockets_js_1 = require("uWebSockets.js"); const uWebSockets_1 = require("graphql-ws/use/uWebSockets"); const index_1 = require("./graphql/index"); const graphql_1 = require("graphql"); const rusty_jwt_1 = require("rusty-jwt"); const JwtValidator_1 = require("./services/JwtValidator"); const redis_pubsub_1 = require("./graphql/redis-pubsub"); function startServer(config) { const accessTokenService = new rusty_jwt_1.RustJWT(config.jwt.access); const refreshTokenService = new rusty_jwt_1.RustJWT(config.jwt.refresh); const { pubsub } = (0, redis_pubsub_1.createRedisPubSub)(config.redis); const yoga = (0, index_1.createGraphQLServer)({ ...config.graphql, pubsub, }); function getAllowedList(cors) { return Array.isArray(cors) ? cors : cors?.origin; } const wsHandler = (0, uWebSockets_1.makeBehavior)({ execute: args => args.rootValue.execute(args), subscribe: args => args.rootValue.subscribe(args), onSubscribe: async (ctx, _, payload) => { const origin = ctx.extra.persistedRequest.headers?.origin; const allowedList = getAllowedList(config.graphql.cors); if (allowedList !== '*' && !allowedList?.includes(origin)) { return [new graphql_1.GraphQLError('ws:Unauthorized: Origin not allowed')]; } const auth = (0, JwtValidator_1.JwtValidator)({ headers: ctx.extra.persistedRequest.headers, aTs: accessTokenService, rTs: refreshTokenService, debug: config.jwt.debug, }); if (!auth) { return [new graphql_1.GraphQLError('ws:Unauthorized: Invalid or missing token claims')]; } const { schema, execute, subscribe, contextFactory, parse, validate } = yoga.getEnveloped({ req: ctx, authorization: auth, }); const args = { schema, operationName: payload.operationName, document: parse(payload.query), variableValues: payload.variables, contextValue: { ...(await contextFactory()), authorization: auth, }, rootValue: { execute, subscribe } }; const errors = validate(args.schema, args.document); if (errors.length) return errors.map((err) => new graphql_1.GraphQLError(err.message)); return args; }, }); return { start() { const PORT = config.port || 3003; const HOST = config.host || 'localhost'; (0, uWebSockets_js_1.App)() .any('/*', (res, req) => { const origin = req.getHeader('origin'); const allowedList = getAllowedList(config.graphql.cors); const allowedOrigin = allowedList === "*" ? allowedList?.includes(origin) ? origin : "" : "*"; res.writeHeader("Access-Control-Allow-Origin", allowedOrigin); res.writeHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.writeHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); res.writeHeader("Access-Control-Allow-Credentials", "true"); if (req.getMethod() === 'options') { res.writeStatus('204 No Content').end(); } else { yoga(res, req); } }) .ws(yoga.graphqlEndpoint, wsHandler) .listen(HOST, PORT, () => { console.log(`Server is running on http://${HOST}:${PORT}`); }); }, }; }