mysql-orm-lite 1.0.1 → 2.1.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.
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.schema = void 0;
7
+ const connectionManager_1 = __importDefault(require("./connectionManager"));
8
+ const schema = {
9
+ /**
10
+ * Get list of all tables in the database
11
+ * @param dbConfig - Optional database configuration
12
+ * @returns Array of table names
13
+ */
14
+ async tables(dbConfig) {
15
+ const pool = await connectionManager_1.default.getPool(dbConfig);
16
+ const config = dbConfig || connectionManager_1.default.defaultConfig;
17
+ if (!config || !config.database) {
18
+ throw new Error('Database name is required for schema introspection');
19
+ }
20
+ const query = `
21
+ SELECT TABLE_NAME
22
+ FROM INFORMATION_SCHEMA.TABLES
23
+ WHERE TABLE_SCHEMA = ?
24
+ AND TABLE_TYPE = 'BASE TABLE'
25
+ ORDER BY TABLE_NAME
26
+ `;
27
+ const [rows] = await pool.query(query, [config.database]);
28
+ return rows.map(row => row.TABLE_NAME);
29
+ },
30
+ /**
31
+ * Get column information for a specific table
32
+ * @param tableName - Name of the table
33
+ * @param dbConfig - Optional database configuration
34
+ * @returns Array of column information
35
+ */
36
+ async columns(tableName, dbConfig) {
37
+ if (!tableName) {
38
+ throw new Error('Table name is required');
39
+ }
40
+ const pool = await connectionManager_1.default.getPool(dbConfig);
41
+ const config = dbConfig || connectionManager_1.default.defaultConfig;
42
+ if (!config || !config.database) {
43
+ throw new Error('Database name is required for schema introspection');
44
+ }
45
+ const query = `
46
+ SELECT
47
+ COLUMN_NAME as name,
48
+ COLUMN_TYPE as type,
49
+ IS_NULLABLE as nullable,
50
+ COLUMN_KEY as \`key\`,
51
+ COLUMN_DEFAULT as \`default\`,
52
+ EXTRA as extra
53
+ FROM INFORMATION_SCHEMA.COLUMNS
54
+ WHERE TABLE_SCHEMA = ?
55
+ AND TABLE_NAME = ?
56
+ ORDER BY ORDINAL_POSITION
57
+ `;
58
+ const [rows] = await pool.query(query, [config.database, tableName]);
59
+ return rows.map(row => ({
60
+ name: row.name,
61
+ type: row.type,
62
+ nullable: row.nullable === 'YES',
63
+ key: row.key || '',
64
+ default: row.default,
65
+ extra: row.extra || ''
66
+ }));
67
+ },
68
+ /**
69
+ * Get index information for a specific table
70
+ * @param tableName - Name of the table
71
+ * @param dbConfig - Optional database configuration
72
+ * @returns Array of index information
73
+ */
74
+ async indexes(tableName, dbConfig) {
75
+ if (!tableName) {
76
+ throw new Error('Table name is required');
77
+ }
78
+ const pool = await connectionManager_1.default.getPool(dbConfig);
79
+ const config = dbConfig || connectionManager_1.default.defaultConfig;
80
+ if (!config || !config.database) {
81
+ throw new Error('Database name is required for schema introspection');
82
+ }
83
+ const query = `
84
+ SELECT
85
+ INDEX_NAME as name,
86
+ COLUMN_NAME as \`column\`,
87
+ NON_UNIQUE as non_unique,
88
+ INDEX_TYPE as type
89
+ FROM INFORMATION_SCHEMA.STATISTICS
90
+ WHERE TABLE_SCHEMA = ?
91
+ AND TABLE_NAME = ?
92
+ ORDER BY INDEX_NAME, SEQ_IN_INDEX
93
+ `;
94
+ const [rows] = await pool.query(query, [config.database, tableName]);
95
+ return rows.map(row => ({
96
+ name: row.name,
97
+ column: row.column,
98
+ unique: row.non_unique === 0,
99
+ type: row.type
100
+ }));
101
+ },
102
+ /**
103
+ * Get foreign key relationships for a specific table or all tables
104
+ * @param tableName - Name of the table (optional, if not provided returns all foreign keys)
105
+ * @param dbConfig - Optional database configuration
106
+ * @returns Array of foreign key information
107
+ */
108
+ async foreignKeys(tableName, dbConfig) {
109
+ const pool = await connectionManager_1.default.getPool(dbConfig);
110
+ const config = dbConfig || connectionManager_1.default.defaultConfig;
111
+ if (!config || !config.database) {
112
+ throw new Error('Database name is required for schema introspection');
113
+ }
114
+ let query = `
115
+ SELECT
116
+ TABLE_NAME as childTable,
117
+ REFERENCED_TABLE_NAME as parentTable,
118
+ CONSTRAINT_NAME as constraintName,
119
+ COLUMN_NAME as columnName,
120
+ REFERENCED_COLUMN_NAME as referencedColumnName
121
+ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
122
+ WHERE TABLE_SCHEMA = ?
123
+ AND REFERENCED_TABLE_NAME IS NOT NULL
124
+ `;
125
+ const params = [config.database];
126
+ if (tableName) {
127
+ query += ` AND (TABLE_NAME = ? OR REFERENCED_TABLE_NAME = ?)`;
128
+ params.push(tableName, tableName);
129
+ }
130
+ query += ` ORDER BY TABLE_NAME, ORDINAL_POSITION`;
131
+ const [rows] = await pool.query(query, params);
132
+ return rows;
133
+ },
134
+ /**
135
+ * Get the correct order to delete/truncate tables based on foreign key dependencies
136
+ * Uses topological sort to ensure child tables are deleted before parent tables
137
+ * @param dbConfig - Optional database configuration
138
+ * @returns Array of table names in deletion order (children first)
139
+ */
140
+ async deleteOrder(dbConfig) {
141
+ const foreignKeys = await this.foreignKeys(undefined, dbConfig);
142
+ // Build dependency graph
143
+ const graph = {};
144
+ for (const fk of foreignKeys) {
145
+ if (!graph[fk.childTable]) {
146
+ graph[fk.childTable] = [];
147
+ }
148
+ if (!graph[fk.childTable].includes(fk.parentTable)) {
149
+ graph[fk.childTable].push(fk.parentTable);
150
+ }
151
+ }
152
+ // Perform topological sort
153
+ const visited = new Set();
154
+ const result = [];
155
+ function visit(table) {
156
+ if (!visited.has(table)) {
157
+ visited.add(table);
158
+ const parents = graph[table] || [];
159
+ parents.forEach(visit);
160
+ result.push(table);
161
+ }
162
+ }
163
+ // Visit all child tables
164
+ Object.keys(graph).forEach(visit);
165
+ // Include all tables (both parents and children)
166
+ const allTables = new Set([
167
+ ...Object.keys(graph),
168
+ ...Object.values(graph).flat()
169
+ ]);
170
+ // Add orphan tables (tables with no dependencies)
171
+ for (const table of allTables) {
172
+ if (!visited.has(table)) {
173
+ result.push(table);
174
+ }
175
+ }
176
+ // Reverse to get child-first order and remove duplicates
177
+ return [...new Set(result)].reverse();
178
+ }
179
+ };
180
+ exports.schema = schema;
181
+ exports.default = schema;
@@ -0,0 +1,9 @@
1
+ import TransactionCRUD from './TransactionCRUD';
2
+ declare const transactionManager: {
3
+ setInstance: (instance: TransactionCRUD) => void;
4
+ getInstance: () => TransactionCRUD | null;
5
+ clearInstance: () => void;
6
+ hasActiveTransaction: () => boolean;
7
+ };
8
+ export default transactionManager;
9
+ export { transactionManager };
@@ -1,21 +1,21 @@
1
- 'use strict';
2
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transactionManager = void 0;
3
4
  let transactionInstance = null;
