@geenius/tools 0.1.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 (160) hide show
  1. package/.changeset/config.json +11 -0
  2. package/.env.example +2 -0
  3. package/.github/CODEOWNERS +1 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
  6. package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  7. package/.github/dependabot.yml +11 -0
  8. package/.github/workflows/ci.yml +23 -0
  9. package/.github/workflows/release.yml +29 -0
  10. package/.node-version +1 -0
  11. package/.nvmrc +1 -0
  12. package/.prettierrc +7 -0
  13. package/.project/ACCOUNT.yaml +4 -0
  14. package/.project/IDEAS.yaml +7 -0
  15. package/.project/PROJECT.yaml +11 -0
  16. package/.project/ROADMAP.yaml +15 -0
  17. package/CHANGELOG.md +16 -0
  18. package/CODE_OF_CONDUCT.md +26 -0
  19. package/CONTRIBUTING.md +69 -0
  20. package/LICENSE +21 -0
  21. package/README.md +1 -0
  22. package/SECURITY.md +18 -0
  23. package/SUPPORT.md +14 -0
  24. package/package.json +75 -0
  25. package/packages/convex/shared/README.md +1 -0
  26. package/packages/convex/shared/package.json +42 -0
  27. package/packages/convex/shared/src/audit/index.ts +5 -0
  28. package/packages/convex/shared/src/audit/presets.ts +165 -0
  29. package/packages/convex/shared/src/audit/schema.ts +85 -0
  30. package/packages/convex/shared/src/audit/write.ts +102 -0
  31. package/packages/convex/shared/src/extract.ts +75 -0
  32. package/packages/convex/shared/src/index.ts +41 -0
  33. package/packages/convex/shared/src/messages.ts +45 -0
  34. package/packages/convex/shared/src/security.ts +112 -0
  35. package/packages/convex/shared/src/throw.ts +184 -0
  36. package/packages/convex/shared/src/types.ts +57 -0
  37. package/packages/convex/shared/src/utils.ts +58 -0
  38. package/packages/convex/shared/tsconfig.json +28 -0
  39. package/packages/convex/shared/tsup.config.ts +12 -0
  40. package/packages/devtools/package.json +27 -0
  41. package/packages/devtools/react/README.md +1 -0
  42. package/packages/devtools/react/package.json +53 -0
  43. package/packages/devtools/react/src/components/DesignPreview.tsx +59 -0
  44. package/packages/devtools/react/src/components/DesignSwitcherDropdown.tsx +99 -0
  45. package/packages/devtools/react/src/components/DevSidebar.tsx +247 -0
  46. package/packages/devtools/react/src/components/DevToolbar.tsx +242 -0
  47. package/packages/devtools/react/src/components/GitHubIssueDialog.tsx +402 -0
  48. package/packages/devtools/react/src/components/InspectorOverlay.tsx +312 -0
  49. package/packages/devtools/react/src/components/PageLoadWaterfall.tsx +144 -0
  50. package/packages/devtools/react/src/components/PerformancePanel.tsx +330 -0
  51. package/packages/devtools/react/src/context/DevModeContext.tsx +226 -0
  52. package/packages/devtools/react/src/context/PerformanceContext.tsx +143 -0
  53. package/packages/devtools/react/src/data/designs.ts +13 -0
  54. package/packages/devtools/react/src/hooks/useGitHubLabels.ts +47 -0
  55. package/packages/devtools/react/src/hooks/useVirtualList.ts +124 -0
  56. package/packages/devtools/react/src/index.ts +77 -0
  57. package/packages/devtools/react/src/panels/ConvexSpy.tsx +130 -0
  58. package/packages/devtools/react/src/panels/DatabaseSeeder.tsx +116 -0
  59. package/packages/devtools/react/src/panels/DevModePhase2.tsx +191 -0
  60. package/packages/devtools/react/src/panels/DevModePhase3.tsx +234 -0
  61. package/packages/devtools/react/src/panels/FeatureFlagsToggle.tsx +104 -0
  62. package/packages/devtools/react/src/panels/QuickRouteJump.tsx +152 -0
  63. package/packages/devtools/react/src/services/github-service.ts +247 -0
  64. package/packages/devtools/react/tsconfig.json +31 -0
  65. package/packages/devtools/react/tsup.config.ts +18 -0
  66. package/packages/devtools/solidjs/README.md +1 -0
  67. package/packages/devtools/solidjs/package.json +49 -0
  68. package/packages/devtools/solidjs/src/components/DesignPreview.tsx +51 -0
  69. package/packages/devtools/solidjs/src/components/DesignSwitcherDropdown.tsx +95 -0
  70. package/packages/devtools/solidjs/src/components/DevSidebar.tsx +247 -0
  71. package/packages/devtools/solidjs/src/components/DevToolbar.tsx +242 -0
  72. package/packages/devtools/solidjs/src/components/GitHubIssueDialog.tsx +400 -0
  73. package/packages/devtools/solidjs/src/components/InspectorOverlay.tsx +311 -0
  74. package/packages/devtools/solidjs/src/components/PageLoadWaterfall.tsx +144 -0
  75. package/packages/devtools/solidjs/src/components/PerformancePanel.tsx +330 -0
  76. package/packages/devtools/solidjs/src/context/DevModeContext.tsx +216 -0
  77. package/packages/devtools/solidjs/src/context/PerformanceContext.tsx +135 -0
  78. package/packages/devtools/solidjs/src/data/designs.ts +13 -0
  79. package/packages/devtools/solidjs/src/hooks/createGitHubLabels.ts +47 -0
  80. package/packages/devtools/solidjs/src/index.ts +64 -0
  81. package/packages/devtools/solidjs/src/services/github-service.ts +247 -0
  82. package/packages/devtools/solidjs/tsconfig.json +21 -0
  83. package/packages/devtools/src/index.ts +377 -0
  84. package/packages/devtools/tsup.config.ts +12 -0
  85. package/packages/env/package.json +30 -0
  86. package/packages/env/src/index.ts +264 -0
  87. package/packages/env/tsup.config.ts +12 -0
  88. package/packages/errors/package.json +27 -0
  89. package/packages/errors/react/README.md +1 -0
  90. package/packages/errors/react/package.json +72 -0
  91. package/packages/errors/react/src/analytics.ts +16 -0
  92. package/packages/errors/react/src/components/ErrorBoundary.tsx +248 -0
  93. package/packages/errors/react/src/components/ErrorDisplay.tsx +328 -0
  94. package/packages/errors/react/src/components/ValidationErrors.tsx +102 -0
  95. package/packages/errors/react/src/config.ts +199 -0
  96. package/packages/errors/react/src/constants.ts +74 -0
  97. package/packages/errors/react/src/hooks/useErrorBoundary.ts +92 -0
  98. package/packages/errors/react/src/hooks/useErrorHandler.ts +87 -0
  99. package/packages/errors/react/src/index.ts +96 -0
  100. package/packages/errors/react/src/types.ts +102 -0
  101. package/packages/errors/react/src/utils/errorMessages.ts +35 -0
  102. package/packages/errors/react/src/utils/errorPolicy.ts +139 -0
  103. package/packages/errors/react/src/utils/extractAppError.ts +174 -0
  104. package/packages/errors/react/src/utils/formatError.ts +112 -0
  105. package/packages/errors/react/tsconfig.json +25 -0
  106. package/packages/errors/react/tsup.config.ts +24 -0
  107. package/packages/errors/solidjs/README.md +1 -0
  108. package/packages/errors/solidjs/package.json +46 -0
  109. package/packages/errors/solidjs/src/components/ErrorDisplay.tsx +179 -0
  110. package/packages/errors/solidjs/src/config.ts +98 -0
  111. package/packages/errors/solidjs/src/hooks/createErrorHandler.ts +107 -0
  112. package/packages/errors/solidjs/src/index.ts +61 -0
  113. package/packages/errors/solidjs/src/types.ts +34 -0
  114. package/packages/errors/solidjs/src/utils/errorPolicy.ts +56 -0
  115. package/packages/errors/solidjs/src/utils/extractAppError.ts +94 -0
  116. package/packages/errors/solidjs/src/utils/formatError.ts +33 -0
  117. package/packages/errors/solidjs/tsconfig.json +26 -0
  118. package/packages/errors/solidjs/tsup.config.ts +21 -0
  119. package/packages/errors/src/index.ts +320 -0
  120. package/packages/errors/tsup.config.ts +12 -0
  121. package/packages/logger/package.json +27 -0
  122. package/packages/logger/react/README.md +1 -0
  123. package/packages/logger/react/package.json +46 -0
  124. package/packages/logger/react/src/index.ts +4 -0
  125. package/packages/logger/react/src/useMetrics.ts +42 -0
  126. package/packages/logger/react/src/usePerformanceLog.ts +61 -0
  127. package/packages/logger/react/tsconfig.json +31 -0
  128. package/packages/logger/react/tsup.config.ts +12 -0
  129. package/packages/logger/solidjs/README.md +1 -0
  130. package/packages/logger/solidjs/package.json +45 -0
  131. package/packages/logger/solidjs/src/createMetrics.ts +37 -0
  132. package/packages/logger/solidjs/src/createPerformanceLog.ts +58 -0
  133. package/packages/logger/solidjs/src/index.ts +4 -0
  134. package/packages/logger/solidjs/tsconfig.json +32 -0
  135. package/packages/logger/solidjs/tsup.config.ts +12 -0
  136. package/packages/logger/src/index.ts +363 -0
  137. package/packages/logger/tsup.config.ts +12 -0
  138. package/packages/perf/package.json +27 -0
  139. package/packages/perf/react/README.md +1 -0
  140. package/packages/perf/react/package.json +59 -0
  141. package/packages/perf/react/src/components/PerformanceDashboard.tsx +257 -0
  142. package/packages/perf/react/src/hooks/useMonitoredQuery.ts +89 -0
  143. package/packages/perf/react/src/hooks/usePerformanceMetrics.ts +78 -0
  144. package/packages/perf/react/src/index.ts +33 -0
  145. package/packages/perf/react/src/services/PerformanceMonitor.ts +313 -0
  146. package/packages/perf/react/src/types.ts +77 -0
  147. package/packages/perf/react/tsconfig.json +25 -0
  148. package/packages/perf/react/tsup.config.ts +19 -0
  149. package/packages/perf/solidjs/README.md +1 -0
  150. package/packages/perf/solidjs/package.json +41 -0
  151. package/packages/perf/solidjs/src/components/PerformanceDashboard.tsx +207 -0
  152. package/packages/perf/solidjs/src/hooks/createPerformanceMetrics.ts +73 -0
  153. package/packages/perf/solidjs/src/index.ts +31 -0
  154. package/packages/perf/solidjs/src/services/PerformanceMonitor.ts +134 -0
  155. package/packages/perf/solidjs/src/types.ts +78 -0
  156. package/packages/perf/solidjs/tsconfig.json +26 -0
  157. package/packages/perf/solidjs/tsup.config.ts +14 -0
  158. package/packages/perf/src/index.ts +410 -0
  159. package/packages/perf/tsup.config.ts +12 -0
  160. package/pnpm-workspace.yaml +2 -0
