A useful pattern is to pack all the necessary operations of the GraphQL API into a library, referred to as an SDK in the following example. This library must implement the operations and all the necessary queries and mutations.
To implement such an SDK in NodeJS:
export const TitleFragmentFragmentDoc = gql`fragment TitleFragment on Title {idcreatedAtupdatedAtnameslugnodeTypeIdentityTypeIdentityTypeNameentityIdhasChildrencustomFields {...BulkCustomFieldsFragment}}${BulkCustomFieldsFragmentFragmentDoc}`;export const TitlesDocument = gql`query titles($filters: TitleFilters, $orderBy: [TitleOrderBy!], $assocFilters: TitleAssocFilters, $first: Int, $skip: Int, $after: Cursor) {titles(filters: $filters, orderBy: $orderBy, assocFilters: $assocFilters, first: $first, skip: $skip, after: $after) {totalCountpageInfo {hasNextPagelastCursor}edges {cursornode {...TitleFragment}}}}${TitleFragmentFragmentDoc}`;export const TitleDocument = gql`query title($id: ID!) {title(id: $id) {...TitleFragment}}${TitleFragmentFragmentDoc}`;export const CreateTitleDocument = gql`mutation createTitle($input: TitleInput!) {createTitle(input: $input) {...TitleFragment}}${TitleFragmentFragmentDoc}`;export const UpdateTitleDocument = gql`mutation updateTitle($id: ID!, $input: TitleInput, $unset: [String!]) {updateTitle(id: $id, input: $input, unset: $unset) {...TitleFragment}}${TitleFragmentFragmentDoc}`;
export type Requester<C= {}> = <R, V>(doc: DocumentNode, vars?: V, options?: C) => Promise<R>export function getSdk<C>(requester: Requester<C>) {return {titles(variables?: ConnectApiTitlesQueryVariables, options?: C): Promise<ConnectApiTitlesQuery> {return requester<ConnectApiTitlesQuery, ConnectApiTitlesQueryVariables>(TitlesDocument, variables, options);},title(variables: ConnectApiTitleQueryVariables, options?: C): Promise<ConnectApiTitleQuery> {return requester<ConnectApiTitleQuery, ConnectApiTitleQueryVariables>(TitleDocument, variables, options);},createTitle(variables: ConnectApiCreateTitleMutationVariables, options?: C): Promise<ConnectApiCreateTitleMutation> {return requester<ConnectApiCreateTitleMutation, ConnectApiCreateTitleMutationVariables>(CreateTitleDocument, variables, options);},updateTitle(variables: ConnectApiUpdateTitleMutationVariables, options?: C): Promise<ConnectApiUpdateTitleMutation> {return requester<ConnectApiUpdateTitleMutation, ConnectApiUpdateTitleMutationVariables>(UpdateTitleDocument, variables, options);},deleteTitle(variables: ConnectApiDeleteTitleMutationVariables, options?: C): Promise<ConnectApiDeleteTitleMutation> {return requester<ConnectApiDeleteTitleMutation, ConnectApiDeleteTitleMutationVariables>(DeleteTitleDocument, variables, options);}};}export type Sdk = ReturnType<typeof getSdk>;
async function request(query: any, variables?: any) {const body = JSON.stringify([{query: query.loc.source.body?.replace(/[\s,]+/g, ' ')?.trim(),variables}]);const payload = {url: endpoint,body,organization_slug: orgSlug,};const hmac = crypto.createHmac('sha256', secretKey);hmac.write(JSON.stringify(payload));hmac.end();const signature = hmac.read().toString('hex');const response = await requestretry.post({url: `https://${endpoint}`,headers: {'Content-Type': 'application/json','X-Organization-Slug': orgSlug,'oz-key-id': publicKey,'oz-signature': signature,},body,maxAttempts: 5,retryStrategy: requestretry.RetryStrategies.HTTPOrNetworkError,});if (response.statusCode !== 200) {throw new Error(response.body);} else {let gqlResponse = JSON.parse(response.body);if (gqlResponse.length > 0) {gqlResponse = gqlResponse[0];} else {throw new Error('Did not receive data from server');}if (gqlResponse.errors) {throw new Error(gqlResponse.errors[0].message);}return gqlResponse.data;}}function getConnectSdk() {return getSdk(async <R, V>(doc: DocumentNode, vars: V): Promise<R> => {return request(doc, vars);});}const sdk = getConnectSdk();
async function getTitleById(id: string): Promise<ConnectApiTitleFragmentFragment> {console.log('getTitleById');const response = await sdk.title({ id });return response.title;}