4
-
5
- module.exports = {
5
+ const transactionManager = {
6
6
  setInstance: (instance) => {
7
7
  transactionInstance = instance;
8
8
  },
9
-
10
9
  getInstance: () => {
11
10
  return transactionInstance || null;
12
11
  },
13
-
14
12
  clearInstance: () => {
15
13
  transactionInstance = null;
16
14
  },
17
-
18
15
  hasActiveTransaction: () => {
16
+ // Accessing private property via any cast since it's an internal check
19
17
  return transactionInstance !== null && transactionInstance.transactionActive;
20
18
  }
21
19
  };
20
+ exports.transactionManager = transactionManager;
21
+ exports.default = transactionManager;
@@ -0,0 +1,124 @@
1
+ export interface DbConfig {
2
+ host?: string;
3
+ user?: string;
4
+ password?: string;
5
+ database?: string;
6
+ port?: number;
7
+ connectionLimit?: number;
8
+ [key: string]: any;
9
+ }
10
+ export interface Logger {
11
+ info: (...args: any[]) => void;
12
+ error: (...args: any[]) => void;
13
+ warn: (...args: any[]) => void;
14
+ }
15
+ export interface JoinOptions {
16
+ type?: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
17
+ table: string;
18
+ alias?: string;
19
+ on: string | string[];
20
+ }
21
+ export interface WhereConditions {
22
+ [key: string]: any;
23
+ }
24
+ export interface SelectOptions {
25
+ table: string;
26
+ fields?: string | string[];
27
+ joins?: JoinOptions[];
28
+ where?: WhereConditions;
29
+ orderBy?: string;
30
+ limit?: number;
31
+ offset?: number;
32
+ groupBy?: string;
33
+ having?: string;
34
+ alias?: string;
35
+ forUpdate?: boolean;
36
+ }
37
+ export interface UpdateOptions {
38
+ table: string;
39
+ data: Record<string, any>;
40
+ where?: WhereConditions;
41
+ }
42
+ export interface DeleteOptions {
43
+ table: string;
44
+ where: WhereConditions;
45
+ }
46
+ export interface ColumnInfo {
47
+ name: string;
48
+ type: string;
49
+ nullable: boolean;
50
+ key: string;
51
+ default: string | null;
52
+ extra: string;
53
+ }
54
+ export interface IndexInfo {
55
+ name: string;
56
+ column: string;
57
+ unique: boolean;
58
+ type: string;
59
+ }
60
+ export interface ForeignKeyInfo {
61
+ childTable: string;
62
+ parentTable: string;
63
+ constraintName: string;
64
+ columnName: string;
65
+ referencedColumnName: string;
66
+ }
67
+ export interface DependencyGraph {
68
+ [childTable: string]: string[];
69
+ }
70
+ export interface QueryMetric {
71
+ query: string;
72
+ duration: number;
73
+ timestamp: number;
74
+ type: 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'OTHER';
75
+ params?: any[];
76
+ }
77
+ export interface ConnectionPoolStats {
78
+ activeConnections: number;
79
+ idleConnections: number;
80
+ totalConnections: number;
81
+ waitingRequests: number;
82
+ }
83
+ export interface PerformanceStats {
84
+ enabled: boolean;
85
+ totalQueries: number;
86
+ averageQueryTime: number;
87
+ slowestQueries: QueryMetric[];
88
+ queryCountByType: {
89
+ SELECT: number;
90
+ INSERT: number;
91
+ UPDATE: number;
92
+ DELETE: number;
93
+ OTHER: number;
94
+ };
95
+ startTime: number;
96
+ uptime: number;
97
+ }
98
+ export interface BulkInsertOptions {
99
+ batchSize?: number;
100
+ ignore?: boolean;
101
+ }
102
+ export interface BulkInsertResult {
103
+ totalInserted: number;
104
+ batches: number;
105
+ firstInsertId?: number;
106
+ lastInsertId?: number;
107
+ }
108
+ export interface UpsertOptions {
109
+ conflictKey: string | string[];
110
+ updateFields?: string[];
111
+ }
112
+ export interface UpsertResult {
113
+ action: 'inserted' | 'updated';
114
+ affectedRows: number;
115
+ insertId?: number;
116
+ }
117
+ export interface BulkUpsertOptions extends BulkInsertOptions {
118
+ conflictKey: string | string[];
119
+ updateFields?: string[];
120
+ }
121
+ export interface BulkUpsertResult {
122
+ totalAffected: number;
123
+ batches: number;
124
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "mysql-orm-lite",
3
- "version": "1.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "A lightweight ORM for MySQL with connection pooling, query builder, and transaction support",
5
- "main": "index.js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "private": false,
7
8
  "scripts": {
9
+ "build": "tsc",
10
+ "prepublishOnly": "npm run build",
8
11
  "test": "echo \"Error: no test specified\" && exit 1"
9
12
  },
10
13
  "keywords": [
@@ -36,6 +39,9 @@
36
39
  "mysql2": "^3.0.0"
37
40
  },
38
41
  "devDependencies": {
39
- "mysql2": "^3.11.5"
42
+ "@types/node": "^25.2.1",
43
+ "mysql2": "^3.11.5",
44
+ "ts-node": "^10.9.2",
45
+ "typescript": "^5.9.3"
40
46
  }
41
- }
47
+ }
package/src/index.ts ADDED
@@ -0,0 +1,76 @@
1
+ import connectionManager from './lib/connectionManager';
2
+ import * as crud from './lib/crud';
3
+ import TransactionCRUD from './lib/TransactionCRUD';
4
+ import transactionManager from './lib/transactionManager';
5
+ import schema from './lib/schema';
6
+ import performanceMonitor from './lib/performanceMonitor';
7
+
8
+ export {
9
+ connectionManager,
10
+ transactionManager,
11
+ TransactionCRUD,
12
+ schema,
13
+ performanceMonitor
14
+ };
15
+
16
+ // CRUD Operations (Non-transactional)
17
+ export const find = crud.find;
18
+ export const findCount = crud.findCount;
19
+ export const insert = crud.insert;
20
+ export const update = crud.update;
21
+ export const _delete = crud.delete;
22
+ export { _delete as delete };
23
+
24
+ // Bulk Operations
25
+ export const bulkInsert = crud.bulkInsert;
26
+ export const upsert = crud.upsert;
27
+ export const bulkUpsert = crud.bulkUpsert;
28
+
29
+ // Query Builder - Full names
30
+ export const buildAndExecuteSelectQuery = crud.buildAndExecuteSelectQuery;
31
+ export const buildAndExecuteUpdateQuery = crud.buildAndExecuteUpdateQuery;
32
+ export const buildAndExecuteDeleteQuery = crud.buildAndExecuteDeleteQuery;
33
+
34
+ // Query Builder - Alternative shorter names
35
+ export const select = crud.select;
36
+ export const findWhere = crud.findWhere;
37
+ export const query = crud.query;
38
+ export const updateWhere = crud.updateWhere;
39
+ export const updateQuery = crud.updateQuery;
40
+ export const deleteWhere = crud.deleteWhere;
41
+ export const remove = crud.remove;
42
+
43
+ // Utility exports
44
+ export const utils = crud.utils;
45
+
46
+ // Convenience method to create transaction
47
+ export const createTransaction = () => new TransactionCRUD();
48
+
49
+ // Default export for CJS compatibility and convenience
50
+ export default {
51
+ connectionManager,
52
+ transactionManager,
53
+ TransactionCRUD,
54
+ schema,
55
+ performanceMonitor,
56
+ find,
57
+ findCount,
58
+ insert,
59
+ update,
60
+ delete: _delete,
61
+ buildAndExecuteSelectQuery,
62
+ buildAndExecuteUpdateQuery,
63
+ buildAndExecuteDeleteQuery,
64
+ select,
65
+ findWhere,
66
+ query,
67
+ updateWhere,
68
+ updateQuery,
69
+ deleteWhere,
70
+ remove,
71
+ utils,
72
+ createTransaction,
73
+ bulkInsert,
74
+ upsert,
75
+ bulkUpsert
76
+ };
@@ -1,8 +1,12 @@
1
- 'use strict';
2
- const connectionManager = require('./connectionManager');
3
- const crudUtils = require('./crud').utils;
1
+ import connectionManager from './connectionManager';
2
+ import { utils as crudUtils } from './crud';
3
+ import { DbConfig, SelectOptions, UpdateOptions, DeleteOptions } from '../types';
4
4
 
