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.
Files changed (78) hide show
  1. package/dist/adapters/hono.d.ts.map +1 -1
  2. package/dist/adapters/hono.js +5 -0
  3. package/dist/adapters/hono.js.map +1 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/core/handler.d.ts.map +1 -1
  7. package/dist/core/handler.js +85 -4
  8. package/dist/core/handler.js.map +1 -1
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/providers/events/helpers.d.ts +22 -0
  14. package/dist/providers/events/helpers.d.ts.map +1 -0
  15. package/dist/providers/events/helpers.js +874 -0
  16. package/dist/providers/events/helpers.js.map +1 -0
  17. package/dist/public/assets/{main-BIlYgyPi.js → main-B_Zdj1LN.js} +139 -139
  18. package/dist/public/assets/main-RoeYO1I-.css +1 -0
  19. package/dist/public/index.html +2 -2
  20. package/dist/routes.d.ts.map +1 -1
  21. package/dist/routes.js +193 -0
  22. package/dist/routes.js.map +1 -1
  23. package/dist/studio.d.ts.map +1 -1
  24. package/dist/studio.js +6 -1
  25. package/dist/studio.js.map +1 -1
  26. package/dist/types/events.d.ts +43 -0
  27. package/dist/types/events.d.ts.map +1 -0
  28. package/dist/types/events.js +306 -0
  29. package/dist/types/events.js.map +1 -0
  30. package/dist/types/handler.d.ts +31 -0
  31. package/dist/types/handler.d.ts.map +1 -1
  32. package/dist/types/handler.js.map +1 -1
  33. package/dist/utils/auth-callbacks-injector.d.ts +3 -0
  34. package/dist/utils/auth-callbacks-injector.d.ts.map +1 -0
  35. package/dist/utils/auth-callbacks-injector.js +227 -0
  36. package/dist/utils/auth-callbacks-injector.js.map +1 -0
  37. package/dist/utils/auth-callbacks-wrapper.d.ts +7 -0
  38. package/dist/utils/auth-callbacks-wrapper.d.ts.map +1 -0
  39. package/dist/utils/auth-callbacks-wrapper.js +123 -0
  40. package/dist/utils/auth-callbacks-wrapper.js.map +1 -0
  41. package/dist/utils/database-hook-injector.d.ts +3 -0
  42. package/dist/utils/database-hook-injector.d.ts.map +1 -0
  43. package/dist/utils/database-hook-injector.js +141 -0
  44. package/dist/utils/database-hook-injector.js.map +1 -0
  45. package/dist/utils/email-otp-hooks-injector.d.ts +29 -0
  46. package/dist/utils/email-otp-hooks-injector.d.ts.map +1 -0
  47. package/dist/utils/email-otp-hooks-injector.js +134 -0
  48. package/dist/utils/email-otp-hooks-injector.js.map +1 -0
  49. package/dist/utils/event-ingestion.d.ts +38 -0
  50. package/dist/utils/event-ingestion.d.ts.map +1 -0
  51. package/dist/utils/event-ingestion.js +169 -0
  52. package/dist/utils/event-ingestion.js.map +1 -0
  53. package/dist/utils/hook-injector.d.ts +9 -0
  54. package/dist/utils/hook-injector.d.ts.map +1 -0
  55. package/dist/utils/hook-injector.js +649 -0
  56. package/dist/utils/hook-injector.js.map +1 -0
  57. package/dist/utils/html-injector.d.ts +17 -0
  58. package/dist/utils/html-injector.d.ts.map +1 -1
  59. package/dist/utils/html-injector.js +15 -0
  60. package/dist/utils/html-injector.js.map +1 -1
  61. package/dist/utils/org-hooks-injector.d.ts +74 -0
  62. package/dist/utils/org-hooks-injector.d.ts.map +1 -0
  63. package/dist/utils/org-hooks-injector.js +678 -0
  64. package/dist/utils/org-hooks-injector.js.map +1 -0
  65. package/dist/utils/org-hooks-wrapper.d.ts +74 -0
  66. package/dist/utils/org-hooks-wrapper.d.ts.map +1 -0
  67. package/dist/utils/org-hooks-wrapper.js +687 -0
  68. package/dist/utils/org-hooks-wrapper.js.map +1 -0
  69. package/dist/utils/organization-hooks-wrapper.d.ts +38 -0
  70. package/dist/utils/organization-hooks-wrapper.d.ts.map +1 -0
  71. package/dist/utils/organization-hooks-wrapper.js +297 -0
  72. package/dist/utils/organization-hooks-wrapper.js.map +1 -0
  73. package/package.json +7 -4
  74. package/public/assets/{main-BIlYgyPi.js → main-B_Zdj1LN.js} +139 -139
  75. package/public/assets/main-RoeYO1I-.css +1 -0
  76. package/public/index.html +2 -2
  77. package/dist/public/assets/main-s8HrXBxq.css +0 -1
  78. package/public/assets/main-s8HrXBxq.css +0 -1
