Skip to content

Commit 14e1f4e

Browse files
Copilothotlong
andcommitted
Fix resource cleanup and improve type safety in plugin-better-auth
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 5512f5a commit 14e1f4e

File tree

2 files changed

+95
-36
lines changed

2 files changed

+95
-36
lines changed

packages/plugins/better-auth/src/auth-client.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
let authInstance: any;
9+
let dbConnection: any; // Store database connection for cleanup
910

1011
export interface BetterAuthConfig {
1112
databaseUrl?: string;
@@ -29,21 +30,24 @@ export const getBetterAuth = async (config: BetterAuthConfig = {}) => {
2930
// Initialize database connection based on database type
3031
if (isPostgres) {
3132
const { Pool } = await import("pg");
32-
database = new Pool({
33+
dbConnection = new Pool({
3334
connectionString: dbUrl!
3435
});
36+
database = dbConnection;
3537
} else if (isMongo) {
3638
const { MongoClient } = await import("mongodb");
3739
const client = new MongoClient(dbUrl!);
3840
await client.connect();
41+
dbConnection = client;
3942
database = client.db();
4043
} else {
4144
const sqlite3Import = await import("better-sqlite3");
4245
// Handle both ESM/Interop (default export) and CJS (direct export)
4346
const Database = (sqlite3Import.default || sqlite3Import) as any;
44-
const filename = (dbUrl && dbUrl.replace('sqlite:', '')) ? (dbUrl && dbUrl.replace('sqlite:', '')) : 'objectos.db';
47+
const filename = (dbUrl?.replace('sqlite:', '')) || 'objectos.db';
4548
console.log(`[Better-Auth Plugin] Initializing with SQLite database: ${filename}`);
46-
database = new Database(filename);
49+
dbConnection = new Database(filename);
50+
database = dbConnection;
4751
}
4852

4953
// Configure Better-Auth with organization and role plugins
@@ -105,7 +109,13 @@ export const getBetterAuth = async (config: BetterAuthConfig = {}) => {
105109
};
106110
} catch (e) {
107111
console.error("[Better-Auth Plugin] Error in user create hook:", e);
108-
return { data: user };
112+
// Ensure a default role is set even in error cases
113+
return {
114+
data: {
115+
...user,
116+
role: 'user'
117+
}
118+
};
109119
}
110120
}
111121
}
@@ -151,8 +161,29 @@ export const getBetterAuth = async (config: BetterAuthConfig = {}) => {
151161
}
152162
};
153163

