@apollo-orbit/angular
Version:
A full-featured GraphQL client for Angular
981 lines (961 loc) • 36.7 kB
JavaScript
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