@medyll/idae-db 0.0.1 → 0.2.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 CHANGED
@@ -1,58 +1,102 @@
1
- # create-svelte
2
1
 
3
- Everything you need to build a Svelte library, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
2
+ # @medyll/idae-db
4
3
 
5
- Read more about creating a library [in the docs](https://kit.svelte.dev/docs/packaging).
4
+ @medyll/idae-db is a flexible and powerful library for interacting with various databases, with a particular focus on MongoDB support.
6
5
 
7
- ## Creating a project
8
-
9
- If you're seeing this, you've probably already done this step. Congrats!
6
+ ## Installation
10
7
 
11
8
  ```bash
12
- # create a new project in the current directory
13
- npm create svelte@latest
14
-
15
- # create a new project in my-app
16
- npm create svelte@latest my-app
9
+ npm install @medyll/idae-db
17
10
  ```
18
11
 
19
- ## Developing
12
+ ## Key Features
20
13
 
21
- Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
14
+ - Robust support for MongoDB
15
+ - Unified interface for different types of databases
16
+ - Efficient connection management
17
+ - Intuitive and flexible API
22
18
 
23
- ```bash
24
- npm run dev
19
+ ## Quick Start with MongoDB
25
20
 
26
- # or start the server and open the app in a new browser tab
27
- npm run dev -- --open
28
- ```
21
+ ```typescript
22
+ import { IdaeDb, DbType } from '@medyll/idae-db';
29
23
 
30
- Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
24
+ async function main() {
25
+ // Initialize MongoDB connection
26
+ const mongoDb = IdaeDb.init('mongodb://localhost:27017', {
27
+ dbType: DbType.MONGODB,
28
+ dbScope: 'myapp_'
29
+ });
31
30
 
32
- ## Building
31
+ // Create a connection
32
+ await mongoDb.db('example_db');
33
33
 
34
- To build your library:
34
+ // Use the 'users' collection
35
+ const usersCollection = mongoDb.collection('users');
35
36
 
36
- ```bash
37
- npm run package
38
- ```
37
+ // Insert a document
38
+ await usersCollection.update('user1', {
39
+ name: 'John Doe',
40
+ email: 'john@example.com',
41
+ age: 30
42
+ });
39
43
 
40
- To create a production version of your showcase app:
44
+ // Find a document
45
+ const user = await usersCollection.findOne({ query: { email: 'john@example.com' } });
46
+ console.log('Found user:', user);
41
47
 
42
- ```bash
43
- npm run build
48
+ // Close the connection
49
+ await mongoDb.closeConnection();
50
+ }
51
+
52
+ main().catch(console.error);
44
53
  ```
45
54
 
46
- You can preview the production build with `npm run preview`.
55
+ ## MongoDB Features
56
+
57
+ - Easy creation and management of connections
58
+ - Simplified CRUD operations
59
+ - Support for complex queries
60
+ - Index management
61
+ - Transactions (coming soon)
62
+
63
+ ## Advanced Configuration
64
+
65
+ ```typescript
66
+ const mongoDb = IdaeDb.init('mongodb://localhost:27017', {
67
+ dbType: DbType.MONGODB,
68
+ dbScope: 'myapp_',
69
+ dbScopeSeparator: '_',
70
+ idaeModelOptions: {
71
+ // Model-specific options
72
+ }
73
+ });
74
+ ```
47
75
 
48
- > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
76
+ ## MongoDB API
49
77
 
50
- ## Publishing
78
+ - `collection(name: string)`: Access a MongoDB collection
79
+ - `find(params)`: Search for documents
80
+ - `findOne(params)`: Find a single document
81
+ - `update(id, data)`: Update a document
82
+ - `deleteById(id)`: Delete a document by ID
83
+ - `createIndex(fieldOrSpec, options)`: Create an index on the collection
51
84
 
52
- Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
85
+ ## Connection Management
53
86
 
54
- To publish your library to [npm](https://www.npmjs.com):
87
+ - Efficiently managed multiple connections
88
+ - Automatic closure of connections
55
89
 
56
- ```bash
57
- npm publish
58
- ```
90
+ ## Roadmap
91
+
92
+ - Enhanced support for other databases (MySQL, ChromaDB)
93
+ - Advanced features for MongoDB (aggregations, watch)
94
+ - Performance optimizations
95
+
96
+ ## Contribution
97
+
98
+ Contributions are welcome! Feel free to open issues or submit pull requests.
99
+
100
+ ## License
101
+
102
+ MIT
@@ -1,12 +1,19 @@
1
- import { Collection, Document } from "mongodb";
2
- import { IdaeDbConnection } from "./IdaeDbConnection";
1
+ import type { Collection, Document } from 'mongodb';
2
+ import { IdaeDbConnection } from './IdaeDbConnection.js';
3
+ export interface IdaeModelOptions {
4
+ autoIncrementFormat?: (collection: string) => string;
5
+ autoIncrementDbCollection?: string;
6
+ }
3
7
  export declare class IdaeDBModel<T extends Document> {
8
+ private connection;
9
+ private _collectionName;
4
10
  private _collection;
5
11
  private _autoIncrementField;
12
+ private _autoIncrementDbCollection;
6
13
  private _fieldId;
7
- constructor(connection: IdaeDbConnection, collectionName: string, options?: {
8
- autoIncrementFormat?: (collection: string) => string;
9
- });
14
+ constructor(connection: IdaeDbConnection, _collectionName: string, options?: Partial<IdaeModelOptions>);
10
15
  get collection(): Collection<T>;
11
- get fieldId(): string | undefined;
16
+ get collectionName(): string;
17
+ get fieldId(): string;
18
+ getNextIncrement(): Promise<any>;
12
19
  }
@@ -1,19 +1,38 @@
1
- // packages\idae-db\lib\IdaeDBModel.ts
2
- import { Collection, Document } from "mongodb";
3
- import { IdaeDbConnection } from "./IdaeDbConnection";
1
+ import { IdaeDbConnection } from './IdaeDbConnection.js';
2
+ import { IdaeDb } from './idaeDb.js';
3
+ // models are attached to a connection
4
4
  export class IdaeDBModel {
5
+ connection;
6
+ _collectionName;
5
7
  _collection;
6
8
  _autoIncrementField = undefined;
7
- _fieldId = "_id";
8
- constructor(connection, collectionName, options) {
9
- this._collection = connection.getDb().collection(collectionName);
10
- this._autoIncrementField = options?.autoIncrementFormat?.(collectionName);
11
- this._fieldId = this._autoIncrementField ?? "_id";
9
+ _autoIncrementDbCollection = undefined;
10
+ _fieldId = '_id';
11
+ constructor(connection, _collectionName, options) {
12
+ this.connection = connection;
13
+ this._collectionName = _collectionName;
14
+ this._collection = this.connection.getDb().collection(_collectionName);
15
+ this._autoIncrementField = options?.autoIncrementFormat?.(_collectionName);
16
+ this._autoIncrementDbCollection = options?.autoIncrementDbCollection ?? 'auto_increment';
17
+ this._fieldId = this._autoIncrementField ?? '_id';
12
18
  }
13
19
  get collection() {
14
20
  return this._collection;
15
21
  }
22
+ get collectionName() {
23
+ return this._collectionName;
24
+ }
16
25
  get fieldId() {
17
26
  return this._fieldId;
18
27
  }
28
+ async getNextIncrement() {
29
+ const idaeAuto = IdaeDb.init(this.connection.idaeDb.uri, this.connection.idaeDb.options);
30
+ const increment_name = 'increment';
31
+ await idaeAuto.db(increment_name);
32
+ const incrementCollection = idaeAuto.collection(this._autoIncrementDbCollection);
33
+ // await incrementCollection.createIndex({ _id: 1 }, { unique: true });
34
+ await incrementCollection.updateWhere({ query: { _id: this.fieldId } }, { $inc: { value: 1 } }, { upsert: true });
35
+ const next = await incrementCollection.findOne({ query: { _id: this.fieldId } });
36
+ return next?.value;
37
+ }
19
38
  }
@@ -0,0 +1,36 @@
1
+ import { DbType, type IdaeDbAdapterInterface, type IdaeDbParams } from './types.js';
2
+ import { IdaeDbConnection } from './IdaeDbConnection.js';
3
+ import { IdaeEventEmitter, type EventListeners } from './IdaeEventEmitter.js';
4
+ export type AdapterConstructor = new <T extends Document = Document>(collection: string, connection: IdaeDbConnection) => IdaeDbAdapterInterface<T>;
5
+ export declare class IdaeDbAdapter<T extends Document> extends IdaeEventEmitter {
6
+ private dbType;
7
+ private adapter;
8
+ private static adapters;
9
+ /**
10
+ * Adds a new adapter for a specific database type.
11
+ * @param dbType The type of database for this adapter.
12
+ * @param adapterConstructor The constructor function for the adapter.
13
+ */
14
+ static addAdapter<A>(dbType: DbType, adapterConstructor: AdapterConstructor): void;
15
+ constructor(collection: string, connection: IdaeDbConnection, dbType: DbType);
16
+ private applyAdapter;
17
+ /**
18
+ * Registers event listeners specific to this collection.
19
+ * @param events An object containing event listeners for different operations.
20
+ */
21
+ registerEvents(events: EventListeners<T>): void;
22
+ static getAdapterForDbType(dbType: DbType): AdapterConstructor | undefined;
23
+ create(data: Partial<T>): Promise<T | {
24
+ error: string;
25
+ } | import("mongodb").UpdateResult<T>>;
26
+ findById(id: string): Promise<T | import("chromadb").GetResponse | T[] | null>;
27
+ find(params: IdaeDbParams<T>): Promise<import("chromadb").QueryResponse | import("mongodb").WithId<T>[] | T[]>;
28
+ findOne(params: IdaeDbParams<T>): Promise<any>;
29
+ update(id: string, updateData: Partial<T>): Promise<T | {
30
+ error: string;
31
+ } | import("mongodb").UpdateResult<T> | null>;
32
+ updateWhere(params: IdaeDbParams<T>, updateData: Partial<T>): Promise<void | T | import("mongodb").UpdateResult<T> | null>;
33
+ deleteById(id: string): Promise<string[] | T | import("mongodb").DeleteResult | null>;
34
+ deleteWhere(params: IdaeDbParams<T>): Promise<any>;
35
+ transaction<TResult>(callback: (session: any) => Promise<TResult>): Promise<TResult>;
36
+ }
@@ -0,0 +1,148 @@
1
+ // lib/IdaeDbAdapter.ts
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var _a, _b, _c, _d;
12
+ import { DbType } from './types.js';
13
+ import { IdaeDbConnection } from './IdaeDbConnection.js';
14
+ import { MongoDBAdapter } from './adapters/MongoDBAdapter.js';
15
+ import { MySQLAdapter } from './adapters/MySQLAdapter.js';
16
+ import { ChromaDBAdapter } from './adapters/ChromaDBAdapter.js';
17
+ import { IdaeEventEmitter, withEmitter } from './IdaeEventEmitter.js';
18
+ export class IdaeDbAdapter extends IdaeEventEmitter {
19
+ dbType;
20
+ adapter;
21
+ static adapters = new Map();
22
+ static {
23
+ IdaeDbAdapter.addAdapter(DbType.MONGODB, MongoDBAdapter);
24
+ IdaeDbAdapter.addAdapter(DbType.MYSQL, MySQLAdapter);
25
+ IdaeDbAdapter.addAdapter(DbType.CHROMADB, ChromaDBAdapter);
26
+ }
27
+ /**
28
+ * Adds a new adapter for a specific database type.
29
+ * @param dbType The type of database for this adapter.
30
+ * @param adapterConstructor The constructor function for the adapter.
31
+ */
32
+ static addAdapter(dbType, adapterConstructor) {
33
+ IdaeDbAdapter.adapters.set(dbType, adapterConstructor);
34
+ }
35
+ constructor(collection, connection, dbType) {
36
+ super();
37
+ this.dbType = dbType;
38
+ this.applyAdapter(collection, connection, this.dbType);
39
+ }
40
+ applyAdapter(collection, connection, dbType) {
41
+ const AdapterConstructor = IdaeDbAdapter.adapters.get(dbType);
42
+ if (!AdapterConstructor) {
43
+ throw new Error(`No adapter found for database type: ${dbType}`);
44
+ }
45
+ this.adapter = new AdapterConstructor(collection, connection);
46
+ }
47
+ /**
48
+ * Registers event listeners specific to this collection.
49
+ * @param events An object containing event listeners for different operations.
50
+ */
51
+ registerEvents(events) {
52
+ for (const [method, listeners] of Object.entries(events)) {
53
+ if (listeners.pre) {
54
+ this.on(`pre:${String(method)}`, listeners.pre);
55
+ }
56
+ if (listeners.post) {
57
+ this.on(`post:${String(method)}`, listeners.post);
58
+ }
59
+ if (listeners.error) {
60
+ this.on(`error:${String(method)}`, listeners.error);
61
+ }
62
+ }
63
+ }
64
+ static getAdapterForDbType(dbType) {
65
+ return IdaeDbAdapter.adapters.get(dbType);
66
+ }
67
+ async create(data) {
68
+ return this.adapter.create(data);
69
+ }
70
+ async findById(id) {
71
+ return this.adapter.findById(id);
72
+ }
73
+ async find(params) {
74
+ return this.adapter.find(params);
75
+ }
76
+ async findOne(params) {
77
+ return this.adapter.findOne(params);
78
+ }
79
+ async update(id, updateData) {
80
+ return this.adapter.update(id, updateData);
81
+ }
82
+ async updateWhere(params, updateData) {
83
+ return this.adapter.updateWhere(params, updateData);
84
+ }
85
+ async deleteById(id) {
86
+ return this.adapter.deleteById(id);
87
+ }
88
+ async deleteWhere(params) {
89
+ return this.adapter.deleteWhere(params);
90
+ }
91
+ async transaction(callback) {
92
+ return this.adapter.transaction(callback);
93
+ }
94
+ }
95
+ __decorate([
96
+ withEmitter(),
97
+ __metadata("design:type", Function),
98
+ __metadata("design:paramtypes", [typeof (_a = typeof Partial !== "undefined" && Partial) === "function" ? _a : Object]),
99
+ __metadata("design:returntype", Promise)
100
+ ], IdaeDbAdapter.prototype, "create", null);
101
+ __decorate([
102
+ withEmitter(),
103
+ __metadata("design:type", Function),
104
+ __metadata("design:paramtypes", [String]),
105
+ __metadata("design:returntype", Promise)
106
+ ], IdaeDbAdapter.prototype, "findById", null);
107
+ __decorate([
108
+ withEmitter(),
109
+ __metadata("design:type", Function),
110
+ __metadata("design:paramtypes", [Object]),
111
+ __metadata("design:returntype", Promise)
112
+ ], IdaeDbAdapter.prototype, "find", null);
113
+ __decorate([
114
+ withEmitter(),
115
+ __metadata("design:type", Function),
116
+ __metadata("design:paramtypes", [Object]),
117
+ __metadata("design:returntype", Promise)
118
+ ], IdaeDbAdapter.prototype, "findOne", null);
119
+ __decorate([
120
+ withEmitter(),
121
+ __metadata("design:type", Function),
122
+ __metadata("design:paramtypes", [String, typeof (_b = typeof Partial !== "undefined" && Partial) === "function" ? _b : Object]),
123
+ __metadata("design:returntype", Promise)
124
+ ], IdaeDbAdapter.prototype, "update", null);
125
+ __decorate([
126
+ withEmitter(),
127
+ __metadata("design:type", Function),
128
+ __metadata("design:paramtypes", [Object, typeof (_c = typeof Partial !== "undefined" && Partial) === "function" ? _c : Object]),
129
+ __metadata("design:returntype", Promise)
130
+ ], IdaeDbAdapter.prototype, "updateWhere", null);
131
+ __decorate([
132
+ withEmitter(),
133
+ __metadata("design:type", Function),
134
+ __metadata("design:paramtypes", [String]),
135
+ __metadata("design:returntype", Promise)
136
+ ], IdaeDbAdapter.prototype, "deleteById", null);
137
+ __decorate([
138
+ withEmitter(),
139
+ __metadata("design:type", Function),
140
+ __metadata("design:paramtypes", [Object]),
141
+ __metadata("design:returntype", Promise)
142
+ ], IdaeDbAdapter.prototype, "deleteWhere", null);
143
+ __decorate([
144
+ withEmitter(),
145
+ __metadata("design:type", Function),
146
+ __metadata("design:paramtypes", [Function]),
147
+ __metadata("design:returntype", typeof (_d = typeof Promise !== "undefined" && Promise) === "function" ? _d : Object)
148
+ ], IdaeDbAdapter.prototype, "transaction", null);
@@ -1,16 +1,17 @@
1
- import { Db } from "mongodb";
2
- import { Connection as MysqlConnection } from "mysql2/promise";
3
- import { DbType } from "./types";
1
+ import { IdaeDBModel } from './IdaeDBModel.js';
2
+ import { IdaeDb } from './idaeDb.js';
4
3
  export declare class IdaeDbConnection {
5
- private uri;
6
- private dbName;
7
- private dbType;
8
- private mongoClient;
9
- private mongoDb;
10
- private mysqlConnection;
11
- constructor(uri: string, dbName: string, dbType: DbType);
12
- connect(): Promise<void>;
13
- getDb(): Db | MysqlConnection;
4
+ #private;
5
+ private _idaeDb;
6
+ private _dbName;
7
+ constructor(_idaeDb: IdaeDb, _dbName: string);
8
+ connect(): Promise<IdaeDbConnection>;
9
+ getDb(): any;
10
+ getModel: <T extends Document>(collectionName: string) => IdaeDBModel<T>;
11
+ getClient<T>(): T;
14
12
  close(): Promise<void>;
15
- getDbType(): DbType;
13
+ get dbName(): string;
14
+ get connected(): boolean;
15
+ get idaeDb(): IdaeDb;
16
+ private getFullDbName;
16
17
  }
@@ -1,74 +1,73 @@
1
1
  // packages\idae-db\lib\IdaeDbConnection.ts
2
- import { MongoClient, Db } from "mongodb";
3
- import { Connection as MysqlConnection } from "mysql2/promise";
4
- import { DbType } from "./types";
2
+ import { DbType } from './types.js';
3
+ import { IdaeDBModel } from './IdaeDBModel.js';
4
+ import { IdaeDb } from './idaeDb.js';
5
5
  export class IdaeDbConnection {
6
- uri;
7
- dbName;
8
- dbType;
9
- mongoClient = null;
10
- mongoDb = null;
11
- mysqlConnection = null;
12
- constructor(uri, dbName, dbType) {
13
- this.uri = uri;
14
- this.dbName = dbName;
15
- this.dbType = dbType;
6
+ _idaeDb;
7
+ _dbName;
8
+ #models = new Map();
9
+ #uri;
10
+ #dbType;
11
+ #Db;
12
+ #client;
13
+ #adapterClass;
14
+ #connected = false;
15
+ constructor(_idaeDb, _dbName) {
16
+ this._idaeDb = _idaeDb;
17
+ this._dbName = _dbName;
18
+ this.#uri = _idaeDb.uri;
19
+ this.#dbType = _idaeDb.options.dbType;
20
+ this.#adapterClass = _idaeDb.adapterClass;
21
+ // add prefix if requested
22
+ this._dbName = this.getFullDbName();
16
23
  }
17
24
  async connect() {
25
+ if (!this.#adapterClass?.connect)
26
+ throw new Error('Adapter does not have a connect method');
18
27
  try {
19
- switch (this.dbType) {
20
- case DbType.MONGODB:
21
- this.mongoClient = new MongoClient(this.uri);
22
- await this.mongoClient.connect();
23
- this.mongoDb = this.mongoClient.db(this.dbName);
24
- console.log("Connected to MongoDB");
25
- break;
26
- case DbType.MYSQL:
27
- // this.mysqlConnection = await mysql.createConnection(...);
28
- console.log("Connected to MySQL");
29
- break;
30
- default:
31
- throw new Error(`Unsupported database type: ${this.dbType}`);
32
- }
28
+ this.#client = await this.#adapterClass.connect(this.#uri);
29
+ this.#Db = this.#adapterClass.getDb(this.#client, this._dbName);
30
+ this.#connected = true;
31
+ return this;
33
32
  }
34
33
  catch (error) {
35
- console.error(`Error connecting to ${this.dbType}:`, error);
34
+ console.error(`Error connecting to ${this.#dbType}:`, error);
35
+ this.#connected = false;
36
36
  throw error;
37
37
  }
