Skip to content

Commit

Permalink
Add support for --graph flag (#1858)
Browse files Browse the repository at this point in the history
* Add --graph flag to all commands

This commit adds a --graph flag (alias -g) which can be set for all CLI
commands. There is no handling in this commit.
  • Loading branch information
zionts authored Mar 30, 2020
1 parent fe1ec25 commit 9ffe78d
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 87 deletions.
10 changes: 5 additions & 5 deletions packages/apollo-language-server/src/config/__tests__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
ApolloConfig,
ApolloConfigFormat,
getServiceFromKey,
getServiceName,
getGraphIdFromConfig,
isClientConfig,
isLocalServiceConfig,
isServiceConfig,
Expand Down Expand Up @@ -36,25 +36,25 @@ describe("getServiceName", () => {
const rawConfig: ApolloConfigFormat = {
client: { service: "my-service" }
};
expect(getServiceName(rawConfig)).toEqual("my-service");
expect(getGraphIdFromConfig(rawConfig)).toEqual("my-service");

const rawConfigWithTag: ApolloConfigFormat = {
client: { service: "my-service@master" }
};
expect(getServiceName(rawConfigWithTag)).toEqual("my-service");
expect(getGraphIdFromConfig(rawConfigWithTag)).toEqual("my-service");
});

it("finds service name when client.service is an object", () => {
const rawConfig: ApolloConfigFormat = {
client: { service: { name: "my-service" } }
};
expect(getServiceName(rawConfig)).toEqual("my-service");
expect(getGraphIdFromConfig(rawConfig)).toEqual("my-service");
});
});
describe("service config", () => {
it("finds service name from raw service config", () => {
const rawConfig: ApolloConfigFormat = { service: { name: "my-service" } };
expect(getServiceName(rawConfig)).toEqual("my-service");
expect(getGraphIdFromConfig(rawConfig)).toEqual("my-service");
});
});
});
Expand Down
29 changes: 20 additions & 9 deletions packages/apollo-language-server/src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { dirname } from "path";
import merge from "lodash.merge";
import { ServiceID, ServiceSpecifier, ClientID } from "../engine";
import { ClientID, ServiceID, ServiceSpecifier } from "../engine";
import URI from "vscode-uri";
import { WithRequired } from "apollo-env";
import { getServiceName, parseServiceSpecifier } from "./utils";
import { getGraphIdFromConfig, parseServiceSpecifier } from "./utils";
import { ValidationRule } from "graphql/validation/ValidationContext";

