Skip to content

Commit

Permalink
feat(angular-query): migrate to provideEnvironmentInitializer
Browse files Browse the repository at this point in the history
  • Loading branch information
OmerGronich committed Nov 29, 2024
1 parent 3f690e4 commit af5b47b
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
} from '@tanstack/angular-query-experimental'
import {
DestroyRef,
ENVIRONMENT_INITIALIZER,
PLATFORM_ID,
inject,
provideEnvironmentInitializer,
signal,
} from '@angular/core'
import { isPlatformBrowser } from '@angular/common'
Expand Down Expand Up @@ -60,35 +60,31 @@ export function withPersistQueryClient(
const isRestoring = signal(false)
const providers = [
provideIsRestoring(isRestoring.asReadonly()),
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue: () => {
if (!isPlatformBrowser(inject(PLATFORM_ID))) return
const destroyRef = inject(DestroyRef)
const queryClient = injectQueryClient()
provideEnvironmentInitializer(() => {
if (!isPlatformBrowser(inject(PLATFORM_ID))) return
const destroyRef = inject(DestroyRef)
const queryClient = injectQueryClient()

isRestoring.set(true)
const restorations = persistQueryClientOptions.map(
({ onSuccess, persistOptions }) => {
const options = { queryClient, ...persistOptions }
return persistQueryClientRestore(options).then(async () => {
try {
if (onSuccess) {
await onSuccess()
}
} finally {
const cleanup = persistQueryClientSubscribe(options)
destroyRef.onDestroy(cleanup)
isRestoring.set(true)
const restorations = persistQueryClientOptions.map(
({ onSuccess, persistOptions }) => {
const options = { queryClient, ...persistOptions }
return persistQueryClientRestore(options).then(async () => {
try {
if (onSuccess) {
await onSuccess()
}
})
},
)
Promise.all(restorations).finally(() => {
isRestoring.set(false)
})
},
},
} finally {
const cleanup = persistQueryClientSubscribe(options)
destroyRef.onDestroy(cleanup)
}
})
},
)
Promise.all(restorations).finally(() => {
isRestoring.set(false)
})
}),
]
return queryFeature('PersistQueryClient', providers)
}
162 changes: 77 additions & 85 deletions packages/angular-query-experimental/src/providers.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {
DestroyRef,
ENVIRONMENT_INITIALIZER,
Injector,
PLATFORM_ID,
computed,
effect,
inject,
makeEnvironmentProviders,
provideEnvironmentInitializer,
runInInjectionContext,
} from '@angular/core'
import { QueryClient, onlineManager } from '@tanstack/query-core'
Expand All @@ -21,6 +21,8 @@ import type {
TanstackQueryDevtools,
} from '@tanstack/query-devtools'

type Providers = Provider | EnvironmentProviders

/**
* Usually {@link provideTanStackQuery} is used once to set up TanStack Query and the
* {@link https://tanstack.com/query/latest/docs/reference/QueryClient|QueryClient}
Expand Down Expand Up @@ -98,15 +100,11 @@ export function provideTanStackQuery(
): EnvironmentProviders {
return makeEnvironmentProviders([
provideQueryClient(queryClient),
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue: () => {
queryClient.mount()
// Unmount the query client on application destroy
inject(DestroyRef).onDestroy(() => queryClient.unmount())
},
},
provideEnvironmentInitializer(() => {
queryClient.mount()
// Unmount the query client on application destroy
inject(DestroyRef).onDestroy(() => queryClient.unmount())
}),
features.map((feature) => feature.ɵproviders),
])
}
Expand All @@ -132,7 +130,7 @@ export function provideAngularQuery(
*/
export interface QueryFeature<TFeatureKind extends QueryFeatureKind> {
ɵkind: TFeatureKind
ɵproviders: Array<Provider>
ɵproviders: Providers
}

