Skip to content

Commit

Permalink
FAI-9741: Remove v1 support from FarosClient (#258)
Browse files Browse the repository at this point in the history
  • Loading branch information
ted-faros committed May 29, 2024
1 parent be2a3bb commit ecddcc8
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 135 deletions.
9 changes: 1 addition & 8 deletions src/adapter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,7 @@ export class QueryAdapter {
constructor(
private readonly faros: FarosClient,
private readonly v1Schema: gql.GraphQLSchema
) {
if (faros.graphVersion !== 'v2') {
throw new VError(
'query adapter only works with v2 clients. found version: %s',
faros.graphVersion
);
}
}
) {}

/** Converts a V2 field value into a V1 field value */
private v1Value(v2Value: any, type: LeafValueType): any {
Expand Down
74 changes: 4 additions & 70 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {get as traverse, isEmpty, unset} from 'lodash';
import pino, {Logger} from 'pino';
import {Dictionary} from 'ts-essentials';
import {promisify} from 'util';
import VError from 'verror';
import * as zlib from 'zlib';

import {makeAxiosInstanceWithRetry} from './axios';
Expand All @@ -17,7 +16,6 @@ import {
FarosClientConfig,
GraphVersion,
Location,
Model,
NamedQuery,
Phantom,
SecretName,
Expand All @@ -36,7 +34,6 @@ export const GRAPH_VERSION_HEADER = 'x-faros-graph-version';
/** Faros API client **/
export class FarosClient {
private readonly api: AxiosInstance;
readonly graphVersion: GraphVersion;
readonly phantoms: Phantom;

constructor(
Expand All @@ -46,24 +43,21 @@ export class FarosClient {
) {
const url = Utils.urlWithoutTrailingSlashes(cfg.url);

const useGraphQLV2 = cfg.useGraphQLV2 ?? true;

this.api = makeAxiosInstanceWithRetry(
{
...axiosConfig,
baseURL: url,
headers: {
...axiosConfig?.headers,
authorization: cfg.apiKey,
...(useGraphQLV2 && {[GRAPH_VERSION_HEADER]: 'v2'}),
[GRAPH_VERSION_HEADER]: GraphVersion.V2,
},
maxBodyLength: Infinity, // rely on server to enforce request body size
maxContentLength: Infinity, // accept any response size
},
logger
);

this.graphVersion = useGraphQLV2 ? GraphVersion.V2 : GraphVersion.V1;
this.phantoms = cfg.phantoms || Phantom.IncludeNestedOnly;
}

Expand Down Expand Up @@ -137,47 +131,6 @@ export class FarosClient {
}
}

async models(graph: string): Promise<ReadonlyArray<Model>> {
if (this.graphVersion !== GraphVersion.V1) {
throw new VError(
`listing models is not supported for ${this.graphVersion} graphs`
);
}

try {
const {data} = await this.api.get(`/graphs/${graph}/models`);
return data.models;
} catch (err: any) {
throw wrapApiError(err, `unable to list models: ${graph}`);
}
}

async addModels(
graph: string,
models: string,
schema?: string
): Promise<void> {
if (this.graphVersion !== GraphVersion.V1) {
throw new VError(
`Adding models is not supported for ${this.graphVersion} graphs`
);
}
try {
await this.api.post(`/graphs/${graph}/models`, models, {
headers: {'content-type': 'application/graphql'},
params: {
...(schema && {schema}),
},
});
} catch (err: any) {
throw wrapApiError(err, `failed to add models to graph: ${graph}`);
}
}

async addCanonicalModels(graph: string): Promise<void> {
return await this.addModels(graph, '', 'canonical');
}

async namedQuery(name: string): Promise<NamedQuery | undefined> {
try {
const {data} = await this.api.get(`/queries/${name}`);
Expand All @@ -190,29 +143,11 @@ export class FarosClient {
}
}

async entrySchema(graph: string): Promise<any> {
if (this.graphVersion !== GraphVersion.V1) {
throw new VError(
`entry schema is not supported for ${this.graphVersion} graphs`
);
}

try {
const {data} = await this.api.get(
`/graphs/${graph}/revisions/entries/schema`
);
return data.schema;
} catch (err: any) {
throw wrapApiError(err, `unable to load entry schema of graph: ${graph}`);
}
}

queryParameters(): Dictionary<any> {
const result: Dictionary<any> = {};
if (this.graphVersion === GraphVersion.V2) {
result.phantoms = this.phantoms;
}
return result;
return {
phantoms: this.phantoms,
};
}

private async doGql(
Expand All @@ -223,7 +158,6 @@ export class FarosClient {
try {
let req: any = variables ? {query, variables} : {query};
let doCompression =
this.graphVersion === GraphVersion.V2 &&
Buffer.byteLength(query, 'utf8') > 10 * 1024; // 10KB
if (doCompression) {
try {
Expand Down
2 changes: 0 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
export interface FarosClientConfig {
readonly url: string;
readonly apiKey: string;
readonly useGraphQLV2?: boolean;
readonly phantoms?: Phantom;
}

export enum GraphVersion {
V1 = 'v1',
V2 = 'v2',
}

Expand Down
15 changes: 5 additions & 10 deletions test/adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import _ from 'lodash';
import {FarosClient} from '../src';
import * as sut from '../src/adapter';
import {
graphSchemaForAdapterTest as v1Schema,
graphSchemaV2ForAdapterTest as v2Schema,
toArray,
toIterator} from './helpers';
graphSchemaForAdapterTest as v1Schema,
graphSchemaV2ForAdapterTest as v2Schema,
toArray,
toIterator,
} from './helpers';

describe('AST utilities', () => {
// Sorts fields and removes directives and aliases
Expand Down Expand Up @@ -652,12 +653,6 @@ describe('query adapter', () => {
return adapter.nodes('default', run.v1Query);
}

test('invalid faros client fails', () => {
const faros: FarosClient = {graphVersion: 'v1'} as any;
expect(() => new sut.QueryAdapter(faros, v1Schema))
.toThrowError('query adapter only works with v2 clients');
});

test('query', async () => {
const v1Nodes = asV1Nodes({
v1Query: `
Expand Down
50 changes: 5 additions & 45 deletions test/client.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import nock from 'nock';

import {FarosClient, FarosClientConfig, Schema} from '../src';
import {GRAPH_VERSION_HEADER} from '../src/client';
import {Phantom, WebhookEvent, WebhookEventStatus} from '../src/types';

const apiUrl = 'https://test.faros.ai';
const clientConfig = {url: apiUrl, apiKey: 'test-key', useGraphQLV2: false};
const clientConfig = {url: apiUrl, apiKey: 'test-key'};
const client = new FarosClient(clientConfig);

describe('client', () => {
Expand Down Expand Up @@ -67,23 +66,6 @@ describe('client', () => {
expect(res).toBe(false);
});

test('get models', async () => {
const mock = nock(apiUrl)
.get('/graphs/g1/models')
.reply(200, {
models: [
{name: 'model1', key: ['key1A', 'key1B']},
{name: 'model2', key: ['key2A', 'key2B']},
],
});
const res = await client.models('g1');
mock.done();
expect(res).toEqual([
{name: 'model1', key: ['key1A', 'key1B']},
{name: 'model2', key: ['key2A', 'key2B']},
]);
});

test('get query', async () => {
const mock = nock(apiUrl)
.get('/queries/my-query')
Expand All @@ -96,15 +78,6 @@ describe('client', () => {
});
});

test('get entry schema', async () => {
const mock = nock(apiUrl)
.get('/graphs/g1/revisions/entries/schema')
.reply(200, {schema: []});
const res = await client.entrySchema('g1');
mock.done();
expect(res).toEqual([]);
});

test('gql', async () => {
const query = `{
tms {
Expand All @@ -118,6 +91,7 @@ describe('client', () => {

const mock = nock(apiUrl)
.post('/graphs/g1/graphql', JSON.stringify({query}))
.query({phantoms: Phantom.IncludeNestedOnly})
.reply(200, {data: {tms: {tasks: {nodes: [{uid: '1'}, {uid: '2'}]}}}});

const res = await client.gql('g1', query);
Expand Down Expand Up @@ -167,23 +141,11 @@ describe('client', () => {
expect(res).toStrictEqual(gqlSchema);
});

test('use v2 off by default', async () => {
const mock = nock(apiUrl, {
badheaders: [GRAPH_VERSION_HEADER],
})
.get('/graphs/foobar/graphql/schema')
.reply(200, gqlSchema);

await client.gqlSchema('foobar');
mock.done();
});

test('check v2 header value', async () => {
await expectV2Request(
{
url: apiUrl,
apiKey: 'test-key',
useGraphQLV2: true,
},
true
);
Expand All @@ -193,7 +155,6 @@ describe('client', () => {
cfg: FarosClientConfig,
expected: true | URLSearchParams
) {
expect(cfg.useGraphQLV2).toBeTruthy();
const mock = nock(apiUrl, {
reqheaders: {
// use literal to be sure as variable requires []'s
Expand All @@ -215,7 +176,6 @@ describe('client', () => {
const clientConfig = {
url: apiUrl,
apiKey: 'test-key',
useGraphQLV2: true,
};
await expectV2Request(clientConfig, expected);
});
Expand All @@ -227,7 +187,6 @@ describe('client', () => {
const clientConfig = {
url: apiUrl,
apiKey: 'test-key',
useGraphQLV2: true,
phantoms: Phantom.Exclude,
};
await expectV2Request(clientConfig, expected);
Expand All @@ -245,7 +204,7 @@ describe('client', () => {
.query({phantoms: Phantom.IncludeNestedOnly})
.reply(200, {data: {result: 'ok'}});

const clientConfig = {url: apiUrl, apiKey: 'test-key', useGraphQLV2: true};
const clientConfig = {url: apiUrl, apiKey: 'test-key'};
const client = new FarosClient(clientConfig);

const res = await client.gql('g1', query);
Expand All @@ -269,7 +228,6 @@ describe('client', () => {
const clientConfig = {
url: apiUrl,
apiKey: 'test-key',
useGraphQLV2: true,
};
const client = new FarosClient(clientConfig);
// baseline test
Expand Down Expand Up @@ -314,6 +272,7 @@ describe('client', () => {
'/graphs/g1/graphql',
JSON.stringify({query, variables: {pageSize: 100, after: 'abc'}})
)
.query({phantoms: Phantom.IncludeNestedOnly})
.reply(200, {
data: {tms: {tasks: {edges: [{node: {uid: '1'}}, {node: {uid: '2'}}]}}},
});
Expand All @@ -328,6 +287,7 @@ describe('client', () => {
test('introspect', async () => {
const mock = nock(apiUrl)
.post('/graphs/g1/graphql')
.query({phantoms: Phantom.IncludeNestedOnly})
.reply(200, {
data: {
__schema: {
Expand Down

0 comments on commit ecddcc8

Please sign in to comment.