@@ -0,0 +1,649 @@
1
+ import { getSessionFromCtx } from 'better-auth/api';
2
+ import { createAuthMiddleware } from 'better-auth/plugins';
3
+ import { wrapAuthCallbacks } from './auth-callbacks-injector.js';
4
+ import { emitEvent } from './event-ingestion.js';
5
+ import { wrapOrganizationPluginHooks } from './org-hooks-injector.js';
6
+ const INJECTED_HOOKS_MARKER = '__better_auth_studio_events_injected__';
7
+ /**
8
+ * Create a Better Auth plugin for event ingestion
9
+ */
10
+ let beforeSession = null;
11
+ function createEventIngestionPlugin(eventsConfig) {
12
+ const capturedConfig = eventsConfig;
13
+ const eventMiddleware = createAuthMiddleware(async (ctx) => {
14
+ if (!capturedConfig?.enabled) {
15
+ return ctx;
16
+ }
17
+ setTimeout(() => {
18
+ try {
19
+ const path = ctx?.path || ctx?.context?.path || '';
20
+ if (!path)
21
+ return;
22
+ const returned = ctx?.context?.returned;
23
+ if (!returned)
24
+ return;
25
+ // Guard against Better Auth internal errors
26
+ if (typeof returned === 'object' && returned !== null) {
27
+ // Check if returned has problematic properties that might cause errors
28
+ try {
29
+ // Try to access common properties safely
30
+ const _ = returned.statusCode;
31
+ }
32
+ catch (e) {
33
+ // If accessing properties causes errors, skip processing
34
+ return;
35
+ }
36
+ }
37
+ const isError = returned.statusCode && returned.statusCode >= 400;
38
+ const isSuccess = !isError && returned.statusCode === 200;
39
+ let ip = null;
40
+ const headersObj = {};
41
+ try {
42
+ if (ctx.headers && typeof ctx.headers === 'object') {
43
+ if (typeof ctx.headers.get === 'function') {
44
+ try {
45
+ ip = ctx.headers.get('x-forwarded-for') || ctx.headers.get('x-real-ip') || null;
46
+ }
47
+ catch (e) { }
48
+ }
49
+ else {
50
+ ip = ctx.headers['x-forwarded-for'] || ctx.headers['x-real-ip'] || null;
51
+ }
52
+ }
53
+ }
54
+ catch (e) { }
55
+ if (path === '/sign-up' || path === '/sign-up/email') {
56
+ const body = ctx.body || {};
57
+ const user = returned || ctx.context.returned;
58
+ if (!isError) {
59
+ emitEvent('user.joined', {
60
+ status: 'success',
61
+ userId: returned.user.id,
62
+ sessionId: '',
63
+ metadata: {
64
+ email: body.email || returned.user.email || '',
65
+ name: body.name || returned.user.name || '',
66
+ },
67
+ request: {
68
+ headers: headersObj,
69
+ ip: ip || undefined,
70
+ },
71
+ }, capturedConfig).catch(() => { });
72
+ }
73
+ else if (isError) {
74
+ emitEvent('user.joined', {
75
+ status: 'failed',
76
+ metadata: {
77
+ email: body.email,
78
+ name: body.name,
79
+ reason: returned.statusCode === 400
80
+ ? 'validation_failed'
81
+ : returned.statusCode === 409
82
+ ? 'user_already_exists'
83
+ : returned.body?.code || returned.body?.message || 'unknown',
84
+ },
85
+ request: {
86
+ headers: headersObj,
87
+ ip: ip || undefined,
88
+ },
89
+ }, capturedConfig).catch(() => { });
90
+ }
91
+ }
92
+ if (path === '/sign-in' || path === '/sign-in/email') {
93
+ const body = ctx.body || {};
94
+ const user = returned.user || ctx.context?.returned;
95
+ const session = returned.newSession || ctx.context?.newSession;
96
+ if (!isError) {
97
+ emitEvent('user.logged_in', {
98
+ status: 'success',
99
+ userId: user.id,
100
+ sessionId: session?.id,
101
+ metadata: {
102
+ name: user.name,
103
+ email: body.email || user.email,
104
+ },
105
+ request: {
106
+ headers: headersObj,
107
+ ip: ip || undefined,
108
+ },
109
+ }, capturedConfig).catch(() => { });
110
+ // Also emit session.created
111
+ if (session) {
112
+ emitEvent('session.created', {
113
+ status: 'success',
114
+ userId: user.id,
115
+ sessionId: session.id,
116
+ metadata: {
117
+ name: user.name,
118
+ email: body.email || user.email,
119
+ token: session.token,
120
+ },
121
+ request: {
122
+ headers: headersObj,
123
+ ip: ip || undefined,
124
+ },
125
+ }, capturedConfig).catch(() => { });
126
+ }
127
+ }
128
+ else if (isError) {
129
+ emitEvent('user.logged_in', {
130
+ status: 'failed',
131
+ metadata: {
132
+ email: body.email,
133
+ reason: returned.statusCode === 401
134
+ ? 'invalid_credentials'
135
+ : returned.body?.code || 'unknown',
136
+ },
137
+ request: {
138
+ headers: headersObj,
139
+ ip: ip || undefined,
140
+ },
141
+ }, capturedConfig).catch(() => { });
142
+ }
143
+ }
144
+ if (path === '/sign-out') {
145
+ const session = beforeSession;
146
+ const { user, session: sessionData } = session || {};
147
+ if (!isError && user) {
148
+ emitEvent('user.logged_out', {
149
+ status: 'success',
150
+ userId: user.id,
151
+ sessionId: sessionData?.id,
152
+ metadata: {
153
+ email: user?.email,
154
+ name: user?.name,
155
+ },
156
+ request: {
157
+ headers: headersObj,
158
+ ip: ip || undefined,
159
+ },
160
+ }, capturedConfig).catch(() => { });
161
+ }
162
+ }
163
+ // User deleted
164
+ // OAuth unlinked
165
+ if (path === '/unlink-account') {
166
+ const session = ctx.context?.session;
167
+ const unlinkReturned = ctx.context?.returned || returned;
168
+ const body = ctx.body || {};
169
+ if (!isError &&
170
+ session &&
171
+ unlinkReturned &&
172
+ typeof unlinkReturned === 'object' &&
173
+ 'status' in unlinkReturned) {
174
+ emitEvent('oauth.unlinked', {
175
+ status: 'success',
176
+ userId: session.user.id,
177
+ metadata: {
178
+ provider: body.providerId || body.provider,
179
+ accountId: body.accountId,
180
+ email: session.user.email,
181
+ },
182
+ request: {
183
+ headers: headersObj,
184
+ ip: ip || undefined,
185
+ },
186
+ }, capturedConfig).catch(() => { });
187
+ }
188
+ else if (isError) {
189
+ emitEvent('oauth.unlinked', {
190
+ status: 'failed',
191
+ metadata: {
192
+ provider: body.providerId || body.provider,
193
+ reason: returned.statusCode === 400
194
+ ? 'invalid_request'
195
+ : returned.body?.code || returned.body?.message || 'unknown',
196
+ },
197
+ request: {
198
+ headers: headersObj,
199
+ ip: ip || undefined,
200
+ },
201
+ }, capturedConfig).catch(() => { });
202
+ }
203
+ }
204
+ const isCallbackPath = path.startsWith('/callback/') ||
205
+ path.startsWith('/callback') ||
206
+ path.startsWith('/oauth2/callback/') ||
207
+ path.startsWith('/oauth2/callback');
208
+ if (isCallbackPath) {
209
+ try {
210
+ const newSession = ctx.context?.newSession || returned?.newSession;
211
+ const user = newSession?.user ||
212
+ returned?.user ||
213
+ returned?.data?.user ||
214
+ ctx.context?.user ||
215
+ ctx.user ||
216
+ (returned?.data && typeof returned.data === 'object' && 'user' in returned.data
217
+ ? returned.data.user
218
+ : null);
219
+ const existingUser = ctx.context?.existingUser;
220
+ const params = ctx.params;
221
+ if (user) {
222
+ const provider = path.includes('/callback/')
223
+ ? path.split('/callback/')[1]?.split('/')[0]
224
+ : path.includes('/oauth2/callback/')
225
+ ? path.split('/oauth2/callback/')[1]?.split('/')[0]
226
+ : path.includes('/callback')
227
+ ? path.split('/callback')[1]?.split('/')[1] ||
228
+ path.split('/callback')[1]?.split('?')[0]
229
+ : undefined;
230
+ if (existingUser) {
231
+ emitEvent('oauth.linked', {
232
+ status: 'success',
233
+ userId: user.id,
234
+ metadata: {
235
+ provider: params.id,
236
+ email: user.email,
237
+ name: user.name,
238
+ },
239
+ request: {
240
+ headers: headersObj,
241
+ ip: ip || undefined,
242
+ },
243
+ }, capturedConfig).catch(() => { });
244
+ }
245
+ else {
246
+ // New user signing in via OAuth
247
+ emitEvent('oauth.sign_in', {
248
+ status: 'success',
249
+ userId: user.id,
250
+ sessionId: newSession?.session?.id || newSession?.id,
251
+ metadata: {
252
+ provider: params.id,
253
+ providerId: params.id,
254
+ userEmail: user.email,
255
+ email: user.email,
256
+ name: user.name,
257
+ emailVerified: user.emailVerified,
258
+ },
259
+ request: {
260
+ headers: headersObj,
261
+ ip: ip || undefined,
262
+ },
263
+ }, capturedConfig)
264
+ .then(() => {
265
+ if (!isError && newSession && user) {
266
+ emitEvent('session.created', {
267
+ status: 'success',
268
+ userId: user.id,
269
+ sessionId: newSession.session?.id || newSession.id,
270
+ metadata: {
271
+ name: user.name,
272
+ email: user.email,
273
+ provider: params.id,
274
+ },
275
+ request: {
276
+ headers: headersObj,
277
+ ip: ip || undefined,
278
+ },
279
+ }, capturedConfig).catch(() => { });
280
+ }
281
+ else if (isError) {
282
+ emitEvent('session.created', {
283
+ status: 'failed',
284
+ metadata: {
285
+ reason: returned.statusCode === 401
286
+ ? 'authentication_failed'
287
+ : returned.body?.code || 'unknown',
288
+ provider: path.includes('/callback/')
289
+ ? path.split('/callback/')[1]?.split('/')[0]
290
+ : undefined,
291
+ },
292
+ request: {
293
+ headers: headersObj,
294
+ ip: ip || undefined,
295
+ },
296
+ }, capturedConfig).catch(() => { });
297
+ }
298
+ })
299
+ .catch(() => { });
300
+ }
301
+ }
302
+ }
303
+ catch (callbackError) {
304
+ // Suppress Better Auth internal errors
305
+ const errorMessage = callbackError?.message || String(callbackError || '');
306
+ if (!errorMessage.includes('reloadNavigation') &&
307
+ !errorMessage.includes('Cannot read properties of undefined')) {
308
+ console.error('[OAuth Callback] Error:', errorMessage);
309
+ }
310
+ }
311
+ }
312
+ // Organization created
313
+ if (path === '/organization/create') {
314
+ const orgReturned = ctx.context?.returned || returned;
315
+ getSessionFromCtx(ctx)
316
+ .then((session) => {
317
+ if (!isError &&
318
+ orgReturned &&
319
+ typeof orgReturned === 'object' &&
320
+ 'id' in orgReturned) {
321
+ emitEvent('organization.created', {
322
+ status: 'success',
323
+ organizationId: orgReturned.id,
324
+ userId: session?.user.id,
325
+ metadata: {
326
+ organizationName: orgReturned.name,
327
+ organizationSlug: orgReturned.slug,
328
+ email: session?.user.email,
329
+ name: session?.user.name,
330
+ },
331
+ request: {
332
+ headers: headersObj,
333
+ ip: ip || undefined,
334
+ },
335
+ }, capturedConfig).catch(() => { });
336
+ }
337
+ else if (isError) {
338
+ const body = ctx.body || {};
339
+ emitEvent('organization.created', {
340
+ status: 'failed',
341
+ userId: session?.user.id,
342
+ metadata: {
343
+ organizationName: body?.name,
344
+ organizationSlug: body?.slug,
345
+ reason: returned.statusCode === 400
346
+ ? 'validation_failed'
347
+ : returned.statusCode === 409
348
+ ? 'organization_exists'
349
+ : returned.body?.code || returned.body?.message || 'unknown',
350
+ },
351
+ request: {
352
+ headers: headersObj,
353
+ ip: ip || undefined,
354
+ },
355
+ }, capturedConfig).catch(() => { });
356
+ }
357
+ })
358
+ .catch(() => { });
359
+ }
360
+ if (path === '/admin/ban-user') {
361
+ const body = ctx.body || {};
362
+ const user = returned?.user || ctx.context?.returned?.user || ctx.context?.user;
363
+ if (!isError && user) {
364
+ emitEvent('user.banned', {
365
+ status: 'success',
366
+ userId: user.id,
367
+ metadata: {
368
+ email: user.email,
369
+ name: user.name,
370
+ },
371
+ request: {
372
+ headers: headersObj,
373
+ ip: ip || undefined,
374
+ },
375
+ }, capturedConfig).catch(() => { });
376
+ }
377
+ else if (isError) {
378
+ emitEvent('user.banned', {
379
+ status: 'failed',
380
+ metadata: {
381
+ reason: returned.body?.code || returned.body?.message || 'unknown',
382
+ },
383
+ request: {
384
+ headers: headersObj,
385
+ ip: ip || undefined,
386
+ },
387
+ }, capturedConfig).catch(() => { });
388
+ }
389
+ }
390
+ if (path === '/admin/unban-user') {
391
+ const body = ctx.body || {};
392
+ const user = returned?.user || ctx.context?.returned?.user || ctx.context?.user;
393
+ if (!isError && user) {
394
+ emitEvent('user.unbanned', {
395
+ status: 'success',
396
+ userId: user.id,
397
+ metadata: {
398
+ email: user.email,
399
+ name: user.name,
400
+ },
401
+ request: {
402
+ headers: headersObj,
403
+ ip: ip || undefined,
404
+ },
405
+ }, capturedConfig).catch(() => { });
406
+ }
407
+ else if (isError) {
408
+ emitEvent('user.unbanned', {
409
+ status: 'failed',
410
+ metadata: {
411
+ reason: returned.body?.code || returned.body?.message || 'unknown',
412
+ },
413
+ request: {
414
+ headers: headersObj,
415
+ ip: ip || undefined,
416
+ },
417
+ }, capturedConfig).catch(() => { });
418
+ }
419
+ }
420
+ if (path === '/update-user') {
421
+ const updateReturned = ctx.context?.returned || returned;
422
+ const session = ctx.context?.session;
423
+ const oldData = ctx.context?._oldUserData;
424
+ const body = ctx.body || {};
425
+ if (!isError && updateReturned && session) {
426
+ const updatedFields = {};
427
+ const oldValues = {};
428
+ if (body.name !== undefined && body.name !== oldData?.name) {
429
+ updatedFields.name = body.name;
430
+ oldValues.name = oldData?.name;
431
+ }
432
+ if (body.image !== undefined && body.image !== oldData?.image) {
433
+ updatedFields.image = body.image;
434
+ oldValues.image = oldData?.image;
435
+ }
436
+ if (body.email !== undefined && body.email !== oldData?.email) {
437
+ updatedFields.email = body.email;
438
+ oldValues.email = oldData?.email;
439
+ }
440
+ if (Object.keys(updatedFields).length > 0) {
441
+ emitEvent('user.updated', {
442
+ status: 'success',
443
+ userId: session.user.id,
444
+ metadata: {
445
+ email: session.user.email,
446
+ name: session.user.name,
447
+ updatedFields: updatedFields,
448
+ oldValues: oldValues,
449
+ updatedAt: new Date().toISOString(),
450
+ },
451
+ request: {
452
+ headers: headersObj,
453
+ ip: ip || undefined,
454
+ },
455
+ }, capturedConfig).catch(() => { });
456
+ }
457
+ }
458
+ else if (isError) {
459
+ emitEvent('user.updated', {
460
+ status: 'failed',
461
+ metadata: {
462
+ reason: returned.statusCode === 400
463
+ ? 'validation_failed'
464
+ : returned.statusCode === 401
465
+ ? 'unauthorized'
466
+ : returned.statusCode === 403
467
+ ? 'forbidden'
468
+ : returned.body?.code || returned.body?.message || 'unknown',
469
+ },
470
+ request: {
471
+ headers: headersObj,
472
+ ip: ip || undefined,
473
+ },
474
+ }, capturedConfig).catch(() => { });
475
+ }
476
+ }
477
+ }
478
+ catch (error) {
479
+ // Suppress Better Auth internal errors (reloadNavigation, etc.)
480
+ const errorMessage = error?.message || String(error || '');
481
+ if (errorMessage.includes('reloadNavigation') ||
482
+ errorMessage.includes('Cannot read properties of undefined')) {
483
+ // These are Better Auth internal errors, not our issue
484
+ return;
485
+ }
486
+ console.error('[Event Hook] Error:', errorMessage);
487
+ }
488
+ }, 0);
489
+ });
490
+ const oauthAccountAfter = async (account, context) => {
491
+ if (!context || !context.internalAdapter) {
492
+ return;
493
+ }
494
+ if (!account || !account.userId || !account.providerId) {
495
+ return;
496
+ }
497
+ if (account.providerId !== 'credential') {
498
+ try {
499
+ if (typeof context.internalAdapter.findUserById !== 'function' ||
500
+ typeof context.internalAdapter.findAccounts !== 'function') {
501
+ return;
502
+ }
503
+ const user = await context.internalAdapter.findUserById(account.userId);
504
+ if (user) {
505
+ const existingAccounts = await context.internalAdapter.findAccounts(account.userId);
506
+ const isLinking = existingAccounts && existingAccounts.length > 1; // More than just this new account
507
+ if (isLinking) {
508
+ await emitEvent('oauth.linked', {
509
+ status: 'success',
510
+ userId: account.userId,
511
+ metadata: {
512
+ provider: account.providerId,
513
+ providerId: account.providerId,
514
+ userEmail: user.email,
515
+ email: user.email,
516
+ name: user.name,
517
+ accountId: account.accountId,
518
+ linkedAt: new Date().toISOString(),
519
+ },
520
+ }, capturedConfig).catch(() => { });
521
+ }
522
+ else {
523
+ await emitEvent('oauth.sign_in', {
524
+ status: 'success',
525
+ userId: account.userId,
526
+ metadata: {
527
+ provider: account.providerId,
528
+ providerId: account.providerId,
529
+ userEmail: user.email,
530
+ email: user.email,
531
+ name: user.name,
532
+ emailVerified: user.emailVerified,
533
+ accountId: account.accountId,
534
+ createdAt: user.createdAt
535
+ ? new Date(user.createdAt).toISOString()
536
+ : new Date().toISOString(),
537
+ },
538
+ }, capturedConfig).catch(() => { });
539
+ }
540
+ }
541
+ }
542
+ catch (error) {
543
+ console.error('[OAuth DB Hook] Error:', error);
544
+ }
545
+ }
546
+ };
547
+ return {
548
+ id: 'better-auth-studio-events',
549
+ hooks: {
550
+ before: [
551
+ {
552
+ matcher: (context) => {
553
+ return context.path === '/sign-out';
554
+ },
555
+ handler: async (context) => {
556
+ const body = context.body || {};
557
+ beforeSession = await context.context.internalAdapter.findSession(body.token);
558
+ },
559
+ },
560
+ {
561
+ matcher: (context) => {
562
+ return context.path === '/update-user';
563
+ },
564
+ handler: async (context) => {
565
+ const session = context.context?.session;
566
+ if (session?.user) {
567
+ context.context._oldUserData = {
568
+ name: session.user.name,
569
+ image: session.user.image,
570
+ email: session.user.email,
571
+ };
572
+ }
573
+ return context;
574
+ },
575
+ },
576
+ ],
577
+ after: [
578
+ {
579
+ matcher: (context) => {
580
+ const path = context?.path || context?.context?.path || '';
581
+ const shouldMatch = path === '/sign-up' ||
582
+ path === '/sign-up/email' ||
583
+ path === '/sign-in' ||
584
+ path === '/sign-in/email' ||
585
+ path.startsWith('/sign-in/social') ||
586
+ path === '/sign-out' ||
587
+ path === '/update-password' ||
588
+ path === '/change-password' ||
589
+ path === '/verify-email' ||
590
+ path === '/forget-password' ||
591
+ path === '/delete-user' ||
592
+ path === '/unlink-account' ||
593
+ path.startsWith('/callback') ||
594
+ path.startsWith('/oauth2/callback') ||
595
+ path === '/organization/create' ||
596
+ path === '/organization/update' ||
597
+ path === '/organization/delete' ||
598
+ path === '/update-user' ||
599
+ path.startsWith('/admin/');
600
+ return shouldMatch;
601
+ },
602
+ handler: eventMiddleware,
603
+ },
604
+ ],
605
+ },
606
+ // TODO: I cant be able to reach the database hook from this. this will be important for most of event ingestions
607
+ // databaseHooks: {
608
+ // account: {
609
+ // create: {
610
+ // after: oauthAccountAfter,
611
+ // },
612
+ // },
613
+ // },
614
+ };
615
+ }
616
+ /**
617
+ * Inject middleware hooks into Better Auth using plugins
618
+ *
619
+ * Better Auth processes plugins during initialization, so we add the plugin
620
+ * to auth.options.plugins array
621
+ */
622
+ export function injectEventHooks(auth, eventsConfig) {
623
+ if (!auth || !eventsConfig?.enabled) {
624
+ return;
625
+ }
626
+ try {
627
+ if (auth.options?.[INJECTED_HOOKS_MARKER]) {
628
+ return;
629
+ }
630
+ const eventPlugin = createEventIngestionPlugin(eventsConfig);
631
+ if (!auth.options) {
632
+ auth.options = {};
633
+ }
634
+ if (!auth.options.plugins) {
635
+ auth.options.plugins = [];
636
+ }
637
+ const existingPlugin = auth.options.plugins.find((p) => p?.id === 'better-auth-studio-events');
638
+ if (!existingPlugin) {
639
+ auth.options.plugins.push(eventPlugin);
640
+ }
641
+ auth.options[INJECTED_HOOKS_MARKER] = true;
642
+ wrapOrganizationPluginHooks(auth, eventsConfig);
643
+ wrapAuthCallbacks(auth, eventsConfig);
644
+ }
645
+ catch (error) {
646
+ console.error('[Event Hooks] Failed to inject:', error);
647
+ }
648
+ }
649
+ //# sourceMappingURL=hook-injector.js.map