@mlagie/sql-connector 2.0.13 → 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.
package/index.d.ts CHANGED
@@ -12,8 +12,18 @@ export type SqlType =
12
12
  | "Text"
13
13
  | "DateTime"
14
14
  | "Timestamp";
15
+ export type SqlTypeConstructor =
16
+ | StringConstructor
17
+ | NumberConstructor
18
+ | BooleanConstructor
19
+ | DateConstructor
20
+ | ObjectConstructor
21
+ | ArrayConstructor;
22
+
23
+ export type SchemaTypeInput = SqlType | { name: SqlType } | SqlTypeConstructor;
24
+
15
25
  export interface SchemaField {
16
- type: SqlType | { name: SqlType };
26
+ type: SchemaTypeInput;
17
27
  length?: number;
18
28
  required?: boolean;
19
29
  default?: any | SqlType | "CurrentTimestamp";
@@ -29,6 +39,71 @@ export interface SchemaDict {
29
39
  [key: string]: SchemaField;
30
40
  }
31
41
 
42
+ type NormalizeSqlType<T> =
43
+ T extends { name: infer Name }
44
+ ? NormalizeSqlType<Name>
45
+ : T extends StringConstructor
46
+ ? "String"
47
+ : T extends NumberConstructor
48
+ ? "Number"
49
+ : T extends BooleanConstructor
50
+ ? "Boolean"
51
+ : T extends DateConstructor
52
+ ? "Date"
53
+ : T extends ObjectConstructor
54
+ ? "Object"
55
+ : T extends ArrayConstructor
56
+ ? "Array"
57
+ : T extends SqlType
58
+ ? T
59
+ : never;
60
+
61
+ type InferSqlType<T> =
62
+ NormalizeSqlType<T> extends "String" | "Text"
63
+ ? string
64
+ : NormalizeSqlType<T> extends "Number" | "Float"
65
+ ? number
66
+ : NormalizeSqlType<T> extends "Boolean"
67
+ ? boolean
68
+ : NormalizeSqlType<T> extends "Date" | "DateTime" | "Timestamp" | "Now"
69
+ ? Date
70
+ : NormalizeSqlType<T> extends "Object"
71
+ ? Record<string, unknown>
72
+ : NormalizeSqlType<T> extends "Array"
73
+ ? unknown[]
74
+ : unknown;
75
+
76
+ type HasKey<T, K extends PropertyKey> = K extends keyof T ? true : false;
77
+
78
+ type InferFieldValue<TField> =
79
+ InferSqlType<TField extends { type: infer T } ? T : TField>;
80
+
81
+ type InferFieldNullable<TField> =
82
+ TField extends { required: true }
83
+ ? false
84
+ : TField extends { primary_key: true }
85
+ ? false
86
+ : TField extends { auto_increment: true }
87
+ ? false
88
+ : HasKey<TField, "default"> extends true
89
+ ? false
90
+ : true;
91
+
92
+ export type InferSchema<TSchema extends SchemaDict> = {
93
+ [K in keyof TSchema]: InferFieldNullable<TSchema[K]> extends true
94
+ ? InferFieldValue<TSchema[K]> | null
95
+ : InferFieldValue<TSchema[K]>;
96
+ };
97
+
98
+ export type SchemaLike<TSchema extends SchemaDict = SchemaDict> =
99
+ | Schema<TSchema>
100
+ | {
101
+ schemaDict: TSchema;
102
+ schema?: TSchema;
103
+ };
104
+
105
+ export type ModelRecord<TData extends Record<string, any> = Record<string, any>> = ModelInstance<TData> & TData;
106
+
32
107
  /**
33
108
  * Represents a database schema.
34
109
  *
@@ -44,9 +119,10 @@ export interface SchemaDict {
44
119
  * }
45
120
  * });
46
121
  */
47
- export class Schema {
48
- constructor(schemaDict: SchemaDict);
49
- schemaDict: SchemaDict;
122
+ export class Schema<TSchema extends SchemaDict = SchemaDict> {
123
+ constructor(schemaDict: TSchema);
124
+ schemaDict: TSchema;
125
+ schema: TSchema;
50
126
  }
51
127
 
52
128
  /**
@@ -87,12 +163,12 @@ export function logout(): Promise<void>;
87
163
  * Represents a database model.
88
164
  * @class
89
165
  */
90
- export class Model {
166
+ export class Model<TSchema extends SchemaDict = SchemaDict> {
91
167
  static sqlTypeMap: Record<SqlType, string>;
92
168
  static pendingModels: Model[];
93
169
  name: string;
94
- schema: Schema;
95
- constructor(name: string, schema: Schema);
170
+ schema: SchemaLike<TSchema>;
171
+ constructor(name: string, schema: SchemaLike<TSchema>);
96
172
  /**
97
173
  * Creates all tables in the correct order based on foreign keys.
98
174
  * @returns {Promise<void>}
@@ -104,7 +180,7 @@ export class Model {
104
180
  * @returns {Promise<Object>} A promise that resolves with the result of the insertion.
105
181
  * @throws {Error} Throws an error if the insert fails.
106
182
  */
107
- save(data: Record<string, any>): Promise<any>;
183
+ save(data: Partial<InferSchema<TSchema>>): Promise<any>;
108
184
  /**
109
185
  * Retrieves multiple rows from the table.
110
186
  * @param {Object} [options] - Query options (attributes, where, order, limit).
@@ -116,23 +192,23 @@ export class Model {
116
192
  */
117
193
  find(options?: {
118
194
  select?: string[];
119
- where?: Record<string, any>;
195
+ where?: Record<string, any> | Partial<InferSchema<TSchema>> | string;
120
196
  order?: [string, string][];
121
197
  limit?: number;
122
- }): Promise<any[]>;
198
+ }): Promise<Array<ModelRecord<InferSchema<TSchema>>>>;
123
199
  /**
124
200
  *
125
201
  * @param {Object} filter The filter criteria for the query. Should be an object where keys are column names and values are the values to filter by.
126
202
  * @returns {Promise<ModelInstance|number>} - A promise that resolves to a `ModelInstance` if a record is found, or `0` if no records match the filter.
127
203
  */
128
- count(filter?: Record<string, any>): Promise<any>;
204
+ count(filter?: Record<string, any> | Partial<InferSchema<TSchema>>): Promise<number>;
129
205
  /**
130
206
  * Runs a custom SQL_request query.
131
207
  * @param {string} custom The custom SQL_request query to execute.
132
208
  * @returns {Promise<void>} A promise that resolves when the query is executed.
133
209
  * @throws {Error} Throws an error if query execution fails.
134
210
  */
135
- customRequest(custom: string): Promise<any>;
211
+ customRequest<TResult extends Record<string, any> = InferSchema<TSchema>>(custom: string): Promise<ModelRecord<TResult> | 0>;
136
212
  /**
137
213
  * Deletes a record from the SQL table corresponding to the provided filter.
138
214
  *
@@ -143,7 +219,7 @@ export class Model {
143
219
  * or an instance of ModelInstance representing the deleted row.
144
220
  * @throws {Error} Throws an error if the SQL query fails.
145
221
  */
146
- delete(filter: Record<string, any>): Promise<number | ModelInstance>;
222
+ delete(filter: Record<string, any> | Partial<InferSchema<TSchema>>): Promise<number>;
147
223
  /**
148
224
  * Asynchronously drops a table if it exists in the database.
149
225
  *
@@ -181,11 +257,11 @@ export class Model {
181
257
  * Represents an instance of a database model.
182
258
  * @class
183
259
  */
184
- export class ModelInstance {
260
+ export class ModelInstance<TData extends Record<string, any> = Record<string, any>> {
185
261
  name: string;
186
- data: any;
187
- schema?: Schema;
188
- constructor(name: string, data: any, schema?: Schema);
262
+ data: TData;
263
+ schema?: SchemaLike<any>;
264
+ constructor(name: string, data: TData, schema?: SchemaLike<any>);
189
265
  /**
190
266
  * Updates a single entry in the database table.
191
267
  *
@@ -193,14 +269,14 @@ export class ModelInstance {
193
269
  * @returns {int} A promise that resolves with updated data.
194
270
  * @throws {Error} Throws an error if the update fails.
195
271
  */
196
- updateOne(model: Record<string, any>): Promise<number>;
272
+ updateOne(model: Partial<TData>): Promise<number>;
197
273
  /**
198
274
  * Deletes a single entry in the database table.
199
275
  * @param {Object} model An object containing the key-value pairs to use for deletion.
200
276
  * @returns {Promise<Object>} A promise that resolves with the data deleted.
201
277
  * @throws {Error} Throws an error if the deletion fails.
202
278
  */
203
- delete(filter: Record<string, any>): Promise<number | ModelInstance>;
279
+ delete(filter: Record<string, any>): Promise<number>;
204
280
  /**
205
281
  * Deletes a single entry in the database table based on the instance data.
206
282
  * @returns {Promise<number>} A promise that resolves to the number of rows deleted.
@@ -213,7 +289,7 @@ export class ModelInstance {
213
289
  * @returns {Promise<void>} A promise that resolves when the query is executed.
214
290
  * @throws {Error} Throws an error if query execution fails.
215
291
  */
216
- customRequest(custom: string): Promise<any>;
292
+ customRequest<TResult = any>(custom: string): Promise<TResult>;
217
293
  }
218
294
 
219
295
  export const client: Record<string, any>;
package/package.json CHANGED
@@ -1,8 +1,15 @@
1
1
  {
2
2
  "name": "@mlagie/sql-connector",
3
- "version": "2.0.13",
3
+ "version": "2.1.0",
4
4
  "description": "The sql-connector module allows you to manage connections to a MySQL database, define table schemas, and interact with data in a simple and efficient way.",
5
5
  "main": "index.js",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./index.d.ts",
9
+ "require": "./index.js",
10
+ "default": "./index.js"
11
+ }
12
+ },
6
13
  "files": [
7
14
  "src",
8
15
  "docs",
@@ -44,6 +51,13 @@
44
51
  "author": "lagie-marin",
45
52
  "license": "MIT",
46
53
  "types": "index.d.ts",
54
+ "typesVersions": {
55
+ "*": {
56
+ "*": [
57
+ "index.d.ts"
58
+ ]
59
+ }
60
+ },
47
61
  "type": "commonjs",
48
62
  "bugs": {
49
63
  "url": "https://github.com/mlagie/sql-connector/issues"
@@ -51,8 +65,8 @@
51
65
  "homepage": "https://github.com/mlagie/sql-connector#readme",
52
66
  "private": false,
53
67
  "dependencies": {
54
- "@mlagie/logger": "1.0.2",
55
- "mysql2": "3.23.1"
68
+ "@mlagie/logger": "1.0.5",
69
+ "mysql2": "3.23.2"
56
70
  },
57
71
  "devDependencies": {
58
72
  "@eslint/js": "^10.0.1",
@@ -306,16 +306,30 @@ class Model {
306
306
  /**
307
307
  * Counts the number of records matching the given filter.
308
308
  * @param {Object} filter The filter criteria for the query. Should be an object where keys are column names and values are the values to filter by.
309
- * @returns {Promise<ModelInstance|number>} - A promise that resolves to a `ModelInstance` if a record is found, or `0` if no records match the filter.
309
+ * @returns {Promise<number>} - A promise that resolves to the number of matching records.
310
310
  */
311
311
  async count(filter) {
312
- return this.customRequest(`SELECT COUNT(*) as count FROM ${escapeIdentifier(this.name)} ${filter != undefined ? `WHERE ${generateCondition(formatObject(filter))}` : ""}`, "count");
312
+ try {
313
+ const rows = await getConnexion().promise().execute(`SELECT COUNT(*) as count FROM ${escapeIdentifier(this.name)} ${filter != undefined ? `WHERE ${generateCondition(formatObject(filter))}` : ""}`);
314
+ const resultRows = rows && Array.isArray(rows) ? rows[0] : [];
315
+
316
+ if (!resultRows || resultRows.length === 0) return 0;
317
+
318
+ const firstRow = resultRows[0];
319
+ if (!firstRow || typeof firstRow !== "object") return Number(firstRow) || 0;
320
+
321
+ const countValue = firstRow.count ?? firstRow["COUNT(*)"] ?? firstRow[Object.keys(firstRow)[0]];
322
+ return Number(countValue) || 0;
323
+ } catch (err) {
324
+ error(`Error executing query count: ${err}`);
325
+ throw err;
326
+ }
313
327
  }
314
328
 
315
329
  /**
316
330
  * Runs a custom SQL_request query.
317
331
  * @param {string} custom The custom SQL_request query to execute.
318
- * @returns {Promise<void>} A promise that resolves when the query is executed.
332
+ * @returns {Promise<ModelInstance>} A promise that resolves when the query is executed.
319
333
  * @throws {Error} Throws an error if query execution fails.
320
334
  */
321
335
  async customRequest(custom, custom_err_name = "") {
@@ -1,4 +1,4 @@
1
- const { error, logs } = require("@mlagie/logger");
1
+ const { error } = require("@mlagie/logger");
2
2
  const { getConnexion } = require("../db/connexion");
3
3
  const formatObject = require("../utils/formatObject");
4
4
  const generateCondition = require("../utils/generateCondition");
@@ -159,8 +159,6 @@ class ModelInstance {
159
159
  */
160
160
  async deleteOne() {
161
161
  const sql_request = `DELETE FROM ${this._name} WHERE ${generateCondition(formatObject(this.getRecordData()))}`;
162
-
163
- logs(sql_request)
164
162
  const rows = await getConnexion().promise().execute(sql_request).catch((err) => {
165
163
  error(`Error executing query deleteOne: ${err}`);
166
164
  throw err;