in cli/src/commands/graph/federated-graph/commands/fetch.ts [9:188]
export default (opts: BaseCommandOptions) => {
const cmd = new Command('fetch');
cmd.description('Fetches the schemas of the federated graph, all of its subgraphs and the router config.');
cmd.argument('<name>', 'The name of the federated graph to fetch.');
cmd.option('-n, --namespace [string]', 'The namespace of the federated graph or monograph.');
cmd.option('-o, --out [string]', 'Destination folder for storing all the required files.');
cmd.option(
'-a, --apollo-compatibility',
'Enable apollo compatibility to generate the composition configs and script to generate schema using rover.',
);
cmd.option(
'-v, --federation-version [string]',
'The version of federation to be used by rover in the format "1", "2", or "2.x.y". Default is 2.5.0.',
);
cmd.action(async (name, options) => {
try {
const fedGraphSchemas = await getFederatedGraphSchemas({
client: opts.client,
name,
namespace: options.namespace,
});
const basePath = resolve(options.out, `${name}${options.namespace ? `-${options.namespace}` : ''}`);
const superGraphPath = join(basePath, '/supergraph/');
const subgraphPath = join(basePath, '/subgraphs/');
const scriptsPath = join(basePath, '/scripts/');
if (!existsSync(superGraphPath)) {
mkdirSync(superGraphPath, { recursive: true });
}
if (!existsSync(subgraphPath)) {
mkdirSync(subgraphPath, { recursive: true });
}
if (!existsSync(scriptsPath) && options.apolloCompatibility) {
mkdirSync(scriptsPath, { recursive: true });
}
const routerConfig = await fetchRouterConfig({
client: opts.client,
name,
namespace: options.namespace,
});
writeFileSync(join(superGraphPath, `cosmoConfig.json`), routerConfig);
writeFileSync(join(superGraphPath, `cosmoSchema.graphql`), fedGraphSchemas.sdl);
if (fedGraphSchemas.clientSchema) {
writeFileSync(join(superGraphPath, `cosmoClientSchema.graphql`), fedGraphSchemas.clientSchema);
}
const subgraphs = await getSubgraphsOfFedGraph({ client: opts.client, name, namespace: options.namespace });
const cosmoSubgraphsConfig: {
name: string;
schema: {
file: string;
};
routing_url?: string;
subscription?: {
url: string;
protocol: string;
};
}[] = [];
const roverSubgraphsConfig: {
[name: string]: {
routing_url: string;
schema: {
file: string;
};
};
} = {};
const roverSubgraphsSubcriptionConfig: {
[name: string]: {
path: string;
protocol: string;
};
} = {};
for (const subgraph of subgraphs) {
const subgraphSDL = await getSubgraphSDL({
client: opts.client,
fedGraphName: name,
namespace: options.namespace,
subgraphName: subgraph.name,
});
if (!subgraphSDL) {
continue;
}
/* The config.yaml should not define a routing URL if the subgraph is an EDG.
* The local routingUrl variable is an empty object when the subgraph is an EDG, and a set property otherwise.
* This variable is spread into the push to ensure the routing URL is only defined when necessary.
* */
const routingUrl = subgraph.isEventDrivenGraph ? {} : { routing_url: subgraph.routingURL };
const filePath = join(subgraphPath, `${subgraph.name}.graphql`);
cosmoSubgraphsConfig.push({
name: subgraph.name,
...routingUrl,
schema: {
file: filePath,
},
subscription:
subgraph.subscriptionURL === '' || subgraph.isEventDrivenGraph
? undefined
: { url: subgraph.subscriptionURL, protocol: subgraph.subscriptionProtocol },
});
if (options.apolloCompatibility) {
roverSubgraphsConfig[subgraph.name] = {
routing_url: subgraph.routingURL,
schema: {
file: filePath,
},
};
if (subgraph.subscriptionURL !== '') {
roverSubgraphsSubcriptionConfig[subgraph.name] = {
path: subgraph.subscriptionURL,
protocol: 'graphql_ws',
};
}
}
writeFileSync(filePath, subgraphSDL);
}
const cosmoCompositionConfig = yaml.dump({
version: 1,
subgraphs: cosmoSubgraphsConfig,
});
writeFileSync(join(basePath, `cosmo-composition.yaml`), cosmoCompositionConfig);
if (options.apolloCompatibility) {
const roverCompositionConfig = yaml.dump({
federation_version: `${
options.federationVersion &&
options.federationVersion.length > 1 &&
!options.federationVersion.startsWith('=')
? '='
: ''
}${options.federationVersion || '=2.5.0'}`,
subgraphs: roverSubgraphsConfig,
subscription:
Object.keys(roverSubgraphsSubcriptionConfig).length === 0
? undefined
: {
enabled: true,
mode: {
passthrough: {
subgraphs: roverSubgraphsSubcriptionConfig,
},
},
},
});
writeFileSync(join(basePath, `rover-composition.yaml`), roverCompositionConfig);
const apolloScript = `npm install -g @apollo/rover
rover supergraph compose --config '${join(basePath, `rover-composition.yaml`)}' --output '${join(
superGraphPath,
'apolloSchema.graphql',
)}'
`;
writeFileSync(join(scriptsPath, `apollo.sh`), apolloScript);
}
console.log(
pc.green(
`Successfully fetched the schemas of the federated graph, all its subgraphs and the router config of the federated graph ${pc.bold(
name,
)}.`,
),
);
} catch (e: any) {
if (e.message) {
console.error(pc.red(e.message));
}
process.exitCode = 1;
// eslint-disable-next-line no-useless-return
return;
}
});
return cmd;
};