@qwickapps/server 1.3.0 → 1.4.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.
Files changed (241) hide show
  1. package/README.md +311 -0
  2. package/dist/core/control-panel.d.ts.map +1 -1
  3. package/dist/core/control-panel.js +144 -2
  4. package/dist/core/control-panel.js.map +1 -1
  5. package/dist/core/plugin-registry.d.ts +36 -0
  6. package/dist/core/plugin-registry.d.ts.map +1 -1
  7. package/dist/core/plugin-registry.js +26 -0
  8. package/dist/core/plugin-registry.js.map +1 -1
  9. package/dist/core/types.d.ts +19 -0
  10. package/dist/core/types.d.ts.map +1 -1
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +4 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/plugins/auth/adapter-wrapper.d.ts +47 -0
  16. package/dist/plugins/auth/adapter-wrapper.d.ts.map +1 -0
  17. package/dist/plugins/auth/adapter-wrapper.js +166 -0
  18. package/dist/plugins/auth/adapter-wrapper.js.map +1 -0
  19. package/dist/plugins/auth/adapter-wrapper.test.d.ts +7 -0
  20. package/dist/plugins/auth/adapter-wrapper.test.d.ts.map +1 -0
  21. package/dist/plugins/auth/adapter-wrapper.test.js +303 -0
  22. package/dist/plugins/auth/adapter-wrapper.test.js.map +1 -0
  23. package/dist/plugins/auth/adapters/index.d.ts +1 -0
  24. package/dist/plugins/auth/adapters/index.d.ts.map +1 -1
  25. package/dist/plugins/auth/adapters/index.js +1 -0
  26. package/dist/plugins/auth/adapters/index.js.map +1 -1
  27. package/dist/plugins/auth/adapters/supabase-adapter.d.ts.map +1 -1
  28. package/dist/plugins/auth/adapters/supabase-adapter.js.map +1 -1
  29. package/dist/plugins/auth/adapters/supertokens-adapter.d.ts +18 -0
  30. package/dist/plugins/auth/adapters/supertokens-adapter.d.ts.map +1 -0
  31. package/dist/plugins/auth/adapters/supertokens-adapter.js +267 -0
  32. package/dist/plugins/auth/adapters/supertokens-adapter.js.map +1 -0
  33. package/dist/plugins/auth/config-store.d.ts +11 -0
  34. package/dist/plugins/auth/config-store.d.ts.map +1 -0
  35. package/dist/plugins/auth/config-store.js +232 -0
  36. package/dist/plugins/auth/config-store.js.map +1 -0
  37. package/dist/plugins/auth/config-store.test.d.ts +7 -0
  38. package/dist/plugins/auth/config-store.test.d.ts.map +1 -0
  39. package/dist/plugins/auth/config-store.test.js +299 -0
  40. package/dist/plugins/auth/config-store.test.js.map +1 -0
  41. package/dist/plugins/auth/env-config.d.ts +138 -0
  42. package/dist/plugins/auth/env-config.d.ts.map +1 -0
  43. package/dist/plugins/auth/env-config.js +1122 -0
  44. package/dist/plugins/auth/env-config.js.map +1 -0
  45. package/dist/plugins/auth/index.d.ts +7 -1
  46. package/dist/plugins/auth/index.d.ts.map +1 -1
  47. package/dist/plugins/auth/index.js +7 -0
  48. package/dist/plugins/auth/index.js.map +1 -1
  49. package/dist/plugins/auth/supertokens-adapter.test.d.ts +10 -0
  50. package/dist/plugins/auth/supertokens-adapter.test.d.ts.map +1 -0
  51. package/dist/plugins/auth/supertokens-adapter.test.js +486 -0
  52. package/dist/plugins/auth/supertokens-adapter.test.js.map +1 -0
  53. package/dist/plugins/auth/types.d.ts +176 -0
  54. package/dist/plugins/auth/types.d.ts.map +1 -1
  55. package/dist/plugins/auth/types.js.map +1 -1
  56. package/dist/plugins/cache-plugin.test.js +3 -0
  57. package/dist/plugins/cache-plugin.test.js.map +1 -1
  58. package/dist/plugins/index.d.ts +6 -2
  59. package/dist/plugins/index.d.ts.map +1 -1
  60. package/dist/plugins/index.js +5 -1
  61. package/dist/plugins/index.js.map +1 -1
  62. package/dist/plugins/postgres-plugin.test.js +3 -0
  63. package/dist/plugins/postgres-plugin.test.js.map +1 -1
  64. package/dist/plugins/preferences/__tests__/deep-merge.test.d.ts +7 -0
  65. package/dist/plugins/preferences/__tests__/deep-merge.test.d.ts.map +1 -0
  66. package/dist/plugins/preferences/__tests__/deep-merge.test.js +215 -0
  67. package/dist/plugins/preferences/__tests__/deep-merge.test.js.map +1 -0
  68. package/dist/plugins/preferences/__tests__/preferences-plugin.test.d.ts +7 -0
  69. package/dist/plugins/preferences/__tests__/preferences-plugin.test.d.ts.map +1 -0
  70. package/dist/plugins/preferences/__tests__/preferences-plugin.test.js +265 -0
  71. package/dist/plugins/preferences/__tests__/preferences-plugin.test.js.map +1 -0
  72. package/dist/plugins/preferences/index.d.ts +12 -0
  73. package/dist/plugins/preferences/index.d.ts.map +1 -0
  74. package/dist/plugins/preferences/index.js +13 -0
  75. package/dist/plugins/preferences/index.js.map +1 -0
  76. package/dist/plugins/preferences/preferences-plugin.d.ts +39 -0
  77. package/dist/plugins/preferences/preferences-plugin.d.ts.map +1 -0
  78. package/dist/plugins/preferences/preferences-plugin.js +226 -0
  79. package/dist/plugins/preferences/preferences-plugin.js.map +1 -0
  80. package/dist/plugins/preferences/stores/index.d.ts +9 -0
  81. package/dist/plugins/preferences/stores/index.d.ts.map +1 -0
  82. package/dist/plugins/preferences/stores/index.js +9 -0
  83. package/dist/plugins/preferences/stores/index.js.map +1 -0
  84. package/dist/plugins/preferences/stores/postgres-store.d.ts +41 -0
  85. package/dist/plugins/preferences/stores/postgres-store.d.ts.map +1 -0
  86. package/dist/plugins/preferences/stores/postgres-store.js +181 -0
  87. package/dist/plugins/preferences/stores/postgres-store.js.map +1 -0
  88. package/dist/plugins/preferences/types.d.ts +91 -0
  89. package/dist/plugins/preferences/types.d.ts.map +1 -0
  90. package/dist/plugins/preferences/types.js +10 -0
  91. package/dist/plugins/preferences/types.js.map +1 -0
  92. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.d.ts +7 -0
  93. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.d.ts.map +1 -0
  94. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.js +220 -0
  95. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.js.map +1 -0
  96. package/dist/plugins/rate-limit/cleanup.d.ts +40 -0
  97. package/dist/plugins/rate-limit/cleanup.d.ts.map +1 -0
  98. package/dist/plugins/rate-limit/cleanup.js +72 -0
  99. package/dist/plugins/rate-limit/cleanup.js.map +1 -0
  100. package/dist/plugins/rate-limit/env-config.d.ts +91 -0
  101. package/dist/plugins/rate-limit/env-config.d.ts.map +1 -0
  102. package/dist/plugins/rate-limit/env-config.js +318 -0
  103. package/dist/plugins/rate-limit/env-config.js.map +1 -0
  104. package/dist/plugins/rate-limit/index.d.ts +76 -0
  105. package/dist/plugins/rate-limit/index.d.ts.map +1 -0
  106. package/dist/plugins/rate-limit/index.js +79 -0
  107. package/dist/plugins/rate-limit/index.js.map +1 -0
  108. package/dist/plugins/rate-limit/middleware.d.ts +40 -0
  109. package/dist/plugins/rate-limit/middleware.d.ts.map +1 -0
  110. package/dist/plugins/rate-limit/middleware.js +169 -0
  111. package/dist/plugins/rate-limit/middleware.js.map +1 -0
  112. package/dist/plugins/rate-limit/rate-limit-plugin.d.ts +44 -0
  113. package/dist/plugins/rate-limit/rate-limit-plugin.d.ts.map +1 -0
  114. package/dist/plugins/rate-limit/rate-limit-plugin.js +354 -0
  115. package/dist/plugins/rate-limit/rate-limit-plugin.js.map +1 -0
  116. package/dist/plugins/rate-limit/rate-limit-service.d.ts +110 -0
  117. package/dist/plugins/rate-limit/rate-limit-service.d.ts.map +1 -0
  118. package/dist/plugins/rate-limit/rate-limit-service.js +172 -0
  119. package/dist/plugins/rate-limit/rate-limit-service.js.map +1 -0
  120. package/dist/plugins/rate-limit/stores/cache-store.d.ts +33 -0
  121. package/dist/plugins/rate-limit/stores/cache-store.d.ts.map +1 -0
  122. package/dist/plugins/rate-limit/stores/cache-store.js +225 -0
  123. package/dist/plugins/rate-limit/stores/cache-store.js.map +1 -0
  124. package/dist/plugins/rate-limit/stores/index.d.ts +8 -0
  125. package/dist/plugins/rate-limit/stores/index.d.ts.map +1 -0
  126. package/dist/plugins/rate-limit/stores/index.js +8 -0
  127. package/dist/plugins/rate-limit/stores/index.js.map +1 -0
  128. package/dist/plugins/rate-limit/stores/postgres-store.d.ts +34 -0
  129. package/dist/plugins/rate-limit/stores/postgres-store.d.ts.map +1 -0
  130. package/dist/plugins/rate-limit/stores/postgres-store.js +320 -0
  131. package/dist/plugins/rate-limit/stores/postgres-store.js.map +1 -0
  132. package/dist/plugins/rate-limit/strategies/fixed-window.d.ts +21 -0
  133. package/dist/plugins/rate-limit/strategies/fixed-window.d.ts.map +1 -0
  134. package/dist/plugins/rate-limit/strategies/fixed-window.js +97 -0
  135. package/dist/plugins/rate-limit/strategies/fixed-window.js.map +1 -0
  136. package/dist/plugins/rate-limit/strategies/index.d.ts +14 -0
  137. package/dist/plugins/rate-limit/strategies/index.d.ts.map +1 -0
  138. package/dist/plugins/rate-limit/strategies/index.js +27 -0
  139. package/dist/plugins/rate-limit/strategies/index.js.map +1 -0
  140. package/dist/plugins/rate-limit/strategies/sliding-window.d.ts +22 -0
  141. package/dist/plugins/rate-limit/strategies/sliding-window.d.ts.map +1 -0
  142. package/dist/plugins/rate-limit/strategies/sliding-window.js +122 -0
  143. package/dist/plugins/rate-limit/strategies/sliding-window.js.map +1 -0
  144. package/dist/plugins/rate-limit/strategies/token-bucket.d.ts +28 -0
  145. package/dist/plugins/rate-limit/strategies/token-bucket.d.ts.map +1 -0
  146. package/dist/plugins/rate-limit/strategies/token-bucket.js +121 -0
  147. package/dist/plugins/rate-limit/strategies/token-bucket.js.map +1 -0
  148. package/dist/plugins/rate-limit/types.d.ts +265 -0
  149. package/dist/plugins/rate-limit/types.d.ts.map +1 -0
  150. package/dist/plugins/rate-limit/types.js +9 -0
  151. package/dist/plugins/rate-limit/types.js.map +1 -0
  152. package/dist/plugins/users/__tests__/users-plugin.test.d.ts +9 -0
  153. package/dist/plugins/users/__tests__/users-plugin.test.d.ts.map +1 -0
  154. package/dist/plugins/users/__tests__/users-plugin.test.js +546 -0
  155. package/dist/plugins/users/__tests__/users-plugin.test.js.map +1 -0
  156. package/dist/plugins/users/index.d.ts +2 -2
  157. package/dist/plugins/users/index.d.ts.map +1 -1
  158. package/dist/plugins/users/index.js +1 -1
  159. package/dist/plugins/users/index.js.map +1 -1
  160. package/dist/plugins/users/types.d.ts +36 -0
  161. package/dist/plugins/users/types.d.ts.map +1 -1
  162. package/dist/plugins/users/users-plugin.d.ts +8 -2
  163. package/dist/plugins/users/users-plugin.d.ts.map +1 -1
  164. package/dist/plugins/users/users-plugin.js +122 -5
  165. package/dist/plugins/users/users-plugin.js.map +1 -1
  166. package/dist-ui/assets/index-D7DoZ9rL.js +478 -0
  167. package/dist-ui/assets/index-D7DoZ9rL.js.map +1 -0
  168. package/dist-ui/index.html +1 -1
  169. package/dist-ui-lib/api/controlPanelApi.d.ts +194 -7
  170. package/dist-ui-lib/dashboard/WidgetComponentRegistry.d.ts +9 -5
  171. package/dist-ui-lib/dashboard/builtInWidgets.d.ts +7 -1
  172. package/dist-ui-lib/dashboard/widgets/AuthStatusWidget.d.ts +9 -0
  173. package/dist-ui-lib/dashboard/widgets/IntegrationStatusWidget.d.ts +9 -0
  174. package/dist-ui-lib/dashboard/widgets/index.d.ts +2 -0
  175. package/dist-ui-lib/index.js +3665 -3945
  176. package/dist-ui-lib/index.js.map +1 -1
  177. package/dist-ui-lib/pages/AuthPage.d.ts +1 -0
  178. package/dist-ui-lib/pages/IntegrationsPage.d.ts +1 -0
  179. package/dist-ui-lib/pages/PluginsPage.d.ts +1 -0
  180. package/dist-ui-lib/pages/RateLimitPage.d.ts +1 -0
  181. package/package.json +7 -2
  182. package/src/core/control-panel.ts +161 -2
  183. package/src/core/plugin-registry.ts +63 -0
  184. package/src/core/types.ts +17 -0
  185. package/src/index.ts +45 -0
  186. package/src/plugins/auth/adapter-wrapper.test.ts +395 -0
  187. package/src/plugins/auth/adapter-wrapper.ts +205 -0
  188. package/src/plugins/auth/adapters/index.ts +1 -0
  189. package/src/plugins/auth/adapters/supabase-adapter.ts +22 -14
  190. package/src/plugins/auth/adapters/supertokens-adapter.ts +326 -0
  191. package/src/plugins/auth/config-store.test.ts +417 -0
  192. package/src/plugins/auth/config-store.ts +305 -0
  193. package/src/plugins/auth/env-config.ts +1279 -0
  194. package/src/plugins/auth/index.ts +30 -0
  195. package/src/plugins/auth/supertokens-adapter.test.ts +621 -0
  196. package/src/plugins/auth/types.ts +218 -0
  197. package/src/plugins/cache-plugin.test.ts +3 -0
  198. package/src/plugins/index.ts +75 -0
  199. package/src/plugins/postgres-plugin.test.ts +3 -0
  200. package/src/plugins/preferences/__tests__/deep-merge.test.ts +242 -0
  201. package/src/plugins/preferences/__tests__/preferences-plugin.test.ts +350 -0
  202. package/src/plugins/preferences/index.ts +30 -0
  203. package/src/plugins/preferences/preferences-plugin.ts +270 -0
  204. package/src/plugins/preferences/stores/index.ts +9 -0
  205. package/src/plugins/preferences/stores/postgres-store.ts +252 -0
  206. package/src/plugins/preferences/types.ts +100 -0
  207. package/src/plugins/rate-limit/__tests__/rate-limit-plugin.test.ts +259 -0
  208. package/src/plugins/rate-limit/cleanup.ts +117 -0
  209. package/src/plugins/rate-limit/env-config.ts +400 -0
  210. package/src/plugins/rate-limit/index.ts +128 -0
  211. package/src/plugins/rate-limit/middleware.ts +212 -0
  212. package/src/plugins/rate-limit/rate-limit-plugin.ts +400 -0
  213. package/src/plugins/rate-limit/rate-limit-service.ts +228 -0
  214. package/src/plugins/rate-limit/stores/cache-store.ts +261 -0
  215. package/src/plugins/rate-limit/stores/index.ts +8 -0
  216. package/src/plugins/rate-limit/stores/postgres-store.ts +402 -0
  217. package/src/plugins/rate-limit/strategies/fixed-window.ts +116 -0
  218. package/src/plugins/rate-limit/strategies/index.ts +30 -0
  219. package/src/plugins/rate-limit/strategies/sliding-window.ts +157 -0
  220. package/src/plugins/rate-limit/strategies/token-bucket.ts +154 -0
  221. package/src/plugins/rate-limit/types.ts +338 -0
  222. package/src/plugins/users/__tests__/users-plugin.test.ts +690 -0
  223. package/src/plugins/users/index.ts +3 -0
  224. package/src/plugins/users/types.ts +38 -0
  225. package/src/plugins/users/users-plugin.ts +142 -5
  226. package/ui/src/App.tsx +35 -14
  227. package/ui/src/api/controlPanelApi.ts +326 -1
  228. package/ui/src/components/ControlPanelApp.tsx +3 -0
  229. package/ui/src/dashboard/PluginWidgetRenderer.tsx +13 -10
  230. package/ui/src/dashboard/WidgetComponentRegistry.tsx +13 -9
  231. package/ui/src/dashboard/builtInWidgets.tsx +13 -3
  232. package/ui/src/dashboard/widgets/AuthStatusWidget.tsx +143 -0
  233. package/ui/src/dashboard/widgets/IntegrationStatusWidget.tsx +135 -0
  234. package/ui/src/dashboard/widgets/index.ts +2 -0
  235. package/ui/src/pages/AuthPage.tsx +1103 -0
  236. package/ui/src/pages/IntegrationsPage.tsx +288 -0
  237. package/ui/src/pages/PluginsPage.tsx +394 -0
  238. package/ui/src/pages/RateLimitPage.tsx +292 -0
  239. package/ui/vite.lib.config.ts +5 -0
  240. package/dist-ui/assets/index-Bsp2ntcw.js +0 -465
  241. package/dist-ui/assets/index-Bsp2ntcw.js.map +0 -1
