UNPKG

wgc

Version:

The official CLI tool to manage the GraphQL Federation Platform Cosmo

215 lines (212 loc) 5.85 kB
/* eslint-disable import/named */ import { existsSync, readFileSync, writeFileSync } from 'node:fs'; import { federateSubgraphs, ROUTER_COMPATIBILITY_VERSION_ONE, } from '@wundergraph/composition'; import boxen from 'boxen'; import { buildClientSchema, printSchema } from 'graphql'; import yaml from 'js-yaml'; import pc from 'picocolors'; import { program } from 'commander'; import { isValidSubscriptionProtocol, isValidWebsocketSubprotocol, } from '@wundergraph/cosmo-shared'; import { config, configFile } from './core/config.js'; const introspectionQuery = `query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }`; const sdlQuery = ` { _service{ sdl } } `; export const introspectSubgraph = async ({ subgraphURL, additionalHeaders, rawIntrospection, }) => { const headers = new Headers(); headers.append('Content-Type', 'application/json'); for (const header of additionalHeaders) { headers.append(header.key, header.value); } const graphql = JSON.stringify({ query: rawIntrospection ? introspectionQuery : sdlQuery, variables: {}, }); const response = await fetch(subgraphURL, { method: 'POST', headers, body: graphql, }); if (response.status !== 200) { return { success: false, errorMessage: 'Could not introspect the subgraph.', sdl: '', }; } const body = await response.json(); const data = body.data; const sdl = rawIntrospection ? printSchema(buildClientSchema(data)) : data._service.sdl; return { success: true, sdl, }; }; /** * Composes a list of subgraphs into a single schema. */ export function composeSubgraphs(subgraphs, disableResolvabilityValidation) { // @TODO get router compatibility version programmatically return federateSubgraphs({ disableResolvabilityValidation, subgraphs, version: ROUTER_COMPATIBILITY_VERSION_ONE }); } export const readConfigFile = () => { if (!existsSync(configFile)) { return {}; } const data = yaml.load(readFileSync(configFile, 'utf8')); return data !== null && data !== void 0 ? data : {}; }; export const updateConfigFile = (newData) => { const existingData = readConfigFile(); const updatedData = yaml.dump({ ...existingData, ...newData, }); writeFileSync(configFile, updatedData); }; export const checkForUpdates = async () => { try { if (config.disableUpdateCheck === 'true') { return; } const currentTime = Date.now(); const configFileData = readConfigFile(); if (configFileData.lastUpdateCheck && currentTime - configFileData.lastUpdateCheck < 24 * 60 * 60 * 1000) { return; } const response = await fetch(`https://registry.npmjs.org/wgc/latest`); const latestVersion = (await response.json()).version; if (config.version === latestVersion) { return; } const message = `Update available! ${pc.red(config.version)}${pc.green(latestVersion)} Changelog: https://github.com/wundergraph/cosmo/releases/tag/wgc@${latestVersion} Run npm i -g wgc@latest`; console.warn(boxen(message, { padding: 1, margin: 1, align: 'center', borderColor: 'yellow', borderStyle: 'round', })); updateConfigFile({ lastUpdateCheck: currentTime, }); } catch (e) { throw new Error(`Failed to check for updates. You can disable update check by setting env DISABLE_UPDATE_CHECK=true. ${e.message}`); } }; export const validateSubscriptionProtocols = ({ subscriptionProtocol, websocketSubprotocol, }) => { if (subscriptionProtocol && !isValidSubscriptionProtocol(subscriptionProtocol)) { program.error(pc.red(pc.bold(`The subscription protocol '${pc.bold(subscriptionProtocol)}' is not valid. Please use one of the following: sse, sse_post, ws.`))); } if (websocketSubprotocol) { if (subscriptionProtocol && subscriptionProtocol !== 'ws') { program.error(pc.red(pc.bold(`The websocket subprotocol '${pc.bold(websocketSubprotocol)}' can only be used if the subscription protocol is 'ws'.`))); } if (!isValidWebsocketSubprotocol(websocketSubprotocol)) { program.error(pc.red(pc.bold(`The websocket subprotocol '${pc.bold(websocketSubprotocol)}' is not valid. Please use one of the following: auto, graphql-ws, graphql-transport-ws.`))); } } }; //# sourceMappingURL=utils.js.map