Skip to content

Commit 9ffe78d

Browse files
authored
Add support for --graph flag (#1858)
* 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.
1 parent fe1ec25 commit 9ffe78d

17 files changed

Lines changed: 158 additions & 87 deletions

File tree

packages/apollo-language-server/src/config/__tests__/utils.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
ApolloConfig,
33
ApolloConfigFormat,
44
getServiceFromKey,
5-
getServiceName,
5+
getGraphIdFromConfig,
66
isClientConfig,
77
isLocalServiceConfig,
88
isServiceConfig,
@@ -36,25 +36,25 @@ describe("getServiceName", () => {
3636
const rawConfig: ApolloConfigFormat = {
3737
client: { service: "my-service" }
3838
};
39-
expect(getServiceName(rawConfig)).toEqual("my-service");
39+
expect(getGraphIdFromConfig(rawConfig)).toEqual("my-service");
4040

4141
const rawConfigWithTag: ApolloConfigFormat = {
4242
client: { service: "my-service@master" }
4343
};
44-
expect(getServiceName(rawConfigWithTag)).toEqual("my-service");
44+
expect(getGraphIdFromConfig(rawConfigWithTag)).toEqual("my-service");
4545
});
4646

4747
it("finds service name when client.service is an object", () => {
4848
const rawConfig: ApolloConfigFormat = {
4949
client: { service: { name: "my-service" } }
5050
};
51-
expect(getServiceName(rawConfig)).toEqual("my-service");
51+
expect(getGraphIdFromConfig(rawConfig)).toEqual("my-service");
5252
});
5353
});
5454
describe("service config", () => {
5555
it("finds service name from raw service config", () => {
5656
const rawConfig: ApolloConfigFormat = { service: { name: "my-service" } };
57-
expect(getServiceName(rawConfig)).toEqual("my-service");
57+
expect(getGraphIdFromConfig(rawConfig)).toEqual("my-service");
5858
});
5959
});
6060
});

packages/apollo-language-server/src/config/config.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { dirname } from "path";
22
import merge from "lodash.merge";
3-
import { ServiceID, ServiceSpecifier, ClientID } from "../engine";
3+
import { ClientID, ServiceID, ServiceSpecifier } from "../engine";
44
import URI from "vscode-uri";
55
import { WithRequired } from "apollo-env";
6-
import { getServiceName, parseServiceSpecifier } from "./utils";
6+
import { getGraphIdFromConfig, parseServiceSpecifier } from "./utils";
77
import { ValidationRule } from "graphql/validation/ValidationContext";
88

