Skip to content

Commit

Permalink
fix: take variant name as input while migrating (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
JivusAyrus authored Sep 6, 2023
1 parent 98b8edd commit 6ace9fc
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 36 deletions.
6 changes: 6 additions & 0 deletions connect/src/wg/cosmo/platform/v1/platform_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3985,6 +3985,11 @@ export class MigrateFromApolloRequest extends Message<MigrateFromApolloRequest>
*/
apiKey = "";

/**
* @generated from field: string variantName = 2;
*/
variantName = "";

constructor(data?: PartialMessage<MigrateFromApolloRequest>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -3994,6 +3999,7 @@ export class MigrateFromApolloRequest extends Message<MigrateFromApolloRequest>
static readonly typeName = "wg.cosmo.platform.v1.MigrateFromApolloRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "apiKey", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "variantName", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): MigrateFromApolloRequest {
Expand Down
17 changes: 15 additions & 2 deletions controlplane/src/core/bufservices/PlatformService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1789,10 +1789,23 @@ export default function (opts: RouterOptions): Partial<ServiceImpl<typeof Platfo
};
}

const apolloMigrator = new ApolloMigrator({ apiKey: req.apiKey, organizationSlug: org.slug });
const apolloMigrator = new ApolloMigrator({
apiKey: req.apiKey,
organizationSlug: org.slug,
variantName: req.variantName,
});

const graph = await apolloMigrator.fetchGraphID();
const graphDetails = await apolloMigrator.fetchGraphDetails({ graphID: graph.id, variantName: 'main' });
const graphDetails = await apolloMigrator.fetchGraphDetails({ graphID: graph.id });

if (!graphDetails.success) {
return {
response: {
code: EnumStatusCode.ERR,
details: graphDetails.errorMessage,
},
};
}

