@morojs/moro 1.5.3 → 1.5.5
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/dist/core/auth/morojs-adapter.js +23 -12
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/http/http-server.js +12 -8
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/logger/filters.js +12 -4
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/logger.d.ts +45 -0
- package/dist/core/logger/logger.js +579 -60
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger.js +4 -2
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +1 -0
- package/dist/core/modules/auto-discovery.js +9 -5
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/modules.d.ts +1 -0
- package/dist/core/modules/modules.js +8 -2
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +1 -0
- package/dist/core/networking/adapters/ws-adapter.js +3 -1
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/service-discovery.d.ts +1 -0
- package/dist/core/networking/service-discovery.js +23 -11
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/moro.d.ts +35 -0
- package/dist/moro.js +156 -25
- package/dist/moro.js.map +1 -1
- package/dist/types/logger.d.ts +3 -0
- package/package.json +1 -1
- package/src/core/auth/morojs-adapter.ts +25 -12
- package/src/core/database/README.md +26 -16
- package/src/core/http/http-server.ts +15 -12
- package/src/core/logger/filters.ts +12 -4
- package/src/core/logger/logger.ts +649 -62
- package/src/core/middleware/built-in/request-logger.ts +6 -2
- package/src/core/modules/auto-discovery.ts +13 -5
- package/src/core/modules/modules.ts +9 -5
- package/src/core/networking/adapters/ws-adapter.ts +3 -1
- package/src/core/networking/service-discovery.ts +23 -9
- package/src/moro.ts +200 -28
- package/src/types/logger.ts +3 -0
|
@@ -7,16 +7,19 @@ The MoroJS database module provides a pluggable adapter system for different dat
|
|
|
7
7
|
### SQL Databases
|
|
8
8
|
|
|
9
9
|
#### MySQL Adapter
|
|
10
|
+
|
|
10
11
|
- **Package Required**: `mysql2`
|
|
11
12
|
- **Usage**: Production-ready with connection pooling
|
|
12
13
|
- **Type**: `mysql`
|
|
13
14
|
|
|
14
|
-
#### PostgreSQL Adapter
|
|
15
|
+
#### PostgreSQL Adapter
|
|
16
|
+
|
|
15
17
|
- **Package Required**: `pg` and `@types/pg`
|
|
16
18
|
- **Usage**: Full PostgreSQL feature support
|
|
17
19
|
- **Type**: `postgresql`, `postgres`, or `pg`
|
|
18
20
|
|
|
19
21
|
#### SQLite Adapter
|
|
22
|
+
|
|
20
23
|
- **Package Required**: `better-sqlite3`
|
|
21
24
|
- **Usage**: Lightweight, file-based database
|
|
22
25
|
- **Type**: `sqlite` or `sqlite3`
|
|
@@ -24,11 +27,13 @@ The MoroJS database module provides a pluggable adapter system for different dat
|
|
|
24
27
|
### NoSQL Databases
|
|
25
28
|
|
|
26
29
|
#### MongoDB Adapter
|
|
30
|
+
|
|
27
31
|
- **Package Required**: `mongodb`
|
|
28
32
|
- **Usage**: Document database with aggregation support
|
|
29
33
|
- **Type**: `mongodb` or `mongo`
|
|
30
34
|
|
|
31
35
|
#### Redis Adapter
|
|
36
|
+
|
|
32
37
|
- **Package Required**: `ioredis`
|
|
33
38
|
- **Usage**: In-memory key-value store with pub/sub
|
|
34
39
|
- **Type**: `redis`
|
|
@@ -36,6 +41,7 @@ The MoroJS database module provides a pluggable adapter system for different dat
|
|
|
36
41
|
### ORM
|
|
37
42
|
|
|
38
43
|
#### Drizzle Adapter
|
|
44
|
+
|
|
39
45
|
- **Package Required**: `drizzle-orm` + database driver
|
|
40
46
|
- **Usage**: Type-safe ORM with schema validation
|
|
41
47
|
- **Type**: `drizzle` or `orm`
|
|
@@ -43,7 +49,7 @@ The MoroJS database module provides a pluggable adapter system for different dat
|
|
|
43
49
|
## Factory Pattern (Recommended)
|
|
44
50
|
|
|
45
51
|
```typescript
|
|
46
|
-
import { createDatabaseAdapter } from 'moro';
|
|
52
|
+
import { createDatabaseAdapter } from '@morojs/moro';
|
|
47
53
|
|
|
48
54
|
// SQL Databases
|
|
49
55
|
const mysql = createDatabaseAdapter('mysql', {
|
|
@@ -52,7 +58,7 @@ const mysql = createDatabaseAdapter('mysql', {
|
|
|
52
58
|
user: 'root',
|
|
53
59
|
password: 'password',
|
|
54
60
|
database: 'my_app',
|
|
55
|
-
connectionLimit: 10
|
|
61
|
+
connectionLimit: 10,
|
|
56
62
|
});
|
|
57
63
|
|
|
58
64
|
const postgres = createDatabaseAdapter('postgresql', {
|
|
@@ -62,12 +68,12 @@ const postgres = createDatabaseAdapter('postgresql', {
|
|
|
62
68
|
password: 'password',
|
|
63
69
|
database: 'my_app',
|
|
64
70
|
connectionLimit: 10,
|
|
65
|
-
ssl: false
|
|
71
|
+
ssl: false,
|
|
66
72
|
});
|
|
67
73
|
|
|
68
74
|
const sqlite = createDatabaseAdapter('sqlite', {
|
|
69
75
|
filename: 'app.db',
|
|
70
|
-
memory: false
|
|
76
|
+
memory: false,
|
|
71
77
|
});
|
|
72
78
|
|
|
73
79
|
// NoSQL Databases
|
|
@@ -76,34 +82,34 @@ const mongodb = createDatabaseAdapter('mongodb', {
|
|
|
76
82
|
port: 27017,
|
|
77
83
|
database: 'my_app',
|
|
78
84
|
username: 'user',
|
|
79
|
-
password: 'password'
|
|
85
|
+
password: 'password',
|
|
80
86
|
});
|
|
81
87
|
|
|
82
88
|
const redis = createDatabaseAdapter('redis', {
|
|
83
89
|
host: 'localhost',
|
|
84
90
|
port: 6379,
|
|
85
91
|
password: 'password',
|
|
86
|
-
keyPrefix: 'myapp:'
|
|
92
|
+
keyPrefix: 'myapp:',
|
|
87
93
|
});
|
|
88
94
|
|
|
89
95
|
// ORM
|
|
90
96
|
const drizzle = createDatabaseAdapter('drizzle', {
|
|
91
97
|
database: drizzleInstance,
|
|
92
|
-
schema: schemaObject
|
|
98
|
+
schema: schemaObject,
|
|
93
99
|
});
|
|
94
100
|
```
|
|
95
101
|
|
|
96
102
|
## Direct Instantiation
|
|
97
103
|
|
|
98
104
|
```typescript
|
|
99
|
-
import {
|
|
100
|
-
MySQLAdapter,
|
|
101
|
-
PostgreSQLAdapter,
|
|
105
|
+
import {
|
|
106
|
+
MySQLAdapter,
|
|
107
|
+
PostgreSQLAdapter,
|
|
102
108
|
SQLiteAdapter,
|
|
103
109
|
MongoDBAdapter,
|
|
104
110
|
RedisAdapter,
|
|
105
111
|
DrizzleAdapter
|
|
106
|
-
} from 'moro';
|
|
112
|
+
} from '@morojs/moro';
|
|
107
113
|
|
|
108
114
|
// SQL
|
|
109
115
|
const mysql = new MySQLAdapter({ host: 'localhost', ... });
|
|
@@ -151,7 +157,7 @@ const updated = await db.update('users', { name: 'Jane' }, { id: 1 });
|
|
|
151
157
|
const deleted = await db.delete('users', { id: 1 });
|
|
152
158
|
|
|
153
159
|
// Transactions
|
|
154
|
-
const result = await db.transaction(async
|
|
160
|
+
const result = await db.transaction(async tx => {
|
|
155
161
|
const user = await tx.insert('users', userData);
|
|
156
162
|
await tx.insert('profiles', { user_id: user.id, ...profileData });
|
|
157
163
|
return user;
|
|
@@ -161,6 +167,7 @@ const result = await db.transaction(async (tx) => {
|
|
|
161
167
|
## Usage Examples
|
|
162
168
|
|
|
163
169
|
### SQL Operations
|
|
170
|
+
|
|
164
171
|
```typescript
|
|
165
172
|
// Standard CRUD operations work across all SQL adapters
|
|
166
173
|
const users = await db.query('SELECT * FROM users WHERE age > ?', [18]);
|
|
@@ -171,6 +178,7 @@ const deleted = await db.delete('users', { id: 1 });
|
|
|
171
178
|
```
|
|
172
179
|
|
|
173
180
|
### MongoDB Operations
|
|
181
|
+
|
|
174
182
|
```typescript
|
|
175
183
|
// MongoDB uses collections instead of tables
|
|
176
184
|
const users = await mongoDb.query('users'); // Get all
|
|
@@ -179,12 +187,13 @@ const user = await mongoDb.queryOne('users', { email: 'john@example.com' });
|
|
|
179
187
|
|
|
180
188
|
// MongoDB-specific methods
|
|
181
189
|
const stats = await mongoDb.aggregate('users', [
|
|
182
|
-
{ $group: { _id: null, avgAge: { $avg: '$age' } } }
|
|
190
|
+
{ $group: { _id: null, avgAge: { $avg: '$age' } } },
|
|
183
191
|
]);
|
|
184
192
|
await mongoDb.createIndex('users', { email: 1 }, { unique: true });
|
|
185
193
|
```
|
|
186
194
|
|
|
187
195
|
### Redis Operations
|
|
196
|
+
|
|
188
197
|
```typescript
|
|
189
198
|
// Key-value operations
|
|
190
199
|
await redisDb.set('user:123', userData, 3600); // with TTL
|
|
@@ -197,6 +206,7 @@ await redisDb.publish('notifications', message);
|
|
|
197
206
|
```
|
|
198
207
|
|
|
199
208
|
### Drizzle ORM Operations
|
|
209
|
+
|
|
200
210
|
```typescript
|
|
201
211
|
// Type-safe queries (requires schema setup)
|
|
202
212
|
const users = await drizzleDb.select('users').where(eq(schema.users.age, 25));
|
|
@@ -213,7 +223,7 @@ Choose and install the appropriate database package:
|
|
|
213
223
|
```bash
|
|
214
224
|
# SQL Databases
|
|
215
225
|
npm install mysql2 # MySQL
|
|
216
|
-
npm install pg @types/pg # PostgreSQL
|
|
226
|
+
npm install pg @types/pg # PostgreSQL
|
|
217
227
|
npm install better-sqlite3 # SQLite
|
|
218
228
|
|
|
219
229
|
# NoSQL Databases
|
|
@@ -225,4 +235,4 @@ npm install drizzle-orm # Drizzle ORM
|
|
|
225
235
|
# Plus the appropriate driver (mysql2, pg, better-sqlite3, etc.)
|
|
226
236
|
```
|
|
227
237
|
|
|
228
|
-
The adapters will gracefully handle missing packages with helpful error messages.
|
|
238
|
+
The adapters will gracefully handle missing packages with helpful error messages.
|
|
@@ -281,12 +281,13 @@ export class MoroHttpServer {
|
|
|
281
281
|
await route.handler(httpReq, httpRes);
|
|
282
282
|
} catch (error) {
|
|
283
283
|
// Debug: Log the actual error and where it came from
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
284
|
+
this.logger.debug('Request error details', 'RequestHandler', {
|
|
285
|
+
errorType: typeof error,
|
|
286
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
287
|
+
errorStack: error instanceof Error ? error.stack : 'No stack trace',
|
|
288
|
+
requestPath: req.url,
|
|
289
|
+
requestMethod: req.method,
|
|
290
|
+
});
|
|
290
291
|
|
|
291
292
|
this.logger.error('Request error', 'RequestHandler', {
|
|
292
293
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -310,11 +311,10 @@ export class MoroHttpServer {
|
|
|
310
311
|
httpRes.setHeader('Content-Type', 'application/json');
|
|
311
312
|
} else {
|
|
312
313
|
// Even setHeader doesn't exist - object is completely wrong
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
);
|
|
314
|
+
this.logger.error('Response object is not a proper ServerResponse', 'RequestHandler', {
|
|
315
|
+
responseType: typeof httpRes,
|
|
316
|
+
responseKeys: Object.keys(httpRes),
|
|
317
|
+
});
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
if (typeof httpRes.end === 'function') {
|
|
@@ -326,7 +326,10 @@ export class MoroHttpServer {
|
|
|
326
326
|
})
|
|
327
327
|
);
|
|
328
328
|
} else {
|
|
329
|
-
|
|
329
|
+
this.logger.error(
|
|
330
|
+
'Cannot send error response - end() method missing',
|
|
331
|
+
'RequestHandler'
|
|
332
|
+
);
|
|
330
333
|
}
|
|
331
334
|
}
|
|
332
335
|
}
|
|
@@ -22,16 +22,24 @@ export const contextFilter = (allowedContexts: string[]): LogFilter => ({
|
|
|
22
22
|
// Rate limiting filter
|
|
23
23
|
export const rateLimitFilter = (maxPerSecond: number): LogFilter => {
|
|
24
24
|
const timestamps: number[] = [];
|
|
25
|
+
let lastCleanup = 0;
|
|
25
26
|
|
|
26
27
|
return {
|
|
27
28
|
name: 'rate-limit',
|
|
28
29
|
filter: (entry: LogEntry) => {
|
|
29
30
|
const now = Date.now();
|
|
30
|
-
const oneSecondAgo = now - 1000;
|
|
31
31
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
// Batch cleanup for better performance and thread safety
|
|
33
|
+
if (now - lastCleanup > 1000) {
|
|
34
|
+
const cutoff = now - 1000;
|
|
35
|
+
let keepIndex = 0;
|
|
36
|
+
for (let i = 0; i < timestamps.length; i++) {
|
|
37
|
+
if (timestamps[i] >= cutoff) {
|
|
38
|
+
timestamps[keepIndex++] = timestamps[i];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
timestamps.length = keepIndex;
|
|
42
|
+
lastCleanup = now;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
// Check rate limit
|