Skip to content

Instantly share code, notes, and snippets.

@rupe120
Last active August 23, 2024 15:00
Show Gist options
  • Save rupe120/6a2f7c2e6a757b250cbe755d7d6cbf14 to your computer and use it in GitHub Desktop.
Save rupe120/6a2f7c2e6a757b250cbe755d7d6cbf14 to your computer and use it in GitHub Desktop.
A wrapper for the Apollo Client and AppSync to simplify the interaction with AppSync
import { ApolloClient, HttpLink, InMemoryCache, OperationVariables, ApolloLink } from '@apollo/client';
import { TypedDocumentNode } from "@apollo/client";
import { createAuthLink, AUTH_TYPE, AuthOptions } from "aws-appsync-auth-link";
import { createSubscriptionHandshakeLink } from "aws-appsync-subscription-link";
import WebSocket from 'ws';
export class AppSyncClientConfig {
url: string;
region: string;
apiKey: string;
forceUser?: string;
constructor(url: string, region: string, apiKey: string, forceUser?: string) {
this.url = url;
this.region = region;
this.apiKey = apiKey;
this.forceUser = forceUser;
}
}
class AppSyncWebSocket extends WebSocket {
constructor(url: string, protocols?: string | string[]) {
console.log("AppSyncWebSocket created - url:", url);
console.log("AppSyncWebSocket created - protocols:", protocols);
super(url, protocols);
}
}
// https://github.com/apollographql/apollo-client/issues/11063
global.WebSocket = AppSyncWebSocket;
export class AppSyncClient {
config: AppSyncClientConfig;
client: ApolloClient<any>;
constructor(config: AppSyncClientConfig) {
this.config = config;
const httpLink = new HttpLink({
uri: this.config.url,
headers: {
"x-api-key": this.config.apiKey,
},
});
const auth: AuthOptions = {
type: AUTH_TYPE.API_KEY,
apiKey: this.config.apiKey,
};
const authLink = createAuthLink({ url: this.config.url, region: this.config.region, auth });
authLink.setOnError((error) => {
console.error("Auth error:", JSON.stringify(error));
});
const subscriptionHandshakeLink = createSubscriptionHandshakeLink(
{
url: this.config.url,
region: this.config.region,
auth
}, httpLink);
subscriptionHandshakeLink.setOnError((error) => {
console.error("Subscription handshake error:", JSON.stringify(error));
});
const apolloLink = ApolloLink.from([
authLink,
subscriptionHandshakeLink,
]);
this.client = new ApolloClient({
link: apolloLink,
cache: new InMemoryCache()
});
}
public async query<TResponse, TInput extends OperationVariables>(query: any, variables: TInput) {
try {
const response = await this.client.query<TResponse, TInput>({
query,
variables,
fetchPolicy: "no-cache",
});
return response.data;
} catch (error) {
console.error("Error fetching AppSync data:", JSON.stringify(error));
throw error;
}
}
public async mutate<TResponse, TInput extends OperationVariables>(mutation: any, variables: TInput) {
try {
const response = await this.client.mutate<TResponse, TInput>({
mutation,
variables,
fetchPolicy: "no-cache",
});
return response.data;
} catch (error) {
console.error("Error fetching AppSync data:", JSON.stringify(error));
throw error;
}
}
public async subscribe<TResponse, TInput extends OperationVariables>(subscription: TypedDocumentNode, variables: TInput, callback: (data: TResponse) => void) {
const observable = this.client.subscribe<TResponse, TInput>({
query: subscription,
variables,
});
observable.subscribe({
next: (data) => {
callback(data.data!);
},
error: (error) => {
console.error("Error subscribing to AppSync data:", JSON.stringify(error));
throw error;
},
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment