UNPKG

ruru

Version:

Grafast-flavoured GraphiQL distribution

177 lines 6.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.options = options; exports.run = run; const node_http_1 = require("node:http"); const graphile_config_1 = require("graphile-config"); const load_1 = require("graphile-config/load"); const server_ts_1 = require("./server.js"); const static_ts_1 = require("./static.js"); const DEFAULT_STATIC_PATH = "/ruru-static/"; function options(yargs) { return yargs .usage("$0", "Run a Ruru server") .example("$0 [-SP] [--endpoint http://localhost:5678/graphql]", "Runs a Ruru server accessing the given GraphQL API, with subscriptions support and automatic proxying (to bypass CORS issues)") .option("endpoint", { alias: "e", type: "string", description: "endpoint for query and mutation operations", }) .option("port", { alias: "p", type: "number", description: "port number to run the server on", }) .option("proxy", { alias: "P", type: "boolean", description: "Proxy requests to work around CORS issues", }) .options("subscriptions", { alias: "S", type: "boolean", description: "enable subscriptions, converting --endpoint to a ws:// URL", }) .option("subscription-endpoint", { alias: "s", type: "string", description: "endpoint for subscription operations (overrides -S)", }) .option("config", { alias: "C", type: "string", description: "The path to the graphile.config.mjs (or similar) file", normalize: true, }); } /** * Optionally we proxy the request. */ async function tryLoadHttpProxyCreateProxyServer() { try { const module = (await import("http-proxy")); return module.default?.createProxyServer ?? module.createProxyServer; } catch { return null; } } async function configFromArgs(args) { const { port, endpoint, subscriptionEndpoint, subscriptions, proxy: enableProxy, config: configFileLocation, } = args; const userPreset = await (0, load_1.loadConfig)(configFileLocation); const preset = { extends: [...(userPreset ? [userPreset] : [])], ruru: {}, }; if (port) { preset.ruru.port = port; } if (endpoint) { preset.ruru.endpoint = endpoint; } if (subscriptionEndpoint) { preset.ruru.subscriptionEndpoint = subscriptionEndpoint; } if (subscriptions) { preset.ruru.subscriptions = subscriptions; } if (enableProxy) { preset.ruru.enableProxy = enableProxy; } const config = (0, graphile_config_1.resolvePreset)(preset); return config; } async function run(args) { const config = await configFromArgs(args); const { port = 1337, endpoint = "http://localhost:5678/graphql", subscriptionEndpoint, subscriptions = false, enableProxy, } = config.ruru ?? {}; const createProxyServer = enableProxy ? await tryLoadHttpProxyCreateProxyServer() : null; const proxy = createProxyServer?.({ target: endpoint, ws: true, changeOrigin: true, }); if (enableProxy && !proxy) { throw new Error("Failed to create a proxy - please be sure to install the 'http-proxy' module alongside 'ruru'"); } proxy?.on("error", (e, req, res) => { console.error("Error occurred whilst attempting to proxy:", e); if (res && "writeHead" in res && res.writeHead) { res.writeHead(500, { "Content-Type": "application/json", }); res.end('{"errors": [{"message": "Proxying failed"}]}'); } else if (res) { // Terminate the socket res.end(); } }); const endpointUrl = new URL(endpoint); const subscriptionEndpointUrl = subscriptionEndpoint ? new URL(subscriptionEndpoint) : subscriptions ? (() => { const url = new URL(endpointUrl); url.protocol = endpointUrl.protocol === "https:" ? "wss:" : "ws:"; return url; })() : undefined; const endpointBase = new URL(endpointUrl); endpointBase.pathname = ""; endpointBase.search = ""; endpointBase.hash = ""; const endpointWsBase = new URL(endpointBase); endpointWsBase.protocol = endpointBase.protocol === "https:" ? "wss:" : "ws:"; if (!proxy) { console.log(`If you receive CORS issues, consider installing the 'http-proxy' module alongside 'ruru' and using the '-P' option so that we'll proxy to the API for you`); } const serverConfig = { ...config.ruru, staticPath: config.ruru?.staticPath ?? DEFAULT_STATIC_PATH, endpoint: proxy ? endpointUrl.pathname + endpointUrl.search : endpoint, subscriptionEndpoint: proxy && subscriptionEndpointUrl ? subscriptionEndpointUrl.pathname + subscriptionEndpointUrl.search : subscriptionEndpoint, }; const staticMiddleware = (0, static_ts_1.serveStatic)(serverConfig.staticPath); const server = (0, node_http_1.createServer)((req, res) => { const next = (e) => { if (e) { console.error(`Fatal request error: ${e}`); res.writeHead(500, { "content-type": "text/plain" }); res.end("Internal server error (see logs for details)"); } else if (proxy) { proxy.web(req, res, { target: endpointBase }); } else { res.writeHead(308, { location: "/" }); res.end(); } }; if (req.url === "/" && (!req.headers.accept || /\btext\/html\b/.test(req.headers.accept))) { res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); res.end((0, server_ts_1.ruruHTML)(serverConfig)); } else if (req.url?.startsWith(serverConfig.staticPath)) { staticMiddleware(req, res, next); } else { next(); } }); if (proxy) { server.on("upgrade", (req, socket, head) => { proxy.ws(req, socket, head, { target: endpointWsBase, }); }); } server.listen(port, () => { console.log(`Serving Ruru at http://localhost:${port} for GraphQL API at '${endpoint}'`); }); } //# sourceMappingURL=cli.js.map