Skip to content

Commit

Permalink
feat(query): support observables in each client method
Browse files Browse the repository at this point in the history
  • Loading branch information
donbabbeo authored Jan 20, 2024
1 parent 82e6d3c commit 7c82603
Show file tree
Hide file tree
Showing 16 changed files with 921 additions and 148 deletions.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,49 @@ export class TodosService {
}
```

For methods that require a `queryFn` parameter like
[ensureQueryData](https://tanstack.com/query/latest/docs/react/reference/QueryClient#queryclientensurequerydata), [fetchQuery](https://tanstack.com/query/latest/docs/react/reference/QueryClient#queryclientfetchquery), [prefetchQuery](), [fetchInfiniteQuery]() and [prefetchInfiniteQuery]() it's possible to use both Promises and Observables.

```ts
import { injectQueryClient } from '@ngneat/query';

@Injectable({ providedIn: 'root' })
export class TodosService {
#queryClient = injectQueryClient();

getQueryObservable() {
return {
queryKey: ['todos'] as const,
queryFn: () => {
return this.http.get<Todo[]>(
'https://jsonplaceholder.typicode.com/todos',
);
}
};
}

getQueryPromise() {
return {
queryKey: ['todos'] as const,
queryFn: () => {
return lastValueFrom(this.http.get<Todo[]>(
'https://jsonplaceholder.typicode.com/todos',
));
}
};
}

ensureQueryDataFromPromise(): Promise<Todo[]> {
return this.#queryClient.ensureQueryData(this.getQueryFromPromise());
}

ensureQueryDataFromObservable(): Promise<Todo[]> {
return this.#queryClient.ensureQueryData(this.getQueryFromObservable());
}
}
```


> The function should run inside an injection context
### Query
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 16 additions & 12 deletions query/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
export { injectQueryClient, provideQueryClient } from './lib/query-client';
export { injectQuery } from './lib/query';
export { injectMutation } from './lib/mutation';
export { injectInfiniteQuery } from './lib/infinite-query';
export { injectIsFetching } from './lib/is-fetching';
export { injectIsMutating } from './lib/is-mutating';
export { injectInfiniteQuery } from './lib/infinite-query';

export { injectMutation } from './lib/mutation';
export { injectQuery } from './lib/query';
export {
toPromise,
createSuccessObserverResult,
createPendingObserverResult,
} from './lib/utils';
export * from './lib/operators';
injectQueryClient,
provideQueryClient
} from './lib/query-client';

export * from '@tanstack/query-core';
export { ObservableQueryResult, SignalQueryResult } from './lib/types';
export { queryOptions } from './lib/query-options';
export * from './lib/operators';
export { provideQueryClientOptions } from './lib/query-client-options';
export { queryOptions } from './lib/query-options';
export { intersectResults } from './lib/signals';
export { ObservableQueryResult, SignalQueryResult } from './lib/types';
export {
createPendingObserverResult,
createSuccessObserverResult,
toPromise
} from './lib/utils';

77 changes: 22 additions & 55 deletions query/src/lib/base-query.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Injector, Signal, assertInInjectionContext } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import {
DefaultError,
QueryClient,
Expand All @@ -8,15 +10,8 @@ import {
WithRequired,
notifyManager,
} from '@tanstack/query-core';
import { Observable, isObservable, shareReplay } from 'rxjs';
import { toSignal } from '@angular/core/rxjs-interop';
import {
Injector,
Signal,
assertInInjectionContext,
runInInjectionContext,
} from '@angular/core';
import { toPromise } from './utils';
import { Observable, shareReplay } from 'rxjs';
import { normalizeOptions } from './query-options';

export type QueryFunctionWithObservable<
T = unknown,
Expand All @@ -36,8 +31,16 @@ interface _CreateBaseQueryOptions<
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> extends WithRequired<
QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
QueryObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey,
TPageParam
>,
'queryKey'
>,
Options {}
Expand All @@ -48,8 +51,16 @@ export type CreateBaseQueryOptions<
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
> = Omit<
_CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
_CreateBaseQueryOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey,
TPageParam
>,
'queryFn'
> & {
queryFn: QueryFunctionWithObservable<TQueryFnData, TQueryKey>;
Expand Down Expand Up @@ -177,47 +188,3 @@ export function createBaseQuery<
},
};
}

function normalizeOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey extends QueryKey,
>(
client: QueryClient,
options: QueryObserverOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey
>,
injector: Injector,
) {
const defaultedOptions = client.defaultQueryOptions(
options as unknown as QueryObserverOptions,
);
defaultedOptions._optimisticResults = 'optimistic';

const originalQueryFn = defaultedOptions.queryFn;

if (originalQueryFn) {
defaultedOptions.queryFn = function (ctx: QueryFunctionContext) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const _this = this;

return runInInjectionContext(injector, () => {
const value = originalQueryFn.call(_this, ctx);

if (isObservable(value)) {
return toPromise({ source: value, signal: ctx.signal });
}

return value;
});
};
}

return defaultedOptions;
}
6 changes: 3 additions & 3 deletions query/src/lib/infinite-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import { injectQueryClient } from './query-client';
import {
DefaultError,
InfiniteData,
QueryKey,
QueryObserver,
InfiniteQueryObserver,
InfiniteQueryObserverOptions,
InfiniteQueryObserverResult,
QueryKey,
QueryObserver,
WithRequired,
} from '@tanstack/query-core';
import {
Expand Down Expand Up @@ -44,7 +44,7 @@ interface _CreateInfiniteQueryOptions<
>,
Options {}

type CreateInfiniteQueryOptions<
export type CreateInfiniteQueryOptions<
TQueryFnData = unknown,
TError = DefaultError,
TData = TQueryFnData,
Expand Down
Loading

0 comments on commit 7c82603

Please sign in to comment.