@payez/next-mvp 4.1.7 → 4.1.9
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/README.md +792 -792
- package/dist/auth/better-auth.js +15 -3
- package/dist/components/account/MobileNavDrawer.js +18 -18
- package/dist/components/account/UserAvatarMenu.js +1 -1
- package/dist/components/admin/AlertSettingsTab.js +40 -40
- package/dist/components/admin/LoggingSettingsTab.js +28 -28
- package/dist/pages/login/page.js +28 -28
- package/dist/pages/settings/EnhancedSettingsPage.js +17 -17
- package/package.json +1 -1
- package/scripts/dev-broker.ps1 +35 -35
- package/scripts/dev-local.ps1 +45 -45
- package/src/api/auth-handler.ts +548 -548
- package/src/api-handlers/account/change-password.ts +142 -142
- package/src/api-handlers/account/update-phone.ts +79 -79
- package/src/api-handlers/account/verify-email.ts +125 -125
- package/src/api-handlers/account/verify-sms.ts +125 -125
- package/src/api-handlers/admin/analytics.ts +443 -443
- package/src/api-handlers/admin/audit.ts +223 -223
- package/src/api-handlers/admin/index.ts +63 -63
- package/src/api-handlers/admin/redis-sessions.ts +251 -251
- package/src/api-handlers/admin/sessions.ts +318 -318
- package/src/api-handlers/admin/site-logs.ts +365 -365
- package/src/api-handlers/admin/users.ts +242 -242
- package/src/api-handlers/admin/vibe-data.ts +324 -324
- package/src/api-handlers/auth/refresh.ts +682 -682
- package/src/api-handlers/auth/signout.ts +199 -199
- package/src/api-handlers/auth/status.ts +20 -20
- package/src/api-handlers/auth/update-session.ts +110 -110
- package/src/api-handlers/auth/verify-code.ts +112 -112
- package/src/api-handlers/session/refresh-viability.ts +36 -36
- package/src/api-handlers/test/force-expire.ts +60 -60
- package/src/auth/auth-decision.ts +229 -229
- package/src/auth/better-auth.ts +15 -3
- package/src/auth/route-config.ts +219 -219
- package/src/auth/types/auth-types.ts +555 -555
- package/src/auth/types/index.ts +7 -7
- package/src/auth/utils/idp-client.ts +445 -445
- package/src/auth/utils/index.ts +6 -6
- package/src/auth/utils/token-utils.ts +243 -243
- package/src/client/AuthContext.tsx +143 -143
- package/src/client/fetch-with-auth.ts +47 -47
- package/src/components/SessionSync.tsx +138 -138
- package/src/components/SignalRHealthCheck.tsx +131 -131
- package/src/components/account/MobileNavDrawer.tsx +305 -305
- package/src/components/account/UserAvatarMenu.tsx +266 -266
- package/src/components/account/index.ts +13 -13
- package/src/components/admin/AlertSettingsTab.tsx +728 -728
- package/src/components/admin/AnalyticsTab.tsx +703 -703
- package/src/components/admin/DataBrowserTab.tsx +505 -505
- package/src/components/admin/LoggingSettingsTab.tsx +665 -665
- package/src/components/admin/SessionsTab.tsx +414 -414
- package/src/components/admin/StatsTab.tsx +379 -379
- package/src/components/admin/VibeAdminLayout.tsx +187 -187
- package/src/components/admin/index.ts +59 -59
- package/src/components/auth/FederatedAuthSection.tsx +95 -95
- package/src/components/auth/ModeAwareLoginPage.tsx +135 -135
- package/src/components/auth/ModeAwareSignupPage.tsx +267 -267
- package/src/components/auth/TraditionalAuthSection.tsx +99 -99
- package/src/components/recovery/CompleteStep.tsx +36 -36
- package/src/components/recovery/InitiateRecoveryStep.tsx +68 -68
- package/src/components/recovery/SelectMethodStep.tsx +73 -73
- package/src/components/recovery/SetPasswordStep.tsx +97 -97
- package/src/components/recovery/VerifyCodeStep.tsx +90 -90
- package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -160
- package/src/components/reserved/ReservedStatusBox.tsx +118 -118
- package/src/components/ui/BetaBadge.tsx +58 -58
- package/src/components/ui/Footer.tsx +93 -93
- package/src/config/env.ts +57 -57
- package/src/config/logger.ts +62 -62
- package/src/config/vibe-log-transport.ts +264 -264
- package/src/hooks/useAuth.ts +117 -117
- package/src/hooks/useAuthSettings.ts +97 -97
- package/src/hooks/useAvailableProviders.ts +120 -120
- package/src/hooks/usePasswordValidation.ts +127 -127
- package/src/hooks/usePublicAuthSettings.ts +149 -149
- package/src/hooks/useSessionExpiration.ts +101 -101
- package/src/hooks/useViabilitySession.ts +336 -336
- package/src/index.ts +60 -60
- package/src/lib/api-handler.ts +643 -643
- package/src/lib/app-slug.ts +178 -178
- package/src/lib/geolocation.ts +265 -265
- package/src/lib/idp-fetch.ts +110 -110
- package/src/lib/jwt-decode.ts +82 -82
- package/src/lib/roles.ts +177 -177
- package/src/lib/site-logger.ts +245 -245
- package/src/lib/standardized-client-api.ts +901 -901
- package/src/lib/test-aware-get-token.ts +41 -41
- package/src/lib/user-agent-parser.ts +252 -252
- package/src/logging/api/admin-analytics.ts +51 -51
- package/src/logging/api/audit-log.ts +53 -53
- package/src/logging/components/AdminAnalyticsLayout.tsx +49 -49
- package/src/logging/components/AuditLogViewer.tsx +125 -125
- package/src/logging/components/ErrorMetricsCard.tsx +98 -98
- package/src/logging/components/HealthMetricsCard.tsx +70 -70
- package/src/logging/hooks/useAdminAnalytics.ts +22 -22
- package/src/logging/hooks/useAuditLog.ts +24 -24
- package/src/logging/hooks/useErrorMetrics.ts +40 -40
- package/src/logging/hooks/useHealthMetrics.ts +44 -44
- package/src/logging/index.ts +18 -18
- package/src/logging/types/analytics.ts +81 -81
- package/src/logging/types/audit.ts +31 -31
- package/src/logging/types/index.ts +3 -3
- package/src/middleware/create-middleware.ts +663 -663
- package/src/middleware/rbac-check.ts +279 -279
- package/src/middleware/twofa-presets.ts +224 -224
- package/src/pages/admin-login/page.tsx +221 -221
- package/src/pages/admin-page-permissions/PagePermissionsAdminPage.tsx +527 -527
- package/src/pages/admin-page-permissions/index.ts +7 -7
- package/src/pages/admin-roles/RolesAdminPage.tsx +533 -533
- package/src/pages/admin-roles/modals.tsx +469 -469
- package/src/pages/client-admin/ClientSiteAdminPage.tsx +382 -382
- package/src/pages/client-admin/index.ts +33 -33
- package/src/pages/coming-soon/page.tsx +83 -83
- package/src/pages/login/page.tsx +456 -456
- package/src/pages/profile/EnhancedProfilePage.tsx +485 -485
- package/src/pages/profile/index.ts +9 -9
- package/src/pages/profile/page.tsx +166 -166
- package/src/pages/recovery/page.tsx +234 -234
- package/src/pages/roles/MyRolesPage.tsx +211 -211
- package/src/pages/roles/components.tsx +294 -294
- package/src/pages/roles/index.ts +17 -17
- package/src/pages/security/EnhancedSecurityPage.tsx +565 -565
- package/src/pages/security/index.ts +9 -9
- package/src/pages/security/page.tsx +507 -507
- package/src/pages/settings/EnhancedSettingsPage.tsx +642 -642
- package/src/pages/settings/index.ts +9 -9
- package/src/pages/settings/page.tsx +47 -47
- package/src/pages/showcase/ShowcasePage.tsx +532 -532
- package/src/pages/showcase/index.ts +13 -13
- package/src/pages/test-env/EmergencyLogoutPage.tsx +180 -180
- package/src/pages/test-env/JwtInspectPage.tsx +456 -456
- package/src/pages/test-env/RefreshTokenPage.tsx +157 -157
- package/src/pages/test-env/TestEnvPage.tsx +118 -118
- package/src/pages/test-env/index.ts +25 -25
- package/src/pages/verify-code/page.tsx +652 -652
- package/src/routes/account/update-phone.ts +13 -13
- package/src/routes/auth/logout.ts +108 -108
- package/src/routes/auth/nextauth.ts +45 -45
- package/src/routes/auth/settings.ts +75 -75
- package/src/routes/auth/viability.ts +224 -224
- package/src/server/auth-guard.ts +170 -170
- package/src/server/slim-middleware.ts +117 -117
- package/src/server/with-auth.ts +93 -93
- package/src/stores/authStore.ts +1899 -1899
- package/src/templates/instrumentation.ts +41 -41
- package/src/utils/logout.ts +30 -30
- package/src/vibe/client.ts +590 -590
- package/src/vibe/enterprise-auth.ts +208 -208
- package/src/vibe/errors.ts +185 -185
- package/src/vibe/generic.ts +431 -431
- package/src/vibe/hooks/index.ts +367 -367
- package/src/vibe/index.ts +132 -132
- package/src/vibe/sessions.ts +551 -551
- package/src/vibe/types.ts +577 -577
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
4
|
-
import { signalRActivityService, type HealthStatus } from '../services/signalrActivityService';
|
|
5
|
-
|
|
6
|
-
interface SignalRHealthCheckProps {
|
|
7
|
-
className?: string;
|
|
8
|
-
idpBaseUrl: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Simple health check component using SignalR connection state
|
|
13
|
-
* Following Occam's Razor: Connection alive = Service healthy, Connection dead = Service unhealthy
|
|
14
|
-
*/
|
|
15
|
-
export default function SignalRHealthCheck({ className = '', idpBaseUrl }: SignalRHealthCheckProps) {
|
|
16
|
-
// Allow disabling via env for noisy environments (e.g., production demos)
|
|
17
|
-
if (process.env.NEXT_PUBLIC_DISABLE_HEALTH_MONITOR === 'true') {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const [healthStatus, setHealthStatus] = useState<HealthStatus>({
|
|
22
|
-
isHealthy: false,
|
|
23
|
-
message: 'Initializing...',
|
|
24
|
-
lastHeartbeat: null,
|
|
25
|
-
connectionId: null
|
|
26
|
-
});
|
|
27
|
-
const [isInitializing, setIsInitializing] = useState(true);
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
let unsubscribe: (() => void) | null = null;
|
|
31
|
-
|
|
32
|
-
const initializeHealthService = async () => {
|
|
33
|
-
try {
|
|
34
|
-
// Subscribe to health status changes
|
|
35
|
-
unsubscribe = signalRActivityService.subscribe((status) => {
|
|
36
|
-
setHealthStatus(status);
|
|
37
|
-
setIsInitializing(false);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Start the health monitoring
|
|
41
|
-
await signalRActivityService.start(idpBaseUrl);
|
|
42
|
-
} catch (error) {
|
|
43
|
-
// Handle service unavailable gracefully without console spam
|
|
44
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
45
|
-
const isServiceDown = errorMessage.includes('ERR_CONNECTION_REFUSED') ||
|
|
46
|
-
errorMessage.includes('Failed to fetch');
|
|
47
|
-
|
|
48
|
-
if (isServiceDown) {
|
|
49
|
-
console.info('Health monitoring: Backend service unavailable');
|
|
50
|
-
setHealthStatus({
|
|
51
|
-
isHealthy: false,
|
|
52
|
-
message: 'Backend service offline',
|
|
53
|
-
lastHeartbeat: null,
|
|
54
|
-
connectionId: null
|
|
55
|
-
});
|
|
56
|
-
} else {
|
|
57
|
-
console.error('Failed to initialize SignalR health service:', error);
|
|
58
|
-
setHealthStatus({
|
|
59
|
-
isHealthy: false,
|
|
60
|
-
message: 'Failed to initialize health monitoring',
|
|
61
|
-
lastHeartbeat: null,
|
|
62
|
-
connectionId: null
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
setIsInitializing(false);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
initializeHealthService();
|
|
70
|
-
|
|
71
|
-
// Cleanup on unmount
|
|
72
|
-
return () => {
|
|
73
|
-
if (unsubscribe) {
|
|
74
|
-
unsubscribe();
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}, [idpBaseUrl]);
|
|
78
|
-
|
|
79
|
-
const getStatusColor = () => {
|
|
80
|
-
if (isInitializing) return 'text-yellow-600';
|
|
81
|
-
return healthStatus.isHealthy ? 'text-green-600' : 'text-orange-600'; // Orange instead of alarming red
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const getStatusIcon = () => {
|
|
85
|
-
if (isInitializing) return '🔄';
|
|
86
|
-
return healthStatus.isHealthy ? '✅' : '🔶'; // Orange diamond instead of scary red X
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const getStatusMessage = () => {
|
|
90
|
-
if (isInitializing) return 'Connecting to service...';
|
|
91
|
-
return healthStatus.message;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const formatLastHeartbeat = () => {
|
|
95
|
-
if (!healthStatus.lastHeartbeat) return null;
|
|
96
|
-
const now = new Date();
|
|
97
|
-
const diff = Math.floor((now.getTime() - healthStatus.lastHeartbeat.getTime()) / 1000);
|
|
98
|
-
|
|
99
|
-
if (diff < 60) return `${diff}s ago`;
|
|
100
|
-
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
|
|
101
|
-
return `${Math.floor(diff / 3600)}h ago`;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<div className={`flex items-center space-x-2 ${className}`}>
|
|
106
|
-
<span className="text-lg" role="img" aria-label="status">
|
|
107
|
-
{getStatusIcon()}
|
|
108
|
-
</span>
|
|
109
|
-
|
|
110
|
-
<div className="flex flex-col">
|
|
111
|
-
<span className={`text-sm font-medium ${getStatusColor()}`}>
|
|
112
|
-
{getStatusMessage()}
|
|
113
|
-
</span>
|
|
114
|
-
|
|
115
|
-
{healthStatus.lastHeartbeat && (
|
|
116
|
-
<span className="text-xs text-gray-500">
|
|
117
|
-
Last heartbeat: {formatLastHeartbeat()}
|
|
118
|
-
</span>
|
|
119
|
-
)}
|
|
120
|
-
|
|
121
|
-
{/* Uncomment for SignalR debugging:
|
|
122
|
-
{process.env.NODE_ENV === 'development' && healthStatus.connectionId && (
|
|
123
|
-
<span className="text-xs text-gray-400 font-mono">
|
|
124
|
-
Connection: {healthStatus.connectionId.substring(0, 8)}...
|
|
125
|
-
</span>
|
|
126
|
-
)}
|
|
127
|
-
*/}
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { signalRActivityService, type HealthStatus } from '../services/signalrActivityService';
|
|
5
|
+
|
|
6
|
+
interface SignalRHealthCheckProps {
|
|
7
|
+
className?: string;
|
|
8
|
+
idpBaseUrl: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Simple health check component using SignalR connection state
|
|
13
|
+
* Following Occam's Razor: Connection alive = Service healthy, Connection dead = Service unhealthy
|
|
14
|
+
*/
|
|
15
|
+
export default function SignalRHealthCheck({ className = '', idpBaseUrl }: SignalRHealthCheckProps) {
|
|
16
|
+
// Allow disabling via env for noisy environments (e.g., production demos)
|
|
17
|
+
if (process.env.NEXT_PUBLIC_DISABLE_HEALTH_MONITOR === 'true') {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const [healthStatus, setHealthStatus] = useState<HealthStatus>({
|
|
22
|
+
isHealthy: false,
|
|
23
|
+
message: 'Initializing...',
|
|
24
|
+
lastHeartbeat: null,
|
|
25
|
+
connectionId: null
|
|
26
|
+
});
|
|
27
|
+
const [isInitializing, setIsInitializing] = useState(true);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
let unsubscribe: (() => void) | null = null;
|
|
31
|
+
|
|
32
|
+
const initializeHealthService = async () => {
|
|
33
|
+
try {
|
|
34
|
+
// Subscribe to health status changes
|
|
35
|
+
unsubscribe = signalRActivityService.subscribe((status) => {
|
|
36
|
+
setHealthStatus(status);
|
|
37
|
+
setIsInitializing(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Start the health monitoring
|
|
41
|
+
await signalRActivityService.start(idpBaseUrl);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
// Handle service unavailable gracefully without console spam
|
|
44
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
45
|
+
const isServiceDown = errorMessage.includes('ERR_CONNECTION_REFUSED') ||
|
|
46
|
+
errorMessage.includes('Failed to fetch');
|
|
47
|
+
|
|
48
|
+
if (isServiceDown) {
|
|
49
|
+
console.info('Health monitoring: Backend service unavailable');
|
|
50
|
+
setHealthStatus({
|
|
51
|
+
isHealthy: false,
|
|
52
|
+
message: 'Backend service offline',
|
|
53
|
+
lastHeartbeat: null,
|
|
54
|
+
connectionId: null
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
console.error('Failed to initialize SignalR health service:', error);
|
|
58
|
+
setHealthStatus({
|
|
59
|
+
isHealthy: false,
|
|
60
|
+
message: 'Failed to initialize health monitoring',
|
|
61
|
+
lastHeartbeat: null,
|
|
62
|
+
connectionId: null
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
setIsInitializing(false);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
initializeHealthService();
|
|
70
|
+
|
|
71
|
+
// Cleanup on unmount
|
|
72
|
+
return () => {
|
|
73
|
+
if (unsubscribe) {
|
|
74
|
+
unsubscribe();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}, [idpBaseUrl]);
|
|
78
|
+
|
|
79
|
+
const getStatusColor = () => {
|
|
80
|
+
if (isInitializing) return 'text-yellow-600';
|
|
81
|
+
return healthStatus.isHealthy ? 'text-green-600' : 'text-orange-600'; // Orange instead of alarming red
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const getStatusIcon = () => {
|
|
85
|
+
if (isInitializing) return '🔄';
|
|
86
|
+
return healthStatus.isHealthy ? '✅' : '🔶'; // Orange diamond instead of scary red X
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const getStatusMessage = () => {
|
|
90
|
+
if (isInitializing) return 'Connecting to service...';
|
|
91
|
+
return healthStatus.message;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const formatLastHeartbeat = () => {
|
|
95
|
+
if (!healthStatus.lastHeartbeat) return null;
|
|
96
|
+
const now = new Date();
|
|
97
|
+
const diff = Math.floor((now.getTime() - healthStatus.lastHeartbeat.getTime()) / 1000);
|
|
98
|
+
|
|
99
|
+
if (diff < 60) return `${diff}s ago`;
|
|
100
|
+
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
|
|
101
|
+
return `${Math.floor(diff / 3600)}h ago`;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div className={`flex items-center space-x-2 ${className}`}>
|
|
106
|
+
<span className="text-lg" role="img" aria-label="status">
|
|
107
|
+
{getStatusIcon()}
|
|
108
|
+
</span>
|
|
109
|
+
|
|
110
|
+
<div className="flex flex-col">
|
|
111
|
+
<span className={`text-sm font-medium ${getStatusColor()}`}>
|
|
112
|
+
{getStatusMessage()}
|
|
113
|
+
</span>
|
|
114
|
+
|
|
115
|
+
{healthStatus.lastHeartbeat && (
|
|
116
|
+
<span className="text-xs text-gray-500">
|
|
117
|
+
Last heartbeat: {formatLastHeartbeat()}
|
|
118
|
+
</span>
|
|
119
|
+
)}
|
|
120
|
+
|
|
121
|
+
{/* Uncomment for SignalR debugging:
|
|
122
|
+
{process.env.NODE_ENV === 'development' && healthStatus.connectionId && (
|
|
123
|
+
<span className="text-xs text-gray-400 font-mono">
|
|
124
|
+
Connection: {healthStatus.connectionId.substring(0, 8)}...
|
|
125
|
+
</span>
|
|
126
|
+
)}
|
|
127
|
+
*/}
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|