forked from TanStack/query
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinject-devtools-panel.ts
150 lines (136 loc) · 4.23 KB
/
inject-devtools-panel.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import {
DestroyRef,
Injector,
PLATFORM_ID,
assertInInjectionContext,
computed,
effect,
inject,
runInInjectionContext,
untracked,
} from '@angular/core'
import { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'
import {
QueryClient,
onlineManager,
} from '@tanstack/angular-query-experimental'
import { isPlatformBrowser } from '@angular/common'
import type { ElementRef } from '@angular/core'
import type { DevtoolsErrorType } from '@tanstack/query-devtools'
export interface InjectDevtoolsPanelOptions {
/**
* The `Injector` in which to create the devtools panel.
*
* If this is not provided, the current injection context will be used instead (via `inject`).
*/
injector?: Injector
}
/**
* Inject a TanStack Query devtools panel and render it in the DOM.
*
* Devtools panel allows programmatic control over the devtools, for example if you want to render
* the devtools as part of your own devtools.
*
* Consider `withDevtools` instead if you don't need this.
* @param injectDevtoolsPanelFn - A function that returns devtools panel options.
* @param options - Additional configuration
* @returns DevtoolsPanelRef
* @see https://tanstack.com/query/v5/docs/framework/angular/devtools
*/
export function injectDevtoolsPanel(
injectDevtoolsPanelFn: () => DevtoolsPanelOptions,
options?: InjectDevtoolsPanelOptions,
): DevtoolsPanelRef {
!options?.injector && assertInInjectionContext(injectDevtoolsPanel)
const currentInjector = options?.injector ?? inject(Injector)
return runInInjectionContext(currentInjector, () => {
const destroyRef = inject(DestroyRef)
const isBrowser = isPlatformBrowser(inject(PLATFORM_ID))
const injectedClient = inject(QueryClient, { optional: true })
const queryOptions = computed(injectDevtoolsPanelFn)
let devtools: TanstackQueryDevtoolsPanel | null = null
const destroy = () => {
devtools?.unmount()
devtools = null
}
if (!isBrowser)
return {
destroy,
}
effect(() => {
const {
client = injectedClient,
errorTypes = [],
styleNonce,
shadowDOMTarget,
onClose,
hostElement,
} = queryOptions()
untracked(() => {
if (!client) throw new Error('No QueryClient found')
if (!devtools && hostElement) {
devtools = new TanstackQueryDevtoolsPanel({
client,
queryFlavor: 'Angular Query',
version: '5',
buttonPosition: 'bottom-left',
position: 'bottom',
initialIsOpen: true,
errorTypes,
styleNonce,
shadowDOMTarget,
onClose,
onlineManager,
})
devtools.mount(hostElement.nativeElement)
} else if (devtools && hostElement) {
devtools.setClient(client)
devtools.setErrorTypes(errorTypes)
onClose && devtools.setOnClose(onClose)
} else if (devtools && !hostElement) {
destroy()
}
})
})
destroyRef.onDestroy(destroy)
return {
destroy,
}
})
}
/**
* A devtools panel, which can be manually destroyed.
*/
export interface DevtoolsPanelRef {
/**
* Destroy the panel, removing it from the DOM and stops listening to signal changes.
*/
destroy: () => void
}
export interface DevtoolsPanelOptions {
/**
* Custom instance of QueryClient
*/
client?: QueryClient
/**
* Use this so you can define custom errors that can be shown in the devtools.
*/
errorTypes?: Array<DevtoolsErrorType>
/**
* Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
*/
styleNonce?: string
/**
* Use this so you can attach the devtool's styles to specific element in the DOM.
*/
shadowDOMTarget?: ShadowRoot
/**
* Callback function that is called when the devtools panel is closed
*/
onClose?: () => unknown
/**
* Element where to render the devtools panel. When set to undefined or null, the devtools panel will not be created, or destroyed if existing.
* If changed from undefined to a ElementRef, the devtools panel will be created.
*/
hostElement?: ElementRef
}