154-
export const resetAuthInstance = () => {
164+
export const resetAuthInstance = async () => {
165+
// Close database connections before resetting
166+
if (dbConnection) {
167+
try {
168+
// Check connection type and close appropriately
169+
if (dbConnection.end) {
170+
// PostgreSQL Pool
171+
await dbConnection.end();
172+
} else if (dbConnection.close) {
173+
// MongoDB client or SQLite
174+
if (dbConnection.close.constructor.name === 'AsyncFunction') {
175+
await dbConnection.close();
176+
} else {
177+
dbConnection.close();
178+
}
179+
}
180+
console.log('[Better-Auth Plugin] Database connection closed');
181+
} catch (e) {
182+
console.error('[Better-Auth Plugin] Error closing database connection:', e);
183+
}
184+
}
155185
authInstance = undefined;
186+
dbConnection = undefined;
156187
};
157188

158-
export default { getBetterAuth, resetAuthInstance };
189+
export { getBetterAuth as default };

packages/plugins/better-auth/src/plugin.ts

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,19 @@
1212
*/
1313

1414
import type { PluginDefinition, PluginContextData, ObjectStackManifest } from '@objectstack/spec/system';
15-
import { getBetterAuth, BetterAuthConfig } from './auth-client';
15+
import { getBetterAuth, resetAuthInstance, BetterAuthConfig } from './auth-client';
16+
17+
/**
18+
* Extended app context with router and eventBus
19+
*/
20+
interface ExtendedAppContext {
21+
router?: {
22+
all?: (path: string, handler: (req: any, res: any) => any) => void;
23+
};
24+
eventBus?: {
25+
emit?: (event: string, data: any) => void;
26+
};
27+
}
1628

1729
/**
1830
* Plugin Manifest
@@ -83,9 +95,9 @@ export const createBetterAuthPlugin = (options: BetterAuthPluginOptions = {}): P
8395
const handler = toNodeHandler(auth);
8496

8597
// Mount the auth handler on all /api/auth/* routes
86-
const router = (context.app as any).router;
87-
if (router && typeof router.all === 'function') {
88-
router.all('/api/auth/*', async (req: any, res: any) => {
98+
const app = context.app as ExtendedAppContext;
99+
if (app.router && typeof app.router.all === 'function') {
100+
app.router.all('/api/auth/*', async (req: any, res: any) => {
89101
// Pass the request to Better-Auth handler
90102
return handler(req, res);
91103
});
@@ -95,18 +107,18 @@ export const createBetterAuthPlugin = (options: BetterAuthPluginOptions = {}): P
95107
}
96108

97109
// Emit plugin enabled event
98-
const eventBus = (context.app as any).eventBus;
99-
if (eventBus && typeof eventBus.emit === 'function') {
100-
eventBus.emit('plugin.enabled', {
110+
if (app.eventBus && typeof app.eventBus.emit === 'function') {
111+
app.eventBus.emit('plugin.enabled', {
101112
pluginId: BetterAuthManifest.id,
102113
timestamp: new Date().toISOString()
103114
});
104115
}
105116

106117
context.logger.info('[Better-Auth Plugin] Enabled successfully');
107118
} catch (error) {
108-
context.logger.error('[Better-Auth Plugin] Failed to enable:', error);
109-
throw error;
119+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
120+
context.logger.error(`[Better-Auth Plugin] Failed to enable: ${errorMessage}`, error);
121+
throw new Error(`Better-Auth Plugin initialization failed: ${errorMessage}`);
110122
}
111123
},
112124

@@ -116,19 +128,27 @@ export const createBetterAuthPlugin = (options: BetterAuthPluginOptions = {}): P
116128
async onDisable(context: PluginContextData) {
117129
context.logger.info('[Better-Auth Plugin] Disabling...');
118130

119-
// Store last disabled timestamp
120-
await context.storage.set('last_disabled', new Date().toISOString());
121-
122-
// Emit plugin disabled event
123-
const eventBus = (context.app as any).eventBus;
124-
if (eventBus && typeof eventBus.emit === 'function') {
125-
eventBus.emit('plugin.disabled', {
126-
pluginId: BetterAuthManifest.id,
127-
timestamp: new Date().toISOString()
128-
});
131+
try {
132+
// Close database connections and reset auth instance
133+
await resetAuthInstance();
134+
135+
// Store last disabled timestamp
136+
await context.storage.set('last_disabled', new Date().toISOString());
137+
138+
// Emit plugin disabled event
139+
const app = context.app as ExtendedAppContext;
140+
if (app.eventBus && typeof app.eventBus.emit === 'function') {
141+
app.eventBus.emit('plugin.disabled', {
142+
pluginId: BetterAuthManifest.id,
143+
timestamp: new Date().toISOString()
144+
});
145+
}
146+
147+
context.logger.info('[Better-Auth Plugin] Disabled successfully');
148+
} catch (error) {
149+
context.logger.error('[Better-Auth Plugin] Error during disable:', error);
150+
throw error;
129151
}
130-
131-
context.logger.info('[Better-Auth Plugin] Disabled');
132152
},
133153

134154
/**
@@ -137,15 +157,23 @@ export const createBetterAuthPlugin = (options: BetterAuthPluginOptions = {}): P
137157
async onUninstall(context: PluginContextData) {
138158
context.logger.info('[Better-Auth Plugin] Uninstalling...');
139159

140-
// Cleanup plugin storage
141-
await context.storage.delete('install_date');
142-
await context.storage.delete('last_disabled');
143-
await context.storage.delete('config');
144-
145-
// Note: User data in the database is NOT automatically deleted
146-
// This should be handled by the administrator
147-
148-
context.logger.warn('[Better-Auth Plugin] Uninstalled - User authentication data preserved in database');
160+
try {
161+
// Close database connections and reset auth instance
162+
await resetAuthInstance();
163+
164+
// Cleanup plugin storage
165+
await context.storage.delete('install_date');
166+
await context.storage.delete('last_disabled');
167+
await context.storage.delete('config');
168+
169+
// Note: User data in the database is NOT automatically deleted
170+
// This should be handled by the administrator
171+
172+
context.logger.warn('[Better-Auth Plugin] Uninstalled - User authentication data preserved in database');
173+
} catch (error) {
174+
context.logger.error('[Better-Auth Plugin] Error during uninstall:', error);
175+
throw error;
176+
}
149177
},
150178
};
151179
};

0 commit comments

Comments
 (0)