/**
Expand All @@ -143,7 +141,7 @@ export interface QueryFeature<TFeatureKind extends QueryFeatureKind> {
*/
export function queryFeature<TFeatureKind extends QueryFeatureKind>(
kind: TFeatureKind,
providers: Array<Provider>,
providers: Providers,
): QueryFeature<TFeatureKind> {
return { ɵkind: kind, ɵproviders: providers }
}
Expand Down Expand Up @@ -250,95 +248,89 @@ export interface DevtoolsOptions {
export function withDevtools(
optionsFn?: () => DevtoolsOptions,
): DeveloperToolsFeature {
let providers: Array<Provider> = []
let providers: Providers = []
if (!isDevMode() && !optionsFn) {
providers = []
} else {
providers = [
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useFactory: () => {
if (!isPlatformBrowser(inject(PLATFORM_ID))) return noop
const injector = inject(Injector)
const options = computed(() =>
runInInjectionContext(injector, () => optionsFn?.() ?? {}),
)
provideEnvironmentInitializer(() => {
if (!isPlatformBrowser(inject(PLATFORM_ID))) return noop
const injector = inject(Injector)
const options = computed(() =>
runInInjectionContext(injector, () => optionsFn?.() ?? {}),
)

let devtools: TanstackQueryDevtools | null = null
let el: HTMLElement | null = null
let devtools: TanstackQueryDevtools | null = null
let el: HTMLElement | null = null

const shouldLoadToolsSignal = computed(() => {
const { loadDevtools } = options()
return typeof loadDevtools === 'boolean'
? loadDevtools
: isDevMode()
})
const shouldLoadToolsSignal = computed(() => {
const { loadDevtools } = options()
return typeof loadDevtools === 'boolean' ? loadDevtools : isDevMode()
})

const destroyRef = inject(DestroyRef)
const destroyRef = inject(DestroyRef)

const getResolvedQueryClient = () => {
const injectedClient = injector.get(QueryClient, null)
const client = options().client ?? injectedClient
if (!client) {
throw new Error('No QueryClient found')
}
return client
const getResolvedQueryClient = () => {
const injectedClient = injector.get(QueryClient, null)
const client = options().client ?? injectedClient
if (!client) {
throw new Error('No QueryClient found')
}
return client
}

const destroyDevtools = () => {
devtools?.unmount()
el?.remove()
devtools = null
}
const destroyDevtools = () => {
devtools?.unmount()
el?.remove()
devtools = null
}

return () =>
effect(() => {
const shouldLoadTools = shouldLoadToolsSignal()
const {
client,
position,
errorTypes,
buttonPosition,
initialIsOpen,
} = options()
return () =>
effect(() => {
const shouldLoadTools = shouldLoadToolsSignal()
const {
client,
position,
errorTypes,
buttonPosition,
initialIsOpen,
} = options()

if (devtools && !shouldLoadTools) {
destroyDevtools()
return
} else if (devtools && shouldLoadTools) {
client && devtools.setClient(client)
position && devtools.setPosition(position)
errorTypes && devtools.setErrorTypes(errorTypes)
buttonPosition && devtools.setButtonPosition(buttonPosition)
initialIsOpen && devtools.setInitialIsOpen(initialIsOpen)
return
} else if (!shouldLoadTools) {
return
}
if (devtools && !shouldLoadTools) {
destroyDevtools()
return
} else if (devtools && shouldLoadTools) {
client && devtools.setClient(client)
position && devtools.setPosition(position)
errorTypes && devtools.setErrorTypes(errorTypes)
buttonPosition && devtools.setButtonPosition(buttonPosition)
initialIsOpen && devtools.setInitialIsOpen(initialIsOpen)
return
} else if (!shouldLoadTools) {
return
}

el = document.body.appendChild(document.createElement('div'))
el.classList.add('tsqd-parent-container')
el = document.body.appendChild(document.createElement('div'))
el.classList.add('tsqd-parent-container')

import('@tanstack/query-devtools').then((queryDevtools) =>
runInInjectionContext(injector, () => {
devtools = new queryDevtools.TanstackQueryDevtools({
...options(),
client: getResolvedQueryClient(),
queryFlavor: 'Angular Query',
version: '5',
onlineManager,
})
import('@tanstack/query-devtools').then((queryDevtools) =>
runInInjectionContext(injector, () => {
devtools = new queryDevtools.TanstackQueryDevtools({
...options(),
client: getResolvedQueryClient(),
queryFlavor: 'Angular Query',
version: '5',
onlineManager,
})

el && devtools.mount(el)
el && devtools.mount(el)

// Unmount the devtools on application destroy
destroyRef.onDestroy(destroyDevtools)
}),
)
})
},
},
// Unmount the devtools on application destroy
destroyRef.onDestroy(destroyDevtools)
}),
)
})
}),
]
}
return queryFeature('DeveloperTools', providers)
Expand Down

0 comments on commit af5b47b

Please sign in to comment.