diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dc5593..7995812 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/README.md b/README.md index 5de01af..6a7ca83 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,7 @@ bootstrapApplication(AppComponent, { providers: [ ... - provideStoreRtkQuery({ - setupListeners: true, - baseUrl: environment.baseAPI, // Optional environment baseUrl - }), + provideStoreRtkQuery({ setupListeners: true }), ... ], @@ -304,7 +301,7 @@ export function providePostsQuery(): EnvironmentProviders { } // -// OR +// OR // New Standalone Provider Api import { provideStoreApi } from 'ngrx-rtk-query'; diff --git a/projects/ngrx-rtk-query/src/lib/fetch-base-query.ts b/projects/ngrx-rtk-query/src/lib/fetch-base-query.ts index fa712ce..7097a60 100644 --- a/projects/ngrx-rtk-query/src/lib/fetch-base-query.ts +++ b/projects/ngrx-rtk-query/src/lib/fetch-base-query.ts @@ -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 { - const baseQueryEnvironment = fetchBaseQueryDefault(queryArgs); +export type FetchBaseQueryFactory = () => ReturnType; +export function fetchBaseQuery(factory: FetchBaseQueryFactory): ReturnType; +export function fetchBaseQuery(queryArgs?: FetchBaseQueryArgs): ReturnType; +export function fetchBaseQuery( + paramsOrFactory: FetchBaseQueryArgs | FetchBaseQueryFactory = {}, +): ReturnType { + 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); }; } diff --git a/projects/ngrx-rtk-query/src/lib/provide-rtk-query.ts b/projects/ngrx-rtk-query/src/lib/provide-rtk-query.ts index d225993..065c1d3 100644 --- a/projects/ngrx-rtk-query/src/lib/provide-rtk-query.ts +++ b/projects/ngrx-rtk-query/src/lib/provide-rtk-query.ts @@ -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'; @@ -15,7 +15,6 @@ export function provideStoreRtkQuery(config?: Partial): Enviro return makeEnvironmentProviders([ { provide: STORE_RTK_QUERY_CONFIG, useValue: moduleConfig }, - ThunkService, { provide: ENVIRONMENT_INITIALIZER, multi: true, @@ -26,6 +25,6 @@ export function provideStoreRtkQuery(config?: Partial): Enviro ]); } -export function provideStoreApi(api: any): EnvironmentProviders { +export function provideStoreApi(api: Api, string, string, any>): EnvironmentProviders { return provideState(api.reducerPath, api.reducer, { metaReducers: [api.metareducer] }); } diff --git a/projects/ngrx-rtk-query/src/lib/store-rtk-query.config.ts b/projects/ngrx-rtk-query/src/lib/store-rtk-query.config.ts index 81842cc..2e71354 100644 --- a/projects/ngrx-rtk-query/src/lib/store-rtk-query.config.ts +++ b/projects/ngrx-rtk-query/src/lib/store-rtk-query.config.ts @@ -3,7 +3,6 @@ import { setupListeners } from '@reduxjs/toolkit/query'; export interface StoreQueryConfig { setupListeners: boolean | Parameters[1]; - baseUrl: string; } export let currentConfig: StoreQueryConfig | undefined; @@ -13,7 +12,6 @@ export const setupConfig = (config: StoreQueryConfig) => { export const defaultConfig: StoreQueryConfig = { setupListeners: false, - baseUrl: '', }; export const STORE_RTK_QUERY_CONFIG = new InjectionToken('STORE_RTK_QUERY_CONFIG'); diff --git a/projects/ngrx-rtk-query/src/lib/thunk.service.ts b/projects/ngrx-rtk-query/src/lib/thunk.service.ts index 96a7a29..1bf2ff4 100644 --- a/projects/ngrx-rtk-query/src/lib/thunk.service.ts +++ b/projects/ngrx-rtk-query/src/lib/thunk.service.ts @@ -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 = { @@ -40,14 +41,16 @@ export function select(mapFn: (state: any) => K): Signal { 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 = []; } diff --git a/src/app/core/services/counter.ts b/src/app/core/services/counter.ts index b22f6f4..650339b 100644 --- a/src/app/core/services/counter.ts +++ b/src/app/core/services/counter.ts @@ -1,3 +1,5 @@ +import { inject } from '@angular/core'; +import { Store } from '@ngrx/store'; import { createApi, fetchBaseQuery } from 'ngrx-rtk-query'; export interface CountResponse { @@ -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({