mango-orm 1.0.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 ADDED
@@ -0,0 +1,1244 @@
1
+ # ๐Ÿฅญ Mango ORM
2
+
3
+ <div align="center">
4
+
5
+ **A lightweight, type-safe MySQL ORM for Node.js and TypeScript**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/mango-orm.svg)](https://www.npmjs.com/package/mango-orm)
8
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
10
+
11
+ [Features](#-features) โ€ข [Installation](#-installation) โ€ข [Quick Start](#-quick-start) โ€ข [Documentation](#-complete-documentation) โ€ข [Examples](#-usage-examples)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ ## โš ๏ธ Development Status
18
+
19
+ **This project is currently under active development.** Features are being added and refined. The API may change in future versions. Not recommended for production use yet.
20
+
21
+ ## ๐Ÿ“– Table of Contents
22
+
23
+ - [Features](#-features)
24
+ - [Installation](#-installation)
25
+ - [Quick Start](#-quick-start)
26
+ - [Complete Documentation](#-complete-documentation)
27
+ - [Database Connection](#1-database-connection)
28
+ - [Creating Tables](#2-creating-tables)
29
+ - [Inserting Data](#3-inserting-data)
30
+ - [Querying Data](#4-querying-data)
31
+ - [Filtering & Conditions](#5-filtering--conditions-where-and-or)
32
+ - [Updating Data](#6-updating-data)
33
+ - [Deleting Data](#7-deleting-data)
34
+ - [Advanced Features](#8-advanced-features)
35
+ - [API Reference](#-api-reference)
36
+ - [Security](#-security)
37
+ - [Contributing](#-contributing)
38
+
39
+ ## โœจ Features
40
+
41
+ - ๐Ÿ”’ **Type-safe**: Full TypeScript support with generics for compile-time safety
42
+ - ๐Ÿ”— **Fluent API**: Chainable methods for readable, expressive queries
43
+ - ๐Ÿ›ก๏ธ **SQL Injection Protection**: Parameterized queries throughout for security
44
+ - ๐ŸŠ **Connection Pooling**: Built-in MySQL connection pool for better performance
45
+ - ๐Ÿ“ฆ **Auto-Discovery**: Automatically loads existing table schemas on connect
46
+ - โšก **Zero Config**: Works out of the box with sensible defaults
47
+ - ๐ŸŽฏ **Simple API**: Intuitive, easy to learn, and quick to master
48
+ - ๐Ÿ” **Query Builder**: WHERE, AND, OR conditions with full operator support
49
+ - โ™ป๏ธ **CRUD Complete**: Create, Read, Update, Delete operations all supported
50
+ - ๐Ÿงน **Clean Code**: Well-documented, formatted, and maintainable codebase
51
+
52
+ ## ๐Ÿ“ฆ Installation
53
+
54
+ ```bash
55
+ # Using npm
56
+ npm install mango-orm mysql @types/mysql
57
+
58
+ # Using yarn
59
+ yarn add mango-orm mysql @types/mysql
60
+
61
+ # Using pnpm (recommended)
62
+ pnpm add mango-orm mysql @types/mysql
63
+ ```
64
+
65
+ ### Requirements
66
+
67
+ - **Node.js**: >= 14.x
68
+ - **TypeScript**: >= 4.5 (for TypeScript projects)
69
+ - **MySQL**: >= 5.7 or MariaDB >= 10.2
70
+
71
+ ## ๐Ÿš€ Quick Start
72
+
73
+ Get started with Mango ORM in less than 5 minutes!
74
+
75
+ ```typescript
76
+ import { Mango } from "mango-orm";
77
+
78
+ // 1. Initialize and connect
79
+ const mango = new Mango();
80
+ await mango.connect({
81
+ host: "localhost",
82
+ user: "root",
83
+ password: "your_password",
84
+ database: "your_database"
85
+ });
86
+
87
+ // 2. Define your data structure
88
+ interface User {
89
+ id?: number;
90
+ username: string;
91
+ email: string;
92
+ age?: number;
93
+ }
94
+
95
+ // 3. Create a table
96
+ const users = await mango.createTable<User>("users", {
97
+ id: mango.types().int().autoIncrement().primaryKey(),
98
+ username: mango.types().varchar(50).notNull().unique(),
99
+ email: mango.types().varchar(100).notNull(),
100
+ age: mango.types().int()
101
+ });
102
+
103
+ // 4. Insert data
104
+ await users.insertOne({
105
+ username: "john_doe",
106
+ email: "john@example.com",
107
+ age: 25
108
+ }).execute();
109
+
110
+ // 5. Query data with conditions
111
+ const adults = await users
112
+ .selectAll()
113
+ .where("age", ">=", 18)
114
+ .orderBy("username")
115
+ .execute();
116
+
117
+ console.log(adults);
118
+
119
+ // 6. Update data
120
+ await users
121
+ .update({ age: 26 })
122
+ .where("username", "=", "john_doe")
123
+ .execute();
124
+
125
+ // 7. Delete data
126
+ await users
127
+ .delete()
128
+ .where("age", "<", 18)
129
+ .execute();
130
+
131
+ // 8. Disconnect when done
132
+ await mango.disconnect();
133
+ ```
134
+
135
+ ---
136
+
137
+ ## ๐Ÿ“š Complete Documentation
138
+
139
+ ### 1. Database Connection
140
+
141
+ #### Basic Connection
142
+
143
+ ```typescript
144
+ const mango = new Mango();
145
+
146
+ await mango.connect({
147
+ host: "localhost", // MySQL server host
148
+ user: "root", // Database username
149
+ password: "mypassword", // Database password
150
+ database: "myapp" // Database name
151
+ });
152
+ ```
153
+
154
+ #### Connection Features
155
+
156
+ - โœ… **Auto-connects** using connection pooling for performance
157
+ - โœ… **Auto-discovers** all existing tables and their schemas
158
+ - โœ… **Validates** connection parameters
159
+ - โœ… **Returns** Mango instance for chaining
160
+
161
+ #### Disconnect
162
+
163
+ Always disconnect when your application is shutting down:
164
+
165
+ ```typescript
166
+ await mango.disconnect();
167
+ ```
168
+
169
+ ### 2. Creating Tables
170
+
171
+ #### Define Your Schema
172
+
173
+ ```typescript
174
+ interface Post {
175
+ id?: number;
176
+ title: string;
177
+ content: string;
178
+ author_id: number;
179
+ created_at?: Date;
180
+ is_published?: boolean;
181
+ }
182
+
183
+ const posts = await mango.createTable<Post>("posts", {
184
+ id: mango.types().int().autoIncrement().primaryKey(),
185
+ title: mango.types().varchar(200).notNull(),
186
+ content: mango.types().text().notNull(),
187
+ author_id: mango.types().int().notNull(),
188
+ created_at: mango.types().timeStamp(),
189
+ is_published: mango.types().boolean()
190
+ });
191
+ ```
192
+
193
+ #### Available Data Types
194
+
195
+ | Type | Method | Example | SQL Output |
196
+ |------|--------|---------|------------|
197
+ | Integer | `int()` | `types().int()` | `INT` |
198
+ | Big Integer | `bigInt()` | `types().bigInt()` | `BIGINT` |
199
+ | Float | `float()` | `types().float()` | `FLOAT` |
200
+ | Variable String | `varchar(n)` | `types().varchar(255)` | `VARCHAR(255)` |
201
+ | Fixed String | `char(n)` | `types().char(10)` | `CHAR(10)` |
202
+ | Text | `text()` | `types().text()` | `TEXT` |
203
+ | Date | `date()` | `types().date()` | `DATE` |
204
+ | DateTime | `dateTime()` | `types().dateTime()` | `DATETIME` |
205
+ | Timestamp | `timeStamp()` | `types().timeStamp()` | `TIMESTAMP` |
206
+ | Boolean | `boolean()` | `types().boolean()` | `BOOLEAN` |
207
+ | Tiny Integer | `tinyInt(n)` | `types().tinyInt(1)` | `TINYINT(1)` |
208
+
209
+ #### Type Modifiers
210
+
211
+ Chain modifiers to customize your columns:
212
+
213
+ ```typescript
214
+ mango.types()
215
+ .int() // Column type
216
+ .notNull() // Cannot be NULL
217
+ .autoIncrement() // Auto-incrementing
218
+ .primaryKey() // Primary key
219
+ .unique() // Unique constraint
220
+ ```
221
+
222
+ **Common Patterns:**
223
+
224
+ ```typescript
225
+ // Primary key (typical ID column)
226
+ id: mango.types().int().autoIncrement().primaryKey()
227
+
228
+ // Required email with uniqueness
229
+ email: mango.types().varchar(100).notNull().unique()
230
+
231
+ // Optional text field
232
+ bio: mango.types().text()
233
+
234
+ // Required foreign key
235
+ user_id: mango.types().int().notNull()
236
+ ```
237
+
238
+ #### Accessing Existing Tables
239
+
240
+ After connection, all existing tables are automatically loaded:
241
+
242
+ ```typescript
243
+ // Get a typed table instance
244
+ const existingUsers = mango.selectTable<User>("users");
245
+
246
+ // Query immediately
247
+ const data = await existingUsers.selectAll().execute();
248
+ ```
249
+
250
+ ```
251
+
252
+ #### Table Information
253
+
254
+ ```typescript
255
+ const tableName = users.getName(); // Returns: "users"
256
+ const fields = users.getFields(); // Returns: ["id", "username", "email"]
257
+
258
+ console.log(`Table: ${tableName}`);
259
+ console.log(`Columns:`, fields);
260
+ ```
261
+
262
+ ---
263
+
264
+ ### 5. Filtering & Conditions (WHERE, AND, OR)
265
+
266
+ #### WHERE Clause
267
+
268
+ Filter results with WHERE conditions:
269
+
270
+ ```typescript
271
+ // Find user by username
272
+ const user = await users
273
+ .selectAll()
274
+ .where("username", "=", "john_doe")
275
+ .execute();
276
+
277
+ // Find adult users
278
+ const adults = await users
279
+ .selectAll()
280
+ .where("age", ">=", 18)
281
+ .execute();
282
+
283
+ // Find published posts
284
+ const published = await posts
285
+ .selectAll()
286
+ .where("is_published", "=", true)
287
+ .execute();
288
+ ```
289
+
290
+ #### Supported Operators
291
+
292
+ | Operator | Description | Example |
293
+ |----------|-------------|---------|
294
+ | `=` | Equal to | `where("age", "=", 25)` |
295
+ | `!=` or `<>` | Not equal | `where("status", "!=", "deleted")` |
296
+ | `>` | Greater than | `where("age", ">", 18)` |
297
+ | `<` | Less than | `where("price", "<", 100)` |
298
+ | `>=` | Greater or equal | `where("age", ">=", 21)` |
299
+ | `<=` | Less or equal | `where("stock", "<=", 10)` |
300
+ | `LIKE` | Pattern match | `where("email", "LIKE", "%@gmail.com")` |
301
+ | `NOT LIKE` | Not matching | `where("name", "NOT LIKE", "test%")` |
302
+ | `IN` | In list | Use `whereIn()` method |
303
+ | `NOT IN` | Not in list | Use `whereNotIn()` method |
304
+
305
+ #### AND Conditions
306
+
307
+ Combine multiple conditions (all must be true):
308
+
309
+ ```typescript
310
+ // Find young adults
311
+ const youngAdults = await users
312
+ .selectAll()
313
+ .where("age", ">=", 18)
314
+ .and("age", "<=", 30)
315
+ .execute();
316
+
317
+ // Find published posts by specific author
318
+ const authorPosts = await posts
319
+ .selectAll()
320
+ .where("author_id", "=", 1)
321
+ .and("is_published", "=", true)
322
+ .execute();
323
+
324
+ // Multiple AND conditions
325
+ const specificUsers = await users
326
+ .selectAll()
327
+ .where("age", ">", 25)
328
+ .and("age", "<", 40)
329
+ .and("email", "LIKE", "%@company.com")
330
+ .execute();
331
+ ```
332
+
333
+ #### OR Conditions
334
+
335
+ Alternative conditions (any can be true):
336
+
337
+ ```typescript
338
+ // Find users who are either admins or moderators
339
+ const staff = await users
340
+ .selectAll()
341
+ .where("role", "=", "admin")
342
+ .or("role", "=", "moderator")
343
+ .execute();
344
+
345
+ // Find urgent or high priority tasks
346
+ const important = await tasks
347
+ .selectAll()
348
+ .where("priority", "=", "urgent")
349
+ .or("priority", "=", "high")
350
+ .execute();
351
+ ```
352
+
353
+ #### Combining AND/OR
354
+
355
+ ```typescript
356
+ // Complex conditions: (age >= 18 AND age <= 65) OR is_verified = true
357
+ const eligible = await users
358
+ .selectAll()
359
+ .where("age", ">=", 18)
360
+ .and("age", "<=", 65)
361
+ .or("is_verified", "=", true)
362
+ .execute();
363
+ ```
364
+
365
+ #### WHERE IN / NOT IN
366
+
367
+ Check if value exists in a list:
368
+
369
+ ```typescript
370
+ // Find users with specific IDs
371
+ const selectedUsers = await users
372
+ .selectAll()
373
+ .whereIn("id", [1, 5, 10, 15])
374
+ .execute();
375
+
376
+ // Find posts by multiple authors
377
+ const multiAuthorPosts = await posts
378
+ .selectAll()
379
+ .whereIn("author_id", [1, 2, 3])
380
+ .execute();
381
+
382
+ // Exclude specific users
383
+ const otherUsers = await users
384
+ .selectAll()
385
+ .whereNotIn("id", [1, 2, 3])
386
+ .execute();
387
+ ```
388
+
389
+ #### Working with Falsy Values
390
+
391
+ **Important:** WHERE conditions support falsy values (0, false, empty string):
392
+
393
+ ```typescript
394
+ // โœ… Works correctly with 0
395
+ const inactiveUsers = await users
396
+ .selectAll()
397
+ .where("login_count", "=", 0)
398
+ .execute();
399
+
400
+ // โœ… Works correctly with false
401
+ const unpublished = await posts
402
+ .selectAll()
403
+ .where("is_published", "=", false)
404
+ .execute();
405
+
406
+ // โœ… Works correctly with empty string
407
+ const noDescription = await products
408
+ .selectAll()
409
+ .where("description", "=", "")
410
+ .execute();
411
+ ```
412
+
413
+ ---
414
+
415
+ ### 6. Updating Data
416
+
417
+ Update existing records with WHERE conditions:
418
+
419
+ ```typescript
420
+ // Update single field
421
+ await users
422
+ .update({ age: 26 })
423
+ .where("username", "=", "john_doe")
424
+ .execute();
425
+
426
+ // Update multiple fields
427
+ await users
428
+ .update({
429
+ email: "newemail@example.com",
430
+ age: 30,
431
+ is_verified: true
432
+ })
433
+ .where("id", "=", 5)
434
+ .execute();
435
+
436
+ // Update with AND conditions
437
+ await posts
438
+ .update({ is_published: true })
439
+ .where("author_id", "=", 1)
440
+ .and("title", "LIKE", "%Draft%")
441
+ .execute();
442
+
443
+ // Bulk update
444
+ await products
445
+ .update({ stock: 0 })
446
+ .where("stock", "<", 5)
447
+ .execute();
448
+ ```
449
+
450
+ **Important Notes:**
451
+ - โœ… Always use WHERE to avoid updating all rows
452
+ - โœ… Validates all field names exist in table
453
+ - โœ… Supports all data types
454
+ - โœ… Uses prepared statements for security
455
+
456
+ ---
457
+
458
+ ### 7. Deleting Data
459
+
460
+ Remove records from table:
461
+
462
+ ```typescript
463
+ // Delete specific user
464
+ await users
465
+ .delete()
466
+ .where("id", "=", 10)
467
+ .execute();
468
+
469
+ // Delete with conditions
470
+ await posts
471
+ .delete()
472
+ .where("is_published", "=", false)
473
+ .and("created_at", "<", "2024-01-01")
474
+ .execute();
475
+
476
+ // Delete using IN
477
+ await users
478
+ .delete()
479
+ .whereIn("id", [5, 10, 15])
480
+ .execute();
481
+ ```
482
+
483
+ **โš ๏ธ Warning:** DELETE without WHERE will remove ALL rows!
484
+
485
+ ```typescript
486
+ // This deletes everything! Use with caution
487
+ await users.delete().execute(); // โŒ Dangerous!
488
+
489
+ // Better: Use truncate for clearing table
490
+ await users.truncate().execute(); // โœ… Explicit intent
491
+ ```
492
+
493
+ ---
494
+
495
+ ### 8. Advanced Features
496
+
497
+ #### Join Tables
498
+
499
+ Combine data from multiple tables:
500
+
501
+ ```typescript
502
+ const userPosts = await users
503
+ .selectAll()
504
+ .join("INNER", "posts", {
505
+ left: "users.id",
506
+ operator: "=",
507
+ right: "posts.author_id"
508
+ })
509
+ .execute();
510
+
511
+ // LEFT JOIN
512
+ const allUsersWithPosts = await users
513
+ .selectAll()
514
+ .join("LEFT", "posts", {
515
+ left: "users.id",
516
+ operator: "=",
517
+ right: "posts.author_id"
518
+ })
519
+ .execute();
520
+ ```
521
+
522
+ **Join Types:** `INNER`, `LEFT`, `RIGHT`, `FULL`
523
+
524
+ #### Modifying Table Schema
525
+
526
+ **Add New Columns:**
527
+
528
+ ```typescript
529
+ await users.addColumns({
530
+ phone: mango.types().varchar(20),
531
+ address: mango.types().text(),
532
+ verified_at: mango.types().dateTime()
533
+ }).execute();
534
+ ```
535
+
536
+ **Remove Columns:**
537
+
538
+ ```typescript
539
+ await users.removeColumns(["phone", "address"]).execute();
540
+ ```
541
+
542
+ #### Truncate Table
543
+
544
+ Remove all rows (faster than DELETE):
545
+
546
+ ```typescript
547
+ await users.truncate().execute();
548
+ ```
549
+
550
+ #### Drop Table
551
+
552
+ Permanently delete a table:
553
+
554
+ ```typescript
555
+ await mango.dropTable("old_table");
556
+ ```
557
+
558
+ #### Custom Raw Queries
559
+
560
+ For complex queries not covered by the query builder:
561
+
562
+ ```typescript
563
+ // Custom SELECT
564
+ const result = await users.customQuery<User>(
565
+ "SELECT * FROM users WHERE age > ? AND email LIKE ?",
566
+ [18, "%@gmail.com"]
567
+ );
568
+
569
+ // Custom INSERT with RETURNING (if supported)
570
+ const inserted = await posts.customQuery(
571
+ "INSERT INTO posts (title, content) VALUES (?, ?) RETURNING id",
572
+ ["New Post", "Content here"]
573
+ );
574
+
575
+ // Complex JOIN
576
+ const complexQuery = await users.customQuery(
577
+ `SELECT u.*, COUNT(p.id) as post_count
578
+ FROM users u
579
+ LEFT JOIN posts p ON u.id = p.author_id
580
+ GROUP BY u.id
581
+ HAVING post_count > ?`,
582
+ [5]
583
+ );
584
+ ```
585
+
586
+ **Tips:**
587
+ - Always use `?` placeholders for values
588
+ - Never concatenate user input into queries
589
+ - Use for complex operations like GROUP BY, HAVING, subqueries
590
+
591
+ ---
592
+
593
+ ### 3. Inserting Data
594
+
595
+ #### Single Row Insert
596
+
597
+ Insert one record at a time:
598
+
599
+ ```typescript
600
+ // Basic insert
601
+ await users.insertOne({
602
+ username: "jane_doe",
603
+ email: "jane@example.com",
604
+ age: 28
605
+ }).execute();
606
+
607
+ // Insert with all fields
608
+ await posts.insertOne({
609
+ title: "Getting Started with Mango",
610
+ content: "This is a comprehensive guide...",
611
+ author_id: 1,
612
+ is_published: true
613
+ }).execute();
614
+ ```
615
+
616
+ **Features:**
617
+ - โœ… Type-safe: TypeScript validates field names and types
618
+ - โœ… SQL Injection protected with prepared statements
619
+ - โœ… Auto-validates fields exist in table schema
620
+ - โœ… Supports all data types (numbers, strings, booleans, dates, null)
621
+
622
+ #### Bulk Insert
623
+
624
+ Insert multiple rows efficiently:
625
+
626
+ ```typescript
627
+ await posts.insertMany(
628
+ ["title", "content", "author_id"], // Column names
629
+ [ // Data rows
630
+ ["First Post", "Content here", 1],
631
+ ["Second Post", "More content", 1],
632
+ ["Third Post", "Even more", 2]
633
+ ]
634
+ ).execute();
635
+
636
+ // Insert 1000 records efficiently
637
+ const bulkData = [];
638
+ for (let i = 0; i < 1000; i++) {
639
+ bulkData.push([`User ${i}`, `user${i}@example.com`, 20 + i % 50]);
640
+ }
641
+
642
+ await users.insertMany(
643
+ ["username", "email", "age"],
644
+ bulkData
645
+ ).execute();
646
+ ```
647
+
648
+ **Performance:**
649
+ - โœ… Single query for all rows (much faster than multiple inserts)
650
+ - โœ… Efficient for batch operations
651
+ - โœ… Validates all rows have same number of columns
652
+
653
+ ### 4. Querying Data
654
+
655
+ #### Select All Columns
656
+
657
+ ```typescript
658
+ // Get all users
659
+ const allUsers = await users.selectAll().execute();
660
+
661
+ // Get all posts
662
+ const allPosts = await posts.selectAll().execute();
663
+ ```
664
+
665
+ #### Select Specific Columns
666
+
667
+ ```typescript
668
+ // Select only username and email
669
+ const userContacts = await users
670
+ .selectColumns(["username", "email"])
671
+ .execute();
672
+
673
+ // Select specific post fields
674
+ const postTitles = await posts
675
+ .selectColumns(["id", "title", "created_at"])
676
+ .execute();
677
+ ```
678
+
679
+ #### Select Distinct Values
680
+
681
+ Get unique values only:
682
+
683
+ ```typescript
684
+ // Get unique email domains
685
+ const uniqueEmails = await users
686
+ .selectDistinctColumns(["email"])
687
+ .execute();
688
+
689
+ // Get unique authors
690
+ const uniqueAuthors = await posts
691
+ .selectDistinctColumns(["author_id"])
692
+ .execute();
693
+ ```
694
+
695
+ #### Ordering Results
696
+
697
+ Sort your query results:
698
+
699
+ ```typescript
700
+ // Order by username ascending (A-Z)
701
+ const sortedUsers = await users
702
+ .selectAll()
703
+ .orderBy("username")
704
+ .sort(1) // 1 = ASC, -1 = DESC
705
+ .execute();
706
+
707
+ // Order by age descending (highest first)
708
+ const oldestFirst = await users
709
+ .selectAll()
710
+ .orderBy("age")
711
+ .sort(-1) // Descending order
712
+ .execute();
713
+
714
+ // Order posts by creation date (newest first)
715
+ const recentPosts = await posts
716
+ .selectAll()
717
+ .orderBy("created_at")
718
+ .sort(-1)
719
+ .execute();
720
+ ```
721
+
722
+ #### Limiting and Pagination
723
+
724
+ ```typescript
725
+ // Get first 10 users
726
+ const firstTen = await users
727
+ .selectAll()
728
+ .limit(10)
729
+ .execute();
730
+
731
+ // Get 10 users, skip first 20 (page 3, 10 per page)
732
+ const page3 = await users
733
+ .selectAll()
734
+ .limit(10)
735
+ .offset(20)
736
+ .execute();
737
+
738
+ // Complete pagination example
739
+ const PAGE_SIZE = 25;
740
+ const page = 2; // Get page 2
741
+
742
+ const paginatedUsers = await users
743
+ .selectAll()
744
+ .orderBy("id")
745
+ .sort(1)
746
+ .limit(PAGE_SIZE)
747
+ .offset((page - 1) * PAGE_SIZE)
748
+ .execute();
749
+ ```
750
+
751
+ ### Modifying Tables
752
+
753
+ **Add Columns:**
754
+ ```typescript
755
+ await users.addColumns({
756
+ age: mango.types().int(),
757
+ phone: mango.types().varchar(20)
758
+ }).execute();
759
+ ```
760
+
761
+ **Remove Columns:**
762
+ ```typescript
763
+ await users.removeColumns(["age"]).execute();
764
+ ```
765
+
766
+ ### Truncate and Drop
767
+
768
+ **Truncate Table:**
769
+ ```typescript
770
+ await users.truncate().execute();
771
+ ```
772
+
773
+ **Drop Table:**
774
+ ```typescript
775
+ await mango.dropTable("users");
776
+ ```
777
+
778
+ ### Custom Queries
779
+
780
+ ```typescript
781
+ const result = await users.customQuery<User>(
782
+ "SELECT * FROM users WHERE age > ?",
783
+ [18]
784
+ );
785
+ ```
786
+
787
+ ---
788
+
789
+ ## ๐Ÿ”ง API Reference
790
+
791
+ ### Mango Class
792
+
793
+ Main class for database connection and management.
794
+
795
+ | Method | Parameters | Returns | Description |
796
+ |--------|------------|---------|-------------|
797
+ | `connect(config)` | `{host, user, password, database}` | `Promise<Mango>` | Connect to MySQL and load tables |
798
+ | `disconnect()` | - | `Promise<void>` | Close connection pool |
799
+ | `createTable<T>(name, fields)` | `name: string`, `fields: Record` | `Promise<MangoTable<T>>` | Create new table |
800
+ | `selectTable<T>(name)` | `name: string` | `MangoTable<T>` | Get existing table instance |
801
+ | `dropTable(name)` | `name: string` | `Promise<void>` | Drop table permanently |
802
+ | `getTables()` | - | `MangoTable[]` | Get all table instances |
803
+ | `types()` | - | `MangoType` | Get schema type builder |
804
+ | `customQuery<T>(query, params)` | `query: string`, `params: any[]` | `Promise<T>` | Execute raw SQL |
805
+
806
+ ---
807
+
808
+ ### MangoTable<T> Class
809
+
810
+ Query builder for table operations (all methods chainable except `execute()`).
811
+
812
+ #### Query Building Methods
813
+
814
+ | Method | Parameters | Returns | Description |
815
+ |--------|------------|---------|-------------|
816
+ | `selectAll()` | - | `this` | Select all columns |
817
+ | `selectColumns(cols)` | `cols: string[]` | `this` | Select specific columns |
818
+ | `selectDistinctColumns(cols)` | `cols: string[]` | `this` | Select unique values |
819
+ | `orderBy(column)` | `column: string` | `this` | Order results by column |
820
+ | `sort(direction)` | `1` (ASC) or `-1` (DESC) | `this` | Sort direction |
821
+ | `limit(n)` | `n: number` | `this` | Limit number of results |
822
+ | `offset(n)` | `n: number` | `this` | Skip n rows |
823
+
824
+ #### Filtering Methods
825
+
826
+ | Method | Parameters | Returns | Description |
827
+ |--------|------------|---------|-------------|
828
+ | `where(field, op, value)` | `field: string`, `op: string`, `value: any` | `this` | Add WHERE condition |
829
+ | `and(field, op, value)` | `field: string`, `op: string`, `value: any` | `this` | Add AND condition |
830
+ | `or(field, op, value)` | `field: string`, `op: string`, `value: any` | `this` | Add OR condition |
831
+ | `whereIn(field, values)` | `field: string`, `values: any[]` | `this` | WHERE field IN (values) |
832
+ | `whereNotIn(field, values)` | `field: string`, `values: any[]` | `this` | WHERE field NOT IN (values) |
833
+
834
+ #### Data Modification Methods
835
+
836
+ | Method | Parameters | Returns | Description |
837
+ |--------|------------|---------|-------------|
838
+ | `insertOne(data)` | `data: Record<string, any>` | `this` | Insert single row |
839
+ | `insertMany(fields, data)` | `fields: string[]`, `data: any[][]` | `this` | Insert multiple rows |
840
+ | `update(data)` | `data: Record<string, any>` | `this` | Update rows (use with WHERE) |
841
+ | `delete()` | - | `this` | Delete rows (use with WHERE) |
842
+
843
+ #### Schema Modification Methods
844
+
845
+ | Method | Parameters | Returns | Description |
846
+ |--------|------------|---------|-------------|
847
+ | `addColumns(fields)` | `fields: Record<string, MangoType>` | `this` | Add new columns |
848
+ | `removeColumns(fields)` | `fields: string[]` | `this` | Remove columns |
849
+ | `truncate()` | - | `this` | Remove all rows |
850
+
851
+ #### Utility Methods
852
+
853
+ | Method | Parameters | Returns | Description |
854
+ |--------|------------|---------|-------------|
855
+ | `execute()` | - | `Promise<T[]>` | Execute the built query |
856
+ | `customQuery<Type>(query, params)` | `query: string`, `params: any[]` | `Promise<Type[]>` | Execute custom SQL |
857
+ | `getName()` | - | `string` | Get table name |
858
+ | `getFields()` | - | `string[]` | Get column names (copy) |
859
+ | `getQuery()` | - | `MangoQuery` | Get query object (advanced) |
860
+
861
+ #### Advanced Methods
862
+
863
+ | Method | Parameters | Returns | Description |
864
+ |--------|------------|---------|-------------|
865
+ | `join(type, table, condition)` | `type`, `table: string`, `condition` | `this` | Join tables |
866
+ | `commit()` | - | `this` | Add COMMIT to query |
867
+ | `rollback()` | - | `this` | Add ROLLBACK to query |
868
+
869
+ ---
870
+
871
+ ### MangoType Class
872
+
873
+ Schema type builder for column definitions.
874
+
875
+ #### Data Types
876
+
877
+ | Method | Returns | SQL Output | Description |
878
+ |--------|---------|------------|-------------|
879
+ | `int()` | `this` | `INT` | Integer number |
880
+ | `bigInt()` | `this` | `BIGINT` | Large integer |
881
+ | `float()` | `this` | `FLOAT` | Floating point |
882
+ | `varchar(n)` | `this` | `VARCHAR(n)` | Variable string |
883
+ | `char(n)` | `this` | `CHAR(n)` | Fixed string |
884
+ | `text()` | `this` | `TEXT` | Long text |
885
+ | `date()` | `this` | `DATE` | Date only |
886
+ | `dateTime()` | `this` | `DATETIME` | Date and time |
887
+ | `timeStamp()` | `this` | `TIMESTAMP` | Auto-updating timestamp |
888
+ | `boolean()` | `this` | `BOOLEAN` | True/false |
889
+ | `tinyInt(n)` | `this` | `TINYINT(n)` | Small integer |
890
+
891
+ #### Modifiers
892
+
893
+ | Method | Returns | SQL Output | Description |
894
+ |--------|---------|------------|-------------|
895
+ | `notNull()` | `this` | `NOT NULL` | Cannot be null |
896
+ | `autoIncrement()` | `this` | `AUTO_INCREMENT` | Auto-incrementing |
897
+ | `primaryKey()` | `this` | `PRIMARY KEY` | Primary key |
898
+ | `unique()` | `this` | `UNIQUE` | Must be unique |
899
+ | `getQuery()` | `string` | - | Get built SQL string |
900
+
901
+ ---
902
+
903
+ ## ๐Ÿ” Security
904
+
905
+ Mango ORM is built with security in mind:
906
+
907
+ ### โœ… Prepared Statements
908
+
909
+ All queries use parameterized statements to prevent SQL injection:
910
+
911
+ ```typescript
912
+ // โœ… SAFE - Values are parameterized
913
+ await users.insertOne({
914
+ username: userInput, // Automatically escaped
915
+ email: emailInput
916
+ }).execute();
917
+
918
+ // โœ… SAFE - WHERE values are parameterized
919
+ await users
920
+ .selectAll()
921
+ .where("username", "=", userInput) // Safe from injection
922
+ .execute();
923
+
924
+ // โœ… SAFE - Bulk insert with parameterized values
925
+ await posts.insertMany(
926
+ ["title", "content"],
927
+ [[userTitle, userContent]] // All values escaped
928
+ ).execute();
929
+ ```
930
+
931
+ ### โš ๏ธ Custom Queries
932
+
933
+ When using `customQuery()`, **always use placeholders**:
934
+
935
+ ```typescript
936
+ // โœ… SAFE - Using placeholders
937
+ const results = await users.customQuery(
938
+ "SELECT * FROM users WHERE email = ?",
939
+ [userEmail]
940
+ );
941
+
942
+ // โŒ UNSAFE - String concatenation
943
+ const unsafe = await users.customQuery(
944
+ `SELECT * FROM users WHERE email = '${userEmail}'`, // SQL INJECTION RISK!
945
+ []
946
+ );
947
+ ```
948
+
949
+ ### ๐Ÿ›ก๏ธ Field Validation
950
+
951
+ All operations validate field names against table schema:
952
+
953
+ ```typescript
954
+ // โœ… Validated - Throws error if 'invalid_field' doesn't exist
955
+ await users.insertOne({
956
+ invalid_field: "value" // Error: Field doesn't exist
957
+ }).execute();
958
+ ```
959
+
960
+ ### ๐Ÿ”’ Connection Security
961
+
962
+ ```typescript
963
+ // Use environment variables for credentials
964
+ await mango.connect({
965
+ host: process.env.DB_HOST,
966
+ user: process.env.DB_USER,
967
+ password: process.env.DB_PASSWORD,
968
+ database: process.env.DB_NAME
969
+ });
970
+ ```
971
+
972
+ **Best Practices:**
973
+ - โœ… Never commit credentials to source control
974
+ - โœ… Use `.env` files with proper `.gitignore`
975
+ - โœ… Rotate credentials regularly
976
+ - โœ… Use least-privilege database users
977
+ - โœ… Enable SSL/TLS for production databases
978
+
979
+ ---
980
+
981
+ ## ๐Ÿšง Current Limitations
982
+
983
+ While Mango is functional, some features are still in development:
984
+
985
+ - โณ **No Transaction Support**: BEGIN/COMMIT/ROLLBACK not fully implemented
986
+ - โณ **Limited JOIN Support**: Basic joins work but complex joins need testing
987
+ - โณ **No Migration System**: Schema versioning and migrations coming soon
988
+ - โณ **No Relations**: ORM-style relations (hasMany, belongsTo) not yet available
989
+ - โณ **No Query Caching**: Results are not cached (may add in future)
990
+ - โณ **No Connection Retry**: Failed connections don't auto-retry
991
+ - โณ **Single Database Only**: Cannot connect to multiple databases simultaneously
992
+
993
+ ---
994
+
995
+ ## ๐Ÿ—บ๏ธ Roadmap
996
+
997
+ ### Short Term (v0.3.0)
998
+ - [x] WHERE clause support
999
+ - [x] UPDATE operations
1000
+ - [x] DELETE operations
1001
+ - [x] Comprehensive documentation
1002
+ - [ ] Transaction support (BEGIN, COMMIT, ROLLBACK)
1003
+ - [ ] Better error messages with stack traces
1004
+ - [ ] Connection pool configuration options
1005
+
1006
+ ### Medium Term (v0.4.0)
1007
+ - [ ] Migration system
1008
+ - [ ] Seed data functionality
1009
+ - [ ] Query result caching
1010
+ - [ ] Batch operation optimization
1011
+ - [ ] Advanced JOIN support
1012
+ - [ ] Aggregate functions (COUNT, SUM, AVG, etc.)
1013
+ - [ ] GROUP BY and HAVING clauses
1014
+
1015
+ ### Long Term (v1.0.0)
1016
+ - [ ] Relation support (hasOne, hasMany, belongsTo, manyToMany)
1017
+ - [ ] Eager loading and lazy loading
1018
+ - [ ] Model hooks (beforeCreate, afterUpdate, etc.)
1019
+ - [ ] Query event listeners
1020
+ - [ ] Schema validation
1021
+ - [ ] Multiple database connections
1022
+ - [ ] Read/write splitting
1023
+ - [ ] Query builder visual tool
1024
+
1025
+ ---
1026
+
1027
+ ## ๐Ÿ“ Example Project
1028
+
1029
+ ### Quick Test
1030
+
1031
+ Check out the `/test` directory for complete working examples:
1032
+
1033
+ ```bash
1034
+ # Clone the repository
1035
+ git clone https://github.com/devSiddharthKarn/Mango.git
1036
+ cd Mango
1037
+
1038
+ # Install dependencies
1039
+ pnpm install
1040
+ # or: npm install
1041
+
1042
+ # Configure database
1043
+ # Edit test/test.ts with your database credentials
1044
+
1045
+ # Run tests
1046
+ pnpm run test
1047
+ ```
1048
+
1049
+ ### Example Code Structure
1050
+
1051
+ ```
1052
+ Mango/
1053
+ โ”œโ”€โ”€ src/
1054
+ โ”‚ โ””โ”€โ”€ mango.ts # Main ORM code
1055
+ โ”œโ”€โ”€ test/
1056
+ โ”‚ โ”œโ”€โ”€ test.ts # Basic usage examples
1057
+ โ”‚ โ””โ”€โ”€ test-operations.ts # Advanced operations
1058
+ โ”œโ”€โ”€ package.json
1059
+ โ”œโ”€โ”€ tsconfig.json
1060
+ โ””โ”€โ”€ README.md
1061
+ ```
1062
+
1063
+ ### Sample Application
1064
+
1065
+ Here's a complete example application:
1066
+
1067
+ ```typescript
1068
+ import { Mango } from "mango-orm";
1069
+
1070
+ interface User {
1071
+ id?: number;
1072
+ username: string;
1073
+ email: string;
1074
+ age: number;
1075
+ created_at?: Date;
1076
+ }
1077
+
1078
+ async function main() {
1079
+ // 1. Connect
1080
+ const mango = new Mango();
1081
+ await mango.connect({
1082
+ host: "localhost",
1083
+ user: "root",
1084
+ password: "password",
1085
+ database: "myapp"
1086
+ });
1087
+
1088
+ // 2. Create table
1089
+ const users = await mango.createTable<User>("users", {
1090
+ id: mango.types().int().autoIncrement().primaryKey(),
1091
+ username: mango.types().varchar(50).notNull().unique(),
1092
+ email: mango.types().varchar(100).notNull(),
1093
+ age: mango.types().int().notNull(),
1094
+ created_at: mango.types().timeStamp()
1095
+ });
1096
+
1097
+ // 3. Insert sample data
1098
+ await users.insertOne({
1099
+ username: "alice",
1100
+ email: "alice@example.com",
1101
+ age: 25
1102
+ }).execute();
1103
+
1104
+ // 4. Query with filters
1105
+ const adults = await users
1106
+ .selectColumns(["username", "email", "age"])
1107
+ .where("age", ">=", 18)
1108
+ .orderBy("age")
1109
+ .sort(-1)
1110
+ .limit(10)
1111
+ .execute();
1112
+
1113
+ console.log("Adult users:", adults);
1114
+
1115
+ // 5. Update
1116
+ await users
1117
+ .update({ age: 26 })
1118
+ .where("username", "=", "alice")
1119
+ .execute();
1120
+
1121
+ // 6. Delete
1122
+ await users
1123
+ .delete()
1124
+ .where("age", "<", 13)
1125
+ .execute();
1126
+
1127
+ // 7. Cleanup
1128
+ await mango.disconnect();
1129
+ }
1130
+
1131
+ main().catch(console.error);
1132
+ ```
1133
+
1134
+ ---
1135
+
1136
+ ## ๐Ÿค Contributing
1137
+
1138
+ We welcome contributions! This project is in active development and there are many ways to help:
1139
+
1140
+ ### Ways to Contribute
1141
+
1142
+ - ๐Ÿ› **Report Bugs**: Open an issue with reproduction steps
1143
+ - ๐Ÿ’ก **Suggest Features**: Share your ideas for new features
1144
+ - ๐Ÿ“ **Improve Documentation**: Fix typos, add examples, clarify concepts
1145
+ - ๐Ÿ”ง **Submit Pull Requests**: Fix bugs or implement features
1146
+ - โญ **Star the Project**: Show your support on GitHub
1147
+ - ๐Ÿ“ข **Spread the Word**: Share Mango with others
1148
+
1149
+ ### Development Setup
1150
+
1151
+ ```bash
1152
+ # Fork and clone the repository
1153
+ git clone https://github.com/YOUR_USERNAME/Mango.git
1154
+ cd Mango
1155
+
1156
+ # Install dependencies
1157
+ pnpm install
1158
+
1159
+ # Make your changes in src/
1160
+
1161
+ # Test your changes
1162
+ pnpm run test
1163
+
1164
+ # Build TypeScript
1165
+ pnpm run build
1166
+
1167
+ # Commit and push
1168
+ git add .
1169
+ git commit -m "Description of changes"
1170
+ git push origin your-branch-name
1171
+ ```
1172
+
1173
+ ### Guidelines
1174
+
1175
+ - โœ… Write clear commit messages
1176
+ - โœ… Add tests for new features
1177
+ - โœ… Update documentation for API changes
1178
+ - โœ… Follow existing code style (use Prettier)
1179
+ - โœ… Keep PRs focused on single features/fixes
1180
+
1181
+ ### Code of Conduct
1182
+
1183
+ Be respectful, inclusive, and constructive. We're here to build something great together!
1184
+
1185
+ ---
1186
+
1187
+ ## ๐Ÿ“„ License
1188
+
1189
+ **ISC License**
1190
+
1191
+ Copyright (c) 2024 Siddharth Karn
1192
+
1193
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
1194
+
1195
+ ---
1196
+
1197
+ ## ๐Ÿ‘ค Author
1198
+
1199
+ **Siddharth Karn**
1200
+
1201
+ - GitHub: [@devSiddharthKarn](https://github.com/devSiddharthKarn)
1202
+ - Project: [Mango ORM](https://github.com/devSiddharthKarn/Mango)
1203
+
1204
+ ---
1205
+
1206
+ ## ๐Ÿ™ Acknowledgments
1207
+
1208
+ - Inspired by popular ORMs like Prisma, Sequelize, and TypeORM
1209
+ - Built with โค๏ธ using TypeScript
1210
+ - Community feedback and contributions
1211
+
1212
+ ---
1213
+
1214
+ ## ๐Ÿ“ž Support & Community
1215
+
1216
+ - ๐Ÿ› **Issues**: [GitHub Issues](https://github.com/devSiddharthKarn/Mango/issues)
1217
+ - ๐Ÿ’ฌ **Discussions**: [GitHub Discussions](https://github.com/devSiddharthKarn/Mango/discussions)
1218
+ - ๐Ÿ“ง **Email**: [Create an issue for private matters]
1219
+
1220
+ ---
1221
+
1222
+ ## โš ๏ธ Disclaimer
1223
+
1224
+ **This is an educational project currently under active development.**
1225
+
1226
+ - Not recommended for production use yet
1227
+ - API may change in future versions
1228
+ - No stability guarantees until v1.0.0
1229
+ - Use at your own risk
1230
+ - Always backup your data
1231
+
1232
+ ---
1233
+
1234
+ <div align="center">
1235
+
1236
+ **Made with ๐Ÿฅญ by Siddharth Karn**
1237
+ *Eat more mangoes ๐Ÿฅญ๐Ÿฅญ๐Ÿฅญ!*
1238
+
1239
+ If you find this project helpful, please give it a โญ on [GitHub](https://github.com/devSiddharthKarn/Mango)!
1240
+
1241
+ [Report Bug](https://github.com/devSiddharthKarn/Mango/issues) โ€ข [Request Feature](https://github.com/devSiddharthKarn/Mango/issues) โ€ข [Contribute](https://github.com/devSiddharthKarn/Mango/pulls)
1242
+
1243
+ </div>
1244
+