better-auth-studio 1.1.1-beta.3 → 1.1.1-beta.5
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/adapters/hono.d.ts.map +1 -1
- package/dist/adapters/hono.js +5 -0
- package/dist/adapters/hono.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/handler.d.ts.map +1 -1
- package/dist/core/handler.js +85 -4
- package/dist/core/handler.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/events/helpers.d.ts +22 -0
- package/dist/providers/events/helpers.d.ts.map +1 -0
- package/dist/providers/events/helpers.js +874 -0
- package/dist/providers/events/helpers.js.map +1 -0
- package/dist/public/assets/{main-BIlYgyPi.js → main-B_Zdj1LN.js} +139 -139
- package/dist/public/assets/main-RoeYO1I-.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +193 -0
- package/dist/routes.js.map +1 -1
- package/dist/studio.d.ts.map +1 -1
- package/dist/studio.js +6 -1
- package/dist/studio.js.map +1 -1
- package/dist/types/events.d.ts +43 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +306 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/handler.d.ts +31 -0
- package/dist/types/handler.d.ts.map +1 -1
- package/dist/types/handler.js.map +1 -1
- package/dist/utils/auth-callbacks-injector.d.ts +3 -0
- package/dist/utils/auth-callbacks-injector.d.ts.map +1 -0
- package/dist/utils/auth-callbacks-injector.js +227 -0
- package/dist/utils/auth-callbacks-injector.js.map +1 -0
- package/dist/utils/auth-callbacks-wrapper.d.ts +7 -0
- package/dist/utils/auth-callbacks-wrapper.d.ts.map +1 -0
- package/dist/utils/auth-callbacks-wrapper.js +123 -0
- package/dist/utils/auth-callbacks-wrapper.js.map +1 -0
- package/dist/utils/database-hook-injector.d.ts +3 -0
- package/dist/utils/database-hook-injector.d.ts.map +1 -0
- package/dist/utils/database-hook-injector.js +141 -0
- package/dist/utils/database-hook-injector.js.map +1 -0
- package/dist/utils/email-otp-hooks-injector.d.ts +29 -0
- package/dist/utils/email-otp-hooks-injector.d.ts.map +1 -0
- package/dist/utils/email-otp-hooks-injector.js +134 -0
- package/dist/utils/email-otp-hooks-injector.js.map +1 -0
- package/dist/utils/event-ingestion.d.ts +38 -0
- package/dist/utils/event-ingestion.d.ts.map +1 -0
- package/dist/utils/event-ingestion.js +169 -0
- package/dist/utils/event-ingestion.js.map +1 -0
- package/dist/utils/hook-injector.d.ts +9 -0
- package/dist/utils/hook-injector.d.ts.map +1 -0
- package/dist/utils/hook-injector.js +649 -0
- package/dist/utils/hook-injector.js.map +1 -0
- package/dist/utils/html-injector.d.ts +17 -0
- package/dist/utils/html-injector.d.ts.map +1 -1
- package/dist/utils/html-injector.js +15 -0
- package/dist/utils/html-injector.js.map +1 -1
- package/dist/utils/org-hooks-injector.d.ts +74 -0
- package/dist/utils/org-hooks-injector.d.ts.map +1 -0
- package/dist/utils/org-hooks-injector.js +678 -0
- package/dist/utils/org-hooks-injector.js.map +1 -0
- package/dist/utils/org-hooks-wrapper.d.ts +74 -0
- package/dist/utils/org-hooks-wrapper.d.ts.map +1 -0
- package/dist/utils/org-hooks-wrapper.js +687 -0
- package/dist/utils/org-hooks-wrapper.js.map +1 -0
- package/dist/utils/organization-hooks-wrapper.d.ts +38 -0
- package/dist/utils/organization-hooks-wrapper.d.ts.map +1 -0
- package/dist/utils/organization-hooks-wrapper.js +297 -0
- package/dist/utils/organization-hooks-wrapper.js.map +1 -0
- package/package.json +7 -4
- package/public/assets/{main-BIlYgyPi.js → main-B_Zdj1LN.js} +139 -139
- package/public/assets/main-RoeYO1I-.css +1 -0
- package/public/index.html +2 -2
- package/dist/public/assets/main-s8HrXBxq.css +0 -1
- package/public/assets/main-s8HrXBxq.css +0 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { emitEvent } from './event-ingestion.js';
|
|
2
|
+
/**
|
|
3
|
+
* Helper to extract request info from Better Auth request object
|
|
4
|
+
*/
|
|
5
|
+
function getRequestInfo(request) {
|
|
6
|
+
const headersObj = {};
|
|
7
|
+
let ip;
|
|
8
|
+
if (request) {
|
|
9
|
+
try {
|
|
10
|
+
if (request instanceof Request) {
|
|
11
|
+
request.headers.forEach((value, key) => {
|
|
12
|
+
headersObj[key] = value;
|
|
13
|
+
});
|
|
14
|
+
ip =
|
|
15
|
+
request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || undefined;
|
|
16
|
+
}
|
|
17
|
+
else if (request.headers) {
|
|
18
|
+
if (typeof request.headers.get === 'function') {
|
|
19
|
+
ip =
|
|
20
|
+
request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || undefined;
|
|
21
|
+
request.headers.forEach?.((value, key) => {
|
|
22
|
+
headersObj[key] = value;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
ip = request.headers['x-forwarded-for'] || request.headers['x-real-ip'] || undefined;
|
|
27
|
+
Object.entries(request.headers).forEach(([key, value]) => {
|
|
28
|
+
headersObj[key] = String(value);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
// Ignore errors
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { headers: headersObj, ip };
|
|
38
|
+
}
|
|
39
|
+
// Share password reset method tracking with auth-callbacks-injector
|
|
40
|
+
// This is used to determine if password reset was via OTP or token
|
|
41
|
+
// We need to access it from auth-callbacks-injector, so we'll use a shared approach
|
|
42
|
+
// by setting it on the email-otp plugin options temporarily, or we can use a module-level map
|
|
43
|
+
// For now, we'll track it in the callback and let onPasswordReset check it
|
|
44
|
+
// The passwordResetMethod map in auth-callbacks-injector will be used for completion tracking
|
|
45
|
+
/**
|
|
46
|
+
* Wraps email-otp plugin callbacks to automatically emit events
|
|
47
|
+
* This wraps the sendVerificationOTP callback similar to how organization hooks work
|
|
48
|
+
*
|
|
49
|
+
* @param eventsConfig - The events configuration
|
|
50
|
+
* @param existingCallback - The original sendVerificationOTP callback
|
|
51
|
+
* @param passwordResetMethodMap - Optional shared Map to track password reset method (OTP vs token)
|
|
52
|
+
*/
|
|
53
|
+
export function wrapEmailOTPPluginCallbacks(eventsConfig, existingCallback, passwordResetMethodMap) {
|
|
54
|
+
if (!eventsConfig?.enabled) {
|
|
55
|
+
return existingCallback;
|
|
56
|
+
}
|
|
57
|
+
if (!existingCallback) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const capturedConfig = eventsConfig;
|
|
61
|
+
return async (data, ctx) => {
|
|
62
|
+
const requestInfo = getRequestInfo(ctx?.request || ctx);
|
|
63
|
+
// Call the original callback first
|
|
64
|
+
const originalPromise = existingCallback(data, ctx);
|
|
65
|
+
// Track and emit event for password reset OTP
|
|
66
|
+
if (data.type === 'forget-password') {
|
|
67
|
+
const email = data.email.toLowerCase();
|
|
68
|
+
// Track that this is an OTP-based password reset
|
|
69
|
+
// This will be checked by onPasswordReset in auth-callbacks-injector
|
|
70
|
+
if (passwordResetMethodMap) {
|
|
71
|
+
passwordResetMethodMap.set(email, 'otp');
|
|
72
|
+
}
|
|
73
|
+
// Emit event for password reset OTP requested
|
|
74
|
+
const eventPromise = emitEvent('password.reset_requested_otp', {
|
|
75
|
+
status: 'success',
|
|
76
|
+
metadata: {
|
|
77
|
+
email: data.email,
|
|
78
|
+
type: 'forget-password',
|
|
79
|
+
requestedAt: new Date().toISOString(),
|
|
80
|
+
},
|
|
81
|
+
request: requestInfo,
|
|
82
|
+
}, capturedConfig).catch(() => { });
|
|
83
|
+
// Wait for original callback to complete
|
|
84
|
+
await originalPromise;
|
|
85
|
+
// Don't wait for event emission to avoid blocking
|
|
86
|
+
eventPromise.catch(() => { });
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
await originalPromise;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Automatically wraps email-otp plugin callbacks to emit events
|
|
95
|
+
* This should be called during Better Auth initialization
|
|
96
|
+
* Similar to wrapOrganizationPluginHooks but for callbacks
|
|
97
|
+
*
|
|
98
|
+
* @param auth - The Better Auth instance
|
|
99
|
+
* @param eventsConfig - The events configuration
|
|
100
|
+
* @param passwordResetMethodMap - Optional shared Map to track password reset method (OTP vs token)
|
|
101
|
+
*/
|
|
102
|
+
export function wrapEmailOTPPluginHooks(auth, eventsConfig, passwordResetMethodMap) {
|
|
103
|
+
if (!auth || !eventsConfig?.enabled) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const plugins = auth.options?.plugins || [];
|
|
108
|
+
const emailOtpPlugin = plugins.find((p) => p?.id === 'email-otp');
|
|
109
|
+
if (!emailOtpPlugin) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Check if already wrapped to avoid double wrapping
|
|
113
|
+
if (emailOtpPlugin.__studio_callbacks_wrapped) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Wrap the sendVerificationOTP callback
|
|
117
|
+
const existingSendVerificationOTP = emailOtpPlugin.options?.sendVerificationOTP;
|
|
118
|
+
if (existingSendVerificationOTP) {
|
|
119
|
+
const wrappedCallback = wrapEmailOTPPluginCallbacks(eventsConfig, existingSendVerificationOTP, passwordResetMethodMap);
|
|
120
|
+
if (wrappedCallback) {
|
|
121
|
+
if (!emailOtpPlugin.options) {
|
|
122
|
+
emailOtpPlugin.options = {};
|
|
123
|
+
}
|
|
124
|
+
emailOtpPlugin.options.sendVerificationOTP = wrappedCallback;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Mark as wrapped to prevent double wrapping
|
|
128
|
+
emailOtpPlugin.__studio_callbacks_wrapped = true;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.error('[Email OTP Callbacks] Failed to wrap callbacks:', error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=email-otp-hooks-injector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-otp-hooks-injector.js","sourceRoot":"","sources":["../../src/utils/email-otp-hooks-injector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD;;GAEG;AACH,SAAS,cAAc,CAAC,OAAuB;IAC7C,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,IAAI,EAAsB,CAAC;IAE3B,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,IAAI,OAAO,YAAY,OAAO,EAAE,CAAC;gBAC/B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACrC,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,CAAC,CAAC,CAAC;gBACH,EAAE;oBACA,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC;YAC5F,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC3B,IAAI,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;oBAC9C,EAAE;wBACA,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC;oBAC1F,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,KAAa,EAAE,GAAW,EAAE,EAAE;wBACvD,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;oBAC1B,CAAC,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC;oBACrF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;wBACvD,UAAU,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;oBAClC,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;AACrC,CAAC;AAED,oEAAoE;AACpE,mEAAmE;AACnE,oFAAoF;AACpF,8FAA8F;AAC9F,2EAA2E;AAC3E,8FAA8F;AAE9F;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CACzC,YAAoC,EACpC,gBAAiJ,EACjJ,sBAAqD;IAErD,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QAC3B,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,cAAc,GAAG,YAAY,CAAC;IAEpC,OAAO,KAAK,EACV,IAAgG,EAChG,GAAS,EACT,EAAE;QACF,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC;QAExD,mCAAmC;QACnC,MAAM,eAAe,GAAG,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAEpD,8CAA8C;QAC9C,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAEvC,iDAAiD;YACjD,qEAAqE;YACrE,IAAI,sBAAsB,EAAE,CAAC;gBAC3B,sBAAsB,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC3C,CAAC;YAED,8CAA8C;YAC9C,MAAM,YAAY,GAAG,SAAS,CAC5B,8BAA8B,EAC9B;gBACE,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE;oBACR,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,IAAI,EAAE,iBAAiB;oBACvB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACtC;gBACD,OAAO,EAAE,WAAW;aACrB,EACD,cAAc,CACf,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAElB,yCAAyC;YACzC,MAAM,eAAe,CAAC;YACtB,kDAAkD;YAClD,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,MAAM,eAAe,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAS,EACT,YAAoC,EACpC,sBAAqD;IAErD,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;QAC5C,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,WAAW,CAAC,CAAC;QAEvE,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,oDAAoD;QACpD,IAAI,cAAc,CAAC,0BAA0B,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,wCAAwC;QACxC,MAAM,2BAA2B,GAAG,cAAc,CAAC,OAAO,EAAE,mBAAmB,CAAC;QAChF,IAAI,2BAA2B,EAAE,CAAC;YAChC,MAAM,eAAe,GAAG,2BAA2B,CACjD,YAAY,EACZ,2BAA2B,EAC3B,sBAAsB,CACvB,CAAC;YAEF,IAAI,eAAe,EAAE,CAAC;gBACpB,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;oBAC5B,cAAc,CAAC,OAAO,GAAG,EAAE,CAAC;gBAC9B,CAAC;gBACD,cAAc,CAAC,OAAO,CAAC,mBAAmB,GAAG,eAAe,CAAC;YAC/D,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,cAAc,CAAC,0BAA0B,GAAG,IAAI,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AuthEventType, EventIngestionProvider } from '../types/events.js';
|
|
2
|
+
import type { StudioConfig } from '../types/handler.js';
|
|
3
|
+
/**
|
|
4
|
+
* Initialize event ingestion
|
|
5
|
+
*/
|
|
6
|
+
export declare function initializeEventIngestion(eventsConfig: StudioConfig['events']): void;
|
|
7
|
+
/**
|
|
8
|
+
* Emit an event
|
|
9
|
+
*/
|
|
10
|
+
export declare function emitEvent(type: AuthEventType, data: {
|
|
11
|
+
status: 'success' | 'failed';
|
|
12
|
+
userId?: string;
|
|
13
|
+
sessionId?: string;
|
|
14
|
+
organizationId?: string;
|
|
15
|
+
metadata?: Record<string, any>;
|
|
16
|
+
request?: {
|
|
17
|
+
headers: Record<string, string>;
|
|
18
|
+
ip?: string;
|
|
19
|
+
};
|
|
20
|
+
}, eventsConfig?: StudioConfig['events']): Promise<void>;
|
|
21
|
+
export declare function shutdownEventIngestion(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Health check
|
|
24
|
+
*/
|
|
25
|
+
export declare function checkEventIngestionHealth(): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Get initialization status
|
|
28
|
+
*/
|
|
29
|
+
export declare function isEventIngestionInitialized(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get current queue size (for monitoring)
|
|
32
|
+
*/
|
|
33
|
+
export declare function getEventQueueSize(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Get the current event ingestion provider
|
|
36
|
+
*/
|
|
37
|
+
export declare function getEventIngestionProvider(): EventIngestionProvider | null;
|
|
38
|
+
//# sourceMappingURL=event-ingestion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-ingestion.d.ts","sourceRoot":"","sources":["../../src/utils/event-ingestion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,sBAAsB,EAGvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AASxD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI,CAqBnF;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE;IACJ,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D,EACD,YAAY,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAuEf;AAwBD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmB5D;AAED;;GAEG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,OAAO,CAAC,CAUlE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,sBAAsB,GAAG,IAAI,CAEzE"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { EVENT_TEMPLATES, getEventSeverity } from '../types/events.js';
|
|
2
|
+
let provider = null;
|
|
3
|
+
let config = null;
|
|
4
|
+
let eventQueue = [];
|
|
5
|
+
let flushTimer = null;
|
|
6
|
+
let isShuttingDown = false;
|
|
7
|
+
let isInitialized = false;
|
|
8
|
+
/**
|
|
9
|
+
* Initialize event ingestion
|
|
10
|
+
*/
|
|
11
|
+
export function initializeEventIngestion(eventsConfig) {
|
|
12
|
+
if (!eventsConfig?.enabled) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
config = eventsConfig;
|
|
16
|
+
provider = eventsConfig.provider || null;
|
|
17
|
+
if (!provider) {
|
|
18
|
+
console.warn('Event ingestion is enabled but no provider provided');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
isInitialized = true;
|
|
22
|
+
if (config.batchSize && config.batchSize > 1) {
|
|
23
|
+
const flushInterval = config.flushInterval || 5000;
|
|
24
|
+
flushTimer = setInterval(() => {
|
|
25
|
+
flushEvents().catch(console.error);
|
|
26
|
+
}, flushInterval);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Emit an event
|
|
31
|
+
*/
|
|
32
|
+
export async function emitEvent(type, data, eventsConfig) {
|
|
33
|
+
const activeConfig = eventsConfig || config;
|
|
34
|
+
if (!activeConfig?.enabled) {
|
|
35
|
+
initializeEventIngestion(eventsConfig);
|
|
36
|
+
}
|
|
37
|
+
const useConfig = activeConfig || config;
|
|
38
|
+
if (!useConfig) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (useConfig.include && !useConfig.include.includes(type)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (useConfig.exclude && useConfig.exclude.includes(type)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const template = EVENT_TEMPLATES[type];
|
|
48
|
+
const tempEvent = {
|
|
49
|
+
id: '',
|
|
50
|
+
type,
|
|
51
|
+
timestamp: new Date(),
|
|
52
|
+
status: data.status,
|
|
53
|
+
userId: data.userId,
|
|
54
|
+
sessionId: data.sessionId,
|
|
55
|
+
organizationId: data.organizationId,
|
|
56
|
+
metadata: data.metadata || {},
|
|
57
|
+
source: 'app',
|
|
58
|
+
};
|
|
59
|
+
const displayMessage = template ? template(tempEvent) : type;
|
|
60
|
+
const event = {
|
|
61
|
+
id: crypto.randomUUID(),
|
|
62
|
+
type,
|
|
63
|
+
timestamp: new Date(),
|
|
64
|
+
status: data.status,
|
|
65
|
+
userId: data.userId,
|
|
66
|
+
sessionId: data.sessionId,
|
|
67
|
+
organizationId: data.organizationId,
|
|
68
|
+
metadata: data.metadata || {},
|
|
69
|
+
ipAddress: data.request?.ip,
|
|
70
|
+
userAgent: data.request?.headers['user-agent'] || data.request?.headers['User-Agent'],
|
|
71
|
+
source: 'app',
|
|
72
|
+
display: {
|
|
73
|
+
message: displayMessage,
|
|
74
|
+
severity: getEventSeverity(tempEvent, data.status),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const batchSize = useConfig.batchSize || 1;
|
|
78
|
+
if (batchSize > 1 && provider?.ingestBatch) {
|
|
79
|
+
eventQueue.push(event);
|
|
80
|
+
if (eventQueue.length >= batchSize) {
|
|
81
|
+
await flushEvents();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
try {
|
|
86
|
+
console.log(`[Event Ingestion] Emitting event: ${type}`, {
|
|
87
|
+
userId: event.userId,
|
|
88
|
+
message: event.display?.message,
|
|
89
|
+
});
|
|
90
|
+
await provider?.ingest(event);
|
|
91
|
+
console.log(`[Event Ingestion] ✅ Successfully ingested event: ${type}`);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(`[Event Ingestion] ❌ Failed to ingest event ${type}:`, error);
|
|
95
|
+
if (useConfig.retryOnError) {
|
|
96
|
+
eventQueue.push(event);
|
|
97
|
+
console.log(`[Event Ingestion] Queued event for retry: ${type}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function flushEvents() {
|
|
103
|
+
if (eventQueue.length === 0 || !provider || isShuttingDown) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const eventsToSend = [...eventQueue];
|
|
107
|
+
eventQueue = [];
|
|
108
|
+
try {
|
|
109
|
+
if (provider.ingestBatch) {
|
|
110
|
+
await provider.ingestBatch(eventsToSend);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
await Promise.all(eventsToSend.map((event) => provider.ingest(event)));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('Batch event ingestion error:', error);
|
|
118
|
+
if (config?.retryOnError) {
|
|
119
|
+
eventQueue.unshift(...eventsToSend);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export async function shutdownEventIngestion() {
|
|
124
|
+
isShuttingDown = true;
|
|
125
|
+
if (flushTimer) {
|
|
126
|
+
clearInterval(flushTimer);
|
|
127
|
+
flushTimer = null;
|
|
128
|
+
}
|
|
129
|
+
await flushEvents();
|
|
130
|
+
if (provider?.shutdown) {
|
|
131
|
+
await provider.shutdown();
|
|
132
|
+
}
|
|
133
|
+
provider = null;
|
|
134
|
+
config = null;
|
|
135
|
+
eventQueue = [];
|
|
136
|
+
isInitialized = false;
|
|
137
|
+
isShuttingDown = false;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Health check
|
|
141
|
+
*/
|
|
142
|
+
export async function checkEventIngestionHealth() {
|
|
143
|
+
if (!provider) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
if (provider.healthCheck) {
|
|
147
|
+
return await provider.healthCheck();
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get initialization status
|
|
153
|
+
*/
|
|
154
|
+
export function isEventIngestionInitialized() {
|
|
155
|
+
return isInitialized;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get current queue size (for monitoring)
|
|
159
|
+
*/
|
|
160
|
+
export function getEventQueueSize() {
|
|
161
|
+
return eventQueue.length;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get the current event ingestion provider
|
|
165
|
+
*/
|
|
166
|
+
export function getEventIngestionProvider() {
|
|
167
|
+
return provider;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=event-ingestion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-ingestion.js","sourceRoot":"","sources":["../../src/utils/event-ingestion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StudioConfig } from '../types/handler.js';
|
|
2
|
+
/**
|
|
3
|
+
* Inject middleware hooks into Better Auth using plugins
|
|
4
|
+
*
|
|
5
|
+
* Better Auth processes plugins during initialization, so we add the plugin
|
|
6
|
+
* to auth.options.plugins array
|
|
7
|
+
*/
|
|
8
|
+
export declare function injectEventHooks(auth: any, eventsConfig: StudioConfig['events']): void;
|
|
9
|
+
//# sourceMappingURL=hook-injector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-injector.d.ts","sourceRoot":"","sources":["../../src/utils/hook-injector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA4tBxD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI,CAmCtF"}
|