99
export interface EngineStatsWindow {
@@ -132,16 +132,16 @@ export class ApolloConfig {
132132
public isClient: boolean;
133133
public isService: boolean;
134134
public engine: EngineConfig;
135-
public name?: string;
136135
public service?: ServiceConfigFormat;
137136
public client?: ClientConfigFormat;
138137
private _variant?: string;
138+
private _graphId?: string;
139139

140140
constructor(public rawConfig: ApolloConfigFormat, public configURI?: URI) {
141141
this.isService = !!rawConfig.service;
142142
this.isClient = !!rawConfig.client;
143143
this.engine = rawConfig.engine!;
144-
this.name = getServiceName(rawConfig);
144+
this._graphId = getGraphIdFromConfig(rawConfig);
145145
this.client = rawConfig.client;
146146
this.service = rawConfig.service;
147147
}
@@ -162,21 +162,32 @@ export class ApolloConfig {
162162
return configs;
163163
}
164164

165-
set variant(tag: string) {
166-
this._variant = tag;
165+
set variant(variant: string) {
166+
this._variant = variant;
167167
}
168168

169169
get variant(): string {
170170
if (this._variant) return this._variant;
171171
let tag: string = "current";
172172
if (this.client && typeof this.client.service === "string") {
173-
const specifierTag = parseServiceSpecifier(this.client
174-
.service as ServiceSpecifier)[1];
175-
if (specifierTag) tag = specifierTag;
173+
const parsedVariant = parseServiceSpecifier(this.client.service)[1];
174+
if (parsedVariant) tag = parsedVariant;
175+
} else if (this.service && typeof this.service.name === "string") {
176+
const parsedVariant = parseServiceSpecifier(this.service.name)[1];
177+
if (parsedVariant) tag = parsedVariant;
176178
}
177179
return tag;
178180
}
179181

182+
set graph(graphId: string | undefined) {
183+
this._graphId = graphId;
184+
}
185+
186+
get graph(): string | undefined {
187+
if (this._graphId) return this._graphId;
188+
return getGraphIdFromConfig(this.rawConfig);
189+
}
190+
180191
// this type needs to be an "EveryKeyIsOptionalApolloConfig"
181192
public setDefaults({ client, engine, service }: any): void {
182193
const config = merge(this.rawConfig, { client, engine, service });

packages/apollo-language-server/src/config/utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ export function getServiceFromKey(key?: string) {
3535
return;
3636
}
3737

38-
export function getServiceName(config: ApolloConfigFormat) {
39-
if (config.service) return config.service.name;
38+
export function getGraphIdFromConfig(config: ApolloConfigFormat) {
39+
if (config.service && config.service.name)
40+
return parseServiceSpecifier(config.service.name)[0];
4041
if (config.client) {
4142
if (typeof config.client.service === "string") {
4243
return parseServiceSpecifier(config.client

packages/apollo-language-server/src/project/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export class GraphQLClientProject extends GraphQLProject {
114114

115115
super({ config, fileSet, loadingHandler, clientIdentity });
116116
this.rootURI = rootURI;
117-
this.serviceID = config.name;
117+
this.serviceID = config.graph;
118118

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

151151
get displayName(): string {
152-
return this.config.name || "Unnamed Project";
152+
return this.config.graph || "Unnamed Project";
153153
}
154154

155155
initialize() {

packages/apollo-language-server/src/project/service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class GraphQLServiceProject extends GraphQLProject {
3636
}
3737

3838
get displayName() {
39-
return this.config.name || "Unnamed Project";
39+
return this.config.graph || "Unnamed Project";
4040
}
4141

4242
initialize() {

packages/apollo-language-server/src/providers/schema/engine.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ export class EngineSchemaProvider implements GraphQLSchemaProvider {
2727
if (this.schema && (!override || !override.force)) return this.schema;
2828
const { engine, client } = this.config;
2929

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

@@ -47,23 +47,11 @@ export class EngineSchemaProvider implements GraphQLSchemaProvider {
4747
);
4848
}
4949

50-
const [id, tag = "current"] = parseServiceSpecifier(client.service);
51-
52-
// make sure the API key is valid for the service we're requesting a schema of.
53-
if (isServiceKey(engine.apiKey)) {
54-
const keyServiceName = getServiceFromKey(engine.apiKey);
55-
if (id !== keyServiceName) {
56-
throw new Error(
57-
`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.`
58-
);
59-
}
60-
}
61-
6250
const { data, errors } = await this.client.execute<GetSchemaByTag>({
6351
query: SCHEMA_QUERY,
6452
variables: {
65-
id,
66-
tag: override && override.tag ? override.tag : tag
53+
id: this.config.graph,
54+
tag: override && override.tag ? override.tag : this.config.variant
6755
}
6856
});
6957
if (errors) {
@@ -73,7 +61,7 @@ export class EngineSchemaProvider implements GraphQLSchemaProvider {
7361

7462
if (!(data && data.service && data.service.__typename === "Service")) {
7563
throw new Error(
76-
`Unable to get schema from Apollo Graph Manager for graph ${id}`
64+
`Unable to get schema from Apollo Graph Manager for graph ${this.config.graph}`
7765
);
7866
}
7967

packages/apollo-language-server/src/providers/schema/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
ApolloConfig,
88
isClientConfig,
99
isServiceConfig,
10-
isLocalServiceConfig
10+
isLocalServiceConfig,
11+
ClientConfig
1112
} from "../../config";
1213

1314
import { EndpointSchemaProvider } from "./endpoint";
@@ -64,6 +65,10 @@ export function schemaProviderFromConfig(
6465
}
6566
}
6667

68+
if (config.graph && config.engine) {
69+
return new EngineSchemaProvider(config as ClientConfig, clientIdentity);
70+
}
71+
6772
throw new Error(
6873
"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"
6974
);

packages/apollo/src/Command.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import Command, { flags } from "@oclif/command";
2-
import Listr from "listr";
3-
import { ListrTask } from "listr";
2+
import Listr, { ListrTask } from "listr";
43
import { parse, resolve } from "path";
54

65
import {
6+
ApolloConfig,
7+
Debug,
8+
getGraphIdFromConfig,
9+
getServiceFromKey,
10+
GraphQLClientProject,
711
GraphQLProject,
812
GraphQLServiceProject,
9-
GraphQLClientProject,
10-
loadConfig,
1113
isClientConfig,
1214
isServiceConfig,
13-
ApolloConfig,
14-
getServiceFromKey,
15-
Debug
15+
loadConfig
1616
} from "apollo-language-server";
17-
import { WithRequired, DeepPartial } from "apollo-env";
17+
import { DeepPartial, WithRequired } from "apollo-env";
1818
import { OclifLoadingHandler } from "./OclifLoadingHandler";
1919
import URI from "vscode-uri";
20-
import { tagFlagDeprecatedWarning } from "./utils/sharedMessages";
20+
import chalk from "chalk";
2121

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

@@ -38,6 +38,7 @@ export interface Flags {
3838
frontend?: string;
3939
tag?: string;
4040
variant?: string;
41+
graph?: string;
4142
skipSSLValidation?: boolean;
4243
}
4344

@@ -147,8 +148,14 @@ export abstract class ProjectCommand extends Command {
147148
}
148149

149150
config.variant = flags.variant || flags.tag || config.variant;
151+
config.graph = flags.graph || getGraphIdFromConfig(config.rawConfig);
152+
150153
if (flags.tag) {
151-
console.warn(tagFlagDeprecatedWarning);
154+
console.warn(
155+
chalk.yellow(
156+
"Using the --tag flag is deprecated. Please use --variant (or -v) instead."
157+
)
158+
);
152159
}
153160
// flag overrides
154161
config.setDefaults({
@@ -197,6 +204,14 @@ export abstract class ProjectCommand extends Command {
197204
config.setDefaults(defaults);
198205
}
199206

207+
const [tokenType, identifier] =
208+
(config.engine.apiKey && config.engine.apiKey.split(":")) || [];
209+
if (tokenType == "service" && identifier !== config.graph) {
210+
throw new Error(
211+
`Cannot specify a service token that does not match graph. Graph ${config.graph} does not match graph from token (${identifier})`
212+
);
213+
}
214+
200215
return config;
201216
}
202217

@@ -298,6 +313,11 @@ export abstract class ClientCommand extends ProjectCommand {
298313
"The variant of the graph in Apollo Graph Manager to associate this client to",
299314
exclusive: ["tag"]
300315
}),
316+
graph: flags.string({
317+
char: "g",
318+
description:
319+
"The ID for the graph in Apollo Graph Manager to operate client commands with. Overrides config file if set."
320+
}),
301321
queries: flags.string({
302322
description: "Deprecated in favor of the includes flag"
303323
}),

packages/apollo/src/commands/client/check.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default class ClientCheck extends ClientCommand {
4141
{
4242
title: "Checking client compatibility with service",
4343
task: async ctx => {
44-
if (!config.name) {
44+
if (!config.graph) {
4545
throw graphUndefinedError;
4646
}
4747
ctx.gitContext = await gitInfo(this.log);
@@ -59,7 +59,7 @@ export default class ClientCheck extends ClientCommand {
5959
}));
6060

6161
ctx.validationResults = await project.engine.validateOperations({
62-
id: config.name,
62+
id: config.graph,
6363
tag: config.variant,
6464
operations: ctx.operations.map(({ body, name }) => ({
6565
body,

packages/apollo/src/commands/client/push.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ export default class ClientPush extends ClientCommand {
5353
},
5454
{
5555
title: `Checked operations against ${chalk.cyan(
56-
config.name + "@" + config.variant
56+
config.graph + "@" + config.variant
5757
)}`,
5858
task: async () => {}
5959
},
6060
{
6161
title: "Pushing operations to operation registry",
6262
task: async (_, task) => {
63-
if (!config.name) {
63+
if (!config.graph) {
6464
throw graphUndefinedError;
6565
}
6666

@@ -84,7 +84,7 @@ export default class ClientPush extends ClientCommand {
8484
identifier: referenceID || name,
8585
version
8686
},
87-
id: config.name,
87+
id: config.graph,
8888
operations: operationManifest,
8989
manifestVersion: 2,
9090
graphVariant: config.variant

0 commit comments

Comments
 (0)