5
5
  class TransactionCRUD {
6
+ private connection: any = null;
7
+ private transactionActive: boolean = false;
8
+ public debug: boolean = false;
9
+
6
10
  constructor() {
7
11
  this.connection = null;
8
12
  this.transactionActive = false;
@@ -11,9 +15,9 @@ class TransactionCRUD {
11
15
 
12
16
  /**
13
17
  * Initialize a transaction
14
- * @param {Object} dbConfig - Database configuration (optional)
18
+ * @param dbConfig - Database configuration (optional)
15
19
  */
16
- async init(dbConfig) {
20
+ async init(dbConfig?: DbConfig): Promise<any> {
17
21
  const logger = connectionManager.getLogger();
18
22
  try {
19
23
  const pool = await connectionManager.getPool(dbConfig);
@@ -37,7 +41,7 @@ class TransactionCRUD {
37
41
  /**
38
42
  * Execute a query within the transaction
39
43
  */
40
- async executeQuery(query, params = [], operation = 'TRANS_QUERY') {
44
+ async executeQuery(query: string, params: any[] = [], operation = 'TRANS_QUERY'): Promise<any> {
41
45
  if (!this.connection || !this.transactionActive) {
42
46
  throw new Error('No active transaction. Call init() first.');
43
47
  }
@@ -53,7 +57,7 @@ class TransactionCRUD {
53
57
  }
54
58
 
55
59
  return results;
56
- } catch (error) {
60
+ } catch (error: any) {
57
61
  logger.error(`${operation} Failed: ${error.message}`);
58
62
  logger.error(`Query: ${query}`);
59
63
  throw error;
@@ -63,7 +67,7 @@ class TransactionCRUD {
63
67
  /**
64
68
  * Commit the transaction
65
69
  */
66
- async commit() {
70
+ async commit(): Promise<void> {
67
71
  if (!this.connection || !this.transactionActive) {
68
72
  throw new Error('No active transaction to commit');
69
73
  }
@@ -84,7 +88,7 @@ class TransactionCRUD {
84
88
  /**
85
89
  * Rollback the transaction
86
90
  */
87
- async rollback() {
91
+ async rollback(): Promise<void> {
88
92
  if (!this.connection) return;
89
93
 
90
94
  const logger = connectionManager.getLogger();
@@ -98,7 +102,7 @@ class TransactionCRUD {
98
102
  }
99
103
  }
100
104
 
101
- _cleanup() {
105
+ private _cleanup(): void {
102
106
  if (this.connection) {
103
107
  this.connection.release();
104
108
  this.connection = null;
@@ -108,11 +112,11 @@ class TransactionCRUD {
108
112
 
109
113
  // CRUD Methods
110
114
 
111
- async find(query, params = []) {
115
+ async find(query: string, params: any[] = []): Promise<any[]> {
112
116
  return await this.executeQuery(query, params, 'TRANS_FIND');
113
117
  }
114
118
 
115
- async insert(table, data) {
119
+ async insert(table: string, data: Record<string, any>): Promise<any> {
116
120
  if (!table || !data) throw new Error('Invalid table or data');
117
121
  const fields = Object.keys(data);
118
122
  const values = Object.values(data);
@@ -123,7 +127,7 @@ class TransactionCRUD {
123
127
  return result.insertId;
124
128
  }
125
129
 
126
- async update(table, data, query) {
130
+ async update(table: string, data: Record<string, any>, query: string): Promise<number> {
127
131
  if (!query || !query.toLowerCase().includes('where')) throw new Error('Update requires WHERE');
128
132
 
129
133
  const { setFields, params } = crudUtils.prepareUpdateParams(data);
@@ -133,14 +137,14 @@ class TransactionCRUD {
133
137
  return result.affectedRows;
134
138
  }
135
139
 
136
- async delete(query, table) {
140
+ async delete(query: string, table?: string): Promise<number> {
137
141
  if (!query || !query.toLowerCase().includes('where')) throw new Error('Delete requires WHERE');
138
142
  const sql = table ? `DELETE FROM ${table} ${query}` : query;
139
143
  const result = await this.executeQuery(sql, [], 'TRANS_DELETE');
140
144
  return result.affectedRows;
141
145
  }
142
146
 
143
- async buildAndExecuteSelectQuery(options = {}) {
147
+ async buildAndExecuteSelectQuery(options: SelectOptions): Promise<any[]> {
144
148
  const logger = connectionManager.getLogger();
145
149
  try {
146
150
  const { query, params } = crudUtils._buildSelectQuery(options);
@@ -151,7 +155,7 @@ class TransactionCRUD {
151
155
  }
152
156
  }
153
157
 
154
- async buildAndExecuteUpdateQuery(options = {}) {
158
+ async buildAndExecuteUpdateQuery(options: UpdateOptions): Promise<number> {
155
159
  const logger = connectionManager.getLogger();
156
160
  try {
157
161
  const { query, params } = crudUtils._buildUpdateQuery(options);
@@ -163,7 +167,7 @@ class TransactionCRUD {
163
167
  }
164
168
  }
165
169
 
166
- async buildAndExecuteDeleteQuery(options = {}) {
170
+ async buildAndExecuteDeleteQuery(options: DeleteOptions): Promise<number> {
167
171
  const logger = connectionManager.getLogger();
168
172
  try {
169
173
  const { query, params } = crudUtils._buildDeleteQuery(options);
@@ -176,38 +180,39 @@ class TransactionCRUD {
176
180
  }
177
181
 
178
182
  // Alternative shorter method names (aliases)
179
- async select(options) {
183
+ async select(options: SelectOptions): Promise<any[]> {
180
184
  return this.buildAndExecuteSelectQuery(options);
181
185
  }
182
186
 
183
- async findWhere(options) {
187
+ async findWhere(options: SelectOptions): Promise<any[]> {
184
188
  return this.buildAndExecuteSelectQuery(options);
185
189
  }
186
190
 
187
- async findForUpdate(options) {
191
+ async findForUpdate(options: SelectOptions): Promise<any[]> {
188
192
  options.forUpdate = true;
189
193
  return this.buildAndExecuteSelectQuery(options);
190
194
  }
191
195
 
192
- async query(options) {
196
+ async query(options: SelectOptions): Promise<any[]> {
193
197
  return this.buildAndExecuteSelectQuery(options);
194
198
  }
195
199
 
196
- async updateWhere(options) {
200
+ async updateWhere(options: UpdateOptions): Promise<number> {
197
201
  return this.buildAndExecuteUpdateQuery(options);
198
202
  }
199
203
 
200
- async updateQuery(options) {
204
+ async updateQuery(options: UpdateOptions): Promise<number> {
201
205
  return this.buildAndExecuteUpdateQuery(options);
202
206
  }
203
207
 
204
- async deleteWhere(options) {
208
+ async deleteWhere(options: DeleteOptions): Promise<number> {
205
209
  return this.buildAndExecuteDeleteQuery(options);
206
210
  }
207
211
 
208
- async remove(options) {
212
+ async remove(options: DeleteOptions): Promise<number> {
209
213
  return this.buildAndExecuteDeleteQuery(options);
210
214
  }
211
215
  }
212
216
 
213
- module.exports = TransactionCRUD;
217
+ export default TransactionCRUD;
218
+ export { TransactionCRUD };