@@ -0,0 +1,292 @@
1
+ import { useState, useEffect } from 'react';
2
+ import {
3
+ Box,
4
+ Card,
5
+ CardContent,
6
+ Typography,
7
+ TextField,
8
+ Select,
9
+ MenuItem,
10
+ FormControl,
11
+ InputLabel,
12
+ Switch,
13
+ FormControlLabel,
14
+ Button,
15
+ CircularProgress,
16
+ Alert,
17
+ IconButton,
18
+ Tooltip,
19
+ Chip,
20
+ } from '@mui/material';
21
+ import RefreshIcon from '@mui/icons-material/Refresh';
22
+ import SaveIcon from '@mui/icons-material/Save';
23
+ import SpeedIcon from '@mui/icons-material/Speed';
24
+ import StorageIcon from '@mui/icons-material/Storage';
25
+ import CachedIcon from '@mui/icons-material/Cached';
26
+ import { api, RateLimitConfig, RateLimitStrategy } from '../api/controlPanelApi';
27
+
28
+ /**
29
+ * Format milliseconds to human-readable duration
30
+ */
31
+ function formatDuration(ms: number): string {
32
+ if (ms < 1000) return `${ms}ms`;
33
+ if (ms < 60000) return `${ms / 1000}s`;
34
+ if (ms < 3600000) return `${ms / 60000}m`;
35
+ return `${ms / 3600000}h`;
36
+ }
37
+
38
+ export function RateLimitPage() {
39
+ const [config, setConfig] = useState<RateLimitConfig | null>(null);
40
+ const [loading, setLoading] = useState(true);
41
+ const [saving, setSaving] = useState(false);
42
+ const [error, setError] = useState<string | null>(null);
43
+ const [success, setSuccess] = useState<string | null>(null);
44
+
45
+ // Editable fields
46
+ const [windowMs, setWindowMs] = useState<number>(60000);
47
+ const [maxRequests, setMaxRequests] = useState<number>(100);
48
+ const [strategy, setStrategy] = useState<RateLimitStrategy>('sliding-window');
49
+ const [cleanupEnabled, setCleanupEnabled] = useState<boolean>(true);
50
+ const [cleanupIntervalMs, setCleanupIntervalMs] = useState<number>(300000);
51
+
52
+ const fetchConfig = async () => {
53
+ setLoading(true);
54
+ setError(null);
55
+ try {
56
+ const data = await api.getRateLimitConfig();
57
+ setConfig(data);
58
+ // Update editable fields
59
+ setWindowMs(data.windowMs);
60
+ setMaxRequests(data.maxRequests);
61
+ setStrategy(data.strategy);
62
+ setCleanupEnabled(data.cleanupEnabled);
63
+ setCleanupIntervalMs(data.cleanupIntervalMs);
64
+ } catch (err) {
65
+ setError(err instanceof Error ? err.message : 'Failed to fetch config');
66
+ } finally {
67
+ setLoading(false);
68
+ }
69
+ };
70
+
71
+ useEffect(() => {
72
+ fetchConfig();
73
+ }, []);
74
+
75
+ const handleSave = async () => {
76
+ setSaving(true);
77
+ setError(null);
78
+ setSuccess(null);
79
+ try {
80
+ const result = await api.updateRateLimitConfig({
81
+ windowMs,
82
+ maxRequests,
83
+ strategy,
84
+ cleanupEnabled,
85
+ cleanupIntervalMs,
86
+ });
87
+ setConfig(result.config);
88
+ setSuccess('Configuration saved successfully');
89
+ setTimeout(() => setSuccess(null), 3000);
90
+ } catch (err) {
91
+ setError(err instanceof Error ? err.message : 'Failed to save config');
92
+ } finally {
93
+ setSaving(false);
94
+ }
95
+ };
96
+
97
+ const hasChanges = config && (
98
+ windowMs !== config.windowMs ||
99
+ maxRequests !== config.maxRequests ||
100
+ strategy !== config.strategy ||
101
+ cleanupEnabled !== config.cleanupEnabled ||
102
+ cleanupIntervalMs !== config.cleanupIntervalMs
103
+ );
104
+
105
+ if (loading) {
106
+ return (
107
+ <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '50vh' }}>
108
+ <CircularProgress />
109
+ </Box>
110
+ );
111
+ }
112
+
113
+ if (error && !config) {
114
+ return (
115
+ <Card sx={{ bgcolor: 'var(--theme-surface)', border: '1px solid var(--theme-error)' }}>
116
+ <CardContent>
117
+ <Typography color="error">{error}</Typography>
118
+ </CardContent>
119
+ </Card>
120
+ );
121
+ }
122
+
123
+ return (
124
+ <Box>
125
+ <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
126
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
127
+ <SpeedIcon sx={{ color: 'var(--theme-primary)', fontSize: 32 }} />
128
+ <Typography variant="h4" sx={{ color: 'var(--theme-text-primary)' }}>
129
+ Rate Limits
130
+ </Typography>
131
+ </Box>
132
+ <Box sx={{ display: 'flex', gap: 1 }}>
133
+ <Tooltip title="Refresh">
134
+ <IconButton onClick={fetchConfig} sx={{ color: 'var(--theme-text-secondary)' }}>
135
+ <RefreshIcon />
136
+ </IconButton>
137
+ </Tooltip>
138
+ <Button
139
+ variant="contained"
140
+ startIcon={saving ? <CircularProgress size={16} color="inherit" /> : <SaveIcon />}
141
+ onClick={handleSave}
142
+ disabled={saving || !hasChanges}
143
+ sx={{ minWidth: 100 }}
144
+ >
145
+ {saving ? 'Saving...' : 'Save'}
146
+ </Button>
147
+ </Box>
148
+ </Box>
149
+ <Typography variant="body2" sx={{ mb: 4, color: 'var(--theme-text-secondary)' }}>
150
+ Configure rate limiting defaults for your API
151
+ </Typography>
152
+
153
+ {/* Success/Error messages */}
154
+ {success && <Alert severity="success" sx={{ mb: 3 }}>{success}</Alert>}
155
+ {error && config && <Alert severity="error" sx={{ mb: 3 }}>{error}</Alert>}
156
+
157
+ {/* Status Card */}
158
+ <Card sx={{ bgcolor: 'var(--theme-surface)', mb: 3 }}>
159
+ <CardContent>
160
+ <Typography variant="h6" sx={{ color: 'var(--theme-text-primary)', mb: 2 }}>
161
+ System Status
162
+ </Typography>
163
+ <Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
164
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
165
+ <StorageIcon sx={{ color: 'var(--theme-text-secondary)' }} />
166
+ <Box>
167
+ <Typography variant="caption" sx={{ color: 'var(--theme-text-secondary)' }}>Store</Typography>
168
+ <Typography sx={{ color: 'var(--theme-text-primary)' }}>{config?.store}</Typography>
169
+ </Box>
170
+ </Box>
171
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
172
+ <CachedIcon sx={{ color: config?.cacheAvailable ? 'var(--theme-success)' : 'var(--theme-warning)' }} />
173
+ <Box>
174
+ <Typography variant="caption" sx={{ color: 'var(--theme-text-secondary)' }}>Cache</Typography>
175
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
176
+ <Typography sx={{ color: 'var(--theme-text-primary)' }}>{config?.cache}</Typography>
177
+ <Chip
178
+ label={config?.cacheAvailable ? 'Available' : 'Unavailable'}
179
+ size="small"
180
+ sx={{
181
+ bgcolor: config?.cacheAvailable ? 'var(--theme-success)20' : 'var(--theme-warning)20',
182
+ color: config?.cacheAvailable ? 'var(--theme-success)' : 'var(--theme-warning)',
183
+ }}
184
+ />
185
+ </Box>
186
+ </Box>
187
+ </Box>
188
+ </Box>
189
+ </CardContent>
190
+ </Card>
191
+
192
+ {/* Rate Limit Settings */}
193
+ <Card sx={{ bgcolor: 'var(--theme-surface)', mb: 3 }}>
194
+ <CardContent>
195
+ <Typography variant="h6" sx={{ color: 'var(--theme-text-primary)', mb: 3 }}>
196
+ Default Rate Limit Settings
197
+ </Typography>
198
+
199
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
200
+ {/* Strategy */}
201
+ <FormControl fullWidth>
202
+ <InputLabel sx={{ color: 'var(--theme-text-secondary)' }}>Strategy</InputLabel>
203
+ <Select
204
+ value={strategy}
205
+ label="Strategy"
206
+ onChange={(e) => setStrategy(e.target.value as RateLimitStrategy)}
207
+ sx={{
208
+ color: 'var(--theme-text-primary)',
209
+ '& .MuiOutlinedInput-notchedOutline': { borderColor: 'var(--theme-border)' },
210
+ }}
211
+ >
212
+ <MenuItem value="sliding-window">
213
+ Sliding Window - Smooth rate limiting with weighted overlap
214
+ </MenuItem>
215
+ <MenuItem value="fixed-window">
216
+ Fixed Window - Simple discrete time windows
217
+ </MenuItem>
218
+ <MenuItem value="token-bucket">
219
+ Token Bucket - Allows bursts while maintaining average rate
220
+ </MenuItem>
221
+ </Select>
222
+ </FormControl>
223
+
224
+ {/* Window and Max Requests */}
225
+ <Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
226
+ <TextField
227
+ label="Window (ms)"
228
+ type="number"
229
+ value={windowMs}
230
+ onChange={(e) => setWindowMs(Math.max(1000, parseInt(e.target.value) || 60000))}
231
+ helperText={`= ${formatDuration(windowMs)}`}
232
+ sx={{ flex: 1, minWidth: 200 }}
233
+ InputProps={{ inputProps: { min: 1000, step: 1000 } }}
234
+ />
235
+ <TextField
236
+ label="Max Requests"
237
+ type="number"
238
+ value={maxRequests}
239
+ onChange={(e) => setMaxRequests(Math.max(1, parseInt(e.target.value) || 100))}
240
+ helperText="Per window per key"
241
+ sx={{ flex: 1, minWidth: 200 }}
242
+ InputProps={{ inputProps: { min: 1 } }}
243
+ />
244
+ </Box>
245
+
246
+ {/* Summary */}
247
+ <Alert severity="info" sx={{ bgcolor: 'var(--theme-surface)' }}>
248
+ <Typography variant="body2">
249
+ <strong>Current limit:</strong> {maxRequests} requests per {formatDuration(windowMs)} using {strategy} strategy
250
+ </Typography>
251
+ </Alert>
252
+ </Box>
253
+ </CardContent>
254
+ </Card>
255
+
256
+ {/* Cleanup Settings */}
257
+ <Card sx={{ bgcolor: 'var(--theme-surface)' }}>
258
+ <CardContent>
259
+ <Typography variant="h6" sx={{ color: 'var(--theme-text-primary)', mb: 3 }}>
260
+ Cleanup Job
261
+ </Typography>
262
+
263
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
264
+ <FormControlLabel
265
+ control={
266
+ <Switch
267
+ checked={cleanupEnabled}
268
+ onChange={(e) => setCleanupEnabled(e.target.checked)}
269
+ color="primary"
270
+ />
271
+ }
272
+ label="Enable automatic cleanup of expired rate limits"
273
+ sx={{ color: 'var(--theme-text-primary)' }}
274
+ />
275
+
276
+ {cleanupEnabled && (
277
+ <TextField
278
+ label="Cleanup Interval (ms)"
279
+ type="number"
280
+ value={cleanupIntervalMs}
281
+ onChange={(e) => setCleanupIntervalMs(Math.max(60000, parseInt(e.target.value) || 300000))}
282
+ helperText={`= ${formatDuration(cleanupIntervalMs)}`}
283
+ sx={{ maxWidth: 300 }}
284
+ InputProps={{ inputProps: { min: 60000, step: 60000 } }}
285
+ />
286
+ )}
287
+ </Box>
288
+ </CardContent>
289
+ </Card>
290
+ </Box>
291
+ );
292
+ }
@@ -28,6 +28,11 @@ export default defineConfig({
28
28
  external: [
29
29
  'react',
30
30
  'react-dom',
31
+ 'react/jsx-runtime',
32
+ 'react/jsx-dev-runtime',
33
+ 'react-is',
34
+ 'prop-types',
35
+ 'hoist-non-react-statics',
31
36
  'react-router-dom',
32
37
  '@mui/material',
33
38
  '@mui/icons-material',