UNPKG

@apollo-orbit/angular

Version:

A fully-featured GraphQL client for Angular with modular state management.

382 lines (369 loc) 14.4 kB
import * as i1 from '@apollo/client/core'; import { ApolloError, NetworkStatus, ApolloClient } from '@apollo/client/core'; export { ApolloCache, ApolloClient, ApolloError, Cache, InMemoryCache, NetworkStatus, gql } from '@apollo/client/core'; import * as i0 from '@angular/core'; import { Injectable, InjectionToken, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, inject } from '@angular/core'; import { Observable, defer, of } from 'rxjs'; import { map, startWith, catchError } from 'rxjs/operators'; function extendCache(cache) { return Object.defineProperties(cache, { watchQuery: { value: watchQuery, writable: false, configurable: false } }); } function watchQuery(options) { const { immediate = true, optimistic = true } = options; return new Observable(subscriber => this.watch({ ...options, optimistic, immediate, callback: ({ result, ...rest }) => subscriber.next({ ...rest, data: result }) })); } function toQueryResult({ errors, ...result }) { return { ...result, error: getApolloError(errors, result.error) }; } function toMutationResult(fetchResult, apolloError) { fetchResult ??= {}; const { errors, data, extensions } = fetchResult; const context = 'context' in fetchResult ? fetchResult.context : undefined; return { data: data ?? undefined, error: getApolloError(errors, apolloError), context, extensions }; } function toSubscriptionResult(fetchResult) { return toMutationResult(fetchResult); } function getApolloError(graphQLErrors, apolloError) { return graphQLErrors && graphQLErrors.length > 0 ? new ApolloError({ graphQLErrors }) : apolloError; } class QueryObservable extends Observable { observableQuery; previousData; constructor(observableQuery, { notifyOnLoading = true, throwError = false }) { super(subscriber => { let subscription; if (notifyOnLoading) { // on calling getCurrentResult apollo client sets lastResult based on fetchPolicy // when lastResult is present, apollo client emits value on subscription // otherwise, it is emitted here instead const currentResult = this.getCurrentResult(); const lastResult = observableQuery.getLastResult(); if (!lastResult) { const { previousData } = this; subscriber.next({ ...currentResult, previousData }); this.previousData = currentResult.data ?? previousData; } } const observer = { next: () => { const currentResult = this.getCurrentResult(); const { previousData } = this; subscriber.next({ ...currentResult, previousData }); this.previousData = currentResult.data ?? previousData; }, error: error => { subscription = undefined; if (throwError) { subscriber.error(error); } else { const currentResult = this.getCurrentResult(); const { previousData } = this; subscriber.next({ ...currentResult, previousData }); this.previousData = currentResult.data ?? previousData; subscription = observableQuery.resubscribeAfterError(observer); } }, complete: () => { subscription = undefined; subscriber.complete(); } }; subscription = observableQuery.subscribe(observer); return () => subscription?.unsubscribe(); }); this.observableQuery = observableQuery; } get query() { return this.observableQuery.query; } get variables() { return this.observableQuery.variables; } get options() { return this.observableQuery.options; } get queryId() { return this.observableQuery.queryId; } get queryName() { return this.observableQuery.queryName; } result() { return this.observableQuery.result(); } getCurrentResult(saveAsLastResult = true) { return toQueryResult(this.observableQuery.getCurrentResult(saveAsLastResult)); } // Compares newResult to the snapshot we took of this.lastResult when it was // first received. isDifferentFromLastResult(newResult, variables) { return this.observableQuery.isDifferentFromLastResult(newResult, variables); } getLastResult(variablesMustMatch) { return this.observableQuery.getLastResult(variablesMustMatch); } getLastError(variablesMustMatch) { return this.observableQuery.getLastError(variablesMustMatch); } resetLastResults() { this.observableQuery.resetLastResults(); } resetQueryStoreErrors() { this.observableQuery.resetQueryStoreErrors(); } /** * Update the variables of this observable query, and fetch the new results. * This method should be preferred over `setVariables` in most use cases. * * @param variables: The new set of variables. If there are missing variables, * the previous values of those variables will be used. */ refetch(variables) { return this.observableQuery.refetch(variables); } fetchMore(fetchMoreOptions) { return this.observableQuery.fetchMore(fetchMoreOptions); } subscribeToMore(options) { const { query: document, ...rest } = options; return this.observableQuery.subscribeToMore({ document, ...rest }); } setOptions(newOptions) { return this.observableQuery.setOptions(newOptions); } silentSetOptions(newOptions) { this.observableQuery.silentSetOptions(newOptions); } /** * Update the variables of this observable query, and fetch the new results * if they've changed. Most users should prefer `refetch` instead of * `setVariables` in order to to be properly notified of results even when * they come from the cache. * * Note: the `next` callback will *not* fire if the variables have not changed * or if the result is coming from cache. * * Note: the promise will return the old results immediately if the variables * have not changed. * * Note: the promise will return null immediately if the query is not active * (there are no subscribers). * * @private * * @param variables: The new set of variables. If there are missing variables, * the previous values of those variables will be used. */ setVariables(variables) { return this.observableQuery.setVariables(variables); } updateQuery(mapFn) { return this.observableQuery.updateQuery(mapFn); } startPolling(pollInterval) { this.observableQuery.startPolling(pollInterval); } stopPolling() { return this.observableQuery.stopPolling(); } reobserveAsConcast(newOptions, newNetworkStatus) { return this.observableQuery.reobserveAsConcast(newOptions, newNetworkStatus); } reobserve(newOptions, newNetworkStatus) { return this.observableQuery.reobserve(newOptions, newNetworkStatus); } resubscribeAfterError(...args) { return this.observableQuery.resubscribeAfterError(...args); } hasObservers() { return this.observableQuery.hasObservers(); } } const fromZenObservable = (source) => new Observable(source.subscribe.bind(source)); /* eslint-disable max-len */ class Apollo { /** * Instance of ApolloClient */ client; defaultOptions; _cache; constructor(client, defaultOptions) { this.client = client; this.defaultOptions = defaultOptions; this._cache = extendCache(client.cache); } query(options) { const { notifyOnLoading = false, throwError = true } = { ...this.defaultOptions?.query, ...options }; return defer(() => this.client.query(options)).pipe(map(result => toQueryResult(result)), (source => notifyOnLoading ? source.pipe(startWith({ loading: true, networkStatus: NetworkStatus.loading })) : source), (source => !throwError ? source.pipe(catchError((error) => of({ error, loading: false, networkStatus: NetworkStatus.error }))) : source)); } watchQuery(options) { const { notifyOnLoading, throwError } = { ...this.defaultOptions?.watchQuery, ...options }; return new QueryObservable(this.client.watchQuery(options), { notifyOnLoading, throwError }); } watchFragment(options) { return fromZenObservable(this.client.watchFragment(options)); } mutate(options) { return defer(() => this.client.mutate(options)).pipe(map(result => toMutationResult(result))); } subscribe(options) { return defer(() => fromZenObservable(this.client.subscribe(options))).pipe(map(result => toSubscriptionResult(result))); } get cache() { return this._cache; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: Apollo, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: Apollo }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: Apollo, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.ApolloClient }, { type: undefined }] }); const APOLLO_CLIENT_FACTORY = new InjectionToken('[apollo-orbit] client factory'); const apolloClientFactory = (options) => { return new ApolloClient(options); }; function mapQuery(fn) { return (observable) => observable.pipe(map((result) => { const { data, previousData, ...rest } = result; return { ...rest, data: data !== undefined ? fn(data) : undefined, previousData: previousData !== undefined ? fn(previousData) : undefined }; })); } function mapMutation(fn) { return (observable) => observable.pipe(map((result) => { const { data, ...rest } = result; return { ...rest, data: data !== undefined ? fn(data) : undefined }; })); } function mapSubscription(fn) { return (observable) => observable.pipe(map((result) => { const { data, ...rest } = result; return { ...rest, data: data !== undefined ? fn(data) : undefined }; })); } const APOLLO_PROVIDED = new InjectionToken('[apollo-orbit] apollo provided'); const APOLLO_MULTI_ROOT = new InjectionToken('[apollo-orbit] multi root'); const APOLLO_INSTANCE_FACTORY = new InjectionToken('[apollo-orbit] apollo instance factory'); const APOLLO_ORBIT_PROVIDERS = [ [ { provide: Apollo, useFactory: () => apolloFactory(null) }, // guard { provide: APOLLO_PROVIDED, useValue: true }, { provide: APOLLO_INSTANCE_FACTORY, useFactory: apolloInstanceFactory }, { provide: APOLLO_CLIENT_FACTORY, useValue: apolloClientFactory } ] ]; function withApolloOptions(options) { return { kind: 'APOLLO_ORBIT_OPTIONS', providers: getApolloInstanceProviders(Apollo, options) }; } function provideApolloOrbit(...features) { return makeEnvironmentProviders([ ...APOLLO_ORBIT_PROVIDERS, features.map(({ providers }) => providers), { provide: ENVIRONMENT_INITIALIZER, multi: true, useFactory: () => apolloOrbitRootGuard } ]); } function provideApolloInstance(token, options) { return makeEnvironmentProviders(getApolloInstanceProviders(token, options)); } function getApolloInstanceProviders(token, options) { return [ typeof options === 'function' ? { provide: token, useFactory: () => apolloFactory(options()) } : { provide: token, useFactory: () => apolloFactory(options) } ]; } function apolloInstanceFactory() { return (_clientId, client, defaultOptions) => new Apollo(client, defaultOptions); } function apolloFactory(options) { if (!options) throw new Error('withApolloOptions feature must be passed to provideApolloOrbit() before injecting Apollo'); const { id = 'default', cache, defaultOptions, ...rest } = options; const createClient = inject(APOLLO_CLIENT_FACTORY); const client = createClient({ cache, defaultOptions, ...rest }); return inject(APOLLO_INSTANCE_FACTORY)(id, client, defaultOptions); } function apolloOrbitRootGuard() { const isProvided = inject(APOLLO_PROVIDED, { optional: true, skipSelf: true }); const multiRoot = inject(APOLLO_MULTI_ROOT, { optional: true }); if (isProvided && multiRoot !== true) { throw new Error('provideApolloOrbit() has been called more than once. Consider calling provideStates() instead. Otherwise, you may provide APOLLO_MULTI_ROOT token.'); } } class PureQueryOptions { query; variables; context; constructor(query, variables, context) { this.query = query; this.variables = variables; this.context = context; } } class PureMutationOptions { mutation; variables; context; constructor(mutation, variables, context) { this.mutation = mutation; this.variables = variables; this.context = context; } } class PureSubscriptionOptions { query; variables; constructor(query, variables) { this.query = query; this.variables = variables; } } /** * Generated bundle index. Do not edit. */ export { APOLLO_CLIENT_FACTORY, APOLLO_MULTI_ROOT, Apollo, PureMutationOptions, PureQueryOptions, PureSubscriptionOptions, QueryObservable, mapMutation, mapQuery, mapSubscription, provideApolloInstance, provideApolloOrbit, withApolloOptions, APOLLO_INSTANCE_FACTORY as ɵAPOLLO_INSTANCE_FACTORY }; //# sourceMappingURL=apollo-orbit.angular.core.mjs.map