UNPKG

@apollo-orbit/angular

Version:

A full-featured GraphQL client for Angular

981 lines (961 loc) 36.7 kB
import * as i1 from '@apollo/client'; import { NetworkStatus, ApolloClient } from '@apollo/client'; export { ApolloCache, ApolloClient, CombinedGraphQLErrors, CombinedProtocolErrors, InMemoryCache, LinkError, MissingFieldError, NetworkStatus, ServerError, ServerParseError, UnconventionalError, gql } from '@apollo/client'; import * as i0 from '@angular/core'; import { signal, computed, effect, untracked, linkedSignal, PendingTasks, DestroyRef, assertInInjectionContext, inject, Injector, Injectable, InjectionToken, NgZone, makeEnvironmentProviders, provideEnvironmentInitializer, ENVIRONMENT_INITIALIZER } from '@angular/core'; import { Observable, firstValueFrom, noop, defer, of } from 'rxjs'; import { map, startWith, catchError } from 'rxjs/operators'; import { equal } from '@wry/equality'; import { mergeOptions } from '@apollo/client/utilities/internal'; 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 => { try { return this.watch({ ...options, optimistic, immediate, callback: ({ result, ...rest }) => { subscriber.next({ ...rest, data: result }); } }); } catch (error) { subscriber.error(error); return void 0; } }); } function identifyFragment(fragment, id, fragmentName) { const fragmentDefinition = findFragmentDefinition(fragment, fragmentName); return { id: `${fragmentDefinition.typeCondition.name.value}:${id}`, fragmentName: fragmentName ?? fragmentDefinition.name.value, fragment }; } function identifyFragmentType(fragment, fragmentName) { return findFragmentDefinition(fragment, fragmentName).typeCondition.name.value; } function findFragmentDefinition(fragment, fragmentName) { const fragmentDefinition = fragment.definitions.find((definition) => definition.kind === 'FragmentDefinition' && (fragmentName === undefined || definition.name.value === fragmentName)); if (fragmentDefinition === undefined) throw new Error('Fragment definition was not found.'); return fragmentDefinition; } class QueryObservable extends Observable { observableQuery; previousData; constructor(observableQuery, { notifyOnLoading = true }) { super(subscriber => { let subscription; const next = ({ partial, ...result }) => { const { previousData } = this; this.previousData = (result.data ?? previousData); subscriber.next({ ...result, previousData }); }; const complete = () => { subscription = undefined; subscriber.complete(); }; subscription = observableQuery.subscribe({ next: notifyOnLoading ? next : skipInitialLoading(next), complete }); return () => { subscription?.unsubscribe(); subscription = undefined; }; }); this.observableQuery = observableQuery; } get query() { return this.observableQuery.query; } get variables() { return this.observableQuery.variables; } get options() { return this.observableQuery.options; } get queryName() { return this.observableQuery.queryName; } getCurrentResult() { const { partial, ...result } = this.observableQuery.getCurrentResult(); return result; } /** * Update the variables of this observable query, and fetch the new results. * This method should be preferred over `setVariables` in most use cases. * * Returns a `ResultPromise` with an additional `.retain()` method. Calling * `.retain()` keeps the network operation running even if the `ObservableQuery` * no longer requires the result. * * Note: `refetch()` guarantees that a value will be emitted from the * observable, even if the result is deep equal to the previous value. * * @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(options) { return this.observableQuery.fetchMore(options); } subscribeToMore(options) { const { subscription: document, ...rest } = options; return this.observableQuery.subscribeToMore({ document, ...rest }); } /** * 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: `setVariables()` guarantees that a value will be emitted from the * observable, even if the result is deeply equal to the previous value. * * Note: the promise will resolve with the last emitted result * when either the variables match the current variables or there * are no subscribers to the query. * * @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); } /** * A function that enables you to update the query's cached result without executing a followup GraphQL operation. * * See [using updateQuery and updateFragment](https://www.apollographql.com/docs/react/caching/cache-interaction/#using-updatequery-and-updatefragment) for additional information. */ updateQuery(mapFn) { return this.observableQuery.updateQuery(mapFn); } /** * A function that instructs the query to begin re-executing at a specified interval (in milliseconds). */ startPolling(pollInterval) { this.observableQuery.startPolling(pollInterval); } /** * A function that instructs the query to stop polling after a previous call to `startPolling`. */ stopPolling() { return this.observableQuery.stopPolling(); } /** * Reevaluate the query, optionally against new options. New options will be * merged with the current options when given. * * Note: `variables` can be reset back to their defaults (typically empty) by calling `reobserve` with * `variables: undefined`. */ reobserve(newOptions) { return this.observableQuery.reobserve(newOptions); } hasObservers() { return this.observableQuery.hasObservers(); } /** * Tears down the `ObservableQuery` and stops all active operations by sending a `complete` notification. */ stop() { this.observableQuery.stop(); } } function skipInitialLoading(fn) { let first = true; return ((result) => { const skipped = first && result.loading; first = false; if (skipped) return; return fn(result); }); } class SignalCacheQuery { cache; options; /** * The cache query result, containing `data`, `complete`, and `missing`. */ result; /** * The data returned by the cache query. */ data; /** * A signal indicating whether the query result contains complete data. * - `true`: All requested fields are available in the cache * - `false`: Some fields are missing from the cache * - `undefined`: Query has not been executed yet */ complete; /** * A signal containing an array of missing field errors if the query is incomplete. * Will be `undefined` if the query is complete or has not been executed. */ missing; _result; variables; subscription; constructor(injector, cache, options) { this.cache = cache; this.options = options; this._result = signal({ data: undefined, complete: false }, ...(ngDevMode ? [{ debugName: "_result" }] : [])); const { variables } = options; this.result = this._result.asReadonly(); this.data = computed(() => this.result().data, ...(ngDevMode ? [{ debugName: "data" }] : [])); this.complete = computed(() => this.result().complete, ...(ngDevMode ? [{ debugName: "complete" }] : [])); this.missing = computed(() => this.result().missing, ...(ngDevMode ? [{ debugName: "missing" }] : [])); this.variables = typeof variables === 'function' ? computed(variables, { equal }) : signal(variables); effect(onCleanup => { this.subscription = this.subscribe(this.variables()); onCleanup(() => { this.subscription?.unsubscribe(); this.subscription = undefined; }); }, { injector }); } subscribe(variables) { return this.cache .watchQuery({ ...this.options, variables }) .subscribe(result => this._result.set(result)); } } class SignalFragment { apollo; options; /** * The fragment result, containing `data`, `complete`, and `missing`. */ result; /** * The data returned by the fragment. */ data; /** * `true` if all requested fields in the fragment are present in the cache, `false` otherwise. */ complete; /** * If `complete` is `false`, this field describes which fields are missing. */ missing; _result; from; variables; subscription; constructor(injector, apollo, options) { this.apollo = apollo; this.options = options; this._result = signal({ data: {}, complete: false }, ...(ngDevMode ? [{ debugName: "_result" }] : [])); const { variables, from } = options; this.result = this._result.asReadonly(); this.data = computed(() => this.result().data, ...(ngDevMode ? [{ debugName: "data" }] : [])); this.complete = computed(() => this.result().complete, ...(ngDevMode ? [{ debugName: "complete" }] : [])); this.missing = computed(() => this.result().missing, ...(ngDevMode ? [{ debugName: "missing" }] : [])); this.from = typeof from === 'function' ? computed(from, { equal }) : signal(from); this.variables = typeof variables === 'function' ? computed(variables, { equal }) : signal(variables); effect(onCleanup => { const from = this.from(); const variables = this.variables(); this.subscription = this.subscribe(from, variables); onCleanup(() => { this.subscription?.unsubscribe(); this.subscription = undefined; }); }, { injector }); } subscribe(from, variables) { return this.apollo.watchFragment({ ...this.options, from, variables }).subscribe(result => this._result.set(result)); } } class SignalMutation { apollo; mutation; options; /** * The mutation result, containing `data`, `loading`, and `error` and `called`. */ result; /** * If `true`, the mutation is currently in flight. */ loading; /** * The data returned from the mutation. */ data; /** * The error encountered during the mutation. */ error; /** * If `true`, the mutation's mutate method has been called. */ called; _result; mutationId; constructor(apollo, mutation, options) { this.apollo = apollo; this.mutation = mutation; this.options = options; this.mutationId = 0; this._result = signal({ data: undefined, called: false, loading: false }, ...(ngDevMode ? [{ debugName: "_result" }] : [])); this.result = this._result.asReadonly(); this.loading = computed(() => this.result().loading, ...(ngDevMode ? [{ debugName: "loading" }] : [])); this.data = computed(() => this.result().data, ...(ngDevMode ? [{ debugName: "data" }] : [])); this.error = computed(() => this.result().error, ...(ngDevMode ? [{ debugName: "error" }] : [])); this.called = computed(() => this.result().called, ...(ngDevMode ? [{ debugName: "called" }] : [])); } /** * Execute the mutation with the provided variables and options. */ mutate(...[executeOptions]) { if (!untracked(this.loading)) { this._result.set({ loading: true, error: undefined, data: undefined, called: true }); } // Increment the mutation ID to track concurrent mutations const mutationId = ++this.mutationId; const { mutation } = this; const { onData, onError, ...mergedOptions } = mergeOptions(this.options ?? {}, executeOptions ?? {}); const mutationOptions = { ...mergedOptions, mutation }; return firstValueFrom(this.apollo.mutate(mutationOptions)) .then(result => { const { data, error } = result; if (error) { onError?.(error, mutationOptions); } if (!error && data !== undefined) { onData?.(data, mutationOptions); } // Only update signal if this is still the current mutation if (mutationId === this.mutationId) { const newResult = { called: true, loading: false, data, error }; this._result.set(newResult); } return result; }) .catch(error => { onError?.(error, mutationOptions); // Only update signal if this is still the current mutation if (mutationId === this.mutationId) { const newResult = { called: true, loading: false, data: undefined, error }; this._result.set(newResult); } return { data: undefined, error }; }); } /** * Reset the mutation result to its initial state. */ reset() { this.mutationId = 0; this._result.set({ data: undefined, called: false, loading: false }); } } class SignalQueryExecutionError extends Error { constructor(methodName) { super(`'${methodName}' cannot be called while the query is not active.`); this.name = 'SignalQueryExecutionError'; } } class SignalQuery { apollo; options; /** * The query result, containing `data`, `loading`, `error`, `networkStatus`, `previousData`, `dataState`. */ result; /** * If `true`, the query is currently in flight. */ loading = computed(() => this.result().loading, ...(ngDevMode ? [{ debugName: "loading" }] : [])); /** * The current network status of the query. */ networkStatus = computed(() => this.result().networkStatus, ...(ngDevMode ? [{ debugName: "networkStatus" }] : [])); /** * The data returned by the query, or `undefined` if loading, errored, or no data received yet. */ data = computed(() => this.result().data, ...(ngDevMode ? [{ debugName: "data" }] : [])); /** * The data from the previous successful result, useful for displaying stale data during refetches. */ previousData = computed(() => this.result().previousData, ...(ngDevMode ? [{ debugName: "previousData" }] : [])); /** * An error object if the query failed, `undefined` otherwise. */ error = computed(() => this.result().error, ...(ngDevMode ? [{ debugName: "error" }] : [])); /** * A writable signal that represents the current query variables. */ variables; /** * Whether the query is currently active, subscribed to the underlying observable and receiving cache updates. */ active; /** * Whether the query is currently enabled. * * This property starts as `true` for non-lazy queries and `false` for lazy queries. * * Calling `execute()` sets it to `true`, while calling `terminate()` sets it to `false`. * * When `true`: * - The query automatically executes when variables change from `null` to a non-null value * - Variable changes trigger re-execution with the new variables * * When `false`: * - Variable changes are ignored and do not trigger re-execution * - The query must be manually started via `execute()` * * Note: This is different from `active`, which indicates whether the query is currently connected to its observable and actively watching the cache. */ enabled; observable; subscription; _active; _result; _enabled; constructor(injector, apollo, options) { this.apollo = apollo; this.options = options; const { variables, lazy = false } = options; this.variables = variables !== undefined ? linkedSignal(variables, { equal }) : signal(variables); this._enabled = signal(!lazy, ...(ngDevMode ? [{ debugName: "_enabled" }] : [])); this.enabled = this._enabled.asReadonly(); this._result = signal({ data: undefined, dataState: 'empty', loading: false, networkStatus: NetworkStatus.ready }, ...(ngDevMode ? [{ debugName: "_result" }] : [])); this.result = this._result.asReadonly(); this._active = signal(false, ...(ngDevMode ? [{ debugName: "_active" }] : [])); this.active = this._active.asReadonly(); effect(() => { const variables = this.variables(); const enabled = untracked(this.enabled); const active = untracked(this.active); if (!enabled) return; if (variables !== null) { if (!active) { this._execute({ variables }).catch(noop); } else { this.observable?.setVariables(variables).catch(noop); } } else if (active) { this._terminate(); } }, { injector }); if (!lazy) { const pendingTasks = injector.get(PendingTasks); effect(() => { if (untracked(this.variables) !== null) { const resolvePendingTask = pendingTasks.add(); this.execute().then(resolvePendingTask).catch(noop); } }, { injector }); } injector.get(DestroyRef).onDestroy(() => this.terminate()); } /** * Execute the query with the provided options. */ execute(execOptions = {}) { this._enabled.set(true); return this._execute(execOptions); } /** * Terminate query execution and unsubscribe from the observable. */ terminate() { this._enabled.set(false); this._terminate(); } /** * Refetch the query with the current variables. */ refetch(variables) { if (!this.observable) throw new SignalQueryExecutionError('refetch'); return this.observable.refetch(variables) .catch(error => ({ data: undefined, error })); } /** * Fetch more data and merge it with the existing result. */ fetchMore(options) { if (!this.observable) throw new SignalQueryExecutionError('fetchMore'); return this.observable.fetchMore(options) .catch(error => ({ data: undefined, error })); } /** * Update the query's cached data. */ updateQuery(mapFn) { if (!this.observable) throw new SignalQueryExecutionError('updateQuery'); this.observable.updateQuery(mapFn); } /** * Start polling the query. */ startPolling(pollInterval) { if (!this.observable) throw new SignalQueryExecutionError('startPolling'); this.observable.startPolling(pollInterval); } /** * Stop polling the query. */ stopPolling() { if (!this.observable) throw new SignalQueryExecutionError('stopPolling'); this.observable.stopPolling(); } /** * Subscribe to more data. */ subscribeToMore(options) { if (!this.observable) throw new SignalQueryExecutionError('subscribeToMore'); return this.observable.subscribeToMore(options); } _execute(execOptions = {}) { if ('variables' in execOptions) { this.variables.set(execOptions.variables); } const variables = untracked(this.variables); if (variables === null) { return Promise.resolve({ data: this.data() }); } this._active.set(true); const { query, lazy, notifyOnLoading = true, notifyOnNetworkStatusChange = true, ...options } = this.options; const newOptions = { ...options, ...execOptions, notifyOnLoading, notifyOnNetworkStatusChange, query, variables }; this.observable ??= this.apollo.watchQuery(newOptions); this.subscription ??= this.observable.subscribe(result => this._result.set(result)); return this.observable.reobserve(newOptions) .catch(error => ({ data: undefined, error })); } _terminate() { this._active.set(false); this.subscription?.unsubscribe(); this.subscription = undefined; this.observable = undefined; this._result.update(({ data, previousData }) => ({ data: undefined, dataState: 'empty', loading: false, networkStatus: NetworkStatus.ready, previousData: data ?? previousData })); } } class SignalSubscription { apollo; options; /** * The subscription result, containing `data`, `loading`, and `error`. */ result; /** * If `true`, the subscription is currently loading the initial result. */ loading; /** * The data returned by the subscription, or `undefined` if loading, errored, or no data received yet. */ data; /** * An error object if the subscription failed, `undefined` otherwise. */ error; /** * A writable signal that represents the current subscription variables. */ variables; /** * Whether the subscription is currently active, connected to the server and receiving real-time updates. */ active; /** * Whether the subscription is currently enabled. * * This property starts as `true` for non-lazy subscriptions and `false` for lazy subscriptions. * * Calling `execute()` sets it to `true`, while calling `terminate()` sets it to `false`. * * When `true`: * - The subscription automatically starts when variables change from `null` to a non-null value * - Variable changes trigger re-subscription with the new variables * * When `false`: * - Variable changes are ignored and do not trigger re-subscription * - The subscription must be manually started via `execute()` * * Note: This is different from `active`, which indicates whether the subscription is currently connected to the server and receiving real-time updates. */ enabled; subscription; _active; _result; _enabled; constructor(injector, apollo, options) { this.apollo = apollo; this.options = options; const { variables, lazy = false } = options; this._enabled = signal(!lazy, ...(ngDevMode ? [{ debugName: "_enabled" }] : [])); this.enabled = this._enabled.asReadonly(); this._active = signal(false, ...(ngDevMode ? [{ debugName: "_active" }] : [])); this.active = this._active.asReadonly(); this._result = signal({ loading: false, data: undefined, error: undefined }, ...(ngDevMode ? [{ debugName: "_result" }] : [])); this.result = this._result.asReadonly(); this.loading = computed(() => this.result().loading, ...(ngDevMode ? [{ debugName: "loading" }] : [])); this.data = computed(() => this.result().data, ...(ngDevMode ? [{ debugName: "data" }] : [])); this.error = computed(() => this.result().error, ...(ngDevMode ? [{ debugName: "error" }] : [])); this.variables = variables !== undefined ? linkedSignal(variables, { equal }) : signal(variables); effect(() => { const variables = this.variables(); const enabled = untracked(this.enabled); const active = untracked(this.active); if (!enabled) return; if (variables !== null) { this._execute({ variables }); } else if (active) { this._terminate(); } }, { injector }); effect(() => { const variables = this.variables(); if (untracked(this.active) && variables !== null) { this.execute({ variables }); } }, { injector }); injector.get(DestroyRef).onDestroy(() => this.terminate()); } /** * Execute subscription. */ execute(execOptions = {}) { this._enabled.set(true); this._execute(execOptions); } /** * Terminate subscription. */ terminate() { this._enabled.set(false); this._terminate(); } _execute(execOptions = {}) { if ('variables' in execOptions) { this.variables.set(execOptions.variables); } const variables = untracked(this.variables); if (variables === null) { return; } this._active.set(true); this._result.set({ loading: true, data: undefined, error: undefined }); const { subscription, onData, onError, onComplete, injector, lazy, ...options } = this.options; this.subscription?.unsubscribe(); this.subscription = this.apollo.subscribe({ ...options, ...execOptions, subscription, variables }).subscribe({ next: result => { this._result.set({ loading: false, ...result }); if (result.error) { onError?.(result.error); } else if (result.data !== undefined) { onData?.(result.data); } }, // error is never called for subscriptions in Apollo Client complete: () => { this.terminate(); onComplete?.(); } }); } _terminate() { this._active.set(false); this.subscription?.unsubscribe(); this.subscription = undefined; this._result.update(result => ({ ...result, loading: false })); } } class ApolloSignal { apollo; constructor(apollo) { this.apollo = apollo; } query(options) { if (!options.injector) { assertInInjectionContext(this.query.bind(this)); } const injector = options.injector ?? inject(Injector); return new SignalQuery(injector, this.apollo, options); } mutation(mutation, options) { return new SignalMutation(this.apollo, mutation, options); } subscription(options) { if (!options.injector) { assertInInjectionContext(this.subscription.bind(this)); } const injector = options.injector ?? inject(Injector); return new SignalSubscription(injector, this.apollo, options); } fragment(options) { if (!options.injector) { assertInInjectionContext(this.fragment.bind(this)); } const injector = options.injector ?? inject(Injector); return new SignalFragment(injector, this.apollo, options); } cacheQuery(options) { if (!options.injector) { assertInInjectionContext(this.cacheQuery.bind(this)); } const injector = options.injector ?? inject(Injector); return new SignalCacheQuery(injector, this.apollo.cache, options); } } class Apollo { /** * Instance of ApolloClient */ client; cache; signal; defaultOptions; constructor(client, defaultOptions) { this.client = client; this.defaultOptions = defaultOptions; this.cache = extendCache(client.cache); this.signal = new ApolloSignal(this); } query(options) { const { notifyOnLoading = false, throwError = true } = { ...this.defaultOptions?.query, ...options }; return defer(() => this.client.query(options)).pipe(map(({ data, error }) => data === undefined ? { data: undefined, error, dataState: 'empty', loading: false, networkStatus: NetworkStatus.ready } : { data, error, dataState: 'complete', loading: false, networkStatus: NetworkStatus.ready }), (source => notifyOnLoading ? source.pipe(startWith({ data: undefined, dataState: 'empty', loading: true, networkStatus: NetworkStatus.loading })) : source), (source => !throwError ? source.pipe(catchError((error) => of({ error, data: undefined, dataState: 'empty', loading: false, networkStatus: NetworkStatus.error }))) : source)); } watchQuery(options) { const { notifyOnLoading } = { ...this.defaultOptions?.watchQuery, ...options }; return new QueryObservable(this.client.watchQuery(options), { notifyOnLoading }); } watchFragment(options) { let { from, fragment, ...rest } = options; // Extract fragment type from the fragment document if __typename is not provided. if (typeof from === 'object' && 'id' in from && Object.keys(from).length === 1) { from = { __typename: identifyFragmentType(fragment), id: from.id }; } return this.client.watchFragment({ from, fragment, ...rest }); } mutate(options) { return defer(() => this.client.mutate(options)); } subscribe(options) { const { subscription: query, ...rest } = options; return defer(() => this.client.subscribe({ query, ...rest })); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: Apollo, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: Apollo }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", 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) => { const ngZone = inject(NgZone); return ngZone.runOutsideAngular(() => new ApolloClient(options)); }; class ApolloRegistry { providers = []; _instances; register(token) { const injector = inject(Injector); this.providers.push(() => injector.get(token)); this._instances = undefined; } get instances() { return (this._instances ??= this.providers.map(provider => provider())); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ApolloRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ApolloRegistry }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ApolloRegistry, decorators: [{ type: Injectable }] }); const APOLLO_INSTANCE_FACTORY = new InjectionToken('[apollo-orbit] apollo instance factory'); function mapQuery(mapFn) { return (observable) => observable.pipe(map(result => mapQueryResult(result, mapFn))); } function mapMutation(mapFn) { return (observable) => observable.pipe(map(result => mapMutationResult(result, mapFn))); } function mapSubscription(mapFn) { return (observable) => observable.pipe(map(result => mapSubscriptionResult(result, mapFn))); } function mapQueryResult(result, mapFn) { const { data, previousData, ...rest } = result; return { ...rest, data: data !== undefined ? mapFn(data) : undefined, previousData: previousData !== undefined ? mapFn(previousData) : undefined }; } function mapMutationResult(result, mapFn) { const { data, ...rest } = result; return { ...rest, data: data !== undefined ? mapFn(data) : undefined }; } function mapSubscriptionResult(result, mapFn) { const { data, ...rest } = result; return { ...rest, data: data !== undefined ? mapFn(data) : undefined }; } const APOLLO_PROVIDED = new InjectionToken('[apollo-orbit] apollo provided'); const APOLLO_MULTI_ROOT = new InjectionToken('[apollo-orbit] multi root'); function withApolloOptions(options) { return { kind: 'APOLLO_ORBIT_OPTIONS', providers: getApolloInstanceProviders(Apollo, options) }; } function provideApollo(...features) { return makeEnvironmentProviders([ ApolloRegistry, { provide: Apollo, useFactory: () => apolloFactory(null) }, // guard { provide: APOLLO_PROVIDED, useValue: true }, { provide: APOLLO_INSTANCE_FACTORY, useFactory: apolloInstanceFactory }, { provide: APOLLO_CLIENT_FACTORY, useValue: apolloClientFactory }, provideEnvironmentInitializer(apolloOrbitRootGuard), features.map(({ providers }) => providers) ]); } function provideApolloInstance(token, options) { return makeEnvironmentProviders(getApolloInstanceProviders(token, options)); } function getApolloInstanceProviders(token, options) { return [ { provide: ENVIRONMENT_INITIALIZER, multi: true, useValue: () => inject(ApolloRegistry).register(token) }, { provide: token, useFactory: typeof options === 'function' ? () => apolloFactory(options()) : () => 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 provideApollo() 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('provideApollo() should only be called once. To override this behaviour, may provide APOLLO_MULTI_ROOT token.'); } } /* eslint-disable max-len */ /** * Generated bundle index. Do not edit. */ export { APOLLO_CLIENT_FACTORY, APOLLO_MULTI_ROOT, Apollo, ApolloSignal, QueryObservable, SignalCacheQuery, SignalFragment, SignalMutation, SignalQuery, SignalQueryExecutionError, SignalSubscription, identifyFragment, identifyFragmentType, mapMutation, mapMutationResult, mapQuery, mapQueryResult, mapSubscription, mapSubscriptionResult, provideApollo, provideApolloInstance, withApolloOptions, APOLLO_INSTANCE_FACTORY as ɵAPOLLO_INSTANCE_FACTORY, ApolloRegistry as ɵApolloRegistry }; //# sourceMappingURL=apollo-orbit.angular.mjs.map