better-auth-studio 1.0.6 → 1.0.8

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 (51) hide show
  1. package/dist/config.d.ts +1 -0
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +126 -29
  4. package/dist/config.js.map +1 -1
  5. package/dist/routes.d.ts.map +1 -1
  6. package/dist/routes.js +28 -2
  7. package/dist/routes.js.map +1 -1
  8. package/package.json +8 -1
  9. package/frontend/index.html +0 -13
  10. package/frontend/package-lock.json +0 -4675
  11. package/frontend/package.json +0 -52
  12. package/frontend/pnpm-lock.yaml +0 -4020
  13. package/frontend/postcss.config.js +0 -6
  14. package/frontend/src/App.tsx +0 -36
  15. package/frontend/src/components/CommandPalette.tsx +0 -219
  16. package/frontend/src/components/Layout.tsx +0 -159
  17. package/frontend/src/components/ui/badge.tsx +0 -40
  18. package/frontend/src/components/ui/button.tsx +0 -53
  19. package/frontend/src/components/ui/card.tsx +0 -78
  20. package/frontend/src/components/ui/input.tsx +0 -20
  21. package/frontend/src/components/ui/label.tsx +0 -19
  22. package/frontend/src/components/ui/select.tsx +0 -71
  23. package/frontend/src/index.css +0 -130
  24. package/frontend/src/lib/utils.ts +0 -6
  25. package/frontend/src/main.tsx +0 -10
  26. package/frontend/src/pages/Dashboard.tsx +0 -231
  27. package/frontend/src/pages/OrganizationDetails.tsx +0 -1281
  28. package/frontend/src/pages/Organizations.tsx +0 -874
  29. package/frontend/src/pages/Sessions.tsx +0 -623
  30. package/frontend/src/pages/Settings.tsx +0 -1019
  31. package/frontend/src/pages/TeamDetails.tsx +0 -666
  32. package/frontend/src/pages/Users.tsx +0 -728
  33. package/frontend/tailwind.config.js +0 -75
  34. package/frontend/tsconfig.json +0 -31
  35. package/frontend/tsconfig.node.json +0 -10
  36. package/frontend/vite.config.ts +0 -31
  37. package/src/auth-adapter.ts +0 -473
  38. package/src/cli.ts +0 -51
  39. package/src/config.ts +0 -320
  40. package/src/data.ts +0 -351
  41. package/src/routes.ts +0 -1585
  42. package/src/studio.ts +0 -86
  43. package/test-project/README.md +0 -0
  44. package/test-project/better-auth.db +0 -0
  45. package/test-project/better-auth_migrations/2025-08-27T15-55-04.099Z.sql +0 -7
  46. package/test-project/better-auth_migrations/2025-09-04T02-33-19.422Z.sql +0 -7
  47. package/test-project/package.json +0 -29
  48. package/test-project/pnpm-lock.yaml +0 -1728
  49. package/test-project/src/auth.ts +0 -47
  50. package/test-project/src/index.ts +0 -40
  51. package/tsconfig.json +0 -21
