Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 34 additions & 30 deletions src/components/GraphQLVoyagerComponent/GraphQLVoyagerComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import { Header, Page, Content, Progress } from '@backstage/core-components';
import { Config } from '@backstage/config';
import { configApiRef, useApi } from '@backstage/core-plugin-api';
import { Content, Progress } from '@backstage/core-components';
import Alert from '@material-ui/lab/Alert';
import { useAsync } from 'react-use';
import { getIntrospectionQuery } from 'graphql/utilities';
import {
getIntrospectionQuery,
introspectionFromSchema,
buildSchema,
} from "graphql/utilities";
import { Voyager } from 'graphql-voyager';
import fetch from 'isomorphic-fetch';
import 'graphql-voyager/dist/voyager.css';
Expand All @@ -28,41 +30,43 @@ const displayOptions = {
hideRoot: true
};

export const GraphQLVoyagerComponent = () => {
const config: Config = useApi(configApiRef);
const graphqlEndpoint = config.get<{ baseUrl: string }>('graphql').baseUrl;
export const GraphQLVoyagerComponent = ({
endpoint,
sdl,
}: {
endpoint?: string;
sdl?: string;
}) => {
const {
value: result,
loading,
error
} = useAsync(async () => await introspectionProvider(graphqlEndpoint), []);
error,
} = useAsync(async () => {
if (sdl) {
const data = introspectionFromSchema(buildSchema(sdl));
return { data };
}
if (endpoint) {
return await introspectionProvider(endpoint);
}
throw new Error("Must specify endpoint or schema SDL");
}, [endpoint, sdl]);

if (loading) {
return (
<Page themeId='tool'>
<Header
title='Graphql Voyager'
subtitle='A visual representation of the schema.'
/>
<Content>
<Progress />
</Content>
</Page>
<Content>
<Progress />
</Content>
);
} else if (error) {
return <Alert severity='error'>{error.message}</Alert>;
return <Alert severity="error">{error.message}</Alert>;
}

return (
<Page themeId='tool'>
<Header
title='Graphql Voyager'
subtitle='A visual representation of the schema.'
/>
<Voyager
displayOptions={displayOptions}
hideSettings
introspection={result}
/>
</Page>
<Voyager
displayOptions={displayOptions}
hideSettings
introspection={result}
/>
);
};
1 change: 0 additions & 1 deletion src/components/GraphQLVoyagerComponent/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import { GraphQLVoyagerComponent } from './GraphQLVoyagerComponent';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { configApiRef } from '@backstage/core-plugin-api';
Expand All @@ -9,30 +8,31 @@ import {
renderInTestApp,
TestApiProvider
} from '@backstage/test-utils';
import { GraphQLVoyagerPageComponent } from './GraphQLVoyagerPageComponent';

describe('GraphQLVoyagerComponent', () => {
describe("GraphQLVoyagerPageComponent", () => {
const server = setupServer();
// Enable sane handlers for network requests
setupRequestMockHandlers(server);

// setup mock response
beforeEach(() => {
server.use(
rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))),
rest.get("/*", (_, res, ctx) => res(ctx.status(200), ctx.json({})))
);
});

it('should render', async () => {
it("should render", async () => {
const mockConfig = new MockConfigApi({
graphql: { baseUrl: 'https://example.com' }
graphql: { baseUrl: "https://example.com" },
});
const rendered = await renderInTestApp(
<TestApiProvider apis={[[configApiRef, mockConfig]]}>
<GraphQLVoyagerComponent />
<GraphQLVoyagerPageComponent />
</TestApiProvider>
);
expect(
rendered.getByText('A visual representation of the schema.')
rendered.getByText("A visual representation of the schema.")
).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import { Header, Page } from "@backstage/core-components";
import { Config } from "@backstage/config";
import { configApiRef, useApi } from "@backstage/core-plugin-api";
import { GraphQLVoyagerComponent } from "../GraphQLVoyagerComponent/GraphQLVoyagerComponent";

export const GraphQLVoyagerPageComponent = () => {
const config: Config = useApi(configApiRef);
const graphqlEndpoint = config.get<{ baseUrl: string }>("graphql").baseUrl;

return (
<Page themeId="tool">
<Header
title="Graphql Voyager"
subtitle="A visual representation of the schema."
/>
<GraphQLVoyagerComponent endpoint={graphqlEndpoint} />
</Page>
);
};
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { graphqlVoyagerPlugin, GraphqlVoyagerPage } from './plugin';
export { GraphQLVoyagerComponent } from "./components/GraphQLVoyagerComponent/GraphQLVoyagerComponent";
9 changes: 5 additions & 4 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ export const graphqlVoyagerPlugin = createPlugin({

export const GraphqlVoyagerPage = graphqlVoyagerPlugin.provide(
createRoutableExtension({
name: "graphql-voyager",
component: () =>
import('./components/GraphQLVoyagerComponent').then(
(m) => m.GraphQLVoyagerComponent
),
mountPoint: rootRouteRef
import(
"./components/GraphQLVoyagerPageComponent/GraphQLVoyagerPageComponent"
).then((m) => m.GraphQLVoyagerPageComponent),
mountPoint: rootRouteRef,
})
);