@neupgroup/mapper 1.2.0 → 1.2.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/README.md CHANGED
@@ -1,37 +1,706 @@
1
- # @neupgroup/mapper
2
-
3
- Core library for Neup.Mapper. Provides simple schema registration utilities that can be expanded over time.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install @neupgroup/mapper
9
- ```
10
-
11
- ## Usage
12
-
13
- ```ts
14
- import Mapper from '@neupgroup/mapper';
15
-
16
- const mapper = new Mapper();
17
-
18
- mapper.register({
19
- name: 'User',
20
- fields: [
21
- { name: 'id', type: 'string' },
22
- { name: 'email', type: 'string' },
23
- { name: 'createdAt', type: 'date' },
24
- ],
25
- });
26
-
27
- console.log(mapper.list());
28
- ```
29
-
30
- ## Build
31
-
32
- ```bash
33
- npx tsc -p ./tsconfig.json
34
- ```
35
-
36
- Outputs are generated to `dist/` with type declarations.
1
+ # @neupgroup/mapper
2
+
3
+ Schema and mapping utilities with lightweight ORM helpers. Define schemas, attach adapters per connection, and perform CRUD with a simple, fluent API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @neupgroup/mapper
9
+ ```
10
+
11
+ ## 🚀 Quick Start Options
12
+
13
+ ### **Option 1: One-Import Quick Start**
14
+ **The simplest way to get started - just import and use:**
15
+
16
+ ```ts
17
+ import Mapper from '@neupgroup/mapper'
18
+
19
+ // 1. Define a schema (Mapper auto-configures with sensible defaults)
20
+ Mapper.schema('users')
21
+ .use({ connection: 'default', collection: 'users' })
22
+ .setStructure([
23
+ { name: 'id', type: 'int', autoIncrement: true },
24
+ { name: 'name', type: 'string' },
25
+ { name: 'email', type: 'string' }
26
+ ])
27
+
28
+ // 2. Use immediately - no setup required!
29
+ await Mapper.add('users', { name: 'Alice', email: 'alice@example.com' })
30
+ const users = await Mapper.get('users')
31
+ const user = await Mapper.getOne('users', { email: 'alice@example.com' })
32
+ await Mapper.update('users', { email: 'alice@example.com' }, { name: 'Alice Cooper' })
33
+ await Mapper.delete('users', { email: 'alice@example.com' })
34
+ ```
35
+
36
+ ### **Option 2: Configuration-Based Approach**
37
+ **Use configuration files to manage connections and schemas:**
38
+
39
+ ```ts
40
+ import { createConfigMapper } from '@neupgroup/mapper'
41
+
42
+ // Define your configuration
43
+ const config = {
44
+ connections: [
45
+ ['mydb', 'sql', 'user', 'myapp', 'localhost', 5432],
46
+ ['myapi', 'api', 'https://api.example.com']
47
+ ],
48
+ schemas: {
49
+ users: {
50
+ connection: 'mydb',
51
+ collection: 'users',
52
+ structure: [
53
+ { name: 'id', type: 'int', autoIncrement: true },
54
+ { name: 'name', type: 'string' },
55
+ { name: 'email', type: 'string' }
56
+ ]
57
+ }
58
+ }
59
+ }
60
+
61
+ // Create mapper from config
62
+ const mapper = createConfigMapper(config)
63
+
64
+ // Use the mapper
65
+ await mapper.useConnection('mydb').table('users').add({ name: 'Alice', email: 'alice@example.com' })
66
+ const users = await mapper.useConnection('mydb').table('users').select().execute()
67
+ ```
68
+
69
+ ### **Option 3: PHP-Style Fluent API**
70
+ **Use static method chaining for dynamic connections:**
71
+
72
+ ```ts
73
+ import { StaticMapper as Mapper } from '@neupgroup/mapper'
74
+
75
+ // Create persistent connections
76
+ Mapper.makeConnection('mydb', 'mysql', {
77
+ host: 'localhost',
78
+ user: 'root',
79
+ password: 'password',
80
+ database: 'myapp'
81
+ })
82
+
83
+ // Use connections with method chaining
84
+ const users = await Mapper.useConnection('mydb')
85
+ .table('users')
86
+ .select()
87
+ .where('active', true)
88
+ .execute()
89
+
90
+ // Create temporary connections on-the-fly
91
+ const tempData = await Mapper.makeTempConnection('mongodb', {
92
+ url: 'mongodb://localhost:27017',
93
+ database: 'temp'
94
+ })
95
+ .collection('cache')
96
+ .find({ expired: false })
97
+ .execute()
98
+ ```
99
+
100
+ ### **Auto-Configuration Magic** ✨
101
+
102
+ The Mapper automatically configures itself based on your environment:
103
+
104
+ - **Environment Variables**: `DATABASE_URL=mysql://user:pass@host:port/db`
105
+ - **Browser Global**: `window.__MAPPER_CONFIG__`
106
+ - **Default Fallback**: In-memory API connection for instant prototyping
107
+
108
+ **Connection type auto-detection:**
109
+ ```
110
+ mysql://... → MySQL
111
+ postgres://... → PostgreSQL
112
+ mongodb://... → MongoDB
113
+ firestore://... → Firestore
114
+ ```
115
+
116
+ ### **Manual Configuration (Optional)**
117
+
118
+ ```ts
119
+ // Connect to your database
120
+ Mapper.connect('mydb', 'mysql', {
121
+ host: 'localhost',
122
+ port: 3306,
123
+ user: 'root',
124
+ password: 'password',
125
+ database: 'myapp'
126
+ })
127
+
128
+ // Or use environment variables
129
+ // DATABASE_URL=mysql://root:password@localhost:3306/myapp
130
+ ```
131
+
132
+ ## 🛠️ Complete Usage Examples
133
+
134
+ ### **Example 1: Zero-Configuration Setup**
135
+ ```ts
136
+ import Mapper from '@neupgroup/mapper'
137
+
138
+ // Works immediately with in-memory storage
139
+ const users = await Mapper.get('users') // Returns empty array
140
+ ```
141
+
142
+ ### **Example 2: Environment-Based Configuration**
143
+ ```bash
144
+ # Set environment variable
145
+ export DATABASE_URL=mysql://user:password@localhost:3306/myapp
146
+
147
+ # Or in browser
148
+ window.__MAPPER_CONFIG__ = {
149
+ connection: {
150
+ name: 'mydb',
151
+ type: 'mysql',
152
+ key: { host: 'localhost', user: 'root', password: 'pass', database: 'myapp' }
153
+ }
154
+ }
155
+ ```
156
+
157
+ ```ts
158
+ import Mapper from '@neupgroup/mapper'
159
+
160
+ // Automatically configured from environment
161
+ const users = await Mapper.get('users')
162
+ ```
163
+
164
+ ### **Example 3: Schema with Multiple Field Types**
165
+ ```ts
166
+ import Mapper from '@neupgroup/mapper'
167
+
168
+ Mapper.schema('products')
169
+ .use({ connection: 'default', collection: 'products' })
170
+ .setStructure([
171
+ { name: 'id', type: 'int', autoIncrement: true },
172
+ { name: 'name', type: 'string' },
173
+ { name: 'price', type: 'number' },
174
+ { name: 'inStock', type: 'boolean' },
175
+ { name: 'createdAt', type: 'date' },
176
+ { name: 'categoryId', type: 'int' }
177
+ ])
178
+
179
+ // Add product
180
+ await Mapper.add('products', {
181
+ name: 'Laptop',
182
+ price: 999.99,
183
+ inStock: true,
184
+ createdAt: new Date(),
185
+ categoryId: 1
186
+ })
187
+
188
+ // Get products with filters
189
+ const expensiveProducts = await Mapper.get('products', { price: 500 }, '>')
190
+ const inStockProducts = await Mapper.get('products', { inStock: true })
191
+ ```
192
+
193
+ ### **Example 4: Advanced Query Operations**
194
+ ```ts
195
+ import Mapper from '@neupgroup/mapper'
196
+
197
+ // Complex queries using the underlying API
198
+ const query = Mapper.use('users')
199
+ .where('age', 18, '>=')
200
+ .where('status', 'active')
201
+
202
+ const activeAdults = await query.get()
203
+ const firstActiveAdult = await query.getOne()
204
+
205
+ // Update multiple records
206
+ await query.to({ lastLogin: new Date() }).update()
207
+
208
+ // Delete with complex conditions
209
+ await Mapper.use('users')
210
+ .where('lastLogin', new Date('2023-01-01'), '<')
211
+ .delete()
212
+ ```
213
+
214
+ ### **Example 5: Multiple Databases**
215
+ ```ts
216
+ import Mapper from '@neupgroup/mapper'
217
+
218
+ // Connect to multiple databases
219
+ Mapper.connect('mysql_db', 'mysql', {
220
+ host: 'localhost',
221
+ user: 'root',
222
+ password: 'password',
223
+ database: 'main_app'
224
+ })
225
+
226
+ Mapper.connect('mongo_cache', 'mongodb', {
227
+ uri: 'mongodb://localhost:27017',
228
+ database: 'cache'
229
+ })
230
+
231
+ // Use different connections for different schemas
232
+ Mapper.schema('users')
233
+ .use({ connection: 'mysql_db', collection: 'users' })
234
+ .setStructure([...])
235
+
236
+ Mapper.schema('sessions')
237
+ .use({ connection: 'mongo_cache', collection: 'sessions' })
238
+ .setStructure([...])
239
+
240
+ // Query from different databases
241
+ const users = await Mapper.get('users') // From MySQL
242
+ const sessions = await Mapper.get('sessions') // From MongoDB
243
+ ```
244
+
245
+ ## 🌍 Environment Configuration Guide
246
+
247
+ ### **Node.js Environment Variables**
248
+
249
+ The Mapper automatically detects these environment variables:
250
+
251
+ ```bash
252
+ # Basic database URL (auto-detects type)
253
+ DATABASE_URL=mysql://user:password@localhost:3306/myapp
254
+
255
+ # Or specific connection types
256
+ MYSQL_URL=mysql://user:password@localhost:3306/myapp
257
+ POSTGRES_URL=postgres://user:password@localhost:5432/myapp
258
+ MONGODB_URL=mongodb://localhost:27017/myapp
259
+ FIRESTORE_URL=firestore://project-id
260
+ ```
261
+
262
+ ### **Browser Environment**
263
+
264
+ For client-side applications, use the global configuration:
265
+
266
+ ```html
267
+ <script>
268
+ window.__MAPPER_CONFIG__ = {
269
+ connection: {
270
+ name: 'api',
271
+ type: 'api',
272
+ key: {
273
+ endpoint: 'https://api.example.com',
274
+ apiKey: 'your-api-key'
275
+ }
276
+ },
277
+ schemas: [
278
+ {
279
+ name: 'users',
280
+ connection: 'api',
281
+ collection: 'users',
282
+ structure: [
283
+ { name: 'id', type: 'int' },
284
+ { name: 'name', type: 'string' }
285
+ ]
286
+ }
287
+ ]
288
+ }
289
+ </script>
290
+ ```
291
+
292
+ ### **Configuration Priority Order**
293
+
294
+ 1. **Manual Configuration**: `Mapper.connect()` calls
295
+ 2. **Environment Variables**: `DATABASE_URL` and others
296
+ 3. **Browser Global**: `window.__MAPPER_CONFIG__`
297
+ 4. **Default Fallback**: In-memory API connection
298
+
299
+ ### **Docker & Production Setup**
300
+
301
+ ```dockerfile
302
+ # Dockerfile
303
+ ENV DATABASE_URL=mysql://user:password@db:3306/myapp
304
+ ```
305
+
306
+ ```yaml
307
+ # docker-compose.yml
308
+ services:
309
+ app:
310
+ environment:
311
+ - DATABASE_URL=mysql://user:password@db:3306/myapp
312
+ ```
313
+
314
+ ### **Configuration Validation**
315
+
316
+ ```ts
317
+ import Mapper from '@neupgroup/mapper'
318
+
319
+ // Check current configuration
320
+ console.log('Connections:', Mapper.getConnections().list())
321
+ console.log('Schemas:', Mapper.getSchemaManager().list())
322
+
323
+ // Verify auto-configuration worked
324
+ const config = Mapper.getConnections().get('default')
325
+ if (!config) {
326
+ console.log('No auto-configuration detected, using manual setup...')
327
+ Mapper.connect('manual', 'mysql', { /* config */ })
328
+ }
329
+ ```
330
+
331
+ ## Advanced Usage (Original API)
332
+
333
+ For more control, you can still use the original granular API:
334
+
335
+ ```ts
336
+ import { connection, schema } from '@neupgroup/mapper'
337
+ import type { DbAdapter, QueryOptions } from '@neupgroup/mapper'
338
+
339
+ // 1) Define connections
340
+ const conRegistry = connection()
341
+ conRegistry.create('mysql_prod', 'mysql').key({
342
+ host: '127.0.0.1',
343
+ port: 3306,
344
+ user: 'root',
345
+ password: 's3cr3t',
346
+ database: 'appdb',
347
+ })
348
+
349
+ // 2) Attach an adapter for the connection
350
+ const adapter: DbAdapter = {
351
+ async getDocuments(options: QueryOptions) { return [] },
352
+ async addDocument(collectionName: string, data: Record<string, any>) { return 'new-id' },
353
+ async updateDocument(collectionName: string, docId: string, data: Record<string, any>) { },
354
+ async deleteDocument(collectionName: string, docId: string) { },
355
+ }
356
+ conRegistry.attachAdapter('mysql_prod', adapter)
357
+
358
+ // 3) Register schema and run CRUD
359
+ const sm = schema(conRegistry)
360
+ sm.create('User')
361
+ .use({ connection: 'mysql_prod', collection: 'users' })
362
+ .setStructure({
363
+ id: 'string',
364
+ email: 'string',
365
+ name: 'string editable',
366
+ createdAt: 'date',
367
+ '?field': 'allow-undefined',
368
+ })
369
+
370
+ const User = sm.use('User')
371
+ await User.add({ id: 'u_1', email: 'alice@example.com', name: 'Alice', createdAt: new Date() })
372
+ await User.where(['id', 'u_1']).to({ name: 'Alice Cooper' }).updateOne()
373
+ const one = await User.where(['id', 'u_1']).getOne()
374
+ await User.where(['id', 'u_1']).deleteOne()
375
+
376
+ ## Connections DSL
377
+
378
+ You can define connections in a simple DSL and load them at runtime.
379
+
380
+ `connections.dsl` example:
381
+
382
+ ```
383
+ connections = [
384
+ mysql_prod = [
385
+ type: mysql,
386
+ host: 127.0.0.1,
387
+ port: 3306,
388
+ user: root,
389
+ password: "s3cr3t",
390
+ database: appdb,
391
+ ],
392
+
393
+ mongo_dev = [
394
+ type: mongodb,
395
+ uri: "mongodb://127.0.0.1:27017",
396
+ database: devdb,
397
+ ],
398
+ ]
399
+ ```
400
+
401
+ Load and normalize:
402
+
403
+ ```ts
404
+ import { parseConnectionsDsl, toNormalizedConnections, connection, schema } from '@neupgroup/mapper'
405
+
406
+ const text = await fs.promises.readFile('connections.dsl', 'utf8')
407
+ const envMap = parseConnectionsDsl(text)
408
+ const conns = toNormalizedConnections(envMap)
409
+
410
+ const conRegistry = connection()
411
+ for (const c of conns) {
412
+ conRegistry.register({ name: c.name, type: c.type, key: c.key })
413
+ }
414
+ const sm = schema(conRegistry)
415
+ ```
416
+
417
+ Notes:
418
+ - `type` (or `dbType`) defaults to `api` if omitted.
419
+ - Values can be quoted or unquoted; `#` comments are ignored.
420
+
421
+ ## Adapters
422
+
423
+ Adapters implement backend-specific operations. Shape:
424
+
425
+ ```ts
426
+ export interface DbAdapter {
427
+ get?(options: QueryOptions): Promise<any[]>
428
+ getOne?(options: QueryOptions): Promise<any | null>
429
+ getDocuments(options: QueryOptions): Promise<any[]>
430
+ addDocument(collectionName: string, data: Record<string, any>): Promise<string>
431
+ updateDocument(collectionName: string, docId: string, data: Record<string, any>): Promise<void>
432
+ deleteDocument(collectionName: string, docId: string): Promise<void>
433
+ }
434
+ ```
435
+
436
+ Attach to a connection with `conRegistry.attachAdapter('<name>', adapter)` before querying.
437
+
438
+ ## Schemas & Structure
439
+
440
+ Define schemas with a descriptor object or explicit fields array:
441
+
442
+ ```ts
443
+ sm.create('Product')
444
+ .use({ connection: 'mysql_prod', collection: 'products' })
445
+ .setStructure({
446
+ id: 'string',
447
+ title: 'string editable',
448
+ price: 'number',
449
+ createdAt: 'date',
450
+ '?field': 'allow-undefined',
451
+ })
452
+ ```
453
+
454
+ Field tokens:
455
+ - `type`: one of `string`, `number`, `boolean`, `date`, `int`.
456
+ - `editable`: marks commonly modified fields.
457
+ - `'?field'`: enables accepting fields not listed in the schema.
458
+
459
+ ## Query & CRUD
460
+
461
+ Build queries and run operations:
462
+
463
+ ```ts
464
+ const Q = sm.use('Product')
465
+ await Q.add({ id: 'p_1', title: 'Widget', price: 9.99 })
466
+ const items = await Q.where('price', 10, '<').get()
467
+ const one = await Q.where(['id', 'p_1']).getOne()
468
+ await Q.where(['id', 'p_1']).to({ price: 7.99 }).updateOne()
469
+ await Q.where(['id', 'p_1']).deleteOne()
470
+ ```
471
+
472
+ Methods:
473
+ - `where(field, value, operator?)`, `where([field, value])` and `whereComplex(raw)`.
474
+ - `get`, `getOne`, `add`, `delete`, `deleteOne`, `to(update).update`, `updateOne`.
475
+
476
+ ## Documentation Helpers
477
+
478
+ For apps that want to render built-in documentation:
479
+
480
+ ```ts
481
+ import { documentationMd, markdownToHtml, getDocumentationHtml } from '@neupgroup/mapper'
482
+
483
+ const html = getDocumentationHtml()
484
+ ```
485
+
486
+ ## API Reference
487
+
488
+ ### **Core Functions**
489
+ - `connection()` → create connections registry (see `src/index.ts:299`–`301`)
490
+ - `schema(conns?)` → create `SchemaManager` (see `src/index.ts:303`–`306`)
491
+ - `schemas` → singleton `SchemaManager` (see `src/index.ts:308`–`311`)
492
+ - `createOrm(adapter)` → wrapper around a `DbAdapter` (see `src/orm/index.ts:3`–`27`)
493
+ - `parseConnectionsDsl(text)`, `toNormalizedConnections(map)` (see `src/env.ts:31`–`75`, `87`–`95`)
494
+ - `documentationMd`, `markdownToHtml`, `getDocumentationHtml` (see `src/docs.ts:5`–`275`, `277`–`356`)
495
+
496
+ ### **Configuration-Based API**
497
+ - `createConfigMapper(config)` → Create mapper from configuration object
498
+ - `createDefaultMapper()` → Create mapper with default configuration
499
+ - `ConfigBasedMapper` → Class for configuration-based mapping
500
+ - `configure(config)` → Configure the mapper
501
+ - `makeConnection(name, type, config)` → Add connection
502
+ - `useConnection(name)` → Use specific connection
503
+ - `getConnection(name)` → Get connection details
504
+
505
+ ### **Fluent API (StaticMapper)**
506
+ - `StaticMapper.makeConnection(name, type, config)` → Create persistent connection
507
+ - `StaticMapper.useConnection(name)` → Use existing connection
508
+ - `StaticMapper.makeTempConnection(type, config)` → Create temporary connection
509
+ - `StaticMapper.getConnection(name)` → Get connection by name
510
+ - `StaticMapper.listConnections()` → List all connections
511
+
512
+ ### **Query Builder Methods**
513
+ - `table(name)` / `collection(name)` → Specify table/collection
514
+ - `select()` / `find()` → Start select query
515
+ - `where(field, value, operator?)` → Add where condition
516
+ - `orderBy(field, direction?)` → Add ordering
517
+ - `limit(count)` → Limit results
518
+ - `execute()` → Execute query
519
+ - `add(data)` → Insert data
520
+ - `update(data)` → Update data
521
+ - `delete()` → Delete data
522
+
523
+ ### **Types**
524
+ - `DbAdapter`, `QueryOptions`, `EnvDslConnections`, `NormalizedConnection`
525
+ - `ConnectionConfig`, `MapperConfig`, `FluentConnectionBuilder`
526
+ - `ConnectionType`: `'sql' | 'mysql' | 'postgres' | 'mongodb' | 'firestore' | 'api'`
527
+
528
+ ## Build & Local Development
529
+
530
+ ```bash
531
+ npm run build
532
+ ```
533
+
534
+ Outputs are generated to `dist/` with type declarations.
535
+
536
+ ## Error Handling & Troubleshooting
537
+
538
+ - Wrap operations in `try/catch` and handle nulls from `getOne()`.
539
+ - Verify credentials and network connectivity for your backend.
540
+ - Ensure schema field names and types match your storage engine.
541
+
542
+ ---
543
+
544
+ Copyright © Neup Group
545
+
546
+ ## 🎯 Quick Reference
547
+
548
+ ### **One-Import Benefits**
549
+
550
+ ✅ **Zero Configuration**: Works out of the box
551
+ ✅ **Auto-Detection**: Automatically configures from environment
552
+ ✅ **Universal**: Works in Node.js and browsers
553
+ ✅ **Type Safe**: Full TypeScript support
554
+ ✅ **Progressive**: Start simple, scale to complex
555
+ ✅ **Lightweight**: Minimal overhead, maximum performance
556
+
557
+ ### **Migration from Original API**
558
+
559
+ The new `Mapper` default export is fully compatible with the original API:
560
+
561
+ ```ts
562
+ // Old way (still works)
563
+ import { connection, schema } from '@neupgroup/mapper'
564
+ const conns = connection()
565
+ const sm = schema(conns)
566
+
567
+ // New way (recommended)
568
+ import Mapper from '@neupgroup/mapper'
569
+ // Mapper is pre-configured and ready to use
570
+
571
+ // Access underlying managers if needed
572
+ const conns = Mapper.getConnections()
573
+ const sm = Mapper.getSchemaManager()
574
+ ```
575
+
576
+ ### **Best Practices**
577
+
578
+ 1. **Start with defaults**: Let Mapper auto-configure itself
579
+ 2. **Use environment variables**: Set `DATABASE_URL` for production
580
+ 3. **Define schemas early**: Create schemas at app startup
581
+ 4. **Use TypeScript**: Get full type safety and IntelliSense
582
+ 5. **Handle errors**: Wrap operations in try/catch blocks
583
+
584
+ ### **Common Patterns**
585
+
586
+ ```ts
587
+ // Pattern 1: Quick CRUD (One-Import)
588
+ await Mapper.add('users', data)
589
+ const users = await Mapper.get('users')
590
+
591
+ // Pattern 2: Configuration-Based
592
+ const mapper = createConfigMapper(config)
593
+ await mapper.useConnection('mydb').table('users').add(data)
594
+
595
+ // Pattern 3: Fluent API
596
+ await StaticMapper.useConnection('mydb').table('users').add(data).execute()
597
+
598
+ // Pattern 4: Complex queries
599
+ const results = await Mapper.use('users')
600
+ .where('age', 18, '>=')
601
+ .where('country', 'US')
602
+ .get()
603
+
604
+ // Pattern 5: Batch operations
605
+ const users = await Mapper.get('users')
606
+ for (const user of users) {
607
+ await Mapper.update('users', { id: user.id }, { lastSeen: new Date() })
608
+ }
609
+ ```
610
+
611
+ ## 🔄 **Choosing the Right Approach**
612
+
613
+ ### **When to Use Each Method**
614
+
615
+ | Approach | Best For | Example Use Case |
616
+ |----------|----------|------------------|
617
+ | **One-Import** | Quick prototyping, simple apps | `Mapper.add('users', data)` |
618
+ | **Configuration-Based** | Enterprise apps, multiple environments | Load from config files |
619
+ | **Fluent API** | Dynamic connections, runtime decisions | Create temp connections on-demand |
620
+
621
+ ### **Migration Between Approaches**
622
+
623
+ ```ts
624
+ // Start with One-Import
625
+ import Mapper from '@neupgroup/mapper'
626
+ await Mapper.add('users', { name: 'Alice' })
627
+
628
+ // Gradually move to Configuration-Based
629
+ import { createConfigMapper } from '@neupgroup/mapper'
630
+ const mapper = createConfigMapper(config)
631
+ await mapper.useConnection('mydb').table('users').add({ name: 'Alice' })
632
+
633
+ // Or use Fluent API for dynamic scenarios
634
+ import { StaticMapper } from '@neupgroup/mapper'
635
+ StaticMapper.makeConnection('temp', 'mysql', config)
636
+ await StaticMapper.useConnection('temp').table('users').add({ name: 'Alice' })
637
+ ```
638
+
639
+ ### **Real-World Examples**
640
+
641
+ **Microservices Configuration:**
642
+ ```ts
643
+ // config/mapper.config.ts
644
+ export const mapperConfig = {
645
+ connections: [
646
+ ['user-service', 'postgres', 'user', 'users_db', 'user-db.internal', 5432],
647
+ ['order-service', 'mysql', 'order', 'orders_db', 'order-db.internal', 3306],
648
+ ['analytics-api', 'api', 'https://analytics.internal.company.com']
649
+ ]
650
+ }
651
+
652
+ // services/UserService.ts
653
+ import { createConfigMapper } from '@neupgroup/mapper'
654
+ import { mapperConfig } from '../config/mapper.config'
655
+
656
+ const mapper = createConfigMapper(mapperConfig)
657
+
658
+ export class UserService {
659
+ async getUser(id: string) {
660
+ return await mapper.useConnection('user-service')
661
+ .table('users')
662
+ .select()
663
+ .where('id', id)
664
+ .execute()
665
+ }
666
+ }
667
+ ```
668
+
669
+ **Dynamic Connection Management:**
670
+ ```ts
671
+ // utils/ConnectionManager.ts
672
+ import { StaticMapper } from '@neupgroup/mapper'
673
+
674
+ export class ConnectionManager {
675
+ private activeConnections: Set<string> = new Set()
676
+
677
+ async createTenantConnection(tenantId: string, dbConfig: any) {
678
+ const connectionName = `tenant-${tenantId}`
679
+
680
+ StaticMapper.makeConnection(connectionName, 'mysql', {
681
+ host: dbConfig.host,
682
+ database: `tenant_${tenantId}`,
683
+ user: dbConfig.user,
684
+ password: dbConfig.password
685
+ })
686
+
687
+ this.activeConnections.add(connectionName)
688
+ return connectionName
689
+ }
690
+
691
+ async queryTenant(tenantId: string, table: string) {
692
+ const connectionName = `tenant-${tenantId}`
693
+ return await StaticMapper.useConnection(connectionName)
694
+ .table(table)
695
+ .select()
696
+ .execute()
697
+ }
698
+
699
+ cleanupConnection(tenantId: string) {
700
+ const connectionName = `tenant-${tenantId}`
701
+ this.activeConnections.delete(connectionName)
702
+ // Connection cleanup handled automatically
703
+ }
704
+ }
705
+ ```
37
706