UNPKG

@leosprograms/graphql-client-holochain

Version:

ValueFlows GraphQLClient configurations, providing pluggable backend datasources for different distributed, federated and client/server infrastructure.

116 lines (107 loc) 3.67 kB
/** * GraphQL client interface for Holochain connection * * @package hREA GraphQL client * @since 2020-07-14 */ // @ts-nocheck import { ApolloClient, InMemoryCache, NormalizedCacheObject } from '@apollo/client/core/index.js' import { SchemaLink } from '@apollo/link-schema' import bindSchema, { autoConnect, BindSchemaOptions, DNAIdMappings, ExtensionOptions, ResolverOptions } from '@leosprograms/vf-graphql-holochain' /* For external client. Are optional because `conductorUri` and `appID` may be autodetected or taken from environment variables and `dnaConfig` discovered through a functional connection to holochain */ interface AutoConnectionOptions { weaveAppAgentClient?: any dnaConfig?: DNAIdMappings conductorUri?: string adminConductorUri?: string appID?: string } export type ClientOptions = Pick<ResolverOptions, 'traceAppSignals'> & Pick<BindSchemaOptions, 'enabledVFModules'> & ExtensionOptions & AutoConnectionOptions /* This method creates the GraphQLSchema from the given options, and then builds an Graphql Apollo Client with the basic InMemoryCache with that schema. */ export async function initGraphQLClient(options: BindSchemaOptions) { const schema = await bindSchema(options) return new ApolloClient({ cache: new InMemoryCache({ dataIdFromObject(object) { switch (object.__typename) { case 'Unit': return `Unit:${object.id}`; // Custom ID for `Unit` type objects // No default case needed; Apollo handles other types automatically } // Implicitly returns `undefined` for types not handled above, // so Apollo uses the default ID generation logic }, }), defaultOptions: { watchQuery: { fetchPolicy: 'cache-and-network', }, query: { fetchPolicy: 'cache-first', }, }, link: new SchemaLink({ schema }) }) } /* This is a zero-config option method (and the main export) where you can generate a GraphQL Apollo Client and have all configuration handled internally for you. It is intended for the less advanced/customized use cases, but still offers basic levels of configuration. */ async function connect(options: ClientOptions = {}) { let bindSchemaOptions: BindSchemaOptions // autodetect `CellId`s if the config is missing some of the necessary values // also autodetect `conductorUri` `adminConductorUri` and `appID` since the caller can leave those undefined // in the options object (and pass them instead from either // environment variables or introspected from the Holochain Launcher) if (!options.dnaConfig || !options.conductorUri || !options.adminConductorUri || !options.appID) { let { dnaConfig, conductorUri, adminConductorUri, appId } = await autoConnect( options.weaveAppAgentClient, options.conductorUri, options.adminConductorUri, options.appID, // traceAppSignals needs to be passed during // the first initialization of the AppWebsocket options.traceAppSignals ) bindSchemaOptions = { ...options, weaveAppAgentClient: options.weaveAppAgentClient, dnaConfig, conductorUri, adminConductorUri, appId, } } else { // the difference between BindSchemaOptions and ClientOptions // is that for BindSchemaOptions `dnaConfig` and `conductorUri` must // be defined, and in this logical branch // we've established that, making this a safe // type cast bindSchemaOptions = { ...options as BindSchemaOptions } } return await initGraphQLClient(bindSchemaOptions) } export default connect