@payez/next-mvp 4.1.10 → 4.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-handlers/account/profile.d.ts +38 -0
- package/dist/api-handlers/account/profile.js +73 -45
- package/dist/api-handlers/account/recovery/send-code.d.ts +33 -0
- package/dist/api-handlers/account/recovery/send-code.js +52 -18
- package/dist/api-handlers/account/recovery/verify-code.d.ts +33 -0
- package/dist/api-handlers/account/recovery/verify-code.js +52 -18
- package/dist/api-handlers/account/verify-email.js +15 -1
- package/dist/api-handlers/account/verify-sms.js +15 -1
- package/dist/api-handlers/auth/passkey-signin.d.ts +29 -0
- package/dist/api-handlers/auth/passkey-signin.js +97 -0
- package/dist/api-handlers/mfa/backup-code-verify.d.ts +73 -0
- package/dist/api-handlers/mfa/backup-code-verify.js +153 -0
- package/dist/api-handlers/mfa/backup-codes.d.ts +7 -0
- package/dist/api-handlers/mfa/backup-codes.js +40 -0
- package/dist/api-handlers/mfa/methods.d.ts +3 -0
- package/dist/api-handlers/mfa/methods.js +41 -0
- package/dist/api-handlers/mfa/totp-confirm.d.ts +8 -0
- package/dist/api-handlers/mfa/totp-confirm.js +41 -0
- package/dist/api-handlers/mfa/totp-enroll.d.ts +8 -0
- package/dist/api-handlers/mfa/totp-enroll.js +41 -0
- package/dist/api-handlers/mfa/totp-verify.d.ts +47 -0
- package/dist/api-handlers/mfa/totp-verify.js +134 -0
- package/dist/api-handlers/passkeys/list.d.ts +7 -0
- package/dist/api-handlers/passkeys/list.js +29 -0
- package/dist/api-handlers/passkeys/manage.d.ts +3 -0
- package/dist/api-handlers/passkeys/manage.js +54 -0
- package/dist/api-handlers/passkeys/register-options.d.ts +8 -0
- package/dist/api-handlers/passkeys/register-options.js +41 -0
- package/dist/api-handlers/passkeys/register-verify.d.ts +7 -0
- package/dist/api-handlers/passkeys/register-verify.js +40 -0
- package/dist/api-handlers/session/viability.js +19 -0
- package/dist/auth/better-auth.d.ts +68 -5
- package/dist/auth/better-auth.js +271 -45
- package/dist/auth/utils/idp-client.d.ts +13 -22
- package/dist/auth/utils/idp-client.js +12 -82
- package/dist/client/better-auth-client.d.ts +14 -2
- package/dist/lib/ensure-fresh-access-token.js +13 -2
- package/dist/lib/session-store.js +28 -21
- package/dist/lib/startup-init.js +19 -19
- package/dist/lib/token-lifecycle.d.ts +2 -0
- package/dist/lib/token-lifecycle.js +61 -7
- package/dist/models/SessionModel.d.ts +17 -0
- package/dist/pages/login/page.d.ts +10 -1
- package/dist/pages/login/page.js +69 -80
- package/dist/pages/verify-code/page.d.ts +10 -1
- package/dist/pages/verify-code/page.js +72 -4
- package/dist/routes/auth/passkey-signin.d.ts +13 -0
- package/dist/routes/auth/passkey-signin.js +18 -0
- package/dist/routes/auth/viability.d.ts +2 -0
- package/dist/routes/auth/viability.js +88 -0
- package/dist/routes/mfa/backup-code-verify.d.ts +1 -0
- package/dist/routes/mfa/backup-code-verify.js +5 -0
- package/dist/routes/mfa/backup-codes.d.ts +10 -0
- package/dist/routes/mfa/backup-codes.js +14 -0
- package/dist/routes/mfa/methods.d.ts +21 -0
- package/dist/routes/mfa/methods.js +10 -0
- package/dist/routes/mfa/totp-confirm.d.ts +10 -0
- package/dist/routes/mfa/totp-confirm.js +14 -0
- package/dist/routes/mfa/totp-enroll.d.ts +10 -0
- package/dist/routes/mfa/totp-enroll.js +14 -0
- package/dist/routes/mfa/totp-verify.d.ts +14 -0
- package/dist/routes/mfa/totp-verify.js +18 -0
- package/dist/routes/passkeys/list.d.ts +10 -0
- package/dist/routes/passkeys/list.js +14 -0
- package/dist/routes/passkeys/manage.d.ts +18 -0
- package/dist/routes/passkeys/manage.js +13 -0
- package/dist/routes/passkeys/register-options.d.ts +10 -0
- package/dist/routes/passkeys/register-options.js +14 -0
- package/dist/routes/passkeys/register-verify.d.ts +10 -0
- package/dist/routes/passkeys/register-verify.js +14 -0
- package/dist/server/auth.d.ts +2 -2
- package/dist/server/decode-session.js +37 -3
- package/package.json +958 -893
- package/scripts/check-internal-url-usage.sh +73 -73
- package/src/api/index.ts +17 -17
- package/src/api-handlers/account/masked-info.ts +45 -45
- package/src/api-handlers/account/profile.ts +99 -80
- package/src/api-handlers/account/recovery/initiate.ts +23 -23
- package/src/api-handlers/account/recovery/send-code.ts +73 -25
- package/src/api-handlers/account/recovery/verify-code.ts +73 -25
- package/src/api-handlers/account/reset-password.ts +23 -23
- package/src/api-handlers/account/send-code.ts +76 -76
- package/src/api-handlers/account/validate-password.ts +118 -118
- package/src/api-handlers/account/verify-email.ts +15 -1
- package/src/api-handlers/account/verify-sms.ts +15 -1
- package/src/api-handlers/admin/stats.ts +249 -249
- package/src/api-handlers/anon/preferences.ts +123 -123
- package/src/api-handlers/auth/jwks.ts +20 -20
- package/src/api-handlers/auth/login.ts +240 -240
- package/src/api-handlers/auth/passkey-signin.ts +98 -0
- package/src/api-handlers/auth/validate.ts +43 -43
- package/src/api-handlers/mfa/backup-code-verify.ts +175 -0
- package/src/api-handlers/mfa/backup-codes.ts +41 -0
- package/src/api-handlers/mfa/methods.ts +46 -0
- package/src/api-handlers/mfa/totp-confirm.ts +42 -0
- package/src/api-handlers/mfa/totp-enroll.ts +42 -0
- package/src/api-handlers/mfa/totp-verify.ts +156 -0
- package/src/api-handlers/passkeys/list.ts +31 -0
- package/src/api-handlers/passkeys/manage.ts +54 -0
- package/src/api-handlers/passkeys/register-options.ts +42 -0
- package/src/api-handlers/passkeys/register-verify.ts +41 -0
- package/src/api-handlers/session/viability.ts +161 -142
- package/src/auth/better-auth.ts +708 -455
- package/src/auth/unauthenticated-routes.ts +2 -2
- package/src/auth/utils/idp-client.ts +13 -95
- package/src/client/better-auth-client.ts +70 -70
- package/src/client/fetchWithSession.ts +21 -21
- package/src/client/index.ts +13 -13
- package/src/client/useAnonSession.ts +131 -131
- package/src/components/admin/VibeAdminContext.tsx +87 -87
- package/src/config/logging-config.ts +82 -82
- package/src/config/unauthenticated-routes.ts +19 -19
- package/src/edge/internal-api-url.ts +65 -65
- package/src/edge/middleware.ts +42 -42
- package/src/hooks/useProfile.ts +75 -75
- package/src/lib/anon-session.ts +213 -213
- package/src/lib/auth-secret.ts +137 -137
- package/src/lib/demo-mode.ts +17 -17
- package/src/lib/ensure-fresh-access-token.ts +13 -2
- package/src/lib/idp-client-config.ts +559 -559
- package/src/lib/idp-fetch.ts +126 -126
- package/src/lib/internal-api.ts +171 -171
- package/src/lib/jwt-decode-client.ts +45 -45
- package/src/lib/rate-limit-service.ts +9 -9
- package/src/lib/redis.ts +26 -26
- package/src/lib/refresh-token-validator.ts +64 -64
- package/src/lib/secret-validation.ts +8 -8
- package/src/lib/session-store.ts +702 -695
- package/src/lib/session.ts +34 -34
- package/src/lib/startup-init.ts +251 -251
- package/src/lib/token-expiry.ts +40 -40
- package/src/lib/token-lifecycle.ts +533 -470
- package/src/lib/types/api-responses.ts +336 -336
- package/src/middleware/auth-decision.ts +43 -43
- package/src/models/DecodedAccessToken.ts +16 -16
- package/src/models/SessionModel.ts +282 -264
- package/src/pages/admin-roles/index.ts +9 -9
- package/src/pages/login/page.tsx +123 -228
- package/src/pages/security/EnhancedSecurityPage.tsx +9 -9
- package/src/pages/verify-code/page.tsx +71 -5
- package/src/routes/account/index.ts +31 -31
- package/src/routes/account/masked-info.ts +36 -36
- package/src/routes/account/send-code.ts +39 -39
- package/src/routes/account/verify-email.ts +40 -40
- package/src/routes/account/verify-sms.ts +40 -40
- package/src/routes/auth/index.ts +22 -22
- package/src/routes/auth/passkey-signin.ts +13 -0
- package/src/routes/auth/refresh.ts +48 -48
- package/src/routes/auth/session.ts +166 -166
- package/src/routes/auth/viability.ts +89 -0
- package/src/routes/index.ts +17 -17
- package/src/routes/mfa/backup-code-verify.ts +1 -0
- package/src/routes/mfa/backup-codes.ts +10 -0
- package/src/routes/mfa/methods.ts +22 -0
- package/src/routes/mfa/totp-confirm.ts +10 -0
- package/src/routes/mfa/totp-enroll.ts +10 -0
- package/src/routes/mfa/totp-verify.ts +14 -0
- package/src/routes/passkeys/list.ts +10 -0
- package/src/routes/passkeys/manage.ts +23 -0
- package/src/routes/passkeys/register-options.ts +10 -0
- package/src/routes/passkeys/register-verify.ts +10 -0
- package/src/routes/session/index.ts +7 -7
- package/src/routes/session/refresh-viability.ts +17 -17
- package/src/server/auth.ts +373 -373
- package/src/server/decode-session.ts +235 -202
- package/src/services/signalrActivityService.ts +258 -258
- package/src/theme/ThemeProvider.tsx +39 -39
- package/src/theme/default.ts +33 -33
- package/src/theme/index.ts +31 -31
- package/src/theme/types.ts +69 -69
- package/src/theme/useTheme.ts +57 -57
- package/src/theme/utils.ts +40 -40
- package/src/types/api.ts +12 -12
- package/src/types/auth.d.ts +23 -23
- package/src/types/auth.ts +22 -22
- package/src/types/logging.ts +11 -11
- package/src/types/recovery.ts +54 -54
- package/src/utils/api.ts +353 -353
- package/src/utils/circuitBreaker.ts +40 -40
- package/src/utils/error-message.ts +108 -108
- package/src/utils/layout/reservedSpace.ts +124 -124
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { createContext, useContext, ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
// -----------------------------------------------------------------------------
|
|
6
|
-
// TYPES
|
|
7
|
-
// -----------------------------------------------------------------------------
|
|
8
|
-
|
|
9
|
-
export interface VibeAdminConfig {
|
|
10
|
-
/** Collection name for this tenant (e.g., "ideal_resume", "idealvibe_app") */
|
|
11
|
-
collectionName: string;
|
|
12
|
-
/** Display name for the app (e.g., "IdealResume", "IdealVibe") */
|
|
13
|
-
appName: string;
|
|
14
|
-
/** Optional logo URL */
|
|
15
|
-
logoUrl?: string;
|
|
16
|
-
/** Base path for admin routes (default: /vibe-admin) */
|
|
17
|
-
basePath?: string;
|
|
18
|
-
/** Custom tabs to add to the admin panel */
|
|
19
|
-
customTabs?: AdminTab[];
|
|
20
|
-
/** Theme mode override */
|
|
21
|
-
isDarkMode?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface AdminTab {
|
|
25
|
-
id: string;
|
|
26
|
-
label: string;
|
|
27
|
-
icon?: React.ElementType;
|
|
28
|
-
component: React.ComponentType;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface VibeAdminContextValue extends VibeAdminConfig {
|
|
32
|
-
/** All tabs including defaults and custom */
|
|
33
|
-
allTabs: AdminTab[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// -----------------------------------------------------------------------------
|
|
37
|
-
// CONTEXT
|
|
38
|
-
// -----------------------------------------------------------------------------
|
|
39
|
-
|
|
40
|
-
const VibeAdminContext = createContext<VibeAdminContextValue | null>(null);
|
|
41
|
-
|
|
42
|
-
// -----------------------------------------------------------------------------
|
|
43
|
-
// HOOK
|
|
44
|
-
// -----------------------------------------------------------------------------
|
|
45
|
-
|
|
46
|
-
export function useVibeAdmin(): VibeAdminContextValue {
|
|
47
|
-
const context = useContext(VibeAdminContext);
|
|
48
|
-
if (!context) {
|
|
49
|
-
throw new Error('useVibeAdmin must be used within a VibeAdminProvider');
|
|
50
|
-
}
|
|
51
|
-
return context;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// -----------------------------------------------------------------------------
|
|
55
|
-
// PROVIDER
|
|
56
|
-
// -----------------------------------------------------------------------------
|
|
57
|
-
|
|
58
|
-
interface VibeAdminProviderProps {
|
|
59
|
-
config: VibeAdminConfig;
|
|
60
|
-
children: ReactNode;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function VibeAdminProvider({ config, children }: VibeAdminProviderProps) {
|
|
64
|
-
// Default tabs - will be populated with actual components
|
|
65
|
-
const defaultTabs: AdminTab[] = [
|
|
66
|
-
{ id: 'stats', label: 'Stats', component: () => null },
|
|
67
|
-
{ id: 'users', label: 'Users', component: () => null },
|
|
68
|
-
{ id: 'sessions', label: 'Sessions', component: () => null },
|
|
69
|
-
{ id: 'analytics', label: 'Analytics', component: () => null },
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
const allTabs = [...defaultTabs, ...(config.customTabs || [])];
|
|
73
|
-
|
|
74
|
-
const value: VibeAdminContextValue = {
|
|
75
|
-
...config,
|
|
76
|
-
basePath: config.basePath || '/vibe-admin',
|
|
77
|
-
allTabs,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<VibeAdminContext.Provider value={value}>
|
|
82
|
-
{children}
|
|
83
|
-
</VibeAdminContext.Provider>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export default VibeAdminProvider;
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
// -----------------------------------------------------------------------------
|
|
6
|
+
// TYPES
|
|
7
|
+
// -----------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
export interface VibeAdminConfig {
|
|
10
|
+
/** Collection name for this tenant (e.g., "ideal_resume", "idealvibe_app") */
|
|
11
|
+
collectionName: string;
|
|
12
|
+
/** Display name for the app (e.g., "IdealResume", "IdealVibe") */
|
|
13
|
+
appName: string;
|
|
14
|
+
/** Optional logo URL */
|
|
15
|
+
logoUrl?: string;
|
|
16
|
+
/** Base path for admin routes (default: /vibe-admin) */
|
|
17
|
+
basePath?: string;
|
|
18
|
+
/** Custom tabs to add to the admin panel */
|
|
19
|
+
customTabs?: AdminTab[];
|
|
20
|
+
/** Theme mode override */
|
|
21
|
+
isDarkMode?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AdminTab {
|
|
25
|
+
id: string;
|
|
26
|
+
label: string;
|
|
27
|
+
icon?: React.ElementType;
|
|
28
|
+
component: React.ComponentType;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface VibeAdminContextValue extends VibeAdminConfig {
|
|
32
|
+
/** All tabs including defaults and custom */
|
|
33
|
+
allTabs: AdminTab[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// -----------------------------------------------------------------------------
|
|
37
|
+
// CONTEXT
|
|
38
|
+
// -----------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
const VibeAdminContext = createContext<VibeAdminContextValue | null>(null);
|
|
41
|
+
|
|
42
|
+
// -----------------------------------------------------------------------------
|
|
43
|
+
// HOOK
|
|
44
|
+
// -----------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
export function useVibeAdmin(): VibeAdminContextValue {
|
|
47
|
+
const context = useContext(VibeAdminContext);
|
|
48
|
+
if (!context) {
|
|
49
|
+
throw new Error('useVibeAdmin must be used within a VibeAdminProvider');
|
|
50
|
+
}
|
|
51
|
+
return context;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// -----------------------------------------------------------------------------
|
|
55
|
+
// PROVIDER
|
|
56
|
+
// -----------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
interface VibeAdminProviderProps {
|
|
59
|
+
config: VibeAdminConfig;
|
|
60
|
+
children: ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function VibeAdminProvider({ config, children }: VibeAdminProviderProps) {
|
|
64
|
+
// Default tabs - will be populated with actual components
|
|
65
|
+
const defaultTabs: AdminTab[] = [
|
|
66
|
+
{ id: 'stats', label: 'Stats', component: () => null },
|
|
67
|
+
{ id: 'users', label: 'Users', component: () => null },
|
|
68
|
+
{ id: 'sessions', label: 'Sessions', component: () => null },
|
|
69
|
+
{ id: 'analytics', label: 'Analytics', component: () => null },
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const allTabs = [...defaultTabs, ...(config.customTabs || [])];
|
|
73
|
+
|
|
74
|
+
const value: VibeAdminContextValue = {
|
|
75
|
+
...config,
|
|
76
|
+
basePath: config.basePath || '/vibe-admin',
|
|
77
|
+
allTabs,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<VibeAdminContext.Provider value={value}>
|
|
82
|
+
{children}
|
|
83
|
+
</VibeAdminContext.Provider>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default VibeAdminProvider;
|
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import { promises as fs } from 'fs';
|
|
2
|
-
import { watch, existsSync } from 'fs';
|
|
3
|
-
import { LoggingConfig, LogLevel } from '../types/logging';
|
|
4
|
-
|
|
5
|
-
const isEdgeRuntime = typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
|
|
6
|
-
|
|
7
|
-
class LoggingConfigManager {
|
|
8
|
-
private config: LoggingConfig | null = null;
|
|
9
|
-
private configPath: string;
|
|
10
|
-
private watchers: Set<(config: LoggingConfig) => void> = new Set();
|
|
11
|
-
private fileWatcher: ReturnType<typeof watch> | null = null;
|
|
12
|
-
private isEdgeRuntime: boolean;
|
|
13
|
-
private isBrowser: boolean;
|
|
14
|
-
|
|
15
|
-
constructor() {
|
|
16
|
-
this.isBrowser = typeof window !== 'undefined';
|
|
17
|
-
this.isEdgeRuntime = typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
|
|
18
|
-
if (this.isEdgeRuntime || this.isBrowser) {
|
|
19
|
-
this.configPath = '/config/logging.json';
|
|
20
|
-
this.config = this.getDefaultConfig();
|
|
21
|
-
} else {
|
|
22
|
-
const cwd = process.cwd().replace(/\\/g, '/');
|
|
23
|
-
this.configPath = cwd + '/config/logging.json';
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async loadConfig(): Promise<LoggingConfig> {
|
|
28
|
-
if (this.isEdgeRuntime || this.isBrowser) {
|
|
29
|
-
if (!this.config) { this.config = this.getDefaultConfig(); }
|
|
30
|
-
return this.config;
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
const configContent = await fs.readFile(this.configPath, 'utf-8');
|
|
34
|
-
const rawConfig = JSON.parse(configContent);
|
|
35
|
-
const config = this.validateAndMergeConfig(rawConfig);
|
|
36
|
-
this.config = config; this.notifyWatchers(config); return config;
|
|
37
|
-
} catch (error) {
|
|
38
|
-
console.warn(`Failed to load logging config from ${this.configPath}:`, error);
|
|
39
|
-
return this.getDefaultConfig();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async getConfig(): Promise<LoggingConfig> { if (!this.config) { return await this.loadConfig(); } return this.config; }
|
|
44
|
-
getConfigSync(): LoggingConfig { return this.config || this.getDefaultConfig(); }
|
|
45
|
-
|
|
46
|
-
startWatching(): void { if (this.isEdgeRuntime || this.isBrowser) { return; } if (this.fileWatcher) { return; } try { if (!existsSync(this.configPath)) { console.warn(`Logging config file not found at ${this.configPath} — watch disabled`); return; } this.fileWatcher = watch(this.configPath, { persistent: false }, (eventType) => { if (eventType === 'change') { this.loadConfig().catch(console.error); } }); } catch (error) { console.warn('Failed to start watching logging config file:', error); } }
|
|
47
|
-
stopWatching(): void { if (this.isEdgeRuntime || this.isBrowser) { return; } if (this.fileWatcher) { this.fileWatcher.close(); this.fileWatcher = null; } }
|
|
48
|
-
addWatcher(callback: (config: LoggingConfig) => void): void { this.watchers.add(callback); }
|
|
49
|
-
removeWatcher(callback: (config: LoggingConfig) => void): void { this.watchers.delete(callback); }
|
|
50
|
-
private notifyWatchers(config: LoggingConfig): void { this.watchers.forEach(cb => { try { cb(config); } catch (error) { console.error('Error in logging config watcher:', error); } }); }
|
|
51
|
-
|
|
52
|
-
private validateAndMergeConfig(rawConfig: any): LoggingConfig {
|
|
53
|
-
const defaults = this.getDefaultConfig();
|
|
54
|
-
const config: LoggingConfig = {
|
|
55
|
-
logLevel: this.validateLogLevel(rawConfig.logLevel) || this.validateLogLevel(process.env.LOG_LEVEL) || defaults.logLevel,
|
|
56
|
-
console: { enabled: rawConfig.console?.enabled ?? (process.env.LOG_CONSOLE === 'true' || process.env.NODE_ENV === 'development'), colors: rawConfig.console?.colors ?? defaults.console.colors },
|
|
57
|
-
graylog: { enabled: false, host: defaults.graylog.host, port: defaults.graylog.port, facility: defaults.graylog.facility, staticMeta: { ...defaults.graylog.staticMeta } },
|
|
58
|
-
components: { ...defaults.components, ...rawConfig.components },
|
|
59
|
-
levels: { ...defaults.levels, ...rawConfig.levels }
|
|
60
|
-
};
|
|
61
|
-
return config;
|
|
62
|
-
}
|
|
63
|
-
private validateLogLevel(level: any): LogLevel | null { const validLevels: LogLevel[] = ['error', 'warn', 'info', 'http', 'debug']; return validLevels.includes(level) ? level : null; }
|
|
64
|
-
private getHostname(): string { if (this.isEdgeRuntime) return 'edge-runtime'; if (this.isBrowser) return 'browser-client'; try { return require('os').hostname(); } catch { return 'unknown'; } }
|
|
65
|
-
private getDefaultConfig(): LoggingConfig {
|
|
66
|
-
return {
|
|
67
|
-
logLevel: 'info',
|
|
68
|
-
console: { enabled: process.env.NODE_ENV === 'development', colors: true },
|
|
69
|
-
graylog: { enabled: false, host: '127.0.0.1', port: 12201, facility: 'next-mvp', staticMeta: { service: 'next-mvp', application: 'next-mvp', version: '1.0.0', environment: process.env.NODE_ENV || 'development', hostname: this.getHostname(), instance: process.env.NEXT_INSTANCE_ID || 'unknown' } },
|
|
70
|
-
components: { auth: { enabled: true, prefix: '[AUTH]' }, idp: { enabled: true, prefix: '[IDP]' }, api: { enabled: true, prefix: '[API]' }, circuitBreaker: { enabled: true, prefix: '[CIRCUIT-BREAKER]' }, token: { enabled: true, prefix: '[TOKEN]' }, tokenSync: { enabled: true, prefix: '[TOKEN-SYNC]' }, tokenRefresh: { enabled: true, prefix: '[TOKEN-REFRESH]' }, redis: { enabled: true, prefix: '[REDIS]' } },
|
|
71
|
-
levels: { error: 0, warn: 1, info: 2, http: 3, debug: 4 }
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export const loggingConfigManager = new LoggingConfigManager();
|
|
77
|
-
export const getLoggingConfig = () => loggingConfigManager.getConfig();
|
|
78
|
-
export const getLoggingConfigSync = () => loggingConfigManager.getConfigSync();
|
|
79
|
-
export const startConfigWatching = () => loggingConfigManager.startWatching();
|
|
80
|
-
export const stopConfigWatching = () => loggingConfigManager.stopWatching();
|
|
81
|
-
export const addConfigWatcher = (callback: (config: LoggingConfig) => void) => loggingConfigManager.addWatcher(callback);
|
|
82
|
-
export const removeConfigWatcher = (callback: (config: LoggingConfig) => void) => loggingConfigManager.removeWatcher(callback);
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { watch, existsSync } from 'fs';
|
|
3
|
+
import { LoggingConfig, LogLevel } from '../types/logging';
|
|
4
|
+
|
|
5
|
+
const isEdgeRuntime = typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
|
|
6
|
+
|
|
7
|
+
class LoggingConfigManager {
|
|
8
|
+
private config: LoggingConfig | null = null;
|
|
9
|
+
private configPath: string;
|
|
10
|
+
private watchers: Set<(config: LoggingConfig) => void> = new Set();
|
|
11
|
+
private fileWatcher: ReturnType<typeof watch> | null = null;
|
|
12
|
+
private isEdgeRuntime: boolean;
|
|
13
|
+
private isBrowser: boolean;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
this.isBrowser = typeof window !== 'undefined';
|
|
17
|
+
this.isEdgeRuntime = typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
|
|
18
|
+
if (this.isEdgeRuntime || this.isBrowser) {
|
|
19
|
+
this.configPath = '/config/logging.json';
|
|
20
|
+
this.config = this.getDefaultConfig();
|
|
21
|
+
} else {
|
|
22
|
+
const cwd = process.cwd().replace(/\\/g, '/');
|
|
23
|
+
this.configPath = cwd + '/config/logging.json';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async loadConfig(): Promise<LoggingConfig> {
|
|
28
|
+
if (this.isEdgeRuntime || this.isBrowser) {
|
|
29
|
+
if (!this.config) { this.config = this.getDefaultConfig(); }
|
|
30
|
+
return this.config;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const configContent = await fs.readFile(this.configPath, 'utf-8');
|
|
34
|
+
const rawConfig = JSON.parse(configContent);
|
|
35
|
+
const config = this.validateAndMergeConfig(rawConfig);
|
|
36
|
+
this.config = config; this.notifyWatchers(config); return config;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.warn(`Failed to load logging config from ${this.configPath}:`, error);
|
|
39
|
+
return this.getDefaultConfig();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async getConfig(): Promise<LoggingConfig> { if (!this.config) { return await this.loadConfig(); } return this.config; }
|
|
44
|
+
getConfigSync(): LoggingConfig { return this.config || this.getDefaultConfig(); }
|
|
45
|
+
|
|
46
|
+
startWatching(): void { if (this.isEdgeRuntime || this.isBrowser) { return; } if (this.fileWatcher) { return; } try { if (!existsSync(this.configPath)) { console.warn(`Logging config file not found at ${this.configPath} — watch disabled`); return; } this.fileWatcher = watch(this.configPath, { persistent: false }, (eventType) => { if (eventType === 'change') { this.loadConfig().catch(console.error); } }); } catch (error) { console.warn('Failed to start watching logging config file:', error); } }
|
|
47
|
+
stopWatching(): void { if (this.isEdgeRuntime || this.isBrowser) { return; } if (this.fileWatcher) { this.fileWatcher.close(); this.fileWatcher = null; } }
|
|
48
|
+
addWatcher(callback: (config: LoggingConfig) => void): void { this.watchers.add(callback); }
|
|
49
|
+
removeWatcher(callback: (config: LoggingConfig) => void): void { this.watchers.delete(callback); }
|
|
50
|
+
private notifyWatchers(config: LoggingConfig): void { this.watchers.forEach(cb => { try { cb(config); } catch (error) { console.error('Error in logging config watcher:', error); } }); }
|
|
51
|
+
|
|
52
|
+
private validateAndMergeConfig(rawConfig: any): LoggingConfig {
|
|
53
|
+
const defaults = this.getDefaultConfig();
|
|
54
|
+
const config: LoggingConfig = {
|
|
55
|
+
logLevel: this.validateLogLevel(rawConfig.logLevel) || this.validateLogLevel(process.env.LOG_LEVEL) || defaults.logLevel,
|
|
56
|
+
console: { enabled: rawConfig.console?.enabled ?? (process.env.LOG_CONSOLE === 'true' || process.env.NODE_ENV === 'development'), colors: rawConfig.console?.colors ?? defaults.console.colors },
|
|
57
|
+
graylog: { enabled: false, host: defaults.graylog.host, port: defaults.graylog.port, facility: defaults.graylog.facility, staticMeta: { ...defaults.graylog.staticMeta } },
|
|
58
|
+
components: { ...defaults.components, ...rawConfig.components },
|
|
59
|
+
levels: { ...defaults.levels, ...rawConfig.levels }
|
|
60
|
+
};
|
|
61
|
+
return config;
|
|
62
|
+
}
|
|
63
|
+
private validateLogLevel(level: any): LogLevel | null { const validLevels: LogLevel[] = ['error', 'warn', 'info', 'http', 'debug']; return validLevels.includes(level) ? level : null; }
|
|
64
|
+
private getHostname(): string { if (this.isEdgeRuntime) return 'edge-runtime'; if (this.isBrowser) return 'browser-client'; try { return require('os').hostname(); } catch { return 'unknown'; } }
|
|
65
|
+
private getDefaultConfig(): LoggingConfig {
|
|
66
|
+
return {
|
|
67
|
+
logLevel: 'info',
|
|
68
|
+
console: { enabled: process.env.NODE_ENV === 'development', colors: true },
|
|
69
|
+
graylog: { enabled: false, host: '127.0.0.1', port: 12201, facility: 'next-mvp', staticMeta: { service: 'next-mvp', application: 'next-mvp', version: '1.0.0', environment: process.env.NODE_ENV || 'development', hostname: this.getHostname(), instance: process.env.NEXT_INSTANCE_ID || 'unknown' } },
|
|
70
|
+
components: { auth: { enabled: true, prefix: '[AUTH]' }, idp: { enabled: true, prefix: '[IDP]' }, api: { enabled: true, prefix: '[API]' }, circuitBreaker: { enabled: true, prefix: '[CIRCUIT-BREAKER]' }, token: { enabled: true, prefix: '[TOKEN]' }, tokenSync: { enabled: true, prefix: '[TOKEN-SYNC]' }, tokenRefresh: { enabled: true, prefix: '[TOKEN-REFRESH]' }, redis: { enabled: true, prefix: '[REDIS]' } },
|
|
71
|
+
levels: { error: 0, warn: 1, info: 2, http: 3, debug: 4 }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const loggingConfigManager = new LoggingConfigManager();
|
|
77
|
+
export const getLoggingConfig = () => loggingConfigManager.getConfig();
|
|
78
|
+
export const getLoggingConfigSync = () => loggingConfigManager.getConfigSync();
|
|
79
|
+
export const startConfigWatching = () => loggingConfigManager.startWatching();
|
|
80
|
+
export const stopConfigWatching = () => loggingConfigManager.stopWatching();
|
|
81
|
+
export const addConfigWatcher = (callback: (config: LoggingConfig) => void) => loggingConfigManager.addWatcher(callback);
|
|
82
|
+
export const removeConfigWatcher = (callback: (config: LoggingConfig) => void) => loggingConfigManager.removeWatcher(callback);
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
export interface UnauthenticatedRouteConfig { pattern: string; description: string; allowDuringCircuitBreakerOpen?: boolean; requiresRateLimit?: boolean; }
|
|
2
|
-
export const UNAUTHENTICATED_ROUTES: UnauthenticatedRouteConfig[] = [
|
|
3
|
-
{ pattern: '/account-auth/*', description: 'All authentication pages', allowDuringCircuitBreakerOpen: true },
|
|
4
|
-
{ pattern: '/account-auth/login', description: 'Login page', allowDuringCircuitBreakerOpen: true },
|
|
5
|
-
{ pattern: '/account-auth/verify-code', description: '2FA page', allowDuringCircuitBreakerOpen: true },
|
|
6
|
-
{ pattern: '/api/auth/*', description: 'Auth API endpoints', allowDuringCircuitBreakerOpen: true, requiresRateLimit: true },
|
|
7
|
-
{ pattern: '/api/session/refresh-viability', description: 'Refresh viability check', allowDuringCircuitBreakerOpen: true },
|
|
8
|
-
{ pattern: '/landing', description: 'Public landing', allowDuringCircuitBreakerOpen: true },
|
|
9
|
-
{ pattern: '/service-unavailable', description: 'Service unavailable', allowDuringCircuitBreakerOpen: true },
|
|
10
|
-
{ pattern: '/favicon.ico', description: 'Favicon', allowDuringCircuitBreakerOpen: true },
|
|
11
|
-
{ pattern: '/robots.txt', description: 'Robots.txt', allowDuringCircuitBreakerOpen: true },
|
|
12
|
-
{ pattern: '/sitemap.xml', description: 'Sitemap', allowDuringCircuitBreakerOpen: true },
|
|
13
|
-
{ pattern: '/_next/*', description: 'Next.js assets', allowDuringCircuitBreakerOpen: true },
|
|
14
|
-
{ pattern: '/public/*', description: 'Public assets', allowDuringCircuitBreakerOpen: true }
|
|
15
|
-
];
|
|
16
|
-
export function isUnauthenticatedRoute(pathname: string): boolean { return UNAUTHENTICATED_ROUTES.some(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); }
|
|
17
|
-
export function isAllowedDuringCircuitBreakerOpen(pathname: string): boolean { const route = UNAUTHENTICATED_ROUTES.find(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); return route?.allowDuringCircuitBreakerOpen === true; }
|
|
18
|
-
export function requiresRateLimit(pathname: string): boolean { const route = UNAUTHENTICATED_ROUTES.find(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); return route?.requiresRateLimit === true; }
|
|
19
|
-
export default { UNAUTHENTICATED_ROUTES, isUnauthenticatedRoute, isAllowedDuringCircuitBreakerOpen, requiresRateLimit };
|
|
1
|
+
export interface UnauthenticatedRouteConfig { pattern: string; description: string; allowDuringCircuitBreakerOpen?: boolean; requiresRateLimit?: boolean; }
|
|
2
|
+
export const UNAUTHENTICATED_ROUTES: UnauthenticatedRouteConfig[] = [
|
|
3
|
+
{ pattern: '/account-auth/*', description: 'All authentication pages', allowDuringCircuitBreakerOpen: true },
|
|
4
|
+
{ pattern: '/account-auth/login', description: 'Login page', allowDuringCircuitBreakerOpen: true },
|
|
5
|
+
{ pattern: '/account-auth/verify-code', description: '2FA page', allowDuringCircuitBreakerOpen: true },
|
|
6
|
+
{ pattern: '/api/auth/*', description: 'Auth API endpoints', allowDuringCircuitBreakerOpen: true, requiresRateLimit: true },
|
|
7
|
+
{ pattern: '/api/session/refresh-viability', description: 'Refresh viability check', allowDuringCircuitBreakerOpen: true },
|
|
8
|
+
{ pattern: '/landing', description: 'Public landing', allowDuringCircuitBreakerOpen: true },
|
|
9
|
+
{ pattern: '/service-unavailable', description: 'Service unavailable', allowDuringCircuitBreakerOpen: true },
|
|
10
|
+
{ pattern: '/favicon.ico', description: 'Favicon', allowDuringCircuitBreakerOpen: true },
|
|
11
|
+
{ pattern: '/robots.txt', description: 'Robots.txt', allowDuringCircuitBreakerOpen: true },
|
|
12
|
+
{ pattern: '/sitemap.xml', description: 'Sitemap', allowDuringCircuitBreakerOpen: true },
|
|
13
|
+
{ pattern: '/_next/*', description: 'Next.js assets', allowDuringCircuitBreakerOpen: true },
|
|
14
|
+
{ pattern: '/public/*', description: 'Public assets', allowDuringCircuitBreakerOpen: true }
|
|
15
|
+
];
|
|
16
|
+
export function isUnauthenticatedRoute(pathname: string): boolean { return UNAUTHENTICATED_ROUTES.some(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); }
|
|
17
|
+
export function isAllowedDuringCircuitBreakerOpen(pathname: string): boolean { const route = UNAUTHENTICATED_ROUTES.find(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); return route?.allowDuringCircuitBreakerOpen === true; }
|
|
18
|
+
export function requiresRateLimit(pathname: string): boolean { const route = UNAUTHENTICATED_ROUTES.find(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); return route?.requiresRateLimit === true; }
|
|
19
|
+
export default { UNAUTHENTICATED_ROUTES, isUnauthenticatedRoute, isAllowedDuringCircuitBreakerOpen, requiresRateLimit };
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal API URL Utility for Edge Runtime
|
|
3
|
-
*
|
|
4
|
-
* INTERNAL_API_URL is REQUIRED. This is the URL for THIS application calling ITSELF.
|
|
5
|
-
* Used for middleware to call its own API routes (e.g., /api/session/viability).
|
|
6
|
-
*
|
|
7
|
-
* WHY HTTP IS REQUIRED (not optional):
|
|
8
|
-
* - This is the app calling its OWN backend within the same pod/container
|
|
9
|
-
* - NextAuth cookies are encrypted based on request protocol
|
|
10
|
-
* - TLS is terminated at ingress, so the pod receives HTTP internally
|
|
11
|
-
* - Using HTTPS here causes cookie decryption failures
|
|
12
|
-
* - This is NOT about "K8s internal traffic doesn't need TLS" - it's about
|
|
13
|
-
* protocol consistency for cookie encryption
|
|
14
|
-
*
|
|
15
|
-
* This is NOT for calling the IDP - use IDP_URL for that.
|
|
16
|
-
*
|
|
17
|
-
* For local dev, set INTERNAL_API_URL=http://localhost:3000 (or your dev port).
|
|
18
|
-
*
|
|
19
|
-
* @module edge/internal-api-url
|
|
20
|
-
* @version 3.0.0
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { NextRequest } from 'next/server';
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Get the internal API base URL for middleware to call its own API routes.
|
|
27
|
-
*
|
|
28
|
-
* THROWS if INTERNAL_API_URL is not set. No fallbacks.
|
|
29
|
-
*
|
|
30
|
-
* @param request - The Next.js request object (unused, kept for API compatibility)
|
|
31
|
-
* @returns Base URL string for constructing internal API calls
|
|
32
|
-
* @throws Error if INTERNAL_API_URL environment variable is not set
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```typescript
|
|
36
|
-
* import { getInternalApiUrl } from '@payez/next-mvp/edge';
|
|
37
|
-
*
|
|
38
|
-
* export async function middleware(request: NextRequest) {
|
|
39
|
-
* const baseUrl = getInternalApiUrl(request);
|
|
40
|
-
* const apiUrl = new URL('/api/session/check', baseUrl);
|
|
41
|
-
*
|
|
42
|
-
* const response = await fetch(apiUrl, {
|
|
43
|
-
* headers: {
|
|
44
|
-
* 'Cookie': request.headers.get('cookie') || ''
|
|
45
|
-
* }
|
|
46
|
-
* });
|
|
47
|
-
* }
|
|
48
|
-
* ```
|
|
49
|
-
*
|
|
50
|
-
* @environment INTERNAL_API_URL - REQUIRED. URL for this app to call ITSELF.
|
|
51
|
-
* MUST be HTTP (not HTTPS) - see module docs for why.
|
|
52
|
-
* K8s: http://myapp.namespace.svc.cluster.local:80
|
|
53
|
-
* Local: http://localhost:3000
|
|
54
|
-
*/
|
|
55
|
-
export function getInternalApiUrl(request: NextRequest): string {
|
|
56
|
-
const internalUrl = process.env.INTERNAL_API_URL;
|
|
57
|
-
if (!internalUrl) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
'[INTERNAL_API_URL] FATAL: INTERNAL_API_URL environment variable is REQUIRED. ' +
|
|
60
|
-
'This is for the app to call ITSELF. MUST be HTTP (not HTTPS). ' +
|
|
61
|
-
'Set to http://myapp.namespace.svc.cluster.local:80 (K8s) or http://localhost:3000 (local).'
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
return internalUrl;
|
|
65
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Internal API URL Utility for Edge Runtime
|
|
3
|
+
*
|
|
4
|
+
* INTERNAL_API_URL is REQUIRED. This is the URL for THIS application calling ITSELF.
|
|
5
|
+
* Used for middleware to call its own API routes (e.g., /api/session/viability).
|
|
6
|
+
*
|
|
7
|
+
* WHY HTTP IS REQUIRED (not optional):
|
|
8
|
+
* - This is the app calling its OWN backend within the same pod/container
|
|
9
|
+
* - NextAuth cookies are encrypted based on request protocol
|
|
10
|
+
* - TLS is terminated at ingress, so the pod receives HTTP internally
|
|
11
|
+
* - Using HTTPS here causes cookie decryption failures
|
|
12
|
+
* - This is NOT about "K8s internal traffic doesn't need TLS" - it's about
|
|
13
|
+
* protocol consistency for cookie encryption
|
|
14
|
+
*
|
|
15
|
+
* This is NOT for calling the IDP - use IDP_URL for that.
|
|
16
|
+
*
|
|
17
|
+
* For local dev, set INTERNAL_API_URL=http://localhost:3000 (or your dev port).
|
|
18
|
+
*
|
|
19
|
+
* @module edge/internal-api-url
|
|
20
|
+
* @version 3.0.0
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { NextRequest } from 'next/server';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the internal API base URL for middleware to call its own API routes.
|
|
27
|
+
*
|
|
28
|
+
* THROWS if INTERNAL_API_URL is not set. No fallbacks.
|
|
29
|
+
*
|
|
30
|
+
* @param request - The Next.js request object (unused, kept for API compatibility)
|
|
31
|
+
* @returns Base URL string for constructing internal API calls
|
|
32
|
+
* @throws Error if INTERNAL_API_URL environment variable is not set
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { getInternalApiUrl } from '@payez/next-mvp/edge';
|
|
37
|
+
*
|
|
38
|
+
* export async function middleware(request: NextRequest) {
|
|
39
|
+
* const baseUrl = getInternalApiUrl(request);
|
|
40
|
+
* const apiUrl = new URL('/api/session/check', baseUrl);
|
|
41
|
+
*
|
|
42
|
+
* const response = await fetch(apiUrl, {
|
|
43
|
+
* headers: {
|
|
44
|
+
* 'Cookie': request.headers.get('cookie') || ''
|
|
45
|
+
* }
|
|
46
|
+
* });
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @environment INTERNAL_API_URL - REQUIRED. URL for this app to call ITSELF.
|
|
51
|
+
* MUST be HTTP (not HTTPS) - see module docs for why.
|
|
52
|
+
* K8s: http://myapp.namespace.svc.cluster.local:80
|
|
53
|
+
* Local: http://localhost:3000
|
|
54
|
+
*/
|
|
55
|
+
export function getInternalApiUrl(request: NextRequest): string {
|
|
56
|
+
const internalUrl = process.env.INTERNAL_API_URL;
|
|
57
|
+
if (!internalUrl) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
'[INTERNAL_API_URL] FATAL: INTERNAL_API_URL environment variable is REQUIRED. ' +
|
|
60
|
+
'This is for the app to call ITSELF. MUST be HTTP (not HTTPS). ' +
|
|
61
|
+
'Set to http://myapp.namespace.svc.cluster.local:80 (K8s) or http://localhost:3000 (local).'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return internalUrl;
|
|
65
|
+
}
|
package/src/edge/middleware.ts
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Edge Runtime Compatible Exports
|
|
3
|
-
*
|
|
4
|
-
* This module exports only Edge Runtime compatible code for use in Next.js middleware.
|
|
5
|
-
* Client-side utilities that depend on browser APIs or server-only code are excluded.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Authentication middleware and configuration (Edge Runtime compatible)
|
|
9
|
-
export { makeAuthDecision } from '../auth/auth-decision';
|
|
10
|
-
export {
|
|
11
|
-
isUnauthenticatedRoute,
|
|
12
|
-
configurePublicRoutes,
|
|
13
|
-
getRouteConfig,
|
|
14
|
-
configure2FABypassRoutes,
|
|
15
|
-
should2FABypass,
|
|
16
|
-
get2FABypassConfig
|
|
17
|
-
} from '../auth/route-config';
|
|
18
|
-
export type { UnauthenticatedRouteConfig, ProtectedRouteConfig } from '../auth/route-config';
|
|
19
|
-
export { createMvpMiddleware } from '../middleware/create-middleware';
|
|
20
|
-
export type {
|
|
21
|
-
MvpMiddlewareOptions,
|
|
22
|
-
CircuitBreakerProvider,
|
|
23
|
-
MiddlewareLogger,
|
|
24
|
-
AuthContext,
|
|
25
|
-
AuthAction,
|
|
26
|
-
SessionPointer,
|
|
27
|
-
SessionStatus
|
|
28
|
-
} from '../middleware/create-middleware';
|
|
29
|
-
|
|
30
|
-
// Two-Factor Authentication Presets (Edge Runtime compatible)
|
|
31
|
-
export {
|
|
32
|
-
TwoFactorPresets,
|
|
33
|
-
AMRValues,
|
|
34
|
-
ACRLevels,
|
|
35
|
-
validateAMR,
|
|
36
|
-
validateACR,
|
|
37
|
-
checkTwoFactorRequirements
|
|
38
|
-
} from '../middleware/twofa-presets';
|
|
39
|
-
export type { TwoFactorRequirements, RouteConfig } from '../middleware/twofa-presets';
|
|
40
|
-
|
|
41
|
-
// Internal API URL utilities for Edge Runtime
|
|
42
|
-
export { getInternalApiUrl } from './internal-api-url';
|
|
1
|
+
/**
|
|
2
|
+
* Edge Runtime Compatible Exports
|
|
3
|
+
*
|
|
4
|
+
* This module exports only Edge Runtime compatible code for use in Next.js middleware.
|
|
5
|
+
* Client-side utilities that depend on browser APIs or server-only code are excluded.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Authentication middleware and configuration (Edge Runtime compatible)
|
|
9
|
+
export { makeAuthDecision } from '../auth/auth-decision';
|
|
10
|
+
export {
|
|
11
|
+
isUnauthenticatedRoute,
|
|
12
|
+
configurePublicRoutes,
|
|
13
|
+
getRouteConfig,
|
|
14
|
+
configure2FABypassRoutes,
|
|
15
|
+
should2FABypass,
|
|
16
|
+
get2FABypassConfig
|
|
17
|
+
} from '../auth/route-config';
|
|
18
|
+
export type { UnauthenticatedRouteConfig, ProtectedRouteConfig } from '../auth/route-config';
|
|
19
|
+
export { createMvpMiddleware } from '../middleware/create-middleware';
|
|
20
|
+
export type {
|
|
21
|
+
MvpMiddlewareOptions,
|
|
22
|
+
CircuitBreakerProvider,
|
|
23
|
+
MiddlewareLogger,
|
|
24
|
+
AuthContext,
|
|
25
|
+
AuthAction,
|
|
26
|
+
SessionPointer,
|
|
27
|
+
SessionStatus
|
|
28
|
+
} from '../middleware/create-middleware';
|
|
29
|
+
|
|
30
|
+
// Two-Factor Authentication Presets (Edge Runtime compatible)
|
|
31
|
+
export {
|
|
32
|
+
TwoFactorPresets,
|
|
33
|
+
AMRValues,
|
|
34
|
+
ACRLevels,
|
|
35
|
+
validateAMR,
|
|
36
|
+
validateACR,
|
|
37
|
+
checkTwoFactorRequirements
|
|
38
|
+
} from '../middleware/twofa-presets';
|
|
39
|
+
export type { TwoFactorRequirements, RouteConfig } from '../middleware/twofa-presets';
|
|
40
|
+
|
|
41
|
+
// Internal API URL utilities for Edge Runtime
|
|
42
|
+
export { getInternalApiUrl } from './internal-api-url';
|