Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for --graph flag #1858

Merged
merged 13 commits into from
Mar 30, 2020
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
14 changes: 10 additions & 4 deletions packages/apollo-language-server/src/graphqlTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ export interface CheckPartialSchema_service_checkPartialSchema_checkSchemaResult
/**
* delta in seconds from current time that determines the start of the window
* for reported metrics included in a schema diff. A day window from the present
* day would have a \`from\` value of -86400. In rare cases, this could be an ISO
* day would have a `from` value of -86400. In rare cases, this could be an ISO
* timestamp if the user passed one in on diff creation
*/
from: any | null;
/**
* delta in seconds from current time that determines the end of the
* window for reported metrics included in a schema diff. A day window
* from the present day would have a \`to\` value of -0. In rare
* from the present day would have a `to` value of -0. In rare
* cases, this could be an ISO timestamp if the user passed one in on diff
* creation
*/
Expand Down Expand Up @@ -207,14 +207,14 @@ export interface CheckSchema_service_checkSchema_diffToPrevious_validationConfig
/**
* delta in seconds from current time that determines the start of the window
* for reported metrics included in a schema diff. A day window from the present
* day would have a \`from\` value of -86400. In rare cases, this could be an ISO
* day would have a `from` value of -86400. In rare cases, this could be an ISO
* timestamp if the user passed one in on diff creation
*/
from: any | null;
/**
* delta in seconds from current time that determines the end of the
* window for reported metrics included in a schema diff. A day window
* from the present day would have a \`to\` value of -0. In rare
* from the present day would have a `to` value of -0. In rare
* cases, this could be an ISO timestamp if the user passed one in on diff
* creation
*/
Expand Down Expand Up @@ -520,7 +520,13 @@ export interface SchemaTagsAndFieldStats_service_stats_fieldStats_metrics {

export interface SchemaTagsAndFieldStats_service_stats_fieldStats {
__typename: "ServiceFieldStatsRecord";
/**
* Dimensions of ServiceFieldStats that can be grouped by.
*/
groupBy: SchemaTagsAndFieldStats_service_stats_fieldStats_groupBy;
/**
* Metrics of ServiceFieldStats that can be aggregated over.
*/
metrics: SchemaTagsAndFieldStats_service_stats_fieldStats_metrics;
}

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 @@ -45,23 +45,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 @@ -71,7 +59,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