if (await fedGraphRepo.exists(graph.name)) {
return {
Expand Down
33 changes: 28 additions & 5 deletions controlplane/src/core/services/ApolloMigrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ import { SubgraphRepository } from '../repositories/SubgraphRepository.js';
export default class ApolloMigrator {
apiKey = '';
organizationSlug = '';
constructor({ apiKey, organizationSlug }: { apiKey: string; organizationSlug: string }) {
variantName = '';
constructor({
apiKey,
organizationSlug,
variantName,
}: {
apiKey: string;
organizationSlug: string;
variantName: string;
}) {
this.apiKey = apiKey;
this.organizationSlug = organizationSlug;
this.variantName = variantName;
}

public async fetchGraphID(): Promise<{ id: string; name: string }> {
Expand Down Expand Up @@ -49,9 +59,11 @@ export default class ApolloMigrator {
}

// fetches the schemas of the subgraphs and the routing url of the federated graph
public async fetchGraphDetails({ graphID, variantName }: { graphID: string; variantName: string }): Promise<{
public async fetchGraphDetails({ graphID }: { graphID: string }): Promise<{
success: boolean;
fedGraphRoutingURL: string;
subgraphs: MigrationSubgraph[];
errorMessage?: string;
}> {
const headers = new Headers();
headers.append('X-API-KEY', this.apiKey);
Expand Down Expand Up @@ -91,20 +103,31 @@ export default class ApolloMigrator {
body: graphql,
});
if (response.status !== 200) {
throw new Error('Could not fetch the subgraphs from apollo.');
return {
success: false,
fedGraphRoutingURL: '',
subgraphs: [],
errorMessage: 'Could not fetch the graphs from apollo.',
};
}
const body = await response.json();
const data = body.data;
const variants: any[] = data.graph.variants;

const variant = variants.find((v: { name: string }) => v.name === variantName);
const variant = variants.find((v: { name: string }) => v.name === this.variantName);

if (!variant) {
throw new Error('Could not find the requested variant of the graph.');
return {
success: false,
fedGraphRoutingURL: '',
subgraphs: [],
errorMessage: 'Could not find the requested variant of the graph.',
};
}
const subgraphs: any[] = variant.subgraphs;

return {
success: true,
fedGraphRoutingURL: variant.url,
subgraphs: subgraphs.map((subgraph) => {
return {
Expand Down
1 change: 1 addition & 0 deletions proto/wg/cosmo/platform/v1/platform.proto
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ message RemoveInvitationResponse {

message MigrateFromApolloRequest {
string apiKey = 1;
string variantName = 2;
}

message MigrateFromApolloResponse {
Expand Down
89 changes: 60 additions & 29 deletions studio/src/components/federatedgraphs-cards.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
import { useFireworks } from '@/hooks/use-fireworks';
import { SubmitHandler, useZodForm } from '@/hooks/use-form';
import { docsBaseURL } from '@/lib/constants';
import { useChartData } from '@/lib/insights-helpers';
import { ChevronDoubleRightIcon, CommandLineIcon } from '@heroicons/react/24/outline';
import { useMutation } from '@tanstack/react-query';
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common_pb';
import { migrateFromApollo } from '@wundergraph/cosmo-connect/dist/platform/v1/platform-PlatformService_connectquery';
import { FederatedGraph } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
import { getTime, parseISO, subDays } from 'date-fns';
import Link from 'next/link';
import { Dispatch, SetStateAction, useContext, useState } from 'react';
import { Line, LineChart, ResponsiveContainer, XAxis } from 'recharts';
import { z } from 'zod';
import { UserContext } from './app-provider';
import { ComposeStatusMessage } from './compose-status';
import { ComposeStatusBulb } from './compose-status-bulb';
import { EmptyState } from './empty-state';
import { TimeAgo } from './time-ago';
import { Button } from './ui/button';
import { Card } from './ui/card';
import { CLI } from './ui/cli';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from './ui/dialog';
import { Input } from './ui/input';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip';
import { useToast } from './ui/use-toast';
import { Logo } from './logo';
import { SiApollographql } from 'react-icons/si';
import { cn } from '@/lib/utils';
import { useFireworks } from "@/hooks/use-fireworks";
import { SubmitHandler, useZodForm } from "@/hooks/use-form";
import { docsBaseURL } from "@/lib/constants";
import { useChartData } from "@/lib/insights-helpers";
import {
ChevronDoubleRightIcon,
CommandLineIcon,
} from "@heroicons/react/24/outline";
import { useMutation } from "@tanstack/react-query";
import { EnumStatusCode } from "@wundergraph/cosmo-connect/dist/common_pb";
import { migrateFromApollo } from "@wundergraph/cosmo-connect/dist/platform/v1/platform-PlatformService_connectquery";
import { FederatedGraph } from "@wundergraph/cosmo-connect/dist/platform/v1/platform_pb";
import { getTime, parseISO, subDays } from "date-fns";
import Link from "next/link";
import { Dispatch, SetStateAction, useContext, useState } from "react";
import { Line, LineChart, ResponsiveContainer, XAxis } from "recharts";
import { z } from "zod";
import { UserContext } from "./app-provider";
import { ComposeStatusMessage } from "./compose-status";
import { ComposeStatusBulb } from "./compose-status-bulb";
import { EmptyState } from "./empty-state";
import { TimeAgo } from "./time-ago";
import { Button } from "./ui/button";
import { Card } from "./ui/card";
import { CLI } from "./ui/cli";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "./ui/dialog";
import { Input } from "./ui/input";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "./ui/tooltip";
import { useToast } from "./ui/use-toast";
import { Logo } from "./logo";
import { SiApollographql } from "react-icons/si";
import { cn } from "@/lib/utils";

// this is required to render a blank line with LineChart
const fallbackData = [
Expand All @@ -53,6 +67,9 @@ const MigrationDialog = ({
apiKey: z
.string()
.min(1, { message: "API Key must contain at least 1 character." }),
variantName: z
.string()
.min(1, { message: "Variant name must contain at least 1 character." }),
});

type MigrateInput = z.infer<typeof migrateInputSchema>;
Expand All @@ -79,6 +96,7 @@ const MigrationDialog = ({
mutate(
{
apiKey: data.apiKey,
variantName: data.variantName,
},
{
onSuccess: (d) => {
Expand Down Expand Up @@ -167,6 +185,19 @@ const MigrationDialog = ({
</span>
)}
</div>
<div className="flex flex-col gap-y-2">
<span className="text-sm font-semibold">Graph Variant Name</span>
<Input
className="w-full"
type="text"
{...register("variantName")}
/>
{errors.variantName && (
<span className="px-2 text-xs text-destructive">
{errors.variantName.message}
</span>
)}
</div>

<Button
className="mt-2"
Expand Down

0 comments on commit 6ace9fc

Please sign in to comment.