@medyll/idae-db 0.149.0 → 0.155.2

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 medyll
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 medyll
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,178 +1,337 @@
1
- # Idae Database Library
2
-
3
- The Idae Database Library provides a flexible and extensible way to interact with various databases such as MongoDB, MySQL. It includes features like event emitters for pre/post hooks, auto-increment fields, and more.
4
-
5
- ## Installation
6
-
7
- To install the library, run:
8
-
9
- ```bash
10
- npm install idae-db
11
- ```
12
-
13
- ## Scripts
14
-
15
- ```bash
16
- npm run test # Run all tests
17
- npm run test:coverage # Run tests with coverage (v8)
18
- npm run test:mongodb # Run only the MongoDB adapter suite (in-memory mongo)
19
- ```
20
-
21
- ## Usage
22
-
23
- ### Initialization
24
-
25
- First, initialize the database connection:
26
-
27
- #### MongoDB
28
-
29
- ```typescript
30
- import { IdaeDb } from './lib/idaeDb.js';
31
- import { DbType } from './lib/@types/types.js';
32
-
33
- const mongoDb = IdaeDb.init('mongodb://localhost:27017', {
34
- dbType: DbType.MONGODB,
35
- dbScope: 'a_idae_db_sitebase',
36
- dbScopeSeparator: '_',
37
- idaeModelOptions: {
38
- autoIncrementFormat: (collection: string) => `id${collection}`,
39
- autoIncrementDbCollection: 'auto_increment'
40
- }
41
- });
42
- ```
43
-
44
- #### MySQL
45
-
46
- ```typescript
47
- import { IdaeDb } from './lib/idaeDb.js';
48
- import { DbType } from './lib/@types/types.js';
49
-
50
- const mysqlDb = IdaeDb.init('mysql://user:password@localhost:3306', {
51
- dbType: DbType.MYSQL,
52
- dbScope: 'a_idae_db_sitebase',
53
- dbScopeSeparator: '_',
54
- idaeModelOptions: {
55
- autoIncrementFormat: (collection: string) => `id${collection}`,
56
- autoIncrementDbCollection: 'auto_increment'
57
- }
58
- });
59
- ```
60
-
61
- ### Create a Connection
62
-
63
- Create a connection to the database:
64
-
65
- ```typescript
66
- await mongoDb.db('app');
67
- await mysqlDb.db('app');
68
- ```
69
-
70
- ### Define a Model
71
-
72
- Define a model interface:
73
-
74
- ```typescript
75
- interface User {
76
- iduser: number;
77
- name: string;
78
- email: string;
79
- age: number;
80
- }
81
- ```
82
-
83
- ### Register Event Listeners
84
-
85
- Register event listeners for various operations:
86
-
87
- ```typescript
88
- const usersCollection = mongoDb.collection<User>('user');
89
-
90
- usersCollection.registerEvents<any>({
91
- findById: {
92
- pre: (id) => console.log(`About to find document with id: ${id}`),
93
- post: (result, id) => console.log(`Found document for id ${id}:`, result),
94
- error: (error) => console.error('Error in findById:', error)
95
- },
96
- update: {
97
- pre: (id, data) => console.log(`About to update document ${id} with:`, data),
98
- post: (result, id, data) => console.log(`Updated document ${id}:`, result)
99
- },
100
- create: {
101
- pre: (data) => console.log(`About to create document with:`, data),
102
- post: (data, result) => console.log(`Created document `, data, result)
103
- }
104
- });
105
- ```
106
-
107
- ### CRUD Operations
108
-
109
- Perform CRUD operations:
110
-
111
- #### MongoDB
112
-
113
- ```typescript
114
- // Create a new user
115
- const newUser = await usersCollection.create({
116
- name: 'John Doe',
117
- email: 'john@example.com',
118
- age: 30
119
- });
120
-
121
- // Find a user by email
122
- const user = await usersCollection.findOne({ query: { email: 'john@example.com' } });
123
-
124
- // Update a user's age
125
- const updateResult = await usersCollection.update(user.iduser, { age: 31 });
126
-
127
- // Find users with age greater than 25
128
- const users = await usersCollection.find({
129
- query: { age: { $gt: 25 } },
130
- sortBy: 'name:asc',
131
- limit: 10
132
- });
133
-
134
- // Delete a user by ID
135
- const deleteResult = await usersCollection.deleteById(5);
136
- ```
137
-
138
- #### MySQL
139
-
140
- ```typescript
141
- const usersCollection = mysqlDb.collection<User>('user');
142
-
143
- // Create a new user
144
- const newUser = await usersCollection.create({
145
- name: 'John Doe',
146
- email: 'john@example.com',
147
- age: 30
148
- });
149
-
150
- // Find a user by email
151
- const user = await usersCollection.findOne({ query: { email: 'john@example.com' } });
152
-
153
- // Update a user's age
154
- const updateResult = await usersCollection.update(user.iduser, { age: 31 });
155
-
156
- // Find users with age greater than 25
157
- const users = await usersCollection.find({
158
- query: { age: { $gt: 25 } },
159
- sortBy: 'name:asc',
160
- limit: 10
161
- });
162
-
163
- // Delete a user by ID
164
- const deleteResult = await usersCollection.deleteById(5);
165
- ```
166
-
167
- ### Close Connections
168
-
169
- Close all connections when done:
170
-
171
- ```typescript
172
- await mongoDb.closeAllConnections();
173
- await mysqlDb.closeAllConnections();
174
- ```
175
-
176
- ## License
177
-
1
+ # Idae Database Library
2
+
3
+ **Idae Database Library** is a flexible, type-safe, event-driven database abstraction for Node.js and TypeScript. It supports MongoDB, MySQL, ChromaDB, PouchDB, SQLite, and PostgreSQL with a unified API, event hooks, and singleton connection management.
4
+
5
+ ## Features
6
+
7
+ - **Multi-Database Support:** MongoDB, MySQL, ChromaDB, PouchDB, SQLite, PostgreSQL
8
+ - **Event-driven CRUD:** Pre/post/error hooks on all operations
9
+ - **Type Safety:** Full TypeScript generics, strict mode
10
+ - **Singleton Pattern:** One connection per URI+DbType
11
+ - **Adapter Pattern:** Easily extend to new databases
12
+ - **Auto-increment:** Native for MongoDB, extensible for others
13
+ - **Transaction Support:** Native in MongoDB/MySQL
14
+
15
+ ## Supported Adapters
16
+
17
+ | DbType | Adapter Class | Peer Dependency |
18
+ |-------------- |----------------------|-----------------|
19
+ | MONGODB | MongoDBAdapter | mongodb |
20
+ | MYSQL | MySQLAdapter | mysql2 |
21
+ | CHROMADB | ChromaDBAdapter | chromadb |
22
+ | POUCHDB | PouchDBAdapter | pouchdb |
23
+ | SQLITE | SQLiteAdapter | sqlite3 |
24
+ | POSTGRESQL | PostgreSQLAdapter | pg |
25
+
26
+ ## Installation
27
+
28
+ Install the core library and the peer dependencies for your database(s):
29
+
30
+ ```bash
31
+ pnpm add @medyll/idae-db
32
+ # For MongoDB:
33
+ pnpm add mongodb
34
+ # For MySQL:
35
+ pnpm add mysql2
36
+ # For ChromaDB:
37
+ pnpm add chromadb
38
+ # For PouchDB:
39
+ pnpm add pouchdb
40
+ # For SQLite:
41
+ pnpm add sqlite3
42
+ # For PostgreSQL:
43
+ pnpm add pg
44
+ ```
45
+
46
+ ## Quick Start
47
+
48
+ ### 1. Initialize a Database
49
+
50
+ ```typescript
51
+ import { IdaeDb } from '@medyll/idae-db';
52
+ import { DbType } from '@medyll/idae-db/lib/@types/types';
53
+
54
+ const db = IdaeDb.init('mongodb://localhost:27017', {
55
+ dbType: DbType.MONGODB,
56
+ dbScope: 'app',
57
+ });
58
+ await db.db('app');
59
+ ```
60
+
61
+ ### 2. Define a Model
62
+
63
+ ```typescript
64
+ interface User {
65
+ iduser: number;
66
+ name: string;
67
+ email: string;
68
+ age: number;
69
+ }
70
+ ```
71
+
72
+ ### 3. CRUD Operations
73
+
74
+ ```typescript
75
+ const users = db.collection<User>('user');
76
+ const newUser = await users.create({ name: 'Alice', email: 'alice@example.com', age: 25 });
77
+ const found = await users.findOne({ query: { email: 'alice@example.com' } });
78
+ await users.update(found.iduser, { age: 26 });
79
+ await users.deleteById(found.iduser);
80
+ ```
81
+
82
+ ### 4. Event Hooks
83
+
84
+ ```typescript
85
+ users.registerEvents({
86
+ create: {
87
+ pre: (data) => console.log('Creating:', data),
88
+ post: (result, data) => console.log('Created:', result),
89
+ error: (err) => console.error(err)
90
+ }
91
+ });
92
+ ```
93
+
94
+ ## Adapter Usage Examples
95
+
96
+ ### MongoDB
97
+
98
+ ```typescript
99
+ const mongoDb = IdaeDb.init('mongodb://localhost:27017', { dbType: DbType.MONGODB });
100
+ await mongoDb.db('app');
101
+ const users = mongoDb.collection<User>('user');
102
+ ```
103
+
104
+ ### MySQL
105
+
106
+ ```typescript
107
+ const mysqlDb = IdaeDb.init('mysql://user:password@localhost:3306', { dbType: DbType.MYSQL });
108
+ await mysqlDb.db('app');
109
+ const users = mysqlDb.collection<User>('user');
110
+ ```
111
+
112
+ ### ChromaDB
113
+
114
+ ```typescript
115
+ const chromaDb = IdaeDb.init('chromadb://localhost:8000', { dbType: DbType.CHROMADB });
116
+ await chromaDb.db('app');
117
+ const items = chromaDb.collection<any>('item');
118
+ ```
119
+
120
+ ### PouchDB
121
+
122
+ ```typescript
123
+ const pouchDb = IdaeDb.init('pouchdb://./my-pouchdb-folder', { dbType: DbType.POUCHDB });
124
+ await pouchDb.db('app');
125
+ const docs = pouchDb.collection<any>('doc');
126
+ ```
127
+
128
+ ### SQLite
129
+
130
+ ```typescript
131
+ const sqliteDb = IdaeDb.init('sqlite://./mydb.sqlite', { dbType: DbType.SQLITE });
132
+ await sqliteDb.db('app');
133
+ const users = sqliteDb.collection<User>('user');
134
+ ```
135
+
136
+ ### PostgreSQL
137
+
138
+ ```typescript
139
+ const pgDb = IdaeDb.init('postgresql://user:password@localhost:5432/mydb', { dbType: DbType.POSTGRESQL });
140
+ await pgDb.db('app');
141
+ const users = pgDb.collection<User>('user');
142
+ ```
143
+
144
+ ## Event System
145
+
146
+ All CRUD methods emit `pre:method`, `post:method`, and `error:method` events. Register listeners with `registerEvents`:
147
+
148
+ ```typescript
149
+ users.registerEvents({
150
+ create: {
151
+ pre: (data) => console.log('Creating:', data),
152
+ post: (result, data) => console.log('Created:', result),
153
+ error: (err) => console.error(err)
154
+ },
155
+ update: {
156
+ pre: (id, data) => console.log('Updating:', id, data),
157
+ post: (result, id, data) => console.log('Updated:', result),
158
+ error: (err) => console.error(err)
159
+ }
160
+ });
161
+ ```
162
+
163
+ ## Type Safety
164
+
165
+ - All models are fully typed (`T extends object`)
166
+ - Query params: `IdaeDbParams<T>`
167
+ - MongoDB filters: use `Filter<T>`
168
+ - ID field: MongoDB uses `_id` or custom via `autoIncrementFormat`
169
+
170
+ ## Singleton & Connection Management
171
+
172
+ - One instance per URI+DbType
173
+ - Use `.closeAllConnections()` to gracefully close all DBs:
174
+
175
+ ```typescript
176
+ await db.closeAllConnections();
177
+ ```
178
+
179
+ ## Scripts
180
+
181
+ ```bash
182
+ pnpm run test # Run all tests
183
+ pnpm run build # Build the package
184
+ pnpm run lint # Lint code
185
+ pnpm run format # Format code
186
+ ```
187
+
188
+ ## License
189
+
190
+ MIT License
191
+ import { DbType } from './lib/@types/types.js';
192
+
193
+ const pouchDb = IdaeDb.init('pouchdb://./my-pouchdb-folder', {
194
+ dbType: DbType.POUCHDB
195
+ });
196
+ ```
197
+
198
+ #### SQLite
199
+
200
+ ```typescript
201
+ import { IdaeDb } from './lib/idaeDb.js';
202
+ import { DbType } from './lib/@types/types.js';
203
+
204
+ const sqliteDb = IdaeDb.init('sqlite://./mydb.sqlite', {
205
+ dbType: DbType.SQLITE
206
+ });
207
+ ```
208
+
209
+ #### PostgreSQL
210
+
211
+ ```typescript
212
+ import { IdaeDb } from './lib/idaeDb.js';
213
+ import { DbType } from './lib/@types/types.js';
214
+
215
+ const pgDb = IdaeDb.init('postgresql://user:password@localhost:5432/mydb', {
216
+ dbType: DbType.POSTGRESQL
217
+ });
218
+ ```
219
+
220
+ ### Create a Connection
221
+
222
+ Create a connection to the database:
223
+
224
+ ```typescript
225
+ await mongoDb.db('app');
226
+ await mysqlDb.db('app');
227
+ ```
228
+
229
+ ### Define a Model
230
+
231
+ Define a model interface:
232
+
233
+ ```typescript
234
+ interface User {
235
+ iduser: number;
236
+ name: string;
237
+ email: string;
238
+ age: number;
239
+ }
240
+ ```
241
+
242
+ ### Register Event Listeners
243
+
244
+ Register event listeners for various operations:
245
+
246
+ ```typescript
247
+ const usersCollection = mongoDb.collection<User>('user');
248
+
249
+ usersCollection.registerEvents<any>({
250
+ findById: {
251
+ pre: (id) => console.log(`About to find document with id: ${id}`),
252
+ post: (result, id) => console.log(`Found document for id ${id}:`, result),
253
+ error: (error) => console.error('Error in findById:', error)
254
+ },
255
+ update: {
256
+ pre: (id, data) => console.log(`About to update document ${id} with:`, data),
257
+ post: (result, id, data) => console.log(`Updated document ${id}:`, result)
258
+ },
259
+ create: {
260
+ pre: (data) => console.log(`About to create document with:`, data),
261
+ post: (data, result) => console.log(`Created document `, data, result)
262
+ }
263
+ });
264
+ ```
265
+
266
+ ### CRUD Operations
267
+
268
+ Perform CRUD operations:
269
+
270
+ #### MongoDB
271
+
272
+ ```typescript
273
+ // Create a new user
274
+ const newUser = await usersCollection.create({
275
+ name: 'John Doe',
276
+ email: 'john@example.com',
277
+ age: 30
278
+ });
279
+
280
+ // Find a user by email
281
+ const user = await usersCollection.findOne({ query: { email: 'john@example.com' } });
282
+
283
+ // Update a user's age
284
+ const updateResult = await usersCollection.update(user.iduser, { age: 31 });
285
+
286
+ // Find users with age greater than 25
287
+ const users = await usersCollection.find({
288
+ query: { age: { $gt: 25 } },
289
+ sortBy: 'name:asc',
290
+ limit: 10
291
+ });
292
+
293
+ // Delete a user by ID
294
+ const deleteResult = await usersCollection.deleteById(5);
295
+ ```
296
+
297
+ #### MySQL
298
+
299
+ ```typescript
300
+ const usersCollection = mysqlDb.collection<User>('user');
301
+
302
+ // Create a new user
303
+ const newUser = await usersCollection.create({
304
+ name: 'John Doe',
305
+ email: 'john@example.com',
306
+ age: 30
307
+ });
308
+
309
+ // Find a user by email
310
+ const user = await usersCollection.findOne({ query: { email: 'john@example.com' } });
311
+
312
+ // Update a user's age
313
+ const updateResult = await usersCollection.update(user.iduser, { age: 31 });
314
+
315
+ // Find users with age greater than 25
316
+ const users = await usersCollection.find({
317
+ query: { age: { $gt: 25 } },
318
+ sortBy: 'name:asc',
319
+ limit: 10
320
+ });
321
+
322
+ // Delete a user by ID
323
+ const deleteResult = await usersCollection.deleteById(5);
324
+ ```
325
+
326
+ ### Close Connections
327
+
328
+ Close all connections when done:
329
+
330
+ ```typescript
331
+ await mongoDb.closeAllConnections();
332
+ await mysqlDb.closeAllConnections();
333
+ ```
334
+
335
+ ## License
336
+
178
337
  This project is licensed under the MIT License.
package/cli.js ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+
7
+ const pkgJson = require(path.join(__dirname, 'package.json'));
8
+ const packageName = pkgJson.name.replace(/^@[^/]+\//, '');
9
+ const cmd = process.argv[2];
10
+
11
+
12
+ if (cmd === 'get-readme') {
13
+ const readmePath = path.join(__dirname, 'README.md');
14
+ if (fs.existsSync(readmePath)) {
15
+ const content = fs.readFileSync(readmePath, 'utf8');
16
+ console.log(content);
17
+ } else {
18
+ console.error('README.md not found in this package.');
19
+ process.exit(1);
20
+ }
21
+ } else if (cmd === 'install-skill') {
22
+ const readline = require('readline');
23
+ const rl = readline.createInterface({
24
+ input: process.stdin,
25
+ output: process.stdout
26
+ });
27
+ const skillSrc = path.join(__dirname, 'SKILL.md');
28
+ const skillDest = path.resolve(__dirname, `../../../.github/skills/${packageName}/SKILL.md`);
29
+ if (!fs.existsSync(skillSrc)) {
30
+ console.error('SKILL.md not found in this package.');
31
+ process.exit(1);
32
+ }
33
+ rl.question(`This will copy SKILL.md to .github/skills/${packageName}/SKILL.md. Continue? (y/n): `, (answer) => {
34
+ if (answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes') {
35
+ fs.mkdirSync(path.dirname(skillDest), { recursive: true });
36
+ fs.copyFileSync(skillSrc, skillDest);
37
+ console.log(`SKILL.md installed to .github/skills/${packageName}/SKILL.md`);
38
+ } else {
39
+ console.log('Operation cancelled.');
40
+ }
41
+ rl.close();
42
+ });
43
+ } else {
44
+ console.log('Usage: <cli> get-readme | install-skill');
45
+ process.exit(1);
46
+ }
@@ -0,0 +1 @@
1
+ declare module 'pg';
@@ -33,7 +33,10 @@ export interface IdaeDbParamsSortOptions {
33
33
  export declare enum DbType {
34
34
  MONGODB = "mongodb",
35
35
  MYSQL = "mysql",
36
- CHROMADB = "chromaDb"
36
+ CHROMADB = "chromaDb",
37
+ POUCHDB = "pouchdb",
38
+ SQLITE = "sqlite",
39
+ POSTGRESQL = "postgresql"
37
40
  }
38
41
  export declare abstract class AbstractIdaeDbAdapter<T extends object> implements IdaeDbAdapterInterface<T> {
39
42
  abstract createIndex(fieldOrSpec: unknown, options?: unknown): Promise<string>;
@@ -5,6 +5,9 @@ export var DbType;
5
5
  DbType["MONGODB"] = "mongodb";
6
6
  DbType["MYSQL"] = "mysql";
7
7
  DbType["CHROMADB"] = "chromaDb";
8
+ DbType["POUCHDB"] = "pouchdb";
9
+ DbType["SQLITE"] = "sqlite";
10
+ DbType["POSTGRESQL"] = "postgresql";
8
11
  })(DbType || (DbType = {}));
9
12
  export class AbstractIdaeDbAdapter {
10
13
  static connect(uri) {
@@ -14,6 +14,9 @@ import { IdaeDbConnection } from './IdaeDbConnection.js';
14
14
  import { MongoDBAdapter } from './adapters/MongoDBAdapter.js';
15
15
  import { MySQLAdapter } from './adapters/MySQLAdapter.js';
16
16
  import { ChromaDBAdapter } from './adapters/ChromaDBAdapter.js';
17
+ import { PouchDBAdapter } from './adapters/PouchDBAdapter.js';
18
+ import { SQLiteAdapter } from './adapters/SQLiteAdapter.js';
19
+ import { PostgreSQLAdapter } from './adapters/PostgreSQLAdapter.js';
17
20
  import { IdaeEventEmitter, withEmitter } from './IdaeEventEmitter.js';
18
21
  /**
19
22
  * IdaeDbAdapter class that extends IdaeEventEmitter and implements AbstractIdaeDbAdapter.
@@ -26,6 +29,9 @@ export class IdaeDbAdapter extends IdaeEventEmitter {
26
29
  IdaeDbAdapter.addAdapter(DbType.MONGODB, MongoDBAdapter);
27
30
  IdaeDbAdapter.addAdapter(DbType.MYSQL, MySQLAdapter);
28
31
  IdaeDbAdapter.addAdapter(DbType.CHROMADB, ChromaDBAdapter);
32
+ IdaeDbAdapter.addAdapter(DbType.POUCHDB, PouchDBAdapter);
33
+ IdaeDbAdapter.addAdapter(DbType.SQLITE, SQLiteAdapter);
34
+ IdaeDbAdapter.addAdapter(DbType.POSTGRESQL, PostgreSQLAdapter);
29
35
  }
30
36
  /**
31
37
  * Adds a new adapter for a specific database type.
@@ -14,9 +14,9 @@ export declare class MongoDBAdapter<T extends Document> implements AbstractIdaeD
14
14
  find(params: IdaeDbParams<T>): Promise<T[]>;
15
15
  findOne(params: IdaeDbParams<T>): Promise<T | null>;
16
16
  create(data: Partial<T>): Promise<T>;
17
- update(id: string, updateData: Partial<T>, options?: UpdateOptions): Promise<any>;
18
- updateWhere<OPT = never>(params: IdaeDbParams<T>, updateData: Partial<T>, options?: OPT): Promise<any>;
19
- deleteById(id: string | number): Promise<any>;
17
+ update(id: string, updateData: Partial<T>, options?: UpdateOptions): Promise<import("mongodb").UpdateResult<T>>;
18
+ updateWhere<OPT = never>(params: IdaeDbParams<T>, updateData: Partial<T>, options?: OPT): Promise<import("mongodb").UpdateResult<T>>;
19
+ deleteById(id: string | number): Promise<import("mongodb").DeleteResult>;
20
20
  deleteWhere(params: IdaeDbParams<T>): Promise<{
21
21
  deletedCount?: number;
22
22
  }>;
@@ -0,0 +1,22 @@
1
+ import type { IdaeDbAdapterInterface, IdaeDbParams } from '../@types/types';
2
+ export declare class PostgreSQLAdapter<T extends object> implements IdaeDbAdapterInterface<T> {
3
+ private client;
4
+ private table;
5
+ private idField;
6
+ constructor(collection: string, connection: any);
7
+ static connect(uri: string, options?: any): Promise<any>;
8
+ static getDb(connection: any, dbName: string): Promise<any>;
9
+ static close(connection: any): Promise<void>;
10
+ create(data: Partial<T>): Promise<T>;
11
+ find(params?: IdaeDbParams<T>): Promise<T[]>;
12
+ findOne(params: IdaeDbParams<T>): Promise<T | null>;
13
+ update(id: string, data: Partial<T>): Promise<T | null>;
14
+ deleteById(id: string): Promise<boolean>;
15
+ transaction<TResult>(callback: (session: unknown) => Promise<TResult>): Promise<TResult>;
16
+ createIndex<F, O>(fieldOrSpec: F, options?: O): Promise<unknown>;
17
+ findById(id: string): Promise<T[]>;
18
+ updateWhere<OPT = never>(params: IdaeDbParams<T>, updateData: Partial<T>, options?: OPT): Promise<unknown>;
19
+ deleteWhere(params: IdaeDbParams<T>): Promise<{
20
+ deletedCount?: number;
21
+ }>;
22
+ }
@@ -0,0 +1,127 @@
1
+ import { Client } from 'pg';
2
+ export class PostgreSQLAdapter {
3
+ client;
4
+ table;
5
+ idField;
6
+ constructor(collection, connection) {
7
+ // connection est un IdaeDbConnection, on récupère la vraie connexion
8
+ this.client = connection.getDb();
9
+ this.table = collection;
10
+ this.idField = 'id';
11
+ }
12
+ static async connect(uri, options) {
13
+ const client = new Client({ connectionString: uri, ...options });
14
+ await client.connect();
15
+ return client;
16
+ }
17
+ static async getDb(connection, dbName) {
18
+ // PostgreSQL: pas de notion de dbName, retourne la connexion
19
+ return connection;
20
+ }
21
+ static async close(connection) {
22
+ await connection.end();
23
+ }
24
+ async create(data) {
25
+ const keys = Object.keys(data);
26
+ const values = keys.map((k) => data[k]);
27
+ const placeholders = keys.map((_, i) => `$${i + 1}`).join(',');
28
+ const sql = `INSERT INTO ${this.table} (${keys.join(',')}) VALUES (${placeholders}) RETURNING *`;
29
+ const result = await this.client.query(sql, values);
30
+ return result.rows[0];
31
+ }
32
+ async find(params) {
33
+ const { query = {}, limit, sortBy } = params || {};
34
+ let sql = `SELECT * FROM ${this.table}`;
35
+ const where = [];
36
+ const values = [];
37
+ let idx = 1;
38
+ for (const k in query) {
39
+ where.push(`${k} = $${idx}`);
40
+ values.push(query[k]);
41
+ idx++;
42
+ }
43
+ if (where.length)
44
+ sql += ' WHERE ' + where.join(' AND ');
45
+ if (sortBy)
46
+ sql += ` ORDER BY ${sortBy}`;
47
+ if (limit)
48
+ sql += ` LIMIT ${limit}`;
49
+ const result = await this.client.query(sql, values);
50
+ return result.rows;
51
+ }
52
+ async findOne(params) {
53
+ const results = await this.find({ ...params, limit: 1 });
54
+ return results[0] || null;
55
+ }
56
+ async update(id, data) {
57
+ const keys = Object.keys(data);
58
+ const values = keys.map((k) => data[k]);
59
+ const set = keys.map((k, i) => `${k} = $${i + 1}`).join(', ');
60
+ const sql = `UPDATE ${this.table} SET ${set} WHERE ${this.idField} = $${keys.length + 1} RETURNING *`;
61
+ const result = await this.client.query(sql, [...values, id]);
62
+ return result.rows[0];
63
+ }
64
+ async deleteById(id) {
65
+ const sql = `DELETE FROM ${this.table} WHERE ${this.idField} = $1`;
66
+ const result = await this.client.query(sql, [id]);
67
+ return result.rowCount > 0;
68
+ }
69
+ async transaction(callback) {
70
+ await this.client.query('BEGIN');
71
+ try {
72
+ // PostgreSQL n'expose pas de session explicite, on passe undefined
73
+ const result = await callback(undefined);
74
+ await this.client.query('COMMIT');
75
+ return result;
76
+ }
77
+ catch (e) {
78
+ await this.client.query('ROLLBACK');
79
+ throw e;
80
+ }
81
+ }
82
+ async createIndex(fieldOrSpec, options) {
83
+ // Not implemented for PostgreSQL (no-op)
84
+ return Promise.resolve();
85
+ }
86
+ async findById(id) {
87
+ const sql = `SELECT * FROM ${this.table} WHERE ${this.idField} = $1`;
88
+ const result = await this.client.query(sql, [id]);
89
+ return result.rows;
90
+ }
91
+ async updateWhere(params, updateData, options) {
92
+ // Simple implementation: update all matching rows
93
+ const { query = {} } = params;
94
+ const keys = Object.keys(updateData);
95
+ const values = keys.map((k) => updateData[k]);
96
+ const set = keys.map((k, i) => `${k} = $${i + 1}`).join(', ');
97
+ const where = [];
98
+ const whereValues = [];
99
+ let idx = keys.length + 1;
100
+ for (const k in query) {
101
+ where.push(`${k} = $${idx}`);
102
+ whereValues.push(query[k]);
103
+ idx++;
104
+ }
105
+ let sql = `UPDATE ${this.table} SET ${set}`;
106
+ if (where.length)
107
+ sql += ' WHERE ' + where.join(' AND ');
108
+ const result = await this.client.query(sql, [...values, ...whereValues]);
109
+ return { rowCount: result.rowCount };
110
+ }
111
+ async deleteWhere(params) {
112
+ const { query = {} } = params;
113
+ const where = [];
114
+ const values = [];
115
+ let idx = 1;
116
+ for (const k in query) {
117
+ where.push(`${k} = $${idx}`);
118
+ values.push(query[k]);
119
+ idx++;
120
+ }
121
+ let sql = `DELETE FROM ${this.table}`;
122
+ if (where.length)
123
+ sql += ' WHERE ' + where.join(' AND ');
124
+ const result = await this.client.query(sql, values);
125
+ return { deletedCount: result.rowCount };
126
+ }
127
+ }
@@ -0,0 +1,14 @@
1
+ import type { IdaiDbAdapterInterface, IdaeDbParams } from '../@types/types';
2
+ export declare class PouchDBAdapter<T extends object> implements IdaiDbAdapterInterface<T> {
3
+ private db;
4
+ constructor(collection: string, connection: any);
5
+ static connect(uri: string, options?: any): Promise<any>;
6
+ static getDb(connection: any, dbName: string): Promise<any>;
7
+ static close(connection: any): Promise<void>;
8
+ create(data: Partial<T>): Promise<T>;
9
+ find(params?: IdaeDbParams<T>): Promise<T[]>;
10
+ findOne(params: IdaeDbParams<T>): Promise<T | null>;
11
+ update(id: string, data: Partial<T>): Promise<T | null>;
12
+ deleteById(id: string): Promise<boolean>;
13
+ transaction(fn: () => Promise<any>): Promise<any>;
14
+ }
@@ -0,0 +1,62 @@
1
+ import PouchDB from 'pouchdb';
2
+ export class PouchDBAdapter {
3
+ db;
4
+ constructor(collection, connection) {
5
+ // connection est un IdaeDbConnection, on récupère la vraie connexion
6
+ this.db = connection.getDb();
7
+ }
8
+ static async connect(uri, options) {
9
+ // uri: pouchdb://./folder or pouchdb://memory
10
+ let dbPath = uri.replace(/^pouchdb:\/\//, '');
11
+ if (!dbPath)
12
+ dbPath = 'idae-pouchdb';
13
+ return new PouchDB(dbPath, options);
14
+ }
15
+ static async getDb(connection, dbName) {
16
+ // PouchDB does not use dbName, just return the connection
17
+ return connection;
18
+ }
19
+ static async close(connection) {
20
+ await connection.close();
21
+ }
22
+ async create(data) {
23
+ const doc = { ...data };
24
+ const result = await this.db.post(doc);
25
+ return { ...doc, _id: result.id, _rev: result.rev };
26
+ }
27
+ async find(params) {
28
+ // Only supports simple query for now
29
+ const { query = {}, limit, sortBy } = params || {};
30
+ const result = await this.db.find({ selector: query, limit });
31
+ return result.docs;
32
+ }
33
+ async findOne(params) {
34
+ const docs = await this.find({ ...params, limit: 1 });
35
+ return docs[0] || null;
36
+ }
37
+ async update(id, data) {
38
+ try {
39
+ const doc = await this.db.get(id);
40
+ const updated = { ...doc, ...data };
41
+ const result = await this.db.put(updated);
42
+ return { ...updated, _rev: result.rev };
43
+ }
44
+ catch (e) {
45
+ return null;
46
+ }
47
+ }
48
+ async deleteById(id) {
49
+ try {
50
+ const doc = await this.db.get(id);
51
+ await this.db.remove(doc);
52
+ return true;
53
+ }
54
+ catch (e) {
55
+ return false;
56
+ }
57
+ }
58
+ async transaction(fn) {
59
+ // PouchDB natively does not support transactions
60
+ return fn();
61
+ }
62
+ }
@@ -0,0 +1,17 @@
1
+ import type { IdaiDbAdapterInterface, IdaeDbParams } from '../@types/types';
2
+ import sqlite3 from 'sqlite3';
3
+ export declare class SQLiteAdapter<T extends object> implements IdaiDbAdapterInterface<T> {
4
+ private db;
5
+ private table;
6
+ private idField;
7
+ constructor(collection: string, connection: any);
8
+ static connect(uri: string, options?: any): Promise<sqlite3.Database>;
9
+ static getDb(connection: sqlite3.Database, dbName: string): Promise<sqlite3.Database>;
10
+ static close(connection: sqlite3.Database): Promise<void>;
11
+ create(data: Partial<T>): Promise<T>;
12
+ find(params?: IdaeDbParams<T>): Promise<T[]>;
13
+ findOne(params: IdaeDbParams<T>): Promise<T | null>;
14
+ update(id: string, data: Partial<T>): Promise<T | null>;
15
+ deleteById(id: string): Promise<boolean>;
16
+ transaction(fn: () => Promise<any>): Promise<any>;
17
+ }
@@ -0,0 +1,113 @@
1
+ import sqlite3 from 'sqlite3';
2
+ export class SQLiteAdapter {
3
+ db;
4
+ table;
5
+ idField;
6
+ constructor(collection, connection) {
7
+ // connection est un IdaeDbConnection, on récupère la vraie connexion
8
+ this.db = connection.getDb();
9
+ this.table = collection;
10
+ this.idField = 'id';
11
+ }
12
+ static async connect(uri, options) {
13
+ // uri: sqlite://./mydb.sqlite
14
+ const dbPath = uri.replace(/^sqlite:\/\//, '');
15
+ return new Promise((resolve, reject) => {
16
+ const db = new sqlite3.Database(dbPath, (err) => {
17
+ if (err)
18
+ reject(err);
19
+ else
20
+ resolve(db);
21
+ });
22
+ });
23
+ }
24
+ static async getDb(connection, dbName) {
25
+ // SQLite: pas de notion de dbName, retourne la connexion
26
+ return connection;
27
+ }
28
+ static async close(connection) {
29
+ return new Promise((resolve, reject) => {
30
+ connection.close((err) => (err ? reject(err) : resolve()));
31
+ });
32
+ }
33
+ async create(data) {
34
+ const keys = Object.keys(data);
35
+ const values = keys.map((k) => data[k]);
36
+ const placeholders = keys.map(() => '?').join(',');
37
+ const sql = `INSERT INTO ${this.table} (${keys.join(',')}) VALUES (${placeholders})`;
38
+ return new Promise((resolve, reject) => {
39
+ this.db.run(sql, values, function (err) {
40
+ if (err)
41
+ return reject(err);
42
+ resolve({ ...data, id: this.lastID });
43
+ });
44
+ });
45
+ }
46
+ async find(params) {
47
+ const { query = {}, limit, sortBy } = params || {};
48
+ let sql = `SELECT * FROM ${this.table}`;
49
+ const where = [];
50
+ const values = [];
51
+ for (const k in query) {
52
+ where.push(`${k} = ?`);
53
+ values.push(query[k]);
54
+ }
55
+ if (where.length)
56
+ sql += ' WHERE ' + where.join(' AND ');
57
+ if (sortBy)
58
+ sql += ` ORDER BY ${sortBy}`;
59
+ if (limit)
60
+ sql += ` LIMIT ${limit}`;
61
+ return new Promise((resolve, reject) => {
62
+ this.db.all(sql, values, (err, rows) => {
63
+ if (err)
64
+ return reject(err);
65
+ resolve(rows);
66
+ });
67
+ });
68
+ }
69
+ async findOne(params) {
70
+ const results = await this.find({ ...params, limit: 1 });
71
+ return results[0] || null;
72
+ }
73
+ async update(id, data) {
74
+ const keys = Object.keys(data);
75
+ const values = keys.map((k) => data[k]);
76
+ const sql = `UPDATE ${this.table} SET ${keys.map((k) => `${k} = ?`).join(',')} WHERE ${this.idField} = ?`;
77
+ return new Promise((resolve, reject) => {
78
+ this.db.run(sql, [...values, id], function (err) {
79
+ if (err)
80
+ return reject(err);
81
+ resolve({ ...data, id });
82
+ });
83
+ });
84
+ }
85
+ async deleteById(id) {
86
+ const sql = `DELETE FROM ${this.table} WHERE ${this.idField} = ?`;
87
+ return new Promise((resolve, reject) => {
88
+ this.db.run(sql, [id], function (err) {
89
+ if (err)
90
+ return reject(err);
91
+ resolve(this.changes > 0);
92
+ });
93
+ });
94
+ }
95
+ async transaction(fn) {
96
+ await new Promise((resolve, reject) => {
97
+ this.db.run('BEGIN TRANSACTION', (err) => (err ? reject(err) : resolve(null)));
98
+ });
99
+ try {
100
+ const result = await fn();
101
+ await new Promise((resolve, reject) => {
102
+ this.db.run('COMMIT', (err) => (err ? reject(err) : resolve(null)));
103
+ });
104
+ return result;
105
+ }
106
+ catch (e) {
107
+ await new Promise((resolve, reject) => {
108
+ this.db.run('ROLLBACK', (err) => (err ? reject(err) : resolve(null)));
109
+ });
110
+ throw e;
111
+ }
112
+ }
113
+ }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- export * from './idaeDb.js';
2
1
  export * from './IdaeEventEmitter.js';
2
+ export * from './IdaeDBModel.js';
3
3
  export * from './IdaeDbConnection.js';
4
4
  export * from './IdaeDbAdapter.js';
5
- export * from './IdaeDBModel.js';
5
+ export * from './idaeDb.js';
6
+ export * from './adapters/SQLiteAdapter.js';
7
+ export * from './adapters/PouchDBAdapter.js';
8
+ export * from './adapters/PostgreSQLAdapter.js';
6
9
  export * from './adapters/MySQLAdapter.js';
7
10
  export * from './adapters/MongoDBAdapter.js';
8
11
  export * from './adapters/ChromaDBAdapter.js';
package/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  // auto exports of entry components
2
- export * from './idaeDb.js';
3
2
  export * from './IdaeEventEmitter.js';
3
+ export * from './IdaeDBModel.js';
4
4
  export * from './IdaeDbConnection.js';
5
5
  export * from './IdaeDbAdapter.js';
6
- export * from './IdaeDBModel.js';
6
+ export * from './idaeDb.js';
7
+ export * from './adapters/SQLiteAdapter.js';
8
+ export * from './adapters/PouchDBAdapter.js';
9
+ export * from './adapters/PostgreSQLAdapter.js';
7
10
  export * from './adapters/MySQLAdapter.js';
8
11
  export * from './adapters/MongoDBAdapter.js';
9
12
  export * from './adapters/ChromaDBAdapter.js';
package/package.json CHANGED
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "name": "@medyll/idae-db",
3
- "version": "0.149.0",
3
+ "bin": {
4
+ "idae-db": "./cli.js"
5
+ },
6
+ "version": "0.155.2",
7
+ "author": "Lebrun Meddy",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/medyll/idae.git"
11
+ },
4
12
  "description": "@medyll/idae-db is a flexible and powerful library for interacting with various databases, with a particular focus on MongoDB support. It offers robust connection management, an intuitive API, and simplified CRUD operations.",
5
13
  "exports": {
6
14
  ".": {
@@ -15,38 +23,53 @@
15
23
  "!dist/**/*.spec.*"
16
24
  ],
17
25
  "peerDependencies": {
26
+ "pg": ">=8.0.0",
27
+ "pouchdb": ">=8.0.0",
28
+ "sqlite3": ">=5.1.0",
18
29
  "svelte": "^5.0.0-next"
19
30
  },
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "directory": "."
34
+ },
20
35
  "devDependencies": {
36
+ "@semantic-release/github": "^10.3.5",
21
37
  "@sveltejs/adapter-auto": "^6.0.0",
22
38
  "@sveltejs/kit": "^2.20.7",
23
39
  "@sveltejs/package": "^2.3.11",
24
40
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
25
41
  "@types/eslint": "^9.6.1",
42
+ "@types/pouchdb": "^6.4.2",
26
43
  "@vitest/coverage-v8": "^3.1.1",
27
44
  "eslint": "^9.25.0",
28
45
  "eslint-config-prettier": "^10.1.2",
29
46
  "eslint-plugin-svelte": "^3.5.1",
30
47
  "globals": "^16.0.0",
31
48
  "mongodb-memory-server": "^10.1.4",
49
+ "pg": "^8.17.2",
50
+ "pouchdb-adapter-memory": "^9.0.0",
51
+ "pouchdb-find": "^9.0.0",
32
52
  "prettier": "^3.5.3",
33
53
  "prettier-plugin-svelte": "^3.3.3",
34
54
  "publint": "^0.3.12",
55
+ "sqlite3": "^5.1.7",
35
56
  "svelte": "^5.28.1",
36
57
  "svelte-check": "^4.1.6",
37
58
  "typescript": "^5.8.3",
38
59
  "typescript-eslint": "^8.30.1",
39
60
  "vite": "^6.3.2",
40
61
  "vitest": "^3.1.1",
41
- "@medyll/idae-prettier-config": "1.2.1",
42
- "@medyll/idae-query": "0.180.0"
62
+ "@medyll/idae-query": "0.186.2",
63
+ "@medyll/idae-eslint-config": "0.1.5"
43
64
  },
44
65
  "svelte": "./dist/index.js",
45
66
  "types": "./dist/index.d.ts",
46
67
  "type": "module",
47
68
  "scope": "@medyll",
48
69
  "dependencies": {
49
- "chromadb": "^2.2.1"
70
+ "chromadb": "^2.2.1",
71
+ "mongodb": "^7.0.0",
72
+ "mysql2": "^3.16.0"
50
73
  },
51
74
  "scripts": {
52
75
  "dev": "vite dev",
@@ -61,6 +84,6 @@
61
84
  "test:watch": "vitest --watch",
62
85
  "lint": "prettier --check . && eslint .",
63
86
  "format": "prettier --write .",
64
- "package:pre": "node scripts/package-pre.js"
87
+ "prepackage": "node scripts/package-pre.js"
65
88
  }
66
89
  }