@geenius/tools 0.1.0 → 0.3.0
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/package.json +62 -3
- package/packages/convex/shared/README.md +1 -1
- package/packages/devtools/dist/index.d.ts +204 -0
- package/packages/devtools/dist/index.js +186 -0
- package/packages/devtools/dist/index.js.map +1 -0
- package/packages/devtools/react/README.md +1 -1
- package/packages/devtools/solidjs/README.md +1 -1
- package/packages/devtools/solidjs/dist/index.js +1830 -0
- package/packages/devtools/solidjs/dist/index.js.map +1 -0
- package/packages/env/dist/index.d.ts +151 -0
- package/packages/env/dist/index.js +93 -0
- package/packages/env/dist/index.js.map +1 -0
- package/packages/errors/dist/index.d.ts +177 -0
- package/packages/errors/dist/index.js +187 -0
- package/packages/errors/dist/index.js.map +1 -0
- package/packages/errors/react/README.md +1 -1
- package/packages/errors/solidjs/README.md +1 -1
- package/packages/logger/dist/index.d.ts +171 -0
- package/packages/logger/dist/index.js +216 -0
- package/packages/logger/dist/index.js.map +1 -0
- package/packages/logger/react/README.md +1 -1
- package/packages/logger/solidjs/README.md +1 -1
- package/packages/perf/dist/index.d.ts +168 -0
- package/packages/perf/dist/index.js +265 -0
- package/packages/perf/dist/index.js.map +1 -0
- package/packages/perf/react/README.md +1 -1
- package/packages/perf/solidjs/README.md +1 -1
- package/packages/shared/dist/index.d.ts +253 -0
- package/packages/shared/dist/index.js +278 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.env.example +0 -2
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.node-version +0 -1
- package/.nvmrc +0 -1
- package/.prettierrc +0 -7
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -26
- package/CONTRIBUTING.md +0 -69
- package/SECURITY.md +0 -18
- package/SUPPORT.md +0 -14
- package/packages/convex/shared/package.json +0 -42
- package/packages/convex/shared/src/audit/index.ts +0 -5
- package/packages/convex/shared/src/audit/presets.ts +0 -165
- package/packages/convex/shared/src/audit/schema.ts +0 -85
- package/packages/convex/shared/src/audit/write.ts +0 -102
- package/packages/convex/shared/src/extract.ts +0 -75
- package/packages/convex/shared/src/index.ts +0 -41
- package/packages/convex/shared/src/messages.ts +0 -45
- package/packages/convex/shared/src/security.ts +0 -112
- package/packages/convex/shared/src/throw.ts +0 -184
- package/packages/convex/shared/src/types.ts +0 -57
- package/packages/convex/shared/src/utils.ts +0 -58
- package/packages/convex/shared/tsconfig.json +0 -28
- package/packages/convex/shared/tsup.config.ts +0 -12
- package/packages/devtools/package.json +0 -27
- package/packages/devtools/react/package.json +0 -53
- package/packages/devtools/react/src/components/DesignPreview.tsx +0 -59
- package/packages/devtools/react/src/components/DesignSwitcherDropdown.tsx +0 -99
- package/packages/devtools/react/src/components/DevSidebar.tsx +0 -247
- package/packages/devtools/react/src/components/DevToolbar.tsx +0 -242
- package/packages/devtools/react/src/components/GitHubIssueDialog.tsx +0 -402
- package/packages/devtools/react/src/components/InspectorOverlay.tsx +0 -312
- package/packages/devtools/react/src/components/PageLoadWaterfall.tsx +0 -144
- package/packages/devtools/react/src/components/PerformancePanel.tsx +0 -330
- package/packages/devtools/react/src/context/DevModeContext.tsx +0 -226
- package/packages/devtools/react/src/context/PerformanceContext.tsx +0 -143
- package/packages/devtools/react/src/data/designs.ts +0 -13
- package/packages/devtools/react/src/hooks/useGitHubLabels.ts +0 -47
- package/packages/devtools/react/src/hooks/useVirtualList.ts +0 -124
- package/packages/devtools/react/src/index.ts +0 -77
- package/packages/devtools/react/src/panels/ConvexSpy.tsx +0 -130
- package/packages/devtools/react/src/panels/DatabaseSeeder.tsx +0 -116
- package/packages/devtools/react/src/panels/DevModePhase2.tsx +0 -191
- package/packages/devtools/react/src/panels/DevModePhase3.tsx +0 -234
- package/packages/devtools/react/src/panels/FeatureFlagsToggle.tsx +0 -104
- package/packages/devtools/react/src/panels/QuickRouteJump.tsx +0 -152
- package/packages/devtools/react/src/services/github-service.ts +0 -247
- package/packages/devtools/react/tsconfig.json +0 -31
- package/packages/devtools/react/tsup.config.ts +0 -18
- package/packages/devtools/solidjs/package.json +0 -49
- package/packages/devtools/solidjs/src/components/DesignPreview.tsx +0 -51
- package/packages/devtools/solidjs/src/components/DesignSwitcherDropdown.tsx +0 -95
- package/packages/devtools/solidjs/src/components/DevSidebar.tsx +0 -247
- package/packages/devtools/solidjs/src/components/DevToolbar.tsx +0 -242
- package/packages/devtools/solidjs/src/components/GitHubIssueDialog.tsx +0 -400
- package/packages/devtools/solidjs/src/components/InspectorOverlay.tsx +0 -311
- package/packages/devtools/solidjs/src/components/PageLoadWaterfall.tsx +0 -144
- package/packages/devtools/solidjs/src/components/PerformancePanel.tsx +0 -330
- package/packages/devtools/solidjs/src/context/DevModeContext.tsx +0 -216
- package/packages/devtools/solidjs/src/context/PerformanceContext.tsx +0 -135
- package/packages/devtools/solidjs/src/data/designs.ts +0 -13
- package/packages/devtools/solidjs/src/hooks/createGitHubLabels.ts +0 -47
- package/packages/devtools/solidjs/src/index.ts +0 -64
- package/packages/devtools/solidjs/src/services/github-service.ts +0 -247
- package/packages/devtools/solidjs/tsconfig.json +0 -21
- package/packages/devtools/src/index.ts +0 -377
- package/packages/devtools/tsup.config.ts +0 -12
- package/packages/env/package.json +0 -30
- package/packages/env/src/index.ts +0 -264
- package/packages/env/tsup.config.ts +0 -12
- package/packages/errors/package.json +0 -27
- package/packages/errors/react/package.json +0 -72
- package/packages/errors/react/src/analytics.ts +0 -16
- package/packages/errors/react/src/components/ErrorBoundary.tsx +0 -248
- package/packages/errors/react/src/components/ErrorDisplay.tsx +0 -328
- package/packages/errors/react/src/components/ValidationErrors.tsx +0 -102
- package/packages/errors/react/src/config.ts +0 -199
- package/packages/errors/react/src/constants.ts +0 -74
- package/packages/errors/react/src/hooks/useErrorBoundary.ts +0 -92
- package/packages/errors/react/src/hooks/useErrorHandler.ts +0 -87
- package/packages/errors/react/src/index.ts +0 -96
- package/packages/errors/react/src/types.ts +0 -102
- package/packages/errors/react/src/utils/errorMessages.ts +0 -35
- package/packages/errors/react/src/utils/errorPolicy.ts +0 -139
- package/packages/errors/react/src/utils/extractAppError.ts +0 -174
- package/packages/errors/react/src/utils/formatError.ts +0 -112
- package/packages/errors/react/tsconfig.json +0 -25
- package/packages/errors/react/tsup.config.ts +0 -24
- package/packages/errors/solidjs/package.json +0 -46
- package/packages/errors/solidjs/src/components/ErrorDisplay.tsx +0 -179
- package/packages/errors/solidjs/src/config.ts +0 -98
- package/packages/errors/solidjs/src/hooks/createErrorHandler.ts +0 -107
- package/packages/errors/solidjs/src/index.ts +0 -61
- package/packages/errors/solidjs/src/types.ts +0 -34
- package/packages/errors/solidjs/src/utils/errorPolicy.ts +0 -56
- package/packages/errors/solidjs/src/utils/extractAppError.ts +0 -94
- package/packages/errors/solidjs/src/utils/formatError.ts +0 -33
- package/packages/errors/solidjs/tsconfig.json +0 -26
- package/packages/errors/solidjs/tsup.config.ts +0 -21
- package/packages/errors/src/index.ts +0 -320
- package/packages/errors/tsup.config.ts +0 -12
- package/packages/logger/package.json +0 -27
- package/packages/logger/react/package.json +0 -46
- package/packages/logger/react/src/index.ts +0 -4
- package/packages/logger/react/src/useMetrics.ts +0 -42
- package/packages/logger/react/src/usePerformanceLog.ts +0 -61
- package/packages/logger/react/tsconfig.json +0 -31
- package/packages/logger/react/tsup.config.ts +0 -12
- package/packages/logger/solidjs/package.json +0 -45
- package/packages/logger/solidjs/src/createMetrics.ts +0 -37
- package/packages/logger/solidjs/src/createPerformanceLog.ts +0 -58
- package/packages/logger/solidjs/src/index.ts +0 -4
- package/packages/logger/solidjs/tsconfig.json +0 -32
- package/packages/logger/solidjs/tsup.config.ts +0 -12
- package/packages/logger/src/index.ts +0 -363
- package/packages/logger/tsup.config.ts +0 -12
- package/packages/perf/package.json +0 -27
- package/packages/perf/react/package.json +0 -59
- package/packages/perf/react/src/components/PerformanceDashboard.tsx +0 -257
- package/packages/perf/react/src/hooks/useMonitoredQuery.ts +0 -89
- package/packages/perf/react/src/hooks/usePerformanceMetrics.ts +0 -78
- package/packages/perf/react/src/index.ts +0 -33
- package/packages/perf/react/src/services/PerformanceMonitor.ts +0 -313
- package/packages/perf/react/src/types.ts +0 -77
- package/packages/perf/react/tsconfig.json +0 -25
- package/packages/perf/react/tsup.config.ts +0 -19
- package/packages/perf/solidjs/package.json +0 -41
- package/packages/perf/solidjs/src/components/PerformanceDashboard.tsx +0 -207
- package/packages/perf/solidjs/src/hooks/createPerformanceMetrics.ts +0 -73
- package/packages/perf/solidjs/src/index.ts +0 -31
- package/packages/perf/solidjs/src/services/PerformanceMonitor.ts +0 -134
- package/packages/perf/solidjs/src/types.ts +0 -78
- package/packages/perf/solidjs/tsconfig.json +0 -26
- package/packages/perf/solidjs/tsup.config.ts +0 -14
- package/packages/perf/src/index.ts +0 -410
- package/packages/perf/tsup.config.ts +0 -12
- package/pnpm-workspace.yaml +0 -2
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-solidjs — src/components/PerformancePanel.tsx
|
|
2
|
-
|
|
3
|
-
import { createMemo, createEffect } from 'solid-js'
|
|
4
|
-
import { cn } from '@geenius-ui/solid'
|
|
5
|
-
import { X, Trash2, Activity, Zap, Clock, AlertTriangle } from 'lucide-solid'
|
|
6
|
-
import { createPerformanceContext } from '../context/PerformanceContext'
|
|
7
|
-
import type { PerformanceMetric } from '@geenius-tools/logger'
|
|
8
|
-
|
|
9
|
-
function getDurationColor(duration: number | undefined): string {
|
|
10
|
-
if (duration === undefined) return 'text-white/40'
|
|
11
|
-
if (duration > 100) return 'text-red-400'
|
|
12
|
-
if (duration > 50) return 'text-yellow-400'
|
|
13
|
-
return 'text-green-400'
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function getDurationBgColor(duration: number | undefined): string {
|
|
17
|
-
if (duration === undefined) return 'bg-white/20'
|
|
18
|
-
if (duration > 100) return 'bg-red-500'
|
|
19
|
-
if (duration > 50) return 'bg-yellow-500'
|
|
20
|
-
return 'bg-green-500'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function getTypeColor(type: string): string {
|
|
24
|
-
switch (type) {
|
|
25
|
-
case 'network':
|
|
26
|
-
return 'text-blue-400'
|
|
27
|
-
case 'query':
|
|
28
|
-
return 'text-orange-400'
|
|
29
|
-
case 'mutation':
|
|
30
|
-
return 'text-red-400'
|
|
31
|
-
case 'render':
|
|
32
|
-
return 'text-purple-400'
|
|
33
|
-
case 'route':
|
|
34
|
-
return 'text-green-400'
|
|
35
|
-
case 'component':
|
|
36
|
-
return 'text-cyan-400'
|
|
37
|
-
case 'effect':
|
|
38
|
-
return 'text-teal-400'
|
|
39
|
-
default:
|
|
40
|
-
return 'text-white/60'
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getTypeIcon(type: string) {
|
|
45
|
-
switch (type) {
|
|
46
|
-
case 'network':
|
|
47
|
-
return '🌐'
|
|
48
|
-
case 'query':
|
|
49
|
-
return '🔍'
|
|
50
|
-
case 'mutation':
|
|
51
|
-
return '✏️'
|
|
52
|
-
case 'render':
|
|
53
|
-
return '🎨'
|
|
54
|
-
case 'route':
|
|
55
|
-
return '🧭'
|
|
56
|
-
case 'component':
|
|
57
|
-
return '📦'
|
|
58
|
-
case 'effect':
|
|
59
|
-
return '⚡'
|
|
60
|
-
default:
|
|
61
|
-
return '📝'
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const MiniBar = memo(function MiniBar({
|
|
66
|
-
height,
|
|
67
|
-
color,
|
|
68
|
-
label,
|
|
69
|
-
}: {
|
|
70
|
-
height: number
|
|
71
|
-
color: string
|
|
72
|
-
label: string
|
|
73
|
-
}) {
|
|
74
|
-
return (
|
|
75
|
-
<div class="flex flex-col items-center gap-0.5 flex-1 min-w-0">
|
|
76
|
-
<div class="w-full h-12 flex items-end">
|
|
77
|
-
<div
|
|
78
|
-
class={cn('w-full rounded-t-sm transition-all duration-300', color)}
|
|
79
|
-
style={{ height: `${Math.min(height, 100)}%` }}
|
|
80
|
-
title={label}
|
|
81
|
-
/>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
const MetricRow = memo(function MetricRow({
|
|
88
|
-
metric,
|
|
89
|
-
}: {
|
|
90
|
-
metric: PerformanceMetric
|
|
91
|
-
}) {
|
|
92
|
-
const duration = metric.duration
|
|
93
|
-
const durationStr = duration ? `${duration.toFixed(1)}ms` : 'pending...'
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<div
|
|
97
|
-
class={cn(
|
|
98
|
-
'flex items-center gap-3 px-3 py-2 rounded-lg',
|
|
99
|
-
'bg-white/5 hover:bg-white/10 transition-colors',
|
|
100
|
-
)}
|
|
101
|
-
>
|
|
102
|
-
<span class="text-sm">{getTypeIcon(metric.type)}</span>
|
|
103
|
-
<div class="flex-1 min-w-0">
|
|
104
|
-
<div class={cn('text-xs font-medium truncate', getTypeColor(metric.type))}>
|
|
105
|
-
{metric.name}
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
<div
|
|
109
|
-
class={cn(
|
|
110
|
-
'text-xs font-mono font-bold',
|
|
111
|
-
getDurationColor(duration),
|
|
112
|
-
)}
|
|
113
|
-
>
|
|
114
|
-
{durationStr}
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
const StatCard = memo(function StatCard({
|
|
121
|
-
icon: Icon,
|
|
122
|
-
label,
|
|
123
|
-
value,
|
|
124
|
-
color = 'text-white',
|
|
125
|
-
}: {
|
|
126
|
-
icon: React.ElementType
|
|
127
|
-
label: string
|
|
128
|
-
value: string | number
|
|
129
|
-
color?: string
|
|
130
|
-
}) {
|
|
131
|
-
return (
|
|
132
|
-
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-white/5">
|
|
133
|
-
<Icon class={cn('w-4 h-4', color)} />
|
|
134
|
-
<div class="flex flex-col">
|
|
135
|
-
<span class="text-[10px] text-white/50 uppercase">{label}</span>
|
|
136
|
-
<span class="text-sm font-bold text-white">{value}</span>
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const FilterToggle = memo(function FilterToggle({
|
|
143
|
-
label,
|
|
144
|
-
active,
|
|
145
|
-
color,
|
|
146
|
-
onClick,
|
|
147
|
-
}: {
|
|
148
|
-
label: string
|
|
149
|
-
active: boolean
|
|
150
|
-
color: string
|
|
151
|
-
onClick: () => void
|
|
152
|
-
}) {
|
|
153
|
-
return (
|
|
154
|
-
<button
|
|
155
|
-
onClick={onClick}
|
|
156
|
-
class={cn(
|
|
157
|
-
'px-2 py-1 rounded text-xs font-medium transition-all',
|
|
158
|
-
active
|
|
159
|
-
? `${color} text-white`
|
|
160
|
-
: 'bg-white/10 text-white/50 hover:bg-white/20',
|
|
161
|
-
)}
|
|
162
|
-
>
|
|
163
|
-
{label}
|
|
164
|
-
</button>
|
|
165
|
-
)
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
export const PerformancePanel = memo(function PerformancePanel() {
|
|
169
|
-
const {
|
|
170
|
-
isPerformancePanelOpen,
|
|
171
|
-
metrics,
|
|
172
|
-
filters,
|
|
173
|
-
stats,
|
|
174
|
-
togglePerformancePanel,
|
|
175
|
-
clearMetrics,
|
|
176
|
-
toggleFilter,
|
|
177
|
-
} = createPerformanceContext()
|
|
178
|
-
|
|
179
|
-
let listRef: HTMLDivElement | undefined
|
|
180
|
-
|
|
181
|
-
const filteredMetrics = createMemo(() => {
|
|
182
|
-
return metrics.filter((m) => {
|
|
183
|
-
if (m.type === 'network' && !filters.network) return false
|
|
184
|
-
if (m.type === 'query' && !filters.query) return false
|
|
185
|
-
if (m.type === 'mutation' && !filters.mutation) return false
|
|
186
|
-
if (m.type === 'render' && !filters.render) return false
|
|
187
|
-
if (m.type === 'route' && !filters.route) return false
|
|
188
|
-
return true
|
|
189
|
-
})
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
const chartMetrics = createMemo(() => {
|
|
193
|
-
return filteredMetrics.filter((m) => m.duration !== undefined).slice(-20)
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
const maxDuration = createMemo(() => {
|
|
197
|
-
if (chartMetrics.length === 0) return 100
|
|
198
|
-
const max = Math.max(...chartMetrics.map((m) => m.duration || 0))
|
|
199
|
-
return Math.max(max, 100)
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
createEffect(() => {
|
|
203
|
-
if (listRef) {
|
|
204
|
-
listRef.scrollTop = listRef.scrollHeight
|
|
205
|
-
}
|
|
206
|
-
}, [filteredMetrics.length])
|
|
207
|
-
|
|
208
|
-
if (!isPerformancePanelOpen) return null
|
|
209
|
-
|
|
210
|
-
return (
|
|
211
|
-
<div
|
|
212
|
-
data-dev-tool="true"
|
|
213
|
-
class={cn(
|
|
214
|
-
'fixed bottom-20 left-1/2 -translate-x-1/2 z-50',
|
|
215
|
-
'w-[440px] max-h-[400px]',
|
|
216
|
-
'rounded-2xl border border-white/10',
|
|
217
|
-
'bg-gradient-to-b from-slate-900/95 via-slate-800/95 to-slate-900/95',
|
|
218
|
-
'backdrop-blur-xl shadow-2xl shadow-black/50',
|
|
219
|
-
'flex flex-col overflow-hidden',
|
|
220
|
-
'animate-in slide-in-from-bottom-4 fade-in duration-300',
|
|
221
|
-
)}
|
|
222
|
-
>
|
|
223
|
-
{/* Header */}
|
|
224
|
-
<div class="flex items-center justify-between px-4 py-3 border-b border-white/10">
|
|
225
|
-
<div class="flex items-center gap-2">
|
|
226
|
-
<Activity class="w-4 h-4 text-primary" />
|
|
227
|
-
<span class="text-sm font-bold text-white">Performance</span>
|
|
228
|
-
<span class="text-xs text-white/40">
|
|
229
|
-
({filteredMetrics.length} events)
|
|
230
|
-
</span>
|
|
231
|
-
</div>
|
|
232
|
-
<div class="flex items-center gap-1">
|
|
233
|
-
<button
|
|
234
|
-
onClick={clearMetrics}
|
|
235
|
-
class="p-1.5 text-white/40 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
|
|
236
|
-
title="Clear metrics"
|
|
237
|
-
>
|
|
238
|
-
<Trash2 class="w-3.5 h-3.5" />
|
|
239
|
-
</button>
|
|
240
|
-
<button
|
|
241
|
-
onClick={togglePerformancePanel}
|
|
242
|
-
class="p-1.5 text-white/40 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
|
|
243
|
-
title="Close panel"
|
|
244
|
-
>
|
|
245
|
-
<X class="w-4 h-4" />
|
|
246
|
-
</button>
|
|
247
|
-
</div>
|
|
248
|
-
</div>
|
|
249
|
-
|
|
250
|
-
{/* Stats Bar */}
|
|
251
|
-
<div class="flex gap-2 px-4 py-3 border-b border-white/10 overflow-x-auto">
|
|
252
|
-
<StatCard
|
|
253
|
-
icon={Activity}
|
|
254
|
-
label="Requests"
|
|
255
|
-
value={stats.totalRequests}
|
|
256
|
-
color="text-blue-400"
|
|
257
|
-
/>
|
|
258
|
-
<StatCard
|
|
259
|
-
icon={Clock}
|
|
260
|
-
label="Avg"
|
|
261
|
-
value={`${stats.avgDuration}ms`}
|
|
262
|
-
color={
|
|
263
|
-
stats.avgDuration > 100
|
|
264
|
-
? 'text-red-400'
|
|
265
|
-
: stats.avgDuration > 50
|
|
266
|
-
? 'text-yellow-400'
|
|
267
|
-
: 'text-green-400'
|
|
268
|
-
}
|
|
269
|
-
/>
|
|
270
|
-
<StatCard
|
|
271
|
-
icon={Zap}
|
|
272
|
-
label="Fast"
|
|
273
|
-
value={stats.fastRequests}
|
|
274
|
-
color="text-green-400"
|
|
275
|
-
/>
|
|
276
|
-
<StatCard
|
|
277
|
-
icon={AlertTriangle}
|
|
278
|
-
label="Slow"
|
|
279
|
-
value={stats.slowRequests}
|
|
280
|
-
color={stats.slowRequests > 0 ? 'text-red-400' : 'text-white/50'}
|
|
281
|
-
/>
|
|
282
|
-
</div>
|
|
283
|
-
|
|
284
|
-
{/* Mini Chart */}
|
|
285
|
-
{chartMetrics.length > 0 && (
|
|
286
|
-
<div class="px-4 py-3 border-b border-white/10">
|
|
287
|
-
<div class="flex items-end gap-1 h-16">
|
|
288
|
-
{chartMetrics.map((metric) => (
|
|
289
|
-
<MiniBar
|
|
290
|
-
key={metric.id}
|
|
291
|
-
height={((metric.duration || 0) / maxDuration) * 100}
|
|
292
|
-
color={getDurationBgColor(metric.duration)}
|
|
293
|
-
label={`${metric.name}: ${metric.duration?.toFixed(1)}ms`}
|
|
294
|
-
/>
|
|
295
|
-
))}
|
|
296
|
-
</div>
|
|
297
|
-
<div class="flex justify-between mt-1 text-xs text-white/40">
|
|
298
|
-
<span>Recent requests</span>
|
|
299
|
-
<span>0-{maxDuration.toFixed(0)}ms</span>
|
|
300
|
-
</div>
|
|
301
|
-
</div>
|
|
302
|
-
)}
|
|
303
|
-
|
|
304
|
-
{/* Filters */}
|
|
305
|
-
<div class="flex gap-1 px-4 py-2 border-b border-white/10">
|
|
306
|
-
<FilterToggle label="Network" active={filters.network} color="bg-blue-500" onClick={() => toggleFilter('network')} />
|
|
307
|
-
<FilterToggle label="Query" active={filters.query} color="bg-orange-500" onClick={() => toggleFilter('query')} />
|
|
308
|
-
<FilterToggle label="Mutation" active={filters.mutation} color="bg-red-500" onClick={() => toggleFilter('mutation')} />
|
|
309
|
-
<FilterToggle label="Render" active={filters.render} color="bg-purple-500" onClick={() => toggleFilter('render')} />
|
|
310
|
-
<FilterToggle label="Route" active={filters.route} color="bg-green-500" onClick={() => toggleFilter('route')} />
|
|
311
|
-
</div>
|
|
312
|
-
|
|
313
|
-
{/* Metrics List */}
|
|
314
|
-
<div
|
|
315
|
-
ref={listRef}
|
|
316
|
-
class="flex-1 overflow-y-auto px-3 py-2 space-y-1 min-h-[100px] max-h-[180px]"
|
|
317
|
-
>
|
|
318
|
-
{filteredMetrics.length === 0 ? (
|
|
319
|
-
<div class="flex items-center justify-center py-8 text-sm text-white/30">
|
|
320
|
-
No metrics recorded yet
|
|
321
|
-
</div>
|
|
322
|
-
) : (
|
|
323
|
-
filteredMetrics.map((metric) => (
|
|
324
|
-
<MetricRow key={metric.id} metric={metric} />
|
|
325
|
-
))
|
|
326
|
-
)}
|
|
327
|
-
</div>
|
|
328
|
-
</div>
|
|
329
|
-
)
|
|
330
|
-
})
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-solidjs — src/context/DevModeContext.tsx
|
|
2
|
-
|
|
3
|
-
import { createContext, useContext, createSignal, createEffect, type JSX } from 'solid-js'
|
|
4
|
-
|
|
5
|
-
const DEV_MODE_STORAGE_KEY = 'geenius-dev-mode-state'
|
|
6
|
-
|
|
7
|
-
export interface ComponentDetails {
|
|
8
|
-
name: string
|
|
9
|
-
file?: string
|
|
10
|
-
selector: string
|
|
11
|
-
key?: string
|
|
12
|
-
props?: Record<string, unknown>
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface DevModeState {
|
|
16
|
-
isDevMode: boolean
|
|
17
|
-
isSidebarOpen: boolean
|
|
18
|
-
isInspectorMode: boolean
|
|
19
|
-
issueDialog: {
|
|
20
|
-
isOpen: boolean
|
|
21
|
-
type: 'bug' | 'feature'
|
|
22
|
-
initialDescription?: string
|
|
23
|
-
componentDetails?: ComponentDetails[]
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface DevModeContextValue extends DevModeState {
|
|
28
|
-
toggleDevMode: () => void
|
|
29
|
-
toggleSidebar: () => void
|
|
30
|
-
toggleInspector: () => void
|
|
31
|
-
setDevMode: (enabled: boolean) => void
|
|
32
|
-
setSidebarOpen: (open: boolean) => void
|
|
33
|
-
setInspectorMode: (enabled: boolean) => void
|
|
34
|
-
openIssueDialog: (
|
|
35
|
-
type: 'bug' | 'feature',
|
|
36
|
-
description?: string,
|
|
37
|
-
componentDetails?: ComponentDetails[],
|
|
38
|
-
) => void
|
|
39
|
-
closeIssueDialog: () => void
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const defaultState: DevModeState = {
|
|
43
|
-
isDevMode: false,
|
|
44
|
-
isSidebarOpen: false,
|
|
45
|
-
isInspectorMode: false,
|
|
46
|
-
issueDialog: {
|
|
47
|
-
isOpen: false,
|
|
48
|
-
type: 'bug',
|
|
49
|
-
initialDescription: '',
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const DevModeContext = createContext<DevModeContextValue | undefined>(undefined)
|
|
54
|
-
|
|
55
|
-
export function createDevMode() {
|
|
56
|
-
const context = useContext(DevModeContext)
|
|
57
|
-
if (!context) {
|
|
58
|
-
throw new Error('createDevMode must be used within a DevModeProvider')
|
|
59
|
-
}
|
|
60
|
-
return context
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function createDevModeOptional(): DevModeContextValue | null {
|
|
64
|
-
return useContext(DevModeContext) ?? null
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface DevModeProviderProps {
|
|
68
|
-
children: JSX.Element
|
|
69
|
-
/** Whether dev tools are allowed. Default: checks import.meta.env.DEV */
|
|
70
|
-
isAllowed?: boolean
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export const DevModeProvider = memo(function DevModeProvider({
|
|
74
|
-
children,
|
|
75
|
-
isAllowed,
|
|
76
|
-
}: DevModeProviderProps) {
|
|
77
|
-
const resolvedAllowed = isAllowed ?? resolveDevAllowed()
|
|
78
|
-
|
|
79
|
-
const [state, setState] = createSignal<DevModeState>(() => {
|
|
80
|
-
if (!resolvedAllowed || typeof window === 'undefined') return defaultState
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
const stored = localStorage.getItem(DEV_MODE_STORAGE_KEY)
|
|
84
|
-
if (stored) {
|
|
85
|
-
const parsed = JSON.parse(stored) as Partial<DevModeState>
|
|
86
|
-
return {
|
|
87
|
-
isDevMode: parsed.isDevMode ?? false,
|
|
88
|
-
isSidebarOpen: false,
|
|
89
|
-
isInspectorMode: false,
|
|
90
|
-
issueDialog: defaultState.issueDialog,
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
} catch {
|
|
94
|
-
// Ignore parse errors
|
|
95
|
-
}
|
|
96
|
-
return defaultState
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
createEffect(() => {
|
|
100
|
-
if (!resolvedAllowed || typeof window === 'undefined') return
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
localStorage.setItem(
|
|
104
|
-
DEV_MODE_STORAGE_KEY,
|
|
105
|
-
JSON.stringify({ isDevMode: state.isDevMode }),
|
|
106
|
-
)
|
|
107
|
-
} catch {
|
|
108
|
-
// Ignore storage errors
|
|
109
|
-
}
|
|
110
|
-
}, [state.isDevMode, resolvedAllowed])
|
|
111
|
-
|
|
112
|
-
const toggleDevMode = () => {
|
|
113
|
-
setState((prev) => ({
|
|
114
|
-
...prev,
|
|
115
|
-
isDevMode: !prev.isDevMode,
|
|
116
|
-
isSidebarOpen: prev.isDevMode ? false : prev.isSidebarOpen,
|
|
117
|
-
isInspectorMode: prev.isDevMode ? false : prev.isInspectorMode,
|
|
118
|
-
}))
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const toggleSidebar = () => {
|
|
122
|
-
setState((prev) => ({ ...prev, isSidebarOpen: !prev.isSidebarOpen }))
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const toggleInspector = () => {
|
|
126
|
-
setState((prev) => ({
|
|
127
|
-
...prev,
|
|
128
|
-
isInspectorMode: !prev.isInspectorMode,
|
|
129
|
-
}))
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const setDevMode = (enabled: boolean) => {
|
|
133
|
-
setState((prev) => ({
|
|
134
|
-
...prev,
|
|
135
|
-
isDevMode: enabled,
|
|
136
|
-
isSidebarOpen: enabled ? prev.isSidebarOpen : false,
|
|
137
|
-
isInspectorMode: enabled ? prev.isInspectorMode : false,
|
|
138
|
-
}))
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const setSidebarOpen = (open: boolean) => {
|
|
142
|
-
setState((prev) => ({ ...prev, isSidebarOpen: open }))
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const setInspectorMode = (enabled: boolean) => {
|
|
146
|
-
setState((prev) => ({ ...prev, isInspectorMode: enabled }))
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const openIssueDialog = (
|
|
150
|
-
type: 'bug' | 'feature',
|
|
151
|
-
description?: string,
|
|
152
|
-
componentDetails?: ComponentDetails[],
|
|
153
|
-
) => {
|
|
154
|
-
setState((prev) => ({
|
|
155
|
-
...prev,
|
|
156
|
-
issueDialog: {
|
|
157
|
-
isOpen: true,
|
|
158
|
-
type,
|
|
159
|
-
initialDescription: description,
|
|
160
|
-
componentDetails,
|
|
161
|
-
},
|
|
162
|
-
}))
|
|
163
|
-
},
|
|
164
|
-
[]
|
|
165
|
-
|
|
166
|
-
const closeIssueDialog = () => {
|
|
167
|
-
setState((prev) => ({
|
|
168
|
-
...prev,
|
|
169
|
-
issueDialog: { ...prev.issueDialog, isOpen: false },
|
|
170
|
-
}))
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (!resolvedAllowed) {
|
|
174
|
-
return <>{children}</>
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return (
|
|
178
|
-
<DevModeContext.Provider
|
|
179
|
-
value={{
|
|
180
|
-
...state,
|
|
181
|
-
toggleDevMode,
|
|
182
|
-
toggleSidebar,
|
|
183
|
-
toggleInspector,
|
|
184
|
-
setDevMode,
|
|
185
|
-
setSidebarOpen,
|
|
186
|
-
setInspectorMode,
|
|
187
|
-
openIssueDialog,
|
|
188
|
-
closeIssueDialog,
|
|
189
|
-
}}
|
|
190
|
-
>
|
|
191
|
-
{children}
|
|
192
|
-
</DevModeContext.Provider>
|
|
193
|
-
)
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
export function createIsDevToolsVisible(): boolean {
|
|
197
|
-
const context = createDevModeOptional()
|
|
198
|
-
if (!context) return false
|
|
199
|
-
return context.isDevMode
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export function createIsDevAllowed(isAllowed?: boolean): boolean {
|
|
203
|
-
return isAllowed ?? resolveDevAllowed()
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function resolveDevAllowed(): boolean {
|
|
207
|
-
try {
|
|
208
|
-
// @ts-expect-error — Vite env
|
|
209
|
-
if (import.meta?.env?.VITE_CONVEX_IS_DEV === 'true') return true
|
|
210
|
-
// @ts-expect-error — Vite env
|
|
211
|
-
if (import.meta?.env?.DEV) return true
|
|
212
|
-
} catch {
|
|
213
|
-
// Not in Vite
|
|
214
|
-
}
|
|
215
|
-
return false
|
|
216
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools-solidjs — src/context/PerformanceContext.tsx
|
|
2
|
-
|
|
3
|
-
import { createContext, useContext, createSignal, createEffect, type JSX } from 'solid-js'
|
|
4
|
-
import { metricsStore, type PerformanceMetric } from '@geenius-tools/logger'
|
|
5
|
-
|
|
6
|
-
const MAX_METRICS = 100
|
|
7
|
-
|
|
8
|
-
interface PerformanceContextValue {
|
|
9
|
-
isPerformancePanelOpen: boolean
|
|
10
|
-
metrics: PerformanceMetric[]
|
|
11
|
-
filters: {
|
|
12
|
-
network: boolean
|
|
13
|
-
query: boolean
|
|
14
|
-
mutation: boolean
|
|
15
|
-
render: boolean
|
|
16
|
-
route: boolean
|
|
17
|
-
}
|
|
18
|
-
stats: {
|
|
19
|
-
totalRequests: number
|
|
20
|
-
avgDuration: number
|
|
21
|
-
slowRequests: number
|
|
22
|
-
fastRequests: number
|
|
23
|
-
}
|
|
24
|
-
togglePerformancePanel: () => void
|
|
25
|
-
clearMetrics: () => void
|
|
26
|
-
toggleFilter: (filter: keyof PerformanceContextValue['filters']) => void
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const PerformanceContext = createContext<PerformanceContextValue | undefined>(
|
|
30
|
-
undefined,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
export function createPerformanceContext() {
|
|
34
|
-
const context = useContext(PerformanceContext)
|
|
35
|
-
if (!context) {
|
|
36
|
-
throw new Error(
|
|
37
|
-
'createPerformanceContext must be used within PerformanceProvider',
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
return context
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function createPerformanceContextOptional(): PerformanceContextValue | null {
|
|
44
|
-
return useContext(PerformanceContext) ?? null
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface PerformanceProviderProps {
|
|
48
|
-
children: JSX.Element
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export const PerformanceProvider = memo(function PerformanceProvider({
|
|
52
|
-
children,
|
|
53
|
-
}: PerformanceProviderProps) {
|
|
54
|
-
const [isPerformancePanelOpen, setIsPerformancePanelOpen] = createSignal(false)
|
|
55
|
-
const [metrics, setMetrics] = createSignal<PerformanceMetric[]>([])
|
|
56
|
-
const [filters, setFilters] = createSignal({
|
|
57
|
-
network: true,
|
|
58
|
-
query: true,
|
|
59
|
-
mutation: true,
|
|
60
|
-
render: true,
|
|
61
|
-
route: true,
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
createEffect(() => {
|
|
65
|
-
const unsubscribe = metricsStore.subscribe((newMetrics) => {
|
|
66
|
-
setMetrics((prev) => {
|
|
67
|
-
const combined = [...prev, ...newMetrics]
|
|
68
|
-
if (combined.length > MAX_METRICS) {
|
|
69
|
-
return combined.slice(-MAX_METRICS)
|
|
70
|
-
}
|
|
71
|
-
return combined
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
return () => unsubscribe()
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
const stats = () => {
|
|
79
|
-
const filtered = metrics.filter((m) => m.duration !== undefined)
|
|
80
|
-
const total = filtered.length
|
|
81
|
-
|
|
82
|
-
if (total === 0) {
|
|
83
|
-
return {
|
|
84
|
-
totalRequests: 0,
|
|
85
|
-
avgDuration: 0,
|
|
86
|
-
slowRequests: 0,
|
|
87
|
-
fastRequests: 0,
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const durations = filtered.map((m) => m.duration!)
|
|
92
|
-
const avg = durations.reduce((a, b) => a + b, 0) / total
|
|
93
|
-
const slow = durations.filter((d) => d > 100).length
|
|
94
|
-
const fast = durations.filter((d) => d < 50).length
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
totalRequests: total,
|
|
98
|
-
avgDuration: Math.round(avg * 100) / 100,
|
|
99
|
-
slowRequests: slow,
|
|
100
|
-
fastRequests: fast,
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const togglePerformancePanel = () => {
|
|
105
|
-
setIsPerformancePanelOpen((prev) => !prev)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const clearMetrics = () => {
|
|
109
|
-
setMetrics([])
|
|
110
|
-
metricsStore.clear()
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const toggleFilter = (filter: keyof typeof filters) => {
|
|
114
|
-
setFilters((prev) => ({
|
|
115
|
-
...prev,
|
|
116
|
-
[filter]: !prev[filter],
|
|
117
|
-
}))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<PerformanceContext.Provider
|
|
122
|
-
value={{
|
|
123
|
-
isPerformancePanelOpen,
|
|
124
|
-
metrics,
|
|
125
|
-
filters,
|
|
126
|
-
stats: stats(),
|
|
127
|
-
togglePerformancePanel,
|
|
128
|
-
clearMetrics,
|
|
129
|
-
toggleFilter,
|
|
130
|
-
}}
|
|
131
|
-
>
|
|
132
|
-
{children}
|
|
133
|
-
</PerformanceContext.Provider>
|
|
134
|
-
)
|
|
135
|
-
})
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// @geenius-tools/devtools — data/designs.ts
|
|
2
|
-
|
|
3
|
-
export interface Design {
|
|
4
|
-
id: string
|
|
5
|
-
name: string
|
|
6
|
-
path: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const designs: Design[] = Array.from({ length: 21 }, (_, i) => ({
|
|
10
|
-
id: String(i + 1),
|
|
11
|
-
name: `Design ${i + 1}`,
|
|
12
|
-
path: `/dev/design/${i + 1}`,
|
|
13
|
-
}))
|