@medyll/idae-api 0.33.0 → 0.35.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.
@@ -1,3 +1,4 @@
1
+ export { DbType } from "@medyll/idae-db";
1
2
  export interface ApiResponse<T extends object> {
2
3
  data?: T[];
3
4
  count?: number;
@@ -1 +1 @@
1
- export {};
1
+ export { DbType } from "@medyll/idae-db";
@@ -1,10 +1,11 @@
1
1
  import { IdaeApiClient } from "./IdaeApiClient.js";
2
2
  import type { IdaeApiClientRequestParams } from "./IdaeApiClient.js";
3
3
  import type { IdaeApiClientConfigCoreOptions } from "./IdaeApiClientConfig.js";
4
- declare class IdaeApiClientCollection extends IdaeApiClient {
4
+ import type { IdaeDbApiMethods } from "@medyll/idae-db";
5
+ declare class IdaeApiClientCollection extends IdaeApiClient implements IdaeDbApiMethods<object> {
5
6
  private meta;
6
7
  constructor(clientConfig: IdaeApiClientConfigCoreOptions, dbName: string, collectionName: string);
7
- findAll<T>(params?: IdaeApiClientRequestParams): Promise<Response>;
8
+ find<T extends object>(params?: IdaeApiClientRequestParams): Promise<T[]>;
8
9
  findById<T>(id: string): Promise<Response>;
9
10
  create<T>(body: T): Promise<Response>;
10
11
  update<T>(id: string, body: T): Promise<Response>;
@@ -8,7 +8,7 @@ class IdaeApiClientCollection extends IdaeApiClient {
8
8
  collectionName,
9
9
  };
10
10
  }
11
- async findAll(params) {
11
+ async find(params) {
12
12
  return this.request.doRequest({
13
13
  ...this.meta,
14
14
  params,
@@ -1,5 +1,6 @@
1
1
  // packages\idae-api\src\lib\client\IdaeApiClientRequest.ts
2
2
  import { IdaeApiClientConfigCore } from "./IdaeApiClientConfig.js";
3
+ import { encode } from "querystring";
3
4
  class IdaeApiClientRequest {
4
5
  constructor(clientConfig) {
5
6
  this.clientConfig = clientConfig;
@@ -40,7 +41,7 @@ class IdaeApiClientRequest {
40
41
  if (slug)
41
42
  urls.push(slug);
42
43
  if (params)
43
- urls.push(`?${new URLSearchParams(params).toString()}`);
44
+ urls.push(`?params=${encodeURIComponent(JSON.stringify(params))}`);
44
45
  return urls.join("/").replace("//", "/");
45
46
  }
46
47
  }
@@ -1,10 +1,11 @@
1
- import { DBaseService } from "../server/services/DBaseService.js";
2
- type RouteHandler = (service: DBaseService<any>, params: any, body?: any) => Promise<any>;
1
+ import type { IdaeDbAdapter } from "@medyll/idae-db";
2
+ type RouteHandler = (service: IdaeDbAdapter<object>, params: any, body?: any, query?: any) => Promise<any>;
3
3
  export interface RouteDefinition {
4
4
  method: string | string[];
5
5
  path: string;
6
6
  handler: RouteHandler;
7
7
  disabled?: boolean;
8
+ requiresAuth?: boolean;
8
9
  }
9
10
  export declare const routes: RouteDefinition[];
10
11
  export {};
@@ -1,10 +1,9 @@
1
1
  // packages\idae-api\src\lib\config\routeDefinitions.ts
2
- import { DBaseService } from "../server/services/DBaseService.js";
3
2
  export const routes = [
4
3
  {
5
4
  method: "get",
6
5
  path: "/:collectionName",
7
- handler: async (service, params) => service.where(params),
6
+ handler: async (service, params, body, query) => service.find({ query }),
8
7
  },
9
8
  {
10
9
  method: "get",
@@ -29,15 +28,22 @@ export const routes = [
29
28
  {
30
29
  method: "delete",
31
30
  path: "/:collectionName",
32
- handler: async (service, params) => service.deleteManyByQuery(params),
33
- },
34
- {
35
- method: ["where", "create", "update", "deleteById", "deleteManyByQuery"], // default method is then GET or OPTIONS (set further)
31
+ handler: async (service, params) => service.deleteWhere(params),
32
+ },
33
+ {
34
+ method: [
35
+ "find",
36
+ "findById",
37
+ "findOne",
38
+ "create",
39
+ "update",
40
+ "updateWhere",
41
+ "deleteById",
42
+ "deleteWhere",
43
+ "transaction",
44
+ ], // default method is then GET or OPTIONS (set further)
36
45
  path: "/query/:collectionName/:command/:parameters?",
37
46
  handler: async (service, params, body) => {
38
- const decodedParams = params.body
39
- ? service.decodeUrlParams(params.body)
40
- : {};
41
47
  console.log(params.command, "params --- ", { body });
42
48
  return service?.[params.command]?.({ query: body });
43
49
  },
@@ -1,15 +1,18 @@
1
1
  // packages\idae-api\src\lib\idae-api.d.ts
2
2
 
3
- import mongoose from 'mongoose';
3
+ import mongoose from "mongoose";
4
+ import { IdaeDb, IdaeDbAdapter } from "@medyll/idae-db";
4
5
 
5
6
  declare global {
6
- namespace Express {
7
- interface Request {
8
- dbConnection?: mongoose.Connection;
9
- collectionName?: string;
10
- dbName?: string;
11
- }
12
- }
7
+ namespace Express {
8
+ interface Request {
9
+ dbConnection?: mongoose.Connection;
10
+ collectionName?: string;
11
+ dbName?: string;
12
+ idaeDb?: IdaeDb;
13
+ connectedCollection: IdaeDbAdapter;
14
+ }
15
+ }
13
16
  }
14
17
 
15
18
  export {};
package/dist/index.d.ts CHANGED
@@ -5,14 +5,10 @@ export * from './client/IdaeApiClientConfig.js';
5
5
  export * from './client/IdaeApiClientCollection.js';
6
6
  export * from './client/IdaeApiClient.js';
7
7
  export * from './@types/types.js';
8
- export * from './server/services/DBaseService.js';
9
8
  export * from './server/services/AuthService.js';
10
9
  export * from './server/middleware/databaseMiddleware.js';
11
10
  export * from './server/middleware/authMiddleware.js';
12
11
  export * from './server/engine/types.js';
13
12
  export * from './server/engine/routeManager.js';
13
+ export * from './server/engine/requestDatabaseManager.js';
14
14
  export * from './server/engine/mongooseConnectionManager.js';
15
- export * from './server/engine/DatabaseManager.js';
16
- export * from './server/adapters/types.js';
17
- export * from './server/adapters/MySQLAdapter.js';
18
- export * from './server/adapters/MongoDBAdapter.js';
package/dist/index.js CHANGED
@@ -6,14 +6,10 @@ export * from './client/IdaeApiClientConfig.js';
6
6
  export * from './client/IdaeApiClientCollection.js';
7
7
  export * from './client/IdaeApiClient.js';
8
8
  export * from './@types/types.js';
9
- export * from './server/services/DBaseService.js';
10
9
  export * from './server/services/AuthService.js';
11
10
  export * from './server/middleware/databaseMiddleware.js';
12
11
  export * from './server/middleware/authMiddleware.js';
13
12
  export * from './server/engine/types.js';
14
13
  export * from './server/engine/routeManager.js';
14
+ export * from './server/engine/requestDatabaseManager.js';
15
15
  export * from './server/engine/mongooseConnectionManager.js';
16
- export * from './server/engine/DatabaseManager.js';
17
- export * from './server/adapters/types.js';
18
- export * from './server/adapters/MySQLAdapter.js';
19
- export * from './server/adapters/MongoDBAdapter.js';
File without changes
@@ -1,3 +1,4 @@
1
+ import { type IdaeDbOptions } from "@medyll/idae-db";
1
2
  import express from "express";
2
3
  import { type RouteDefinition } from "../config/routeDefinitions.js";
3
4
  import { RouteManager } from "./engine/routeManager.js";
@@ -8,15 +9,10 @@ interface IdaeApiOptions {
8
9
  enableAuth?: boolean;
9
10
  jwtSecret?: string;
10
11
  tokenExpiration?: string;
12
+ idaeDbOptions?: IdaeDbOptions;
11
13
  }
12
14
  declare class IdaeApi {
13
- private static instance;
14
- private _app;
15
- private options;
16
- private routeManager;
17
- private serverInstance;
18
- private _state;
19
- private authMiddleware;
15
+ #private;
20
16
  private constructor();
21
17
  static getInstance(): IdaeApi;
22
18
  get state(): "stopped" | "running";
@@ -26,11 +22,12 @@ declare class IdaeApi {
26
22
  configureIdaeApi(): void;
27
23
  private configureMiddleware;
28
24
  private configureRoutes;
25
+ private addRouteToExpress;
29
26
  private configureErrorHandling;
30
27
  start(): void;
28
+ get idaeApiOptions(): IdaeApiOptions;
31
29
  private handleServerError;
32
30
  stop(): void;
33
- private addRouteToExpress;
34
31
  private handleRequest;
35
32
  get router(): RouteManager;
36
33
  }
@@ -1,41 +1,65 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _a, _IdaeApi_instance, _IdaeApi_app, _IdaeApi_idaeApiOptions, _IdaeApi_routeManager, _IdaeApi_serverInstance, _IdaeApi_state, _IdaeApi_authMiddleware;
1
13
  // packages\idae-api\src\lib\IdaeApi.ts
2
- // version feat
14
+ import {} from "@medyll/idae-db";
3
15
  import express, {} from "express";
4
- import { databaseMiddleware } from "./middleware/databaseMiddleware.js";
5
- import { DBaseService } from "./services/DBaseService.js";
16
+ import { idaeDbMiddleware } from "./middleware/databaseMiddleware.js";
6
17
  import { routes as defaultRoutes, } from "../config/routeDefinitions.js";
7
18
  import { AuthMiddleWare } from "./middleware/authMiddleware.js";
8
19
  import { RouteManager } from "./engine/routeManager.js";
20
+ import qs from "qs";
9
21
  class IdaeApi {
10
22
  constructor() {
11
- this._state = "stopped";
12
- this.authMiddleware = null;
13
- this._app = express();
14
- this.options = {};
15
- this.routeManager = RouteManager.getInstance();
23
+ _IdaeApi_app.set(this, void 0);
24
+ _IdaeApi_idaeApiOptions.set(this, void 0);
25
+ _IdaeApi_routeManager.set(this, void 0);
26
+ _IdaeApi_serverInstance.set(this, void 0);
27
+ _IdaeApi_state.set(this, "stopped");
28
+ _IdaeApi_authMiddleware.set(this, null);
29
+ __classPrivateFieldSet(this, _IdaeApi_app, express(), "f");
30
+ __classPrivateFieldSet(this, _IdaeApi_idaeApiOptions, {}, "f");
31
+ __classPrivateFieldSet(this, _IdaeApi_routeManager, RouteManager.getInstance(), "f");
32
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").set("query parser", function (str) {
33
+ return qs.parse(str, {
34
+ parseArrays: true,
35
+ arrayLimit: Infinity,
36
+ depth: 10,
37
+ parameterLimit: 1000,
38
+ });
39
+ });
16
40
  this.initializeAuth();
17
41
  this.configureIdaeApi();
18
42
  }
19
43
  static getInstance() {
20
- if (!IdaeApi.instance) {
21
- IdaeApi.instance = new IdaeApi();
44
+ if (!__classPrivateFieldGet(_a, _a, "f", _IdaeApi_instance)) {
45
+ __classPrivateFieldSet(_a, _a, new _a(), "f", _IdaeApi_instance);
22
46
  }
23
- return IdaeApi.instance;
47
+ return __classPrivateFieldGet(_a, _a, "f", _IdaeApi_instance);
24
48
  }
25
49
  get state() {
26
- return this._state;
50
+ return __classPrivateFieldGet(this, _IdaeApi_state, "f");
27
51
  }
28
52
  get app() {
29
- return this._app;
53
+ return __classPrivateFieldGet(this, _IdaeApi_app, "f");
30
54
  }
31
55
  setOptions(options) {
32
- this.options = { ...this.options, ...options };
56
+ __classPrivateFieldSet(this, _IdaeApi_idaeApiOptions, { ...__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f"), ...options }, "f");
33
57
  }
34
58
  initializeAuth() {
35
- if (this.options.enableAuth &&
36
- this.options.jwtSecret &&
37
- this.options.tokenExpiration) {
38
- this.authMiddleware = new AuthMiddleWare(this.options.jwtSecret, this.options.tokenExpiration);
59
+ if (__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").enableAuth &&
60
+ __classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").jwtSecret &&
61
+ __classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").tokenExpiration) {
62
+ __classPrivateFieldSet(this, _IdaeApi_authMiddleware, new AuthMiddleWare(__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").jwtSecret, __classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").tokenExpiration), "f");
39
63
  }
40
64
  }
41
65
  configureIdaeApi() {
@@ -44,45 +68,62 @@ class IdaeApi {
44
68
  this.configureErrorHandling();
45
69
  }
46
70
  configureMiddleware() {
47
- this._app.use("/:collectionName", databaseMiddleware);
48
- this._app.use(express.json());
49
- this._app.use(express.urlencoded({ extended: true }));
50
- if (this.authMiddleware) {
51
- this._app.use(this.authMiddleware.createMiddleware());
71
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").use("/:collectionName", idaeDbMiddleware);
72
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").use(express.json());
73
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").use(express.urlencoded({ extended: true }));
74
+ if (__classPrivateFieldGet(this, _IdaeApi_authMiddleware, "f")) {
75
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").use(__classPrivateFieldGet(this, _IdaeApi_authMiddleware, "f").createMiddleware());
52
76
  }
53
77
  }
54
78
  configureRoutes() {
55
- this.routeManager.addRoutes(defaultRoutes);
56
- if (this.options.routes) {
57
- this.routeManager.addRoutes(this.options.routes);
79
+ __classPrivateFieldGet(this, _IdaeApi_routeManager, "f").addRoutes(defaultRoutes);
80
+ if (__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").routes) {
81
+ __classPrivateFieldGet(this, _IdaeApi_routeManager, "f").addRoutes(__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").routes);
82
+ }
83
+ __classPrivateFieldGet(this, _IdaeApi_routeManager, "f").getRoutes().forEach(this.addRouteToExpress.bind(this));
84
+ if (__classPrivateFieldGet(this, _IdaeApi_authMiddleware, "f")) {
85
+ __classPrivateFieldGet(this, _IdaeApi_authMiddleware, "f").configureAuthRoutes(__classPrivateFieldGet(this, _IdaeApi_app, "f"));
86
+ }
87
+ }
88
+ // Add a route to Express
89
+ addRouteToExpress(route) {
90
+ const handlers = [];
91
+ if (route.requiresAuth && __classPrivateFieldGet(this, _IdaeApi_authMiddleware, "f")) {
92
+ handlers.push(__classPrivateFieldGet(this, _IdaeApi_authMiddleware, "f").createMiddleware());
93
+ }
94
+ handlers.push(this.handleRequest(route.handler));
95
+ if (Array.isArray(route.method)) {
96
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").post(route.path, ...handlers);
58
97
  }
59
- this.routeManager.getRoutes().forEach(this.addRouteToExpress.bind(this));
60
- if (this.authMiddleware) {
61
- this.authMiddleware.configureAuthRoutes(this._app);
98
+ else {
99
+ __classPrivateFieldGet(this, _IdaeApi_app, "f")[route.method](route.path, ...handlers);
62
100
  }
63
101
  }
64
102
  configureErrorHandling() {
65
- this._app.use((err, req, res, next) => {
103
+ __classPrivateFieldGet(this, _IdaeApi_app, "f").use((err, req, res, next) => {
66
104
  console.error(err.stack);
67
105
  res.status(500).json({ error: err.message });
68
106
  });
69
107
  }
70
108
  start() {
71
- if (this._state === "running") {
109
+ if (__classPrivateFieldGet(this, _IdaeApi_state, "f") === "running") {
72
110
  console.log("Server is already running.");
73
111
  return;
74
112
  }
75
- const port = this.options.port || 3000;
76
- this.serverInstance = this._app.listen(port, () => {
113
+ const port = __classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").port || 3000;
114
+ __classPrivateFieldSet(this, _IdaeApi_serverInstance, __classPrivateFieldGet(this, _IdaeApi_app, "f").listen(port, () => {
77
115
  console.log(`Server is running on port: ${port}`);
78
- this._state = "running";
79
- });
80
- this.serverInstance.on("error", this.handleServerError.bind(this));
116
+ __classPrivateFieldSet(this, _IdaeApi_state, "running", "f");
117
+ }), "f");
118
+ __classPrivateFieldGet(this, _IdaeApi_serverInstance, "f").on("error", this.handleServerError.bind(this));
119
+ }
120
+ get idaeApiOptions() {
121
+ return __classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f");
81
122
  }
82
123
  handleServerError(error) {
83
124
  if (error.code === "EADDRINUSE") {
84
- console.error(`Port ${this.options.port} is already in use.`);
85
- switch (this.options.onInUse) {
125
+ console.error(`Port ${__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").port} is already in use.`);
126
+ switch (__classPrivateFieldGet(this, _IdaeApi_idaeApiOptions, "f").onInUse) {
86
127
  case "reboot":
87
128
  console.log("Rebooting server...");
88
129
  setTimeout(() => {
@@ -105,47 +146,33 @@ class IdaeApi {
105
146
  }
106
147
  }
107
148
  stop() {
108
- if (this.serverInstance) {
109
- this.serverInstance.close((err) => {
149
+ if (__classPrivateFieldGet(this, _IdaeApi_serverInstance, "f")) {
150
+ __classPrivateFieldGet(this, _IdaeApi_serverInstance, "f").close((err) => {
110
151
  if (err) {
111
152
  console.error("Error while stopping the server:", err);
112
153
  }
113
154
  else {
114
155
  console.log("Server stopped successfully.");
115
- this._state = "stopped";
156
+ __classPrivateFieldSet(this, _IdaeApi_state, "stopped", "f");
116
157
  }
117
158
  });
118
159
  }
119
160
  }
120
- // Add a route to Express
121
- addRouteToExpress(route) {
122
- const handlers = [];
123
- if (route.requiresAuth && this.authMiddleware) {
124
- handlers.push(this.authMiddleware.createMiddleware());
125
- }
126
- handlers.push(this.handleRequest(route.handler));
127
- if (Array.isArray(route.method)) {
128
- console.log({ handlers });
129
- this._app.post(route.path, ...handlers);
130
- }
131
- else {
132
- this._app[route.method](route.path, ...handlers);
133
- }
134
- }
135
161
  // Handle request
136
162
  handleRequest(action) {
137
163
  return async (req, res, next) => {
138
164
  try {
139
- const { collectionName } = req.params;
140
- const connection = req.dbConnection;
141
- if (!connection) {
165
+ const connectedCollection = req.connectedCollection;
166
+ if (!connectedCollection) {
142
167
  throw new Error("Database connection not established");
143
168
  }
144
169
  console.log("----------------------------------------------");
145
- console.log(req.body);
146
- console.log(req.params);
147
- const databaseService = new DBaseService(collectionName, connection, "mongodb");
148
- const result = await action(databaseService, req.params, req.body);
170
+ console.log("body", req.body);
171
+ console.log("params", req.params);
172
+ console.log("query", req.query);
173
+ console.log("dbName", req.dbName);
174
+ // const result = await action(databaseService, req.params, req.body);
175
+ const result = await action(connectedCollection, req.params, req.body, req.query.params ?? req.query);
149
176
  res.json(result);
150
177
  }
151
178
  catch (error) {
@@ -155,10 +182,11 @@ class IdaeApi {
155
182
  }
156
183
  // Expose RouteManager methods
157
184
  get router() {
158
- return this.routeManager;
185
+ return __classPrivateFieldGet(this, _IdaeApi_routeManager, "f");
159
186
  }
160
187
  }
161
- IdaeApi.instance = null;
188
+ _a = IdaeApi, _IdaeApi_app = new WeakMap(), _IdaeApi_idaeApiOptions = new WeakMap(), _IdaeApi_routeManager = new WeakMap(), _IdaeApi_serverInstance = new WeakMap(), _IdaeApi_state = new WeakMap(), _IdaeApi_authMiddleware = new WeakMap();
189
+ _IdaeApi_instance = { value: null };
162
190
  // Export a single instance of ApiServer
163
191
  const idaeApi = IdaeApi.getInstance();
164
192
  export { idaeApi };
@@ -0,0 +1,22 @@
1
+ import type { Request } from "express";
2
+ export interface DatabaseConfigOptions {
3
+ port: number;
4
+ host: string;
5
+ defaultDbName: string;
6
+ connectionPrefix: string;
7
+ }
8
+ declare class RequestDatabaseManager {
9
+ private static instance;
10
+ config: DatabaseConfigOptions;
11
+ private constructor();
12
+ static getInstance(): RequestDatabaseManager;
13
+ fromReq(req: Request): {
14
+ dbName: string;
15
+ collectionName: string;
16
+ dbUri: string;
17
+ };
18
+ closeAllConnections(): Promise<void>;
19
+ }
20
+ declare const requestDatabaseManager: RequestDatabaseManager;
21
+ export default requestDatabaseManager;
22
+ export { RequestDatabaseManager as DatabaseManager, requestDatabaseManager };
@@ -0,0 +1,40 @@
1
+ import dotenv from "dotenv";
2
+ // Load environment variables
3
+ dotenv.config();
4
+ class RequestDatabaseManager {
5
+ constructor(config) {
6
+ this.config = {
7
+ port: Number(process.env.MONGODB_DEFAULT_PORT) || 27017,
8
+ host: process.env.MONGODB_DEFAULT_HOST || "localhost",
9
+ defaultDbName: process.env.MONGODB_DEFAULT_DB || "idaenext_sitebase_app",
10
+ connectionPrefix: process.env.MONGODB_DEFAULT_CONNECTION_PREFIX || "mongodb://",
11
+ ...config,
12
+ };
13
+ }
14
+ static getInstance() {
15
+ if (!RequestDatabaseManager.instance) {
16
+ RequestDatabaseManager.instance = new RequestDatabaseManager();
17
+ }
18
+ return RequestDatabaseManager.instance;
19
+ }
20
+ fromReq(req) {
21
+ const collectionName = req.params.collectionName || "default";
22
+ const dbName = getDbNameFromCollectionName(collectionName, this.config.defaultDbName);
23
+ const collectionNames = collectionName.split(".")?.[1] ?? collectionName.split(".")?.[0];
24
+ const dbUri = `${this.config.connectionPrefix}${this.config.host}:${this.config.port}/${dbName}`;
25
+ return {
26
+ dbName,
27
+ collectionName: collectionNames,
28
+ dbUri,
29
+ };
30
+ function getDbNameFromCollectionName(collectionName, defaultDbName) {
31
+ return collectionName.includes(".")
32
+ ? collectionName.split(".")[0]
33
+ : defaultDbName;
34
+ }
35
+ }
36
+ async closeAllConnections() { }
37
+ }
38
+ const requestDatabaseManager = RequestDatabaseManager.getInstance();
39
+ export default requestDatabaseManager;
40
+ export { RequestDatabaseManager as DatabaseManager, requestDatabaseManager };
@@ -6,7 +6,6 @@ export declare class RouteManager {
6
6
  static getInstance(): RouteManager;
7
7
  addRoute(route: RouteDefinition): void;
8
8
  addRoutes(routes: RouteDefinition[]): void;
9
- removeRoute(path: string, method: string | string[]): void;
10
9
  getRoutes(): RouteDefinition[];
11
10
  enableRoute(path: string, method: string | string[]): void;
12
11
  disableRoute(path: string, method: string | string[]): void;
@@ -14,12 +14,6 @@ export class RouteManager {
14
14
  addRoutes(routes) {
15
15
  routes.forEach((route) => this.addRoute(route));
16
16
  }
17
- removeRoute(path, method) {
18
- this.routes = this.routes.filter((r) => !(r.path === path &&
19
- (Array.isArray(r.method)
20
- ? r.method.includes(method)
21
- : r.method === method)));
22
- }
23
17
  getRoutes() {
24
18
  return this.routes.filter((route) => !route.disabled);
25
19
  }
@@ -1,2 +1,2 @@
1
1
  import type { Request, Response, NextFunction } from "express";
2
- export declare const databaseMiddleware: (req: Request, res: Response, next: NextFunction) => Promise<void>;
2
+ export declare const idaeDbMiddleware: (req: Request, res: Response, next: NextFunction) => Promise<void>;
@@ -1,11 +1,25 @@
1
1
  // packages\idae-api\src\lib\middleware\databaseMiddleware.ts
2
- import databaseManager from "../engine/DatabaseManager.js";
3
- export const databaseMiddleware = async (req, res, next) => {
2
+ import { requestDatabaseManager } from "../engine/requestDatabaseManager.js";
3
+ import { IdaeDb } from "@medyll/idae-db";
4
+ import { idaeApi } from "../IdaeApi.js";
5
+ export const idaeDbMiddleware = async (req, res, next) => {
4
6
  try {
5
- const { collectionName, dbName, connection } = await databaseManager.connectToDatabase(req);
7
+ const { dbName, collectionName, dbUri } = requestDatabaseManager.fromReq(req);
6
8
  req.collectionName = collectionName;
7
- req.dbConnection = connection;
8
9
  req.dbName = dbName;
10
+ req.idaeDb = IdaeDb.init(dbUri, idaeApi.idaeApiOptions.idaeDbOptions);
11
+ // create connection to db
12
+ await req.idaeDb.db("app");
13
+ req.connectedCollection = req.idaeDb.collection(collectionName);
14
+ console.log("Connected to collection", collectionName);
15
+ if (req.query.params) {
16
+ try {
17
+ req.query.params = JSON.parse(decodeURIComponent(req.query.params));
18
+ }
19
+ catch (error) {
20
+ console.error(error);
21
+ }
22
+ }
9
23
  next();
10
24
  }
11
25
  catch (error) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@medyll/idae-api",
3
3
  "scope": "@medyll",
4
- "version": "0.33.0",
4
+ "version": "0.35.0",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "scripts": {
@@ -41,6 +41,7 @@
41
41
  "jsonwebtoken": "^9.0.2",
42
42
  "mongoose": "^8.5.2",
43
43
  "mongoose-sequence": "^6.0.1",
44
+ "qs": "^6.13.0",
44
45
  "sequelize": "^6.37.3"
45
46
  },
46
47
  "devDependencies": {
@@ -78,4 +79,4 @@
78
79
  "svelte": "./dist/index.js",
79
80
  "types": "./dist/index.d.ts",
80
81
  "type": "module"
81
- }
82
+ }
@@ -1,21 +0,0 @@
1
- import type { ApiServerRequestParams } from "../engine/types.js";
2
- import type { Model, Document } from "mongoose";
3
- import mongoose from "mongoose";
4
- import type { DatabaseAdapter } from "./types.js";
5
- export declare class MongoDBAdapter<T extends Document> implements DatabaseAdapter<T> {
6
- private model;
7
- private connection;
8
- constructor(collection: string, connection: mongoose.Connection);
9
- create(document: Partial<T>): Promise<T>;
10
- where(params: ApiServerRequestParams): Promise<T[]>;
11
- findById(id: string): Promise<T | null>;
12
- findOne(params: ApiServerRequestParams): Promise<T | null>;
13
- update(id: string, updateData: Partial<T>): Promise<T | null>;
14
- deleteById(id: string): Promise<T | null>;
15
- deleteManyByQuery(params: ApiServerRequestParams): Promise<{
16
- deletedCount?: number;
17
- }>;
18
- private parseSortOptions;
19
- setModel(collection: string): Model<T, {}, {}, {}, mongoose.IfAny<T, any, Document<unknown, {}, T> & mongoose.Require_id<T>>, any>;
20
- getModel: <T_1 extends Document>(collectionName: string) => Model<T_1>;
21
- }
@@ -1,68 +0,0 @@
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, {
43
- new: true,
44
- });
45
- }
46
- async deleteById(id) {
47
- return this.model.findByIdAndDelete(id);
48
- }
49
- async deleteManyByQuery(params) {
50
- const result = await this.model.deleteMany(params.query);
51
- return { deletedCount: result.deletedCount };
52
- }
53
- parseSortOptions(sortBy) {
54
- const sortOptions = {};
55
- if (sortBy) {
56
- const sortFields = sortBy.split(",");
57
- sortFields.forEach((field) => {
58
- const [key, order] = field.split(":");
59
- sortOptions[key] = order === "desc" ? -1 : 1;
60
- });
61
- }
62
- return sortOptions;
63
- }
64
- setModel(collection) {
65
- const schema = new Schema({}, { strict: false });
66
- return this.connection.model(collection, schema, collection);
67
- }
68
- }
@@ -1,23 +0,0 @@
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 {};
@@ -1,78 +0,0 @@
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
- }
@@ -1,12 +0,0 @@
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
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +0,0 @@
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 };
@@ -1,62 +0,0 @@
1
- // packages\idae-api\src\lib\engine\DatabaseManager.ts
2
- import mongoose from "mongoose";
3
- import dotenv from "dotenv";
4
- import { mongooseConnectionManager, } from "./mongooseConnectionManager.js";
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(".")
25
- ? collectionName.split(".")[0]
26
- : this.config.defaultDbName;
27
- }
28
- async initConnection(dbName) {
29
- const dbUri = `${this.config.connectionPrefix}${this.config.host}:${this.config.port}/${dbName}`;
30
- // use mongooseConnectionManager
31
- const connection = await this.mongooseConnectionManager.createConnection(dbUri, dbName, {
32
- dbName,
33
- autoIndex: false,
34
- bufferCommands: false,
35
- serverSelectionTimeoutMS: 30000,
36
- socketTimeoutMS: 45000,
37
- maxPoolSize: 20,
38
- });
39
- return connection;
40
- }
41
- async connectToDatabase(req) {
42
- const collectionName = req.params.collectionName || "default";
43
- const dbName = this.getDbNameFromCollectionName(collectionName);
44
- const collectionNames = collectionName.split(".")?.[1] ?? collectionName.split(".")?.[0];
45
- try {
46
- const connection = await this.initConnection(dbName);
47
- return {
48
- connection,
49
- dbName,
50
- collectionName: collectionNames,
51
- };
52
- }
53
- catch (error) {
54
- console.error(`Failed to connect to database ${dbName}:`, error);
55
- throw new Error(`Failed to connect to database ${dbName}:`);
56
- }
57
- }
58
- async closeAllConnections() { }
59
- }
60
- const databaseManager = DatabaseManager.getInstance();
61
- export default databaseManager;
62
- export { DatabaseManager, databaseManager };
@@ -1,17 +0,0 @@
1
- import mongoose, { type Document } from "mongoose";
2
- import { type ApiServerRequestParams } from "../engine/types.js";
3
- declare class DBaseService<T extends Document> {
4
- private adapter;
5
- constructor(collection: string, connection: mongoose.Connection, dbType?: "mongodb" | "mysql" | "mariadb" | "postgres");
6
- create(document: Partial<T>): Promise<T>;
7
- where(params: ApiServerRequestParams): Promise<T[]>;
8
- findById(id: string): Promise<T | null>;
9
- findOne(params: ApiServerRequestParams): Promise<T | null>;
10
- update(id: string, updateData: Partial<T>): Promise<T | null>;
11
- deleteById(id: string): Promise<T | null>;
12
- deleteManyByQuery(params: ApiServerRequestParams): Promise<{
13
- deletedCount?: number;
14
- }>;
15
- decodeUrlParams(urlParams: string): ApiServerRequestParams;
16
- }
17
- export { DBaseService };
@@ -1,62 +0,0 @@
1
- // packages\idae-api\src\lib\engine\DBaseService.ts
2
- import mongoose, {} from "mongoose";
3
- import {} from "../engine/types.js";
4
- import { MongoDBAdapter } from "../adapters/MongoDBAdapter.js";
5
- class DBaseService {
6
- constructor(collection, connection, dbType = "mongodb") {
7
- switch (dbType) {
8
- case "mongodb":
9
- this.adapter = new MongoDBAdapter(collection, connection);
10
- break;
11
- case "mysql":
12
- case "mariadb":
13
- // TODO: Implement MySQL adapter
14
- throw new Error("MySQL adapter not implemented yet");
15
- case "postgres":
16
- // TODO: Implement postgres adapter
17
- throw new Error("Postgres adapter not implemented yet");
18
- default:
19
- console.log("dbType", dbType);
20
- throw new Error(`Unsupported database type: ${dbType}`);
21
- }
22
- }
23
- async create(document) {
24
- return this.adapter.create(document);
25
- }
26
- async where(params) {
27
- console.log("where", params);
28
- return this.adapter.where(params);
29
- }
30
- async findById(id) {
31
- return this.adapter.findById(id);
32
- }
33
- async findOne(params) {
34
- return this.adapter.findOne(params);
35
- }
36
- async update(id, updateData) {
37
- return this.adapter.update(id, updateData);
38
- }
39
- async deleteById(id) {
40
- return this.adapter.deleteById(id);
41
- }
42
- async deleteManyByQuery(params) {
43
- return this.adapter.deleteManyByQuery(params);
44
- }
45
- decodeUrlParams(urlParams) {
46
- const params = {};
47
- const urlParamsArray = urlParams.split("&");
48
- urlParamsArray.forEach((param) => {
49
- const [key, value] = param.split("=");
50
- if (key && value) {
51
- try {
52
- params[key] = JSON.parse(decodeURIComponent(value));
53
- }
54
- catch (error) {
55
- params[key] = decodeURIComponent(value);
56
- }
57
- }
58
- });
59
- return params;
60
- }
61
- }
62
- export { DBaseService };