@@ -0,0 +1,102 @@
1
+ // @geenius-tools/errors-react — src/components/ValidationErrors.tsx
2
+
3
+ import { FC } from 'react'
4
+ import { AlertCircle } from 'lucide-react'
5
+ import type { ValidationError } from '../types'
6
+ import { formatValidationErrors } from '../utils/formatError'
7
+
8
+ export interface ValidationErrorsProps {
9
+ errors: ValidationError[]
10
+ className?: string
11
+ grouped?: boolean
12
+ }
13
+
14
+ /**
15
+ * Validation Errors Component
16
+ *
17
+ * Displays validation errors from backend in a user-friendly format.
18
+ * Automatically groups errors by field.
19
+ *
20
+ * @example
21
+ * <ValidationErrors errors={appError.validationErrors} />
22
+ */
23
+ export const ValidationErrors: FC<ValidationErrorsProps> = ({
24
+ errors,
25
+ className = '',
26
+ grouped = true,
27
+ }) => {
28
+ if (!errors || errors.length === 0) return null
29
+
30
+ if (!grouped) {
31
+ return (
32
+ <div className={className} style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
33
+ {errors.map((error, index) => (
34
+ <div
35
+ key={index}
36
+ style={{
37
+ display: 'flex',
38
+ alignItems: 'flex-start',
39
+ gap: '8px',
40
+ padding: '12px',
41
+ borderRadius: '8px',
42
+ backgroundColor: 'rgba(239, 68, 68, 0.05)',
43
+ border: '1px solid rgba(239, 68, 68, 0.2)',
44
+ }}
45
+ >
46
+ <AlertCircle style={{ height: '16px', width: '16px', color: '#dc2626', marginTop: '2px', flexShrink: 0 }} />
47
+ <div style={{ flex: 1 }}>
48
+ <p style={{ fontSize: '14px', fontWeight: 500, color: '#991b1b', margin: 0 }}>
49
+ {error.field}
50
+ </p>
51
+ <p style={{ fontSize: '14px', color: '#b91c1c', margin: 0 }}>
52
+ {error.message}
53
+ </p>
54
+ </div>
55
+ </div>
56
+ ))}
57
+ </div>
58
+ )
59
+ }
60
+
61
+ const groupedErrors = formatValidationErrors(errors)
62
+
63
+ return (
64
+ <div className={className} style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
65
+ <p style={{ fontSize: '14px', fontWeight: 600, margin: 0, textAlign: 'left' }}>
66
+ Please fix the following fields:
67
+ </p>
68
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
69
+ {Object.entries(groupedErrors).map(([field, messages]) => (
70
+ <div
71
+ key={field}
72
+ style={{
73
+ display: 'flex',
74
+ alignItems: 'flex-start',
75
+ gap: '8px',
76
+ padding: '12px',
77
+ borderRadius: '8px',
78
+ backgroundColor: 'rgba(234, 179, 8, 0.05)',
79
+ border: '1px solid rgba(234, 179, 8, 0.2)',
80
+ textAlign: 'left',
81
+ }}
82
+ >
83
+ <AlertCircle style={{ height: '16px', width: '16px', color: '#ca8a04', marginTop: '2px', flexShrink: 0 }} />
84
+ <div style={{ flex: 1 }}>
85
+ <p style={{ fontSize: '14px', fontWeight: 500, textTransform: 'capitalize', color: '#854d0e', margin: 0 }}>
86
+ {field}
87
+ </p>
88
+ {messages.map((message, index) => (
89
+ <p
90
+ key={index}
91
+ style={{ fontSize: '14px', color: '#a16207', margin: 0 }}
92
+ >
93
+ {message}
94
+ </p>
95
+ ))}
96
+ </div>
97
+ </div>
98
+ ))}
99
+ </div>
100
+ </div>
101
+ )
102
+ }
@@ -0,0 +1,199 @@
1
+ // @geenius-tools/errors-react — src/config.ts
2
+ // Pluggable configuration for toast handling and error messages
3
+
4
+ import type { AppErrorCode } from './types'
5
+
6
+ // ============================================================================
7
+ // Toast Configuration
8
+ // ============================================================================
9
+
10
+ /**
11
+ * Toast function interface — matches react-hot-toast API shape
12
+ */
13
+ export interface ToastFn {
14
+ (message: string): void
15
+ error: (message: string, options?: { id?: string }) => void
16
+ success: (message: string, options?: { id?: string }) => void
17
+ loading: (message: string, options?: { id?: string }) => string | number
18
+ }
19
+
20
+ /**
21
+ * Error handler configuration
22
+ */
23
+ export interface ErrorHandlerConfig {
24
+ toast?: ToastFn
25
+ /** Whether to log errors to console in development */
26
+ logInDev?: boolean
27
+ }
28
+
29
+ let _errorHandlerConfig: ErrorHandlerConfig = {
30
+ logInDev: true,
31
+ }
32
+
33
+ /**
34
+ * Configure the global error handler
35
+ *
36
+ * @example
37
+ * import toast from 'react-hot-toast'
38
+ * import { configureErrorHandler } from '@geenius-tools/errors-react'
39
+ *
40
+ * configureErrorHandler({ toast })
41
+ */
42
+ export function configureErrorHandler(config: ErrorHandlerConfig): void {
43
+ _errorHandlerConfig = { ..._errorHandlerConfig, ...config }
44
+ }
45
+
46
+ export function getErrorHandlerConfig(): ErrorHandlerConfig {
47
+ return _errorHandlerConfig
48
+ }
49
+
50
+ // ============================================================================
51
+ // Error Messages Configuration
52
+ // ============================================================================
53
+
54
+ /**
55
+ * Error message set
56
+ */
57
+ export interface ErrorMessageSet {
58
+ /** Short error messages keyed by error code */
59
+ messages: Record<AppErrorCode, string>
60
+ /** User-friendly titles keyed by error code */
61
+ titles: Record<AppErrorCode, string>
62
+ /** Detailed descriptions keyed by error code */
63
+ descriptions: Record<AppErrorCode, string>
64
+ /** Suggested actions keyed by error code */
65
+ actions: Record<AppErrorCode, string>
66
+ /** Validation message helpers */
67
+ validation: Record<string, string>
68
+ }
69
+
70
+ /**
71
+ * English error messages (default)
72
+ */
73
+ export const ERROR_MESSAGES_EN: ErrorMessageSet = {
74
+ messages: {
75
+ UNAUTHENTICATED: 'Authentication required. Please sign in.',
76
+ FORBIDDEN: 'Access denied. You do not have permission for this action.',
77
+ NOT_FOUND: 'The requested resource was not found.',
78
+ BAD_REQUEST: 'Invalid request. Please check your input.',
79
+ CONFLICT: 'A conflict occurred with existing data.',
80
+ INTERNAL: 'An internal error occurred. Please try again later.',
81
+ VALIDATION_ERROR: 'Some fields are invalid. Please check and try again.',
82
+ RATE_LIMITED: 'Too many requests. Please try again later.',
83
+ FEATURE_DISABLED: 'This feature is currently disabled.',
84
+ },
85
+ titles: {
86
+ UNAUTHENTICATED: 'Not Authenticated',
87
+ FORBIDDEN: 'Access Denied',
88
+ NOT_FOUND: 'Not Found',
89
+ BAD_REQUEST: 'Invalid Request',
90
+ CONFLICT: 'Conflict',
91
+ INTERNAL: 'Internal Error',
92
+ VALIDATION_ERROR: 'Validation Error',
93
+ RATE_LIMITED: 'Too Many Requests',
94
+ FEATURE_DISABLED: 'Feature Disabled',
95
+ },
96
+ descriptions: {
97
+ UNAUTHENTICATED: 'Please sign in to continue. Your session may have expired.',
98
+ FORBIDDEN: 'You do not have permission for this action. Contact an administrator if you believe this is an error.',
99
+ NOT_FOUND: 'The requested resource was not found. It may have been deleted or moved.',
100
+ BAD_REQUEST: 'Invalid request. Please check your input and try again.',
101
+ CONFLICT: 'This action could not be completed due to a conflict with existing data.',
102
+ INTERNAL: 'An internal error occurred. Our team has been notified. Please try again later.',
103
+ VALIDATION_ERROR: 'Some of your inputs are invalid. Please check the highlighted fields and try again.',
104
+ RATE_LIMITED: 'You have sent too many requests in a short time. Please wait a moment and try again.',
105
+ FEATURE_DISABLED: 'This feature is currently disabled. Please try again later or contact support.',
106
+ },
107
+ actions: {
108
+ UNAUTHENTICATED: 'Please sign in again.',
109
+ FORBIDDEN: 'Contact an administrator if you need access.',
110
+ NOT_FOUND: 'Go back to the home page or use search.',
111
+ BAD_REQUEST: 'Check your input and try again.',
112
+ CONFLICT: 'Refresh the page and try again.',
113
+ INTERNAL: 'Try again in a few minutes.',
114
+ VALIDATION_ERROR: 'Fix the highlighted fields.',
115
+ RATE_LIMITED: 'Wait a moment and try again.',
116
+ FEATURE_DISABLED: 'Try again later or contact support.',
117
+ },
118
+ validation: {
119
+ required: 'This field is required.',
120
+ minLength: 'Must be at least {min} characters.',
121
+ maxLength: 'Must be at most {max} characters.',
122
+ email: 'Please enter a valid email address.',
123
+ url: 'Please enter a valid URL.',
124
+ },
125
+ }
126
+
127
+ /**
128
+ * German error messages preset
129
+ */
130
+ export const ERROR_MESSAGES_DE: ErrorMessageSet = {
131
+ messages: {
132
+ UNAUTHENTICATED: 'Authentifizierung erforderlich. Bitte melde dich an.',
133
+ FORBIDDEN: 'Zugriff verweigert. Du hast keine Berechtigung für diese Aktion.',
134
+ NOT_FOUND: 'Die angeforderte Ressource wurde nicht gefunden.',
135
+ BAD_REQUEST: 'Ungültige Anfrage. Bitte überprüfe deine Eingaben.',
136
+ CONFLICT: 'Ein Konflikt mit bestehenden Daten ist aufgetreten.',
137
+ INTERNAL: 'Ein interner Fehler ist aufgetreten. Bitte versuche es später erneut.',
138
+ VALIDATION_ERROR: 'Einige Felder sind ungültig. Bitte überprüfe deine Eingaben.',
139
+ RATE_LIMITED: 'Zu viele Anfragen. Bitte versuche es später erneut.',
140
+ FEATURE_DISABLED: 'Diese Funktion ist derzeit deaktiviert.',
141
+ },
142
+ titles: {
143
+ UNAUTHENTICATED: 'Nicht angemeldet',
144
+ FORBIDDEN: 'Zugriff verweigert',
145
+ NOT_FOUND: 'Nicht gefunden',
146
+ BAD_REQUEST: 'Ungültige Anfrage',
147
+ CONFLICT: 'Konflikt',
148
+ INTERNAL: 'Interner Fehler',
149
+ VALIDATION_ERROR: 'Validierungsfehler',
150
+ RATE_LIMITED: 'Zu viele Anfragen',
151
+ FEATURE_DISABLED: 'Funktion deaktiviert',
152
+ },
153
+ descriptions: {
154
+ UNAUTHENTICATED: 'Bitte melde dich an, um fortzufahren. Deine Sitzung ist möglicherweise abgelaufen.',
155
+ FORBIDDEN: 'Du hast keine Berechtigung für diese Aktion. Wenn du glaubst, dass dies ein Fehler ist, wende dich an einen Administrator.',
156
+ NOT_FOUND: 'Die angeforderte Ressource wurde nicht gefunden. Sie wurde möglicherweise gelöscht oder verschoben.',
157
+ BAD_REQUEST: 'Ungültige Anfrage. Bitte überprüfe deine Eingaben und versuche es erneut.',
158
+ CONFLICT: 'Diese Aktion konnte nicht ausgeführt werden, da ein Konflikt mit bestehenden Daten besteht.',
159
+ INTERNAL: 'Ein interner Fehler ist aufgetreten. Unser Team wurde benachrichtigt. Bitte versuche es später erneut.',
160
+ VALIDATION_ERROR: 'Einige deiner Eingaben sind ungültig. Bitte überprüfe die markierten Felder und versuche es erneut.',
161
+ RATE_LIMITED: 'Du hast zu viele Anfragen in kurzer Zeit gesendet. Bitte warte einen Moment und versuche es dann erneut.',
162
+ FEATURE_DISABLED: 'Diese Funktion ist derzeit deaktiviert. Bitte versuche es später erneut oder wende dich an den Support.',
163
+ },
164
+ actions: {
165
+ UNAUTHENTICATED: 'Bitte melde dich erneut an.',
166
+ FORBIDDEN: 'Kontaktiere einen Administrator, wenn du Zugriff benötigst.',
167
+ NOT_FOUND: 'Gehe zurück zur Startseite oder verwende die Suche.',
168
+ BAD_REQUEST: 'Überprüfe deine Eingaben und versuche es erneut.',
169
+ CONFLICT: 'Aktualisiere die Seite und versuche es erneut.',
170
+ INTERNAL: 'Versuche es in einigen Minuten erneut.',
171
+ VALIDATION_ERROR: 'Korrigiere die markierten Felder.',
172
+ RATE_LIMITED: 'Warte einen Moment und versuche es dann erneut.',
173
+ FEATURE_DISABLED: 'Versuche es später erneut oder kontaktiere den Support.',
174
+ },
175
+ validation: {
176
+ required: 'Dieses Feld ist erforderlich.',
177
+ minLength: 'Mindestens {min} Zeichen erforderlich.',
178
+ maxLength: 'Maximal {max} Zeichen erlaubt.',
179
+ email: 'Bitte gib eine gültige E-Mail-Adresse ein.',
180
+ url: 'Bitte gib eine gültige URL ein.',
181
+ },
182
+ }
183
+
184
+ let _currentMessages: ErrorMessageSet = ERROR_MESSAGES_EN
185
+
186
+ /**
187
+ * Configure error messages (set locale)
188
+ *
189
+ * @example
190
+ * import { configureErrorMessages, ERROR_MESSAGES_DE } from '@geenius-tools/errors-react'
191
+ * configureErrorMessages(ERROR_MESSAGES_DE)
192
+ */
193
+ export function configureErrorMessages(messages: ErrorMessageSet): void {
194
+ _currentMessages = messages
195
+ }
196
+
197
+ export function getErrorMessages(): ErrorMessageSet {
198
+ return _currentMessages
199
+ }
@@ -0,0 +1,74 @@
1
+ // @geenius-tools/errors-react — src/constants.ts
2
+
3
+ import {
4
+ AlertCircle,
5
+ AlertTriangle,
6
+ ShieldAlert,
7
+ Clock,
8
+ Ban,
9
+ type LucideIcon,
10
+ } from 'lucide-react'
11
+ import type { AppErrorCode } from './types'
12
+
13
+ /**
14
+ * Icon mapping for each error code
15
+ */
16
+ export const ERROR_CODE_ICONS: Record<AppErrorCode, LucideIcon> = {
17
+ UNAUTHENTICATED: ShieldAlert,
18
+ FORBIDDEN: ShieldAlert,
19
+ NOT_FOUND: AlertCircle,
20
+ BAD_REQUEST: AlertTriangle,
21
+ CONFLICT: AlertTriangle,
22
+ INTERNAL: AlertCircle,
23
+ VALIDATION_ERROR: AlertTriangle,
24
+ RATE_LIMITED: Clock,
25
+ FEATURE_DISABLED: Ban,
26
+ }
27
+
28
+ /**
29
+ * Color classes for each error code
30
+ */
31
+ export const ERROR_CODE_COLORS: Record<AppErrorCode, string> = {
32
+ UNAUTHENTICATED: 'text-purple-600 dark:text-purple-400',
33
+ FORBIDDEN: 'text-red-600 dark:text-red-400',
34
+ NOT_FOUND: 'text-blue-600 dark:text-blue-400',
35
+ BAD_REQUEST: 'text-yellow-600 dark:text-yellow-400',
36
+ CONFLICT: 'text-orange-600 dark:text-orange-400',
37
+ INTERNAL: 'text-red-600 dark:text-red-400',
38
+ VALIDATION_ERROR: 'text-yellow-600 dark:text-yellow-400',
39
+ RATE_LIMITED: 'text-orange-600 dark:text-orange-400',
40
+ FEATURE_DISABLED: 'text-gray-600 dark:text-gray-400',
41
+ }
42
+
43
+ /**
44
+ * Background color classes for error code icons
45
+ */
46
+ export const ERROR_CODE_BG_COLORS: Record<AppErrorCode, string> = {
47
+ UNAUTHENTICATED: 'bg-purple-100 dark:bg-purple-900/30',
48
+ FORBIDDEN: 'bg-red-100 dark:bg-red-900/30',
49
+ NOT_FOUND: 'bg-blue-100 dark:bg-blue-900/30',
50
+ BAD_REQUEST: 'bg-yellow-100 dark:bg-yellow-900/30',
51
+ CONFLICT: 'bg-orange-100 dark:bg-orange-900/30',
52
+ INTERNAL: 'bg-red-100 dark:bg-red-900/30',
53
+ VALIDATION_ERROR: 'bg-yellow-100 dark:bg-yellow-900/30',
54
+ RATE_LIMITED: 'bg-orange-100 dark:bg-orange-900/30',
55
+ FEATURE_DISABLED: 'bg-gray-100 dark:bg-gray-900/30',
56
+ }
57
+
58
+ /**
59
+ * Error severity levels for analytics
60
+ */
61
+ export const ERROR_CODE_SEVERITY: Record<
62
+ AppErrorCode,
63
+ 'low' | 'medium' | 'high' | 'critical'
64
+ > = {
65
+ UNAUTHENTICATED: 'low',
66
+ FORBIDDEN: 'medium',
67
+ NOT_FOUND: 'low',
68
+ BAD_REQUEST: 'medium',
69
+ CONFLICT: 'medium',
70
+ INTERNAL: 'critical',
71
+ VALIDATION_ERROR: 'low',
72
+ RATE_LIMITED: 'medium',
73
+ FEATURE_DISABLED: 'low',
74
+ }
@@ -0,0 +1,92 @@
1
+ // @geenius-tools/errors-react — src/hooks/useErrorBoundary.ts
2
+
3
+ import { useState, useCallback } from 'react'
4
+
5
+ export interface UseErrorBoundaryReturn {
6
+ error: Error | null
7
+ hasError: boolean
8
+ setError: (error: Error | null) => void
9
+ resetError: () => void
10
+ throwError: (error: Error) => void
11
+ }
12
+
13
+ /**
14
+ * Hook for managing error boundary state
15
+ *
16
+ * @example
17
+ * const { error, hasError, setError, resetError } = useErrorBoundary()
18
+ *
19
+ * if (hasError) {
20
+ * return <div>Error: {error?.message}</div>
21
+ * }
22
+ */
23
+ export function useErrorBoundary(): UseErrorBoundaryReturn {
24
+ const [error, setErrorState] = useState<Error | null>(null)
25
+
26
+ const setError = useCallback((error: Error | null) => {
27
+ setErrorState(error)
28
+ }, [])
29
+
30
+ const resetError = useCallback(() => {
31
+ setErrorState(null)
32
+ }, [])
33
+
34
+ const throwError = useCallback((error: Error) => {
35
+ throw error
36
+ }, [])
37
+
38
+ return {
39
+ error,
40
+ hasError: error !== null,
41
+ setError,
42
+ resetError,
43
+ throwError,
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Hook for safe async operations with error handling
49
+ *
50
+ * @example
51
+ * const { execute, loading, error } = useAsyncError()
52
+ *
53
+ * const handleClick = async () => {
54
+ * await execute(async () => {
55
+ * await someAsyncOperation()
56
+ * })
57
+ * }
58
+ */
59
+ export function useAsyncError() {
60
+ const [loading, setLoading] = useState(false)
61
+ const [error, setError] = useState<Error | null>(null)
62
+
63
+ const execute = useCallback(
64
+ async <T>(fn: () => Promise<T>): Promise<T | undefined> => {
65
+ setLoading(true)
66
+ setError(null)
67
+
68
+ try {
69
+ const result = await fn()
70
+ setLoading(false)
71
+ return result
72
+ } catch (err) {
73
+ setError(err instanceof Error ? err : new Error(String(err)))
74
+ setLoading(false)
75
+ return undefined
76
+ }
77
+ },
78
+ [],
79
+ )
80
+
81
+ const resetError = useCallback(() => {
82
+ setError(null)
83
+ }, [])
84
+
85
+ return {
86
+ execute,
87
+ loading,
88
+ error,
89
+ hasError: error !== null,
90
+ resetError,
91
+ }
92
+ }
@@ -0,0 +1,87 @@
1
+ // @geenius-tools/errors-react — src/hooks/useErrorHandler.ts
2
+
3
+ import { useCallback } from 'react'
4
+ import {
5
+ handleAppError,
6
+ shouldRetryError,
7
+ getRetryDelay,
8
+ } from '../utils/errorPolicy'
9
+ import { extractAppError } from '../utils/extractAppError'
10
+
11
+ /**
12
+ * Hook for handling errors with the global error policy
13
+ *
14
+ * @example
15
+ * const { handleError } = useErrorHandler()
16
+ *
17
+ * try {
18
+ * await mutation(...)
19
+ * } catch (error) {
20
+ * handleError(error)
21
+ * }
22
+ */
23
+ export function useErrorHandler() {
24
+ const handleError = useCallback((error: unknown) => {
25
+ handleAppError(error)
26
+ }, [])
27
+
28
+ return { handleError }
29
+ }
30
+
31
+ /**
32
+ * Hook for mutation error handling
33
+ *
34
+ * Provides error handler compatible with TanStack Query mutations.
35
+ *
36
+ * @example
37
+ * const mutation = useMutation({
38
+ * mutationFn: createUser,
39
+ * ...useMutationErrorHandler()
40
+ * })
41
+ */
42
+ export function useMutationErrorHandler() {
43
+ const { handleError } = useErrorHandler()
44
+
45
+ return {
46
+ onError: handleError,
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Hook for query error handling
52
+ */
53
+ export function useQueryErrorHandler() {
54
+ const { handleError } = useErrorHandler()
55
+
56
+ return {
57
+ onError: handleError,
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Hook for error retry logic
63
+ *
64
+ * Provides retry configuration for TanStack Query based on error type.
65
+ */
66
+ export function useErrorRetry(maxRetries = 3) {
67
+ return {
68
+ retry: (failureCount: number, error: unknown) => {
69
+ if (failureCount >= maxRetries) return false
70
+ return shouldRetryError(error)
71
+ },
72
+ retryDelay: (attemptIndex: number, error: unknown) => {
73
+ return getRetryDelay(error, attemptIndex + 1)
74
+ },
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Hook for getting error information
80
+ */
81
+ export function useErrorInfo() {
82
+ const getErrorInfo = useCallback((error: unknown) => {
83
+ return extractAppError(error)
84
+ }, [])
85
+
86
+ return { getErrorInfo }
87
+ }
@@ -0,0 +1,96 @@
1
+ // @geenius-tools/errors-react — src/index.ts
2
+ // Main entry point — everything except Convex-dependent analytics
3
+
4
+ // ===== Types =====
5
+ export type {
6
+ AppErrorCode,
7
+ AppErrorPayload,
8
+ ValidationError,
9
+ ErrorDisplayVariant,
10
+ ErrorAnalyticsFilters,
11
+ ErrorTrend,
12
+ ErrorAnalyticsEntry,
13
+ ErrorMute,
14
+ } from './types'
15
+
16
+ // ===== Config =====
17
+ export {
18
+ configureErrorHandler,
19
+ configureErrorMessages,
20
+ getErrorHandlerConfig,
21
+ getErrorMessages,
22
+ ERROR_MESSAGES_EN,
23
+ ERROR_MESSAGES_DE,
24
+ } from './config'
25
+ export type {
26
+ ToastFn,
27
+ ErrorHandlerConfig,
28
+ ErrorMessageSet,
29
+ } from './config'
30
+
31
+ // ===== Constants =====
32
+ export {
33
+ ERROR_CODE_ICONS,
34
+ ERROR_CODE_COLORS,
35
+ ERROR_CODE_BG_COLORS,
36
+ ERROR_CODE_SEVERITY,
37
+ } from './constants'
38
+
39
+ // ===== Utils =====
40
+ export {
41
+ extractAppError,
42
+ extractRequestId,
43
+ extractFunctionName,
44
+ getErrorDetails,
45
+ normalizeErrorMessage,
46
+ } from './utils/extractAppError'
47
+
48
+ export {
49
+ getErrorTitle,
50
+ getFallbackMessage,
51
+ getErrorDescription,
52
+ getErrorAction,
53
+ } from './utils/errorMessages'
54
+
55
+ export {
56
+ handleAppError,
57
+ handleAppErrorSilent,
58
+ shouldRetryError,
59
+ getRetryDelay,
60
+ } from './utils/errorPolicy'
61
+
62
+ export {
63
+ formatValidationErrors,
64
+ formatValidationErrorsAsString,
65
+ getFieldError,
66
+ getFieldErrors,
67
+ formatTimestamp,
68
+ formatRelativeTime,
69
+ truncateMessage,
70
+ formatErrorCode,
71
+ } from './utils/formatError'
72
+
73
+ // ===== Components =====
74
+ export { ErrorBoundary } from './components/ErrorBoundary'
75
+ export type { ErrorBoundaryProps } from './components/ErrorBoundary'
76
+
77
+ export { ErrorDisplay } from './components/ErrorDisplay'
78
+ export type { ErrorDisplayProps } from './components/ErrorDisplay'
79
+
80
+ export { ValidationErrors } from './components/ValidationErrors'
81
+ export type { ValidationErrorsProps } from './components/ValidationErrors'
82
+
83
+ // ===== Hooks =====
84
+ export {
85
+ useErrorHandler,
86
+ useMutationErrorHandler,
87
+ useQueryErrorHandler,
88
+ useErrorRetry,
89
+ useErrorInfo,
90
+ } from './hooks/useErrorHandler'
91
+
92
+ export {
93
+ useErrorBoundary,
94
+ useAsyncError,
95
+ } from './hooks/useErrorBoundary'
96
+ export type { UseErrorBoundaryReturn } from './hooks/useErrorBoundary'