Skip to content

Commit

Permalink
Merge pull request #59 from SaulMoro/next
Browse files Browse the repository at this point in the history
Add injectable fetchBaseQuery and remove baseUrl in config
  • Loading branch information
SaulMoro authored Oct 24, 2023
2 parents a4dd48b + ecd526a commit 4f2dac9
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 69 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# [16.3.0-next.1](https://github.com/SaulMoro/ngrx-rtk-query/compare/v16.2.0...v16.3.0-next.1) (2023-10-24)


### Features

* **lib:** remove baseUrl and add injectable fetchBaseQuery ([911d51e](https://github.com/SaulMoro/ngrx-rtk-query/commit/911d51e53f650338c175a4ed4c486869049b663c))

# [16.2.0](https://github.com/SaulMoro/ngrx-rtk-query/compare/v16.1.0...v16.2.0) (2023-10-09)


Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ bootstrapApplication(AppComponent, {
providers: [
...

provideStoreRtkQuery({
setupListeners: true,
baseUrl: environment.baseAPI, // Optional environment baseUrl
}),
provideStoreRtkQuery({ setupListeners: true }),

...
],
Expand Down Expand Up @@ -304,7 +301,7 @@ export function providePostsQuery(): EnvironmentProviders {
}
//
// OR
// OR
// New Standalone Provider Api
import { provideStoreApi } from 'ngrx-rtk-query';
Expand Down
66 changes: 11 additions & 55 deletions projects/ngrx-rtk-query/src/lib/fetch-base-query.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,18 @@
import { runInInjectionContext } from '@angular/core';
import type { FetchBaseQueryArgs } from '@reduxjs/toolkit/dist/query/fetchBaseQuery';
import { fetchBaseQuery as fetchBaseQueryDefault } from '@reduxjs/toolkit/query';
import { currentConfig } from './store-rtk-query.config';
import { injector } from './thunk.service';

/**
* This is a very small wrapper around fetch that aims to simplify requests.
*
* @example
* ```ts
* const baseQuery = fetchBaseQuery({
* baseUrl: 'https://api.your-really-great-app.com/v1/',
* prepareHeaders: (headers, { getState }) => {
* const token = (getState() as RootState).auth.token;
* // If we have a token set in state, let's assume that we should be passing it.
* if (token) {
* headers.set('authorization', `Bearer ${token}`);
* }
* return headers;
* },
* })
* ```
*
* @param baseUrl
* The base URL for an API service.
* Typically in the format of https://example.com/
*
* @param prepareHeaders
* An optional function that can be used to inject headers on requests.
* Provides a Headers object, as well as most of the `BaseQueryApi` (`dispatch` is not available).
* Useful for setting authentication or headers that need to be set conditionally.
*
* @link https://developer.mozilla.org/en-US/docs/Web/API/Headers
*
* @param fetchFn
* Accepts a custom `fetch` function if you do not want to use the default on the window.
* Useful in SSR environments if you need to use a library such as `isomorphic-fetch` or `cross-fetch`
*
* @param paramsSerializer
* An optional function that can be used to stringify querystring parameters.
*
* @param isJsonContentType
* An optional predicate function to determine if `JSON.stringify()` should be called on the `body` arg of `FetchArgs`
*
* @param jsonContentType Used when automatically setting the content-type header for a request with a jsonifiable
* body that does not have an explicit content-type header. Defaults to `application/json`.
*
* @param jsonReplacer Custom replacer function used when calling `JSON.stringify()`.
*
* @param timeout
* A number in milliseconds that represents the maximum time a request can take before timing out.
*/
export function fetchBaseQuery(queryArgs: FetchBaseQueryArgs = {}): ReturnType<typeof fetchBaseQueryDefault> {
const baseQueryEnvironment = fetchBaseQueryDefault(queryArgs);
export type FetchBaseQueryFactory = () => ReturnType<typeof fetchBaseQueryDefault>;

export function fetchBaseQuery(factory: FetchBaseQueryFactory): ReturnType<typeof fetchBaseQueryDefault>;
export function fetchBaseQuery(queryArgs?: FetchBaseQueryArgs): ReturnType<typeof fetchBaseQueryDefault>;
export function fetchBaseQuery(
paramsOrFactory: FetchBaseQueryArgs | FetchBaseQueryFactory = {},
): ReturnType<typeof fetchBaseQueryDefault> {
if (typeof paramsOrFactory === 'object') return fetchBaseQueryDefault(paramsOrFactory as FetchBaseQueryArgs);
return async (args, api, extraOptions) => {
const baseUrl = currentConfig?.baseUrl ?? '';
const argUrl = typeof args === 'string' ? args : args.url;
const url = `${baseUrl}${argUrl}`;
const newArgs = typeof args === 'string' ? url : { ...args, url };
return await baseQueryEnvironment(newArgs, api, extraOptions);
const baseQuery = runInInjectionContext(injector, paramsOrFactory as FetchBaseQueryFactory);
return await baseQuery(args, api, extraOptions);
};
}
5 changes: 2 additions & 3 deletions projects/ngrx-rtk-query/src/lib/provide-rtk-query.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ENVIRONMENT_INITIALIZER, EnvironmentProviders, inject, makeEnvironmentProviders } from '@angular/core';
import { provideState } from '@ngrx/store';
import { setupListeners } from '@reduxjs/toolkit/query';
import { Api, setupListeners } from '@reduxjs/toolkit/query';
import { STORE_RTK_QUERY_CONFIG, StoreQueryConfig, defaultConfig, setupConfig } from './store-rtk-query.config';
import { ThunkService, dispatch } from './thunk.service';

Expand All @@ -15,7 +15,6 @@ export function provideStoreRtkQuery(config?: Partial<StoreQueryConfig>): Enviro

return makeEnvironmentProviders([
{ provide: STORE_RTK_QUERY_CONFIG, useValue: moduleConfig },
ThunkService,
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
Expand All @@ -26,6 +25,6 @@ export function provideStoreRtkQuery(config?: Partial<StoreQueryConfig>): Enviro
]);
}

export function provideStoreApi(api: any): EnvironmentProviders {
export function provideStoreApi(api: Api<any, Record<string, any>, string, string, any>): EnvironmentProviders {
return provideState(api.reducerPath, api.reducer, { metaReducers: [api.metareducer] });
}
2 changes: 0 additions & 2 deletions projects/ngrx-rtk-query/src/lib/store-rtk-query.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { setupListeners } from '@reduxjs/toolkit/query';

export interface StoreQueryConfig {
setupListeners: boolean | Parameters<typeof setupListeners>[1];
baseUrl: string;
}

export let currentConfig: StoreQueryConfig | undefined;
Expand All @@ -13,7 +12,6 @@ export const setupConfig = (config: StoreQueryConfig) => {

export const defaultConfig: StoreQueryConfig = {
setupListeners: false,
baseUrl: '',
};

export const STORE_RTK_QUERY_CONFIG = new InjectionToken<StoreQueryConfig>('STORE_RTK_QUERY_CONFIG');
9 changes: 6 additions & 3 deletions projects/ngrx-rtk-query/src/lib/thunk.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Injectable, Signal, inject } from '@angular/core';
import { Injectable, Injector, Signal, inject } from '@angular/core';
import { Action, Store } from '@ngrx/store';
import { AnyAction, ThunkAction } from '@reduxjs/toolkit';
import { InternalMiddlewareState } from '@reduxjs/toolkit/dist/query/core/buildMiddleware/types';

let service: ThunkService;
export let injector: Injector;
let delayedActions: Action[] = [];

export const internalBatchState: InternalMiddlewareState = {
Expand Down Expand Up @@ -40,14 +41,16 @@ export function select<K>(mapFn: (state: any) => K): Signal<K> {
return service?.select(mapFn);
}

@Injectable()
@Injectable({ providedIn: 'root' })
export class ThunkService {
readonly #injector = inject(Injector);
readonly #store = inject(Store);

init() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
service = this;
delayedActions.map((delayedAction) => this.dispatch(delayedAction));
injector = this.#injector;
delayedActions.forEach((delayedAction) => this.dispatch(delayedAction));
delayedActions = [];
}

Expand Down
8 changes: 7 additions & 1 deletion src/app/core/services/counter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { inject } from '@angular/core';
import { Store } from '@ngrx/store';
import { createApi, fetchBaseQuery } from 'ngrx-rtk-query';

export interface CountResponse {
Expand All @@ -6,7 +8,11 @@ export interface CountResponse {

export const counterApi = createApi({
reducerPath: 'counterApi',
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
// Example of overriding the default fetchBaseQuery with injectable
baseQuery: fetchBaseQuery((store = inject(Store)) => {
console.log('store', store);
return fetchBaseQuery({ baseUrl: '/' });
}),
tagTypes: ['Counter'],
endpoints: (build) => ({
getCount: build.query<CountResponse, void>({
Expand Down

0 comments on commit 4f2dac9

Please sign in to comment.