@tanstack/devtools 0.6.20 → 0.6.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk/{XFQ6P775.js → XF4JFOLU.js} +15 -0
- package/dist/dev.js +13 -3
- package/dist/devtools/{YM72BEIK.js → MBQPV7BO.js} +1907 -70
- package/dist/devtools/{6XAY2RKM.js → YRFZDV5N.js} +2260 -169
- package/dist/index.js +13 -3
- package/dist/server.js +9 -2
- package/package.json +6 -3
- package/src/components/source-inspector.tsx +158 -0
- package/src/context/devtools-context.tsx +24 -1
- package/src/core.tsx +15 -1
- package/src/devtools.tsx +3 -28
- package/src/styles/use-styles.ts +829 -0
- package/src/tabs/marketplace/card-utils.test.ts +219 -0
- package/src/tabs/marketplace/card-utils.ts +85 -0
- package/src/tabs/marketplace/marketplace-header.tsx +54 -0
- package/src/tabs/marketplace/plugin-card.tsx +165 -0
- package/src/tabs/marketplace/plugin-section.tsx +51 -0
- package/src/tabs/marketplace/plugin-utils.test.ts +518 -0
- package/src/tabs/marketplace/plugin-utils.ts +248 -0
- package/src/tabs/marketplace/settings-panel.tsx +41 -0
- package/src/tabs/marketplace/tag-filters.tsx +35 -0
- package/src/tabs/marketplace/types.ts +47 -0
- package/src/tabs/plugin-marketplace.tsx +346 -0
- package/src/tabs/plugin-registry.ts +222 -0
- package/src/tabs/plugins-tab.tsx +112 -65
- package/src/tabs/semver-utils.test.ts +218 -0
- package/src/tabs/semver-utils.ts +114 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { For, Show, createSignal, onCleanup, onMount } from 'solid-js'
|
|
2
|
+
import { devtoolsEventClient } from '@tanstack/devtools-client'
|
|
3
|
+
import { usePlugins } from '../context/use-devtools-context'
|
|
4
|
+
import { useStyles } from '../styles/use-styles'
|
|
5
|
+
import { PluginSectionComponent } from './marketplace/plugin-section'
|
|
6
|
+
import { SettingsPanel } from './marketplace/settings-panel'
|
|
7
|
+
import { MarketplaceHeader } from './marketplace/marketplace-header'
|
|
8
|
+
import { FRAMEWORKS } from './marketplace/types'
|
|
9
|
+
import {
|
|
10
|
+
buildPluginCards,
|
|
11
|
+
detectFramework,
|
|
12
|
+
groupIntoSections,
|
|
13
|
+
} from './marketplace/plugin-utils'
|
|
14
|
+
import type { PackageJson } from '@tanstack/devtools-client'
|
|
15
|
+
import type { PluginCard, PluginSection } from './marketplace/types'
|
|
16
|
+
|
|
17
|
+
export const PluginMarketplace = () => {
|
|
18
|
+
const styles = useStyles()
|
|
19
|
+
const { plugins } = usePlugins()
|
|
20
|
+
const [pluginSections, setPluginSections] = createSignal<
|
|
21
|
+
Array<PluginSection>
|
|
22
|
+
>([])
|
|
23
|
+
const [currentPackageJson, setCurrentPackageJson] =
|
|
24
|
+
createSignal<PackageJson | null>(null)
|
|
25
|
+
const [searchInput, setSearchInput] = createSignal('')
|
|
26
|
+
const [searchQuery, setSearchQuery] = createSignal('')
|
|
27
|
+
const [collapsedSections, setCollapsedSections] = createSignal<Set<string>>(
|
|
28
|
+
new Set(),
|
|
29
|
+
)
|
|
30
|
+
const [showActivePlugins, setShowActivePlugins] = createSignal(true)
|
|
31
|
+
const [selectedTags, setSelectedTags] = createSignal<Set<string>>(new Set())
|
|
32
|
+
const [isSettingsOpen, setIsSettingsOpen] = createSignal(false)
|
|
33
|
+
|
|
34
|
+
let debounceTimeout: ReturnType<typeof setTimeout> | undefined
|
|
35
|
+
|
|
36
|
+
// Debounce search input
|
|
37
|
+
const handleSearchInput = (value: string) => {
|
|
38
|
+
setSearchInput(value)
|
|
39
|
+
|
|
40
|
+
if (debounceTimeout) {
|
|
41
|
+
clearTimeout(debounceTimeout)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
debounceTimeout = setTimeout(() => {
|
|
45
|
+
setSearchQuery(value)
|
|
46
|
+
}, 300)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const toggleSection = (framework: string) => {
|
|
50
|
+
setCollapsedSections((prev) => {
|
|
51
|
+
const newSet = new Set(prev)
|
|
52
|
+
if (newSet.has(framework)) {
|
|
53
|
+
newSet.delete(framework)
|
|
54
|
+
} else {
|
|
55
|
+
newSet.add(framework)
|
|
56
|
+
}
|
|
57
|
+
return newSet
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const matchesSearch = (card: PluginCard, query: string): boolean => {
|
|
62
|
+
if (!query) return true
|
|
63
|
+
|
|
64
|
+
const lowerQuery = query.toLowerCase()
|
|
65
|
+
return (
|
|
66
|
+
card.devtoolsPackage.toLowerCase().includes(lowerQuery) ||
|
|
67
|
+
card.requiredPackageName.toLowerCase().includes(lowerQuery) ||
|
|
68
|
+
card.framework.toLowerCase().includes(lowerQuery)
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const getFilteredSections = () => {
|
|
73
|
+
const query = searchQuery()
|
|
74
|
+
const showActive = showActivePlugins()
|
|
75
|
+
const tags = selectedTags()
|
|
76
|
+
const pkg = currentPackageJson()
|
|
77
|
+
|
|
78
|
+
// Regenerate sections from current plugin state
|
|
79
|
+
if (!pkg) return []
|
|
80
|
+
|
|
81
|
+
const currentFramework = detectFramework(pkg, FRAMEWORKS)
|
|
82
|
+
const registeredPlugins = new Set(plugins()?.map((p) => p.id || '') || [])
|
|
83
|
+
|
|
84
|
+
// Build fresh cards from current state
|
|
85
|
+
const allCards = buildPluginCards(
|
|
86
|
+
pkg,
|
|
87
|
+
currentFramework,
|
|
88
|
+
registeredPlugins,
|
|
89
|
+
pluginSections().flatMap((s) => s.cards), // Preserve status from existing cards
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
// Generate sections from cards
|
|
93
|
+
let sections = groupIntoSections(allCards)
|
|
94
|
+
|
|
95
|
+
// Filter out active plugins section if hidden
|
|
96
|
+
if (!showActive) {
|
|
97
|
+
sections = sections.filter((section) => section.id !== 'active')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Filter by tags if any are selected
|
|
101
|
+
if (tags.size > 0) {
|
|
102
|
+
sections = sections
|
|
103
|
+
.map((section) => ({
|
|
104
|
+
...section,
|
|
105
|
+
cards: section.cards.filter((card) => {
|
|
106
|
+
if (!card.metadata?.tags) return false
|
|
107
|
+
return card.metadata.tags.some((tag) => tags.has(tag))
|
|
108
|
+
}),
|
|
109
|
+
}))
|
|
110
|
+
.filter((section) => section.cards.length > 0)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Apply search filter
|
|
114
|
+
if (!query) return sections
|
|
115
|
+
|
|
116
|
+
return sections
|
|
117
|
+
.map((section) => ({
|
|
118
|
+
...section,
|
|
119
|
+
cards: section.cards.filter((card) => matchesSearch(card, query)),
|
|
120
|
+
}))
|
|
121
|
+
.filter((section) => section.cards.length > 0)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
onMount(() => {
|
|
125
|
+
// Listen for package.json updates
|
|
126
|
+
const cleanupJsonRead = devtoolsEventClient.on(
|
|
127
|
+
'package-json-read',
|
|
128
|
+
(event) => {
|
|
129
|
+
setCurrentPackageJson(event.payload.packageJson)
|
|
130
|
+
updatePluginCards(event.payload.packageJson)
|
|
131
|
+
},
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
const cleanupJsonUpdated = devtoolsEventClient.on(
|
|
135
|
+
'package-json-updated',
|
|
136
|
+
(event) => {
|
|
137
|
+
setCurrentPackageJson(event.payload.packageJson)
|
|
138
|
+
updatePluginCards(event.payload.packageJson)
|
|
139
|
+
},
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
// Listen for installation results
|
|
143
|
+
const cleanupDevtoolsInstalled = devtoolsEventClient.on(
|
|
144
|
+
'devtools-installed',
|
|
145
|
+
(event) => {
|
|
146
|
+
setPluginSections((prevSections) =>
|
|
147
|
+
prevSections.map((section) => ({
|
|
148
|
+
...section,
|
|
149
|
+
cards: section.cards.map((card) =>
|
|
150
|
+
card.devtoolsPackage === event.payload.packageName
|
|
151
|
+
? {
|
|
152
|
+
...card,
|
|
153
|
+
status: event.payload.success ? 'success' : 'error',
|
|
154
|
+
error: event.payload.error,
|
|
155
|
+
}
|
|
156
|
+
: card,
|
|
157
|
+
),
|
|
158
|
+
})),
|
|
159
|
+
)
|
|
160
|
+
},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
// Listen for plugin added results
|
|
164
|
+
const cleanupPluginAdded = devtoolsEventClient.on(
|
|
165
|
+
'plugin-added',
|
|
166
|
+
(event) => {
|
|
167
|
+
setPluginSections((prevSections) =>
|
|
168
|
+
prevSections.map((section) => ({
|
|
169
|
+
...section,
|
|
170
|
+
cards: section.cards.map((card) =>
|
|
171
|
+
card.devtoolsPackage === event.payload.packageName
|
|
172
|
+
? {
|
|
173
|
+
...card,
|
|
174
|
+
status: event.payload.success ? 'success' : 'error',
|
|
175
|
+
error: event.payload.error,
|
|
176
|
+
}
|
|
177
|
+
: card,
|
|
178
|
+
),
|
|
179
|
+
})),
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
// When plugin is successfully added, recalculate to move it to active section
|
|
183
|
+
if (event.payload.success) {
|
|
184
|
+
const pkg = currentPackageJson()
|
|
185
|
+
if (pkg) {
|
|
186
|
+
updatePluginCards(pkg)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
onCleanup(() => {
|
|
193
|
+
cleanupJsonRead()
|
|
194
|
+
cleanupJsonUpdated()
|
|
195
|
+
cleanupDevtoolsInstalled()
|
|
196
|
+
cleanupPluginAdded()
|
|
197
|
+
})
|
|
198
|
+
// Emit mounted event to trigger package.json read
|
|
199
|
+
devtoolsEventClient.emit('mounted', undefined)
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
const updatePluginCards = (pkg: PackageJson | null) => {
|
|
203
|
+
if (!pkg) return
|
|
204
|
+
|
|
205
|
+
const currentFramework = detectFramework(pkg, FRAMEWORKS)
|
|
206
|
+
|
|
207
|
+
// Get list of registered plugin names
|
|
208
|
+
const registeredPlugins = new Set(plugins()?.map((p) => p.id || '') || [])
|
|
209
|
+
|
|
210
|
+
const allCards = buildPluginCards(
|
|
211
|
+
pkg,
|
|
212
|
+
currentFramework,
|
|
213
|
+
registeredPlugins,
|
|
214
|
+
pluginSections().flatMap((s) => s.cards),
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
const sections = groupIntoSections(allCards)
|
|
218
|
+
setPluginSections(sections)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const handleAction = (card: PluginCard) => {
|
|
222
|
+
if (
|
|
223
|
+
card.actionType === 'requires-package' ||
|
|
224
|
+
card.actionType === 'wrong-framework' ||
|
|
225
|
+
card.actionType === 'already-installed' ||
|
|
226
|
+
card.actionType === 'version-mismatch'
|
|
227
|
+
) {
|
|
228
|
+
// Can't install devtools without the base package, wrong framework, already installed, or version mismatch
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// change state to installing of the plugin user clicked
|
|
233
|
+
setPluginSections((prevSections) =>
|
|
234
|
+
prevSections.map((section) => ({
|
|
235
|
+
...section,
|
|
236
|
+
cards: section.cards.map((c) =>
|
|
237
|
+
c.devtoolsPackage === card.devtoolsPackage
|
|
238
|
+
? { ...c, status: 'installing' }
|
|
239
|
+
: c,
|
|
240
|
+
),
|
|
241
|
+
})),
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
// Bump the version of the required package and then add to devtools
|
|
245
|
+
if (card.actionType === 'bump-version') {
|
|
246
|
+
// emits the event to vite plugin to bump the package version, this will add it to devtools after
|
|
247
|
+
devtoolsEventClient.emit('bump-package-version', {
|
|
248
|
+
packageName: card.requiredPackageName,
|
|
249
|
+
devtoolsPackage: card.devtoolsPackage,
|
|
250
|
+
pluginName: card.metadata?.title || card.devtoolsPackage,
|
|
251
|
+
minVersion: card.metadata?.requires?.minVersion,
|
|
252
|
+
pluginImport: card.metadata?.pluginImport,
|
|
253
|
+
})
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (card.actionType === 'add-to-devtools') {
|
|
258
|
+
// emits the event to vite plugin to add the plugin
|
|
259
|
+
devtoolsEventClient.emit('add-plugin-to-devtools', {
|
|
260
|
+
packageName: card.devtoolsPackage,
|
|
261
|
+
// should always be defined
|
|
262
|
+
pluginName: card.metadata?.title ?? card.devtoolsPackage,
|
|
263
|
+
pluginImport: card.metadata?.pluginImport,
|
|
264
|
+
})
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
devtoolsEventClient.emit('install-devtools', {
|
|
268
|
+
packageName: card.devtoolsPackage,
|
|
269
|
+
// should always be defined
|
|
270
|
+
pluginName: card.metadata?.title ?? card.devtoolsPackage,
|
|
271
|
+
pluginImport: card.metadata?.pluginImport,
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Get all available tags from plugins (excluding active plugins)
|
|
276
|
+
const getAllTags = () => {
|
|
277
|
+
const tags = new Set<string>()
|
|
278
|
+
pluginSections().forEach((section) => {
|
|
279
|
+
// Only get tags from featured and available sections, not active plugins
|
|
280
|
+
if (section.id === 'featured' || section.id === 'available') {
|
|
281
|
+
section.cards.forEach((card) => {
|
|
282
|
+
if (card.metadata?.tags) {
|
|
283
|
+
card.metadata.tags.forEach((tag) => tags.add(tag))
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
return Array.from(tags).sort()
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const toggleTag = (tag: string) => {
|
|
292
|
+
setSelectedTags((prev) => {
|
|
293
|
+
const newTags = new Set(prev)
|
|
294
|
+
if (newTags.has(tag)) {
|
|
295
|
+
newTags.delete(tag)
|
|
296
|
+
} else {
|
|
297
|
+
newTags.add(tag)
|
|
298
|
+
}
|
|
299
|
+
return newTags
|
|
300
|
+
})
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return (
|
|
304
|
+
<div class={styles().pluginMarketplace}>
|
|
305
|
+
{/* Settings Panel */}
|
|
306
|
+
<SettingsPanel
|
|
307
|
+
isOpen={isSettingsOpen}
|
|
308
|
+
onClose={() => setIsSettingsOpen(false)}
|
|
309
|
+
showActivePlugins={showActivePlugins}
|
|
310
|
+
setShowActivePlugins={setShowActivePlugins}
|
|
311
|
+
/>
|
|
312
|
+
|
|
313
|
+
<MarketplaceHeader
|
|
314
|
+
searchInput={searchInput}
|
|
315
|
+
onSearchInput={handleSearchInput}
|
|
316
|
+
onSettingsClick={() => setIsSettingsOpen(!isSettingsOpen())}
|
|
317
|
+
tags={getAllTags}
|
|
318
|
+
selectedTags={selectedTags}
|
|
319
|
+
onToggleTag={toggleTag}
|
|
320
|
+
/>
|
|
321
|
+
|
|
322
|
+
<Show when={getFilteredSections().length > 0}>
|
|
323
|
+
<For each={getFilteredSections()}>
|
|
324
|
+
{(section) => (
|
|
325
|
+
<PluginSectionComponent
|
|
326
|
+
section={section}
|
|
327
|
+
isCollapsed={() => collapsedSections().has(section.id)}
|
|
328
|
+
onToggleCollapse={() => toggleSection(section.id)}
|
|
329
|
+
onCardAction={handleAction}
|
|
330
|
+
/>
|
|
331
|
+
)}
|
|
332
|
+
</For>
|
|
333
|
+
</Show>
|
|
334
|
+
|
|
335
|
+
<Show when={getFilteredSections().length === 0}>
|
|
336
|
+
<div class={styles().pluginMarketplaceEmpty}>
|
|
337
|
+
<p class={styles().pluginMarketplaceEmptyText}>
|
|
338
|
+
{searchQuery()
|
|
339
|
+
? `No plugins found matching "${searchQuery()}"`
|
|
340
|
+
: 'No additional plugins available. You have all compatible devtools installed and registered!'}
|
|
341
|
+
</p>
|
|
342
|
+
</div>
|
|
343
|
+
</Show>
|
|
344
|
+
</div>
|
|
345
|
+
)
|
|
346
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Registry - Metadata for TanStack and third-party devtools plugins
|
|
3
|
+
*
|
|
4
|
+
* This registry allows plugin authors to customize their marketplace cards with:
|
|
5
|
+
* - Custom titles and descriptions
|
|
6
|
+
* - Logo/image URLs
|
|
7
|
+
* - Minimum version requirements (semver)
|
|
8
|
+
* - External links
|
|
9
|
+
*
|
|
10
|
+
* External companies can open PRs to add their plugins here!
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface PluginMetadata {
|
|
14
|
+
/** Package name (e.g., '@tanstack/react-query-devtools') */
|
|
15
|
+
packageName: string
|
|
16
|
+
|
|
17
|
+
/** Display title shown in the marketplace card */
|
|
18
|
+
title: string
|
|
19
|
+
|
|
20
|
+
/** Short description of what the plugin does */
|
|
21
|
+
description?: string
|
|
22
|
+
|
|
23
|
+
/** URL to a logo image (SVG, PNG, etc.) */
|
|
24
|
+
logoUrl?: string
|
|
25
|
+
|
|
26
|
+
/** Required package dependency */
|
|
27
|
+
requires?: {
|
|
28
|
+
/** Required package name (e.g., '@tanstack/react-query') */
|
|
29
|
+
packageName: string
|
|
30
|
+
/** Minimum required version (semver) */
|
|
31
|
+
minVersion: string
|
|
32
|
+
/** Maximum version (if there's a known breaking change) */
|
|
33
|
+
maxVersion?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Plugin import configuration */
|
|
37
|
+
pluginImport?: {
|
|
38
|
+
/** The exact name to import from the package (e.g., 'FormDevtoolsPlugin' or 'ReactQueryDevtoolsPanel') */
|
|
39
|
+
importName: string
|
|
40
|
+
/** Whether this is a JSX component or a function that returns a plugin */
|
|
41
|
+
type: 'jsx' | 'function'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Custom plugin ID pattern for matching against registered plugins in devtools.
|
|
45
|
+
* If specified, this will be used to match plugin IDs that may have suffixes.
|
|
46
|
+
* For example, pluginId: "tanstack-form" will match "tanstack-form-4" in devtools.
|
|
47
|
+
* The default behavior of devtools is to lowercase the package name and replace non-alphanumeric characters with -
|
|
48
|
+
* so if the name of the plugin is "My awesome Plugin", the default pluginId would be "my-awesome-plugin".
|
|
49
|
+
*/
|
|
50
|
+
pluginId?: string
|
|
51
|
+
|
|
52
|
+
/** Official documentation URL / URL to the docs on how to implement devtools */
|
|
53
|
+
docsUrl?: string
|
|
54
|
+
|
|
55
|
+
/** Plugin author/maintainer */
|
|
56
|
+
author?: string
|
|
57
|
+
|
|
58
|
+
/** Repository URL */
|
|
59
|
+
repoUrl?: string
|
|
60
|
+
|
|
61
|
+
/** Framework this plugin supports */
|
|
62
|
+
framework: 'react' | 'solid' | 'vue' | 'svelte' | 'angular' | 'other'
|
|
63
|
+
|
|
64
|
+
/** Mark as featured to appear in the Featured section with animated border */
|
|
65
|
+
featured?: boolean
|
|
66
|
+
|
|
67
|
+
/** Mark as new to show a "New" banner on the card */
|
|
68
|
+
isNew?: boolean
|
|
69
|
+
|
|
70
|
+
/** Tags for filtering and categorization */
|
|
71
|
+
tags?: Array<string>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Registry of all known devtools plugins
|
|
76
|
+
* External contributors: Add your plugin metadata here!
|
|
77
|
+
*/
|
|
78
|
+
const PLUGIN_REGISTRY: Record<string, PluginMetadata> = {
|
|
79
|
+
// TanStack Query
|
|
80
|
+
'@tanstack/react-query-devtools': {
|
|
81
|
+
packageName: '@tanstack/react-query-devtools',
|
|
82
|
+
title: 'TanStack Query Devtools',
|
|
83
|
+
description:
|
|
84
|
+
'Powerful devtools for TanStack Query - inspect queries, mutations, and cache',
|
|
85
|
+
requires: {
|
|
86
|
+
packageName: '@tanstack/react-query',
|
|
87
|
+
minVersion: '5.0.0',
|
|
88
|
+
},
|
|
89
|
+
pluginId: 'tanstack-query',
|
|
90
|
+
docsUrl: 'https://tanstack.com/query/latest/docs/devtools',
|
|
91
|
+
author: 'TanStack',
|
|
92
|
+
framework: 'react',
|
|
93
|
+
featured: true, // Featured plugin
|
|
94
|
+
tags: ['TanStack', 'data-fetching', 'caching', 'state-management'],
|
|
95
|
+
},
|
|
96
|
+
'@tanstack/solid-query-devtools': {
|
|
97
|
+
packageName: '@tanstack/solid-query-devtools',
|
|
98
|
+
title: 'TanStack Query Devtools',
|
|
99
|
+
description:
|
|
100
|
+
'Powerful devtools for TanStack Query - inspect queries, mutations, and cache',
|
|
101
|
+
requires: {
|
|
102
|
+
packageName: '@tanstack/solid-query',
|
|
103
|
+
minVersion: '5.0.0',
|
|
104
|
+
},
|
|
105
|
+
pluginId: 'tanstack-query',
|
|
106
|
+
docsUrl: 'https://tanstack.com/query/latest/docs/devtools',
|
|
107
|
+
author: 'TanStack',
|
|
108
|
+
framework: 'solid',
|
|
109
|
+
tags: ['TanStack', 'data-fetching', 'caching', 'state-management'],
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
// TanStack Router
|
|
113
|
+
'@tanstack/react-router-devtools': {
|
|
114
|
+
packageName: '@tanstack/react-router-devtools',
|
|
115
|
+
title: 'TanStack Router Devtools',
|
|
116
|
+
description: 'Inspect routes, navigation, and router state in real-time',
|
|
117
|
+
requires: {
|
|
118
|
+
packageName: '@tanstack/react-router',
|
|
119
|
+
minVersion: '1.0.0',
|
|
120
|
+
},
|
|
121
|
+
pluginId: 'tanstack-router',
|
|
122
|
+
docsUrl: 'https://tanstack.com/router/latest/docs/devtools',
|
|
123
|
+
author: 'TanStack',
|
|
124
|
+
framework: 'react',
|
|
125
|
+
featured: true, // Featured plugin
|
|
126
|
+
tags: ['TanStack', 'routing', 'navigation'],
|
|
127
|
+
},
|
|
128
|
+
'@tanstack/solid-router-devtools': {
|
|
129
|
+
packageName: '@tanstack/solid-router-devtools',
|
|
130
|
+
title: 'TanStack Router Devtools',
|
|
131
|
+
description: 'Inspect routes, navigation, and router state in real-time',
|
|
132
|
+
requires: {
|
|
133
|
+
packageName: '@tanstack/solid-router',
|
|
134
|
+
minVersion: '1.0.0',
|
|
135
|
+
},
|
|
136
|
+
pluginId: 'tanstack-router',
|
|
137
|
+
docsUrl: 'https://tanstack.com/router/latest/docs/devtools',
|
|
138
|
+
author: 'TanStack',
|
|
139
|
+
framework: 'solid',
|
|
140
|
+
tags: ['TanStack', 'routing', 'navigation'],
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// TanStack Form
|
|
144
|
+
'@tanstack/react-form-devtools': {
|
|
145
|
+
packageName: '@tanstack/react-form-devtools',
|
|
146
|
+
title: 'TanStack Form Devtools',
|
|
147
|
+
description: 'Debug form state, validation, and field values',
|
|
148
|
+
requires: {
|
|
149
|
+
packageName: '@tanstack/react-form',
|
|
150
|
+
minVersion: '1.23.0',
|
|
151
|
+
},
|
|
152
|
+
pluginImport: {
|
|
153
|
+
importName: 'FormDevtoolsPlugin',
|
|
154
|
+
type: 'function',
|
|
155
|
+
},
|
|
156
|
+
pluginId: 'tanstack-form',
|
|
157
|
+
docsUrl: 'https://tanstack.com/form/latest/docs/devtools',
|
|
158
|
+
author: 'TanStack',
|
|
159
|
+
framework: 'react',
|
|
160
|
+
isNew: true,
|
|
161
|
+
tags: ['TanStack', 'forms', 'validation'],
|
|
162
|
+
},
|
|
163
|
+
'@tanstack/solid-form-devtools': {
|
|
164
|
+
packageName: '@tanstack/solid-form-devtools',
|
|
165
|
+
title: 'TanStack Form Devtools',
|
|
166
|
+
description: 'Debug form state, validation, and field values',
|
|
167
|
+
requires: {
|
|
168
|
+
packageName: '@tanstack/solid-form',
|
|
169
|
+
minVersion: '1.23.0',
|
|
170
|
+
},
|
|
171
|
+
pluginImport: {
|
|
172
|
+
importName: 'FormDevtoolsPlugin',
|
|
173
|
+
type: 'function',
|
|
174
|
+
},
|
|
175
|
+
pluginId: 'tanstack-form',
|
|
176
|
+
docsUrl: 'https://tanstack.com/form/latest/docs/devtools',
|
|
177
|
+
author: 'TanStack',
|
|
178
|
+
isNew: true,
|
|
179
|
+
framework: 'solid',
|
|
180
|
+
tags: ['TanStack', 'forms', 'validation'],
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
// TanStack Pacer (Example - adjust as needed)
|
|
184
|
+
'@tanstack/react-pacer-devtools': {
|
|
185
|
+
packageName: '@tanstack/react-pacer-devtools',
|
|
186
|
+
title: 'Pacer Devtools',
|
|
187
|
+
description: 'Monitor and debug your Pacer animations and transitions',
|
|
188
|
+
requires: {
|
|
189
|
+
packageName: '@tanstack/react-pacer',
|
|
190
|
+
minVersion: '0.16.4',
|
|
191
|
+
},
|
|
192
|
+
author: 'TanStack',
|
|
193
|
+
framework: 'react',
|
|
194
|
+
isNew: true, // New plugin banner
|
|
195
|
+
tags: ['TanStack'],
|
|
196
|
+
},
|
|
197
|
+
'@tanstack/solid-pacer-devtools': {
|
|
198
|
+
packageName: '@tanstack/solid-pacer-devtools',
|
|
199
|
+
title: 'Pacer Devtools',
|
|
200
|
+
description: 'Monitor and debug your Pacer animations and transitions',
|
|
201
|
+
requires: {
|
|
202
|
+
packageName: '@tanstack/solid-pacer',
|
|
203
|
+
minVersion: '0.14.4',
|
|
204
|
+
},
|
|
205
|
+
author: 'TanStack',
|
|
206
|
+
framework: 'solid',
|
|
207
|
+
isNew: true, // New plugin banner
|
|
208
|
+
tags: ['TanStack'],
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
// ==========================================
|
|
212
|
+
// THIRD-PARTY PLUGINS - Examples
|
|
213
|
+
// ==========================================
|
|
214
|
+
// External contributors can add their plugins below!
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get all registered plugin metadata
|
|
219
|
+
*/
|
|
220
|
+
export function getAllPluginMetadata(): Array<PluginMetadata> {
|
|
221
|
+
return Object.values(PLUGIN_REGISTRY)
|
|
222
|
+
}
|