export interface EngineStatsWindow {
Expand Down Expand Up @@ -132,16 +132,16 @@ export class ApolloConfig {
public isClient: boolean;
public isService: boolean;
public engine: EngineConfig;
public name?: string;
public service?: ServiceConfigFormat;
public client?: ClientConfigFormat;
private _variant?: string;
private _graphId?: string;

constructor(public rawConfig: ApolloConfigFormat, public configURI?: URI) {
this.isService = !!rawConfig.service;
this.isClient = !!rawConfig.client;
this.engine = rawConfig.engine!;
this.name = getServiceName(rawConfig);
this._graphId = getGraphIdFromConfig(rawConfig);
this.client = rawConfig.client;
this.service = rawConfig.service;
}
Expand All @@ -162,21 +162,32 @@ export class ApolloConfig {
return configs;
}

set variant(tag: string) {
this._variant = tag;
set variant(variant: string) {
this._variant = variant;
}

get variant(): string {
if (this._variant) return this._variant;
let tag: string = "current";
if (this.client && typeof this.client.service === "string") {
const specifierTag = parseServiceSpecifier(this.client
.service as ServiceSpecifier)[1];
if (specifierTag) tag = specifierTag;
const parsedVariant = parseServiceSpecifier(this.client.service)[1];
if (parsedVariant) tag = parsedVariant;
} else if (this.service && typeof this.service.name === "string") {
const parsedVariant = parseServiceSpecifier(this.service.name)[1];
if (parsedVariant) tag = parsedVariant;
}
return tag;
}

set graph(graphId: string | undefined) {
this._graphId = graphId;
}

get graph(): string | undefined {
if (this._graphId) return this._graphId;
return getGraphIdFromConfig(this.rawConfig);
}

// this type needs to be an "EveryKeyIsOptionalApolloConfig"
public setDefaults({ client, engine, service }: any): void {
const config = merge(this.rawConfig, { client, engine, service });
Expand Down
5 changes: 3 additions & 2 deletions packages/apollo-language-server/src/config/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ export function getServiceFromKey(key?: string) {
return;
}

export function getServiceName(config: ApolloConfigFormat) {
if (config.service) return config.service.name;
export function getGraphIdFromConfig(config: ApolloConfigFormat) {
if (config.service && config.service.name)
return parseServiceSpecifier(config.service.name)[0];
if (config.client) {
if (typeof config.client.service === "string") {
return parseServiceSpecifier(config.client
Expand Down
4 changes: 2 additions & 2 deletions packages/apollo-language-server/src/project/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class GraphQLClientProject extends GraphQLProject {

super({ config, fileSet, loadingHandler, clientIdentity });
this.rootURI = rootURI;
this.serviceID = config.name;
this.serviceID = config.graph;

/**
* This function is used in the Array.filter function below it to remove any .env files and config files.
Expand Down Expand Up @@ -149,7 +149,7 @@ export class GraphQLClientProject extends GraphQLProject {
}

get displayName(): string {
return this.config.name || "Unnamed Project";
return this.config.graph || "Unnamed Project";
}

initialize() {
Expand Down
2 changes: 1 addition & 1 deletion packages/apollo-language-server/src/project/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class GraphQLServiceProject extends GraphQLProject {
}

get displayName() {
return this.config.name || "Unnamed Project";
return this.config.graph || "Unnamed Project";
}

initialize() {
Expand Down
22 changes: 5 additions & 17 deletions packages/apollo-language-server/src/providers/schema/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ export class EngineSchemaProvider implements GraphQLSchemaProvider {
if (this.schema && (!override || !override.force)) return this.schema;
const { engine, client } = this.config;

if (typeof client.service !== "string") {
if (!this.config.graph) {
throw new Error(
`Service name not found for client, found ${client.service}`
`No graph ID found for client. Please specify a graph ID via the config or the --graph flag`
);
}

Expand All @@ -47,23 +47,11 @@ export class EngineSchemaProvider implements GraphQLSchemaProvider {
);
}

const [id, tag = "current"] = parseServiceSpecifier(client.service);

// make sure the API key is valid for the service we're requesting a schema of.
if (isServiceKey(engine.apiKey)) {
const keyServiceName = getServiceFromKey(engine.apiKey);
if (id !== keyServiceName) {
throw new Error(
`API key service name \`${keyServiceName}\` does not match the service name in your config \`${id}\`. Try changing the service name in your config to \`${keyServiceName}\` or get a new key.`
);
}
}

const { data, errors } = await this.client.execute<GetSchemaByTag>({
query: SCHEMA_QUERY,
variables: {
id,
tag: override && override.tag ? override.tag : tag
id: this.config.graph,
tag: override && override.tag ? override.tag : this.config.variant
}
});
if (errors) {
Expand All @@ -73,7 +61,7 @@ export class EngineSchemaProvider implements GraphQLSchemaProvider {

if (!(data && data.service && data.service.__typename === "Service")) {
throw new Error(
`Unable to get schema from Apollo Graph Manager for graph ${id}`
`Unable to get schema from Apollo Graph Manager for graph ${this.config.graph}`
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
ApolloConfig,
isClientConfig,
isServiceConfig,
isLocalServiceConfig
isLocalServiceConfig,
ClientConfig
} from "../../config";

import { EndpointSchemaProvider } from "./endpoint";
Expand Down Expand Up @@ -64,6 +65,10 @@ export function schemaProviderFromConfig(
}
}

if (config.graph && config.engine) {
return new EngineSchemaProvider(config as ClientConfig, clientIdentity);
}

throw new Error(
"No schema provider was created, because the project type was unable to be resolved from your config. Please add either a client or service config. For more information, please refer to https://go.apollo.dev/t/config"
);
Expand Down
40 changes: 30 additions & 10 deletions packages/apollo/src/Command.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import Command, { flags } from "@oclif/command";
import Listr from "listr";
import { ListrTask } from "listr";
import Listr, { ListrTask } from "listr";
import { parse, resolve } from "path";

import {
ApolloConfig,
Debug,
getGraphIdFromConfig,
getServiceFromKey,
GraphQLClientProject,
GraphQLProject,
GraphQLServiceProject,
GraphQLClientProject,
loadConfig,
isClientConfig,
isServiceConfig,
ApolloConfig,
getServiceFromKey,
Debug
loadConfig
} from "apollo-language-server";
import { WithRequired, DeepPartial } from "apollo-env";
import { DeepPartial, WithRequired } from "apollo-env";
import { OclifLoadingHandler } from "./OclifLoadingHandler";
import URI from "vscode-uri";
import { tagFlagDeprecatedWarning } from "./utils/sharedMessages";
import chalk from "chalk";

const { version, referenceID } = require("../package.json");

Expand All @@ -38,6 +38,7 @@ export interface Flags {
frontend?: string;
tag?: string;
variant?: string;
graph?: string;
skipSSLValidation?: boolean;
}

Expand Down Expand Up @@ -147,8 +148,14 @@ export abstract class ProjectCommand extends Command {
}

config.variant = flags.variant || flags.tag || config.variant;
config.graph = flags.graph || getGraphIdFromConfig(config.rawConfig);

if (flags.tag) {
console.warn(tagFlagDeprecatedWarning);
console.warn(
chalk.yellow(
"Using the --tag flag is deprecated. Please use --variant (or -v) instead."
)
);
}
// flag overrides
config.setDefaults({
Expand Down Expand Up @@ -197,6 +204,14 @@ export abstract class ProjectCommand extends Command {
config.setDefaults(defaults);
}

const [tokenType, identifier] =
(config.engine.apiKey && config.engine.apiKey.split(":")) || [];
if (tokenType == "service" && identifier !== config.graph) {
throw new Error(
`Cannot specify a service token that does not match graph. Graph ${config.graph} does not match graph from token (${identifier})`
);
}

return config;
}

Expand Down Expand Up @@ -298,6 +313,11 @@ export abstract class ClientCommand extends ProjectCommand {
"The variant of the graph in Apollo Graph Manager to associate this client to",
exclusive: ["tag"]
}),
graph: flags.string({
char: "g",
description:
"The ID for the graph in Apollo Graph Manager to operate client commands with. Overrides config file if set."
}),
queries: flags.string({
description: "Deprecated in favor of the includes flag"
}),
Expand Down
4 changes: 2 additions & 2 deletions packages/apollo/src/commands/client/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class ClientCheck extends ClientCommand {
{
title: "Checking client compatibility with service",
task: async ctx => {
if (!config.name) {
if (!config.graph) {
throw graphUndefinedError;
}
ctx.gitContext = await gitInfo(this.log);
Expand All @@ -59,7 +59,7 @@ export default class ClientCheck extends ClientCommand {
}));

ctx.validationResults = await project.engine.validateOperations({
id: config.name,
id: config.graph,
tag: config.variant,
operations: ctx.operations.map(({ body, name }) => ({
body,
Expand Down
6 changes: 3 additions & 3 deletions packages/apollo/src/commands/client/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ export default class ClientPush extends ClientCommand {
},
{
title: `Checked operations against ${chalk.cyan(
config.name + "@" + config.variant
config.graph + "@" + config.variant
)}`,
task: async () => {}
},
{
title: "Pushing operations to operation registry",
task: async (_, task) => {
if (!config.name) {
if (!config.graph) {
throw graphUndefinedError;
}

Expand All @@ -84,7 +84,7 @@ export default class ClientPush extends ClientCommand {
identifier: referenceID || name,
version
},
id: config.name,
id: config.graph,
operations: operationManifest,
manifestVersion: 2,
graphVariant: config.variant
Expand Down
Loading

0 comments on commit 9ffe78d

Please sign in to comment.