@medyll/idae-api 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +240 -0
- package/dist/client/IdaeApiClient.d.ts +21 -0
- package/dist/client/IdaeApiClient.js +31 -0
- package/dist/client/IdaeApiClientCollection.d.ts +14 -0
- package/dist/client/IdaeApiClientCollection.js +53 -0
- package/dist/client/IdaeApiClientConfig.d.ts +23 -0
- package/dist/client/IdaeApiClientConfig.js +43 -0
- package/dist/client/IdaeApiClientRequest.d.ts +24 -0
- package/dist/client/IdaeApiClientRequest.js +47 -0
- package/dist/config/routeDefinitions.d.ts +10 -0
- package/dist/config/routeDefinitions.js +48 -0
- package/dist/idae-api.d.ts +15 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/server/IdaeApi.d.ts +38 -0
- package/dist/server/IdaeApi.js +213 -0
- package/dist/server/adapters/MongoDBAdapter.d.ts +20 -0
- package/dist/server/adapters/MongoDBAdapter.js +66 -0
- package/dist/server/adapters/MySQLAdapter.d.ts +23 -0
- package/dist/server/adapters/MySQLAdapter.js +78 -0
- package/dist/server/adapters/types.d.ts +12 -0
- package/dist/server/engine/DatabaseManager.d.ts +26 -0
- package/dist/server/engine/DatabaseManager.js +60 -0
- package/dist/server/engine/mongooseConnectionManager.d.ts +11 -0
- package/dist/server/engine/mongooseConnectionManager.js +25 -0
- package/dist/server/engine/routeManager.d.ts +13 -0
- package/dist/server/engine/routeManager.js +38 -0
- package/dist/server/engine/types.d.ts +10 -0
- package/dist/server/engine/types.js +1 -0
- package/dist/server/middleware/authMiddleware.d.ts +15 -0
- package/dist/server/middleware/authMiddleware.js +83 -0
- package/dist/server/middleware/databaseMiddleware.d.ts +2 -0
- package/dist/server/middleware/databaseMiddleware.js +15 -0
- package/dist/server/services/AuthService.d.ts +13 -0
- package/dist/server/services/AuthService.js +56 -0
- package/dist/server/services/DBaseService.d.ts +17 -0
- package/dist/server/services/DBaseService.js +62 -0
- package/package.json +31 -20
- package/dist/ApiServe.d.ts +0 -10
- package/dist/ApiServe.js +0 -113
- package/dist/engine/DBaseManager.d.ts +0 -15
- package/dist/engine/DBaseManager.js +0 -49
- package/dist/engine/DBaseService.d.ts +0 -16
- package/dist/engine/DBaseService.js +0 -48
- package/dist/engine/tools.d.ts +0 -2
- package/dist/engine/tools.js +0 -11
- package/dist/engine/types.d.ts +0 -9
- /package/dist/{engine → server/adapters}/types.js +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// packages\idae-api\src\lib\IdaeApi.ts
|
|
2
|
+
// version feat
|
|
3
|
+
import express, {} from 'express';
|
|
4
|
+
import { databaseMiddleware } from './middleware/databaseMiddleware';
|
|
5
|
+
import { DBaseService } from './services/DBaseService';
|
|
6
|
+
import { routes as defaultRoutes } from '../config/routeDefinitions';
|
|
7
|
+
import { AuthMiddleWare } from './middleware/authMiddleware';
|
|
8
|
+
import { RouteManager } from './engine/routeManager';
|
|
9
|
+
class IdaeApi {
|
|
10
|
+
constructor() {
|
|
11
|
+
this._state = 'stopped';
|
|
12
|
+
this.authMiddleware = null;
|
|
13
|
+
this._app = express();
|
|
14
|
+
this.options = {};
|
|
15
|
+
this.routeManager = RouteManager.getInstance();
|
|
16
|
+
this.initializeAuth();
|
|
17
|
+
this.configureIdaeApi();
|
|
18
|
+
}
|
|
19
|
+
static getInstance() {
|
|
20
|
+
if (!IdaeApi.instance) {
|
|
21
|
+
IdaeApi.instance = new IdaeApi();
|
|
22
|
+
}
|
|
23
|
+
return IdaeApi.instance;
|
|
24
|
+
}
|
|
25
|
+
get state() {
|
|
26
|
+
return this._state;
|
|
27
|
+
}
|
|
28
|
+
get app() {
|
|
29
|
+
return this._app;
|
|
30
|
+
}
|
|
31
|
+
setOptions(options) {
|
|
32
|
+
this.options = { ...this.options, ...options };
|
|
33
|
+
}
|
|
34
|
+
initializeAuth() {
|
|
35
|
+
if (this.options.enableAuth && this.options.jwtSecret && this.options.tokenExpiration) {
|
|
36
|
+
this.authMiddleware = new AuthMiddleWare(this.options.jwtSecret, this.options.tokenExpiration);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
configureIdaeApi() {
|
|
40
|
+
this.configureMiddleware();
|
|
41
|
+
this.configureRoutes();
|
|
42
|
+
this.configureErrorHandling();
|
|
43
|
+
}
|
|
44
|
+
configureMiddleware() {
|
|
45
|
+
this._app.use('/:collectionName', databaseMiddleware);
|
|
46
|
+
this._app.use(express.json());
|
|
47
|
+
this._app.use(express.urlencoded({ extended: true }));
|
|
48
|
+
if (this.authMiddleware) {
|
|
49
|
+
this._app.use(this.authMiddleware.createMiddleware());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
configureRoutes() {
|
|
53
|
+
this.routeManager.addRoutes(defaultRoutes);
|
|
54
|
+
if (this.options.routes) {
|
|
55
|
+
this.routeManager.addRoutes(this.options.routes);
|
|
56
|
+
}
|
|
57
|
+
this.routeManager.getRoutes().forEach(this.addRouteToExpress.bind(this));
|
|
58
|
+
if (this.authMiddleware) {
|
|
59
|
+
this.authMiddleware.configureAuthRoutes(this._app);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
configureErrorHandling() {
|
|
63
|
+
this._app.use((err, req, res, next) => {
|
|
64
|
+
console.error(err.stack);
|
|
65
|
+
res.status(500).json({ error: err.message });
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
start() {
|
|
69
|
+
if (this._state === 'running') {
|
|
70
|
+
console.log('Server is already running.');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const port = this.options.port || 3000;
|
|
74
|
+
this.serverInstance = this._app.listen(port, () => {
|
|
75
|
+
console.log(`Server is running on port: ${port}`);
|
|
76
|
+
this._state = 'running';
|
|
77
|
+
});
|
|
78
|
+
this.serverInstance.on('error', this.handleServerError.bind(this));
|
|
79
|
+
}
|
|
80
|
+
handleServerError(error) {
|
|
81
|
+
if (error.code === 'EADDRINUSE') {
|
|
82
|
+
console.error(`Port ${this.options.port} is already in use.`);
|
|
83
|
+
switch (this.options.onInUse) {
|
|
84
|
+
case 'reboot':
|
|
85
|
+
console.log('Rebooting server...');
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
this.stop();
|
|
88
|
+
this.start();
|
|
89
|
+
}, 1000);
|
|
90
|
+
break;
|
|
91
|
+
case 'replace':
|
|
92
|
+
console.log('Replacing existing server...');
|
|
93
|
+
this.stop();
|
|
94
|
+
this.start();
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
console.log('Failed to start the server.');
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
stop() {
|
|
106
|
+
if (this.serverInstance) {
|
|
107
|
+
this.serverInstance.close((err) => {
|
|
108
|
+
if (err) {
|
|
109
|
+
console.error('Error while stopping the server:', err);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.log('Server stopped successfully.');
|
|
113
|
+
this._state = 'stopped';
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Add a route to Express
|
|
119
|
+
addRouteToExpress(route) {
|
|
120
|
+
const handlers = [];
|
|
121
|
+
if (route.requiresAuth && this.authMiddleware) {
|
|
122
|
+
handlers.push(this.authMiddleware.createMiddleware());
|
|
123
|
+
}
|
|
124
|
+
handlers.push(this.handleRequest(route.handler));
|
|
125
|
+
if (Array.isArray(route.method)) {
|
|
126
|
+
console.log({ handlers });
|
|
127
|
+
this._app.post(route.path, ...handlers);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this._app[route.method](route.path, ...handlers);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Handle request
|
|
134
|
+
handleRequest(action) {
|
|
135
|
+
return async (req, res, next) => {
|
|
136
|
+
try {
|
|
137
|
+
const { collectionName } = req.params;
|
|
138
|
+
const connection = req.dbConnection;
|
|
139
|
+
if (!connection) {
|
|
140
|
+
throw new Error('Database connection not established');
|
|
141
|
+
}
|
|
142
|
+
console.log('----------------------------------------------');
|
|
143
|
+
console.log(req.body);
|
|
144
|
+
console.log(req.params);
|
|
145
|
+
const databaseService = new DBaseService(collectionName, connection, 'mongodb');
|
|
146
|
+
const result = await action(databaseService, req.params, req.body);
|
|
147
|
+
res.json(result);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
next(error);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
// Expose RouteManager methods
|
|
155
|
+
get router() {
|
|
156
|
+
return this.routeManager;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
IdaeApi.instance = null;
|
|
160
|
+
// Export a single instance of ApiServer
|
|
161
|
+
const idaeApi = IdaeApi.getInstance();
|
|
162
|
+
export { idaeApi };
|
|
163
|
+
// Usage example:
|
|
164
|
+
/*
|
|
165
|
+
import apiServer from './ApiServer';
|
|
166
|
+
import { RouteDefinition } from './config/routeDefinitions';
|
|
167
|
+
|
|
168
|
+
// Configure the server
|
|
169
|
+
apiServer.setOptions({
|
|
170
|
+
port: 3050,
|
|
171
|
+
enableAuth: true,
|
|
172
|
+
jwtSecret: 'your_jwt_secret',
|
|
173
|
+
tokenExpiration: '15m',
|
|
174
|
+
onInUse: 'reboot'
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Start the server
|
|
178
|
+
apiServer.start();
|
|
179
|
+
|
|
180
|
+
console.log(apiServer.state); // 'running'
|
|
181
|
+
|
|
182
|
+
// Add a new route at runtime
|
|
183
|
+
apiServer.router.addRoute({
|
|
184
|
+
method: 'post',
|
|
185
|
+
path: '/dynamic',
|
|
186
|
+
handler: async (service, params, body) => ({ message: 'Dynamic route', data: body })
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Disable a route
|
|
190
|
+
apiServer.router.disableRoute('/custom', 'get');
|
|
191
|
+
|
|
192
|
+
// Enable a route
|
|
193
|
+
apiServer.router.enableRoute('/custom', 'get');
|
|
194
|
+
|
|
195
|
+
// Add multiple routes
|
|
196
|
+
apiServer.router.addRoutes([
|
|
197
|
+
{
|
|
198
|
+
method: 'get',
|
|
199
|
+
path: '/multiple1',
|
|
200
|
+
handler: async () => ({ message: 'Multiple 1' })
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
method: 'get',
|
|
204
|
+
path: '/multiple2',
|
|
205
|
+
handler: async () => ({ message: 'Multiple 2' })
|
|
206
|
+
}
|
|
207
|
+
]);
|
|
208
|
+
|
|
209
|
+
// Stop the server
|
|
210
|
+
apiServer.stop();
|
|
211
|
+
|
|
212
|
+
console.log(apiServer.state); // 'stopped'
|
|
213
|
+
*/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ApiServerRequestParams } from '../engine/types';
|
|
2
|
+
import type { Model, Document } from 'mongoose';
|
|
3
|
+
import mongoose from 'mongoose';
|
|
4
|
+
export declare class MongoDBAdapter<T extends Document> implements DatabaseAdapter<T> {
|
|
5
|
+
private model;
|
|
6
|
+
private connection;
|
|
7
|
+
constructor(collection: string, connection: mongoose.Connection);
|
|
8
|
+
create(document: Partial<T>): Promise<T>;
|
|
9
|
+
where(params: ApiServerRequestParams): Promise<T[]>;
|
|
10
|
+
findById(id: string): Promise<T | null>;
|
|
11
|
+
findOne(params: ApiServerRequestParams): Promise<T | null>;
|
|
12
|
+
update(id: string, updateData: Partial<T>): Promise<T | null>;
|
|
13
|
+
deleteById(id: string): Promise<T | null>;
|
|
14
|
+
deleteManyByQuery(params: ApiServerRequestParams): Promise<{
|
|
15
|
+
deletedCount?: number;
|
|
16
|
+
}>;
|
|
17
|
+
private parseSortOptions;
|
|
18
|
+
setModel(collection: string): Model<T, {}, {}, {}, mongoose.IfAny<T, any, Document<unknown, {}, T> & mongoose.Require_id<T>>, any>;
|
|
19
|
+
getModel: <T_1 extends Document>(collectionName: string) => Model<T_1>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// packages\idae-api\src\lib\adapters\MongoDBAdapter.ts
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import mongoose, { Schema } from 'mongoose';
|
|
4
|
+
// Load environment variables
|
|
5
|
+
dotenv.config();
|
|
6
|
+
// MongoDB Adapter
|
|
7
|
+
export class MongoDBAdapter {
|
|
8
|
+
constructor(collection, connection) {
|
|
9
|
+
this.getModel = (collectionName) => {
|
|
10
|
+
if (this.connection.models[collectionName]) {
|
|
11
|
+
return this.connection.model(collectionName);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return this.setModel(collectionName);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
// just in case
|
|
18
|
+
collection = collection.split('.')[1] ?? collection.split('.')[0];
|
|
19
|
+
this.connection = connection;
|
|
20
|
+
this.model = this.getModel(collection);
|
|
21
|
+
}
|
|
22
|
+
async create(document) {
|
|
23
|
+
const newDocument = new this.model(document);
|
|
24
|
+
return newDocument.save();
|
|
25
|
+
}
|
|
26
|
+
async where(params) {
|
|
27
|
+
const { query = {}, sortBy, limit, skip } = params;
|
|
28
|
+
const sortOptions = this.parseSortOptions(sortBy);
|
|
29
|
+
return this.model
|
|
30
|
+
.find(query)
|
|
31
|
+
.sort(sortOptions)
|
|
32
|
+
.limit(Number(limit) || 0)
|
|
33
|
+
.skip(Number(skip) || 0);
|
|
34
|
+
}
|
|
35
|
+
async findById(id) {
|
|
36
|
+
return this.model.findById(id);
|
|
37
|
+
}
|
|
38
|
+
async findOne(params) {
|
|
39
|
+
return this.model.findOne(params.query);
|
|
40
|
+
}
|
|
41
|
+
async update(id, updateData) {
|
|
42
|
+
return this.model.findByIdAndUpdate(id, updateData, { new: true });
|
|
43
|
+
}
|
|
44
|
+
async deleteById(id) {
|
|
45
|
+
return this.model.findByIdAndDelete(id);
|
|
46
|
+
}
|
|
47
|
+
async deleteManyByQuery(params) {
|
|
48
|
+
const result = await this.model.deleteMany(params.query);
|
|
49
|
+
return { deletedCount: result.deletedCount };
|
|
50
|
+
}
|
|
51
|
+
parseSortOptions(sortBy) {
|
|
52
|
+
const sortOptions = {};
|
|
53
|
+
if (sortBy) {
|
|
54
|
+
const sortFields = sortBy.split(',');
|
|
55
|
+
sortFields.forEach((field) => {
|
|
56
|
+
const [key, order] = field.split(':');
|
|
57
|
+
sortOptions[key] = order === 'desc' ? -1 : 1;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return sortOptions;
|
|
61
|
+
}
|
|
62
|
+
setModel(collection) {
|
|
63
|
+
const schema = new Schema({}, { strict: false });
|
|
64
|
+
return this.connection.model(collection, schema, collection);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ApiServerRequestParams } from '../engine/types';
|
|
2
|
+
import { Model } from 'sequelize';
|
|
3
|
+
import type { DatabaseAdapter } from './types';
|
|
4
|
+
interface MySQLDocument extends Model {
|
|
5
|
+
id: number;
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}
|
|
8
|
+
export declare class MySQLAdapter<T extends MySQLDocument> implements DatabaseAdapter<T> {
|
|
9
|
+
private sequelize;
|
|
10
|
+
private model;
|
|
11
|
+
constructor(tableName: string);
|
|
12
|
+
create(document: Partial<T>): Promise<T>;
|
|
13
|
+
where(params: ApiServerRequestParams): Promise<T[]>;
|
|
14
|
+
findById(id: string): Promise<T | null>;
|
|
15
|
+
findOne(params: ApiServerRequestParams): Promise<T | null>;
|
|
16
|
+
update(id: string, updateData: Partial<T>): Promise<T | null>;
|
|
17
|
+
deleteById(id: string): Promise<T | null>;
|
|
18
|
+
deleteManyByQuery(params: ApiServerRequestParams): Promise<{
|
|
19
|
+
deletedCount?: number;
|
|
20
|
+
}>;
|
|
21
|
+
private parseSortOptions;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Sequelize, Model, DataTypes } from 'sequelize';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
dotenv.config();
|
|
4
|
+
export class MySQLAdapter {
|
|
5
|
+
constructor(tableName) {
|
|
6
|
+
this.sequelize = new Sequelize({
|
|
7
|
+
dialect: 'mysql',
|
|
8
|
+
host: process.env.MYSQL_HOST || 'localhost',
|
|
9
|
+
port: Number(process.env.MYSQL_PORT) || 3306,
|
|
10
|
+
database: process.env.MYSQL_DATABASE || 'database',
|
|
11
|
+
username: process.env.MYSQL_USER || 'root',
|
|
12
|
+
password: process.env.MYSQL_PASSWORD || 'password'
|
|
13
|
+
});
|
|
14
|
+
this.model = this.sequelize.define(tableName, {
|
|
15
|
+
id: {
|
|
16
|
+
type: DataTypes.INTEGER.UNSIGNED,
|
|
17
|
+
autoIncrement: true,
|
|
18
|
+
primaryKey: true
|
|
19
|
+
}
|
|
20
|
+
// Define other fields here as needed
|
|
21
|
+
}, {
|
|
22
|
+
timestamps: false,
|
|
23
|
+
tableName
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async create(document) {
|
|
27
|
+
const newDocument = await this.model.create(document);
|
|
28
|
+
return newDocument;
|
|
29
|
+
}
|
|
30
|
+
async where(params) {
|
|
31
|
+
const { query = {}, sortBy, limit, skip } = params;
|
|
32
|
+
const options = {
|
|
33
|
+
where: query,
|
|
34
|
+
order: this.parseSortOptions(sortBy),
|
|
35
|
+
limit: limit ? Number(limit) : undefined,
|
|
36
|
+
offset: skip ? Number(skip) : undefined
|
|
37
|
+
};
|
|
38
|
+
const results = await this.model.findAll(options);
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
async findById(id) {
|
|
42
|
+
const result = await this.model.findByPk(id);
|
|
43
|
+
return result ? result : null;
|
|
44
|
+
}
|
|
45
|
+
async findOne(params) {
|
|
46
|
+
const { query = {} } = params;
|
|
47
|
+
const result = await this.model.findOne({ where: query });
|
|
48
|
+
return result ? result : null;
|
|
49
|
+
}
|
|
50
|
+
async update(id, updateData) {
|
|
51
|
+
const [affectedCount, affectedRows] = await this.model.update(updateData, {
|
|
52
|
+
where: { id },
|
|
53
|
+
returning: true
|
|
54
|
+
});
|
|
55
|
+
return affectedCount > 0 ? affectedRows[0] : null;
|
|
56
|
+
}
|
|
57
|
+
async deleteById(id) {
|
|
58
|
+
const result = await this.model.findByPk(id);
|
|
59
|
+
if (result) {
|
|
60
|
+
await result.destroy();
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
async deleteManyByQuery(params) {
|
|
66
|
+
const { query = {} } = params;
|
|
67
|
+
const deletedCount = await this.model.destroy({ where: query });
|
|
68
|
+
return { deletedCount };
|
|
69
|
+
}
|
|
70
|
+
parseSortOptions(sortBy) {
|
|
71
|
+
if (!sortBy)
|
|
72
|
+
return [];
|
|
73
|
+
return sortBy.split(',').map((field) => {
|
|
74
|
+
const [key, order] = field.split(':');
|
|
75
|
+
return [key, order === 'desc' ? 'DESC' : 'ASC'];
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ApiServerRequestParams } from '../engine/types';
|
|
2
|
+
export interface DatabaseAdapter<T extends Document> {
|
|
3
|
+
create(document: Partial<T>): Promise<T>;
|
|
4
|
+
where(params: ApiServerRequestParams): Promise<T[]>;
|
|
5
|
+
findById(id: string): Promise<T | null>;
|
|
6
|
+
findOne(params: ApiServerRequestParams): Promise<T | null>;
|
|
7
|
+
update(id: string, updateData: Partial<T>): Promise<T | null>;
|
|
8
|
+
deleteById(id: string): Promise<T | null>;
|
|
9
|
+
deleteManyByQuery(params: ApiServerRequestParams): Promise<{
|
|
10
|
+
deletedCount?: number;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
import type { Request } from 'express';
|
|
3
|
+
export interface DatabaseConfig {
|
|
4
|
+
port: number;
|
|
5
|
+
host: string;
|
|
6
|
+
defaultDbName: string;
|
|
7
|
+
connectionPrefix: string;
|
|
8
|
+
}
|
|
9
|
+
declare class DatabaseManager {
|
|
10
|
+
private static instance;
|
|
11
|
+
private config;
|
|
12
|
+
private mongooseConnectionManager;
|
|
13
|
+
private constructor();
|
|
14
|
+
static getInstance(): DatabaseManager;
|
|
15
|
+
private getDbNameFromCollectionName;
|
|
16
|
+
private initConnection;
|
|
17
|
+
connectToDatabase(req: Request): Promise<{
|
|
18
|
+
connection?: mongoose.Connection;
|
|
19
|
+
dbName?: string;
|
|
20
|
+
collectionName?: string;
|
|
21
|
+
}>;
|
|
22
|
+
closeAllConnections(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
declare const databaseManager: DatabaseManager;
|
|
25
|
+
export default databaseManager;
|
|
26
|
+
export { DatabaseManager, databaseManager };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// packages\idae-api\src\lib\engine\DatabaseManager.ts
|
|
2
|
+
import mongoose from 'mongoose';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
import { mongooseConnectionManager } from './mongooseConnectionManager';
|
|
5
|
+
// Load environment variables
|
|
6
|
+
dotenv.config();
|
|
7
|
+
class DatabaseManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.mongooseConnectionManager = mongooseConnectionManager;
|
|
10
|
+
this.config = {
|
|
11
|
+
port: Number(process.env.MONGODB_DEFAULT_PORT) || 27017,
|
|
12
|
+
host: process.env.MONGODB_DEFAULT_HOST || 'localhost',
|
|
13
|
+
defaultDbName: process.env.MONGODB_DEFAULT_DB || 'idaenext_sitebase_app',
|
|
14
|
+
connectionPrefix: process.env.MONGODB_DEFAULT_CONNECTION_PREFIX || 'mongodb://'
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
static getInstance() {
|
|
18
|
+
if (!DatabaseManager.instance) {
|
|
19
|
+
DatabaseManager.instance = new DatabaseManager();
|
|
20
|
+
}
|
|
21
|
+
return DatabaseManager.instance;
|
|
22
|
+
}
|
|
23
|
+
getDbNameFromCollectionName(collectionName) {
|
|
24
|
+
return collectionName.includes('.') ? collectionName.split('.')[0] : this.config.defaultDbName;
|
|
25
|
+
}
|
|
26
|
+
async initConnection(dbName) {
|
|
27
|
+
const dbUri = `${this.config.connectionPrefix}${this.config.host}:${this.config.port}/${dbName}`;
|
|
28
|
+
// use mongooseConnectionManager
|
|
29
|
+
const connection = await this.mongooseConnectionManager.createConnection(dbUri, dbName, {
|
|
30
|
+
dbName,
|
|
31
|
+
autoIndex: false,
|
|
32
|
+
bufferCommands: false,
|
|
33
|
+
serverSelectionTimeoutMS: 30000,
|
|
34
|
+
socketTimeoutMS: 45000,
|
|
35
|
+
maxPoolSize: 20
|
|
36
|
+
});
|
|
37
|
+
return connection;
|
|
38
|
+
}
|
|
39
|
+
async connectToDatabase(req) {
|
|
40
|
+
const collectionName = req.params.collectionName || 'default';
|
|
41
|
+
const dbName = this.getDbNameFromCollectionName(collectionName);
|
|
42
|
+
const collectionNames = collectionName.split('.')?.[1] ?? collectionName.split('.')?.[0];
|
|
43
|
+
try {
|
|
44
|
+
const connection = await this.initConnection(dbName);
|
|
45
|
+
return {
|
|
46
|
+
connection,
|
|
47
|
+
dbName,
|
|
48
|
+
collectionName: collectionNames
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error(`Failed to connect to database ${dbName}:`, error);
|
|
53
|
+
throw new Error(`Failed to connect to database ${dbName}:`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async closeAllConnections() { }
|
|
57
|
+
}
|
|
58
|
+
const databaseManager = DatabaseManager.getInstance();
|
|
59
|
+
export default databaseManager;
|
|
60
|
+
export { DatabaseManager, databaseManager };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
export declare class MongooseConnectionManager {
|
|
3
|
+
private static instance;
|
|
4
|
+
private constructor();
|
|
5
|
+
private _connections;
|
|
6
|
+
static getInstance(): MongooseConnectionManager;
|
|
7
|
+
createConnection(dbUri: string, dbName: string, options?: mongoose.ConnectOptions): Promise<mongoose.Connection>;
|
|
8
|
+
get connections(): Record<string, mongoose.Connection>;
|
|
9
|
+
getConnection(dbName: string): mongoose.Connection;
|
|
10
|
+
}
|
|
11
|
+
export declare const mongooseConnectionManager: MongooseConnectionManager;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// packages\idae-api\src\lib\engine\mongooseConnectionManager.ts
|
|
2
|
+
import mongoose from 'mongoose';
|
|
3
|
+
export class MongooseConnectionManager {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._connections = {};
|
|
6
|
+
}
|
|
7
|
+
static getInstance() {
|
|
8
|
+
if (!MongooseConnectionManager.instance) {
|
|
9
|
+
MongooseConnectionManager.instance = new MongooseConnectionManager();
|
|
10
|
+
}
|
|
11
|
+
return MongooseConnectionManager.instance;
|
|
12
|
+
}
|
|
13
|
+
async createConnection(dbUri, dbName, options) {
|
|
14
|
+
const connection = await mongoose.createConnection(dbUri, options).asPromise();
|
|
15
|
+
this._connections[dbName] = connection;
|
|
16
|
+
return connection;
|
|
17
|
+
}
|
|
18
|
+
get connections() {
|
|
19
|
+
return this._connections;
|
|
20
|
+
}
|
|
21
|
+
getConnection(dbName) {
|
|
22
|
+
return this._connections?.[dbName];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export const mongooseConnectionManager = MongooseConnectionManager.getInstance();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RouteDefinition } from '../../config/routeDefinitions';
|
|
2
|
+
export declare class RouteManager {
|
|
3
|
+
private static instance;
|
|
4
|
+
private routes;
|
|
5
|
+
private constructor();
|
|
6
|
+
static getInstance(): RouteManager;
|
|
7
|
+
addRoute(route: RouteDefinition): void;
|
|
8
|
+
addRoutes(routes: RouteDefinition[]): void;
|
|
9
|
+
removeRoute(path: string, method: string | string[]): void;
|
|
10
|
+
getRoutes(): RouteDefinition[];
|
|
11
|
+
enableRoute(path: string, method: string | string[]): void;
|
|
12
|
+
disableRoute(path: string, method: string | string[]): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export class RouteManager {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.routes = [];
|
|
4
|
+
}
|
|
5
|
+
static getInstance() {
|
|
6
|
+
if (!RouteManager.instance) {
|
|
7
|
+
RouteManager.instance = new RouteManager();
|
|
8
|
+
}
|
|
9
|
+
return RouteManager.instance;
|
|
10
|
+
}
|
|
11
|
+
addRoute(route) {
|
|
12
|
+
this.routes.push({ ...route, disabled: route.disabled || false });
|
|
13
|
+
}
|
|
14
|
+
addRoutes(routes) {
|
|
15
|
+
routes.forEach((route) => this.addRoute(route));
|
|
16
|
+
}
|
|
17
|
+
removeRoute(path, method) {
|
|
18
|
+
this.routes = this.routes.filter((r) => !(r.path === path &&
|
|
19
|
+
(Array.isArray(r.method) ? r.method.includes(method) : r.method === method)));
|
|
20
|
+
}
|
|
21
|
+
getRoutes() {
|
|
22
|
+
return this.routes.filter((route) => !route.disabled);
|
|
23
|
+
}
|
|
24
|
+
enableRoute(path, method) {
|
|
25
|
+
const route = this.routes.find((r) => r.path === path &&
|
|
26
|
+
(Array.isArray(r.method) ? r.method.includes(method) : r.method === method));
|
|
27
|
+
if (route) {
|
|
28
|
+
route.disabled = false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
disableRoute(path, method) {
|
|
32
|
+
const route = this.routes.find((r) => r.path === path &&
|
|
33
|
+
(Array.isArray(r.method) ? r.method.includes(method) : r.method === method));
|
|
34
|
+
if (route) {
|
|
35
|
+
route.disabled = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Express, Request, Response, NextFunction } from 'express';
|
|
2
|
+
declare class AuthMiddleWare {
|
|
3
|
+
private jwtSecret;
|
|
4
|
+
private tokenExpiration;
|
|
5
|
+
constructor(jwtSecret: string, tokenExpiration: string);
|
|
6
|
+
generateToken(payload: object): string;
|
|
7
|
+
verifyToken(token: string): any;
|
|
8
|
+
refreshToken(token: string): string;
|
|
9
|
+
createMiddleware(): (req: Request, res: Response, next: NextFunction) => Response<any, Record<string, any>> | undefined;
|
|
10
|
+
configureAuthRoutes(app: Express): void;
|
|
11
|
+
private handleLogin;
|
|
12
|
+
private handleLogout;
|
|
13
|
+
private handleRefreshToken;
|
|
14
|
+
}
|
|
15
|
+
export { AuthMiddleWare };
|