UNPKG

@mysten/sui

Version:

Sui TypeScript API(Work in Progress)

129 lines (115 loc) 3.77 kB
// Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 import type { TypedDocumentNode } from '@graphql-typed-document-node/core'; import type { TadaDocumentNode } from 'gql.tada'; import type { DocumentNode } from 'graphql'; import { print } from 'graphql'; import { Experimental_BaseClient } from '../experimental/index.js'; import type { Experimental_SuiClientTypes } from '../experimental/index.js'; import { GraphQLTransport } from '../experimental/transports/graphql.js'; import type { TypedDocumentString } from './generated/queries.js'; export type GraphQLDocument< Result = Record<string, unknown>, Variables = Record<string, unknown>, > = | string | DocumentNode | TypedDocumentString<Result, Variables> | TypedDocumentNode<Result, Variables> | TadaDocumentNode<Result, Variables>; export type GraphQLQueryOptions< Result = Record<string, unknown>, Variables = Record<string, unknown>, > = { query: GraphQLDocument<Result, Variables>; operationName?: string; extensions?: Record<string, unknown>; signal?: AbortSignal; } & (Variables extends { [key: string]: never } ? { variables?: Variables } : { variables: Variables; }); export type GraphQLQueryResult<Result = Record<string, unknown>> = { data?: Result; errors?: GraphQLResponseErrors; extensions?: Record<string, unknown>; }; export type GraphQLResponseErrors = Array<{ message: string; locations?: { line: number; column: number }[]; path?: (string | number)[]; }>; export interface SuiGraphQLClientOptions<Queries extends Record<string, GraphQLDocument>> { url: string; fetch?: typeof fetch; headers?: Record<string, string>; queries?: Queries; network?: Experimental_SuiClientTypes.Network; } export class SuiGraphQLRequestError extends Error {} export class SuiGraphQLClient< // eslint-disable-next-line @typescript-eslint/ban-types Queries extends Record<string, GraphQLDocument> = {}, > extends Experimental_BaseClient { #url: string; #queries: Queries; #headers: Record<string, string>; #fetch: typeof fetch; core: GraphQLTransport = new GraphQLTransport(this); constructor({ url, fetch: fetchFn = fetch, headers = {}, queries = {} as Queries, network = 'unknown', }: SuiGraphQLClientOptions<Queries>) { super({ network, }); this.#url = url; this.#queries = queries; this.#headers = headers; this.#fetch = (...args) => fetchFn(...args); } async query<Result = Record<string, unknown>, Variables = Record<string, unknown>>( options: GraphQLQueryOptions<Result, Variables>, ): Promise<GraphQLQueryResult<Result>> { const res = await this.#fetch(this.#url, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.#headers, }, body: JSON.stringify({ query: typeof options.query === 'string' || options.query instanceof String ? String(options.query) : print(options.query), variables: options.variables, extensions: options.extensions, operationName: options.operationName, }), signal: options.signal, }); if (!res.ok) { throw new SuiGraphQLRequestError(`GraphQL request failed: ${res.statusText} (${res.status})`); } return await res.json(); } async execute< const Query extends Extract<keyof Queries, string>, Result = Queries[Query] extends GraphQLDocument<infer R, unknown> ? R : Record<string, unknown>, Variables = Queries[Query] extends GraphQLDocument<unknown, infer V> ? V : Record<string, unknown>, >( query: Query, options: Omit<GraphQLQueryOptions<Result, Variables>, 'query'>, ): Promise<GraphQLQueryResult<Result>> { return this.query({ ...(options as { variables: Record<string, unknown> }), query: this.#queries[query]!, }) as Promise<GraphQLQueryResult<Result>>; } }