38
38
  }
39
39
  getDb() {
40
- switch (this.dbType) {
41
- case DbType.MONGODB:
42
- if (!this.mongoDb) {
43
- throw new Error("MongoDB not connected. Call connect() first.");
44
- }
45
- return this.mongoDb;
46
- case DbType.MYSQL:
47
- if (!this.mysqlConnection) {
48
- throw new Error("MySQL not connected. Call connect() first.");
49
- }
50
- return this.mysqlConnection;
51
- default:
52
- throw new Error(`Unsupported database type: ${this.dbType}`);
40
+ if (!this.#Db) {
41
+ throw new Error('Db not connected. Call connect() first.');
53
42
  }
43
+ return this.#Db;
54
44
  }
55
- async close() {
56
- switch (this.dbType) {
57
- case DbType.MONGODB:
58
- if (this.mongoClient) {
59
- await this.mongoClient.close();
60
- console.log("Disconnected from MongoDB");
61
- }
62
- break;
63
- case DbType.MYSQL:
64
- if (this.mysqlConnection) {
65
- await this.mysqlConnection.end();
66
- console.log("Disconnected from MySQL");
67
- }
68
- break;
45
+ getModel = (collectionName) => {
46
+ if (!this.#models.has(collectionName)) {
47
+ const model = new IdaeDBModel(this, collectionName, this._idaeDb?.options?.idaeModelOptions);
48
+ this.#models.set(collectionName, model);
49
+ }
50
+ return this.#models.get(collectionName);
51
+ };
52
+ getClient() {
53
+ if (!this.#client) {
54
+ throw new Error('Client not initialized. Call connect() first.');
69
55
  }
56
+ return this.#client;
57
+ }
58
+ async close() {
59
+ if (!this.#adapterClass?.close)
60
+ throw new Error('Adapter does not have a close method');
61
+ await this.#adapterClass?.close(this.#client);
62
+ }
63
+ get dbName() {
64
+ return this._dbName;
65
+ }
66
+ get connected() {
67
+ return this.#connected;
70
68
  }
71
- getDbType() {
72
- return this.dbType;
69
+ get idaeDb() {
70
+ return this._idaeDb;
73
71
  }
72
+ getFullDbName = () => [this.idaeDb.options.dbScope, this._dbName].join('_');
74
73
  }
@@ -0,0 +1,52 @@
1
+ import { EventEmitter } from 'events';
2
+ import { IdaeDbAdapter } from './IdaeDbAdapter.js';
3
+ /**
4
+ * IdaeEventEmitter extends Node's EventEmitter to provide pre/post method hooks.
5
+ */
6
+ export declare class IdaeEventEmitter extends EventEmitter {
7
+ /**
8
+ * Overrides the emit method to ensure type safety.
9
+ * @param event The name of the event to emit.
10
+ * @param args The arguments to pass to the event listeners.
11
+ * @returns Whether the event had listeners.
12
+ */
13
+ emit(event: string | symbol, ...args: any[]): boolean;
14
+ }
15
+ /**
16
+ * Decorator factory to add pre/post hooks to a method.
17
+ * @returns A method decorator that adds event emission for pre/post hooks.
18
+ */
19
+ export declare function withEmitter(): (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any> | void;
20
+ /**
21
+ * Type for pre-execution event listeners.
22
+ */
23
+ export type PreEventListener<T extends any[]> = (...args: T) => void | Promise<void>;
24
+ /**
25
+ * Type for post-execution event listeners.
26
+ */
27
+ export type PostEventListener<T extends any[], R> = (result: R, ...args: T) => void | Promise<void>;
28
+ /**
29
+ * Type for error event listeners.
30
+ */
31
+ export type ErrorEventListener = (error: Error) => void | Promise<void>;
32
+ /**
33
+ * Interface to extend IdaeEventEmitter with strongly typed event listeners.
34
+ */
35
+ export interface TypedIdaeEventEmitter<T> {
36
+ on<K extends keyof T>(event: `pre:${K & string}`, listener: PreEventListener<Parameters<T[K]>>): this;
37
+ on<K extends keyof T>(event: `post:${K & string}`, listener: PostEventListener<Parameters<T[K]>, ReturnType<T[K]>>): this;
38
+ on<K extends keyof T>(event: `error:${K & string}`, listener: ErrorEventListener): this;
39
+ once<K extends keyof T>(event: `pre:${K & string}`, listener: PreEventListener<Parameters<T[K]>>): this;
40
+ once<K extends keyof T>(event: `post:${K & string}`, listener: PostEventListener<Parameters<T[K]>, ReturnType<T[K]>>): this;
41
+ once<K extends keyof T>(event: `error:${K & string}`, listener: ErrorEventListener): this;
42
+ emit<K extends keyof T>(event: `pre:${K & string}`, ...args: Parameters<T[K]>): boolean;
43
+ emit<K extends keyof T>(event: `post:${K & string}`, result: ReturnType<T[K]>, ...args: Parameters<T[K]>): boolean;
44
+ emit<K extends keyof T>(event: `error:${K & string}`, error: Error): boolean;
45
+ }
46
+ export type EventListeners<T> = {
47
+ [K in keyof IdaeDbAdapter<T>]?: {
48
+ pre?: PreEventListener<Parameters<IdaeDbAdapter<T>[K]>>;
49
+ post?: PostEventListener<Parameters<IdaeDbAdapter<T>[K]>, ReturnType<IdaeDbAdapter<T>[K]>>;
50
+ error?: ErrorEventListener;
51
+ };
52
+ };
@@ -0,0 +1,46 @@
1
+ import { EventEmitter } from 'events';
2
+ import { IdaeDbAdapter } from './IdaeDbAdapter.js';
3
+ /**
4
+ * IdaeEventEmitter extends Node's EventEmitter to provide pre/post method hooks.
5
+ */
6
+ export class IdaeEventEmitter extends EventEmitter {
7
+ /**
8
+ * Overrides the emit method to ensure type safety.
9
+ * @param event The name of the event to emit.
10
+ * @param args The arguments to pass to the event listeners.
11
+ * @returns Whether the event had listeners.
12
+ */
13
+ emit(event, ...args) {
14
+ return super.emit(event, ...args);
15
+ }
16
+ }
17
+ /**
18
+ * Decorator factory to add pre/post hooks to a method.
19
+ * @returns A method decorator that adds event emission for pre/post hooks.
20
+ */
21
+ export function withEmitter() {
22
+ return function (target, propertyKey, descriptor) {
23
+ if (descriptor === undefined) {
24
+ descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
25
+ }
26
+ const originalMethod = descriptor.value;
27
+ descriptor.value = async function (...args) {
28
+ // Emit the pre-execution event
29
+ this.emit(`pre:${String(propertyKey)}`, ...args);
30
+ let result;
31
+ try {
32
+ // Execute the original method
33
+ result = await originalMethod.apply(this, args);
34
+ }
35
+ catch (error) {
36
+ // Emit the error event if an exception occurs
37
+ this.emit(`error:${String(propertyKey)}`, error);
38
+ throw error;
39
+ }
40
+ // Emit the post-execution event
41
+ this.emit(`post:${String(propertyKey)}`, result, ...args);
42
+ return result;
43
+ };
44
+ return descriptor;
45
+ };
46
+ }