package/src/routes.ts DELETED
@@ -1,1585 +0,0 @@
1
- import { Router, Request, Response } from 'express';
2
- import { getAuthData } from './data';
3
- import { AuthConfig } from './config';
4
- import { getAuthAdapter, createMockUser, createMockSession, createMockAccount, createMockVerification } from './auth-adapter';
5
-
6
- async function findAuthConfigPath(): Promise<string | null> {
7
- const { join, dirname } = await import('path');
8
- const { existsSync } = await import('fs');
9
-
10
- const possiblePaths = [
11
- 'src/auth.ts',
12
- 'src/auth.js',
13
- 'lib/auth.ts',
14
- 'lib/auth.js',
15
- 'auth.ts',
16
- 'auth.js'
17
- ];
18
-
19
- for (const path of possiblePaths) {
20
- if (existsSync(path)) {
21
- return join(process.cwd(), path);
22
- }
23
- }
24
-
25
- return null;
26
- }
27
-
28
- export function createRoutes(authConfig: AuthConfig) {
29
- const router = Router();
30
-
31
- router.get('/api/health', (req: Request, res: Response) => {
32
- const uptime = process.uptime();
33
- const hours = Math.floor(uptime / 3600);
34
- const minutes = Math.floor((uptime % 3600) / 60);
35
- const seconds = Math.floor(uptime % 60);
36
-
37
- res.json({
38
- status: 'ok',
39
- timestamp: new Date().toISOString(),
40
- system: {
41
- studioVersion: '1.0.0',
42
- nodeVersion: process.version,
43
- platform: process.platform,
44
- arch: process.arch,
45
- uptime: `${hours}h ${minutes}m ${seconds}s`,
46
- memory: {
47
- used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
48
- total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
49
- external: Math.round(process.memoryUsage().external / 1024 / 1024)
50
- },
51
- pid: process.pid,
52
- cwd: process.cwd()
53
- }
54
- });
55
- });
56
-
57
- router.get('/api/config', (req: Request, res: Response) => {
58
- console.log('Raw authConfig:', JSON.stringify(authConfig, null, 2));
59
-
60
- const config = {
61
- appName: authConfig.appName || 'Better Auth',
62
- baseURL: authConfig.baseURL || process.env.BETTER_AUTH_URL,
63
- basePath: authConfig.basePath || '/api/auth',
64
- secret: authConfig.secret ? 'Configured' : 'Not set',
65
-
66
- database: {
67
- type: authConfig.database?.type || 'unknown',
68
- dialect: authConfig.database?.dialect,
69
- casing: authConfig.database?.casing || 'camel',
70
- debugLogs: authConfig.database?.debugLogs || false,
71
- url: authConfig.database?.url
72
- },
73
-
74
- emailVerification: {
75
- sendOnSignUp: authConfig.emailVerification?.sendOnSignUp || false,
76
- sendOnSignIn: authConfig.emailVerification?.sendOnSignIn || false,
77
- autoSignInAfterVerification: authConfig.emailVerification?.autoSignInAfterVerification || false,
78
- expiresIn: authConfig.emailVerification?.expiresIn || 3600
79
- },
80
-
81
- emailAndPassword: {
82
- enabled: authConfig.emailAndPassword?.enabled ?? false,
83
- disableSignUp: authConfig.emailAndPassword?.disableSignUp ?? false,
84
- requireEmailVerification: authConfig.emailAndPassword?.requireEmailVerification ?? false,
85
- maxPasswordLength: authConfig.emailAndPassword?.maxPasswordLength ?? 128,
86
- minPasswordLength: authConfig.emailAndPassword?.minPasswordLength ?? 8,
87
- resetPasswordTokenExpiresIn: authConfig.emailAndPassword?.resetPasswordTokenExpiresIn ?? 3600,
88
- autoSignIn: authConfig.emailAndPassword?.autoSignIn ?? true, // defaults to true
89
- revokeSessionsOnPasswordReset: authConfig.emailAndPassword?.revokeSessionsOnPasswordReset ?? false
90
- },
91
-
92
- socialProviders: authConfig.socialProviders ?
93
- Object.entries(authConfig.socialProviders).map(([provider, config]: [string, any]) => ({
94
- type: provider,
95
- clientId: config.clientId,
96
- clientSecret: config.clientSecret,
97
- redirectUri: config.redirectUri,
98
- ...config
99
- })) :
100
- (authConfig.providers || []),
101
-
102
- user: {
103
- modelName: authConfig.user?.modelName || 'user',
104
- changeEmail: {
105
- enabled: authConfig.user?.changeEmail?.enabled || false
106
- },
107
- deleteUser: {
108
- enabled: authConfig.user?.deleteUser?.enabled || false,
109
- deleteTokenExpiresIn: authConfig.user?.deleteUser?.deleteTokenExpiresIn || 86400
110
- }
111
- },
112
-
113
- session: {
114
- modelName: authConfig.session?.modelName || 'session',
115
- expiresIn: authConfig.session?.expiresIn || 604800, // 7 days
116
- updateAge: authConfig.session?.updateAge || 86400, // 1 day
117
- disableSessionRefresh: authConfig.session?.disableSessionRefresh || false,
118
- storeSessionInDatabase: authConfig.session?.storeSessionInDatabase || false,
119
- preserveSessionInDatabase: authConfig.session?.preserveSessionInDatabase || false,
120
- cookieCache: {
121
- enabled: authConfig.session?.cookieCache?.enabled || false,
122
- maxAge: authConfig.session?.cookieCache?.maxAge || 300
123
- },
124
- freshAge: authConfig.session?.freshAge || 86400
125
- },
126
-
127
- account: {
128
- modelName: authConfig.account?.modelName || 'account',
129
- updateAccountOnSignIn: authConfig.account?.updateAccountOnSignIn !== false, // defaults to true
130
- accountLinking: {
131
- enabled: authConfig.account?.accountLinking?.enabled !== false, // defaults to true
132
- trustedProviders: authConfig.account?.accountLinking?.trustedProviders || [],
133
- allowDifferentEmails: authConfig.account?.accountLinking?.allowDifferentEmails || false,
134
- allowUnlinkingAll: authConfig.account?.accountLinking?.allowUnlinkingAll || false,
135
- updateUserInfoOnLink: authConfig.account?.accountLinking?.updateUserInfoOnLink || false
136
- },
137
- encryptOAuthTokens: authConfig.account?.encryptOAuthTokens || false
138
- },
139
-
140
- verification: {
141
- modelName: authConfig.verification?.modelName || 'verification',
142
- disableCleanup: authConfig.verification?.disableCleanup || false
143
- },
144
-
145
- trustedOrigins: Array.isArray(authConfig.trustedOrigins) ? authConfig.trustedOrigins : [],
146
-
147
- rateLimit: {
148
- enabled: authConfig.rateLimit?.enabled ?? false,
149
- window: authConfig.rateLimit?.window || 10,
150
- max: authConfig.rateLimit?.max || 100,
151
- storage: authConfig.rateLimit?.storage || 'memory',
152
- modelName: authConfig.rateLimit?.modelName || 'rateLimit'
153
- },
154
-
155
- advanced: {
156
- ipAddress: {
157
- ipAddressHeaders: authConfig.advanced?.ipAddress?.ipAddressHeaders || [],
158
- disableIpTracking: authConfig.advanced?.ipAddress?.disableIpTracking || false
159
- },
160
- useSecureCookies: authConfig.advanced?.useSecureCookies || false,
161
- disableCSRFCheck: authConfig.advanced?.disableCSRFCheck || false,
162
- crossSubDomainCookies: {
163
- enabled: authConfig.advanced?.crossSubDomainCookies?.enabled || false,
164
- additionalCookies: authConfig.advanced?.crossSubDomainCookies?.additionalCookies || [],
165
- domain: authConfig.advanced?.crossSubDomainCookies?.domain
166
- },
167
- cookies: authConfig.advanced?.cookies || {},
168
- defaultCookieAttributes: authConfig.advanced?.defaultCookieAttributes || {},
169
- cookiePrefix: authConfig.advanced?.cookiePrefix,
170
- database: {
171
- defaultFindManyLimit: authConfig.advanced?.database?.defaultFindManyLimit || 100,
172
- useNumberId: authConfig.advanced?.database?.useNumberId || false
173
- }
174
- },
175
-
176
- disabledPaths: authConfig.disabledPaths || [],
177
-
178
- telemetry: {
179
- enabled: authConfig.telemetry?.enabled ?? false,
180
- debug: authConfig.telemetry?.debug || false
181
- },
182
-
183
- studio: {
184
- version: '1.0.0',
185
- nodeVersion: process.version,
186
- platform: process.platform,
187
- uptime: process.uptime()
188
- }
189
- };
190
-
191
- console.log('Processed config:', JSON.stringify(config, null, 2));
192
- res.json(config);
193
- });
194
-
195
- router.get('/api/stats', async (req: Request, res: Response) => {
196
- try {
197
- const stats = await getAuthData(authConfig, 'stats');
198
- res.json(stats);
199
- } catch (error) {
200
- console.error('Error fetching stats:', error);
201
- res.status(500).json({ error: 'Failed to fetch statistics' });
202
- }
203
- });
204
-
205
- router.get('/api/counts', async (req: Request, res: Response) => {
206
- try {
207
- const adapter = await getAuthAdapter();
208
- let userCount = 0;
209
- let sessionCount = 0;
210
- let organizationCount = 0;
211
-
212
- if (adapter) {
213
- try {
214
- if (typeof adapter.findMany === 'function') {
215
- const users = await adapter.findMany({ model: 'user', limit: 10000 });
216
- userCount = users?.length || 0;
217
- }
218
- } catch (error) {
219
- console.error('Error fetching user count:', error);
220
- }
221
-
222
- try {
223
- if (typeof adapter.findMany === 'function') {
224
- const sessions = await adapter.findMany({ model: 'session', limit: 10000 });
225
- sessionCount = sessions?.length || 0;
226
- }
227
- } catch (error) {
228
- console.error('Error fetching session count:', error);
229
- }
230
-
231
- try {
232
- if (typeof adapter.findMany === 'function') {
233
- const organizations = await adapter.findMany({ model: 'organization', limit: 10000 });
234
- organizationCount = organizations?.length || 0;
235
- }
236
- } catch (error) {
237
- console.error('Error fetching organization count:', error);
238
- organizationCount = 0;
239
- }
240
- }
241
-
242
- res.json({
243
- users: userCount,
244
- sessions: sessionCount,
245
- organizations: organizationCount
246
- });
247
- } catch (error) {
248
- console.error('Error fetching counts:', error);
249
- res.status(500).json({ error: 'Failed to fetch counts' });
250
- }
251
- });
252
- router.get('/api/users', async (req: Request, res: Response) => {
253
- try {
254
- const page = parseInt(req.query.page as string) || 1;
255
- const limit = parseInt(req.query.limit as string) || 20;
256
- const search = req.query.search as string;
257
- try {
258
- const adapter = await getAuthAdapter();
259
- if (adapter && typeof adapter.findMany === 'function') {
260
- const allUsers = await adapter.findMany({ model: 'user', limit: limit });
261
- console.log('Found users via findMany:', allUsers?.length || 0);
262
-
263
- let filteredUsers = allUsers || [];
264
- if (search) {
265
- filteredUsers = filteredUsers.filter((user: any) =>
266
- user.email?.toLowerCase().includes(search.toLowerCase()) ||
267
- user.name?.toLowerCase().includes(search.toLowerCase())
268
- );
269
- }
270
-
271
- const startIndex = (page - 1) * limit;
272
- const endIndex = startIndex + limit;
273
- const paginatedUsers = filteredUsers.slice(startIndex, endIndex);
274
-
275
- const transformedUsers = paginatedUsers.map((user: any) => ({
276
- id: user.id,
277
- email: user.email,
278
- name: user.name,
279
- image: user.image,
280
- emailVerified: user.emailVerified,
281
- createdAt: user.createdAt,
282
- updatedAt: user.updatedAt,
283
- }));
284
-
285
- res.json({ users: transformedUsers });
286
- return;
287
- }
288
- } catch (adapterError) {
289
- console.error('Error fetching users from adapter:', adapterError);
290
- }
291
-
292
- const result = await getAuthData(authConfig, 'users', { page, limit, search });
293
-
294
- const transformedUsers = (result.data || []).map((user: any) => ({
295
- id: user.id,
296
- email: user.email,
297
- name: user.name,
298
- image: user.image,
299
- emailVerified: user.emailVerified,
300
- createdAt: user.createdAt,
301
- updatedAt: user.updatedAt,
302
- }));
303
-
304
- res.json({ users: transformedUsers });
305
- } catch (error) {
306
- console.error('Error fetching users:', error);
307
- res.status(500).json({ error: 'Failed to fetch users' });
308
- }
309
- });
310
-
311
- router.get('/api/sessions', async (req: Request, res: Response) => {
312
- try {
313
- const page = parseInt(req.query.page as string) || 1;
314
- const limit = parseInt(req.query.limit as string) || 20;
315
-
316
- const sessions = await getAuthData(authConfig, 'sessions', { page, limit });
317
- res.json(sessions);
318
- } catch (error) {
319
- console.error('Error fetching sessions:', error);
320
- res.status(500).json({ error: 'Failed to fetch sessions' });
321
- }
322
- });
323
-
324
- router.get('/api/providers', async (req: Request, res: Response) => {
325
- try {
326
- const providers = await getAuthData(authConfig, 'providers');
327
- res.json(providers);
328
- } catch (error) {
329
- console.error('Error fetching providers:', error);
330
- res.status(500).json({ error: 'Failed to fetch providers' });
331
- }
332
- });
333
-
334
- router.delete('/api/users/:id', async (req: Request, res: Response) => {
335
- try {
336
- const { id } = req.params;
337
- await getAuthData(authConfig, 'deleteUser', { id });
338
- res.json({ success: true });
339
- } catch (error) {
340
- console.error('Error deleting user:', error);
341
- res.status(500).json({ error: 'Failed to delete user' });
342
- }
343
- });
344
-
345
- router.get('/api/plugins', async (req: Request, res: Response) => {
346
- try {
347
- const authConfigPath = await findAuthConfigPath();
348
- if (!authConfigPath) {
349
- return res.json({
350
- plugins: [],
351
- error: 'No auth config found',
352
- configPath: null
353
- });
354
- }
355
-
356
- try {
357
- const authModule = await import(authConfigPath);
358
- const auth = authModule.auth || authModule.default;
359
-
360
- if (!auth) {
361
- return res.json({
362
- plugins: [],
363
- error: 'No auth export found',
364
- configPath: authConfigPath
365
- });
366
- }
367
-
368
- const plugins = auth.options?.plugins || [];
369
- const pluginInfo = plugins.map((plugin: any) => ({
370
- id: plugin.id,
371
- name: plugin.name || plugin.id,
372
- version: plugin.version || 'unknown',
373
- description: plugin.description || `${plugin.id} plugin for Better Auth`,
374
- enabled: true
375
- }));
376
-
377
- res.json({
378
- plugins: pluginInfo,
379
- configPath: authConfigPath,
380
- totalPlugins: pluginInfo.length
381
- });
382
-
383
- } catch (error) {
384
- console.error('Error getting plugins:', error);
385
- res.json({
386
- plugins: [],
387
- error: 'Failed to load auth config',
388
- configPath: authConfigPath
389
- });
390
- }
391
- } catch (error) {
392
- console.error('Error fetching plugins:', error);
393
- res.status(500).json({ error: 'Failed to fetch plugins' });
394
- }
395
- });
396
-
397
- router.get('/api/plugins/teams/status', async (req: Request, res: Response) => {
398
- try {
399
- const authConfigPath = await findAuthConfigPath();
400
- if (!authConfigPath) {
401
- return res.json({
402
- enabled: false,
403
- error: 'No auth config found',
404
- configPath: null
405
- });
406
- }
407
-
408
- try {
409
- const authModule = await import(authConfigPath);
410
- const auth = authModule.auth || authModule.default;
411
-
412
- if (!auth) {
413
- return res.json({
414
- enabled: false,
415
- error: 'No auth export found',
416
- configPath: authConfigPath
417
- });
418
- }
419
-
420
- const organizationPlugin = auth.options?.plugins?.find((plugin: any) =>
421
- plugin.id === "organization"
422
- );
423
-
424
- const teamsEnabled = organizationPlugin?.teams?.enabled === true;
425
-
426
- res.json({
427
- enabled: teamsEnabled,
428
- configPath: authConfigPath,
429
- organizationPlugin: organizationPlugin || null
430
- });
431
-
432
- } catch (error) {
433
- console.error('Error checking teams plugin:', error);
434
- res.json({
435
- enabled: false,
436
- error: 'Failed to load auth config',
437
- configPath: authConfigPath
438
- });
439
- }
440
- } catch (error) {
441
- console.error('Error checking teams status:', error);
442
- res.status(500).json({ error: 'Failed to check teams status' });
443
- }
444
- });
445
-
446
- router.get('/api/organizations/:orgId/invitations', async (req: Request, res: Response) => {
447
- try {
448
- console.log('fetching invitations' , req.params)
449
- const { orgId } = req.params;
450
- const adapter = await getAuthAdapter();
451
- if (adapter && typeof adapter.findMany === 'function') {
452
- try {
453
- const invitations = await adapter.findMany({
454
- model: 'invitation',
455
- where: [
456
- { field: 'organizationId', value: orgId },
457
- { field: 'status', value: 'pending' }
458
- ],
459
- });
460
- const transformedInvitations = (invitations || []).map((invitation: any) => ({
461
- id: invitation.id,
462
- email: invitation.email,
463
- role: invitation.role || 'member',
464
- status: invitation.status || 'pending',
465
- organizationId: invitation.organizationId,
466
- teamId: invitation.teamId,
467
- inviterId: invitation.inviterId,
468
- expiresAt: invitation.expiresAt,
469
- createdAt: invitation.createdAt
470
- }));
471
- res.json({ success: true, invitations: transformedInvitations });
472
- return;
473
- } catch (error) {
474
- console.error('Error fetching invitations from adapter:', error);
475
- }
476
- }
477
-
478
- res.json({ success: true, invitations: [] });
479
- } catch (error) {
480
- console.error('Error fetching invitations:', error);
481
- res.status(500).json({ error: 'Failed to fetch invitations' });
482
- }
483
- });
484
-
485
- router.get('/api/organizations/:orgId/members', async (req: Request, res: Response) => {
486
- try {
487
- const { orgId } = req.params;
488
- const adapter = await getAuthAdapter();
489
-
490
- if (adapter && typeof adapter.findMany === 'function') {
491
- try {
492
- const members = await adapter.findMany({
493
- model: 'member',
494
- where: [{ field: 'organizationId', value: orgId }],
495
- limit: 10000
496
- });
497
- const membersWithUsers = await Promise.all((members || []).map(async (member: any) => {
498
- try {
499
- if (adapter.findMany) {
500
- const users = await adapter.findMany({
501
- model: 'user',
502
- where: [{ field: 'id', value: member.userId }],
503
- limit: 1
504
- });
505
- const user = users?.[0];
506
- return {
507
- id: member.id,
508
- userId: member.userId,
509
- organizationId: member.organizationId,
510
- role: member.role || 'member',
511
- joinedAt: member.joinedAt || member.createdAt,
512
- user: user ? {
513
- id: user.id,
514
- name: user.name,
515
- email: user.email,
516
- image: user.image,
517
- emailVerified: user.emailVerified
518
- } : null
519
- };
520
- }
521
- return null;
522
- } catch (error) {
523
- console.error('Error fetching user for member:', error);
524
- return null;
525
- }
526
- }));
527
-
528
- const validMembers = membersWithUsers.filter(member => member && member.user);
529
-
530
- res.json({ success: true, members: validMembers });
531
- return;
532
- } catch (error) {
533
- console.error('Error fetching members from adapter:', error);
534
- }
535
- }
536
-
537
- res.json({ success: true, members: [] });
538
- } catch (error) {
539
- console.error('Error fetching members:', error);
540
- res.status(500).json({ error: 'Failed to fetch members' });
541
- }
542
- });
543
-
544
- router.post('/api/organizations/:orgId/seed-members', async (req: Request, res: Response) => {
545
- try {
546
- const { orgId } = req.params;
547
- const { count = 5 } = req.body;
548
- const adapter = await getAuthAdapter();
549
-
550
- if (!adapter) {
551
- return res.status(500).json({ error: 'Auth adapter not available' });
552
- }
553
-
554
- if (!adapter.findMany || !adapter.create) {
555
- return res.status(500).json({ error: 'Adapter findMany method not available' });
556
- }
557
-
558
- const generateRandomString = (length: number) => {
559
- const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
560
- let result = '';
561
- for (let i = 0; i < length; i++) {
562
- result += chars.charAt(Math.floor(Math.random() * chars.length));
563
- }
564
- return result;
565
- };
566
-
567
- const results = [];
568
-
569
- for (let i = 0; i < count; i++) {
570
- try {
571
- const randomString = generateRandomString(8);
572
- const email = `user${randomString}@example.com`;
573
- const name = `User ${randomString}`;
574
-
575
- const userData = {
576
- name,
577
- email,
578
- emailVerified: false,
579
- createdAt: new Date(),
580
- updatedAt: new Date()
581
- };
582
-
583
- const user = await adapter.create({
584
- model: 'user',
585
- data: userData
586
- });
587
-
588
- const memberData = {
589
- organizationId: orgId,
590
- userId: user.id,
591
- role: 'member',
592
- createdAt: new Date()
593
- };
594
-
595
- await adapter.create({
596
- model: 'member',
597
- data: memberData
598
- });
599
-
600
- results.push({
601
- success: true,
602
- member: {
603
- userId: user.id,
604
- user: {
605
- name,
606
- email
607
- }
608
- }
609
- });
610
- } catch (error) {
611
- results.push({
612
- success: false,
613
- error: error instanceof Error ? error.message : 'Unknown error'
614
- });
615
- }
616
- }
617
-
618
- res.json({
619
- success: true,
620
- message: `Added ${results.filter(r => r.success).length} members`,
621
- results
622
- });
623
- } catch (error) {
624
- console.error('Error seeding members:', error);
625
- res.status(500).json({ error: 'Failed to seed members' });
626
- }
627
- });
628
-
629
- router.delete('/api/members/:id', async (req: Request, res: Response) => {
630
- try {
631
- const { id } = req.params;
632
- const adapter = await getAuthAdapter();
633
-
634
- if (!adapter) {
635
- return res.status(500).json({ error: 'Auth adapter not available' });
636
- }
637
-
638
- if (!adapter.delete) {
639
- return res.status(500).json({ error: 'Adapter delete method not available' });
640
- }
641
-
642
- await adapter.delete({
643
- model: 'member',
644
- where: [{ field: 'id', value: id }]
645
- });
646
-
647
- res.json({ success: true });
648
- } catch (error) {
649
- console.error('Error removing member:', error);
650
- res.status(500).json({ error: 'Failed to remove member' });
651
- }
652
- });
653
-
654
- router.post('/api/invitations/:id/resend', async (req: Request, res: Response) => {
655
- try {
656
- const { id } = req.params;
657
- const adapter = await getAuthAdapter();
658
-
659
- if (!adapter) {
660
- return res.status(500).json({ error: 'Auth adapter not available' });
661
- }
662
-
663
- if (!adapter.update) {
664
- return res.status(500).json({ error: 'Adapter update method not available' });
665
- }
666
-
667
- await adapter.update({
668
- model: 'invitation',
669
- where: [{ field: 'id', value: id }],
670
- update: {
671
- expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days from now
672
- updatedAt: new Date().toISOString()
673
- }
674
- });
675
-
676
- res.json({ success: true });
677
- } catch (error) {
678
- console.error('Error resending invitation:', error);
679
- res.status(500).json({ error: 'Failed to resend invitation' });
680
- }
681
- });
682
-
683
- router.delete('/api/invitations/:id', async (req: Request, res: Response) => {
684
- try {
685
- const { id } = req.params;
686
- const adapter = await getAuthAdapter();
687
-
688
- if (!adapter) {
689
- return res.status(500).json({ error: 'Auth adapter not available' });
690
- }
691
-
692
- if (!adapter.update) {
693
- return res.status(500).json({ error: 'Adapter update method not available' });
694
- }
695
-
696
- await adapter.update({
697
- model: 'invitation',
698
- where: [{ field: 'id', value: id }],
699
- update: {
700
- status: 'cancelled',
701
- updatedAt: new Date().toISOString()
702
- }
703
- });
704
-
705
- res.json({ success: true });
706
- } catch (error) {
707
- console.error('Error cancelling invitation:', error);
708
- res.status(500).json({ error: 'Failed to cancel invitation' });
709
- }
710
- });
711
-
712
- router.post('/api/organizations/:orgId/invitations', async (req: Request, res: Response) => {
713
- try {
714
- const { orgId } = req.params;
715
- const { email, role = 'member' } = req.body;
716
-
717
- const adapter = await getAuthAdapter();
718
- if (!adapter) {
719
- return res.status(500).json({ error: 'Auth adapter not available' });
720
- }
721
-
722
- const invitationData = {
723
- email,
724
- role,
725
- organizationId: orgId,
726
- status: 'pending',
727
- expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
728
- createdAt: new Date(),
729
- inviterId: 'admin' // In real app, get from session
730
- };
731
-
732
- const invitation = {
733
- id: `inv_${Date.now()}`,
734
- ...invitationData
735
- };
736
- if(!adapter.create) {
737
- return res.status(500).json({ error: 'Adapter create method not available' });
738
- }
739
- const adminId = "dQ2aAFgMwmRKvoqLiM1MCbjbka5g1Nzc"
740
- await adapter.create({
741
- model: 'invitation',
742
- data: {
743
- organizationId: invitationData.organizationId,
744
- email: invitationData.email,
745
- role: invitationData.role,
746
- status: invitationData.status,
747
- inviterId: adminId,
748
- expiresAt: invitationData.expiresAt,
749
- createdAt: invitationData.createdAt,
750
- }
751
- });
752
-
753
- res.json({ success: true, invitation });
754
- } catch (error) {
755
- console.error('Error creating invitation:', error);
756
- res.status(500).json({ error: 'Failed to create invitation' });
757
- }
758
- });
759
-
760
- router.get('/api/organizations/:orgId/teams', async (req: Request, res: Response) => {
761
- try {
762
- const { orgId } = req.params;
763
- const adapter = await getAuthAdapter();
764
-
765
- if (adapter && typeof adapter.findMany === 'function') {
766
- try {
767
- const teams = await adapter.findMany({
768
- model: 'team',
769
- where: [{ field: 'organizationId', value: orgId }],
770
- limit: 10000
771
- });
772
-
773
- const transformedTeams = await Promise.all((teams || []).map(async (team: any) => {
774
- if(!adapter.findMany) {
775
- return null
776
- }
777
- const teamMembers = await adapter.findMany({
778
- model: 'teamMember',
779
- where: [{ field: 'teamId', value: team.id }],
780
- limit: 10000
781
- });
782
-
783
- return {
784
- id: team.id,
785
- name: team.name,
786
- organizationId: team.organizationId,
787
- metadata: team.metadata,
788
- createdAt: team.createdAt,
789
- updatedAt: team.updatedAt,
790
- memberCount: teamMembers ? teamMembers.length : 0
791
- };
792
- }));
793
-
794
- res.json({ success: true, teams: transformedTeams });
795
- return;
796
- } catch (error) {
797
- console.error('Error fetching teams from adapter:', error);
798
- }
799
- }
800
-
801
- res.json({ success: true, teams: [] });
802
- } catch (error) {
803
- console.error('Error fetching teams:', error);
804
- res.status(500).json({ error: 'Failed to fetch teams' });
805
- }
806
- });
807
-
808
- router.post('/api/organizations/:orgId/teams', async (req: Request, res: Response) => {
809
- try {
810
- const { orgId } = req.params;
811
- const { name } = req.body;
812
-
813
- const adapter = await getAuthAdapter();
814
- if (!adapter) {
815
- return res.status(500).json({ error: 'Auth adapter not available' });
816
- }
817
-
818
- const teamData = {
819
- name,
820
- organizationId: orgId,
821
- createdAt: new Date(),
822
- updatedAt: new Date(),
823
- memberCount: 0
824
- };
825
-
826
- const team = {
827
- id: `team_${Date.now()}`,
828
- ...teamData
829
- };
830
- if(!adapter.create) {
831
- return res.status(500).json({ error: 'Adapter create method not available' });
832
- }
833
- await adapter.create({
834
- model: 'team',
835
- data: {
836
- name: teamData.name,
837
- organizationId: teamData.organizationId,
838
- createdAt: teamData.createdAt,
839
- updatedAt: teamData.updatedAt,
840
- }
841
- });
842
- res.json({ success: true, team });
843
- } catch (error) {
844
- console.error('Error creating team:', error);
845
- res.status(500).json({ error: 'Failed to create team' });
846
- }
847
- });
848
-
849
- router.get('/api/teams/:id', async (req: Request, res: Response) => {
850
- try {
851
- const { id } = req.params;
852
- const adapter = await getAuthAdapter();
853
-
854
- if (adapter && typeof adapter.findMany === 'function') {
855
- try {
856
- const teams = await adapter.findMany({
857
- model: 'team',
858
- where: [{ field: 'id', value: id }],
859
- limit: 1
860
- });
861
-
862
- const team = teams?.[0];
863
- if (team) {
864
- let organization = null;
865
- try {
866
- const orgs = await adapter.findMany({
867
- model: 'organization',
868
- where: [{ field: 'id', value: team.organizationId }],
869
- limit: 1
870
- });
871
- organization = orgs?.[0];
872
- } catch (error) {
873
- console.error('Error fetching organization for team:', error);
874
- }
875
-
876
- const transformedTeam = {
877
- id: team.id,
878
- name: team.name,
879
- organizationId: team.organizationId,
880
- metadata: team.metadata,
881
- createdAt: team.createdAt,
882
- updatedAt: team.updatedAt,
883
- memberCount: team.memberCount || 0,
884
- organization: organization ? {
885
- id: organization.id,
886
- name: organization.name
887
- } : null
888
- };
889
-
890
- res.json({ success: true, team: transformedTeam });
891
- return;
892
- }
893
- } catch (error) {
894
- console.error('Error fetching team from adapter:', error);
895
- }
896
- }
897
-
898
- res.status(404).json({ success: false, error: 'Team not found' });
899
- } catch (error) {
900
- console.error('Error fetching team:', error);
901
- res.status(500).json({ error: 'Failed to fetch team' });
902
- }
903
- });
904
-
905
- router.get('/api/teams/:teamId/members', async (req: Request, res: Response) => {
906
- try {
907
- const { teamId } = req.params;
908
- const adapter = await getAuthAdapter();
909
-
910
- if (adapter && typeof adapter.findMany === 'function') {
911
- try {
912
- const teamMembers = await adapter.findMany({
913
- model: 'teamMember',
914
- where: [{ field: 'teamId', value: teamId }],
915
- limit: 10000
916
- });
917
-
918
- const membersWithUsers = await Promise.all((teamMembers || []).map(async (member: any) => {
919
- try {
920
- if (adapter.findMany) {
921
- const users = await adapter.findMany({
922
- model: 'user',
923
- where: [{ field: 'id', value: member.userId }],
924
- limit: 1
925
- });
926
- const user = users?.[0];
927
-
928
- return {
929
- id: member.id,
930
- userId: member.userId,
931
- teamId: member.teamId,
932
- role: member.role || 'member',
933
- joinedAt: member.joinedAt || member.createdAt,
934
- user: user ? {
935
- id: user.id,
936
- name: user.name,
937
- email: user.email,
938
- image: user.image,
939
- emailVerified: user.emailVerified
940
- } : null
941
- };
942
- }
943
- return null;
944
- } catch (error) {
945
- console.error('Error fetching user for team member:', error);
946
- return null;
947
- }
948
- }));
949
-
950
- const validMembers = membersWithUsers.filter(member => member && member.user);
951
-
952
- res.json({ success: true, members: validMembers });
953
- return;
954
- } catch (error) {
955
- console.error('Error fetching team members from adapter:', error);
956
- }
957
- }
958
-
959
- res.json({ success: true, members: [] });
960
- } catch (error) {
961
- console.error('Error fetching team members:', error);
962
- res.status(500).json({ error: 'Failed to fetch team members' });
963
- }
964
- });
965
-
966
- router.post('/api/teams/:teamId/members', async (req: Request, res: Response) => {
967
- try {
968
- const { teamId } = req.params;
969
- const { userIds } = req.body;
970
-
971
- if (!Array.isArray(userIds) || userIds.length === 0) {
972
- return res.status(400).json({ error: 'userIds array is required' });
973
- }
974
-
975
- const adapter = await getAuthAdapter();
976
- if (!adapter || !adapter.create) {
977
- return res.status(500).json({ error: 'Adapter not available' });
978
- }
979
-
980
- const results = [];
981
- for (const userId of userIds) {
982
- try {
983
- await adapter.create({
984
- model: 'teamMember',
985
- data: {
986
- teamId,
987
- userId,
988
- role: 'member',
989
- createdAt: new Date()
990
- }
991
- });
992
-
993
- results.push({ success: true, userId });
994
- } catch (error) {
995
- results.push({
996
- success: false,
997
- userId,
998
- error: error instanceof Error ? error.message : 'Unknown error'
999
- });
1000
- }
1001
- }
1002
-
1003
- res.json({
1004
- success: true,
1005
- message: `Added ${results.filter(r => r.success).length} members`,
1006
- results
1007
- });
1008
- } catch (error) {
1009
- console.error('Error adding team members:', error);
1010
- res.status(500).json({ error: 'Failed to add team members' });
1011
- }
1012
- });
1013
-
1014
- router.delete('/api/team-members/:id', async (req: Request, res: Response) => {
1015
- try {
1016
- const { id } = req.params;
1017
- const adapter = await getAuthAdapter();
1018
-
1019
- if (!adapter || !adapter.delete) {
1020
- return res.status(500).json({ error: 'Adapter not available' });
1021
- }
1022
-
1023
- await adapter.delete({
1024
- model: 'teamMember',
1025
- where: [{ field: 'id', value: id }]
1026
- });
1027
-
1028
- res.json({ success: true });
1029
- } catch (error) {
1030
- console.error('Error removing team member:', error);
1031
- res.status(500).json({ error: 'Failed to remove team member' });
1032
- }
1033
- });
1034
-
1035
- router.put('/api/teams/:id', async (req: Request, res: Response) => {
1036
- try {
1037
- const { id } = req.params;
1038
- const { name } = req.body;
1039
- const adapter = await getAuthAdapter();
1040
- if(!adapter) {
1041
- return res.status(500).json({ error: 'Auth adapter not available' });
1042
- }
1043
- const updatedTeam = {
1044
- id,
1045
- name,
1046
- updatedAt: new Date().toISOString()
1047
- };
1048
- if(!adapter.update) {
1049
- return res.status(500).json({ error: 'Adapter update method not available' });
1050
- }
1051
- await adapter.update({
1052
- model: 'team',
1053
- where: [{ field: 'id', value: id }],
1054
- update: {
1055
- name: updatedTeam.name,
1056
- updatedAt: updatedTeam.updatedAt
1057
- }
1058
- });
1059
- res.json({ success: true, team: updatedTeam });
1060
- } catch (error) {
1061
- console.error('Error updating team:', error);
1062
- res.status(500).json({ error: 'Failed to update team' });
1063
- }
1064
- });
1065
-
1066
- router.delete('/api/teams/:id', async (req: Request, res: Response) => {
1067
- try {
1068
- const { id } = req.params;
1069
- const adapter = await getAuthAdapter();
1070
- if(!adapter) {
1071
- return res.status(500).json({ error: 'Auth adapter not available' });
1072
- }
1073
- if(!adapter.delete) {
1074
- return res.status(500).json({ error: 'Adapter delete method not available' });
1075
- }
1076
- await adapter.delete({
1077
- model: 'team',
1078
- where: [{ field: 'id', value: id }],
1079
- });
1080
- res.json({ success: true });
1081
- } catch (error) {
1082
- console.error('Error deleting team:', error);
1083
- res.status(500).json({ error: 'Failed to delete team' });
1084
- }
1085
- });
1086
-
1087
- router.get('/api/plugins/organization/status', async (req: Request, res: Response) => {
1088
- try {
1089
- const authConfigPath = await findAuthConfigPath();
1090
- if (!authConfigPath) {
1091
- return res.json({
1092
- enabled: false,
1093
- error: 'No auth config found',
1094
- configPath: null
1095
- });
1096
- }
1097
-
1098
- try {
1099
- const authModule = await import(authConfigPath);
1100
- const auth = authModule.auth || authModule.default;
1101
- console.log({ auth })
1102
- if (!auth) {
1103
- return res.json({
1104
- enabled: false,
1105
- error: 'No auth export found',
1106
- configPath: authConfigPath
1107
- });
1108
- }
1109
-
1110
- const hasOrganizationPlugin = auth.options?.plugins?.find((plugin: any) =>
1111
- plugin.id === "organization"
1112
- );
1113
- console.log({ hasOrganizationPlugin })
1114
-
1115
- res.json({
1116
- enabled: !!hasOrganizationPlugin,
1117
- configPath: authConfigPath,
1118
- availablePlugins: auth.options?.plugins?.map((p: any) => p.id) || [],
1119
- organizationPlugin: hasOrganizationPlugin || null
1120
- });
1121
-
1122
- } catch (error) {
1123
- console.error('Error checking organization plugin:', error);
1124
- res.json({
1125
- enabled: false,
1126
- error: 'Failed to load auth config',
1127
- configPath: authConfigPath
1128
- });
1129
- }
1130
- } catch (error) {
1131
- console.error('Error checking plugin status:', error);
1132
- res.status(500).json({ error: 'Failed to check plugin status' });
1133
- }
1134
- });
1135
-
1136
- router.get('/api/organizations', async (req: Request, res: Response) => {
1137
- try {
1138
- const page = parseInt(req.query.page as string) || 1;
1139
- const limit = parseInt(req.query.limit as string) || 20;
1140
- const search = req.query.search as string;
1141
-
1142
- try {
1143
- const adapter = await getAuthAdapter();
1144
- if (adapter && typeof adapter.findMany === 'function') {
1145
- const allOrganizations = await adapter.findMany({ model: 'organization' });
1146
- console.log('Found organizations via findMany:', allOrganizations?.length || 0);
1147
-
1148
- let filteredOrganizations = allOrganizations || [];
1149
- if (search) {
1150
- filteredOrganizations = filteredOrganizations.filter((org: any) =>
1151
- org.name?.toLowerCase().includes(search.toLowerCase()) ||
1152
- org.slug?.toLowerCase().includes(search.toLowerCase())
1153
- );
1154
- }
1155
-
1156
- const startIndex = (page - 1) * limit;
1157
- const endIndex = startIndex + limit;
1158
- const paginatedOrganizations = filteredOrganizations.slice(startIndex, endIndex);
1159
-
1160
- const transformedOrganizations = paginatedOrganizations.map((org: any) => ({
1161
- id: org.id,
1162
- name: org.name,
1163
- slug: org.slug,
1164
- metadata: org.metadata,
1165
- createdAt: org.createdAt,
1166
- updatedAt: org.updatedAt,
1167
- }));
1168
-
1169
- res.json({ organizations: transformedOrganizations });
1170
- return;
1171
- }
1172
- } catch (adapterError) {
1173
- console.error('Error fetching organizations from adapter:', adapterError);
1174
- }
1175
-
1176
- const mockOrganizations = [
1177
- {
1178
- id: 'org_1',
1179
- name: 'Acme Corp',
1180
- slug: 'acme-corp',
1181
- metadata: { status: 'active' },
1182
- createdAt: new Date().toISOString(),
1183
- updatedAt: new Date().toISOString()
1184
- },
1185
- {
1186
- id: 'org_2',
1187
- name: 'Tech Solutions',
1188
- slug: 'tech-solutions',
1189
- metadata: { status: 'active' },
1190
- createdAt: new Date().toISOString(),
1191
- updatedAt: new Date().toISOString()
1192
- }
1193
- ];
1194
-
1195
- res.json({ organizations: mockOrganizations });
1196
- } catch (error) {
1197
- console.error('Error fetching organizations:', error);
1198
- res.status(500).json({ error: 'Failed to fetch organizations' });
1199
- }
1200
- });
1201
-
1202
- router.post('/api/organizations', async (req: Request, res: Response) => {
1203
- try {
1204
- const adapter = await getAuthAdapter();
1205
- if (!adapter) {
1206
- return res.status(500).json({ error: 'Auth adapter not available' });
1207
- }
1208
-
1209
- const orgData = req.body;
1210
-
1211
- if (!orgData.slug && orgData.name) {
1212
- orgData.slug = orgData.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
1213
- }
1214
-
1215
- const organization = await adapter.createOrganization(orgData);
1216
- res.json({ success: true, organization });
1217
- } catch (error) {
1218
- console.error('Error creating organization:', error);
1219
- res.status(500).json({ error: 'Failed to create organization' });
1220
- }
1221
- });
1222
-
1223
- router.put('/api/organizations/:id', async (req: Request, res: Response) => {
1224
- try {
1225
- const { id } = req.params;
1226
- const orgData = req.body;
1227
- const adapter: any = await getAuthAdapter();
1228
- if (!adapter) {
1229
- return res.status(500).json({ error: 'Auth adapter not available' });
1230
- }
1231
- if (orgData.name && !orgData.slug) {
1232
- orgData.slug = orgData.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
1233
- }
1234
-
1235
- const updatedOrganization = {
1236
- id,
1237
- ...orgData,
1238
- updatedAt: new Date().toISOString()
1239
- };
1240
- const updatedOrg = await adapter.update({
1241
- model: 'organization',
1242
- where: [
1243
- { field: 'id', value: id }
1244
- ],
1245
- update: updatedOrganization
1246
- });
1247
- res.json({ success: true, organization: updatedOrg });
1248
- } catch (error) {
1249
- console.error('Error updating organization:', error);
1250
- res.status(500).json({ error: 'Failed to update organization' });
1251
- }
1252
- });
1253
-
1254
- router.get('/api/organizations/:id', async (req: Request, res: Response) => {
1255
- try {
1256
- const { id } = req.params;
1257
- const adapter = await getAuthAdapter();
1258
-
1259
- if (adapter && typeof adapter.findMany === 'function') {
1260
- const organizations = await adapter.findMany({ model: 'organization', limit: 10000 });
1261
- const organization = organizations?.find((org: any) => org.id === id);
1262
-
1263
- if (organization) {
1264
- const transformedOrganization = {
1265
- id: organization.id,
1266
- name: organization.name,
1267
- slug: organization.slug,
1268
- metadata: organization.metadata,
1269
- createdAt: organization.createdAt,
1270
- updatedAt: organization.updatedAt,
1271
- };
1272
-
1273
- res.json({ success: true, organization: transformedOrganization });
1274
- return;
1275
- }
1276
- }
1277
-
1278
- res.status(404).json({ success: false, error: 'Organization not found' });
1279
- } catch (error) {
1280
- console.error('Error fetching organization:', error);
1281
- res.status(500).json({ error: 'Failed to fetch organization' });
1282
- }
1283
- });
1284
-
1285
- router.delete('/api/organizations/:id', async (req: Request, res: Response) => {
1286
- try {
1287
- const { id } = req.params;
1288
- const adapter: any = await getAuthAdapter();
1289
- if (!adapter) {
1290
- return res.status(500).json({ error: 'Auth adapter not available' });
1291
- }
1292
- const deletedOrg = await adapter.delete({
1293
- model: 'organization',
1294
- where: [
1295
- { field: 'id', value: id }
1296
- ]
1297
- });
1298
- res.json({ success: true, organization: deletedOrg });
1299
- } catch (error) {
1300
- console.error('Error deleting organization:', error);
1301
- res.status(500).json({ error: 'Failed to delete organization' });
1302
- }
1303
- });
1304
-
1305
- router.post('/api/users', async (req: Request, res: Response) => {
1306
- try {
1307
- const adapter = await getAuthAdapter();
1308
- if (!adapter) {
1309
- return res.status(500).json({ error: 'Auth adapter not available' });
1310
- }
1311
-
1312
- const userData = req.body;
1313
- const user = await adapter.createUser(userData);
1314
- res.json({ success: true, user });
1315
- } catch (error) {
1316
- console.error('Error creating user:', error);
1317
- res.status(500).json({ error: 'Failed to create user' });
1318
- }
1319
- });
1320
-
1321
- router.put('/api/users/:id', async (req: Request, res: Response) => {
1322
- try {
1323
- const { id } = req.params;
1324
- const userData = req.body;
1325
-
1326
- const updatedUser = await getAuthData(authConfig, 'updateUser', { id, userData });
1327
- res.json({ success: true, user: updatedUser });
1328
- } catch (error) {
1329
- console.error('Error updating user:', error);
1330
- res.status(500).json({ error: 'Failed to update user' });
1331
- }
1332
- });
1333
-
1334
- router.post('/api/seed/users', async (req: Request, res: Response) => {
1335
- try {
1336
- const { count = 1 } = req.body;
1337
- const adapter = await getAuthAdapter();
1338
- console.log({ adapter })
1339
- if (!adapter) {
1340
- return res.status(500).json({ error: 'Auth adapter not available' });
1341
- }
1342
-
1343
- const results = [];
1344
- for (let i = 0; i < count; i++) {
1345
- try {
1346
- if (typeof adapter.createUser !== 'function') {
1347
- throw new Error('createUser method not available on adapter');
1348
- }
1349
-
1350
- const user = await createMockUser(adapter, i + 1);
1351
- results.push({
1352
- success: true,
1353
- user: {
1354
- id: user.id,
1355
- email: user.email,
1356
- name: user.name,
1357
- emailVerified: user.emailVerified,
1358
- image: user.image,
1359
- createdAt: user.createdAt
1360
- }
1361
- });
1362
- } catch (error) {
1363
- results.push({
1364
- success: false,
1365
- error: error instanceof Error ? error.message : 'Unknown error'
1366
- });
1367
- }
1368
- }
1369
-
1370
- res.json({
1371
- success: true,
1372
- message: `Seeded ${results.filter(r => r.success).length} users`,
1373
- results
1374
- });
1375
- } catch (error) {
1376
- console.error('Error seeding users:', error);
1377
- res.status(500).json({ error: 'Failed to seed users' });
1378
- }
1379
- });
1380
-
1381
- router.post('/api/seed/sessions', async (req: Request, res: Response) => {
1382
- try {
1383
- const { count = 1 } = req.body;
1384
- const adapter = await getAuthAdapter();
1385
-
1386
- if (!adapter) {
1387
- return res.status(500).json({ error: 'Auth adapter not available' });
1388
- }
1389
-
1390
- let user;
1391
- try {
1392
- user = await createMockUser(adapter, 1);
1393
- } catch (error) {
1394
- return res.status(500).json({ error: 'Failed to create user for session' });
1395
- }
1396
-
1397
- const results = [];
1398
- for (let i = 0; i < count; i++) {
1399
- try {
1400
- if (typeof adapter.createSession !== 'function') {
1401
- throw new Error('createSession method not available on adapter');
1402
- }
1403
-
1404
- const session = await createMockSession(adapter, user.id, i + 1);
1405
- results.push({
1406
- success: true,
1407
- session: {
1408
- id: session.id,
1409
- userId: session.userId,
1410
- expires: session.expires,
1411
- sessionToken: session.sessionToken,
1412
- createdAt: session.createdAt
1413
- }
1414
- });
1415
- } catch (error) {
1416
- results.push({
1417
- success: false,
1418
- error: error instanceof Error ? error.message : 'Unknown error'
1419
- });
1420
- }
1421
- }
1422
-
1423
- res.json({
1424
- success: true,
1425
- message: `Seeded ${results.filter(r => r.success).length} sessions`,
1426
- results
1427
- });
1428
- } catch (error) {
1429
- console.error('Error seeding sessions:', error);
1430
- res.status(500).json({ error: 'Failed to seed sessions' });
1431
- }
1432
- });
1433
-
1434
- router.post('/api/seed/accounts', async (req: Request, res: Response) => {
1435
- try {
1436
- const { count = 1 } = req.body;
1437
- const adapter = await getAuthAdapter();
1438
-
1439
- if (!adapter) {
1440
- return res.status(500).json({ error: 'Auth adapter not available' });
1441
- }
1442
-
1443
- let user;
1444
- try {
1445
- user = await createMockUser(adapter, 1);
1446
- } catch (error) {
1447
- return res.status(500).json({ error: 'Failed to create user for account' });
1448
- }
1449
-
1450
- const results = [];
1451
- for (let i = 0; i < count; i++) {
1452
- try {
1453
- if (typeof adapter.createAccount !== 'function') {
1454
- throw new Error('createAccount method not available on adapter');
1455
- }
1456
-
1457
- const account = await createMockAccount(adapter, user.id, i + 1);
1458
- results.push({
1459
- success: true,
1460
- account: {
1461
- id: account.id,
1462
- userId: account.userId,
1463
- type: account.type,
1464
- provider: account.provider,
1465
- providerAccountId: account.providerAccountId,
1466
- createdAt: account.createdAt
1467
- }
1468
- });
1469
- } catch (error) {
1470
- results.push({
1471
- success: false,
1472
- error: error instanceof Error ? error.message : 'Unknown error'
1473
- });
1474
- }
1475
- }
1476
-
1477
- res.json({
1478
- success: true,
1479
- message: `Seeded ${results.filter(r => r.success).length} accounts`,
1480
- results
1481
- });
1482
- } catch (error) {
1483
- console.error('Error seeding accounts:', error);
1484
- res.status(500).json({ error: 'Failed to seed accounts' });
1485
- }
1486
- });
1487
-
1488
- router.post('/api/seed/verifications', async (req: Request, res: Response) => {
1489
- try {
1490
- const { count = 1 } = req.body;
1491
- const adapter = await getAuthAdapter();
1492
-
1493
- if (!adapter) {
1494
- return res.status(500).json({ error: 'Auth adapter not available' });
1495
- }
1496
-
1497
- const results = [];
1498
- for (let i = 0; i < count; i++) {
1499
- try {
1500
- if (typeof adapter.createVerification !== 'function') {
1501
- throw new Error('createVerification method not available on adapter');
1502
- }
1503
-
1504
- const verification = await createMockVerification(adapter, `user${i + 1}@example.com`, i + 1);
1505
- results.push({
1506
- success: true,
1507
- verification: {
1508
- id: verification.id,
1509
- identifier: verification.identifier,
1510
- token: verification.token,
1511
- expires: verification.expires,
1512
- createdAt: verification.createdAt
1513
- }
1514
- });
1515
- } catch (error) {
1516
- results.push({
1517
- success: false,
1518
- error: error instanceof Error ? error.message : 'Unknown error'
1519
- });
1520
- }
1521
- }
1522
-
1523
- res.json({
1524
- success: true,
1525
- message: `Seeded ${results.filter(r => r.success).length} verifications`,
1526
- results
1527
- });
1528
- } catch (error) {
1529
- console.error('Error seeding verifications:', error);
1530
- res.status(500).json({ error: 'Failed to seed verifications' });
1531
- }
1532
- });
1533
-
1534
- router.post('/api/seed/organizations', async (req: Request, res: Response) => {
1535
- try {
1536
- const { count = 1 } = req.body;
1537
- const adapter = await getAuthAdapter();
1538
-
1539
- if (!adapter) {
1540
- return res.status(500).json({ error: 'Auth adapter not available' });
1541
- }
1542
-
1543
- const results = [];
1544
- for (let i = 0; i < count; i++) {
1545
- try {
1546
- const organizationData = {
1547
- name: `Organization ${i + 1}`,
1548
- slug: `org-${i + 1}`,
1549
- image: `https://api.dicebear.com/7.x/identicon/svg?seed=org${i + 1}`,
1550
- createdAt: new Date(),
1551
- updatedAt: new Date()
1552
- };
1553
-
1554
- const organization = await adapter.createOrganization(organizationData);
1555
- results.push({
1556
- success: true,
1557
- organization: {
1558
- id: organization.id,
1559
- name: organization.name,
1560
- slug: organization.slug,
1561
- image: organization.image,
1562
- createdAt: organization.createdAt
1563
- }
1564
- });
1565
- } catch (error) {
1566
- results.push({
1567
- success: false,
1568
- error: error instanceof Error ? error.message : 'Unknown error'
1569
- });
1570
- }
1571
- }
1572
-
1573
- res.json({
1574
- success: true,
1575
- message: `Seeded ${results.filter(r => r.success).length} organizations`,
1576
- results
1577
- });
1578
- } catch (error) {
1579
- console.error('Error seeding organizations:', error);
1580
- res.status(500).json({ error: 'Failed to seed organizations' });
1581
- }
1582
- });
1583
-
1584
- return router;
1585
- }