UNPKG

plugin-postgresql-connector

Version:

NocoBase plugin for connecting to external PostgreSQL databases

229 lines (196 loc) 9.26 kB
// PostgreSQL Connector Plugin - Server Entry Point // This file will be implemented in Phase 5: Integration import { Plugin } from '@nocobase/server'; import { ConnectionManager } from './services/ConnectionManager'; import { QueryExecutor } from './services/QueryExecutor'; import { SchemaService } from './services/SchemaService'; import { ConnectionController } from './controllers/connection'; import { QueryController } from './controllers/query'; import { SchemaController } from './controllers/schema'; import path from 'path'; export class PostgreSQLConnectorPlugin extends Plugin { private connectionManager: ConnectionManager; private queryExecutor: QueryExecutor; private schemaService: SchemaService; async afterAdd() { // Initialize services this.connectionManager = new ConnectionManager(); this.queryExecutor = new QueryExecutor(this.connectionManager); this.schemaService = new SchemaService(this.connectionManager); // Register database migrations this.db.addMigrations({ namespace: 'postgresql-connector', directory: path.resolve(__dirname, '../migrations'), }); console.log('PostgreSQL Connector Plugin: Services initialized'); } async beforeLoad() { // Initialize controllers const connectionController = new ConnectionController(this.connectionManager); const queryController = new QueryController(this.connectionManager, this.queryExecutor); const schemaController = new SchemaController(this.connectionManager, this.schemaService); // Register Connection API resources this.app.resource({ name: 'postgresql-connections', actions: { create: connectionController.create.bind(connectionController), test: connectionController.test.bind(connectionController), list: connectionController.list.bind(connectionController), destroy: connectionController.delete.bind(connectionController), update: connectionController.update.bind(connectionController), get: connectionController.get.bind(connectionController), getStatistics: connectionController.getStatistics.bind(connectionController), }, }); // Register Query API resources this.app.resource({ name: 'postgresql-query', actions: { execute: queryController.execute.bind(queryController), executeProcedure: queryController.executeProcedure.bind(queryController), executeFunction: queryController.executeFunction.bind(queryController), getViewData: queryController.getViewData.bind(queryController), getTableData: queryController.getTableData.bind(queryController), getStatistics: queryController.getQueryStatistics.bind(queryController), clearCache: queryController.clearQueryCache.bind(queryController), }, }); // Register Saved Query API resources this.app.resource({ name: 'postgresql-saved-queries', actions: { create: queryController.saveQuery.bind(queryController), list: queryController.getSavedQueries.bind(queryController), get: queryController.getSavedQuery.bind(queryController), destroy: queryController.deleteSavedQuery.bind(queryController), execute: queryController.executeSavedQuery.bind(queryController), }, }); // Register Schema API resources this.app.resource({ name: 'postgresql-schema', actions: { getDatabaseInfo: schemaController.getDatabaseInfo.bind(schemaController), getStatistics: schemaController.getSchemaStatistics.bind(schemaController), getTables: schemaController.getTables.bind(schemaController), getTableColumns: schemaController.getTableColumns.bind(schemaController), getViews: schemaController.getViews.bind(schemaController), getFunctions: schemaController.getFunctions.bind(schemaController), searchObjects: schemaController.searchObjects.bind(schemaController), getOverview: schemaController.getSchemaOverview.bind(schemaController), }, }); // Configure ACL permissions this.app.acl.allow('postgresql-connections', '*', 'loggedIn'); this.app.acl.allow('postgresql-query', '*', 'loggedIn'); this.app.acl.allow('postgresql-saved-queries', '*', 'loggedIn'); this.app.acl.allow('postgresql-schema', '*', 'loggedIn'); // Add specific route patterns for RESTful APIs this.app.acl.allow('postgresql-connections', 'create', 'loggedIn'); this.app.acl.allow('postgresql-connections', 'test', 'loggedIn'); this.app.acl.allow('postgresql-connections', 'list', 'loggedIn'); this.app.acl.allow('postgresql-connections', 'get', 'loggedIn'); this.app.acl.allow('postgresql-connections', 'update', 'loggedIn'); this.app.acl.allow('postgresql-connections', 'destroy', 'loggedIn'); this.app.acl.allow('postgresql-query', 'execute', 'loggedIn'); this.app.acl.allow('postgresql-query', 'executeProcedure', 'loggedIn'); this.app.acl.allow('postgresql-query', 'executeFunction', 'loggedIn'); this.app.acl.allow('postgresql-query', 'getViewData', 'loggedIn'); this.app.acl.allow('postgresql-query', 'getTableData', 'loggedIn'); this.app.acl.allow('postgresql-saved-queries', 'create', 'loggedIn'); this.app.acl.allow('postgresql-saved-queries', 'list', 'loggedIn'); this.app.acl.allow('postgresql-saved-queries', 'get', 'loggedIn'); this.app.acl.allow('postgresql-saved-queries', 'destroy', 'loggedIn'); this.app.acl.allow('postgresql-saved-queries', 'execute', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getDatabaseInfo', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getStatistics', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getTables', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getTableColumns', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getViews', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getFunctions', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'searchObjects', 'loggedIn'); this.app.acl.allow('postgresql-schema', 'getOverview', 'loggedIn'); console.log('PostgreSQL Connector Plugin: API resources registered'); } async load() { // Register frontend components this.app.addComponents({ PostgreSQLConnector: () => import('../client'), }); // Add plugin settings to menu this.app.pluginSettingsManager.add('postgresql-connector', { title: '{{t("PostgreSQL Connector")}}', icon: 'DatabaseOutlined', Component: 'PostgreSQLConnector', aclSnippet: 'postgresql-connector.*', }); // Add package to frontend (for client-side rendering) this.app.pm.addPackageToFront({ packageName: '@nocobase/plugin-postgresql-connector', }); // Register health check endpoint this.app.resource({ name: 'postgresql-health', actions: { check: async (ctx) => { try { const stats = { connectionManager: { activeConnections: this.connectionManager.getActiveConnectionsCount(), statistics: this.connectionManager.getStatistics(), }, queryExecutor: { statistics: this.queryExecutor.getStatistics(), }, serviceStatus: 'healthy', timestamp: new Date().toISOString(), }; ctx.body = { success: true, data: stats, }; } catch (error) { ctx.throw(500, `Health check failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } }, }, }); this.app.acl.allow('postgresql-health', 'check', 'loggedIn'); console.log('PostgreSQL Connector Plugin: Frontend components loaded'); } async install() { // Run database migrations await this.db.sync(); console.log('PostgreSQL Connector Plugin: Database tables created'); } async destroy() { // Cleanup connections when plugin is destroyed if (this.connectionManager) { await this.connectionManager.closeAllConnections(); this.app.logger.info('PostgreSQL Connector Plugin: All connections closed'); } // Clear query cache if (this.queryExecutor) { this.queryExecutor.clearCache(); this.app.logger.info('PostgreSQL Connector Plugin: Query cache cleared'); } console.log('PostgreSQL Connector Plugin: Cleanup completed'); } async enable() { this.app.logger.info('PostgreSQL Connector Plugin: Enabled successfully'); } async disable() { // Close connections when plugin is disabled if (this.connectionManager) { await this.connectionManager.closeAllConnections(); } this.app.logger.info('PostgreSQL Connector Plugin: Disabled successfully'); } getName(): string { return 'postgresql-connector'; } getVersion(): string { return '1.0.0'; } } export default PostgreSQLConnectorPlugin;