@mlagie/sql-connector 2.0.1 → 2.0.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/eslint.config.mjs +26 -1
- package/package.json +2 -1
- package/releases/2.0.2.md +20 -0
- package/src/models/Model.js +21 -53
- package/src/models/ModelInstance.js +26 -35
- package/src/utils/formatObject.js +1 -1
package/eslint.config.mjs
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
1
2
|
import security from "eslint-plugin-security";
|
|
2
3
|
|
|
3
4
|
export default [
|
|
4
5
|
{
|
|
6
|
+
ignores: ["eslint.config.mjs"]
|
|
7
|
+
},
|
|
8
|
+
js.configs.recommended,
|
|
9
|
+
{
|
|
10
|
+
files: ["**/*.js"],
|
|
11
|
+
languageOptions: {
|
|
12
|
+
sourceType: "commonjs",
|
|
13
|
+
globals: {
|
|
14
|
+
console: "readonly",
|
|
15
|
+
exports: "readonly",
|
|
16
|
+
module: "readonly",
|
|
17
|
+
process: "readonly",
|
|
18
|
+
require: "readonly",
|
|
19
|
+
__dirname: "readonly",
|
|
20
|
+
__filename: "readonly"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
5
23
|
plugins: {
|
|
6
24
|
security
|
|
7
25
|
},
|
|
8
26
|
rules: {
|
|
9
|
-
...security.configs.recommended.rules
|
|
27
|
+
...security.configs.recommended.rules,
|
|
28
|
+
"no-unused-vars": [
|
|
29
|
+
"error",
|
|
30
|
+
{
|
|
31
|
+
argsIgnorePattern: "^(?:_|resolve|reject)$",
|
|
32
|
+
varsIgnorePattern: "^_$"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
10
35
|
}
|
|
11
36
|
}
|
|
12
37
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mlagie/sql-connector",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Le module sql-connector permet de gérer les connexions à une base de données MySQL, de définir des schémas de tables, et d'interagir avec les données de manière simple et efficace.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"mysql2": "3.22.5"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
+
"@eslint/js": "^10.0.1",
|
|
42
43
|
"eslint": "^10.6.0",
|
|
43
44
|
"eslint-plugin-security": "^4.0.1"
|
|
44
45
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Release v2.0.2 — Performance Optimization & Code Cleanup
|
|
2
|
+
|
|
3
|
+
This patch release focuses on optimizing the internal runtime footprint and improving overall execution performance by removing legacy, unused code paths and dependencies.
|
|
4
|
+
|
|
5
|
+
## What Was Improved
|
|
6
|
+
|
|
7
|
+
* **Dead Code Elimination:** Removed unused functions, legacy variables, and obsolete logic that were lingering from previous architecture overhauls (such as the old `serveur` logger reference).
|
|
8
|
+
* **Performance Boost:** Cleaning up these elements reduces CPU overhead and memory usage during runtime model instantiation and schema synchronization.
|
|
9
|
+
* **Code Maintenance:** Streamlined internal loops and conditional structures to ensure the ORM remains fast, lightweight, and maintainable.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Component Impact
|
|
14
|
+
|
|
15
|
+
| Impacted Area | Description | Status |
|
|
16
|
+
| :--- | :--- | :--- |
|
|
17
|
+
| **ModelInstance & Models** | Removal of unused references and obsolete properties | **Optimized** |
|
|
18
|
+
| **Runtime Footprint** | Decreased execution overhead during database mappings | **Improved** |
|
|
19
|
+
|
|
20
|
+
*This is a fully backward-compatible patch. Upgrading is highly recommended to benefit from the performance improvements.* `npm update @mlagie/sql-connector`
|
package/src/models/Model.js
CHANGED
|
@@ -54,35 +54,6 @@ function formatDefaultSql(defaultValue, fieldType) {
|
|
|
54
54
|
return `DEFAULT "${String(defaultValue).replace(/"/g, '\\"')}"`;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
function normalizeDefaultValue(defaultValue, fieldType) {
|
|
58
|
-
if (defaultValue === undefined) return null;
|
|
59
|
-
if (defaultValue === null) return "null";
|
|
60
|
-
|
|
61
|
-
if (typeof defaultValue === "function") {
|
|
62
|
-
if (isDateLikeType(fieldType)) return "current_timestamp";
|
|
63
|
-
return normalizeDefaultValue(defaultValue(), fieldType);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (defaultValue instanceof Date) {
|
|
67
|
-
return defaultValue.toISOString().slice(0, 19).replace("T", " ");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (isSqlTemporalDefault(defaultValue)) return "current_timestamp";
|
|
71
|
-
if (typeof defaultValue === "boolean") return defaultValue ? "1" : "0";
|
|
72
|
-
if (typeof defaultValue === "object") return JSON.stringify(defaultValue);
|
|
73
|
-
|
|
74
|
-
return String(defaultValue);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function normalizeDbDefaultValue(defaultValue) {
|
|
78
|
-
if (defaultValue === null || defaultValue === undefined) return null;
|
|
79
|
-
|
|
80
|
-
const normalizedValue = String(defaultValue).trim();
|
|
81
|
-
if (/^current_timestamp(\(\))?$/i.test(normalizedValue)) return "current_timestamp";
|
|
82
|
-
if (/^now\(\)$/i.test(normalizedValue)) return "current_timestamp";
|
|
83
|
-
return normalizedValue;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
57
|
function generateValueSQL(value) {
|
|
87
58
|
return value.map(item => {
|
|
88
59
|
if (item === null) return 'NULL';
|
|
@@ -121,7 +92,7 @@ function getColumnDefinition(fieldName, field) {
|
|
|
121
92
|
}
|
|
122
93
|
|
|
123
94
|
const fieldType = getFieldType(field);
|
|
124
|
-
let colDef
|
|
95
|
+
let colDef;
|
|
125
96
|
|
|
126
97
|
if (Array.isArray(field.enum) && field.enum.length > 0) {
|
|
127
98
|
const enumValues = field.enum.map(v => `'${v.replace(/'/g, "''")}'`).join(", ");
|
|
@@ -166,9 +137,9 @@ class Model {
|
|
|
166
137
|
* @returns {Promise<void>}
|
|
167
138
|
*/
|
|
168
139
|
static async syncAllTables() {
|
|
169
|
-
// Dépendances : {table: [tables dont elle dépend]}
|
|
170
140
|
const dependencies = {};
|
|
171
141
|
const modelMap = {};
|
|
142
|
+
|
|
172
143
|
for (const model of Model.pendingModels) {
|
|
173
144
|
modelMap[model.name] = model;
|
|
174
145
|
dependencies[model.name] = [];
|
|
@@ -181,8 +152,6 @@ class Model {
|
|
|
181
152
|
}
|
|
182
153
|
|
|
183
154
|
const conn = getConnexion();
|
|
184
|
-
const [dbTablesRows] = await conn.promise().query("SHOW TABLES");
|
|
185
|
-
const dbTables = dbTablesRows.map(row => Object.values(row)[0]);
|
|
186
155
|
|
|
187
156
|
const sorted = [];
|
|
188
157
|
const visited = {};
|
|
@@ -342,18 +311,17 @@ class Model {
|
|
|
342
311
|
|
|
343
312
|
const query = `SELECT ${buildSelect(select)} FROM ${this.name}${joinClause} ${buildQueryParts(options)}`;
|
|
344
313
|
|
|
345
|
-
|
|
346
|
-
await getConnexion().promise().query(query)
|
|
347
|
-
|
|
348
|
-
|
|
314
|
+
try {
|
|
315
|
+
const result = await getConnexion().promise().query(query);
|
|
316
|
+
const rows = result && Array.isArray(result) ? result[0] : result;
|
|
317
|
+
|
|
318
|
+
if (!rows || rows.length === 0) return [];
|
|
349
319
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
});
|
|
356
|
-
});
|
|
320
|
+
return rows.map(row => new ModelInstance(this.name, row, this.schema));
|
|
321
|
+
} catch (err) {
|
|
322
|
+
error(`Error executing auto-prefixed find: ${err}`);
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
357
325
|
}
|
|
358
326
|
|
|
359
327
|
/**
|
|
@@ -372,16 +340,16 @@ class Model {
|
|
|
372
340
|
* @throws {Error} Throws an error if query execution fails.
|
|
373
341
|
*/
|
|
374
342
|
async customRequest(custom, custom_err_name = "") {
|
|
375
|
-
|
|
376
|
-
await getConnexion().promise().query(custom)
|
|
377
|
-
if (rows.length == 0) return resolve(0);
|
|
343
|
+
try {
|
|
344
|
+
const rows = await getConnexion().promise().query(custom);
|
|
378
345
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
});
|
|
384
|
-
|
|
346
|
+
if (rows.length == 0) return 0;
|
|
347
|
+
|
|
348
|
+
return new ModelInstance(this.name, rows, this.schema);
|
|
349
|
+
} catch (err) {
|
|
350
|
+
error(`Error executing query ${custom_err_name}: ${err}`);
|
|
351
|
+
throw err;
|
|
352
|
+
}
|
|
385
353
|
}
|
|
386
354
|
|
|
387
355
|
/**
|
|
@@ -3,7 +3,6 @@ const { getConnexion } = require("../db/connexion");
|
|
|
3
3
|
const formatObject = require("../utils/formatObject");
|
|
4
4
|
const generateCondition = require("../utils/generateCondition");
|
|
5
5
|
const util = require("util");
|
|
6
|
-
const { serveur } = require("@mlagie/logger");
|
|
7
6
|
const { getSafe, setSafe } = require("../utils/security/safe");
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -45,7 +44,7 @@ class ModelInstance {
|
|
|
45
44
|
get: () => {
|
|
46
45
|
const val = getSafe(row, key);
|
|
47
46
|
if (typeof val === 'string' && val.trim().startsWith('{') && val.trim().endsWith('}')) {
|
|
48
|
-
try { return JSON.parse(val); } catch
|
|
47
|
+
try { return JSON.parse(val); } catch { return val; }
|
|
49
48
|
}
|
|
50
49
|
return val;
|
|
51
50
|
},
|
|
@@ -99,13 +98,15 @@ class ModelInstance {
|
|
|
99
98
|
if (typeof rawRec === 'string') {
|
|
100
99
|
try {
|
|
101
100
|
rawRec = JSON.parse(rawRec);
|
|
102
|
-
} catch
|
|
101
|
+
} catch {
|
|
102
|
+
rawRec = recordsArray;
|
|
103
|
+
}
|
|
103
104
|
}
|
|
104
105
|
const rec = rawRec;
|
|
105
106
|
|
|
106
107
|
const schemaDict = this.schema && this.schema.schemaDict ? this.schema.schemaDict : null;
|
|
107
108
|
if (schemaDict) {
|
|
108
|
-
const pkKeys = Object.entries(schemaDict).filter(([
|
|
109
|
+
const pkKeys = Object.entries(schemaDict).filter(([, v]) => v && v.primary_key === true).map(([k]) => k);
|
|
109
110
|
if (pkKeys.length > 0) {
|
|
110
111
|
const pkObj = {};
|
|
111
112
|
for (const k of pkKeys) {
|
|
@@ -115,10 +116,11 @@ class ModelInstance {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
if (!whereClause) whereClause = generateCondition(formatObject(rec), false, this.schema);
|
|
118
|
-
} catch
|
|
119
|
-
|
|
119
|
+
} catch {
|
|
120
|
+
const originalFallbackRec = this.getRecordData();
|
|
121
|
+
let fallbackRec = originalFallbackRec;
|
|
120
122
|
if (Array.isArray(fallbackRec)) fallbackRec = fallbackRec[0];
|
|
121
|
-
if (typeof fallbackRec === 'string') { try { fallbackRec = JSON.parse(fallbackRec); } catch
|
|
123
|
+
if (typeof fallbackRec === 'string') { try { fallbackRec = JSON.parse(fallbackRec); } catch { fallbackRec = originalFallbackRec; } }
|
|
122
124
|
whereClause = generateCondition(formatObject(fallbackRec), false, this.schema);
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -152,17 +154,12 @@ class ModelInstance {
|
|
|
152
154
|
async delete(filter) {
|
|
153
155
|
const sql_request = `DELETE FROM ${this.name} WHERE ${generateCondition(formatObject(filter))}`;
|
|
154
156
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (rows[1] != undefined) return resolve(0);
|
|
159
|
-
|
|
160
|
-
resolve(1);
|
|
161
|
-
}).catch((err) => {
|
|
162
|
-
error(`Error executing query delete: ${err}`);
|
|
163
|
-
return 0;
|
|
164
|
-
});
|
|
157
|
+
const rows = await getConnexion().promise().query(sql_request).catch((err) => {
|
|
158
|
+
error(`Error executing query delete: ${err}`);
|
|
159
|
+
throw err;
|
|
165
160
|
});
|
|
161
|
+
|
|
162
|
+
return rows[1] != undefined ? 0 : 1;
|
|
166
163
|
}
|
|
167
164
|
|
|
168
165
|
/**
|
|
@@ -173,16 +170,12 @@ class ModelInstance {
|
|
|
173
170
|
async deleteOne() {
|
|
174
171
|
const sql_request = `DELETE FROM ${this.name} WHERE ${generateCondition(formatObject(this.getRecordData()))}`;
|
|
175
172
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
resolve(1);
|
|
181
|
-
}).catch((err) => {
|
|
182
|
-
error(`Error executing query deleteOne: ${err}`);
|
|
183
|
-
return 0;
|
|
184
|
-
});
|
|
173
|
+
const rows = await getConnexion().promise().query(sql_request).catch((err) => {
|
|
174
|
+
error(`Error executing query deleteOne: ${err}`);
|
|
175
|
+
throw err;
|
|
185
176
|
});
|
|
177
|
+
|
|
178
|
+
return rows[1] != undefined ? 0 : 1;
|
|
186
179
|
}
|
|
187
180
|
|
|
188
181
|
/**
|
|
@@ -192,16 +185,14 @@ class ModelInstance {
|
|
|
192
185
|
* @throws {Error} Throws an error if query execution fails.
|
|
193
186
|
*/
|
|
194
187
|
async customRequest(custom) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
resolve(new ModelInstance(this.name, rows, this.schema)).data;
|
|
200
|
-
}).catch((err) => {
|
|
201
|
-
error(`Error executing query: ${err}`);
|
|
202
|
-
return;
|
|
203
|
-
});
|
|
188
|
+
const rows = await getConnexion().promise().query(custom).catch((err) => {
|
|
189
|
+
error(`Error executing query: ${err}`);
|
|
190
|
+
throw err;
|
|
204
191
|
});
|
|
192
|
+
|
|
193
|
+
if (rows.length == 0) return 0;
|
|
194
|
+
|
|
195
|
+
return new ModelInstance(this.name, rows, this.schema).data;
|
|
205
196
|
}
|
|
206
197
|
}
|
|
207
198
|
|
|
@@ -2,7 +2,7 @@ const { getSafe, setSafe } = require("./security/safe");
|
|
|
2
2
|
|
|
3
3
|
module.exports = function (obj) {
|
|
4
4
|
for (const key in obj) {
|
|
5
|
-
if (
|
|
5
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
6
6
|
const value = getSafe(obj, key);
|
|
7
7
|
if (value instanceof Date) {
|
|
8
8
|
// convert Date to MySQL DATETIME (no timezone)
|